4 * machine independent cursor display routines
7 /* $XConsortium: midispcur.c,v 5.14 94/04/17 20:27:28 dpw Exp $ */
11 Copyright (c) 1989 X Consortium
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
20 The above copyright notice and this permission notice shall be included in
21 all copies or substantial portions of the Software.
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
27 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 Except as contained in this notice, the name of the X Consortium shall not be
31 used in advertising or otherwise to promote the sale, use or other dealings
32 in this Software without prior written authorization from the X Consortium.
39 # include "cursorstr.h"
40 # include "windowstr.h"
41 # include "regionstr.h"
42 # include "dixstruct.h"
43 # include "scrnintstr.h"
44 # include "servermd.h"
45 # include "mipointer.h"
46 # include "misprite.h"
47 # include "gcstruct.h"
49 extern WindowPtr *WindowTable;
51 /* per-screen private data */
53 static int miDCScreenIndex;
54 static unsigned long miDCGeneration = 0;
56 static Bool miDCCloseScreen();
59 GCPtr pSourceGC, pMaskGC;
60 GCPtr pSaveGC, pRestoreGC;
62 GCPtr pPixSourceGC, pPixMaskGC;
63 CloseScreenProcPtr CloseScreen;
64 PixmapPtr pSave, pTemp;
65 } miDCScreenRec, *miDCScreenPtr;
67 /* per-cursor per-screen private data */
69 PixmapPtr sourceBits; /* source bits */
70 PixmapPtr maskBits; /* mask bits */
71 } miDCCursorRec, *miDCCursorPtr;
74 * sprite/cursor method table
77 static Bool miDCRealizeCursor(), miDCUnrealizeCursor();
78 static Bool miDCPutUpCursor(), miDCSaveUnderCursor();
79 static Bool miDCRestoreUnderCursor(), miDCMoveCursor();
80 static Bool miDCChangeSave();
82 static miSpriteCursorFuncRec miDCFuncs = {
87 miDCRestoreUnderCursor,
93 miDCInitialize (pScreen, screenFuncs)
95 miPointerScreenFuncPtr screenFuncs;
97 miDCScreenPtr pScreenPriv;
99 if (miDCGeneration != serverGeneration)
101 miDCScreenIndex = AllocateScreenPrivateIndex ();
102 if (miDCScreenIndex < 0)
104 miDCGeneration = serverGeneration;
106 pScreenPriv = (miDCScreenPtr) xalloc (sizeof (miDCScreenRec));
111 * initialize the entire private structure to zeros
114 pScreenPriv->pSourceGC =
115 pScreenPriv->pMaskGC =
116 pScreenPriv->pSaveGC =
117 pScreenPriv->pRestoreGC =
118 pScreenPriv->pMoveGC =
119 pScreenPriv->pPixSourceGC =
120 pScreenPriv->pPixMaskGC = NULL;
122 pScreenPriv->pSave = pScreenPriv->pTemp = NULL;
124 pScreenPriv->CloseScreen = pScreen->CloseScreen;
125 pScreen->CloseScreen = miDCCloseScreen;
127 pScreen->devPrivates[miDCScreenIndex].ptr = (pointer) pScreenPriv;
129 if (!miSpriteInitialize (pScreen, &miDCFuncs, screenFuncs))
131 xfree ((pointer) pScreenPriv);
137 #define tossGC(gc) (gc ? FreeGC (gc, (GContext) 0) : 0)
138 #define tossPix(pix) (pix ? (*pScreen->DestroyPixmap) (pix) : TRUE)
141 miDCCloseScreen (index, pScreen)
144 miDCScreenPtr pScreenPriv;
146 pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
147 pScreen->CloseScreen = pScreenPriv->CloseScreen;
148 tossGC (pScreenPriv->pSourceGC);
149 tossGC (pScreenPriv->pMaskGC);
150 tossGC (pScreenPriv->pSaveGC);
151 tossGC (pScreenPriv->pRestoreGC);
152 tossGC (pScreenPriv->pMoveGC);
153 tossGC (pScreenPriv->pPixSourceGC);
154 tossGC (pScreenPriv->pPixMaskGC);
155 tossPix (pScreenPriv->pSave);
156 tossPix (pScreenPriv->pTemp);
157 xfree ((pointer) pScreenPriv);
158 return (*pScreen->CloseScreen) (index, pScreen);
162 miDCRealizeCursor (pScreen, pCursor)
166 if (pCursor->bits->refcnt <= 1)
167 pCursor->bits->devPriv[pScreen->myNum] = (pointer)NULL;
172 miDCRealize (pScreen, pCursor)
180 pPriv = (miDCCursorPtr) xalloc (sizeof (miDCCursorRec));
182 return (miDCCursorPtr)NULL;
183 pPriv->sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1);
184 if (!pPriv->sourceBits)
186 xfree ((pointer) pPriv);
187 return (miDCCursorPtr)NULL;
189 pPriv->maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1);
190 if (!pPriv->maskBits)
192 (*pScreen->DestroyPixmap) (pPriv->sourceBits);
193 xfree ((pointer) pPriv);
194 return (miDCCursorPtr)NULL;
196 pCursor->bits->devPriv[pScreen->myNum] = (pointer) pPriv;
198 /* create the two sets of bits, clipping as appropriate */
200 pGC = GetScratchGC (1, pScreen);
203 (void) miDCUnrealizeCursor (pScreen, pCursor);
204 return (miDCCursorPtr)NULL;
207 ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC);
208 (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1,
209 0, 0, pCursor->bits->width, pCursor->bits->height,
210 0, XYPixmap, (char *)pCursor->bits->source);
212 ChangeGC (pGC, GCFunction, gcvals);
213 ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC);
214 (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1,
215 0, 0, pCursor->bits->width, pCursor->bits->height,
216 0, XYPixmap, (char *)pCursor->bits->mask);
218 /* mask bits -- pCursor->mask & ~pCursor->source */
220 ChangeGC (pGC, GCFunction, gcvals);
221 ValidateGC ((DrawablePtr)pPriv->maskBits, pGC);
222 (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1,
223 0, 0, pCursor->bits->width, pCursor->bits->height,
224 0, XYPixmap, (char *)pCursor->bits->mask);
225 gcvals[0] = GXandInverted;
226 ChangeGC (pGC, GCFunction, gcvals);
227 ValidateGC ((DrawablePtr)pPriv->maskBits, pGC);
228 (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1,
229 0, 0, pCursor->bits->width, pCursor->bits->height,
230 0, XYPixmap, (char *)pCursor->bits->source);
236 miDCUnrealizeCursor (pScreen, pCursor)
242 pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum];
243 if (pPriv && (pCursor->bits->refcnt <= 1))
245 (*pScreen->DestroyPixmap) (pPriv->sourceBits);
246 (*pScreen->DestroyPixmap) (pPriv->maskBits);
247 xfree ((pointer) pPriv);
248 pCursor->bits->devPriv[pScreen->myNum] = (pointer)NULL;
254 miDCPutBits (pDrawable, pPriv, sourceGC, maskGC, x, y, w, h, source, mask)
255 DrawablePtr pDrawable;
256 GCPtr sourceGC, maskGC;
260 unsigned long source, mask;
264 if (sourceGC->fgPixel != source)
267 DoChangeGC (sourceGC, GCForeground, gcvals, 0);
269 if (sourceGC->serialNumber != pDrawable->serialNumber)
270 ValidateGC (pDrawable, sourceGC);
271 (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, x, y);
272 if (maskGC->fgPixel != mask)
275 DoChangeGC (maskGC, GCForeground, gcvals, 0);
277 if (maskGC->serialNumber != pDrawable->serialNumber)
278 ValidateGC (pDrawable, maskGC);
279 (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y);
282 #define EnsureGC(gc,win) (gc || miDCMakeGC(&gc, win))
285 miDCMakeGC(ppGC, pWin)
293 gcvals[0] = IncludeInferiors;
295 pGC = CreateGC((DrawablePtr)pWin,
296 GCSubwindowMode|GCGraphicsExposures, gcvals, &status);
298 (*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack);
304 miDCPutUpCursor (pScreen, pCursor, x, y, source, mask)
308 unsigned long source, mask;
310 miDCScreenPtr pScreenPriv;
314 pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum];
317 pPriv = miDCRealize(pScreen, pCursor);
321 pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
322 pWin = WindowTable[pScreen->myNum];
323 if (!EnsureGC(pScreenPriv->pSourceGC, pWin))
325 if (!EnsureGC(pScreenPriv->pMaskGC, pWin))
327 FreeGC (pScreenPriv->pSourceGC, (GContext) 0);
328 pScreenPriv->pSourceGC = 0;
331 miDCPutBits ((DrawablePtr)pWin, pPriv,
332 pScreenPriv->pSourceGC, pScreenPriv->pMaskGC,
333 x, y, pCursor->bits->width, pCursor->bits->height,
339 miDCSaveUnderCursor (pScreen, x, y, w, h)
343 miDCScreenPtr pScreenPriv;
348 pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
349 pSave = pScreenPriv->pSave;
350 pWin = WindowTable[pScreen->myNum];
351 if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h)
354 (*pScreen->DestroyPixmap) (pSave);
355 pScreenPriv->pSave = pSave =
356 (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth);
360 if (!EnsureGC(pScreenPriv->pSaveGC, pWin))
362 pGC = pScreenPriv->pSaveGC;
363 if (pSave->drawable.serialNumber != pGC->serialNumber)
364 ValidateGC ((DrawablePtr) pSave, pGC);
365 (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
371 miDCRestoreUnderCursor (pScreen, x, y, w, h)
375 miDCScreenPtr pScreenPriv;
380 pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
381 pSave = pScreenPriv->pSave;
382 pWin = WindowTable[pScreen->myNum];
385 if (!EnsureGC(pScreenPriv->pRestoreGC, pWin))
387 pGC = pScreenPriv->pRestoreGC;
388 if (pWin->drawable.serialNumber != pGC->serialNumber)
389 ValidateGC ((DrawablePtr) pWin, pGC);
390 (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
396 miDCChangeSave (pScreen, x, y, w, h, dx, dy)
398 int x, y, w, h, dx, dy;
400 miDCScreenPtr pScreenPriv;
404 int sourcex, sourcey, destx, desty, copyw, copyh;
406 pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
407 pSave = pScreenPriv->pSave;
408 pWin = WindowTable[pScreen->myNum];
410 * restore the bits which are about to get trashed
414 if (!EnsureGC(pScreenPriv->pRestoreGC, pWin))
416 pGC = pScreenPriv->pRestoreGC;
417 if (pWin->drawable.serialNumber != pGC->serialNumber)
418 ValidateGC ((DrawablePtr) pWin, pGC);
420 * copy the old bits to the screen.
424 (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
425 0, h - dy, w, dy, x + dx, y + h);
429 (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
430 0, 0, w, -dy, x + dx, y + dy);
446 (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
447 w - dx, sourcey, dx, copyh, x + w, desty);
451 (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
452 0, sourcey, -dx, copyh, x + dx, desty);
454 if (!EnsureGC(pScreenPriv->pSaveGC, pWin))
456 pGC = pScreenPriv->pSaveGC;
457 if (pSave->drawable.serialNumber != pGC->serialNumber)
458 ValidateGC ((DrawablePtr) pSave, pGC);
460 * move the bits that are still valid within the pixmap
486 (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pSave, pGC,
487 sourcex, sourcey, copyw, copyh, destx, desty);
489 * copy the new bits from the screen into the remaining areas of the
494 (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
499 (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
500 x, y + h + dy, w, -dy, 0, h + dy);
516 (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
517 x, sourcey, dx, copyh, 0, desty);
521 (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
522 x + w + dx, sourcey, -dx, copyh, w + dx, desty);
528 miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
531 int x, y, w, h, dx, dy;
532 unsigned long source, mask;
535 miDCScreenPtr pScreenPriv;
542 pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum];
545 pPriv = miDCRealize(pScreen, pCursor);
549 pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
550 pWin = WindowTable[pScreen->myNum];
551 pTemp = pScreenPriv->pTemp;
553 pTemp->drawable.width != pScreenPriv->pSave->drawable.width ||
554 pTemp->drawable.height != pScreenPriv->pSave->drawable.height)
557 (*pScreen->DestroyPixmap) (pTemp);
558 pScreenPriv->pTemp = pTemp = (*pScreen->CreatePixmap)
559 (pScreen, w, h, pScreenPriv->pSave->drawable.depth);
563 if (!pScreenPriv->pMoveGC)
565 pScreenPriv->pMoveGC = CreateGC ((DrawablePtr)pTemp,
566 GCGraphicsExposures, &gcval, &status);
567 if (!pScreenPriv->pMoveGC)
571 * copy the saved area to a temporary pixmap
573 pGC = pScreenPriv->pMoveGC;
574 if (pGC->serialNumber != pTemp->drawable.serialNumber)
575 ValidateGC ((DrawablePtr) pTemp, pGC);
576 (*pGC->ops->CopyArea)((DrawablePtr)pScreenPriv->pSave,
577 (DrawablePtr)pTemp, pGC, 0, 0, w, h, 0, 0);
580 * draw the cursor in the temporary pixmap
582 if (!pScreenPriv->pPixSourceGC)
584 pScreenPriv->pPixSourceGC = CreateGC ((DrawablePtr)pTemp,
585 GCGraphicsExposures, &gcval, &status);
586 if (!pScreenPriv->pPixSourceGC)
589 if (!pScreenPriv->pPixMaskGC)
591 pScreenPriv->pPixMaskGC = CreateGC ((DrawablePtr)pTemp,
592 GCGraphicsExposures, &gcval, &status);
593 if (!pScreenPriv->pPixMaskGC)
596 miDCPutBits ((DrawablePtr)pTemp, pPriv,
597 pScreenPriv->pPixSourceGC, pScreenPriv->pPixMaskGC,
598 dx, dy, pCursor->bits->width, pCursor->bits->height,
602 * copy the temporary pixmap onto the screen
605 if (!EnsureGC(pScreenPriv->pRestoreGC, pWin))
607 pGC = pScreenPriv->pRestoreGC;
608 if (pWin->drawable.serialNumber != pGC->serialNumber)
609 ValidateGC ((DrawablePtr) pWin, pGC);
611 (*pGC->ops->CopyArea) ((DrawablePtr) pTemp, (DrawablePtr) pWin,