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)
60 static DevScreenPrivateKeyRec miDCDeviceKeyRec
;
62 #define miDCDeviceKey (&miDCDeviceKeyRec)
64 static Bool
miDCCloseScreen(ScreenPtr pScreen
);
66 /* per device private data */
68 GCPtr pSourceGC
, pMaskGC
;
69 GCPtr pSaveGC
, pRestoreGC
;
72 PicturePtr pRootPicture
;
74 } miDCBufferRec
, *miDCBufferPtr
;
76 #define miGetDCDevice(dev, screen) \
77 ((DevHasCursor(dev)) ? \
78 (miDCBufferPtr)dixLookupScreenPrivate(&dev->devPrivates, miDCDeviceKey, screen) : \
79 (miDCBufferPtr)dixLookupScreenPrivate(&GetMaster(dev, MASTER_POINTER)->devPrivates, miDCDeviceKey, screen))
82 * The core pointer buffer will point to the index of the virtual core pointer
83 * in the pCursorBuffers array.
86 CloseScreenProcPtr CloseScreen
;
87 PixmapPtr sourceBits
; /* source bits */
88 PixmapPtr maskBits
; /* mask bits */
93 } miDCScreenRec
, *miDCScreenPtr
;
95 #define miGetDCScreen(s) ((miDCScreenPtr)(dixLookupPrivate(&(s)->devPrivates, miDCScreenKey)))
98 miDCInitialize(ScreenPtr pScreen
, miPointerScreenFuncPtr screenFuncs
)
100 miDCScreenPtr pScreenPriv
;
102 if (!dixRegisterPrivateKey(&miDCScreenKeyRec
, PRIVATE_SCREEN
, 0) ||
103 !dixRegisterScreenPrivateKey(&miDCDeviceKeyRec
, pScreen
, PRIVATE_DEVICE
,
107 pScreenPriv
= calloc(1, sizeof(miDCScreenRec
));
111 pScreenPriv
->CloseScreen
= pScreen
->CloseScreen
;
112 pScreen
->CloseScreen
= miDCCloseScreen
;
114 dixSetPrivate(&pScreen
->devPrivates
, miDCScreenKey
, pScreenPriv
);
116 if (!miSpriteInitialize(pScreen
, screenFuncs
)) {
117 free((pointer
) pScreenPriv
);
124 miDCSwitchScreenCursor(ScreenPtr pScreen
, CursorPtr pCursor
, PixmapPtr sourceBits
, PixmapPtr maskBits
, PicturePtr pPicture
)
126 miDCScreenPtr pScreenPriv
= dixLookupPrivate(&pScreen
->devPrivates
, miDCScreenKey
);
128 if (pScreenPriv
->sourceBits
)
129 (*pScreen
->DestroyPixmap
)(pScreenPriv
->sourceBits
);
130 pScreenPriv
->sourceBits
= sourceBits
;
132 if (pScreenPriv
->maskBits
)
133 (*pScreen
->DestroyPixmap
)(pScreenPriv
->maskBits
);
134 pScreenPriv
->maskBits
= maskBits
;
137 if (pScreenPriv
->pPicture
)
138 FreePicture(pScreenPriv
->pPicture
, 0);
139 pScreenPriv
->pPicture
= pPicture
;
142 pScreenPriv
->pCursor
= pCursor
;
146 miDCCloseScreen(ScreenPtr pScreen
)
148 miDCScreenPtr pScreenPriv
;
150 pScreenPriv
= (miDCScreenPtr
) dixLookupPrivate(&pScreen
->devPrivates
,
152 pScreen
->CloseScreen
= pScreenPriv
->CloseScreen
;
154 miDCSwitchScreenCursor(pScreen
, NULL
, NULL
, NULL
, NULL
);
155 free((pointer
) pScreenPriv
);
156 return (*pScreen
->CloseScreen
) (pScreen
);
160 miDCRealizeCursor(ScreenPtr pScreen
, CursorPtr pCursor
)
166 #define EnsurePicture(picture,draw,win) (picture || miDCMakePicture(&picture,draw,win))
169 miDCMakePicture(PicturePtr
* ppPicture
, DrawablePtr pDraw
, WindowPtr pWin
)
171 PictFormatPtr pFormat
;
172 XID subwindow_mode
= IncludeInferiors
;
176 pFormat
= PictureWindowFormat(pWin
);
179 pPicture
= CreatePicture(0, pDraw
, pFormat
,
180 CPSubwindowMode
, &subwindow_mode
,
181 serverClient
, &error
);
182 *ppPicture
= pPicture
;
188 miDCRealize(ScreenPtr pScreen
, CursorPtr pCursor
)
190 miDCScreenPtr pScreenPriv
= dixLookupPrivate(&pScreen
->devPrivates
, miDCScreenKey
);
193 PixmapPtr sourceBits
, maskBits
;
195 if (pScreenPriv
->pCursor
== pCursor
)
200 if (pCursor
->bits
->argb
) {
202 PictFormatPtr pFormat
;
206 pFormat
= PictureMatchFormat(pScreen
, 32, PICT_a8r8g8b8
);
210 pPixmap
= (*pScreen
->CreatePixmap
) (pScreen
, pCursor
->bits
->width
,
211 pCursor
->bits
->height
, 32,
212 CREATE_PIXMAP_USAGE_SCRATCH
);
216 pGC
= GetScratchGC(32, pScreen
);
218 (*pScreen
->DestroyPixmap
) (pPixmap
);
221 ValidateGC(&pPixmap
->drawable
, pGC
);
222 (*pGC
->ops
->PutImage
) (&pPixmap
->drawable
, pGC
, 32,
223 0, 0, pCursor
->bits
->width
,
224 pCursor
->bits
->height
,
225 0, ZPixmap
, (char *) pCursor
->bits
->argb
);
227 pPicture
= CreatePicture(0, &pPixmap
->drawable
,
228 pFormat
, 0, 0, serverClient
, &error
);
229 (*pScreen
->DestroyPixmap
) (pPixmap
);
233 miDCSwitchScreenCursor(pScreen
, pCursor
, NULL
, NULL
, pPicture
);
237 sourceBits
= (*pScreen
->CreatePixmap
) (pScreen
, pCursor
->bits
->width
,
238 pCursor
->bits
->height
, 1, 0);
242 maskBits
= (*pScreen
->CreatePixmap
) (pScreen
, pCursor
->bits
->width
,
243 pCursor
->bits
->height
, 1, 0);
245 (*pScreen
->DestroyPixmap
) (sourceBits
);
249 /* create the two sets of bits, clipping as appropriate */
251 pGC
= GetScratchGC(1, pScreen
);
253 (*pScreen
->DestroyPixmap
) (sourceBits
);
254 (*pScreen
->DestroyPixmap
) (maskBits
);
258 ValidateGC((DrawablePtr
) sourceBits
, pGC
);
259 (*pGC
->ops
->PutImage
) ((DrawablePtr
) sourceBits
, pGC
, 1,
260 0, 0, pCursor
->bits
->width
, pCursor
->bits
->height
,
261 0, XYPixmap
, (char *) pCursor
->bits
->source
);
263 ChangeGC(NullClient
, pGC
, GCFunction
, &gcvals
);
264 ValidateGC((DrawablePtr
) sourceBits
, pGC
);
265 (*pGC
->ops
->PutImage
) ((DrawablePtr
) sourceBits
, pGC
, 1,
266 0, 0, pCursor
->bits
->width
, pCursor
->bits
->height
,
267 0, XYPixmap
, (char *) pCursor
->bits
->mask
);
269 /* mask bits -- pCursor->mask & ~pCursor->source */
271 ChangeGC(NullClient
, pGC
, GCFunction
, &gcvals
);
272 ValidateGC((DrawablePtr
) maskBits
, pGC
);
273 (*pGC
->ops
->PutImage
) ((DrawablePtr
) maskBits
, pGC
, 1,
274 0, 0, pCursor
->bits
->width
, pCursor
->bits
->height
,
275 0, XYPixmap
, (char *) pCursor
->bits
->mask
);
276 gcvals
.val
= GXandInverted
;
277 ChangeGC(NullClient
, pGC
, GCFunction
, &gcvals
);
278 ValidateGC((DrawablePtr
) maskBits
, pGC
);
279 (*pGC
->ops
->PutImage
) ((DrawablePtr
) maskBits
, pGC
, 1,
280 0, 0, pCursor
->bits
->width
, pCursor
->bits
->height
,
281 0, XYPixmap
, (char *) pCursor
->bits
->source
);
284 miDCSwitchScreenCursor(pScreen
, pCursor
, sourceBits
, maskBits
, NULL
);
289 miDCUnrealizeCursor(ScreenPtr pScreen
, CursorPtr pCursor
)
291 miDCScreenPtr pScreenPriv
= dixLookupPrivate(&pScreen
->devPrivates
, miDCScreenKey
);
293 if (pCursor
== pScreenPriv
->pCursor
)
294 miDCSwitchScreenCursor(pScreen
, NULL
, NULL
, NULL
, NULL
);
299 miDCPutBits(DrawablePtr pDrawable
,
304 unsigned w
, unsigned h
, unsigned long source
, unsigned long mask
)
306 miDCScreenPtr pScreenPriv
= dixLookupPrivate(&pDrawable
->pScreen
->devPrivates
, miDCScreenKey
);
310 if (sourceGC
->fgPixel
!= source
) {
312 ChangeGC(NullClient
, sourceGC
, GCForeground
, &gcval
);
314 if (sourceGC
->serialNumber
!= pDrawable
->serialNumber
)
315 ValidateGC(pDrawable
, sourceGC
);
317 if (sourceGC
->miTranslate
) {
318 x
= pDrawable
->x
+ x_org
;
319 y
= pDrawable
->y
+ y_org
;
326 (*sourceGC
->ops
->PushPixels
) (sourceGC
, pScreenPriv
->sourceBits
, pDrawable
, w
, h
,
328 if (maskGC
->fgPixel
!= mask
) {
330 ChangeGC(NullClient
, maskGC
, GCForeground
, &gcval
);
332 if (maskGC
->serialNumber
!= pDrawable
->serialNumber
)
333 ValidateGC(pDrawable
, maskGC
);
335 if (maskGC
->miTranslate
) {
336 x
= pDrawable
->x
+ x_org
;
337 y
= pDrawable
->y
+ y_org
;
344 (*maskGC
->ops
->PushPixels
) (maskGC
, pScreenPriv
->maskBits
, pDrawable
, w
, h
, x
, y
);
348 miDCMakeGC(WindowPtr pWin
)
354 gcvals
[0] = IncludeInferiors
;
356 pGC
= CreateGC((DrawablePtr
) pWin
,
357 GCSubwindowMode
| GCGraphicsExposures
, gcvals
, &status
,
358 (XID
) 0, serverClient
);
363 miDCPutUpCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
, CursorPtr pCursor
,
364 int x
, int y
, unsigned long source
, unsigned long mask
)
366 miDCScreenPtr pScreenPriv
= dixLookupPrivate(&pScreen
->devPrivates
, miDCScreenKey
);
367 miDCBufferPtr pBuffer
;
370 if (!miDCRealize(pScreen
, pCursor
))
373 pWin
= pScreen
->root
;
374 pBuffer
= miGetDCDevice(pDev
, pScreen
);
377 if (pScreenPriv
->pPicture
) {
378 if (!EnsurePicture(pBuffer
->pRootPicture
, &pWin
->drawable
, pWin
))
380 CompositePicture(PictOpOver
,
381 pScreenPriv
->pPicture
,
383 pBuffer
->pRootPicture
,
385 x
, y
, pCursor
->bits
->width
, pCursor
->bits
->height
);
390 miDCPutBits((DrawablePtr
) pWin
,
391 pBuffer
->pSourceGC
, pBuffer
->pMaskGC
,
392 x
, y
, pCursor
->bits
->width
, pCursor
->bits
->height
,
399 miDCSaveUnderCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
,
400 int x
, int y
, int w
, int h
)
402 miDCBufferPtr pBuffer
;
407 pBuffer
= miGetDCDevice(pDev
, pScreen
);
409 pSave
= pBuffer
->pSave
;
410 pWin
= pScreen
->root
;
411 if (!pSave
|| pSave
->drawable
.width
< w
|| pSave
->drawable
.height
< h
) {
413 (*pScreen
->DestroyPixmap
) (pSave
);
414 pBuffer
->pSave
= pSave
=
415 (*pScreen
->CreatePixmap
) (pScreen
, w
, h
, pScreen
->rootDepth
, 0);
420 pGC
= pBuffer
->pSaveGC
;
421 if (pSave
->drawable
.serialNumber
!= pGC
->serialNumber
)
422 ValidateGC((DrawablePtr
) pSave
, pGC
);
423 (*pGC
->ops
->CopyArea
) ((DrawablePtr
) pWin
, (DrawablePtr
) pSave
, pGC
,
429 miDCRestoreUnderCursor(DeviceIntPtr pDev
, ScreenPtr pScreen
,
430 int x
, int y
, int w
, int h
)
432 miDCBufferPtr pBuffer
;
437 pBuffer
= miGetDCDevice(pDev
, pScreen
);
438 pSave
= pBuffer
->pSave
;
440 pWin
= pScreen
->root
;
444 pGC
= pBuffer
->pRestoreGC
;
445 if (pWin
->drawable
.serialNumber
!= pGC
->serialNumber
)
446 ValidateGC((DrawablePtr
) pWin
, pGC
);
447 (*pGC
->ops
->CopyArea
) ((DrawablePtr
) pSave
, (DrawablePtr
) pWin
, pGC
,
453 miDCDeviceInitialize(DeviceIntPtr pDev
, ScreenPtr pScreen
)
455 miDCBufferPtr pBuffer
;
459 if (!DevHasCursor(pDev
))
462 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
463 pScreen
= screenInfo
.screens
[i
];
465 pBuffer
= calloc(1, sizeof(miDCBufferRec
));
469 dixSetScreenPrivate(&pDev
->devPrivates
, miDCDeviceKey
, pScreen
,
471 pWin
= pScreen
->root
;
473 pBuffer
->pSourceGC
= miDCMakeGC(pWin
);
474 if (!pBuffer
->pSourceGC
)
477 pBuffer
->pMaskGC
= miDCMakeGC(pWin
);
478 if (!pBuffer
->pMaskGC
)
481 pBuffer
->pSaveGC
= miDCMakeGC(pWin
);
482 if (!pBuffer
->pSaveGC
)
485 pBuffer
->pRestoreGC
= miDCMakeGC(pWin
);
486 if (!pBuffer
->pRestoreGC
)
490 pBuffer
->pRootPicture
= NULL
;
493 /* (re)allocated lazily depending on the cursor size */
494 pBuffer
->pSave
= NULL
;
501 miDCDeviceCleanup(pDev
, pScreen
);
507 miDCDeviceCleanup(DeviceIntPtr pDev
, ScreenPtr pScreen
)
509 miDCBufferPtr pBuffer
;
512 if (DevHasCursor(pDev
)) {
513 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
514 pScreen
= screenInfo
.screens
[i
];
516 pBuffer
= miGetDCDevice(pDev
, pScreen
);
519 if (pBuffer
->pSourceGC
)
520 FreeGC(pBuffer
->pSourceGC
, (GContext
) 0);
521 if (pBuffer
->pMaskGC
)
522 FreeGC(pBuffer
->pMaskGC
, (GContext
) 0);
523 if (pBuffer
->pSaveGC
)
524 FreeGC(pBuffer
->pSaveGC
, (GContext
) 0);
525 if (pBuffer
->pRestoreGC
)
526 FreeGC(pBuffer
->pRestoreGC
, (GContext
) 0);
529 /* If a pRootPicture was allocated for a root window, it
530 * is freed when that root window is destroyed, so don't
531 * free it again here. */
535 (*pScreen
->DestroyPixmap
) (pBuffer
->pSave
);
538 dixSetScreenPrivate(&pDev
->devPrivates
, miDCDeviceKey
, pScreen
,