diff options
Diffstat (limited to 'xorg-server/mi')
-rw-r--r-- | xorg-server/mi/midispcur.c | 1184 | ||||
-rw-r--r-- | xorg-server/mi/mieq.c | 992 | ||||
-rw-r--r-- | xorg-server/mi/mipointer.c | 1278 | ||||
-rw-r--r-- | xorg-server/mi/mipointrst.h | 1 | ||||
-rw-r--r-- | xorg-server/mi/misprite.c | 2090 |
5 files changed, 2823 insertions, 2722 deletions
diff --git a/xorg-server/mi/midispcur.c b/xorg-server/mi/midispcur.c index ef5c4e29e..9b3e87a57 100644 --- a/xorg-server/mi/midispcur.c +++ b/xorg-server/mi/midispcur.c @@ -1,592 +1,592 @@ -/*
- * 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)
-{
- miDCScreenPtr pScreenPriv;
- miDCCursorPtr pPriv;
- miDCBufferPtr pBuffer;
- WindowPtr pWin;
-
- pPriv = (miDCCursorPtr)dixLookupScreenPrivate(&pCursor->bits->devPrivates,
- miDCCursorBitsKey, pScreen);
- if (!pPriv)
- {
- pPriv = miDCRealize(pScreen, pCursor);
- if (!pPriv)
- return FALSE;
- }
- pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
- miDCScreenKey);
- 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)
-{
- miDCScreenPtr pScreenPriv;
- miDCBufferPtr pBuffer;
- PixmapPtr pSave;
- WindowPtr pWin;
- GCPtr pGC;
-
- pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
- miDCScreenKey);
- 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)
-{
- miDCScreenPtr pScreenPriv;
- miDCBufferPtr pBuffer;
- PixmapPtr pSave;
- WindowPtr pWin;
- GCPtr pGC;
-
- pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
- miDCScreenKey);
- 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);
- }
- }
- }
-}
+/* + * 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(&GetMaster(dev, MASTER_POINTER)->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) +{ + miDCScreenPtr pScreenPriv; + miDCCursorPtr pPriv; + miDCBufferPtr pBuffer; + WindowPtr pWin; + + pPriv = (miDCCursorPtr)dixLookupScreenPrivate(&pCursor->bits->devPrivates, + miDCCursorBitsKey, pScreen); + if (!pPriv) + { + pPriv = miDCRealize(pScreen, pCursor); + if (!pPriv) + return FALSE; + } + pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + miDCScreenKey); + 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) +{ + miDCScreenPtr pScreenPriv; + miDCBufferPtr pBuffer; + PixmapPtr pSave; + WindowPtr pWin; + GCPtr pGC; + + pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + miDCScreenKey); + 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) +{ + miDCScreenPtr pScreenPriv; + miDCBufferPtr pBuffer; + PixmapPtr pSave; + WindowPtr pWin; + GCPtr pGC; + + pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + miDCScreenKey); + 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); + } + } + } +} diff --git a/xorg-server/mi/mieq.c b/xorg-server/mi/mieq.c index 974bec77d..08a0c8758 100644 --- a/xorg-server/mi/mieq.c +++ b/xorg-server/mi/mieq.c @@ -1,495 +1,497 @@ -/*
- *
-Copyright 1990, 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.
- *
- * Author: Keith Packard, MIT X Consortium
- */
-
-/*
- * mieq.c
- *
- * Machine independent event queue
- *
- */
-
-#if HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-# include <X11/X.h>
-# include <X11/Xmd.h>
-# include <X11/Xproto.h>
-# include "misc.h"
-# include "windowstr.h"
-# include "pixmapstr.h"
-# include "inputstr.h"
-# include "mi.h"
-# include "mipointer.h"
-# include "scrnintstr.h"
-# include <X11/extensions/XI.h>
-# include <X11/extensions/XIproto.h>
-# include <X11/extensions/geproto.h>
-# include "extinit.h"
-# include "exglobals.h"
-# include "eventstr.h"
-
-#ifdef DPMSExtension
-# include "dpmsproc.h"
-# include <X11/extensions/dpmsconst.h>
-#endif
-
-#define QUEUE_SIZE 512
-
-#define EnqueueScreen(dev) dev->spriteInfo->sprite->pEnqueueScreen
-#define DequeueScreen(dev) dev->spriteInfo->sprite->pDequeueScreen
-
-typedef struct _Event {
- EventListPtr events;
- ScreenPtr pScreen;
- DeviceIntPtr pDev; /* device this event _originated_ from */
-} EventRec, *EventPtr;
-
-typedef struct _EventQueue {
- HWEventQueueType head, tail; /* long for SetInputCheck */
- CARD32 lastEventTime; /* to avoid time running backwards */
- int lastMotion; /* device ID if last event motion? */
- EventRec events[QUEUE_SIZE]; /* static allocation for signals */
- mieqHandler handlers[128]; /* custom event handler */
-} EventQueueRec, *EventQueuePtr;
-
-static EventQueueRec miEventQueue;
-
-#ifdef XQUARTZ
-#include <pthread.h>
-static pthread_mutex_t miEventQueueMutex = PTHREAD_MUTEX_INITIALIZER;
-
-extern BOOL serverInitComplete;
-extern pthread_mutex_t serverInitCompleteMutex;
-extern pthread_cond_t serverInitCompleteCond;
-
-static inline void wait_for_server_init(void) {
- /* If the server hasn't finished initializing, wait for it... */
- if(!serverInitComplete) {
- pthread_mutex_lock(&serverInitCompleteMutex);
- while(!serverInitComplete)
- pthread_cond_wait(&serverInitCompleteCond, &serverInitCompleteMutex);
- pthread_mutex_unlock(&serverInitCompleteMutex);
- }
-}
-#endif
-
-Bool
-mieqInit(void)
-{
- int i;
-
- miEventQueue.head = miEventQueue.tail = 0;
- miEventQueue.lastEventTime = GetTimeInMillis ();
- miEventQueue.lastMotion = FALSE;
- for (i = 0; i < 128; i++)
- miEventQueue.handlers[i] = NULL;
- for (i = 0; i < QUEUE_SIZE; i++)
- {
- if (miEventQueue.events[i].events == NULL) {
- EventListPtr evlist = InitEventList(1);
- if (!evlist)
- FatalError("Could not allocate event queue.\n");
- miEventQueue.events[i].events = evlist;
- }
- }
-
- SetInputCheck(&miEventQueue.head, &miEventQueue.tail);
- return TRUE;
-}
-
-void
-mieqFini(void)
-{
- int i;
- for (i = 0; i < QUEUE_SIZE; i++)
- {
- if (miEventQueue.events[i].events != NULL) {
- FreeEventList(miEventQueue.events[i].events, 1);
- miEventQueue.events[i].events = NULL;
- }
- }
-}
-
-/*
- * Must be reentrant with ProcessInputEvents. Assumption: mieqEnqueue
- * will never be interrupted. If this is called from both signal
- * handlers and regular code, make sure the signal is suspended when
- * called from regular code.
- */
-
-void
-mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e)
-{
- unsigned int oldtail = miEventQueue.tail;
- EventListPtr evt;
- int isMotion = 0;
- int evlen;
- Time time;
-
-#ifdef XQUARTZ
- wait_for_server_init();
- pthread_mutex_lock(&miEventQueueMutex);
-#endif
-
- CHECKEVENT(e);
-
- /* avoid merging events from different devices */
- if (e->any.type == ET_Motion)
- isMotion = pDev->id;
-
- if (isMotion && isMotion == miEventQueue.lastMotion &&
- oldtail != miEventQueue.head) {
- oldtail = (oldtail - 1) % QUEUE_SIZE;
- }
- else {
- static int stuck = 0;
- /* Toss events which come in late. Usually this means your server's
- * stuck in an infinite loop somewhere, but SIGIO is still getting
- * handled. */
- if (((oldtail + 1) % QUEUE_SIZE) == miEventQueue.head) {
- if (!stuck) {
- ErrorF("[mi] EQ overflowing. The server is probably stuck "
- "in an infinite loop.\n");
- xorg_backtrace();
- stuck = 1;
- }
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
- return;
- }
- stuck = 0;
- }
-
- evlen = e->any.length;
- evt = miEventQueue.events[oldtail].events;
- if (evt->evlen < evlen)
- {
- evt->evlen = evlen;
- evt->event = realloc(evt->event, evt->evlen);
- if (!evt->event)
- {
- ErrorF("[mi] Running out of memory. Tossing event.\n");
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
- return;
- }
- }
-
- memcpy(evt->event, e, evlen);
-
- time = e->any.time;
- /* Make sure that event times don't go backwards - this
- * is "unnecessary", but very useful. */
- if (time < miEventQueue.lastEventTime &&
- miEventQueue.lastEventTime - time < 10000)
- e->any.time = miEventQueue.lastEventTime;
-
- miEventQueue.lastEventTime = ((InternalEvent*)evt->event)->any.time;
- miEventQueue.events[oldtail].pScreen = pDev ? EnqueueScreen(pDev) : NULL;
- miEventQueue.events[oldtail].pDev = pDev;
-
- miEventQueue.lastMotion = isMotion;
- miEventQueue.tail = (oldtail + 1) % QUEUE_SIZE;
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
-}
-
-void
-mieqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool fromDIX)
-{
-#ifdef XQUARTZ
- pthread_mutex_lock(&miEventQueueMutex);
-#endif
- EnqueueScreen(pDev) = pScreen;
- if (fromDIX)
- DequeueScreen(pDev) = pScreen;
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
-}
-
-void
-mieqSetHandler(int event, mieqHandler handler)
-{
-#ifdef XQUARTZ
- pthread_mutex_lock(&miEventQueueMutex);
-#endif
- if (handler && miEventQueue.handlers[event])
- ErrorF("[mi] mieq: warning: overriding existing handler %p with %p for "
- "event %d\n", miEventQueue.handlers[event], handler, event);
-
- miEventQueue.handlers[event] = handler;
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
-}
-
-/**
- * Change the device id of the given event to the given device's id.
- */
-static void
-ChangeDeviceID(DeviceIntPtr dev, InternalEvent* event)
-{
- switch(event->any.type)
- {
- case ET_Motion:
- case ET_KeyPress:
- case ET_KeyRelease:
- case ET_ButtonPress:
- case ET_ButtonRelease:
- case ET_ProximityIn:
- case ET_ProximityOut:
- case ET_Hierarchy:
- case ET_DeviceChanged:
- event->device_event.deviceid = dev->id;
- break;
-#if XFreeXDGA
- case ET_DGAEvent:
- break;
-#endif
- case ET_RawKeyPress:
- case ET_RawKeyRelease:
- case ET_RawButtonPress:
- case ET_RawButtonRelease:
- case ET_RawMotion:
- event->raw_event.deviceid = dev->id;
- break;
- default:
- ErrorF("[mi] Unknown event type (%d), cannot change id.\n",
- event->any.type);
- }
-}
-
-static void
-FixUpEventForMaster(DeviceIntPtr mdev, DeviceIntPtr sdev,
- InternalEvent* original, InternalEvent *master)
-{
- CHECKEVENT(original);
- CHECKEVENT(master);
- /* Ensure chained button mappings, i.e. that the detail field is the
- * value of the mapped button on the SD, not the physical button */
- if (original->any.type == ET_ButtonPress ||
- original->any.type == ET_ButtonRelease)
- {
- int btn = original->device_event.detail.button;
- if (!sdev->button)
- return; /* Should never happen */
-
- master->device_event.detail.button = sdev->button->map[btn];
- }
-}
-
-/**
- * Copy the given event into master.
- * @param sdev The slave device the original event comes from
- * @param original The event as it came from the EQ
- * @param copy The event after being copied
- * @return The master device or NULL if the device is a floating slave.
- */
-DeviceIntPtr
-CopyGetMasterEvent(DeviceIntPtr sdev,
- InternalEvent* original, InternalEvent *copy)
-{
- DeviceIntPtr mdev;
- int len = original->any.length;
- int type = original->any.type;
-
- CHECKEVENT(original);
-
- /* ET_XQuartz has sdev == NULL */
- if (!sdev || !sdev->u.master)
- return NULL;
-
-#if XFreeXDGA
- if (type == ET_DGAEvent)
- type = original->dga_event.subtype;
-#endif
-
- switch(type)
- {
- case ET_KeyPress:
- case ET_KeyRelease:
- mdev = GetMaster(sdev, MASTER_KEYBOARD);
- break;
- case ET_ButtonPress:
- case ET_ButtonRelease:
- case ET_Motion:
- case ET_ProximityIn:
- case ET_ProximityOut:
- mdev = GetMaster(sdev, MASTER_POINTER);
- break;
- default:
- mdev = sdev->u.master;
- break;
- }
-
- memcpy(copy, original, len);
- ChangeDeviceID(mdev, copy);
- FixUpEventForMaster(mdev, sdev, original, copy);
-
- return mdev;
-}
-
-
-/**
- * Post the given @event through the device hierarchy, as appropriate.
- * Use this function if an event must be posted for a given device during the
- * usual event processing cycle.
- */
-void
-mieqProcessDeviceEvent(DeviceIntPtr dev,
- InternalEvent *event,
- ScreenPtr screen)
-{
- mieqHandler handler;
- int x = 0, y = 0;
- DeviceIntPtr master;
- InternalEvent mevent; /* master event */
-
- CHECKEVENT(event);
-
- /* Custom event handler */
- handler = miEventQueue.handlers[event->any.type];
-
- switch (event->any.type) {
- /* Catch events that include valuator information and check if they
- * are changing the screen */
- case ET_Motion:
- case ET_KeyPress:
- case ET_KeyRelease:
- case ET_ButtonPress:
- case ET_ButtonRelease:
- if (dev && screen && screen != DequeueScreen(dev) && !handler) {
- DequeueScreen(dev) = screen;
- x = event->device_event.root_x;
- y = event->device_event.root_y;
- NewCurrentScreen (dev, DequeueScreen(dev), x, y);
- }
- break;
- default:
- break;
- }
- master = CopyGetMasterEvent(dev, event, &mevent);
-
- if (master)
- master->u.lastSlave = dev;
-
- /* If someone's registered a custom event handler, let them
- * steal it. */
- if (handler)
- {
- int screenNum = dev && DequeueScreen(dev) ? DequeueScreen(dev)->myNum : (screen ? screen->myNum : 0);
- handler(screenNum, event, dev);
- /* Check for the SD's master in case the device got detached
- * during event processing */
- if (master && dev->u.master)
- handler(screenNum, &mevent, master);
- } else
- {
- /* process slave first, then master */
- dev->public.processInputProc(event, dev);
-
- /* Check for the SD's master in case the device got detached
- * during event processing */
- if (master && dev->u.master)
- master->public.processInputProc(&mevent, master);
- }
-}
-
-/* Call this from ProcessInputEvents(). */
-void
-mieqProcessInputEvents(void)
-{
- EventRec *e = NULL;
- int evlen;
- ScreenPtr screen;
- static InternalEvent *event = NULL;
- static size_t event_size = 0;
- DeviceIntPtr dev = NULL,
- master = NULL;
-
-#ifdef XQUARTZ
- pthread_mutex_lock(&miEventQueueMutex);
-#endif
-
- while (miEventQueue.head != miEventQueue.tail) {
- e = &miEventQueue.events[miEventQueue.head];
-
- evlen = e->events->evlen;
- if(evlen > event_size)
- {
- event = realloc(event, evlen);
- event_size = evlen;
- }
-
-
- if (!event)
- FatalError("[mi] No memory left for event processing.\n");
-
- memcpy(event, e->events->event, evlen);
-
-
- dev = e->pDev;
- screen = e->pScreen;
-
- miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;
-
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
-
- master = (dev && !IsMaster(dev) && dev->u.master) ? dev->u.master : NULL;
-
- if (screenIsSaved == SCREEN_SAVER_ON)
- dixSaveScreens (serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
-#ifdef DPMSExtension
- else if (DPMSPowerLevel != DPMSModeOn)
- SetScreenSaverTimer();
-
- if (DPMSPowerLevel != DPMSModeOn)
- DPMSSet(serverClient, DPMSModeOn);
-#endif
-
- mieqProcessDeviceEvent(dev, event, screen);
-
- /* Update the sprite now. Next event may be from different device. */
- if (event->any.type == ET_Motion && master)
- miPointerUpdateSprite(dev);
-
-#ifdef XQUARTZ
- pthread_mutex_lock(&miEventQueueMutex);
-#endif
- }
-#ifdef XQUARTZ
- pthread_mutex_unlock(&miEventQueueMutex);
-#endif
-}
-
+/* + * +Copyright 1990, 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. + * + * Author: Keith Packard, MIT X Consortium + */ + +/* + * mieq.c + * + * Machine independent event queue + * + */ + +#if HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +# include <X11/X.h> +# include <X11/Xmd.h> +# include <X11/Xproto.h> +# include "misc.h" +# include "windowstr.h" +# include "pixmapstr.h" +# include "inputstr.h" +# include "mi.h" +# include "mipointer.h" +# include "scrnintstr.h" +# include <X11/extensions/XI.h> +# include <X11/extensions/XIproto.h> +# include <X11/extensions/geproto.h> +# include "extinit.h" +# include "exglobals.h" +# include "eventstr.h" + +#ifdef DPMSExtension +# include "dpmsproc.h" +# include <X11/extensions/dpmsconst.h> +#endif + +#define QUEUE_SIZE 512 + +#define EnqueueScreen(dev) dev->spriteInfo->sprite->pEnqueueScreen +#define DequeueScreen(dev) dev->spriteInfo->sprite->pDequeueScreen + +typedef struct _Event { + EventListPtr events; + ScreenPtr pScreen; + DeviceIntPtr pDev; /* device this event _originated_ from */ +} EventRec, *EventPtr; + +typedef struct _EventQueue { + HWEventQueueType head, tail; /* long for SetInputCheck */ + CARD32 lastEventTime; /* to avoid time running backwards */ + int lastMotion; /* device ID if last event motion? */ + EventRec events[QUEUE_SIZE]; /* static allocation for signals */ + mieqHandler handlers[128]; /* custom event handler */ +} EventQueueRec, *EventQueuePtr; + +static EventQueueRec miEventQueue; + +#ifdef XQUARTZ +#include <pthread.h> +static pthread_mutex_t miEventQueueMutex = PTHREAD_MUTEX_INITIALIZER; + +extern BOOL serverInitComplete; +extern pthread_mutex_t serverInitCompleteMutex; +extern pthread_cond_t serverInitCompleteCond; + +static inline void wait_for_server_init(void) { + /* If the server hasn't finished initializing, wait for it... */ + if(!serverInitComplete) { + pthread_mutex_lock(&serverInitCompleteMutex); + while(!serverInitComplete) + pthread_cond_wait(&serverInitCompleteCond, &serverInitCompleteMutex); + pthread_mutex_unlock(&serverInitCompleteMutex); + } +} +#endif + +Bool +mieqInit(void) +{ + int i; + + miEventQueue.head = miEventQueue.tail = 0; + miEventQueue.lastEventTime = GetTimeInMillis (); + miEventQueue.lastMotion = FALSE; + for (i = 0; i < 128; i++) + miEventQueue.handlers[i] = NULL; + for (i = 0; i < QUEUE_SIZE; i++) + { + if (miEventQueue.events[i].events == NULL) { + EventListPtr evlist = InitEventList(1); + if (!evlist) + FatalError("Could not allocate event queue.\n"); + miEventQueue.events[i].events = evlist; + } + } + + SetInputCheck(&miEventQueue.head, &miEventQueue.tail); + return TRUE; +} + +void +mieqFini(void) +{ + int i; + for (i = 0; i < QUEUE_SIZE; i++) + { + if (miEventQueue.events[i].events != NULL) { + FreeEventList(miEventQueue.events[i].events, 1); + miEventQueue.events[i].events = NULL; + } + } +} + +/* + * Must be reentrant with ProcessInputEvents. Assumption: mieqEnqueue + * will never be interrupted. If this is called from both signal + * handlers and regular code, make sure the signal is suspended when + * called from regular code. + */ + +void +mieqEnqueue(DeviceIntPtr pDev, InternalEvent *e) +{ + unsigned int oldtail = miEventQueue.tail; + EventListPtr evt; + int isMotion = 0; + int evlen; + Time time; + +#ifdef XQUARTZ + wait_for_server_init(); + pthread_mutex_lock(&miEventQueueMutex); +#endif + + CHECKEVENT(e); + + /* avoid merging events from different devices */ + if (e->any.type == ET_Motion) + isMotion = pDev->id; + + if (isMotion && isMotion == miEventQueue.lastMotion && + oldtail != miEventQueue.head) { + oldtail = (oldtail - 1) % QUEUE_SIZE; + } + else { + static int stuck = 0; + /* Toss events which come in late. Usually this means your server's + * stuck in an infinite loop somewhere, but SIGIO is still getting + * handled. */ + if (((oldtail + 1) % QUEUE_SIZE) == miEventQueue.head) { + if (!stuck) { + ErrorF("[mi] EQ overflowing. The server is probably stuck " + "in an infinite loop.\n"); + xorg_backtrace(); + stuck = 1; + } +#ifdef XQUARTZ + pthread_mutex_unlock(&miEventQueueMutex); +#endif + return; + } + stuck = 0; + } + + evlen = e->any.length; + evt = miEventQueue.events[oldtail].events; + if (evt->evlen < evlen) + { + evt->evlen = evlen; + evt->event = realloc(evt->event, evt->evlen); + if (!evt->event) + { + ErrorF("[mi] Running out of memory. Tossing event.\n"); +#ifdef XQUARTZ + pthread_mutex_unlock(&miEventQueueMutex); +#endif + return; + } + } + + memcpy(evt->event, e, evlen); + + time = e->any.time; + /* Make sure that event times don't go backwards - this + * is "unnecessary", but very useful. */ + if (time < miEventQueue.lastEventTime && + miEventQueue.lastEventTime - time < 10000) + e->any.time = miEventQueue.lastEventTime; + + miEventQueue.lastEventTime = ((InternalEvent*)evt->event)->any.time; + miEventQueue.events[oldtail].pScreen = pDev ? EnqueueScreen(pDev) : NULL; + miEventQueue.events[oldtail].pDev = pDev; + + miEventQueue.lastMotion = isMotion; + miEventQueue.tail = (oldtail + 1) % QUEUE_SIZE; +#ifdef XQUARTZ + pthread_mutex_unlock(&miEventQueueMutex); +#endif +} + +void +mieqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool fromDIX) +{ +#ifdef XQUARTZ + pthread_mutex_lock(&miEventQueueMutex); +#endif + EnqueueScreen(pDev) = pScreen; + if (fromDIX) + DequeueScreen(pDev) = pScreen; +#ifdef XQUARTZ + pthread_mutex_unlock(&miEventQueueMutex); +#endif +} + +void +mieqSetHandler(int event, mieqHandler handler) +{ +#ifdef XQUARTZ + pthread_mutex_lock(&miEventQueueMutex); +#endif + if (handler && miEventQueue.handlers[event]) + ErrorF("[mi] mieq: warning: overriding existing handler %p with %p for " + "event %d\n", miEventQueue.handlers[event], handler, event); + + miEventQueue.handlers[event] = handler; +#ifdef XQUARTZ + pthread_mutex_unlock(&miEventQueueMutex); +#endif +} + +/** + * Change the device id of the given event to the given device's id. + */ +static void +ChangeDeviceID(DeviceIntPtr dev, InternalEvent* event) +{ + switch(event->any.type) + { + case ET_Motion: + case ET_KeyPress: + case ET_KeyRelease: + case ET_ButtonPress: + case ET_ButtonRelease: + case ET_ProximityIn: + case ET_ProximityOut: + case ET_Hierarchy: + case ET_DeviceChanged: + event->device_event.deviceid = dev->id; + break; +#if XFreeXDGA + case ET_DGAEvent: + break; +#endif + case ET_RawKeyPress: + case ET_RawKeyRelease: + case ET_RawButtonPress: + case ET_RawButtonRelease: + case ET_RawMotion: + event->raw_event.deviceid = dev->id; + break; + default: + ErrorF("[mi] Unknown event type (%d), cannot change id.\n", + event->any.type); + } +} + +static void +FixUpEventForMaster(DeviceIntPtr mdev, DeviceIntPtr sdev, + InternalEvent* original, InternalEvent *master) +{ + CHECKEVENT(original); + CHECKEVENT(master); + /* Ensure chained button mappings, i.e. that the detail field is the + * value of the mapped button on the SD, not the physical button */ + if (original->any.type == ET_ButtonPress || + original->any.type == ET_ButtonRelease) + { + int btn = original->device_event.detail.button; + if (!sdev->button) + return; /* Should never happen */ + + master->device_event.detail.button = sdev->button->map[btn]; + } +} + +/** + * Copy the given event into master. + * @param sdev The slave device the original event comes from + * @param original The event as it came from the EQ + * @param copy The event after being copied + * @return The master device or NULL if the device is a floating slave. + */ +DeviceIntPtr +CopyGetMasterEvent(DeviceIntPtr sdev, + InternalEvent* original, InternalEvent *copy) +{ + DeviceIntPtr mdev; + int len = original->any.length; + int type = original->any.type; + int mtype; /* which master type? */ + + CHECKEVENT(original); + + /* ET_XQuartz has sdev == NULL */ + if (!sdev || IsMaster(sdev) || IsFloating(sdev)) + return NULL; + +#if XFreeXDGA + if (type == ET_DGAEvent) + type = original->dga_event.subtype; +#endif + + switch(type) + { + case ET_KeyPress: + case ET_KeyRelease: + mtype = MASTER_KEYBOARD; + break; + case ET_ButtonPress: + case ET_ButtonRelease: + case ET_Motion: + case ET_ProximityIn: + case ET_ProximityOut: + mtype = MASTER_POINTER; + break; + default: + mtype = MASTER_ATTACHED; + break; + } + + mdev = GetMaster(sdev, mtype); + memcpy(copy, original, len); + ChangeDeviceID(mdev, copy); + FixUpEventForMaster(mdev, sdev, original, copy); + + return mdev; +} + + +/** + * Post the given @event through the device hierarchy, as appropriate. + * Use this function if an event must be posted for a given device during the + * usual event processing cycle. + */ +void +mieqProcessDeviceEvent(DeviceIntPtr dev, + InternalEvent *event, + ScreenPtr screen) +{ + mieqHandler handler; + int x = 0, y = 0; + DeviceIntPtr master; + InternalEvent mevent; /* master event */ + + CHECKEVENT(event); + + /* Custom event handler */ + handler = miEventQueue.handlers[event->any.type]; + + switch (event->any.type) { + /* Catch events that include valuator information and check if they + * are changing the screen */ + case ET_Motion: + case ET_KeyPress: + case ET_KeyRelease: + case ET_ButtonPress: + case ET_ButtonRelease: + if (dev && screen && screen != DequeueScreen(dev) && !handler) { + DequeueScreen(dev) = screen; + x = event->device_event.root_x; + y = event->device_event.root_y; + NewCurrentScreen (dev, DequeueScreen(dev), x, y); + } + break; + default: + break; + } + master = CopyGetMasterEvent(dev, event, &mevent); + + if (master) + master->lastSlave = dev; + + /* If someone's registered a custom event handler, let them + * steal it. */ + if (handler) + { + int screenNum = dev && DequeueScreen(dev) ? DequeueScreen(dev)->myNum : (screen ? screen->myNum : 0); + handler(screenNum, event, dev); + /* Check for the SD's master in case the device got detached + * during event processing */ + if (master && !IsFloating(dev)) + handler(screenNum, &mevent, master); + } else + { + /* process slave first, then master */ + dev->public.processInputProc(event, dev); + + /* Check for the SD's master in case the device got detached + * during event processing */ + if (master && !IsFloating(dev)) + master->public.processInputProc(&mevent, master); + } +} + +/* Call this from ProcessInputEvents(). */ +void +mieqProcessInputEvents(void) +{ + EventRec *e = NULL; + int evlen; + ScreenPtr screen; + static InternalEvent *event = NULL; + static size_t event_size = 0; + DeviceIntPtr dev = NULL, + master = NULL; + +#ifdef XQUARTZ + pthread_mutex_lock(&miEventQueueMutex); +#endif + + while (miEventQueue.head != miEventQueue.tail) { + e = &miEventQueue.events[miEventQueue.head]; + + evlen = e->events->evlen; + if(evlen > event_size) + { + event = realloc(event, evlen); + event_size = evlen; + } + + + if (!event) + FatalError("[mi] No memory left for event processing.\n"); + + memcpy(event, e->events->event, evlen); + + + dev = e->pDev; + screen = e->pScreen; + + miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE; + +#ifdef XQUARTZ + pthread_mutex_unlock(&miEventQueueMutex); +#endif + + master = (dev) ? GetMaster(dev, MASTER_ATTACHED) : NULL; + + if (screenIsSaved == SCREEN_SAVER_ON) + dixSaveScreens (serverClient, SCREEN_SAVER_OFF, ScreenSaverReset); +#ifdef DPMSExtension + else if (DPMSPowerLevel != DPMSModeOn) + SetScreenSaverTimer(); + + if (DPMSPowerLevel != DPMSModeOn) + DPMSSet(serverClient, DPMSModeOn); +#endif + + mieqProcessDeviceEvent(dev, event, screen); + + /* Update the sprite now. Next event may be from different device. */ + if (event->any.type == ET_Motion && master) + miPointerUpdateSprite(dev); + +#ifdef XQUARTZ + pthread_mutex_lock(&miEventQueueMutex); +#endif + } +#ifdef XQUARTZ + pthread_mutex_unlock(&miEventQueueMutex); +#endif +} + diff --git a/xorg-server/mi/mipointer.c b/xorg-server/mi/mipointer.c index f9ca9a70b..209ea06be 100644 --- a/xorg-server/mi/mipointer.c +++ b/xorg-server/mi/mipointer.c @@ -1,590 +1,688 @@ -/*
-
-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 <X11/Xmd.h>
-# include <X11/Xproto.h>
-# include "misc.h"
-# include "windowstr.h"
-# include "pixmapstr.h"
-# include "mi.h"
-# include "scrnintstr.h"
-# include "mipointrst.h"
-# include "cursorstr.h"
-# include "dixstruct.h"
-# include "inputstr.h"
-# include "inpututils.h"
-
-DevPrivateKeyRec miPointerScreenKeyRec;
-
-#define GetScreenPrivate(s) ((miPointerScreenPtr) \
- dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey))
-#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s)
-
-DevPrivateKeyRec miPointerPrivKeyRec;
-
-#define MIPOINTER(dev) \
- ((!IsMaster(dev) && !dev->u.master) ? \
- (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
- (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey))
-
-static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor);
-static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor);
-static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor);
-static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- BoxPtr pBox);
-static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor, BoxPtr pHotBox,
- BoxPtr pTopLeftBox);
-static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
- int x, int y,
- Bool generateEvent);
-static Bool miPointerCloseScreen(int index, ScreenPtr pScreen);
-static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen,
- int x, int y);
-static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
-static void miPointerDeviceCleanup(DeviceIntPtr pDev,
- ScreenPtr pScreen);
-static void miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y);
-
-static EventList* events; /* for WarpPointer MotionNotifies */
-
-Bool
-miPointerInitialize (ScreenPtr pScreen,
- miPointerSpriteFuncPtr spriteFuncs,
- miPointerScreenFuncPtr screenFuncs,
- Bool waitForUpdate)
-{
- miPointerScreenPtr pScreenPriv;
-
- if (!dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0))
- return FALSE;
-
- if (!dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0))
- return FALSE;
-
- pScreenPriv = malloc(sizeof (miPointerScreenRec));
- if (!pScreenPriv)
- return FALSE;
- pScreenPriv->spriteFuncs = spriteFuncs;
- pScreenPriv->screenFuncs = screenFuncs;
- /*
- * check for uninitialized methods
- */
- if (!screenFuncs->EnqueueEvent)
- screenFuncs->EnqueueEvent = mieqEnqueue;
- if (!screenFuncs->NewEventScreen)
- screenFuncs->NewEventScreen = mieqSwitchScreen;
- pScreenPriv->waitForUpdate = waitForUpdate;
- pScreenPriv->showTransparent = FALSE;
- pScreenPriv->CloseScreen = pScreen->CloseScreen;
- pScreen->CloseScreen = miPointerCloseScreen;
- dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv);
- /*
- * set up screen cursor method table
- */
- pScreen->ConstrainCursor = miPointerConstrainCursor;
- pScreen->CursorLimits = miPointerCursorLimits;
- pScreen->DisplayCursor = miPointerDisplayCursor;
- pScreen->RealizeCursor = miPointerRealizeCursor;
- pScreen->UnrealizeCursor = miPointerUnrealizeCursor;
- pScreen->SetCursorPosition = miPointerSetCursorPosition;
- pScreen->RecolorCursor = miRecolorCursor;
- pScreen->DeviceCursorInitialize = miPointerDeviceInitialize;
- pScreen->DeviceCursorCleanup = miPointerDeviceCleanup;
-
- events = NULL;
- return TRUE;
-}
-
-static Bool
-miPointerCloseScreen (int index, ScreenPtr pScreen)
-{
-#if 0
- miPointerPtr pPointer;
- DeviceIntPtr pDev;
-#endif
-
- SetupScreen(pScreen);
-
-#if 0
- for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pPointer = MIPOINTER(pDev);
-
- if (pScreen == pPointer->pScreen)
- pPointer->pScreen = 0;
- if (pScreen == pPointer->pSpriteScreen)
- pPointer->pSpriteScreen = 0;
- }
- }
-
- if (MIPOINTER(inputInfo.pointer)->pScreen == pScreen)
- MIPOINTER(inputInfo.pointer)->pScreen = 0;
- if (MIPOINTER(inputInfo.pointer)->pSpriteScreen == pScreen)
- MIPOINTER(inputInfo.pointer)->pSpriteScreen = 0;
-#endif
-
- pScreen->CloseScreen = pScreenPriv->CloseScreen;
- free((pointer) pScreenPriv);
- FreeEventList(events, GetMaximumEventsNum());
- events = NULL;
- return (*pScreen->CloseScreen) (index, pScreen);
-}
-
-/*
- * DIX/DDX interface routines
- */
-
-static Bool
-miPointerRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
-{
- SetupScreen(pScreen);
- return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor);
-}
-
-static Bool
-miPointerUnrealizeCursor (DeviceIntPtr pDev,
- ScreenPtr pScreen,
- CursorPtr pCursor)
-{
- SetupScreen(pScreen);
- return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor);
-}
-
-static Bool
-miPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
-{
- miPointerPtr pPointer;
-
- /* return for keyboards */
- if ((IsMaster(pDev) && !DevHasCursor(pDev)) ||
- (!IsMaster(pDev) && pDev->u.master && !DevHasCursor(pDev->u.master)))
- return FALSE;
-
- pPointer = MIPOINTER(pDev);
-
- pPointer->pCursor = pCursor;
- pPointer->pScreen = pScreen;
- miPointerUpdateSprite(pDev);
- return TRUE;
-}
-
-static void
-miPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox)
-{
- miPointerPtr pPointer;
-
- pPointer = MIPOINTER(pDev);
-
- pPointer->limits = *pBox;
- pPointer->confined = PointerConfinedToScreen(pDev);
-}
-
-/*ARGSUSED*/
-static void
-miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
- BoxPtr pHotBox, BoxPtr pTopLeftBox)
-{
- *pTopLeftBox = *pHotBox;
-}
-
-static Bool GenerateEvent;
-
-static Bool
-miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
- int x, int y, Bool generateEvent)
-{
- SetupScreen (pScreen);
-
- GenerateEvent = generateEvent;
- /* device dependent - must pend signal and call miPointerWarpCursor */
- (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y);
- if (!generateEvent)
- miPointerUpdateSprite(pDev);
- return TRUE;
-}
-
-/* Set up sprite information for the device.
- This function will be called once for each device after it is initialized
- in the DIX.
- */
-static Bool
-miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- miPointerPtr pPointer;
- SetupScreen (pScreen);
-
- pPointer = malloc(sizeof(miPointerRec));
- if (!pPointer)
- return FALSE;
-
- pPointer->pScreen = NULL;
- pPointer->pSpriteScreen = NULL;
- pPointer->pCursor = NULL;
- pPointer->pSpriteCursor = NULL;
- pPointer->limits.x1 = 0;
- pPointer->limits.x2 = 32767;
- pPointer->limits.y1 = 0;
- pPointer->limits.y2 = 32767;
- pPointer->confined = FALSE;
- pPointer->x = 0;
- pPointer->y = 0;
-
- if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen)))
- {
- free(pPointer);
- return FALSE;
- }
-
- dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer);
- return TRUE;
-}
-
-/* Clean up after device.
- This function will be called once before the device is freed in the DIX
- */
-static void
-miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- SetupScreen(pScreen);
-
- if (!IsMaster(pDev) && pDev->u.master)
- return;
-
- (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
- free(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey));
- dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL);
-}
-
-
-/* Once signals are ignored, the WarpCursor function can call this */
-
-void
-miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
-{
- miPointerPtr pPointer;
- BOOL changedScreen = FALSE;
-
- SetupScreen (pScreen);
- pPointer = MIPOINTER(pDev);
-
- if (pPointer->pScreen != pScreen)
- {
- (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE);
- changedScreen = TRUE;
- }
-
- if (GenerateEvent)
- miPointerMove (pDev, pScreen, x, y);
- else
- miPointerMoveNoEvent(pDev, pScreen, x, y);
-
- /* Don't call USFS if we use Xinerama, otherwise the root window is
- * updated to the second screen, and we never receive any events.
- * (FDO bug #18668) */
- if (changedScreen
-#ifdef PANORAMIX
- && noPanoramiXExtension
-#endif
- )
- UpdateSpriteForScreen (pDev, pScreen) ;
-}
-
-/*
- * Pointer/CursorDisplay interface routines
- */
-
-/*
- * miPointerUpdateSprite
- *
- * Syncronize the sprite with the cursor - called from ProcessInputEvents
- */
-
-void
-miPointerUpdateSprite (DeviceIntPtr pDev)
-{
- ScreenPtr pScreen;
- miPointerScreenPtr pScreenPriv;
- CursorPtr pCursor;
- int x, y, devx, devy;
- miPointerPtr pPointer;
-
- if (!pDev || !pDev->coreEvents)
- return;
-
- pPointer = MIPOINTER(pDev);
-
- if (!pPointer)
- return;
-
- pScreen = pPointer->pScreen;
- if (!pScreen)
- return;
-
- x = pPointer->x;
- y = pPointer->y;
- devx = pPointer->devx;
- devy = pPointer->devy;
-
- pScreenPriv = GetScreenPrivate (pScreen);
- /*
- * if the cursor has switched screens, disable the sprite
- * on the old screen
- */
- if (pScreen != pPointer->pSpriteScreen)
- {
- if (pPointer->pSpriteScreen)
- {
- miPointerScreenPtr pOldPriv;
-
- pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen);
- if (pPointer->pCursor)
- {
- (*pOldPriv->spriteFuncs->SetCursor)
- (pDev, pPointer->pSpriteScreen, NullCursor, 0, 0);
- }
- (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE);
- }
- (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
- (*pScreenPriv->spriteFuncs->SetCursor)
- (pDev, pScreen, pPointer->pCursor, x, y);
- pPointer->devx = x;
- pPointer->devy = y;
- pPointer->pSpriteCursor = pPointer->pCursor;
- pPointer->pSpriteScreen = pScreen;
- }
- /*
- * if the cursor has changed, display the new one
- */
- else if (pPointer->pCursor != pPointer->pSpriteCursor)
- {
- pCursor = pPointer->pCursor;
- if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent))
- pCursor = NullCursor;
- (*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y);
-
- pPointer->devx = x;
- pPointer->devy = y;
- pPointer->pSpriteCursor = pPointer->pCursor;
- }
- else if (x != devx || y != devy)
- {
- pPointer->devx = x;
- pPointer->devy = y;
- if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
- (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
- }
-}
-
-void
-miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
-{
- miPointerScreenPtr pScreenPriv;
- ScreenPtr pScreen;
- miPointerPtr pPointer;
-
- pPointer = MIPOINTER(pDev);
-
- pScreen = screenInfo.screens[screen_no];
- pScreenPriv = GetScreenPrivate (pScreen);
- (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE);
- NewCurrentScreen (pDev, pScreen, x, y);
-
- pPointer->limits.x2 = pScreen->width;
- pPointer->limits.y2 = pScreen->height;
-}
-
-ScreenPtr
-miPointerCurrentScreen (void)
-{
- return miPointerGetScreen(inputInfo.pointer);
-}
-
-ScreenPtr
-miPointerGetScreen(DeviceIntPtr pDev)
-{
- miPointerPtr pPointer = MIPOINTER(pDev);
- return (pPointer) ? pPointer->pScreen : NULL;
-}
-
-/* Controls whether the cursor image should be updated immediately when
- moved (FALSE) or if something else will be responsible for updating
- it later (TRUE). Returns current setting.
- Caller is responsible for calling OsBlockSignal first.
-*/
-Bool
-miPointerSetWaitForUpdate(ScreenPtr pScreen, Bool wait)
-{
- SetupScreen(pScreen);
- Bool prevWait = pScreenPriv->waitForUpdate;
-
- pScreenPriv->waitForUpdate = wait;
- return prevWait;
-}
-
-
-/* Move the pointer on the current screen, and update the sprite. */
-static void
-miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen,
- int x, int y)
-{
- miPointerPtr pPointer;
- SetupScreen(pScreen);
-
- pPointer = MIPOINTER(pDev);
-
- /* Hack: We mustn't call into ->MoveCursor for anything but the
- * VCP, as this may cause a non-HW rendered cursor to be rendered during
- * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT.
- */
- if ((pDev == inputInfo.pointer || (!IsMaster(pDev) && pDev->u.master == inputInfo.pointer))
- && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
- {
- pPointer->devx = x;
- pPointer->devy = y;
- if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
- (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
- }
-
- pPointer->x = x;
- pPointer->y = y;
- pPointer->pScreen = pScreen;
-}
-
-void
-miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
-{
- miPointerScreenPtr pScreenPriv;
- ScreenPtr pScreen;
- ScreenPtr newScreen;
-
- miPointerPtr pPointer;
-
- if (!pDev || !pDev->coreEvents)
- return;
-
- pPointer = MIPOINTER(pDev);
- pScreen = pPointer->pScreen;
- if (!pScreen)
- return; /* called before ready */
-
- if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
- {
- pScreenPriv = GetScreenPrivate (pScreen);
- if (!pPointer->confined)
- {
- newScreen = pScreen;
- (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y);
- if (newScreen != pScreen)
- {
- pScreen = newScreen;
- (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen,
- FALSE);
- pScreenPriv = GetScreenPrivate (pScreen);
- /* Smash the confine to the new screen */
- pPointer->limits.x2 = pScreen->width;
- pPointer->limits.y2 = pScreen->height;
- }
- }
- }
- /* Constrain the sprite to the current limits. */
- if (*x < pPointer->limits.x1)
- *x = pPointer->limits.x1;
- if (*x >= pPointer->limits.x2)
- *x = pPointer->limits.x2 - 1;
- if (*y < pPointer->limits.y1)
- *y = pPointer->limits.y1;
- if (*y >= pPointer->limits.y2)
- *y = pPointer->limits.y2 - 1;
-
- if (pPointer->x == *x && pPointer->y == *y &&
- pPointer->pScreen == pScreen)
- return;
-
- miPointerMoveNoEvent(pDev, pScreen, *x, *y);
-}
-
-void
-miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
-{
- *x = MIPOINTER(pDev)->x;
- *y = MIPOINTER(pDev)->y;
-}
-
-#ifdef XQUARTZ
-#include <pthread.h>
-void darwinEvents_lock(void);
-void darwinEvents_unlock(void);
-#endif
-
-void
-miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
-{
- int i, nevents;
- int valuators[2];
- ValuatorMask mask;
-
- miPointerMoveNoEvent(pDev, pScreen, x, y);
-
- /* generate motion notify */
- valuators[0] = x;
- valuators[1] = y;
-
- if (!events)
- {
- events = InitEventList(GetMaximumEventsNum());
-
- if (!events)
- {
- FatalError("Could not allocate event store.\n");
- return;
- }
- }
-
- valuator_mask_set_range(&mask, 0, 2, valuators);
- nevents = GetPointerEvents(events, pDev, MotionNotify, 0,
- POINTER_SCREEN | POINTER_ABSOLUTE, &mask);
-
- OsBlockSignals();
-#ifdef XQUARTZ
- darwinEvents_lock();
-#endif
- for (i = 0; i < nevents; i++)
- mieqEnqueue(pDev, (InternalEvent*)events[i].event);
-#ifdef XQUARTZ
- darwinEvents_unlock();
-#endif
- OsReleaseSignals();
-}
+/* + +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. +*/ + +/** + * @file + * This file contains functions to move the pointer on the screen and/or + * restrict its movement. These functions are divided into two sets: + * Screen-specific functions that are used as function pointers from other + * parts of the server (and end up heavily wrapped by e.g. animcur and + * xfixes): + * miPointerConstrainCursor + * miPointerCursorLimits + * miPointerDisplayCursor + * miPointerRealizeCursor + * miPointerUnrealizeCursor + * miPointerSetCursorPosition + * miRecolorCursor + * miPointerDeviceInitialize + * miPointerDeviceCleanup + * If wrapped, these are the last element in the wrapping chain. They may + * call into sprite-specific code through further function pointers though. + * + * The second type of functions are those that are directly called by the + * DIX, DDX and some drivers. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +# include <X11/X.h> +# include <X11/Xmd.h> +# include <X11/Xproto.h> +# include "misc.h" +# include "windowstr.h" +# include "pixmapstr.h" +# include "mi.h" +# include "scrnintstr.h" +# include "mipointrst.h" +# include "cursorstr.h" +# include "dixstruct.h" +# include "inputstr.h" +# include "inpututils.h" + +DevPrivateKeyRec miPointerScreenKeyRec; + +#define GetScreenPrivate(s) ((miPointerScreenPtr) \ + dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey)) +#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s) + +DevPrivateKeyRec miPointerPrivKeyRec; + +#define MIPOINTER(dev) \ + (IsFloating(dev) ? \ + (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \ + (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey)) + +static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + BoxPtr pBox); +static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, BoxPtr pHotBox, + BoxPtr pTopLeftBox); +static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, + Bool generateEvent); +static Bool miPointerCloseScreen(int index, ScreenPtr pScreen); +static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y); +static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen); +static void miPointerDeviceCleanup(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); + +static EventList* events; /* for WarpPointer MotionNotifies */ + +Bool +miPointerInitialize (ScreenPtr pScreen, + miPointerSpriteFuncPtr spriteFuncs, + miPointerScreenFuncPtr screenFuncs, + Bool waitForUpdate) +{ + miPointerScreenPtr pScreenPriv; + + if (!dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + if (!dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0)) + return FALSE; + + pScreenPriv = malloc(sizeof (miPointerScreenRec)); + if (!pScreenPriv) + return FALSE; + pScreenPriv->spriteFuncs = spriteFuncs; + pScreenPriv->screenFuncs = screenFuncs; + /* + * check for uninitialized methods + */ + if (!screenFuncs->EnqueueEvent) + screenFuncs->EnqueueEvent = mieqEnqueue; + if (!screenFuncs->NewEventScreen) + screenFuncs->NewEventScreen = mieqSwitchScreen; + pScreenPriv->waitForUpdate = waitForUpdate; + pScreenPriv->showTransparent = FALSE; + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = miPointerCloseScreen; + dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv); + /* + * set up screen cursor method table + */ + pScreen->ConstrainCursor = miPointerConstrainCursor; + pScreen->CursorLimits = miPointerCursorLimits; + pScreen->DisplayCursor = miPointerDisplayCursor; + pScreen->RealizeCursor = miPointerRealizeCursor; + pScreen->UnrealizeCursor = miPointerUnrealizeCursor; + pScreen->SetCursorPosition = miPointerSetCursorPosition; + pScreen->RecolorCursor = miRecolorCursor; + pScreen->DeviceCursorInitialize = miPointerDeviceInitialize; + pScreen->DeviceCursorCleanup = miPointerDeviceCleanup; + + events = NULL; + return TRUE; +} + +/** + * Destroy screen-specific information. + * + * @param index Screen index of the screen in screenInfo.screens[] + * @param pScreen The actual screen pointer + */ +static Bool +miPointerCloseScreen (int index, ScreenPtr pScreen) +{ + SetupScreen(pScreen); + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + free((pointer) pScreenPriv); + FreeEventList(events, GetMaximumEventsNum()); + events = NULL; + return (*pScreen->CloseScreen) (index, pScreen); +} + +/* + * DIX/DDX interface routines + */ + +static Bool +miPointerRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + SetupScreen(pScreen); + return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor); +} + +static Bool +miPointerUnrealizeCursor (DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor) +{ + SetupScreen(pScreen); + return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor); +} + +static Bool +miPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + miPointerPtr pPointer; + + /* return for keyboards */ + if (!IsPointerDevice(pDev)) + return FALSE; + + pPointer = MIPOINTER(pDev); + + pPointer->pCursor = pCursor; + pPointer->pScreen = pScreen; + miPointerUpdateSprite(pDev); + return TRUE; +} + +/** + * Set up the constraints for the given device. This function does not + * actually constrain the cursor but merely copies the given box to the + * internal constraint storage. + * + * @param pDev The device to constrain to the box + * @param pBox The rectangle to constrain the cursor to + * @param pScreen Used for copying screen confinement + */ +static void +miPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox) +{ + miPointerPtr pPointer; + + pPointer = MIPOINTER(pDev); + + pPointer->limits = *pBox; + pPointer->confined = PointerConfinedToScreen(pDev); +} + +/** + * Should calculate the box for the given cursor, based on screen and the + * confinement given. But we assume that whatever box is passed in is valid + * anyway. + * + * @param pDev The device to calculate the cursor limits for + * @param pScreen The screen the confinement happens on + * @param pCursor The screen the confinement happens on + * @param pHotBox The confinement box for the cursor + * @param[out] pTopLeftBox The new confinement box, always *pHotBox. + */ +static void +miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, + BoxPtr pHotBox, BoxPtr pTopLeftBox) +{ + *pTopLeftBox = *pHotBox; +} + +/** + * Set the device's cursor position to the x/y position on the given screen. + * Generates and event if required. + * + * This function is called from: + * - sprite init code to place onto initial position + * - the various WarpPointer implementations (core, XI, Xinerama, dmx,…) + * - during the cursor update path in CheckMotion + * - in the Xinerama part of NewCurrentScreen + * - when a RandR/RandR1.2 mode was applied (it may have moved the pointer, so + * it's set back to the original pos) + * + * @param pDev The device to move + * @param pScreen The screen the device is on + * @param x The x coordinate in per-screen coordinates + * @param y The y coordinate in per-screen coordinates + * @param generateEvent True if the pointer movement should generate an + * event. + * + * @return TRUE in all cases + */ +static Bool +miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, Bool generateEvent) +{ + SetupScreen (pScreen); + miPointerPtr pPointer = MIPOINTER(pDev); + + pPointer->generateEvent = generateEvent; + + /* device dependent - must pend signal and call miPointerWarpCursor */ + (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y); + if (!generateEvent) + miPointerUpdateSprite(pDev); + return TRUE; +} + +/** + * Set up sprite information for the device. + * This function will be called once for each device after it is initialized + * in the DIX. + * + * @param pDev The newly created device + * @param pScreen The initial sprite scree. + */ +static Bool +miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miPointerPtr pPointer; + SetupScreen (pScreen); + + pPointer = malloc(sizeof(miPointerRec)); + if (!pPointer) + return FALSE; + + pPointer->pScreen = NULL; + pPointer->pSpriteScreen = NULL; + pPointer->pCursor = NULL; + pPointer->pSpriteCursor = NULL; + pPointer->limits.x1 = 0; + pPointer->limits.x2 = 32767; + pPointer->limits.y1 = 0; + pPointer->limits.y2 = 32767; + pPointer->confined = FALSE; + pPointer->x = 0; + pPointer->y = 0; + pPointer->generateEvent = FALSE; + + if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen))) + { + free(pPointer); + return FALSE; + } + + dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer); + return TRUE; +} + +/** + * Clean up after device. + * This function will be called once before the device is freed in the DIX + * + * @param pDev The device to be removed from the server + * @param pScreen Current screen of the device + */ +static void +miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + SetupScreen(pScreen); + + if (!IsMaster(pDev) && !IsFloating(pDev)) + return; + + (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen); + free(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey)); + dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL); +} + + +/** + * Warp the pointer to the given position on the given screen. May generate + * an event, depending on whether we're coming from miPointerSetPosition. + * + * Once signals are ignored, the WarpCursor function can call this + * + * @param pDev The device to warp + * @param pScreen Screen to warp on + * @param x The x coordinate in per-screen coordinates + * @param y The y coordinate in per-screen coordinates + */ + +void +miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + miPointerPtr pPointer; + BOOL changedScreen = FALSE; + + SetupScreen (pScreen); + pPointer = MIPOINTER(pDev); + + if (pPointer->pScreen != pScreen) + { + (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE); + changedScreen = TRUE; + } + + if (pPointer->generateEvent) + miPointerMove (pDev, pScreen, x, y); + else + miPointerMoveNoEvent(pDev, pScreen, x, y); + + /* Don't call USFS if we use Xinerama, otherwise the root window is + * updated to the second screen, and we never receive any events. + * (FDO bug #18668) */ + if (changedScreen +#ifdef PANORAMIX + && noPanoramiXExtension +#endif + ) + UpdateSpriteForScreen (pDev, pScreen) ; +} + +/** + * Syncronize the sprite with the cursor. + * + * @param pDev The device to sync + */ +void +miPointerUpdateSprite (DeviceIntPtr pDev) +{ + ScreenPtr pScreen; + miPointerScreenPtr pScreenPriv; + CursorPtr pCursor; + int x, y, devx, devy; + miPointerPtr pPointer; + + if (!pDev || !pDev->coreEvents) + return; + + pPointer = MIPOINTER(pDev); + + if (!pPointer) + return; + + pScreen = pPointer->pScreen; + if (!pScreen) + return; + + x = pPointer->x; + y = pPointer->y; + devx = pPointer->devx; + devy = pPointer->devy; + + pScreenPriv = GetScreenPrivate (pScreen); + /* + * if the cursor has switched screens, disable the sprite + * on the old screen + */ + if (pScreen != pPointer->pSpriteScreen) + { + if (pPointer->pSpriteScreen) + { + miPointerScreenPtr pOldPriv; + + pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen); + if (pPointer->pCursor) + { + (*pOldPriv->spriteFuncs->SetCursor) + (pDev, pPointer->pSpriteScreen, NullCursor, 0, 0); + } + (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE); + } + (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE); + (*pScreenPriv->spriteFuncs->SetCursor) + (pDev, pScreen, pPointer->pCursor, x, y); + pPointer->devx = x; + pPointer->devy = y; + pPointer->pSpriteCursor = pPointer->pCursor; + pPointer->pSpriteScreen = pScreen; + } + /* + * if the cursor has changed, display the new one + */ + else if (pPointer->pCursor != pPointer->pSpriteCursor) + { + pCursor = pPointer->pCursor; + if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent)) + pCursor = NullCursor; + (*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y); + + pPointer->devx = x; + pPointer->devy = y; + pPointer->pSpriteCursor = pPointer->pCursor; + } + else if (x != devx || y != devy) + { + pPointer->devx = x; + pPointer->devy = y; + if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) + (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); + } +} + +/** + * Set the device to the coordinates on the given screen. + * + * @param pDev The device to move + * @param screen_no Index of the screen to move to + * @param x The x coordinate in per-screen coordinates + * @param y The y coordinate in per-screen coordinates + */ +void +miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y) +{ + miPointerScreenPtr pScreenPriv; + ScreenPtr pScreen; + miPointerPtr pPointer; + + pPointer = MIPOINTER(pDev); + + pScreen = screenInfo.screens[screen_no]; + pScreenPriv = GetScreenPrivate (pScreen); + (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE); + NewCurrentScreen (pDev, pScreen, x, y); + + pPointer->limits.x2 = pScreen->width; + pPointer->limits.y2 = pScreen->height; +} + +/** + * @return The current screen of the VCP + */ +ScreenPtr +miPointerCurrentScreen (void) +{ + return miPointerGetScreen(inputInfo.pointer); +} + +/** + * @return The current screen of the given device or NULL. + */ +ScreenPtr +miPointerGetScreen(DeviceIntPtr pDev) +{ + miPointerPtr pPointer = MIPOINTER(pDev); + return (pPointer) ? pPointer->pScreen : NULL; +} + +/* Controls whether the cursor image should be updated immediately when + moved (FALSE) or if something else will be responsible for updating + it later (TRUE). Returns current setting. + Caller is responsible for calling OsBlockSignal first. +*/ +Bool +miPointerSetWaitForUpdate(ScreenPtr pScreen, Bool wait) +{ + SetupScreen(pScreen); + Bool prevWait = pScreenPriv->waitForUpdate; + + pScreenPriv->waitForUpdate = wait; + return prevWait; +} + + +/* Move the pointer on the current screen, and update the sprite. */ +static void +miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y) +{ + miPointerPtr pPointer; + SetupScreen(pScreen); + + pPointer = MIPOINTER(pDev); + + /* Hack: We mustn't call into ->MoveCursor for anything but the + * VCP, as this may cause a non-HW rendered cursor to be rendered during + * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT. + */ + if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer + && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen) + { + pPointer->devx = x; + pPointer->devy = y; + if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) + (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); + } + + pPointer->x = x; + pPointer->y = y; + pPointer->pScreen = pScreen; +} + +/** + * Set the devices' cursor position to the given x/y position. + * + * This function is called during the pointer update path in + * GetPointerEvents and friends (and the same in the xwin DDX). + * + * @param pDev The device to move + * @param[in,out] x The x coordiante in screen coordinates (in regards to total + * desktop size) + * @param[in,out] y The y coordiante in screen coordinates (in regards to total + * desktop size) + */ +void +miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y) +{ + miPointerScreenPtr pScreenPriv; + ScreenPtr pScreen; + ScreenPtr newScreen; + + miPointerPtr pPointer; + + if (!pDev || !pDev->coreEvents) + return; + + pPointer = MIPOINTER(pDev); + pScreen = pPointer->pScreen; + if (!pScreen) + return; /* called before ready */ + + if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height) + { + pScreenPriv = GetScreenPrivate (pScreen); + if (!pPointer->confined) + { + newScreen = pScreen; + (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y); + if (newScreen != pScreen) + { + pScreen = newScreen; + (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, + FALSE); + pScreenPriv = GetScreenPrivate (pScreen); + /* Smash the confine to the new screen */ + pPointer->limits.x2 = pScreen->width; + pPointer->limits.y2 = pScreen->height; + } + } + } + /* Constrain the sprite to the current limits. */ + if (*x < pPointer->limits.x1) + *x = pPointer->limits.x1; + if (*x >= pPointer->limits.x2) + *x = pPointer->limits.x2 - 1; + if (*y < pPointer->limits.y1) + *y = pPointer->limits.y1; + if (*y >= pPointer->limits.y2) + *y = pPointer->limits.y2 - 1; + + if (pPointer->x == *x && pPointer->y == *y && + pPointer->pScreen == pScreen) + return; + + miPointerMoveNoEvent(pDev, pScreen, *x, *y); +} + +/** + * Get the current position of the device in desktop coordinates. + * + * @param x Return value for the current x coordinate in desktop coordiates. + * @param y Return value for the current y coordinate in desktop coordiates. + */ +void +miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y) +{ + *x = MIPOINTER(pDev)->x; + *y = MIPOINTER(pDev)->y; +} + +#ifdef XQUARTZ +#include <pthread.h> +void darwinEvents_lock(void); +void darwinEvents_unlock(void); +#endif + +/** + * Move the device's pointer to the x/y coordinates on the given screen. + * This function generates and enqueues pointer events. + * + * @param pDev The device to move + * @param pScreen The screen the device is on + * @param x The x coordinate in per-screen coordinates + * @param y The y coordinate in per-screen coordinates + */ +void +miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + int i, nevents; + int valuators[2]; + ValuatorMask mask; + + miPointerMoveNoEvent(pDev, pScreen, x, y); + + /* generate motion notify */ + valuators[0] = x; + valuators[1] = y; + + if (!events) + { + events = InitEventList(GetMaximumEventsNum()); + + if (!events) + { + FatalError("Could not allocate event store.\n"); + return; + } + } + + valuator_mask_set_range(&mask, 0, 2, valuators); + nevents = GetPointerEvents(events, pDev, MotionNotify, 0, + POINTER_SCREEN | POINTER_ABSOLUTE, &mask); + + OsBlockSignals(); +#ifdef XQUARTZ + darwinEvents_lock(); +#endif + for (i = 0; i < nevents; i++) + mieqEnqueue(pDev, (InternalEvent*)events[i].event); +#ifdef XQUARTZ + darwinEvents_unlock(); +#endif + OsReleaseSignals(); +} diff --git a/xorg-server/mi/mipointrst.h b/xorg-server/mi/mipointrst.h index bd9c24a00..c912a17da 100644 --- a/xorg-server/mi/mipointrst.h +++ b/xorg-server/mi/mipointrst.h @@ -44,6 +44,7 @@ typedef struct { Bool confined; /* pointer can't change screens */ int x, y; /* hot spot location */ int devx, devy; /* sprite position */ + Bool generateEvent; /* generate an event during warping? */ } miPointerRec, *miPointerPtr; typedef struct { diff --git a/xorg-server/mi/misprite.c b/xorg-server/mi/misprite.c index 0dce0a266..b0290af29 100644 --- a/xorg-server/mi/misprite.c +++ b/xorg-server/mi/misprite.c @@ -1,1045 +1,1045 @@ -/*
- * misprite.c
- *
- * machine independent software sprite 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 <X11/Xproto.h>
-#include "misc.h"
-#include "pixmapstr.h"
-#include "input.h"
-#include "mi.h"
-#include "cursorstr.h"
-#include <X11/fonts/font.h>
-#include "scrnintstr.h"
-#include "colormapst.h"
-#include "windowstr.h"
-#include "gcstruct.h"
-#include "mipointer.h"
-#include "misprite.h"
-#include "dixfontstr.h"
-#include <X11/fonts/fontstruct.h>
-#include "inputstr.h"
-#include "damage.h"
-
-typedef struct {
- CursorPtr pCursor;
- int x; /* cursor hotspot */
- int y;
- BoxRec saved; /* saved area from the screen */
- Bool isUp; /* cursor in frame buffer */
- Bool shouldBeUp; /* cursor should be displayed */
- WindowPtr pCacheWin; /* window the cursor last seen in */
- Bool isInCacheWin;
- Bool checkPixels; /* check colormap collision */
- ScreenPtr pScreen;
-} miCursorInfoRec, *miCursorInfoPtr;
-
-/*
- * per screen information
- */
-
-typedef struct {
- /* screen procedures */
- CloseScreenProcPtr CloseScreen;
- GetImageProcPtr GetImage;
- GetSpansProcPtr GetSpans;
- SourceValidateProcPtr SourceValidate;
-
- /* window procedures */
- CopyWindowProcPtr CopyWindow;
-
- /* colormap procedures */
- InstallColormapProcPtr InstallColormap;
- StoreColorsProcPtr StoreColors;
-
- /* os layer procedures */
- ScreenBlockHandlerProcPtr BlockHandler;
-
- /* device cursor procedures */
- DeviceCursorInitializeProcPtr DeviceCursorInitialize;
- DeviceCursorCleanupProcPtr DeviceCursorCleanup;
-
- xColorItem colors[2];
- ColormapPtr pInstalledMap;
- ColormapPtr pColormap;
- VisualPtr pVisual;
- DamagePtr pDamage; /* damage tracking structure */
- Bool damageRegistered;
- int numberOfCursors;
-} miSpriteScreenRec, *miSpriteScreenPtr;
-
-#define SOURCE_COLOR 0
-#define MASK_COLOR 1
-
-/*
- * Overlap BoxPtr and Box elements
- */
-#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \
- (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \
- ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2))
-
-/*
- * Overlap BoxPtr, origins, and rectangle
- */
-#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \
- BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h))
-
-/*
- * Overlap BoxPtr, origins and RectPtr
- */
-#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \
- ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \
- (int)((pRect)->width), (int)((pRect)->height))
-/*
- * Overlap BoxPtr and horizontal span
- */
-#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y))
-
-#define LINE_SORT(x1,y1,x2,y2) \
-{ int _t; \
- if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \
- if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } }
-
-#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \
- BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2))
-
-
-#define SPRITE_DEBUG_ENABLE 0
-#if SPRITE_DEBUG_ENABLE
-#define SPRITE_DEBUG(x) ErrorF x
-#else
-#define SPRITE_DEBUG(x)
-#endif
-
-#define MISPRITE(dev) \
- ((!IsMaster(dev) && !dev->u.master) ? \
- (miCursorInfoPtr)dixLookupPrivate(&dev->devPrivates, miSpriteDevPrivatesKey) : \
- (miCursorInfoPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miSpriteDevPrivatesKey))
-
-static void
-miSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
-{
- if (pScreenPriv->damageRegistered) {
- DamageUnregister (&(pScreen->GetScreenPixmap(pScreen)->drawable),
- pScreenPriv->pDamage);
- pScreenPriv->damageRegistered = 0;
- }
-}
-
-static void
-miSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
-{
- if (!pScreenPriv->damageRegistered) {
- pScreenPriv->damageRegistered = 1;
- DamageRegister (&(pScreen->GetScreenPixmap(pScreen)->drawable),
- pScreenPriv->pDamage);
- }
-}
-
-static void
-miSpriteIsUp(miCursorInfoPtr pDevCursor)
-{
- pDevCursor->isUp = TRUE;
-}
-
-static void
-miSpriteIsDown(miCursorInfoPtr pDevCursor)
-{
- pDevCursor->isUp = FALSE;
-}
-
-/*
- * screen wrappers
- */
-
-static DevPrivateKeyRec miSpriteScreenKeyRec;
-#define miSpriteScreenKey (&miSpriteScreenKeyRec)
-#define GetSpriteScreen(pScreen) \
- (dixLookupPrivate(&(pScreen)->devPrivates, miSpriteScreenKey))
-static DevPrivateKeyRec miSpriteDevPrivatesKeyRec;
-#define miSpriteDevPrivatesKey (&miSpriteDevPrivatesKeyRec)
-
-static Bool miSpriteCloseScreen(int i, ScreenPtr pScreen);
-static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy,
- int w, int h, unsigned int format,
- unsigned long planemask, char *pdstLine);
-static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax,
- DDXPointPtr ppt, int *pwidth, int nspans,
- char *pdstStart);
-static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y,
- int width, int height,
- unsigned int subWindowMode);
-static void miSpriteCopyWindow (WindowPtr pWindow,
- DDXPointRec ptOldOrg,
- RegionPtr prgnSrc);
-static void miSpriteBlockHandler(int i, pointer blockData,
- pointer pTimeout,
- pointer pReadMask);
-static void miSpriteInstallColormap(ColormapPtr pMap);
-static void miSpriteStoreColors(ColormapPtr pMap, int ndef,
- xColorItem *pdef);
-
-static void miSpriteComputeSaved(DeviceIntPtr pDev,
- ScreenPtr pScreen);
-
-static Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev,
- ScreenPtr pScreen);
-static void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev,
- ScreenPtr pScreen);
-
-#define SCREEN_PROLOGUE(pPriv, pScreen, field) ((pScreen)->field = \
- (pPriv)->field)
-#define SCREEN_EPILOGUE(pPriv, pScreen, field)\
- ((pPriv)->field = (pScreen)->field, (pScreen)->field = miSprite##field)
-
-/*
- * pointer-sprite method table
- */
-
-static Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor);
-static Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor);
-static void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor, int x, int y);
-static void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
- int x, int y);
-
-miPointerSpriteFuncRec miSpritePointerFuncs = {
- miSpriteRealizeCursor,
- miSpriteUnrealizeCursor,
- miSpriteSetCursor,
- miSpriteMoveCursor,
- miSpriteDeviceCursorInitialize,
- miSpriteDeviceCursorCleanup,
-};
-
-/*
- * other misc functions
- */
-
-static void miSpriteRemoveCursor(DeviceIntPtr pDev,
- ScreenPtr pScreen);
-static void miSpriteSaveUnderCursor(DeviceIntPtr pDev,
- ScreenPtr pScreen);
-static void miSpriteRestoreCursor(DeviceIntPtr pDev,
- ScreenPtr pScreen);
-
-static void
-miSpriteRegisterBlockHandler(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
-{
- if (!pScreenPriv->BlockHandler) {
- pScreenPriv->BlockHandler = pScreen->BlockHandler;
- pScreen->BlockHandler = miSpriteBlockHandler;
- }
-}
-
-static void
-miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
-{
- ScreenPtr pScreen = closure;
- miCursorInfoPtr pCursorInfo;
- DeviceIntPtr pDev;
-
- for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pCursorInfo = MISPRITE(pDev);
-
- if (pCursorInfo->isUp &&
- pCursorInfo->pScreen == pScreen &&
- RegionContainsRect(pRegion, &pCursorInfo->saved) != rgnOUT)
- {
- SPRITE_DEBUG(("Damage remove\n"));
- miSpriteRemoveCursor (pDev, pScreen);
- }
- }
- }
-}
-
-/*
- * miSpriteInitialize -- called from device-dependent screen
- * initialization proc after all of the function pointers have
- * been stored in the screen structure.
- */
-
-Bool
-miSpriteInitialize (ScreenPtr pScreen,
- miPointerScreenFuncPtr screenFuncs)
-{
- miSpriteScreenPtr pScreenPriv;
- VisualPtr pVisual;
-
- if (!DamageSetup (pScreen))
- return FALSE;
-
- if (!dixRegisterPrivateKey(&miSpriteScreenKeyRec, PRIVATE_SCREEN, 0))
- return FALSE;
-
- if (!dixRegisterPrivateKey(&miSpriteDevPrivatesKeyRec, PRIVATE_DEVICE, 0))
- return FALSE;
-
- pScreenPriv = malloc(sizeof (miSpriteScreenRec));
- if (!pScreenPriv)
- return FALSE;
-
- pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage,
- NULL,
- DamageReportRawRegion,
- TRUE,
- pScreen,
- pScreen);
-
- if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE))
- {
- free(pScreenPriv);
- return FALSE;
- }
- for (pVisual = pScreen->visuals;
- pVisual->vid != pScreen->rootVisual;
- pVisual++)
- ;
- pScreenPriv->pVisual = pVisual;
- pScreenPriv->CloseScreen = pScreen->CloseScreen;
- pScreenPriv->GetImage = pScreen->GetImage;
- pScreenPriv->GetSpans = pScreen->GetSpans;
- pScreenPriv->SourceValidate = pScreen->SourceValidate;
-
- pScreenPriv->CopyWindow = pScreen->CopyWindow;
-
- pScreenPriv->InstallColormap = pScreen->InstallColormap;
- pScreenPriv->StoreColors = pScreen->StoreColors;
-
- pScreenPriv->BlockHandler = NULL;
-
- pScreenPriv->DeviceCursorInitialize = pScreen->DeviceCursorInitialize;
- pScreenPriv->DeviceCursorCleanup = pScreen->DeviceCursorCleanup;
-
- pScreenPriv->pInstalledMap = NULL;
- pScreenPriv->pColormap = NULL;
- pScreenPriv->colors[SOURCE_COLOR].red = 0;
- pScreenPriv->colors[SOURCE_COLOR].green = 0;
- pScreenPriv->colors[SOURCE_COLOR].blue = 0;
- pScreenPriv->colors[MASK_COLOR].red = 0;
- pScreenPriv->colors[MASK_COLOR].green = 0;
- pScreenPriv->colors[MASK_COLOR].blue = 0;
- pScreenPriv->damageRegistered = 0;
- pScreenPriv->numberOfCursors = 0;
-
- dixSetPrivate(&pScreen->devPrivates, miSpriteScreenKey, pScreenPriv);
-
- pScreen->CloseScreen = miSpriteCloseScreen;
- pScreen->GetImage = miSpriteGetImage;
- pScreen->GetSpans = miSpriteGetSpans;
- pScreen->SourceValidate = miSpriteSourceValidate;
-
- pScreen->CopyWindow = miSpriteCopyWindow;
- pScreen->InstallColormap = miSpriteInstallColormap;
- pScreen->StoreColors = miSpriteStoreColors;
-
- return TRUE;
-}
-
-/*
- * Screen wrappers
- */
-
-/*
- * CloseScreen wrapper -- unwrap everything, free the private data
- * and call the wrapped function
- */
-
-static Bool
-miSpriteCloseScreen (int i, ScreenPtr pScreen)
-{
- miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen);
-
- pScreen->CloseScreen = pScreenPriv->CloseScreen;
- pScreen->GetImage = pScreenPriv->GetImage;
- pScreen->GetSpans = pScreenPriv->GetSpans;
- pScreen->SourceValidate = pScreenPriv->SourceValidate;
- pScreen->InstallColormap = pScreenPriv->InstallColormap;
- pScreen->StoreColors = pScreenPriv->StoreColors;
-
- DamageDestroy (pScreenPriv->pDamage);
-
- free(pScreenPriv);
-
- return (*pScreen->CloseScreen) (i, pScreen);
-}
-
-static void
-miSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h,
- unsigned int format, unsigned long planemask,
- char *pdstLine)
-{
- ScreenPtr pScreen = pDrawable->pScreen;
- DeviceIntPtr pDev;
- miCursorInfoPtr pCursorInfo;
- miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
-
- SCREEN_PROLOGUE (pPriv, pScreen, GetImage);
-
- if (pDrawable->type == DRAWABLE_WINDOW)
- {
- for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pCursorInfo = MISPRITE(pDev);
- if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
- ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y,
- sx, sy, w, h))
- {
- SPRITE_DEBUG (("GetImage remove\n"));
- miSpriteRemoveCursor (pDev, pScreen);
- }
- }
- }
- }
-
- (*pScreen->GetImage) (pDrawable, sx, sy, w, h,
- format, planemask, pdstLine);
-
- SCREEN_EPILOGUE (pPriv, pScreen, GetImage);
-}
-
-static void
-miSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
- int *pwidth, int nspans, char *pdstStart)
-{
- ScreenPtr pScreen = pDrawable->pScreen;
- DeviceIntPtr pDev;
- miCursorInfoPtr pCursorInfo;
- miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
-
- SCREEN_PROLOGUE (pPriv, pScreen, GetSpans);
-
- if (pDrawable->type == DRAWABLE_WINDOW)
- {
- for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pCursorInfo = MISPRITE(pDev);
-
- if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
- {
- DDXPointPtr pts;
- int *widths;
- int nPts;
- int xorg,
- yorg;
-
- xorg = pDrawable->x;
- yorg = pDrawable->y;
-
- for (pts = ppt, widths = pwidth, nPts = nspans;
- nPts--;
- pts++, widths++)
- {
- if (SPN_OVERLAP(&pCursorInfo->saved,pts->y+yorg,
- pts->x+xorg,*widths))
- {
- SPRITE_DEBUG (("GetSpans remove\n"));
- miSpriteRemoveCursor (pDev, pScreen);
- break;
- }
- }
- }
- }
- }
- }
-
- (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
-
- SCREEN_EPILOGUE (pPriv, pScreen, GetSpans);
-}
-
-static void
-miSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width,
- int height, unsigned int subWindowMode)
-{
- ScreenPtr pScreen = pDrawable->pScreen;
- DeviceIntPtr pDev;
- miCursorInfoPtr pCursorInfo;
- miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
-
- SCREEN_PROLOGUE (pPriv, pScreen, SourceValidate);
-
- if (pDrawable->type == DRAWABLE_WINDOW)
- {
- for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pCursorInfo = MISPRITE(pDev);
- if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
- ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y,
- x, y, width, height))
- {
- SPRITE_DEBUG (("SourceValidate remove\n"));
- miSpriteRemoveCursor (pDev, pScreen);
- }
- }
- }
- }
-
- if (pScreen->SourceValidate)
- (*pScreen->SourceValidate) (pDrawable, x, y, width, height, subWindowMode);
-
- SCREEN_EPILOGUE (pPriv, pScreen, SourceValidate);
-}
-
-static void
-miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
-{
- ScreenPtr pScreen = pWindow->drawable.pScreen;
- DeviceIntPtr pDev;
- miCursorInfoPtr pCursorInfo;
- miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
-
- SCREEN_PROLOGUE (pPriv, pScreen, CopyWindow);
-
- for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pCursorInfo = MISPRITE(pDev);
- /*
- * Damage will take care of destination check
- */
- if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen &&
- RegionContainsRect(prgnSrc, &pCursorInfo->saved) != rgnOUT)
- {
- SPRITE_DEBUG (("CopyWindow remove\n"));
- miSpriteRemoveCursor (pDev, pScreen);
- }
- }
- }
-
- (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
- SCREEN_EPILOGUE (pPriv, pScreen, CopyWindow);
-}
-
-static void
-miSpriteBlockHandler (int i, pointer blockData, pointer pTimeout,
- pointer pReadmask)
-{
- ScreenPtr pScreen = screenInfo.screens[i];
- miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
- DeviceIntPtr pDev;
- miCursorInfoPtr pCursorInfo;
- Bool WorkToDo = FALSE;
-
- for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pCursorInfo = MISPRITE(pDev);
- if (pCursorInfo && !pCursorInfo->isUp
- && pCursorInfo->pScreen == pScreen
- && pCursorInfo->shouldBeUp)
- {
- SPRITE_DEBUG (("BlockHandler save"));
- miSpriteSaveUnderCursor (pDev, pScreen);
- }
- }
- }
- for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pCursorInfo = MISPRITE(pDev);
- if (pCursorInfo && !pCursorInfo->isUp &&
- pCursorInfo->pScreen == pScreen &&
- pCursorInfo->shouldBeUp)
- {
- SPRITE_DEBUG (("BlockHandler restore\n"));
- miSpriteRestoreCursor (pDev, pScreen);
- if (!pCursorInfo->isUp)
- WorkToDo = TRUE;
- }
- }
- }
-
- SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler);
-
- (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
-
- if (WorkToDo)
- SCREEN_EPILOGUE(pPriv, pScreen, BlockHandler);
- else
- pPriv->BlockHandler = NULL;
-}
-
-static void
-miSpriteInstallColormap (ColormapPtr pMap)
-{
- ScreenPtr pScreen = pMap->pScreen;
- miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
-
- SCREEN_PROLOGUE(pPriv, pScreen, InstallColormap);
-
- (*pScreen->InstallColormap) (pMap);
-
- SCREEN_EPILOGUE(pPriv, pScreen, InstallColormap);
-
- /* InstallColormap can be called before devices are initialized. */
- pPriv->pInstalledMap = pMap;
- if (pPriv->pColormap != pMap)
- {
- DeviceIntPtr pDev;
- miCursorInfoPtr pCursorInfo;
- for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pCursorInfo = MISPRITE(pDev);
- pCursorInfo->checkPixels = TRUE;
- if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
- miSpriteRemoveCursor(pDev, pScreen);
- }
- }
-
- }
-}
-
-static void
-miSpriteStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef)
-{
- ScreenPtr pScreen = pMap->pScreen;
- miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
- int i;
- int updated;
- VisualPtr pVisual;
- DeviceIntPtr pDev;
- miCursorInfoPtr pCursorInfo;
-
- SCREEN_PROLOGUE(pPriv, pScreen, StoreColors);
-
- (*pScreen->StoreColors) (pMap, ndef, pdef);
-
- SCREEN_EPILOGUE(pPriv, pScreen, StoreColors);
-
- if (pPriv->pColormap == pMap)
- {
- updated = 0;
- pVisual = pMap->pVisual;
- if (pVisual->class == DirectColor)
- {
- /* Direct color - match on any of the subfields */
-
-#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
-
-#define UpdateDAC(dev, plane,dac,mask) {\
- if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\
- dev->colors[plane].dac = pdef[i].dac; \
- updated = 1; \
- } \
-}
-
-#define CheckDirect(dev, plane) \
- UpdateDAC(dev, plane,red,redMask) \
- UpdateDAC(dev, plane,green,greenMask) \
- UpdateDAC(dev, plane,blue,blueMask)
-
- for (i = 0; i < ndef; i++)
- {
- CheckDirect (pPriv, SOURCE_COLOR)
- CheckDirect (pPriv, MASK_COLOR)
- }
- }
- else
- {
- /* PseudoColor/GrayScale - match on exact pixel */
- for (i = 0; i < ndef; i++)
- {
- if (pdef[i].pixel ==
- pPriv->colors[SOURCE_COLOR].pixel)
- {
- pPriv->colors[SOURCE_COLOR] = pdef[i];
- if (++updated == 2)
- break;
- }
- if (pdef[i].pixel ==
- pPriv->colors[MASK_COLOR].pixel)
- {
- pPriv->colors[MASK_COLOR] = pdef[i];
- if (++updated == 2)
- break;
- }
- }
- }
- if (updated)
- {
- for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
- {
- if (DevHasCursor(pDev))
- {
- pCursorInfo = MISPRITE(pDev);
- pCursorInfo->checkPixels = TRUE;
- if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen)
- miSpriteRemoveCursor (pDev, pScreen);
- }
- }
- }
- }
-}
-
-static void
-miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen)
-{
- miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen);
- CursorPtr pCursor;
- xColorItem *sourceColor, *maskColor;
-
- pCursor = pDevCursor->pCursor;
- sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
- maskColor = &pScreenPriv->colors[MASK_COLOR];
- if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap ||
- !(pCursor->foreRed == sourceColor->red &&
- pCursor->foreGreen == sourceColor->green &&
- pCursor->foreBlue == sourceColor->blue &&
- pCursor->backRed == maskColor->red &&
- pCursor->backGreen == maskColor->green &&
- pCursor->backBlue == maskColor->blue))
- {
- pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
- sourceColor->red = pCursor->foreRed;
- sourceColor->green = pCursor->foreGreen;
- sourceColor->blue = pCursor->foreBlue;
- FakeAllocColor (pScreenPriv->pColormap, sourceColor);
- maskColor->red = pCursor->backRed;
- maskColor->green = pCursor->backGreen;
- maskColor->blue = pCursor->backBlue;
- FakeAllocColor (pScreenPriv->pColormap, maskColor);
- /* "free" the pixels right away, don't let this confuse you */
- FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
- FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
- }
-
- pDevCursor->checkPixels = FALSE;
-
-}
-
-/*
- * miPointer interface routines
- */
-
-#define SPRITE_PAD 8
-
-static Bool
-miSpriteRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
-{
- miCursorInfoPtr pCursorInfo;
-
- if (!IsMaster(pDev) && !pDev->u.master)
- return FALSE;
-
- pCursorInfo = MISPRITE(pDev);
-
- if (pCursor == pCursorInfo->pCursor)
- pCursorInfo->checkPixels = TRUE;
-
- return miDCRealizeCursor(pScreen, pCursor);
-}
-
-static Bool
-miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
-{
- return miDCUnrealizeCursor(pScreen, pCursor);
-}
-
-static void
-miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
- CursorPtr pCursor, int x, int y)
-{
- miCursorInfoPtr pPointer;
- miSpriteScreenPtr pScreenPriv;
-
- if (!IsMaster(pDev) && !pDev->u.master)
- return;
-
- pPointer = MISPRITE(pDev);
- pScreenPriv = GetSpriteScreen(pScreen);
-
- if (!pCursor)
- {
- if (pPointer->shouldBeUp)
- --pScreenPriv->numberOfCursors;
- pPointer->shouldBeUp = FALSE;
- if (pPointer->isUp)
- miSpriteRemoveCursor (pDev, pScreen);
- if (pScreenPriv->numberOfCursors == 0)
- miSpriteDisableDamage(pScreen, pScreenPriv);
- pPointer->pCursor = 0;
- return;
- }
- if (!pPointer->shouldBeUp)
- pScreenPriv->numberOfCursors++;
- pPointer->shouldBeUp = TRUE;
- if (!pPointer->isUp)
- miSpriteRegisterBlockHandler(pScreen, pScreenPriv);
- if (pPointer->x == x &&
- pPointer->y == y &&
- pPointer->pCursor == pCursor &&
- !pPointer->checkPixels)
- {
- return;
- }
- pPointer->x = x;
- pPointer->y = y;
- pPointer->pCacheWin = NullWindow;
- if (pPointer->checkPixels || pPointer->pCursor != pCursor)
- {
- pPointer->pCursor = pCursor;
- miSpriteFindColors (pPointer, pScreen);
- }
- if (pPointer->isUp) {
- /* TODO: reimplement flicker-free MoveCursor */
- SPRITE_DEBUG (("SetCursor remove %d\n", pDev->id));
- miSpriteRemoveCursor (pDev, pScreen);
- }
-
- if (!pPointer->isUp && pPointer->pCursor)
- {
- SPRITE_DEBUG (("SetCursor restore %d\n", pDev->id));
- miSpriteSaveUnderCursor(pDev, pScreen);
- miSpriteRestoreCursor (pDev, pScreen);
- }
-
-}
-
-static void
-miSpriteMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
-{
- CursorPtr pCursor;
-
- if (!IsMaster(pDev) && !pDev->u.master)
- return;
-
- pCursor = MISPRITE(pDev)->pCursor;
-
- miSpriteSetCursor (pDev, pScreen, pCursor, x, y);
-}
-
-
-static Bool
-miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- miCursorInfoPtr pCursorInfo;
- int ret = FALSE;
-
- pCursorInfo = malloc(sizeof(miCursorInfoRec));
- if (!pCursorInfo)
- return FALSE;
-
- pCursorInfo->pCursor = NULL;
- pCursorInfo->x = 0;
- pCursorInfo->y = 0;
- pCursorInfo->isUp = FALSE;
- pCursorInfo->shouldBeUp = FALSE;
- pCursorInfo->pCacheWin = NullWindow;
- pCursorInfo->isInCacheWin = FALSE;
- pCursorInfo->checkPixels = TRUE;
- pCursorInfo->pScreen = FALSE;
-
- ret = miDCDeviceInitialize(pDev, pScreen);
- if (!ret)
- {
- free(pCursorInfo);
- pCursorInfo = NULL;
- }
- dixSetPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey, pCursorInfo);
- return ret;
-}
-
-static void
-miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- if (DevHasCursor(pDev))
- miDCDeviceCleanup(pDev, pScreen);
-}
-
-/*
- * undraw/draw cursor
- */
-
-static void
-miSpriteRemoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- miSpriteScreenPtr pScreenPriv;
- miCursorInfoPtr pCursorInfo;
-
-
- if (!IsMaster(pDev) && !pDev->u.master)
- return;
-
- DamageDrawInternal (pScreen, TRUE);
- pScreenPriv = GetSpriteScreen(pScreen);
- pCursorInfo = MISPRITE(pDev);
-
- miSpriteIsDown(pCursorInfo);
- miSpriteRegisterBlockHandler(pScreen, pScreenPriv);
- pCursorInfo->pCacheWin = NullWindow;
- miSpriteDisableDamage(pScreen, pScreenPriv);
- if (!miDCRestoreUnderCursor(pDev,
- pScreen,
- pCursorInfo->saved.x1,
- pCursorInfo->saved.y1,
- pCursorInfo->saved.x2 -
- pCursorInfo->saved.x1,
- pCursorInfo->saved.y2 -
- pCursorInfo->saved.y1))
- {
- miSpriteIsUp(pCursorInfo);
- }
- miSpriteEnableDamage(pScreen, pScreenPriv);
- DamageDrawInternal (pScreen, FALSE);
-}
-
-/*
- * Called from the block handler, saves area under cursor
- * before waiting for something to do.
- */
-
-static void
-miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- miSpriteScreenPtr pScreenPriv;
- int x, y;
- CursorPtr pCursor;
- miCursorInfoPtr pCursorInfo;
-
- if (!IsMaster(pDev) && !pDev->u.master)
- return;
-
- DamageDrawInternal (pScreen, TRUE);
- pScreenPriv = GetSpriteScreen(pScreen);
- pCursorInfo = MISPRITE(pDev);
-
- miSpriteComputeSaved (pDev, pScreen);
- pCursor = pCursorInfo->pCursor;
-
- x = pCursorInfo->x - (int)pCursor->bits->xhot;
- y = pCursorInfo->y - (int)pCursor->bits->yhot;
- miSpriteDisableDamage(pScreen, pScreenPriv);
-
- miDCSaveUnderCursor(pDev,
- pScreen,
- pCursorInfo->saved.x1,
- pCursorInfo->saved.y1,
- pCursorInfo->saved.x2 -
- pCursorInfo->saved.x1,
- pCursorInfo->saved.y2 -
- pCursorInfo->saved.y1);
- SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id));
- miSpriteEnableDamage(pScreen, pScreenPriv);
- DamageDrawInternal (pScreen, FALSE);
-}
-
-
-/*
- * Called from the block handler, restores the cursor
- * before waiting for something to do.
- */
-
-static void
-miSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- miSpriteScreenPtr pScreenPriv;
- int x, y;
- CursorPtr pCursor;
- miCursorInfoPtr pCursorInfo;
-
- if (!IsMaster(pDev) && !pDev->u.master)
- return;
-
- DamageDrawInternal (pScreen, TRUE);
- pScreenPriv = GetSpriteScreen(pScreen);
- pCursorInfo = MISPRITE(pDev);
-
- miSpriteComputeSaved (pDev, pScreen);
- pCursor = pCursorInfo->pCursor;
-
- x = pCursorInfo->x - (int)pCursor->bits->xhot;
- y = pCursorInfo->y - (int)pCursor->bits->yhot;
- miSpriteDisableDamage(pScreen, pScreenPriv);
- SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id));
- if (pCursorInfo->checkPixels)
- miSpriteFindColors (pCursorInfo, pScreen);
- if (miDCPutUpCursor(pDev, pScreen,
- pCursor, x, y,
- pScreenPriv->colors[SOURCE_COLOR].pixel,
- pScreenPriv->colors[MASK_COLOR].pixel))
- {
- miSpriteIsUp(pCursorInfo);
- pCursorInfo->pScreen = pScreen;
- }
- miSpriteEnableDamage(pScreen, pScreenPriv);
- DamageDrawInternal (pScreen, FALSE);
-}
-
-/*
- * compute the desired area of the screen to save
- */
-
-static void
-miSpriteComputeSaved (DeviceIntPtr pDev, ScreenPtr pScreen)
-{
- int x, y, w, h;
- int wpad, hpad;
- CursorPtr pCursor;
- miCursorInfoPtr pCursorInfo;
-
- if (!IsMaster(pDev) && !pDev->u.master)
- return;
-
- pCursorInfo = MISPRITE(pDev);
-
- pCursor = pCursorInfo->pCursor;
- x = pCursorInfo->x - (int)pCursor->bits->xhot;
- y = pCursorInfo->y - (int)pCursor->bits->yhot;
- w = pCursor->bits->width;
- h = pCursor->bits->height;
- wpad = SPRITE_PAD;
- hpad = SPRITE_PAD;
- pCursorInfo->saved.x1 = x - wpad;
- pCursorInfo->saved.y1 = y - hpad;
- pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2;
- pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2;
-}
-
+/* + * misprite.c + * + * machine independent software sprite 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 <X11/Xproto.h> +#include "misc.h" +#include "pixmapstr.h" +#include "input.h" +#include "mi.h" +#include "cursorstr.h" +#include <X11/fonts/font.h> +#include "scrnintstr.h" +#include "colormapst.h" +#include "windowstr.h" +#include "gcstruct.h" +#include "mipointer.h" +#include "misprite.h" +#include "dixfontstr.h" +#include <X11/fonts/fontstruct.h> +#include "inputstr.h" +#include "damage.h" + +typedef struct { + CursorPtr pCursor; + int x; /* cursor hotspot */ + int y; + BoxRec saved; /* saved area from the screen */ + Bool isUp; /* cursor in frame buffer */ + Bool shouldBeUp; /* cursor should be displayed */ + WindowPtr pCacheWin; /* window the cursor last seen in */ + Bool isInCacheWin; + Bool checkPixels; /* check colormap collision */ + ScreenPtr pScreen; +} miCursorInfoRec, *miCursorInfoPtr; + +/* + * per screen information + */ + +typedef struct { + /* screen procedures */ + CloseScreenProcPtr CloseScreen; + GetImageProcPtr GetImage; + GetSpansProcPtr GetSpans; + SourceValidateProcPtr SourceValidate; + + /* window procedures */ + CopyWindowProcPtr CopyWindow; + + /* colormap procedures */ + InstallColormapProcPtr InstallColormap; + StoreColorsProcPtr StoreColors; + + /* os layer procedures */ + ScreenBlockHandlerProcPtr BlockHandler; + + /* device cursor procedures */ + DeviceCursorInitializeProcPtr DeviceCursorInitialize; + DeviceCursorCleanupProcPtr DeviceCursorCleanup; + + xColorItem colors[2]; + ColormapPtr pInstalledMap; + ColormapPtr pColormap; + VisualPtr pVisual; + DamagePtr pDamage; /* damage tracking structure */ + Bool damageRegistered; + int numberOfCursors; +} miSpriteScreenRec, *miSpriteScreenPtr; + +#define SOURCE_COLOR 0 +#define MASK_COLOR 1 + +/* + * Overlap BoxPtr and Box elements + */ +#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \ + (((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \ + ((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2)) + +/* + * Overlap BoxPtr, origins, and rectangle + */ +#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \ + BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h)) + +/* + * Overlap BoxPtr, origins and RectPtr + */ +#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \ + ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \ + (int)((pRect)->width), (int)((pRect)->height)) +/* + * Overlap BoxPtr and horizontal span + */ +#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y)) + +#define LINE_SORT(x1,y1,x2,y2) \ +{ int _t; \ + if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \ + if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } } + +#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \ + BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2)) + + +#define SPRITE_DEBUG_ENABLE 0 +#if SPRITE_DEBUG_ENABLE +#define SPRITE_DEBUG(x) ErrorF x +#else +#define SPRITE_DEBUG(x) +#endif + +#define MISPRITE(dev) \ + (IsFloating(dev) ? \ + (miCursorInfoPtr)dixLookupPrivate(&dev->devPrivates, miSpriteDevPrivatesKey) : \ + (miCursorInfoPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miSpriteDevPrivatesKey)) + +static void +miSpriteDisableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) +{ + if (pScreenPriv->damageRegistered) { + DamageUnregister (&(pScreen->GetScreenPixmap(pScreen)->drawable), + pScreenPriv->pDamage); + pScreenPriv->damageRegistered = 0; + } +} + +static void +miSpriteEnableDamage(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) +{ + if (!pScreenPriv->damageRegistered) { + pScreenPriv->damageRegistered = 1; + DamageRegister (&(pScreen->GetScreenPixmap(pScreen)->drawable), + pScreenPriv->pDamage); + } +} + +static void +miSpriteIsUp(miCursorInfoPtr pDevCursor) +{ + pDevCursor->isUp = TRUE; +} + +static void +miSpriteIsDown(miCursorInfoPtr pDevCursor) +{ + pDevCursor->isUp = FALSE; +} + +/* + * screen wrappers + */ + +static DevPrivateKeyRec miSpriteScreenKeyRec; +#define miSpriteScreenKey (&miSpriteScreenKeyRec) +#define GetSpriteScreen(pScreen) \ + (dixLookupPrivate(&(pScreen)->devPrivates, miSpriteScreenKey)) +static DevPrivateKeyRec miSpriteDevPrivatesKeyRec; +#define miSpriteDevPrivatesKey (&miSpriteDevPrivatesKeyRec) + +static Bool miSpriteCloseScreen(int i, ScreenPtr pScreen); +static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, + int w, int h, unsigned int format, + unsigned long planemask, char *pdstLine); +static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax, + DDXPointPtr ppt, int *pwidth, int nspans, + char *pdstStart); +static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, + int width, int height, + unsigned int subWindowMode); +static void miSpriteCopyWindow (WindowPtr pWindow, + DDXPointRec ptOldOrg, + RegionPtr prgnSrc); +static void miSpriteBlockHandler(int i, pointer blockData, + pointer pTimeout, + pointer pReadMask); +static void miSpriteInstallColormap(ColormapPtr pMap); +static void miSpriteStoreColors(ColormapPtr pMap, int ndef, + xColorItem *pdef); + +static void miSpriteComputeSaved(DeviceIntPtr pDev, + ScreenPtr pScreen); + +static Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, + ScreenPtr pScreen); + +#define SCREEN_PROLOGUE(pPriv, pScreen, field) ((pScreen)->field = \ + (pPriv)->field) +#define SCREEN_EPILOGUE(pPriv, pScreen, field)\ + ((pPriv)->field = (pScreen)->field, (pScreen)->field = miSprite##field) + +/* + * pointer-sprite method table + */ + +static Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, int x, int y); +static void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y); + +miPointerSpriteFuncRec miSpritePointerFuncs = { + miSpriteRealizeCursor, + miSpriteUnrealizeCursor, + miSpriteSetCursor, + miSpriteMoveCursor, + miSpriteDeviceCursorInitialize, + miSpriteDeviceCursorCleanup, +}; + +/* + * other misc functions + */ + +static void miSpriteRemoveCursor(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miSpriteSaveUnderCursor(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miSpriteRestoreCursor(DeviceIntPtr pDev, + ScreenPtr pScreen); + +static void +miSpriteRegisterBlockHandler(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv) +{ + if (!pScreenPriv->BlockHandler) { + pScreenPriv->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = miSpriteBlockHandler; + } +} + +static void +miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure) +{ + ScreenPtr pScreen = closure; + miCursorInfoPtr pCursorInfo; + DeviceIntPtr pDev; + + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + + if (pCursorInfo->isUp && + pCursorInfo->pScreen == pScreen && + RegionContainsRect(pRegion, &pCursorInfo->saved) != rgnOUT) + { + SPRITE_DEBUG(("Damage remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } + } +} + +/* + * miSpriteInitialize -- called from device-dependent screen + * initialization proc after all of the function pointers have + * been stored in the screen structure. + */ + +Bool +miSpriteInitialize (ScreenPtr pScreen, + miPointerScreenFuncPtr screenFuncs) +{ + miSpriteScreenPtr pScreenPriv; + VisualPtr pVisual; + + if (!DamageSetup (pScreen)) + return FALSE; + + if (!dixRegisterPrivateKey(&miSpriteScreenKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + if (!dixRegisterPrivateKey(&miSpriteDevPrivatesKeyRec, PRIVATE_DEVICE, 0)) + return FALSE; + + pScreenPriv = malloc(sizeof (miSpriteScreenRec)); + if (!pScreenPriv) + return FALSE; + + pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage, + NULL, + DamageReportRawRegion, + TRUE, + pScreen, + pScreen); + + if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE)) + { + free(pScreenPriv); + return FALSE; + } + for (pVisual = pScreen->visuals; + pVisual->vid != pScreen->rootVisual; + pVisual++) + ; + pScreenPriv->pVisual = pVisual; + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreenPriv->GetImage = pScreen->GetImage; + pScreenPriv->GetSpans = pScreen->GetSpans; + pScreenPriv->SourceValidate = pScreen->SourceValidate; + + pScreenPriv->CopyWindow = pScreen->CopyWindow; + + pScreenPriv->InstallColormap = pScreen->InstallColormap; + pScreenPriv->StoreColors = pScreen->StoreColors; + + pScreenPriv->BlockHandler = NULL; + + pScreenPriv->DeviceCursorInitialize = pScreen->DeviceCursorInitialize; + pScreenPriv->DeviceCursorCleanup = pScreen->DeviceCursorCleanup; + + pScreenPriv->pInstalledMap = NULL; + pScreenPriv->pColormap = NULL; + pScreenPriv->colors[SOURCE_COLOR].red = 0; + pScreenPriv->colors[SOURCE_COLOR].green = 0; + pScreenPriv->colors[SOURCE_COLOR].blue = 0; + pScreenPriv->colors[MASK_COLOR].red = 0; + pScreenPriv->colors[MASK_COLOR].green = 0; + pScreenPriv->colors[MASK_COLOR].blue = 0; + pScreenPriv->damageRegistered = 0; + pScreenPriv->numberOfCursors = 0; + + dixSetPrivate(&pScreen->devPrivates, miSpriteScreenKey, pScreenPriv); + + pScreen->CloseScreen = miSpriteCloseScreen; + pScreen->GetImage = miSpriteGetImage; + pScreen->GetSpans = miSpriteGetSpans; + pScreen->SourceValidate = miSpriteSourceValidate; + + pScreen->CopyWindow = miSpriteCopyWindow; + pScreen->InstallColormap = miSpriteInstallColormap; + pScreen->StoreColors = miSpriteStoreColors; + + return TRUE; +} + +/* + * Screen wrappers + */ + +/* + * CloseScreen wrapper -- unwrap everything, free the private data + * and call the wrapped function + */ + +static Bool +miSpriteCloseScreen (int i, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen); + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->GetImage = pScreenPriv->GetImage; + pScreen->GetSpans = pScreenPriv->GetSpans; + pScreen->SourceValidate = pScreenPriv->SourceValidate; + pScreen->InstallColormap = pScreenPriv->InstallColormap; + pScreen->StoreColors = pScreenPriv->StoreColors; + + DamageDestroy (pScreenPriv->pDamage); + + free(pScreenPriv); + + return (*pScreen->CloseScreen) (i, pScreen); +} + +static void +miSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h, + unsigned int format, unsigned long planemask, + char *pdstLine) +{ + ScreenPtr pScreen = pDrawable->pScreen; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE (pPriv, pScreen, GetImage); + + if (pDrawable->type == DRAWABLE_WINDOW) + { + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && + ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y, + sx, sy, w, h)) + { + SPRITE_DEBUG (("GetImage remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } + } + } + + (*pScreen->GetImage) (pDrawable, sx, sy, w, h, + format, planemask, pdstLine); + + SCREEN_EPILOGUE (pPriv, pScreen, GetImage); +} + +static void +miSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, + int *pwidth, int nspans, char *pdstStart) +{ + ScreenPtr pScreen = pDrawable->pScreen; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE (pPriv, pScreen, GetSpans); + + if (pDrawable->type == DRAWABLE_WINDOW) + { + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) + { + DDXPointPtr pts; + int *widths; + int nPts; + int xorg, + yorg; + + xorg = pDrawable->x; + yorg = pDrawable->y; + + for (pts = ppt, widths = pwidth, nPts = nspans; + nPts--; + pts++, widths++) + { + if (SPN_OVERLAP(&pCursorInfo->saved,pts->y+yorg, + pts->x+xorg,*widths)) + { + SPRITE_DEBUG (("GetSpans remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + break; + } + } + } + } + } + } + + (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); + + SCREEN_EPILOGUE (pPriv, pScreen, GetSpans); +} + +static void +miSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width, + int height, unsigned int subWindowMode) +{ + ScreenPtr pScreen = pDrawable->pScreen; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE (pPriv, pScreen, SourceValidate); + + if (pDrawable->type == DRAWABLE_WINDOW) + { + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && + ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y, + x, y, width, height)) + { + SPRITE_DEBUG (("SourceValidate remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } + } + } + + if (pScreen->SourceValidate) + (*pScreen->SourceValidate) (pDrawable, x, y, width, height, subWindowMode); + + SCREEN_EPILOGUE (pPriv, pScreen, SourceValidate); +} + +static void +miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE (pPriv, pScreen, CopyWindow); + + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + /* + * Damage will take care of destination check + */ + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && + RegionContainsRect(prgnSrc, &pCursorInfo->saved) != rgnOUT) + { + SPRITE_DEBUG (("CopyWindow remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } + } + + (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); + SCREEN_EPILOGUE (pPriv, pScreen, CopyWindow); +} + +static void +miSpriteBlockHandler (int i, pointer blockData, pointer pTimeout, + pointer pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[i]; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + Bool WorkToDo = FALSE; + + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (pCursorInfo && !pCursorInfo->isUp + && pCursorInfo->pScreen == pScreen + && pCursorInfo->shouldBeUp) + { + SPRITE_DEBUG (("BlockHandler save")); + miSpriteSaveUnderCursor (pDev, pScreen); + } + } + } + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (pCursorInfo && !pCursorInfo->isUp && + pCursorInfo->pScreen == pScreen && + pCursorInfo->shouldBeUp) + { + SPRITE_DEBUG (("BlockHandler restore\n")); + miSpriteRestoreCursor (pDev, pScreen); + if (!pCursorInfo->isUp) + WorkToDo = TRUE; + } + } + } + + SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler); + + (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); + + if (WorkToDo) + SCREEN_EPILOGUE(pPriv, pScreen, BlockHandler); + else + pPriv->BlockHandler = NULL; +} + +static void +miSpriteInstallColormap (ColormapPtr pMap) +{ + ScreenPtr pScreen = pMap->pScreen; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + + SCREEN_PROLOGUE(pPriv, pScreen, InstallColormap); + + (*pScreen->InstallColormap) (pMap); + + SCREEN_EPILOGUE(pPriv, pScreen, InstallColormap); + + /* InstallColormap can be called before devices are initialized. */ + pPriv->pInstalledMap = pMap; + if (pPriv->pColormap != pMap) + { + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + pCursorInfo->checkPixels = TRUE; + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) + miSpriteRemoveCursor(pDev, pScreen); + } + } + + } +} + +static void +miSpriteStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef) +{ + ScreenPtr pScreen = pMap->pScreen; + miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen); + int i; + int updated; + VisualPtr pVisual; + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + + SCREEN_PROLOGUE(pPriv, pScreen, StoreColors); + + (*pScreen->StoreColors) (pMap, ndef, pdef); + + SCREEN_EPILOGUE(pPriv, pScreen, StoreColors); + + if (pPriv->pColormap == pMap) + { + updated = 0; + pVisual = pMap->pVisual; + if (pVisual->class == DirectColor) + { + /* Direct color - match on any of the subfields */ + +#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask))) + +#define UpdateDAC(dev, plane,dac,mask) {\ + if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\ + dev->colors[plane].dac = pdef[i].dac; \ + updated = 1; \ + } \ +} + +#define CheckDirect(dev, plane) \ + UpdateDAC(dev, plane,red,redMask) \ + UpdateDAC(dev, plane,green,greenMask) \ + UpdateDAC(dev, plane,blue,blueMask) + + for (i = 0; i < ndef; i++) + { + CheckDirect (pPriv, SOURCE_COLOR) + CheckDirect (pPriv, MASK_COLOR) + } + } + else + { + /* PseudoColor/GrayScale - match on exact pixel */ + for (i = 0; i < ndef; i++) + { + if (pdef[i].pixel == + pPriv->colors[SOURCE_COLOR].pixel) + { + pPriv->colors[SOURCE_COLOR] = pdef[i]; + if (++updated == 2) + break; + } + if (pdef[i].pixel == + pPriv->colors[MASK_COLOR].pixel) + { + pPriv->colors[MASK_COLOR] = pdef[i]; + if (++updated == 2) + break; + } + } + } + if (updated) + { + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + pCursorInfo->checkPixels = TRUE; + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) + miSpriteRemoveCursor (pDev, pScreen); + } + } + } + } +} + +static void +miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen); + CursorPtr pCursor; + xColorItem *sourceColor, *maskColor; + + pCursor = pDevCursor->pCursor; + sourceColor = &pScreenPriv->colors[SOURCE_COLOR]; + maskColor = &pScreenPriv->colors[MASK_COLOR]; + if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap || + !(pCursor->foreRed == sourceColor->red && + pCursor->foreGreen == sourceColor->green && + pCursor->foreBlue == sourceColor->blue && + pCursor->backRed == maskColor->red && + pCursor->backGreen == maskColor->green && + pCursor->backBlue == maskColor->blue)) + { + pScreenPriv->pColormap = pScreenPriv->pInstalledMap; + sourceColor->red = pCursor->foreRed; + sourceColor->green = pCursor->foreGreen; + sourceColor->blue = pCursor->foreBlue; + FakeAllocColor (pScreenPriv->pColormap, sourceColor); + maskColor->red = pCursor->backRed; + maskColor->green = pCursor->backGreen; + maskColor->blue = pCursor->backBlue; + FakeAllocColor (pScreenPriv->pColormap, maskColor); + /* "free" the pixels right away, don't let this confuse you */ + FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel); + FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel); + } + + pDevCursor->checkPixels = FALSE; + +} + +/* + * miPointer interface routines + */ + +#define SPRITE_PAD 8 + +static Bool +miSpriteRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + miCursorInfoPtr pCursorInfo; + + if (IsFloating(pDev)) + return FALSE; + + pCursorInfo = MISPRITE(pDev); + + if (pCursor == pCursorInfo->pCursor) + pCursorInfo->checkPixels = TRUE; + + return miDCRealizeCursor(pScreen, pCursor); +} + +static Bool +miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + return miDCUnrealizeCursor(pScreen, pCursor); +} + +static void +miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, int x, int y) +{ + miCursorInfoPtr pPointer; + miSpriteScreenPtr pScreenPriv; + + if (IsFloating(pDev)) + return; + + pPointer = MISPRITE(pDev); + pScreenPriv = GetSpriteScreen(pScreen); + + if (!pCursor) + { + if (pPointer->shouldBeUp) + --pScreenPriv->numberOfCursors; + pPointer->shouldBeUp = FALSE; + if (pPointer->isUp) + miSpriteRemoveCursor (pDev, pScreen); + if (pScreenPriv->numberOfCursors == 0) + miSpriteDisableDamage(pScreen, pScreenPriv); + pPointer->pCursor = 0; + return; + } + if (!pPointer->shouldBeUp) + pScreenPriv->numberOfCursors++; + pPointer->shouldBeUp = TRUE; + if (!pPointer->isUp) + miSpriteRegisterBlockHandler(pScreen, pScreenPriv); + if (pPointer->x == x && + pPointer->y == y && + pPointer->pCursor == pCursor && + !pPointer->checkPixels) + { + return; + } + pPointer->x = x; + pPointer->y = y; + pPointer->pCacheWin = NullWindow; + if (pPointer->checkPixels || pPointer->pCursor != pCursor) + { + pPointer->pCursor = pCursor; + miSpriteFindColors (pPointer, pScreen); + } + if (pPointer->isUp) { + /* TODO: reimplement flicker-free MoveCursor */ + SPRITE_DEBUG (("SetCursor remove %d\n", pDev->id)); + miSpriteRemoveCursor (pDev, pScreen); + } + + if (!pPointer->isUp && pPointer->pCursor) + { + SPRITE_DEBUG (("SetCursor restore %d\n", pDev->id)); + miSpriteSaveUnderCursor(pDev, pScreen); + miSpriteRestoreCursor (pDev, pScreen); + } + +} + +static void +miSpriteMoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + CursorPtr pCursor; + + if (IsFloating(pDev)) + return; + + pCursor = MISPRITE(pDev)->pCursor; + + miSpriteSetCursor (pDev, pScreen, pCursor, x, y); +} + + +static Bool +miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miCursorInfoPtr pCursorInfo; + int ret = FALSE; + + pCursorInfo = malloc(sizeof(miCursorInfoRec)); + if (!pCursorInfo) + return FALSE; + + pCursorInfo->pCursor = NULL; + pCursorInfo->x = 0; + pCursorInfo->y = 0; + pCursorInfo->isUp = FALSE; + pCursorInfo->shouldBeUp = FALSE; + pCursorInfo->pCacheWin = NullWindow; + pCursorInfo->isInCacheWin = FALSE; + pCursorInfo->checkPixels = TRUE; + pCursorInfo->pScreen = FALSE; + + ret = miDCDeviceInitialize(pDev, pScreen); + if (!ret) + { + free(pCursorInfo); + pCursorInfo = NULL; + } + dixSetPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey, pCursorInfo); + return ret; +} + +static void +miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + if (DevHasCursor(pDev)) + miDCDeviceCleanup(pDev, pScreen); +} + +/* + * undraw/draw cursor + */ + +static void +miSpriteRemoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv; + miCursorInfoPtr pCursorInfo; + + + if (IsFloating(pDev)) + return; + + DamageDrawInternal (pScreen, TRUE); + pScreenPriv = GetSpriteScreen(pScreen); + pCursorInfo = MISPRITE(pDev); + + miSpriteIsDown(pCursorInfo); + miSpriteRegisterBlockHandler(pScreen, pScreenPriv); + pCursorInfo->pCacheWin = NullWindow; + miSpriteDisableDamage(pScreen, pScreenPriv); + if (!miDCRestoreUnderCursor(pDev, + pScreen, + pCursorInfo->saved.x1, + pCursorInfo->saved.y1, + pCursorInfo->saved.x2 - + pCursorInfo->saved.x1, + pCursorInfo->saved.y2 - + pCursorInfo->saved.y1)) + { + miSpriteIsUp(pCursorInfo); + } + miSpriteEnableDamage(pScreen, pScreenPriv); + DamageDrawInternal (pScreen, FALSE); +} + +/* + * Called from the block handler, saves area under cursor + * before waiting for something to do. + */ + +static void +miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv; + int x, y; + CursorPtr pCursor; + miCursorInfoPtr pCursorInfo; + + if (IsFloating(pDev)) + return; + + DamageDrawInternal (pScreen, TRUE); + pScreenPriv = GetSpriteScreen(pScreen); + pCursorInfo = MISPRITE(pDev); + + miSpriteComputeSaved (pDev, pScreen); + pCursor = pCursorInfo->pCursor; + + x = pCursorInfo->x - (int)pCursor->bits->xhot; + y = pCursorInfo->y - (int)pCursor->bits->yhot; + miSpriteDisableDamage(pScreen, pScreenPriv); + + miDCSaveUnderCursor(pDev, + pScreen, + pCursorInfo->saved.x1, + pCursorInfo->saved.y1, + pCursorInfo->saved.x2 - + pCursorInfo->saved.x1, + pCursorInfo->saved.y2 - + pCursorInfo->saved.y1); + SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id)); + miSpriteEnableDamage(pScreen, pScreenPriv); + DamageDrawInternal (pScreen, FALSE); +} + + +/* + * Called from the block handler, restores the cursor + * before waiting for something to do. + */ + +static void +miSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miSpriteScreenPtr pScreenPriv; + int x, y; + CursorPtr pCursor; + miCursorInfoPtr pCursorInfo; + + if (IsFloating(pDev)) + return; + + DamageDrawInternal (pScreen, TRUE); + pScreenPriv = GetSpriteScreen(pScreen); + pCursorInfo = MISPRITE(pDev); + + miSpriteComputeSaved (pDev, pScreen); + pCursor = pCursorInfo->pCursor; + + x = pCursorInfo->x - (int)pCursor->bits->xhot; + y = pCursorInfo->y - (int)pCursor->bits->yhot; + miSpriteDisableDamage(pScreen, pScreenPriv); + SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id)); + if (pCursorInfo->checkPixels) + miSpriteFindColors (pCursorInfo, pScreen); + if (miDCPutUpCursor(pDev, pScreen, + pCursor, x, y, + pScreenPriv->colors[SOURCE_COLOR].pixel, + pScreenPriv->colors[MASK_COLOR].pixel)) + { + miSpriteIsUp(pCursorInfo); + pCursorInfo->pScreen = pScreen; + } + miSpriteEnableDamage(pScreen, pScreenPriv); + DamageDrawInternal (pScreen, FALSE); +} + +/* + * compute the desired area of the screen to save + */ + +static void +miSpriteComputeSaved (DeviceIntPtr pDev, ScreenPtr pScreen) +{ + int x, y, w, h; + int wpad, hpad; + CursorPtr pCursor; + miCursorInfoPtr pCursorInfo; + + if (IsFloating(pDev)) + return; + + pCursorInfo = MISPRITE(pDev); + + pCursor = pCursorInfo->pCursor; + x = pCursorInfo->x - (int)pCursor->bits->xhot; + y = pCursorInfo->y - (int)pCursor->bits->yhot; + w = pCursor->bits->width; + h = pCursor->bits->height; + wpad = SPRITE_PAD; + hpad = SPRITE_PAD; + pCursorInfo->saved.x1 = x - wpad; + pCursorInfo->saved.y1 = y - hpad; + pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2; + pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2; +} + |