aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/mi
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2011-03-15 21:35:41 +0000
committermarha <marha@users.sourceforge.net>2011-03-15 21:35:41 +0000
commit5e633abcca598289d0423d89bb400b41e6417259 (patch)
tree74258f0d1f9f5f2b171d16fd9654a13803216c6f /xorg-server/mi
parentb5d1fd89898edb34f73679b542c754d837d44cf8 (diff)
downloadvcxsrv-5e633abcca598289d0423d89bb400b41e6417259.tar.gz
vcxsrv-5e633abcca598289d0423d89bb400b41e6417259.tar.bz2
vcxsrv-5e633abcca598289d0423d89bb400b41e6417259.zip
xserver libX11 libxcb mesa git update 15 Mar 2011
Diffstat (limited to 'xorg-server/mi')
-rw-r--r--xorg-server/mi/mipointer.c1386
-rw-r--r--xorg-server/mi/mipointer.h1
-rw-r--r--xorg-server/mi/misprite.c2087
3 files changed, 1741 insertions, 1733 deletions
diff --git a/xorg-server/mi/mipointer.c b/xorg-server/mi/mipointer.c
index 209ea06be..e8ed106ea 100644
--- a/xorg-server/mi/mipointer.c
+++ b/xorg-server/mi/mipointer.c
@@ -1,688 +1,698 @@
-/*
-
-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();
-}
+/*
+
+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;
+
+ if (pScreen->ConstrainCursorHarder)
+ pScreen->ConstrainCursorHarder(pDev, pScreen, Absolute, &x, &y);
+
+ /* 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).
+ *
+ * The coordinates provided are always absolute. The parameter mode whether
+ * it was relative or absolute movement that landed us at those coordinates.
+ *
+ * @param pDev The device to move
+ * @param mode Movement mode (Absolute or Relative)
+ * @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 mode, 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 (pScreen->ConstrainCursorHarder)
+ pScreen->ConstrainCursorHarder(pDev, pScreen, mode, x, y);
+
+ 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/mipointer.h b/xorg-server/mi/mipointer.h
index caf505019..426ef1650 100644
--- a/xorg-server/mi/mipointer.h
+++ b/xorg-server/mi/mipointer.h
@@ -133,6 +133,7 @@ extern _X_EXPORT void miPointerGetPosition(
* x and y are modified in-place. */
extern _X_EXPORT void miPointerSetPosition(
DeviceIntPtr pDev,
+ int mode,
int *x,
int *y);
diff --git a/xorg-server/mi/misprite.c b/xorg-server/mi/misprite.c
index b0290af29..0b47592f0 100644
--- a/xorg-server/mi/misprite.c
+++ b/xorg-server/mi/misprite.c
@@ -1,1045 +1,1042 @@
-/*
- * 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;
-}
-
+/*
+ * 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, sizeof(miCursorInfoRec)))
+ 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)
+{
+ int ret = miDCDeviceInitialize(pDev, pScreen);
+
+ if (ret)
+ {
+ miCursorInfoPtr pCursorInfo;
+ pCursorInfo = dixLookupPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey);
+ 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;
+ }
+
+ return ret;
+}
+
+static void
+miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
+{
+ miCursorInfoPtr pCursorInfo = dixLookupPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey);
+
+ if (DevHasCursor(pDev))
+ miDCDeviceCleanup(pDev, pScreen);
+
+ memset(pCursorInfo, 0, sizeof(miCursorInfoRec));
+}
+
+/*
+ * 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;
+}
+