4 * machine independent cursor display routines
9 Copyright 1989, 1998 The Open Group
11 Permission to use, copy, modify, distribute, and sell this software and its
12 documentation for any purpose is hereby granted without fee, provided that
13 the above copyright notice appear in all copies and that both that
14 copyright notice and this permission notice appear in supporting
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
24 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 Except as contained in this notice, the name of The Open Group shall not be
28 used in advertising or otherwise to promote the sale, use or other dealings
29 in this Software without prior written authorization from The Open Group.
32 #ifdef HAVE_DIX_CONFIG_H
33 #include <dix-config.h>
39 #include "cursorstr.h"
40 #include "windowstr.h"
41 #include "regionstr.h"
42 #include "dixstruct.h"
43 #include "scrnintstr.h"
45 #include "mipointer.h"
50 #include "picturestr.h"
55 /* per-screen private data */
56 static DevPrivateKeyRec miDCScreenKeyRec
;
58 #define miDCScreenKey (&miDCScreenKeyRec)
59 static DevScreenPrivateKeyRec miDCCursorBitsKeyRec
;
61 #define miDCCursorBitsKey (&miDCCursorBitsKeyRec)
62 static DevScreenPrivateKeyRec miDCDeviceKeyRec
;
64 #define miDCDeviceKey (&miDCDeviceKeyRec)
66 static Bool
miDCCloseScreen(int index
, ScreenPtr pScreen
);
68 /* per device private data */
70 GCPtr pSourceGC
, pMaskGC
;
71 GCPtr pSaveGC
, pRestoreGC
;
74 PicturePtr pRootPicture
;
76 } miDCBufferRec
, *miDCBufferPtr
;
78 #define miGetDCDevice(dev, screen) \
79 ((DevHasCursor(dev)) ? \
80 (miDCBufferPtr)dixLookupScreenPrivate(&dev->devPrivates, miDCDeviceKey, screen) : \
81 (miDCBufferPtr)dixLookupScreenPrivate(&GetMaster(dev, MASTER_POINTER)->devPrivates, miDCDeviceKey, screen))
84 * The core pointer buffer will point to the index of the virtual core pointer
85 * in the pCursorBuffers array.
88 CloseScreenProcPtr CloseScreen
;
89 } miDCScreenRec
, *miDCScreenPtr
;
91 #define miGetDCScreen(s) ((miDCScreenPtr)(dixLookupPrivate(&(s)->devPrivates, miDCScreenKey)))
93 /* per-cursor per-screen private data */
95 PixmapPtr sourceBits
; /* source bits */
96 PixmapPtr maskBits
; /* mask bits */
100 } miDCCursorRec
, *miDCCursorPtr
;
103 miDCInitialize(ScreenPtr pScreen
, miPointerScreenFuncPtr screenFuncs
)
105 miDCScreenPtr pScreenPriv
;
107 if (!dixRegisterPrivateKey(&miDCScreenKeyRec
, PRIVATE_SCREEN
, 0) ||
108 !dixRegisterScreenPrivateKey(&miDCCursorBitsKeyRec
, pScreen
,
109 PRIVATE_CURSOR_BITS
, 0) ||
110 !dixRegisterScreenPrivateKey(&miDCDeviceKeyRec
, pScreen
, PRIVATE_DEVICE
,
114 pScreenPriv
= malloc(sizeof(miDCScreenRec
));
118 pScreenPriv
->CloseScreen
= pScreen
->CloseScreen
;
119 pScreen
->CloseScreen
= miDCCloseScreen
;
121 dixSetPrivate(&pScreen
->devPrivates
, miDCScreenKey
, pScreenPriv
);
123 if (!miSpriteInitialize(pScreen
, screenFuncs
)) {
124 free((pointer
) pScreenPriv
);
131 miDCCloseScreen(int index
, ScreenPtr pScreen
)
133 miDCScreenPtr pScreenPriv
;
135 pScreenPriv
= (miDCScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
137 pScreen
->CloseScreen
= pScreenPriv
->CloseScreen
;
138 free((pointer
) pScreenPriv
);
139 return (*pScreen
->CloseScreen
) (index
, pScreen
);
143 miDCRealizeCursor(ScreenPtr pScreen
, CursorPtr pCursor
)
145 if (pCursor
->bits
->refcnt
<= 1)
146 dixSetScreenPrivate(&pCursor
->bits
->devPrivates
, miDCCursorBitsKey
,
152 #define EnsurePicture(picture,draw,win) (picture || miDCMakePicture(&picture,draw,win))
155 miDCGetWindowVisual(WindowPtr pWin
)
157 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
158 VisualID vid
= wVisual(pWin
);
161 for (i
= 0; i
< pScreen
->numVisuals
; i
++)
162 if (pScreen
->visuals
[i
].vid
== vid
)
163 return &pScreen
->visuals
[i
];
168 miDCMakePicture(PicturePtr
* ppPicture
, DrawablePtr pDraw
, WindowPtr pWin
)
170 ScreenPtr pScreen
= pDraw
->pScreen
;
172 PictFormatPtr pFormat
;
173 XID subwindow_mode
= IncludeInferiors
;
177 pVisual
= miDCGetWindowVisual(pWin
);
180 pFormat
= PictureMatchVisual(pScreen
, pDraw
->depth
, pVisual
);
183 pPicture
= CreatePicture(0, pDraw
, pFormat
,
184 CPSubwindowMode
, &subwindow_mode
,
185 serverClient
, &error
);
186 *ppPicture
= pPicture
;
192 miDCRealize(ScreenPtr pScreen
, CursorPtr pCursor
)
198 pPriv
= malloc(sizeof(miDCCursorRec
));
202 if (pCursor
->bits
->argb
) {
204 PictFormatPtr pFormat
;
207 pFormat
= PictureMatchFormat(pScreen
, 32, PICT_a8r8g8b8
);
209 free((pointer
) pPriv
);
213 pPriv
->sourceBits
= 0;
215 pPixmap
= (*pScreen
->CreatePixmap
) (pScreen
, pCursor
->bits
->width
,
216 pCursor
->bits
->height
, 32,
217 CREATE_PIXMAP_USAGE_SCRATCH
);
219 free((pointer
) pPriv
);
222 pGC
= GetScratchGC(32, pScreen
);
224 (*pScreen
->DestroyPixmap
) (pPixmap
);
225 free((pointer
) pPriv
);
228 ValidateGC(&pPixmap
->drawable
, pGC
);
229 (*pGC
->ops
->PutImage
) (&pPixmap
->drawable
, pGC
, 32,
230 0, 0, pCursor
->bits
->width
,
231 pCursor
->bits
->height
,
232 0, ZPixmap
, (char *) pCursor
->bits
->argb
);
234 pPriv
->pPicture
= CreatePicture(0, &pPixmap
->drawable
,
235 pFormat
, 0, 0, serverClient
, &error
);
236 (*pScreen
->DestroyPixmap
) (pPixmap
);
237 if (!pPriv
->pPicture
) {
238 free((pointer
) pPriv
);
241 dixSetScreenPrivate(&pCursor
->bits
->devPrivates
, miDCCursorBitsKey
,
248 (*pScreen
->CreatePixmap
) (pScreen
, pCursor
->bits
->width
,
249 pCursor
->bits
->height
, 1, 0);
250 if (!pPriv
->sourceBits
) {
251 free((pointer
) pPriv
);
255 (*pScreen
->CreatePixmap
) (pScreen
, pCursor
->bits
->width
,
256 pCursor
->bits
->height
, 1, 0);
257 if (!pPriv
->maskBits
) {
258 (*pScreen
->DestroyPixmap
) (pPriv
->sourceBits
);
259 free((pointer
) pPriv
);
262 dixSetScreenPrivate(&pCursor
->bits
->devPrivates
, miDCCursorBitsKey
, pScreen
,
265 /* create the two sets of bits, clipping as appropriate */
267 pGC
= GetScratchGC(1, pScreen
);
269 (void) miDCUnrealizeCursor(pScreen
, pCursor
);
273 ValidateGC((DrawablePtr
) pPriv
->sourceBits
, pGC
);
274 (*pGC
->ops
->PutImage
) ((DrawablePtr
) pPriv
->sourceBits
, pGC
, 1,
275 0, 0, pCursor
->bits
->width
, pCursor
->bits
->height
,
276 0, XYPixmap
, (char *) pCursor
->bits
->source
);
278 ChangeGC(NullClient
, pGC
, GCFunction
, &gcvals
);
279 ValidateGC((DrawablePtr
) pPriv
->sourceBits
, pGC
);
280 (*pGC
->ops
->PutImage
) ((DrawablePtr
) pPriv
->sourceBits
, pGC
, 1,
281 0, 0, pCursor
->bits
->width
, pCursor
->bits
->height
,
282 0, XYPixmap
, (char *) pCursor
->bits
->mask
);
284 /* mask bits -- pCursor->mask & ~pCursor->source */
286 ChangeGC(NullClient
, pGC
, GCFunction
, &gcvals
);
287 ValidateGC((DrawablePtr
) pPriv
->maskBits
, pGC
);
288 (*pGC
->ops
->PutImage
) ((DrawablePtr
) pPriv
->maskBits
, pGC
, 1,
289 0, 0, pCursor
->bits
->width
, pCursor
->bits
->height
,
290 0, XYPixmap
, (char *) pCursor
->bits
->mask
);
291 gcvals
.val
= GXandInverted
;
292 ChangeGC(NullClient
, pGC
, GCFunction
, &gcvals
);
293 ValidateGC((DrawablePtr
) pPriv
->maskBits
, pGC
);
294 (*pGC
->ops
->PutImage
) ((DrawablePtr
) pPriv
->maskBits
, pGC
, 1,
295 0, 0, pCursor
->bits
->width
, pCursor
->bits
->height
,
296 0, XYPixmap
, (char *) pCursor
->bits
->source
);
302 miDCUnrealizeCursor(ScreenPtr pScreen
, CursorPtr pCursor
)
306 pPriv
= (miDCCursorPtr
) dixLookupScreenPrivate(&pCursor
->bits
->devPrivates
,
307 miDCCursorBitsKey
, pScreen
);
308 if (pPriv
&& (pCursor
->bits
->refcnt
<= 1)) {
309 if (pPriv
->sourceBits
)
310 (*pScreen
->DestroyPixmap
) (pPriv
->sourceBits
);
312 (*pScreen
->DestroyPixmap
) (pPriv
->maskBits
);
315 FreePicture(pPriv
->pPicture
, 0);
317 free((pointer
) pPriv
);
318 dixSetScreenPrivate(&pCursor
->bits
->devPrivates
, miDCCursorBitsKey
,
325 miDCPutBits(DrawablePtr pDrawable
,
331 unsigned w
, unsigned h
, unsigned long source
, unsigned long mask
)
336 if (sourceGC
->fgPixel
!= source
) {
338 ChangeGC(NullClient
, sourceGC
, GCForeground
, &gcval
);
340 if (sourceGC
->serialNumber
!= pDrawable
->serialNumber
)
341 ValidateGC(pDrawable
, sourceGC
);
343 if (sourceGC
->miTranslate
) {
344 x
= pDrawable
->x
+ x_org
;
345 y
= pDrawable
->y
+ y_org
;
352 (*sourceGC
->ops
->PushPixels
) (sourceGC
, pPriv
->sourceBits
, pDrawable
, w
, h
,
354 if (maskGC
->fgPixel
!= mask
) {
356 ChangeGC(NullClient
, maskGC
, GCForeground
, &gcval
);
358 if (maskGC
->serialNumber
!= pDrawable
->serialNumber
)
359 ValidateGC(pDrawable
, maskGC
);
361 if (maskGC
->miTranslate
) {
362 x
= pDrawable
->x
+ x_org
;
363 y
= pDrawable
->y
+ y_org
;
370 (*maskGC
->ops
->PushPixels
) (maskGC
, pPriv
->maskBits
, pDrawable
, w
, h
, x
, y
);
374 miDCMakeGC(WindowPtr pWin
)
380 gcvals
[0] = IncludeInferiors
;
382 pGC
= CreateGC((DrawablePtr
) pWin
,
383 GCSubwindowMode
| GCGraphicsExposures
, gcvals
, &status
,
384 (XID
) 0, serverClient
);
389 miDCPutUpCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
, CursorPtr pCursor
,
390 int x
, int y
, unsigned long source
, unsigned long mask
)
393 miDCBufferPtr pBuffer
;
396 pPriv
= (miDCCursorPtr
) dixLookupScreenPrivate(&pCursor
->bits
->devPrivates
,
397 miDCCursorBitsKey
, pScreen
);
399 pPriv
= miDCRealize(pScreen
, pCursor
);
404 pWin
= pScreen
->root
;
405 pBuffer
= miGetDCDevice(pDev
, pScreen
);
408 if (pPriv
->pPicture
) {
409 if (!EnsurePicture(pBuffer
->pRootPicture
, &pWin
->drawable
, pWin
))
411 CompositePicture(PictOpOver
,
414 pBuffer
->pRootPicture
,
416 x
, y
, pCursor
->bits
->width
, pCursor
->bits
->height
);
421 miDCPutBits((DrawablePtr
) pWin
, pPriv
,
422 pBuffer
->pSourceGC
, pBuffer
->pMaskGC
,
423 x
, y
, pCursor
->bits
->width
, pCursor
->bits
->height
,
430 miDCSaveUnderCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
,
431 int x
, int y
, int w
, int h
)
433 miDCBufferPtr pBuffer
;
438 pBuffer
= miGetDCDevice(pDev
, pScreen
);
440 pSave
= pBuffer
->pSave
;
441 pWin
= pScreen
->root
;
442 if (!pSave
|| pSave
->drawable
.width
< w
|| pSave
->drawable
.height
< h
) {
444 (*pScreen
->DestroyPixmap
) (pSave
);
445 pBuffer
->pSave
= pSave
=
446 (*pScreen
->CreatePixmap
) (pScreen
, w
, h
, pScreen
->rootDepth
, 0);
451 pGC
= pBuffer
->pSaveGC
;
452 if (pSave
->drawable
.serialNumber
!= pGC
->serialNumber
)
453 ValidateGC((DrawablePtr
) pSave
, pGC
);
454 (*pGC
->ops
->CopyArea
) ((DrawablePtr
) pWin
, (DrawablePtr
) pSave
, pGC
,
460 miDCRestoreUnderCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
,
461 int x
, int y
, int w
, int h
)
463 miDCBufferPtr pBuffer
;
468 pBuffer
= miGetDCDevice(pDev
, pScreen
);
469 pSave
= pBuffer
->pSave
;
471 pWin
= pScreen
->root
;
475 pGC
= pBuffer
->pRestoreGC
;
476 if (pWin
->drawable
.serialNumber
!= pGC
->serialNumber
)
477 ValidateGC((DrawablePtr
) pWin
, pGC
);
478 (*pGC
->ops
->CopyArea
) ((DrawablePtr
) pSave
, (DrawablePtr
) pWin
, pGC
,
484 miDCDeviceInitialize(DeviceIntPtr pDev
, ScreenPtr pScreen
)
486 miDCBufferPtr pBuffer
;
490 if (!DevHasCursor(pDev
))
493 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
494 pScreen
= screenInfo
.screens
[i
];
496 pBuffer
= calloc(1, sizeof(miDCBufferRec
));
500 dixSetScreenPrivate(&pDev
->devPrivates
, miDCDeviceKey
, pScreen
,
502 pWin
= pScreen
->root
;
504 pBuffer
->pSourceGC
= miDCMakeGC(pWin
);
505 if (!pBuffer
->pSourceGC
)
508 pBuffer
->pMaskGC
= miDCMakeGC(pWin
);
509 if (!pBuffer
->pMaskGC
)
512 pBuffer
->pSaveGC
= miDCMakeGC(pWin
);
513 if (!pBuffer
->pSaveGC
)
516 pBuffer
->pRestoreGC
= miDCMakeGC(pWin
);
517 if (!pBuffer
->pRestoreGC
)
521 pBuffer
->pRootPicture
= NULL
;
524 /* (re)allocated lazily depending on the cursor size */
525 pBuffer
->pSave
= NULL
;
532 miDCDeviceCleanup(pDev
, pScreen
);
538 miDCDeviceCleanup(DeviceIntPtr pDev
, ScreenPtr pScreen
)
540 miDCBufferPtr pBuffer
;
543 if (DevHasCursor(pDev
)) {
544 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
545 pScreen
= screenInfo
.screens
[i
];
547 pBuffer
= miGetDCDevice(pDev
, pScreen
);
550 if (pBuffer
->pSourceGC
)
551 FreeGC(pBuffer
->pSourceGC
, (GContext
) 0);
552 if (pBuffer
->pMaskGC
)
553 FreeGC(pBuffer
->pMaskGC
, (GContext
) 0);
554 if (pBuffer
->pSaveGC
)
555 FreeGC(pBuffer
->pSaveGC
, (GContext
) 0);
556 if (pBuffer
->pRestoreGC
)
557 FreeGC(pBuffer
->pRestoreGC
, (GContext
) 0);
560 /* If a pRootPicture was allocated for a root window, it
561 * is freed when that root window is destroyed, so don't
562 * free it again here. */
566 (*pScreen
->DestroyPixmap
) (pBuffer
->pSave
);
569 dixSetScreenPrivate(&pDev
->devPrivates
, miDCDeviceKey
, pScreen
,