diff options
author | root <root@zombrain.(none)> | 2011-07-25 08:54:41 (GMT) |
---|---|---|
committer | root <root@zombrain.(none)> | 2011-07-25 08:54:41 (GMT) |
commit | ab4fcaad149d4bdccefa8f693c2a8e044b40dd4c (patch) | |
tree | c95c280caabc70e7aedbde723e38820047357be7 /mi/midispcur.c |
initial state (xorg-server 1.10.2)
Diffstat (limited to 'mi/midispcur.c')
-rw-r--r-- | mi/midispcur.c | 584 |
1 files changed, 584 insertions, 0 deletions
diff --git a/mi/midispcur.c b/mi/midispcur.c new file mode 100644 index 0000000..5a87fa2 --- /dev/null +++ b/mi/midispcur.c @@ -0,0 +1,584 @@ +/* + * midispcur.c + * + * machine independent cursor display routines + */ + + +/* + +Copyright 1989, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +# include <X11/X.h> +# include "misc.h" +# include "input.h" +# include "cursorstr.h" +# include "windowstr.h" +# include "regionstr.h" +# include "dixstruct.h" +# include "scrnintstr.h" +# include "servermd.h" +# include "mipointer.h" +# include "misprite.h" +# include "gcstruct.h" + +#ifdef ARGB_CURSOR +# include "picturestr.h" +#endif + +# include "inputstr.h" + +/* per-screen private data */ +static DevPrivateKeyRec miDCScreenKeyRec; +#define miDCScreenKey (&miDCScreenKeyRec) +static DevScreenPrivateKeyRec miDCCursorBitsKeyRec; +#define miDCCursorBitsKey (&miDCCursorBitsKeyRec) +static DevScreenPrivateKeyRec miDCDeviceKeyRec; +#define miDCDeviceKey (&miDCDeviceKeyRec) + +static Bool miDCCloseScreen(int index, ScreenPtr pScreen); + +/* per device private data */ +typedef struct { + GCPtr pSourceGC, pMaskGC; + GCPtr pSaveGC, pRestoreGC; + PixmapPtr pSave; +#ifdef ARGB_CURSOR + PicturePtr pRootPicture; +#endif +} miDCBufferRec, *miDCBufferPtr; + +#define miGetDCDevice(dev, screen) \ + ((DevHasCursor(dev)) ? \ + (miDCBufferPtr)dixLookupScreenPrivate(&dev->devPrivates, miDCDeviceKey, screen) : \ + (miDCBufferPtr)dixLookupScreenPrivate(&dev->u.master->devPrivates, miDCDeviceKey, screen)) + +/* + * The core pointer buffer will point to the index of the virtual core pointer + * in the pCursorBuffers array. + */ +typedef struct { + CloseScreenProcPtr CloseScreen; +} miDCScreenRec, *miDCScreenPtr; + +#define miGetDCScreen(s) ((miDCScreenPtr)(dixLookupPrivate(&(s)->devPrivates, miDCScreenKey))) + +/* per-cursor per-screen private data */ +typedef struct { + PixmapPtr sourceBits; /* source bits */ + PixmapPtr maskBits; /* mask bits */ +#ifdef ARGB_CURSOR + PicturePtr pPicture; +#endif +} miDCCursorRec, *miDCCursorPtr; + +Bool +miDCInitialize (ScreenPtr pScreen, miPointerScreenFuncPtr screenFuncs) +{ + miDCScreenPtr pScreenPriv; + + if (!dixRegisterPrivateKey(&miDCScreenKeyRec, PRIVATE_SCREEN, 0) || + !dixRegisterScreenPrivateKey(&miDCCursorBitsKeyRec, pScreen, PRIVATE_CURSOR_BITS, 0) || + !dixRegisterScreenPrivateKey(&miDCDeviceKeyRec, pScreen, PRIVATE_DEVICE, 0)) + return FALSE; + + pScreenPriv = malloc(sizeof (miDCScreenRec)); + if (!pScreenPriv) + return FALSE; + + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = miDCCloseScreen; + + dixSetPrivate(&pScreen->devPrivates, miDCScreenKey, pScreenPriv); + + if (!miSpriteInitialize (pScreen, screenFuncs)) + { + free((pointer) pScreenPriv); + return FALSE; + } + return TRUE; +} + +static Bool +miDCCloseScreen (int index, ScreenPtr pScreen) +{ + miDCScreenPtr pScreenPriv; + + pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + miDCScreenKey); + pScreen->CloseScreen = pScreenPriv->CloseScreen; + free((pointer) pScreenPriv); + return (*pScreen->CloseScreen) (index, pScreen); +} + +Bool +miDCRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +{ + if (pCursor->bits->refcnt <= 1) + dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, NULL); + return TRUE; +} + +#ifdef ARGB_CURSOR +#define EnsurePicture(picture,draw,win) (picture || miDCMakePicture(&picture,draw,win)) + +static VisualPtr +miDCGetWindowVisual (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + VisualID vid = wVisual (pWin); + int i; + + for (i = 0; i < pScreen->numVisuals; i++) + if (pScreen->visuals[i].vid == vid) + return &pScreen->visuals[i]; + return 0; +} + +static PicturePtr +miDCMakePicture (PicturePtr *ppPicture, DrawablePtr pDraw, WindowPtr pWin) +{ + ScreenPtr pScreen = pDraw->pScreen; + VisualPtr pVisual; + PictFormatPtr pFormat; + XID subwindow_mode = IncludeInferiors; + PicturePtr pPicture; + int error; + + pVisual = miDCGetWindowVisual (pWin); + if (!pVisual) + return 0; + pFormat = PictureMatchVisual (pScreen, pDraw->depth, pVisual); + if (!pFormat) + return 0; + pPicture = CreatePicture (0, pDraw, pFormat, + CPSubwindowMode, &subwindow_mode, + serverClient, &error); + *ppPicture = pPicture; + return pPicture; +} +#endif + +static miDCCursorPtr +miDCRealize (ScreenPtr pScreen, CursorPtr pCursor) +{ + miDCCursorPtr pPriv; + GCPtr pGC; + ChangeGCVal gcvals; + + pPriv = malloc(sizeof (miDCCursorRec)); + if (!pPriv) + return NULL; +#ifdef ARGB_CURSOR + if (pCursor->bits->argb) + { + PixmapPtr pPixmap; + PictFormatPtr pFormat; + int error; + + pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); + if (!pFormat) + { + free((pointer) pPriv); + return NULL; + } + + pPriv->sourceBits = 0; + pPriv->maskBits = 0; + pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, + pCursor->bits->height, 32, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!pPixmap) + { + free((pointer) pPriv); + return NULL; + } + pGC = GetScratchGC (32, pScreen); + if (!pGC) + { + (*pScreen->DestroyPixmap) (pPixmap); + free((pointer) pPriv); + return NULL; + } + ValidateGC (&pPixmap->drawable, pGC); + (*pGC->ops->PutImage) (&pPixmap->drawable, pGC, 32, + 0, 0, pCursor->bits->width, + pCursor->bits->height, + 0, ZPixmap, (char *) pCursor->bits->argb); + FreeScratchGC (pGC); + pPriv->pPicture = CreatePicture (0, &pPixmap->drawable, + pFormat, 0, 0, serverClient, &error); + (*pScreen->DestroyPixmap) (pPixmap); + if (!pPriv->pPicture) + { + free((pointer) pPriv); + return NULL; + } + dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, pPriv); + return pPriv; + } + pPriv->pPicture = 0; +#endif + pPriv->sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0); + if (!pPriv->sourceBits) + { + free((pointer) pPriv); + return NULL; + } + pPriv->maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0); + if (!pPriv->maskBits) + { + (*pScreen->DestroyPixmap) (pPriv->sourceBits); + free((pointer) pPriv); + return NULL; + } + dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, pPriv); + + /* create the two sets of bits, clipping as appropriate */ + + pGC = GetScratchGC (1, pScreen); + if (!pGC) + { + (void) miDCUnrealizeCursor (pScreen, pCursor); + return NULL; + } + + ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1, + 0, 0, pCursor->bits->width, pCursor->bits->height, + 0, XYPixmap, (char *)pCursor->bits->source); + gcvals.val = GXand; + ChangeGC (NullClient, pGC, GCFunction, &gcvals); + ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1, + 0, 0, pCursor->bits->width, pCursor->bits->height, + 0, XYPixmap, (char *)pCursor->bits->mask); + + /* mask bits -- pCursor->mask & ~pCursor->source */ + gcvals.val = GXcopy; + ChangeGC (NullClient, pGC, GCFunction, &gcvals); + ValidateGC ((DrawablePtr)pPriv->maskBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1, + 0, 0, pCursor->bits->width, pCursor->bits->height, + 0, XYPixmap, (char *)pCursor->bits->mask); + gcvals.val = GXandInverted; + ChangeGC (NullClient, pGC, GCFunction, &gcvals); + ValidateGC ((DrawablePtr)pPriv->maskBits, pGC); + (*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1, + 0, 0, pCursor->bits->width, pCursor->bits->height, + 0, XYPixmap, (char *)pCursor->bits->source); + FreeScratchGC (pGC); + return pPriv; +} + +Bool +miDCUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +{ + miDCCursorPtr pPriv; + + pPriv = (miDCCursorPtr)dixLookupScreenPrivate(&pCursor->bits->devPrivates, + miDCCursorBitsKey, pScreen); + if (pPriv && (pCursor->bits->refcnt <= 1)) + { + if (pPriv->sourceBits) + (*pScreen->DestroyPixmap) (pPriv->sourceBits); + if (pPriv->maskBits) + (*pScreen->DestroyPixmap) (pPriv->maskBits); +#ifdef ARGB_CURSOR + if (pPriv->pPicture) + FreePicture (pPriv->pPicture, 0); +#endif + free((pointer) pPriv); + dixSetScreenPrivate(&pCursor->bits->devPrivates, miDCCursorBitsKey, pScreen, NULL); + } + return TRUE; +} + +static void +miDCPutBits ( + DrawablePtr pDrawable, + miDCCursorPtr pPriv, + GCPtr sourceGC, + GCPtr maskGC, + int x_org, + int y_org, + unsigned w, + unsigned h, + unsigned long source, + unsigned long mask) +{ + ChangeGCVal gcval; + int x, y; + + if (sourceGC->fgPixel != source) + { + gcval.val = source; + ChangeGC (NullClient, sourceGC, GCForeground, &gcval); + } + if (sourceGC->serialNumber != pDrawable->serialNumber) + ValidateGC (pDrawable, sourceGC); + + if(sourceGC->miTranslate) + { + x = pDrawable->x + x_org; + y = pDrawable->y + y_org; + } + else + { + x = x_org; + y = y_org; + } + + (*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, x, y); + if (maskGC->fgPixel != mask) + { + gcval.val = mask; + ChangeGC (NullClient, maskGC, GCForeground, &gcval); + } + if (maskGC->serialNumber != pDrawable->serialNumber) + ValidateGC (pDrawable, maskGC); + + if(maskGC->miTranslate) + { + x = pDrawable->x + x_org; + y = pDrawable->y + y_org; + } + else + { + x = x_org; + y = y_org; + } + + (*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y); +} + +static GCPtr +miDCMakeGC(WindowPtr pWin) +{ + GCPtr pGC; + int status; + XID gcvals[2]; + + gcvals[0] = IncludeInferiors; + gcvals[1] = FALSE; + pGC = CreateGC((DrawablePtr)pWin, + GCSubwindowMode|GCGraphicsExposures, gcvals, &status, + (XID)0, serverClient); + return pGC; +} + + +Bool +miDCPutUpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, + int x, int y, unsigned long source, unsigned long mask) +{ + miDCCursorPtr pPriv; + miDCBufferPtr pBuffer; + WindowPtr pWin; + + pPriv = (miDCCursorPtr)dixLookupScreenPrivate(&pCursor->bits->devPrivates, + miDCCursorBitsKey, pScreen); + if (!pPriv) + { + pPriv = miDCRealize(pScreen, pCursor); + if (!pPriv) + return FALSE; + } + + pWin = pScreen->root; + pBuffer = miGetDCDevice(pDev, pScreen); + +#ifdef ARGB_CURSOR + if (pPriv->pPicture) + { + if (!EnsurePicture(pBuffer->pRootPicture, &pWin->drawable, pWin)) + return FALSE; + CompositePicture (PictOpOver, + pPriv->pPicture, + NULL, + pBuffer->pRootPicture, + 0, 0, 0, 0, + x, y, + pCursor->bits->width, + pCursor->bits->height); + } + else +#endif + { + miDCPutBits ((DrawablePtr)pWin, pPriv, + pBuffer->pSourceGC, pBuffer->pMaskGC, + x, y, pCursor->bits->width, pCursor->bits->height, + source, mask); + } + return TRUE; +} + +Bool +miDCSaveUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, int w, int h) +{ + miDCBufferPtr pBuffer; + PixmapPtr pSave; + WindowPtr pWin; + GCPtr pGC; + + pBuffer = miGetDCDevice(pDev, pScreen); + + pSave = pBuffer->pSave; + pWin = pScreen->root; + if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h) + { + if (pSave) + (*pScreen->DestroyPixmap) (pSave); + pBuffer->pSave = pSave = + (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth, 0); + if (!pSave) + return FALSE; + } + + pGC = pBuffer->pSaveGC; + if (pSave->drawable.serialNumber != pGC->serialNumber) + ValidateGC ((DrawablePtr) pSave, pGC); + (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, + x, y, w, h, 0, 0); + return TRUE; +} + +Bool +miDCRestoreUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, int w, int h) +{ + miDCBufferPtr pBuffer; + PixmapPtr pSave; + WindowPtr pWin; + GCPtr pGC; + + pBuffer = miGetDCDevice(pDev, pScreen); + pSave = pBuffer->pSave; + + pWin = pScreen->root; + if (!pSave) + return FALSE; + + pGC = pBuffer->pRestoreGC; + if (pWin->drawable.serialNumber != pGC->serialNumber) + ValidateGC ((DrawablePtr) pWin, pGC); + (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, + 0, 0, w, h, x, y); + return TRUE; +} + +Bool +miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miDCBufferPtr pBuffer; + WindowPtr pWin; + int i; + + if (!DevHasCursor(pDev)) + return TRUE; + + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + + pBuffer = calloc(1, sizeof(miDCBufferRec)); + if (!pBuffer) + goto failure; + + dixSetScreenPrivate(&pDev->devPrivates, miDCDeviceKey, pScreen, pBuffer); + pWin = pScreen->root; + + pBuffer->pSourceGC = miDCMakeGC(pWin); + if (!pBuffer->pSourceGC) + goto failure; + + pBuffer->pMaskGC = miDCMakeGC(pWin); + if (!pBuffer->pMaskGC) + goto failure; + + pBuffer->pSaveGC = miDCMakeGC(pWin); + if (!pBuffer->pSaveGC) + goto failure; + + pBuffer->pRestoreGC = miDCMakeGC(pWin); + if (!pBuffer->pRestoreGC) + goto failure; + +#ifdef ARGB_CURSOR + pBuffer->pRootPicture = NULL; +#endif + + /* (re)allocated lazily depending on the cursor size */ + pBuffer->pSave = NULL; + } + + return TRUE; + +failure: + + miDCDeviceCleanup(pDev, pScreen); + + return FALSE; +} + +void +miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miDCBufferPtr pBuffer; + int i; + + if (DevHasCursor(pDev)) + { + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + + pBuffer = miGetDCDevice(pDev, pScreen); + + if (pBuffer) + { + if (pBuffer->pSourceGC) FreeGC(pBuffer->pSourceGC, (GContext) 0); + if (pBuffer->pMaskGC) FreeGC(pBuffer->pMaskGC, (GContext) 0); + if (pBuffer->pSaveGC) FreeGC(pBuffer->pSaveGC, (GContext) 0); + if (pBuffer->pRestoreGC) FreeGC(pBuffer->pRestoreGC, (GContext) 0); + +#ifdef ARGB_CURSOR + /* If a pRootPicture was allocated for a root window, it + * is freed when that root window is destroyed, so don't + * free it again here. */ +#endif + + if (pBuffer->pSave) (*pScreen->DestroyPixmap)(pBuffer->pSave); + + free(pBuffer); + dixSetScreenPrivate(&pDev->devPrivates, miDCDeviceKey, pScreen, NULL); + } + } + } +} |