2 #ifdef HAVE_XORG_CONFIG_H
3 #include <xorg-config.h>
7 #include "xf86CursorPriv.h"
8 #include "colormapst.h"
11 /* FIXME: This was added with the ABI change of the miPointerSpriteFuncs for
13 * inputInfo is needed to pass the core pointer as the default argument into
14 * the cursor functions.
16 * Externing inputInfo is not the nice way to do it but it works.
20 DevPrivateKeyRec xf86CursorScreenKeyRec
;
22 /* sprite functions */
24 static Bool
xf86CursorRealizeCursor(DeviceIntPtr
, ScreenPtr
, CursorPtr
);
25 static Bool
xf86CursorUnrealizeCursor(DeviceIntPtr
, ScreenPtr
, CursorPtr
);
26 static void xf86CursorSetCursor(DeviceIntPtr
, ScreenPtr
, CursorPtr
, int, int);
27 static void xf86CursorMoveCursor(DeviceIntPtr
, ScreenPtr
, int, int);
28 static Bool
xf86DeviceCursorInitialize(DeviceIntPtr
, ScreenPtr
);
29 static void xf86DeviceCursorCleanup(DeviceIntPtr
, ScreenPtr
);
31 static miPointerSpriteFuncRec xf86CursorSpriteFuncs
= {
32 xf86CursorRealizeCursor
,
33 xf86CursorUnrealizeCursor
,
36 xf86DeviceCursorInitialize
,
37 xf86DeviceCursorCleanup
40 /* Screen functions */
42 static void xf86CursorInstallColormap(ColormapPtr
);
43 static void xf86CursorRecolorCursor(DeviceIntPtr pDev
, ScreenPtr
, CursorPtr
,
45 static Bool
xf86CursorCloseScreen(ScreenPtr
);
46 static void xf86CursorQueryBestSize(int, unsigned short *, unsigned short *,
49 /* ScrnInfoRec functions */
51 static void xf86CursorEnableDisableFBAccess(ScrnInfoPtr
, Bool
);
52 static Bool
xf86CursorSwitchMode(ScrnInfoPtr
, DisplayModePtr
);
55 xf86InitCursor(ScreenPtr pScreen
, xf86CursorInfoPtr infoPtr
)
57 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
58 xf86CursorScreenPtr ScreenPriv
;
59 miPointerScreenPtr PointPriv
;
61 if (!xf86InitHardwareCursor(pScreen
, infoPtr
))
64 if (!dixRegisterPrivateKey(&xf86CursorScreenKeyRec
, PRIVATE_SCREEN
, 0))
67 ScreenPriv
= calloc(1, sizeof(xf86CursorScreenRec
));
71 dixSetPrivate(&pScreen
->devPrivates
, xf86CursorScreenKey
, ScreenPriv
);
73 ScreenPriv
->SWCursor
= TRUE
;
74 ScreenPriv
->isUp
= FALSE
;
75 ScreenPriv
->CurrentCursor
= NULL
;
76 ScreenPriv
->CursorInfoPtr
= infoPtr
;
77 ScreenPriv
->PalettedCursor
= FALSE
;
78 ScreenPriv
->pInstalledMap
= NULL
;
80 ScreenPriv
->CloseScreen
= pScreen
->CloseScreen
;
81 pScreen
->CloseScreen
= xf86CursorCloseScreen
;
82 ScreenPriv
->QueryBestSize
= pScreen
->QueryBestSize
;
83 pScreen
->QueryBestSize
= xf86CursorQueryBestSize
;
84 ScreenPriv
->RecolorCursor
= pScreen
->RecolorCursor
;
85 pScreen
->RecolorCursor
= xf86CursorRecolorCursor
;
87 if ((infoPtr
->pScrn
->bitsPerPixel
== 8) &&
88 !(infoPtr
->Flags
& HARDWARE_CURSOR_TRUECOLOR_AT_8BPP
)) {
89 ScreenPriv
->InstallColormap
= pScreen
->InstallColormap
;
90 pScreen
->InstallColormap
= xf86CursorInstallColormap
;
91 ScreenPriv
->PalettedCursor
= TRUE
;
94 PointPriv
= dixLookupPrivate(&pScreen
->devPrivates
, miPointerScreenKey
);
96 ScreenPriv
->showTransparent
= PointPriv
->showTransparent
;
97 if (infoPtr
->Flags
& HARDWARE_CURSOR_SHOW_TRANSPARENT
)
98 PointPriv
->showTransparent
= TRUE
;
100 PointPriv
->showTransparent
= FALSE
;
101 ScreenPriv
->spriteFuncs
= PointPriv
->spriteFuncs
;
102 PointPriv
->spriteFuncs
= &xf86CursorSpriteFuncs
;
104 ScreenPriv
->EnableDisableFBAccess
= pScrn
->EnableDisableFBAccess
;
105 ScreenPriv
->SwitchMode
= pScrn
->SwitchMode
;
107 ScreenPriv
->ForceHWCursorCount
= 0;
108 ScreenPriv
->HWCursorForced
= FALSE
;
110 pScrn
->EnableDisableFBAccess
= xf86CursorEnableDisableFBAccess
;
111 if (pScrn
->SwitchMode
)
112 pScrn
->SwitchMode
= xf86CursorSwitchMode
;
117 /***** Screen functions *****/
120 xf86CursorCloseScreen(ScreenPtr pScreen
)
122 ScrnInfoPtr pScrn
= xf86ScreenToScrn(pScreen
);
123 miPointerScreenPtr PointPriv
=
124 (miPointerScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
126 xf86CursorScreenPtr ScreenPriv
=
127 (xf86CursorScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
128 xf86CursorScreenKey
);
130 if (ScreenPriv
->isUp
&& pScrn
->vtSema
)
131 xf86SetCursor(pScreen
, NullCursor
, ScreenPriv
->x
, ScreenPriv
->y
);
133 if (ScreenPriv
->CurrentCursor
)
134 FreeCursor(ScreenPriv
->CurrentCursor
, None
);
136 pScreen
->CloseScreen
= ScreenPriv
->CloseScreen
;
137 pScreen
->QueryBestSize
= ScreenPriv
->QueryBestSize
;
138 pScreen
->RecolorCursor
= ScreenPriv
->RecolorCursor
;
139 if (ScreenPriv
->InstallColormap
)
140 pScreen
->InstallColormap
= ScreenPriv
->InstallColormap
;
142 PointPriv
->spriteFuncs
= ScreenPriv
->spriteFuncs
;
143 PointPriv
->showTransparent
= ScreenPriv
->showTransparent
;
145 pScrn
->EnableDisableFBAccess
= ScreenPriv
->EnableDisableFBAccess
;
146 pScrn
->SwitchMode
= ScreenPriv
->SwitchMode
;
148 free(ScreenPriv
->transparentData
);
151 return (*pScreen
->CloseScreen
) (pScreen
);
155 xf86CursorQueryBestSize(int class,
156 unsigned short *width
,
157 unsigned short *height
, ScreenPtr pScreen
)
159 xf86CursorScreenPtr ScreenPriv
=
160 (xf86CursorScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
161 xf86CursorScreenKey
);
163 if (class == CursorShape
) {
164 if (*width
> ScreenPriv
->CursorInfoPtr
->MaxWidth
)
165 *width
= ScreenPriv
->CursorInfoPtr
->MaxWidth
;
166 if (*height
> ScreenPriv
->CursorInfoPtr
->MaxHeight
)
167 *height
= ScreenPriv
->CursorInfoPtr
->MaxHeight
;
170 (*ScreenPriv
->QueryBestSize
) (class, width
, height
, pScreen
);
174 xf86CursorInstallColormap(ColormapPtr pMap
)
176 xf86CursorScreenPtr ScreenPriv
=
177 (xf86CursorScreenPtr
) dixLookupPrivate(&pMap
->pScreen
->devPrivates
,
178 xf86CursorScreenKey
);
180 ScreenPriv
->pInstalledMap
= pMap
;
182 (*ScreenPriv
->InstallColormap
) (pMap
);
186 xf86CursorRecolorCursor(DeviceIntPtr pDev
,
187 ScreenPtr pScreen
, CursorPtr pCurs
, Bool displayed
)
189 xf86CursorScreenPtr ScreenPriv
=
190 (xf86CursorScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
191 xf86CursorScreenKey
);
196 if (ScreenPriv
->SWCursor
)
197 (*ScreenPriv
->RecolorCursor
) (pDev
, pScreen
, pCurs
, displayed
);
199 xf86RecolorCursor(pScreen
, pCurs
, displayed
);
202 /***** ScrnInfoRec functions *********/
205 xf86CursorEnableDisableFBAccess(ScrnInfoPtr pScrn
, Bool enable
)
207 DeviceIntPtr pDev
= inputInfo
.pointer
;
209 ScreenPtr pScreen
= xf86ScrnToScreen(pScrn
);
210 xf86CursorScreenPtr ScreenPriv
=
211 (xf86CursorScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
212 xf86CursorScreenKey
);
214 if (!enable
&& ScreenPriv
->CurrentCursor
!= NullCursor
) {
215 CursorPtr currentCursor
= ScreenPriv
->CurrentCursor
;
217 xf86CursorSetCursor(pDev
, pScreen
, NullCursor
, ScreenPriv
->x
,
219 ScreenPriv
->isUp
= FALSE
;
220 ScreenPriv
->SWCursor
= TRUE
;
221 ScreenPriv
->SavedCursor
= currentCursor
;
224 if (ScreenPriv
->EnableDisableFBAccess
)
225 (*ScreenPriv
->EnableDisableFBAccess
) (pScrn
, enable
);
227 if (enable
&& ScreenPriv
->SavedCursor
) {
229 * Re-set current cursor so drivers can react to FB access having been
230 * temporarily disabled.
232 xf86CursorSetCursor(pDev
, pScreen
, ScreenPriv
->SavedCursor
,
233 ScreenPriv
->x
, ScreenPriv
->y
);
234 ScreenPriv
->SavedCursor
= NULL
;
239 xf86CursorSwitchMode(ScrnInfoPtr pScrn
, DisplayModePtr mode
)
242 ScreenPtr pScreen
= xf86ScrnToScreen(pScrn
);
243 xf86CursorScreenPtr ScreenPriv
=
244 (xf86CursorScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
245 xf86CursorScreenKey
);
247 if (ScreenPriv
->isUp
) {
248 xf86SetCursor(pScreen
, NullCursor
, ScreenPriv
->x
, ScreenPriv
->y
);
249 ScreenPriv
->isUp
= FALSE
;
252 ret
= (*ScreenPriv
->SwitchMode
) (pScrn
, mode
);
255 * Cannot restore cursor here because the new frame[XY][01] haven't been
256 * calculated yet. However, because the hardware cursor was removed above,
257 * ensure the cursor is repainted by miPointerWarpCursor().
259 ScreenPriv
->CursorToRestore
= ScreenPriv
->CurrentCursor
;
260 miPointerSetWaitForUpdate(pScreen
, FALSE
); /* Force cursor repaint */
265 /****** miPointerSpriteFunctions *******/
268 xf86CursorRealizeCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
, CursorPtr pCurs
)
270 xf86CursorScreenPtr ScreenPriv
=
271 (xf86CursorScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
272 xf86CursorScreenKey
);
274 if (CursorRefCount(pCurs
) <= 1)
275 dixSetScreenPrivate(&pCurs
->devPrivates
, CursorScreenKey
, pScreen
,
278 return (*ScreenPriv
->spriteFuncs
->RealizeCursor
) (pDev
, pScreen
, pCurs
);
282 xf86CursorUnrealizeCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
, CursorPtr pCurs
)
284 xf86CursorScreenPtr ScreenPriv
=
285 (xf86CursorScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
286 xf86CursorScreenKey
);
288 if (CursorRefCount(pCurs
) <= 1) {
289 free(dixLookupScreenPrivate
290 (&pCurs
->devPrivates
, CursorScreenKey
, pScreen
));
291 dixSetScreenPrivate(&pCurs
->devPrivates
, CursorScreenKey
, pScreen
,
295 return (*ScreenPriv
->spriteFuncs
->UnrealizeCursor
) (pDev
, pScreen
, pCurs
);
299 xf86CursorSetCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
, CursorPtr pCurs
,
302 xf86CursorScreenPtr ScreenPriv
=
303 (xf86CursorScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
304 xf86CursorScreenKey
);
305 xf86CursorInfoPtr infoPtr
= ScreenPriv
->CursorInfoPtr
;
307 if (pCurs
== NullCursor
) { /* means we're supposed to remove the cursor */
308 if (ScreenPriv
->SWCursor
||
309 !(GetMaster(pDev
, MASTER_POINTER
) == inputInfo
.pointer
))
310 (*ScreenPriv
->spriteFuncs
->SetCursor
) (pDev
, pScreen
, NullCursor
, x
,
312 else if (ScreenPriv
->isUp
) {
313 xf86SetCursor(pScreen
, NullCursor
, x
, y
);
314 ScreenPriv
->isUp
= FALSE
;
316 if (ScreenPriv
->CurrentCursor
)
317 FreeCursor(ScreenPriv
->CurrentCursor
, None
);
318 ScreenPriv
->CurrentCursor
= NullCursor
;
322 /* only update for VCP, otherwise we get cursor jumps when removing a
323 sprite. The second cursor is never HW rendered anyway. */
324 if (GetMaster(pDev
, MASTER_POINTER
) == inputInfo
.pointer
) {
325 CursorPtr cursor
= RefCursor(pCurs
);
326 if (ScreenPriv
->CurrentCursor
)
327 FreeCursor(ScreenPriv
->CurrentCursor
, None
);
328 ScreenPriv
->CurrentCursor
= cursor
;
331 ScreenPriv
->CursorToRestore
= NULL
;
332 ScreenPriv
->HotX
= cursor
->bits
->xhot
;
333 ScreenPriv
->HotY
= cursor
->bits
->yhot
;
335 if (!infoPtr
->pScrn
->vtSema
)
336 ScreenPriv
->SavedCursor
= cursor
;
338 if (infoPtr
->pScrn
->vtSema
&& xorg_list_is_empty(&pScreen
->pixmap_dirty_list
) &&
339 (ScreenPriv
->ForceHWCursorCount
||
342 cursor
->bits
->argb
&&
343 infoPtr
->UseHWCursorARGB
&&
344 (*infoPtr
->UseHWCursorARGB
)(pScreen
, cursor
)) ||
345 (cursor
->bits
->argb
== 0 &&
347 (cursor
->bits
->height
<= infoPtr
->MaxHeight
) &&
348 (cursor
->bits
->width
<= infoPtr
->MaxWidth
) &&
349 (!infoPtr
->UseHWCursor
|| (*infoPtr
->UseHWCursor
) (pScreen
, cursor
)))))) {
351 if (ScreenPriv
->SWCursor
) /* remove the SW cursor */
352 (*ScreenPriv
->spriteFuncs
->SetCursor
) (pDev
, pScreen
,
355 xf86SetCursor(pScreen
, cursor
, x
, y
);
356 ScreenPriv
->SWCursor
= FALSE
;
357 ScreenPriv
->isUp
= TRUE
;
359 miPointerSetWaitForUpdate(pScreen
, !infoPtr
->pScrn
->silkenMouse
);
363 miPointerSetWaitForUpdate(pScreen
, TRUE
);
365 if (ScreenPriv
->isUp
) {
366 /* Remove the HW cursor, or make it transparent */
367 if (infoPtr
->Flags
& HARDWARE_CURSOR_SHOW_TRANSPARENT
) {
368 xf86SetTransparentCursor(pScreen
);
371 xf86SetCursor(pScreen
, NullCursor
, x
, y
);
372 ScreenPriv
->isUp
= FALSE
;
376 if (!ScreenPriv
->SWCursor
)
377 ScreenPriv
->SWCursor
= TRUE
;
381 if (pCurs
->bits
->emptyMask
&& !ScreenPriv
->showTransparent
)
384 (*ScreenPriv
->spriteFuncs
->SetCursor
) (pDev
, pScreen
, pCurs
, x
, y
);
388 xf86CursorMoveCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
, int x
, int y
)
390 xf86CursorScreenPtr ScreenPriv
=
391 (xf86CursorScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
392 xf86CursorScreenKey
);
394 /* only update coordinate state for first sprite, otherwise we get jumps
395 when removing a sprite. The second sprite is never HW rendered anyway */
396 if (GetMaster(pDev
, MASTER_POINTER
) == inputInfo
.pointer
) {
400 if (ScreenPriv
->CursorToRestore
)
401 xf86CursorSetCursor(pDev
, pScreen
, ScreenPriv
->CursorToRestore
, x
,
403 else if (ScreenPriv
->SWCursor
)
404 (*ScreenPriv
->spriteFuncs
->MoveCursor
) (pDev
, pScreen
, x
, y
);
405 else if (ScreenPriv
->isUp
)
406 xf86MoveCursor(pScreen
, x
, y
);
409 (*ScreenPriv
->spriteFuncs
->MoveCursor
) (pDev
, pScreen
, x
, y
);
413 xf86ForceHWCursor(ScreenPtr pScreen
, Bool on
)
415 DeviceIntPtr pDev
= inputInfo
.pointer
;
416 xf86CursorScreenPtr ScreenPriv
=
417 (xf86CursorScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
418 xf86CursorScreenKey
);
421 if (ScreenPriv
->ForceHWCursorCount
++ == 0) {
422 if (ScreenPriv
->SWCursor
&& ScreenPriv
->CurrentCursor
) {
423 ScreenPriv
->HWCursorForced
= TRUE
;
424 xf86CursorSetCursor(pDev
, pScreen
, ScreenPriv
->CurrentCursor
,
425 ScreenPriv
->x
, ScreenPriv
->y
);
428 ScreenPriv
->HWCursorForced
= FALSE
;
432 if (--ScreenPriv
->ForceHWCursorCount
== 0) {
433 if (ScreenPriv
->HWCursorForced
&& ScreenPriv
->CurrentCursor
)
434 xf86CursorSetCursor(pDev
, pScreen
, ScreenPriv
->CurrentCursor
,
435 ScreenPriv
->x
, ScreenPriv
->y
);
441 xf86CreateCursorInfoRec(void)
443 return calloc(1, sizeof(xf86CursorInfoRec
));
447 xf86DestroyCursorInfoRec(xf86CursorInfoPtr infoPtr
)
453 * New cursor has been created. Do your initalizations here.
456 xf86DeviceCursorInitialize(DeviceIntPtr pDev
, ScreenPtr pScreen
)
459 xf86CursorScreenPtr ScreenPriv
=
460 (xf86CursorScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
461 xf86CursorScreenKey
);
464 ret
= (*ScreenPriv
->spriteFuncs
->DeviceCursorInitialize
) (pDev
, pScreen
);
470 * Cursor has been removed. Clean up after yourself.
473 xf86DeviceCursorCleanup(DeviceIntPtr pDev
, ScreenPtr pScreen
)
475 xf86CursorScreenPtr ScreenPriv
=
476 (xf86CursorScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
477 xf86CursorScreenKey
);
479 /* Clean up SW cursor */
480 (*ScreenPriv
->spriteFuncs
->DeviceCursorCleanup
) (pDev
, pScreen
);