os/log: trivial cleanups
[xserver/hramrach.git] / mi / midispcur.c
blob24b9a700da2577d0f22578751b98c254426dc301
1 /*
2 * midispcur.c
4 * machine independent cursor display routines
5 */
7 /*
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
15 documentation.
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>
34 #endif
36 #include <X11/X.h>
37 #include "misc.h"
38 #include "input.h"
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 #ifdef ARGB_CURSOR
50 #include "picturestr.h"
51 #endif
53 #include "inputstr.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 */
69 typedef struct {
70 GCPtr pSourceGC, pMaskGC;
71 GCPtr pSaveGC, pRestoreGC;
72 PixmapPtr pSave;
73 #ifdef ARGB_CURSOR
74 PicturePtr pRootPicture;
75 #endif
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))
83 /*
84 * The core pointer buffer will point to the index of the virtual core pointer
85 * in the pCursorBuffers array.
87 typedef struct {
88 CloseScreenProcPtr CloseScreen;
89 } miDCScreenRec, *miDCScreenPtr;
91 #define miGetDCScreen(s) ((miDCScreenPtr)(dixLookupPrivate(&(s)->devPrivates, miDCScreenKey)))
93 /* per-cursor per-screen private data */
94 typedef struct {
95 PixmapPtr sourceBits; /* source bits */
96 PixmapPtr maskBits; /* mask bits */
97 #ifdef ARGB_CURSOR
98 PicturePtr pPicture;
99 #endif
100 } miDCCursorRec, *miDCCursorPtr;
102 Bool
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,
112 return FALSE;
114 pScreenPriv = malloc(sizeof(miDCScreenRec));
115 if (!pScreenPriv)
116 return FALSE;
118 pScreenPriv->CloseScreen = pScreen->CloseScreen;
119 pScreen->CloseScreen = miDCCloseScreen;
121 dixSetPrivate(&pScreen->devPrivates, miDCScreenKey, pScreenPriv);
123 if (!miSpriteInitialize(pScreen, screenFuncs)) {
124 free((pointer) pScreenPriv);
125 return FALSE;
127 return TRUE;
130 static Bool
131 miDCCloseScreen(int index, ScreenPtr pScreen)
133 miDCScreenPtr pScreenPriv;
135 pScreenPriv = (miDCScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
136 miDCScreenKey);
137 pScreen->CloseScreen = pScreenPriv->CloseScreen;
138 free((pointer) pScreenPriv);
139 return (*pScreen->CloseScreen) (index, pScreen);
142 Bool
143 miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
145 if (pCursor->bits->refcnt <= 1)
146 dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey,
147 pScreen, NULL);
148 return TRUE;
151 #ifdef ARGB_CURSOR
152 #define EnsurePicture(picture,draw,win) (picture || miDCMakePicture(&picture,draw,win))
154 static VisualPtr
155 miDCGetWindowVisual(WindowPtr pWin)
157 ScreenPtr pScreen = pWin->drawable.pScreen;
158 VisualID vid = wVisual(pWin);
159 int i;
161 for (i = 0; i < pScreen->numVisuals; i++)
162 if (pScreen->visuals[i].vid == vid)
163 return &pScreen->visuals[i];
164 return 0;
167 static PicturePtr
168 miDCMakePicture(PicturePtr * ppPicture, DrawablePtr pDraw, WindowPtr pWin)
170 ScreenPtr pScreen = pDraw->pScreen;
171 VisualPtr pVisual;
172 PictFormatPtr pFormat;
173 XID subwindow_mode = IncludeInferiors;
174 PicturePtr pPicture;
175 int error;
177 pVisual = miDCGetWindowVisual(pWin);
178 if (!pVisual)
179 return 0;
180 pFormat = PictureMatchVisual(pScreen, pDraw->depth, pVisual);
181 if (!pFormat)
182 return 0;
183 pPicture = CreatePicture(0, pDraw, pFormat,
184 CPSubwindowMode, &subwindow_mode,
185 serverClient, &error);
186 *ppPicture = pPicture;
187 return pPicture;
189 #endif
191 static miDCCursorPtr
192 miDCRealize(ScreenPtr pScreen, CursorPtr pCursor)
194 miDCCursorPtr pPriv;
195 GCPtr pGC;
196 ChangeGCVal gcvals;
198 pPriv = malloc(sizeof(miDCCursorRec));
199 if (!pPriv)
200 return NULL;
201 #ifdef ARGB_CURSOR
202 if (pCursor->bits->argb) {
203 PixmapPtr pPixmap;
204 PictFormatPtr pFormat;
205 int error;
207 pFormat = PictureMatchFormat(pScreen, 32, PICT_a8r8g8b8);
208 if (!pFormat) {
209 free((pointer) pPriv);
210 return NULL;
213 pPriv->sourceBits = 0;
214 pPriv->maskBits = 0;
215 pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
216 pCursor->bits->height, 32,
217 CREATE_PIXMAP_USAGE_SCRATCH);
218 if (!pPixmap) {
219 free((pointer) pPriv);
220 return NULL;
222 pGC = GetScratchGC(32, pScreen);
223 if (!pGC) {
224 (*pScreen->DestroyPixmap) (pPixmap);
225 free((pointer) pPriv);
226 return NULL;
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);
233 FreeScratchGC(pGC);
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);
239 return NULL;
241 dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey,
242 pScreen, pPriv);
243 return pPriv;
245 pPriv->pPicture = 0;
246 #endif
247 pPriv->sourceBits =
248 (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
249 pCursor->bits->height, 1, 0);
250 if (!pPriv->sourceBits) {
251 free((pointer) pPriv);
252 return NULL;
254 pPriv->maskBits =
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);
260 return NULL;
262 dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen,
263 pPriv);
265 /* create the two sets of bits, clipping as appropriate */
267 pGC = GetScratchGC(1, pScreen);
268 if (!pGC) {
269 (void) miDCUnrealizeCursor(pScreen, pCursor);
270 return NULL;
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);
277 gcvals.val = GXand;
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 */
285 gcvals.val = GXcopy;
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);
297 FreeScratchGC(pGC);
298 return pPriv;
301 Bool
302 miDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
304 miDCCursorPtr pPriv;
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);
311 if (pPriv->maskBits)
312 (*pScreen->DestroyPixmap) (pPriv->maskBits);
313 #ifdef ARGB_CURSOR
314 if (pPriv->pPicture)
315 FreePicture(pPriv->pPicture, 0);
316 #endif
317 free((pointer) pPriv);
318 dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey,
319 pScreen, NULL);
321 return TRUE;
324 static void
325 miDCPutBits(DrawablePtr pDrawable,
326 miDCCursorPtr pPriv,
327 GCPtr sourceGC,
328 GCPtr maskGC,
329 int x_org,
330 int y_org,
331 unsigned w, unsigned h, unsigned long source, unsigned long mask)
333 ChangeGCVal gcval;
334 int x, y;
336 if (sourceGC->fgPixel != source) {
337 gcval.val = 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;
347 else {
348 x = x_org;
349 y = y_org;
352 (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h,
353 x, y);
354 if (maskGC->fgPixel != mask) {
355 gcval.val = 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;
365 else {
366 x = x_org;
367 y = y_org;
370 (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y);
373 static GCPtr
374 miDCMakeGC(WindowPtr pWin)
376 GCPtr pGC;
377 int status;
378 XID gcvals[2];
380 gcvals[0] = IncludeInferiors;
381 gcvals[1] = FALSE;
382 pGC = CreateGC((DrawablePtr) pWin,
383 GCSubwindowMode | GCGraphicsExposures, gcvals, &status,
384 (XID) 0, serverClient);
385 return pGC;
388 Bool
389 miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
390 int x, int y, unsigned long source, unsigned long mask)
392 miDCCursorPtr pPriv;
393 miDCBufferPtr pBuffer;
394 WindowPtr pWin;
396 pPriv = (miDCCursorPtr) dixLookupScreenPrivate(&pCursor->bits->devPrivates,
397 miDCCursorBitsKey, pScreen);
398 if (!pPriv) {
399 pPriv = miDCRealize(pScreen, pCursor);
400 if (!pPriv)
401 return FALSE;
404 pWin = pScreen->root;
405 pBuffer = miGetDCDevice(pDev, pScreen);
407 #ifdef ARGB_CURSOR
408 if (pPriv->pPicture) {
409 if (!EnsurePicture(pBuffer->pRootPicture, &pWin->drawable, pWin))
410 return FALSE;
411 CompositePicture(PictOpOver,
412 pPriv->pPicture,
413 NULL,
414 pBuffer->pRootPicture,
415 0, 0, 0, 0,
416 x, y, pCursor->bits->width, pCursor->bits->height);
418 else
419 #endif
421 miDCPutBits((DrawablePtr) pWin, pPriv,
422 pBuffer->pSourceGC, pBuffer->pMaskGC,
423 x, y, pCursor->bits->width, pCursor->bits->height,
424 source, mask);
426 return TRUE;
429 Bool
430 miDCSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
431 int x, int y, int w, int h)
433 miDCBufferPtr pBuffer;
434 PixmapPtr pSave;
435 WindowPtr pWin;
436 GCPtr pGC;
438 pBuffer = miGetDCDevice(pDev, pScreen);
440 pSave = pBuffer->pSave;
441 pWin = pScreen->root;
442 if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h) {
443 if (pSave)
444 (*pScreen->DestroyPixmap) (pSave);
445 pBuffer->pSave = pSave =
446 (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth, 0);
447 if (!pSave)
448 return FALSE;
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,
455 x, y, w, h, 0, 0);
456 return TRUE;
459 Bool
460 miDCRestoreUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
461 int x, int y, int w, int h)
463 miDCBufferPtr pBuffer;
464 PixmapPtr pSave;
465 WindowPtr pWin;
466 GCPtr pGC;
468 pBuffer = miGetDCDevice(pDev, pScreen);
469 pSave = pBuffer->pSave;
471 pWin = pScreen->root;
472 if (!pSave)
473 return FALSE;
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,
479 0, 0, w, h, x, y);
480 return TRUE;
483 Bool
484 miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
486 miDCBufferPtr pBuffer;
487 WindowPtr pWin;
488 int i;
490 if (!DevHasCursor(pDev))
491 return TRUE;
493 for (i = 0; i < screenInfo.numScreens; i++) {
494 pScreen = screenInfo.screens[i];
496 pBuffer = calloc(1, sizeof(miDCBufferRec));
497 if (!pBuffer)
498 goto failure;
500 dixSetScreenPrivate(&pDev->devPrivates, miDCDeviceKey, pScreen,
501 pBuffer);
502 pWin = pScreen->root;
504 pBuffer->pSourceGC = miDCMakeGC(pWin);
505 if (!pBuffer->pSourceGC)
506 goto failure;
508 pBuffer->pMaskGC = miDCMakeGC(pWin);
509 if (!pBuffer->pMaskGC)
510 goto failure;
512 pBuffer->pSaveGC = miDCMakeGC(pWin);
513 if (!pBuffer->pSaveGC)
514 goto failure;
516 pBuffer->pRestoreGC = miDCMakeGC(pWin);
517 if (!pBuffer->pRestoreGC)
518 goto failure;
520 #ifdef ARGB_CURSOR
521 pBuffer->pRootPicture = NULL;
522 #endif
524 /* (re)allocated lazily depending on the cursor size */
525 pBuffer->pSave = NULL;
528 return TRUE;
530 failure:
532 miDCDeviceCleanup(pDev, pScreen);
534 return FALSE;
537 void
538 miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
540 miDCBufferPtr pBuffer;
541 int i;
543 if (DevHasCursor(pDev)) {
544 for (i = 0; i < screenInfo.numScreens; i++) {
545 pScreen = screenInfo.screens[i];
547 pBuffer = miGetDCDevice(pDev, pScreen);
549 if (pBuffer) {
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);
559 #ifdef ARGB_CURSOR
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. */
563 #endif
565 if (pBuffer->pSave)
566 (*pScreen->DestroyPixmap) (pBuffer->pSave);
568 free(pBuffer);
569 dixSetScreenPrivate(&pDev->devPrivates, miDCDeviceKey, pScreen,
570 NULL);