mipointer.c revision 4642e01f
105b261ecSmrg/*
205b261ecSmrg
305b261ecSmrgCopyright 1989, 1998  The Open Group
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthe above copyright notice appear in all copies and that both that
805b261ecSmrgcopyright notice and this permission notice appear in supporting
905b261ecSmrgdocumentation.
1005b261ecSmrg
1105b261ecSmrgThe above copyright notice and this permission notice shall be included in
1205b261ecSmrgall copies or substantial portions of the Software.
1305b261ecSmrg
1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2005b261ecSmrg
2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be
2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings
2305b261ecSmrgin this Software without prior written authorization from The Open Group.
2405b261ecSmrg*/
2505b261ecSmrg
2605b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2705b261ecSmrg#include <dix-config.h>
2805b261ecSmrg#endif
2905b261ecSmrg
3005b261ecSmrg# define NEED_EVENTS
3105b261ecSmrg# include   <X11/X.h>
3205b261ecSmrg# include   <X11/Xmd.h>
3305b261ecSmrg# include   <X11/Xproto.h>
3405b261ecSmrg# include   "misc.h"
3505b261ecSmrg# include   "windowstr.h"
3605b261ecSmrg# include   "pixmapstr.h"
3705b261ecSmrg# include   "mi.h"
3805b261ecSmrg# include   "scrnintstr.h"
3905b261ecSmrg# include   "mipointrst.h"
4005b261ecSmrg# include   "cursorstr.h"
4105b261ecSmrg# include   "dixstruct.h"
4205b261ecSmrg# include   "inputstr.h"
4305b261ecSmrg
444642e01fSmrgstatic int miPointerScreenKeyIndex;
454642e01fSmrg_X_EXPORT DevPrivateKey miPointerScreenKey = &miPointerScreenKeyIndex;
4605b261ecSmrg
474642e01fSmrg#define GetScreenPrivate(s) ((miPointerScreenPtr) \
484642e01fSmrg    dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey))
4905b261ecSmrg#define SetupScreen(s)	miPointerScreenPtr  pScreenPriv = GetScreenPrivate(s)
5005b261ecSmrg
514642e01fSmrgstatic int miPointerPrivKeyIndex;
524642e01fSmrgstatic DevPrivateKey miPointerPrivKey = &miPointerPrivKeyIndex;
534642e01fSmrg
544642e01fSmrg#define MIPOINTER(dev) \
554642e01fSmrg    ((DevHasCursor((dev)) || (!dev->isMaster && !dev->u.master)) ? \
564642e01fSmrg        (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
574642e01fSmrg        (miPointerPtr)dixLookupPrivate(&(dev)->u.master->devPrivates, miPointerPrivKey))
584642e01fSmrg
594642e01fSmrgstatic Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
604642e01fSmrg                                   CursorPtr pCursor);
614642e01fSmrgstatic Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
624642e01fSmrg                                     CursorPtr pCursor);
634642e01fSmrgstatic Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
644642e01fSmrg                                   CursorPtr pCursor);
654642e01fSmrgstatic void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
664642e01fSmrg                                     BoxPtr pBox);
674642e01fSmrgstatic void miPointerPointerNonInterestBox(DeviceIntPtr pDev,
684642e01fSmrg                                           ScreenPtr pScreen, BoxPtr pBox);
694642e01fSmrgstatic void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen,
704642e01fSmrg                                  CursorPtr pCursor, BoxPtr pHotBox,
714642e01fSmrg                                  BoxPtr pTopLeftBox);
724642e01fSmrgstatic Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
734642e01fSmrg                                       int x, int y,
7405b261ecSmrg				       Bool generateEvent);
7505b261ecSmrgstatic Bool miPointerCloseScreen(int index, ScreenPtr pScreen);
764642e01fSmrgstatic void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen,
774642e01fSmrg                          int x, int y);
784642e01fSmrgstatic Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
794642e01fSmrgstatic void miPointerDeviceCleanup(DeviceIntPtr pDev,
804642e01fSmrg                                   ScreenPtr pScreen);
8105b261ecSmrg
824642e01fSmrgstatic EventList* events; /* for WarpPointer MotionNotifies */
8305b261ecSmrg
8405b261ecSmrg_X_EXPORT Bool
854642e01fSmrgmiPointerInitialize (ScreenPtr                  pScreen,
864642e01fSmrg                     miPointerSpriteFuncPtr     spriteFuncs,
874642e01fSmrg                     miPointerScreenFuncPtr     screenFuncs,
884642e01fSmrg                     Bool                       waitForUpdate)
8905b261ecSmrg{
9005b261ecSmrg    miPointerScreenPtr	pScreenPriv;
9105b261ecSmrg
9205b261ecSmrg    pScreenPriv = (miPointerScreenPtr) xalloc (sizeof (miPointerScreenRec));
9305b261ecSmrg    if (!pScreenPriv)
9405b261ecSmrg	return FALSE;
9505b261ecSmrg    pScreenPriv->spriteFuncs = spriteFuncs;
9605b261ecSmrg    pScreenPriv->screenFuncs = screenFuncs;
9705b261ecSmrg    /*
9805b261ecSmrg     * check for uninitialized methods
9905b261ecSmrg     */
10005b261ecSmrg    if (!screenFuncs->EnqueueEvent)
10105b261ecSmrg	screenFuncs->EnqueueEvent = mieqEnqueue;
10205b261ecSmrg    if (!screenFuncs->NewEventScreen)
10305b261ecSmrg	screenFuncs->NewEventScreen = mieqSwitchScreen;
10405b261ecSmrg    pScreenPriv->waitForUpdate = waitForUpdate;
10505b261ecSmrg    pScreenPriv->showTransparent = FALSE;
10605b261ecSmrg    pScreenPriv->CloseScreen = pScreen->CloseScreen;
10705b261ecSmrg    pScreen->CloseScreen = miPointerCloseScreen;
1084642e01fSmrg    dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv);
10905b261ecSmrg    /*
11005b261ecSmrg     * set up screen cursor method table
11105b261ecSmrg     */
11205b261ecSmrg    pScreen->ConstrainCursor = miPointerConstrainCursor;
11305b261ecSmrg    pScreen->CursorLimits = miPointerCursorLimits;
11405b261ecSmrg    pScreen->DisplayCursor = miPointerDisplayCursor;
11505b261ecSmrg    pScreen->RealizeCursor = miPointerRealizeCursor;
11605b261ecSmrg    pScreen->UnrealizeCursor = miPointerUnrealizeCursor;
11705b261ecSmrg    pScreen->SetCursorPosition = miPointerSetCursorPosition;
11805b261ecSmrg    pScreen->RecolorCursor = miRecolorCursor;
11905b261ecSmrg    pScreen->PointerNonInterestBox = miPointerPointerNonInterestBox;
1204642e01fSmrg    pScreen->DeviceCursorInitialize = miPointerDeviceInitialize;
1214642e01fSmrg    pScreen->DeviceCursorCleanup = miPointerDeviceCleanup;
12205b261ecSmrg
12305b261ecSmrg    events = NULL;
12405b261ecSmrg    return TRUE;
12505b261ecSmrg}
12605b261ecSmrg
12705b261ecSmrgstatic Bool
1284642e01fSmrgmiPointerCloseScreen (int index, ScreenPtr pScreen)
12905b261ecSmrg{
1304642e01fSmrg#if 0
1314642e01fSmrg    miPointerPtr pPointer;
1324642e01fSmrg    DeviceIntPtr pDev;
1334642e01fSmrg#endif
1344642e01fSmrg
13505b261ecSmrg    SetupScreen(pScreen);
13605b261ecSmrg
1374642e01fSmrg#if 0
1384642e01fSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
1394642e01fSmrg    {
1404642e01fSmrg        if (DevHasCursor(pDev))
1414642e01fSmrg        {
1424642e01fSmrg            pPointer = MIPOINTER(pDev);
1434642e01fSmrg
1444642e01fSmrg            if (pScreen == pPointer->pScreen)
1454642e01fSmrg                pPointer->pScreen = 0;
1464642e01fSmrg            if (pScreen == pPointer->pSpriteScreen)
1474642e01fSmrg                pPointer->pSpriteScreen = 0;
1484642e01fSmrg        }
1494642e01fSmrg    }
1504642e01fSmrg
1514642e01fSmrg    if (MIPOINTER(inputInfo.pointer)->pScreen == pScreen)
1524642e01fSmrg        MIPOINTER(inputInfo.pointer)->pScreen = 0;
1534642e01fSmrg    if (MIPOINTER(inputInfo.pointer)->pSpriteScreen == pScreen)
1544642e01fSmrg        MIPOINTER(inputInfo.pointer)->pSpriteScreen = 0;
1554642e01fSmrg#endif
1564642e01fSmrg
15705b261ecSmrg    pScreen->CloseScreen = pScreenPriv->CloseScreen;
15805b261ecSmrg    xfree ((pointer) pScreenPriv);
1594642e01fSmrg    FreeEventList(events, GetMaximumEventsNum());
16005b261ecSmrg    events = NULL;
16105b261ecSmrg    return (*pScreen->CloseScreen) (index, pScreen);
16205b261ecSmrg}
16305b261ecSmrg
16405b261ecSmrg/*
16505b261ecSmrg * DIX/DDX interface routines
16605b261ecSmrg */
16705b261ecSmrg
16805b261ecSmrgstatic Bool
1694642e01fSmrgmiPointerRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
17005b261ecSmrg{
17105b261ecSmrg    SetupScreen(pScreen);
1724642e01fSmrg    return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor);
17305b261ecSmrg}
17405b261ecSmrg
17505b261ecSmrgstatic Bool
1764642e01fSmrgmiPointerUnrealizeCursor (DeviceIntPtr  pDev,
1774642e01fSmrg                          ScreenPtr     pScreen,
1784642e01fSmrg                          CursorPtr     pCursor)
17905b261ecSmrg{
18005b261ecSmrg    SetupScreen(pScreen);
1814642e01fSmrg    return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor);
18205b261ecSmrg}
18305b261ecSmrg
18405b261ecSmrgstatic Bool
1854642e01fSmrgmiPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
18605b261ecSmrg{
1874642e01fSmrg    miPointerPtr pPointer;
1884642e01fSmrg
1894642e01fSmrg    /* return for keyboards */
1904642e01fSmrg    if ((pDev->isMaster && !DevHasCursor(pDev)) ||
1914642e01fSmrg        (!pDev->isMaster && pDev->u.master && !DevHasCursor(pDev->u.master)))
1924642e01fSmrg            return FALSE;
1934642e01fSmrg
1944642e01fSmrg    pPointer = MIPOINTER(pDev);
1954642e01fSmrg
1964642e01fSmrg    pPointer->pCursor = pCursor;
1974642e01fSmrg    pPointer->pScreen = pScreen;
1984642e01fSmrg    miPointerUpdateSprite(pDev);
19905b261ecSmrg    return TRUE;
20005b261ecSmrg}
20105b261ecSmrg
20205b261ecSmrgstatic void
2034642e01fSmrgmiPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox)
20405b261ecSmrg{
2054642e01fSmrg    miPointerPtr pPointer;
2064642e01fSmrg
2074642e01fSmrg    pPointer = MIPOINTER(pDev);
2084642e01fSmrg
2094642e01fSmrg    pPointer->limits = *pBox;
2104642e01fSmrg    pPointer->confined = PointerConfinedToScreen(pDev);
21105b261ecSmrg}
21205b261ecSmrg
21305b261ecSmrg/*ARGSUSED*/
21405b261ecSmrgstatic void
2154642e01fSmrgmiPointerPointerNonInterestBox (DeviceIntPtr    pDev,
2164642e01fSmrg                                ScreenPtr       pScreen,
2174642e01fSmrg                                BoxPtr          pBox)
21805b261ecSmrg{
21905b261ecSmrg    /* until DIX uses this, this will remain a stub */
22005b261ecSmrg}
22105b261ecSmrg
22205b261ecSmrg/*ARGSUSED*/
22305b261ecSmrgstatic void
2244642e01fSmrgmiPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
2254642e01fSmrg                      BoxPtr pHotBox, BoxPtr pTopLeftBox)
22605b261ecSmrg{
22705b261ecSmrg    *pTopLeftBox = *pHotBox;
22805b261ecSmrg}
22905b261ecSmrg
23005b261ecSmrgstatic Bool GenerateEvent;
23105b261ecSmrg
23205b261ecSmrgstatic Bool
2334642e01fSmrgmiPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
2344642e01fSmrg                           int x, int y, Bool generateEvent)
23505b261ecSmrg{
23605b261ecSmrg    SetupScreen (pScreen);
23705b261ecSmrg
23805b261ecSmrg    GenerateEvent = generateEvent;
23905b261ecSmrg    /* device dependent - must pend signal and call miPointerWarpCursor */
2404642e01fSmrg    (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y);
24105b261ecSmrg    if (!generateEvent)
2424642e01fSmrg	miPointerUpdateSprite(pDev);
24305b261ecSmrg    return TRUE;
24405b261ecSmrg}
24505b261ecSmrg
2464642e01fSmrg/* Set up sprite information for the device.
2474642e01fSmrg   This function will be called once for each device after it is initialized
2484642e01fSmrg   in the DIX.
2494642e01fSmrg */
2504642e01fSmrgstatic Bool
2514642e01fSmrgmiPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
2524642e01fSmrg{
2534642e01fSmrg    miPointerPtr pPointer;
2544642e01fSmrg    SetupScreen (pScreen);
2554642e01fSmrg
2564642e01fSmrg    pPointer = xalloc(sizeof(miPointerRec));
2574642e01fSmrg    if (!pPointer)
2584642e01fSmrg        return FALSE;
2594642e01fSmrg
2604642e01fSmrg    pPointer->pScreen = NULL;
2614642e01fSmrg    pPointer->pSpriteScreen = NULL;
2624642e01fSmrg    pPointer->pCursor = NULL;
2634642e01fSmrg    pPointer->pSpriteCursor = NULL;
2644642e01fSmrg    pPointer->limits.x1 = 0;
2654642e01fSmrg    pPointer->limits.x2 = 32767;
2664642e01fSmrg    pPointer->limits.y1 = 0;
2674642e01fSmrg    pPointer->limits.y2 = 32767;
2684642e01fSmrg    pPointer->confined = FALSE;
2694642e01fSmrg    pPointer->x = 0;
2704642e01fSmrg    pPointer->y = 0;
2714642e01fSmrg
2724642e01fSmrg    if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen)))
2734642e01fSmrg    {
2744642e01fSmrg        xfree(pPointer);
2754642e01fSmrg        return FALSE;
2764642e01fSmrg    }
2774642e01fSmrg
2784642e01fSmrg    dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer);
2794642e01fSmrg    return TRUE;
2804642e01fSmrg}
2814642e01fSmrg
2824642e01fSmrg/* Clean up after device.
2834642e01fSmrg   This function will be called once before the device is freed in the DIX
2844642e01fSmrg */
2854642e01fSmrgstatic void
2864642e01fSmrgmiPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
2874642e01fSmrg{
2884642e01fSmrg    if (!pDev->isMaster && pDev->u.master)
2894642e01fSmrg        return;
2904642e01fSmrg
2914642e01fSmrg    SetupScreen(pScreen);
2924642e01fSmrg    (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
2934642e01fSmrg    xfree(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey));
2944642e01fSmrg    dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL);
2954642e01fSmrg}
2964642e01fSmrg
2974642e01fSmrg
29805b261ecSmrg/* Once signals are ignored, the WarpCursor function can call this */
29905b261ecSmrg
30005b261ecSmrg_X_EXPORT void
3014642e01fSmrgmiPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
30205b261ecSmrg{
3034642e01fSmrg    miPointerPtr pPointer;
3044642e01fSmrg    BOOL changedScreen = FALSE;
3054642e01fSmrg
3064642e01fSmrg    pPointer = MIPOINTER(pDev);
30705b261ecSmrg    SetupScreen (pScreen);
30805b261ecSmrg
3094642e01fSmrg    if (pPointer->pScreen != pScreen)
3104642e01fSmrg    {
3114642e01fSmrg	(*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE);
3124642e01fSmrg        changedScreen = TRUE;
3134642e01fSmrg    }
31405b261ecSmrg
31505b261ecSmrg    if (GenerateEvent)
31605b261ecSmrg    {
3174642e01fSmrg	miPointerMove (pDev, pScreen, x, y);
31805b261ecSmrg    }
31905b261ecSmrg    else
32005b261ecSmrg    {
32105b261ecSmrg	/* everything from miPointerMove except the event and history */
32205b261ecSmrg
3234642e01fSmrg    	if (!pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
32405b261ecSmrg    	{
3254642e01fSmrg	    pPointer->devx = x;
3264642e01fSmrg	    pPointer->devy = y;
3274642e01fSmrg	    if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
3284642e01fSmrg		(*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
32905b261ecSmrg    	}
3304642e01fSmrg	pPointer->x = x;
3314642e01fSmrg	pPointer->y = y;
3324642e01fSmrg	pPointer->pScreen = pScreen;
33305b261ecSmrg    }
3344642e01fSmrg
3354642e01fSmrg    /* Don't call USFS if we use Xinerama, otherwise the root window is
3364642e01fSmrg     * updated to the second screen, and we never receive any events.
3374642e01fSmrg     * (FDO bug #18668) */
3384642e01fSmrg    if (changedScreen
3394642e01fSmrg#ifdef PANORAMIX
3404642e01fSmrg            && noPanoramiXExtension
3414642e01fSmrg#endif
3424642e01fSmrg       )
3434642e01fSmrg        UpdateSpriteForScreen (pDev, pScreen) ;
34405b261ecSmrg}
34505b261ecSmrg
34605b261ecSmrg/*
34705b261ecSmrg * Pointer/CursorDisplay interface routines
34805b261ecSmrg */
34905b261ecSmrg
35005b261ecSmrg/*
3514642e01fSmrg * miPointerUpdateSprite
35205b261ecSmrg *
35305b261ecSmrg * Syncronize the sprite with the cursor - called from ProcessInputEvents
35405b261ecSmrg */
35505b261ecSmrg
35605b261ecSmrgvoid
35705b261ecSmrgmiPointerUpdateSprite (DeviceIntPtr pDev)
35805b261ecSmrg{
35905b261ecSmrg    ScreenPtr		pScreen;
36005b261ecSmrg    miPointerScreenPtr	pScreenPriv;
36105b261ecSmrg    CursorPtr		pCursor;
36205b261ecSmrg    int			x, y, devx, devy;
3634642e01fSmrg    miPointerPtr        pPointer;
36405b261ecSmrg
3654642e01fSmrg    if (!pDev || !pDev->coreEvents)
36605b261ecSmrg        return;
36705b261ecSmrg
3684642e01fSmrg    pPointer = MIPOINTER(pDev);
3694642e01fSmrg
3704642e01fSmrg    pScreen = pPointer->pScreen;
37105b261ecSmrg    if (!pScreen)
37205b261ecSmrg	return;
37305b261ecSmrg
3744642e01fSmrg    x = pPointer->x;
3754642e01fSmrg    y = pPointer->y;
3764642e01fSmrg    devx = pPointer->devx;
3774642e01fSmrg    devy = pPointer->devy;
37805b261ecSmrg
37905b261ecSmrg    pScreenPriv = GetScreenPrivate (pScreen);
38005b261ecSmrg    /*
38105b261ecSmrg     * if the cursor has switched screens, disable the sprite
38205b261ecSmrg     * on the old screen
38305b261ecSmrg     */
3844642e01fSmrg    if (pScreen != pPointer->pSpriteScreen)
38505b261ecSmrg    {
3864642e01fSmrg	if (pPointer->pSpriteScreen)
38705b261ecSmrg	{
38805b261ecSmrg	    miPointerScreenPtr  pOldPriv;
38905b261ecSmrg
3904642e01fSmrg	    pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen);
3914642e01fSmrg	    if (pPointer->pCursor)
39205b261ecSmrg	    {
39305b261ecSmrg	    	(*pOldPriv->spriteFuncs->SetCursor)
3944642e01fSmrg			    	(pDev, pPointer->pSpriteScreen, NullCursor, 0, 0);
39505b261ecSmrg	    }
3964642e01fSmrg	    (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE);
39705b261ecSmrg	}
39805b261ecSmrg	(*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
39905b261ecSmrg	(*pScreenPriv->spriteFuncs->SetCursor)
4004642e01fSmrg				(pDev, pScreen, pPointer->pCursor, x, y);
4014642e01fSmrg	pPointer->devx = x;
4024642e01fSmrg	pPointer->devy = y;
4034642e01fSmrg	pPointer->pSpriteCursor = pPointer->pCursor;
4044642e01fSmrg	pPointer->pSpriteScreen = pScreen;
40505b261ecSmrg    }
40605b261ecSmrg    /*
40705b261ecSmrg     * if the cursor has changed, display the new one
40805b261ecSmrg     */
4094642e01fSmrg    else if (pPointer->pCursor != pPointer->pSpriteCursor)
41005b261ecSmrg    {
4114642e01fSmrg	pCursor = pPointer->pCursor;
4124642e01fSmrg	if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent))
41305b261ecSmrg	    pCursor = NullCursor;
4144642e01fSmrg	(*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y);
41505b261ecSmrg
4164642e01fSmrg	pPointer->devx = x;
4174642e01fSmrg	pPointer->devy = y;
4184642e01fSmrg	pPointer->pSpriteCursor = pPointer->pCursor;
41905b261ecSmrg    }
42005b261ecSmrg    else if (x != devx || y != devy)
42105b261ecSmrg    {
4224642e01fSmrg	pPointer->devx = x;
4234642e01fSmrg	pPointer->devy = y;
4244642e01fSmrg	if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
4254642e01fSmrg	    (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
42605b261ecSmrg    }
42705b261ecSmrg}
42805b261ecSmrg
42905b261ecSmrgvoid
43005b261ecSmrgmiPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
43105b261ecSmrg{
43205b261ecSmrg	miPointerScreenPtr pScreenPriv;
43305b261ecSmrg	ScreenPtr pScreen;
4344642e01fSmrg        miPointerPtr pPointer;
4354642e01fSmrg
4364642e01fSmrg        pPointer = MIPOINTER(pDev);
43705b261ecSmrg
43805b261ecSmrg	pScreen = screenInfo.screens[screen_no];
43905b261ecSmrg	pScreenPriv = GetScreenPrivate (pScreen);
4404642e01fSmrg	(*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE);
4414642e01fSmrg	NewCurrentScreen (pDev, pScreen, x, y);
4424642e01fSmrg
4434642e01fSmrg        pPointer->limits.x2 = pScreen->width;
4444642e01fSmrg        pPointer->limits.y2 = pScreen->height;
44505b261ecSmrg}
44605b261ecSmrg
44705b261ecSmrg_X_EXPORT ScreenPtr
44805b261ecSmrgmiPointerCurrentScreen ()
44905b261ecSmrg{
45005b261ecSmrg    return miPointerGetScreen(inputInfo.pointer);
45105b261ecSmrg}
45205b261ecSmrg
45305b261ecSmrg_X_EXPORT ScreenPtr
45405b261ecSmrgmiPointerGetScreen(DeviceIntPtr pDev)
45505b261ecSmrg{
4564642e01fSmrg    miPointerPtr pPointer = MIPOINTER(pDev);
4574642e01fSmrg    return (pPointer) ? pPointer->pScreen : NULL;
45805b261ecSmrg}
45905b261ecSmrg
46005b261ecSmrg/* Move the pointer to x, y on the current screen, update the sprite, and
46105b261ecSmrg * the motion history.  Generates no events.  Does not return changed x
46205b261ecSmrg * and y if they are clipped; use miPointerSetPosition instead. */
46305b261ecSmrg_X_EXPORT void
46405b261ecSmrgmiPointerAbsoluteCursor (int x, int y, unsigned long time)
46505b261ecSmrg{
4664642e01fSmrg    miPointerSetPosition(inputInfo.pointer, &x, &y);
46705b261ecSmrg}
46805b261ecSmrg
46905b261ecSmrg/* Move the pointer on the current screen,  and update the sprite. */
47005b261ecSmrgstatic void
4714642e01fSmrgmiPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen,
4724642e01fSmrg                int x, int y)
47305b261ecSmrg{
4744642e01fSmrg    miPointerPtr pPointer;
47505b261ecSmrg    SetupScreen(pScreen);
47605b261ecSmrg
4774642e01fSmrg    pPointer = MIPOINTER(pDev);
4784642e01fSmrg
4794642e01fSmrg    /* Hack: We mustn't call into ->MoveCursor for anything but the
4804642e01fSmrg     * VCP, as this may cause a non-HW rendered cursor to be rendered during
4814642e01fSmrg     * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT.
4824642e01fSmrg     */
4834642e01fSmrg    if ((pDev == inputInfo.pointer || (!pDev->isMaster && pDev->u.master == inputInfo.pointer))
4844642e01fSmrg        && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
48505b261ecSmrg    {
4864642e01fSmrg	pPointer->devx = x;
4874642e01fSmrg	pPointer->devy = y;
4884642e01fSmrg	if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
4894642e01fSmrg	    (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
49005b261ecSmrg    }
49105b261ecSmrg
4924642e01fSmrg    pPointer->x = x;
4934642e01fSmrg    pPointer->y = y;
4944642e01fSmrg    pPointer->pScreen = pScreen;
49505b261ecSmrg}
49605b261ecSmrg
49705b261ecSmrg_X_EXPORT void
4984642e01fSmrgmiPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
49905b261ecSmrg{
50005b261ecSmrg    miPointerScreenPtr	pScreenPriv;
50105b261ecSmrg    ScreenPtr		pScreen;
50205b261ecSmrg    ScreenPtr		newScreen;
50305b261ecSmrg
5044642e01fSmrg    miPointerPtr        pPointer;
5054642e01fSmrg
5064642e01fSmrg    pPointer = MIPOINTER(pDev);
5074642e01fSmrg    pScreen = pPointer->pScreen;
50805b261ecSmrg    if (!pScreen)
50905b261ecSmrg	return;	    /* called before ready */
51005b261ecSmrg
5114642e01fSmrg    if (!pDev || !pDev->coreEvents)
51205b261ecSmrg        return;
51305b261ecSmrg
51405b261ecSmrg    if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
51505b261ecSmrg    {
51605b261ecSmrg	pScreenPriv = GetScreenPrivate (pScreen);
5174642e01fSmrg	if (!pPointer->confined)
51805b261ecSmrg	{
51905b261ecSmrg	    newScreen = pScreen;
52005b261ecSmrg	    (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y);
52105b261ecSmrg	    if (newScreen != pScreen)
52205b261ecSmrg	    {
52305b261ecSmrg		pScreen = newScreen;
5244642e01fSmrg		(*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen,
5254642e01fSmrg							     FALSE);
52605b261ecSmrg		pScreenPriv = GetScreenPrivate (pScreen);
52705b261ecSmrg	    	/* Smash the confine to the new screen */
5284642e01fSmrg                pPointer->limits.x2 = pScreen->width;
5294642e01fSmrg                pPointer->limits.y2 = pScreen->height;
53005b261ecSmrg	    }
53105b261ecSmrg	}
53205b261ecSmrg    }
53305b261ecSmrg    /* Constrain the sprite to the current limits. */
5344642e01fSmrg    if (*x < pPointer->limits.x1)
5354642e01fSmrg	*x = pPointer->limits.x1;
5364642e01fSmrg    if (*x >= pPointer->limits.x2)
5374642e01fSmrg	*x = pPointer->limits.x2 - 1;
5384642e01fSmrg    if (*y < pPointer->limits.y1)
5394642e01fSmrg	*y = pPointer->limits.y1;
5404642e01fSmrg    if (*y >= pPointer->limits.y2)
5414642e01fSmrg	*y = pPointer->limits.y2 - 1;
5424642e01fSmrg
5434642e01fSmrg    if (pPointer->x == *x && pPointer->y == *y &&
5444642e01fSmrg            pPointer->pScreen == pScreen)
5454642e01fSmrg        return;
54605b261ecSmrg
5474642e01fSmrg    miPointerMoved(pDev, pScreen, *x, *y);
54805b261ecSmrg}
54905b261ecSmrg
55005b261ecSmrg_X_EXPORT void
55105b261ecSmrgmiPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
55205b261ecSmrg{
5534642e01fSmrg    *x = MIPOINTER(pDev)->x;
5544642e01fSmrg    *y = MIPOINTER(pDev)->y;
55505b261ecSmrg}
55605b261ecSmrg
5574642e01fSmrg#ifdef XQUARTZ
5584642e01fSmrg#include <pthread.h>
5594642e01fSmrgvoid darwinEvents_lock(void);
5604642e01fSmrgvoid darwinEvents_unlock(void);
5614642e01fSmrg#endif
5624642e01fSmrg
56305b261ecSmrgvoid
5644642e01fSmrgmiPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
56505b261ecSmrg{
56605b261ecSmrg    int i, nevents;
56705b261ecSmrg    int valuators[2];
56805b261ecSmrg
5694642e01fSmrg    miPointerMoved(pDev, pScreen, x, y);
57005b261ecSmrg
57105b261ecSmrg    /* generate motion notify */
57205b261ecSmrg    valuators[0] = x;
57305b261ecSmrg    valuators[1] = y;
57405b261ecSmrg
57505b261ecSmrg    if (!events)
57605b261ecSmrg    {
5774642e01fSmrg        events = InitEventList(GetMaximumEventsNum());
57805b261ecSmrg
57905b261ecSmrg        if (!events)
58005b261ecSmrg        {
58105b261ecSmrg            FatalError("Could not allocate event store.\n");
58205b261ecSmrg            return;
58305b261ecSmrg        }
58405b261ecSmrg    }
58505b261ecSmrg
5864642e01fSmrg    nevents = GetPointerEvents(events, pDev, MotionNotify, 0, POINTER_SCREEN | POINTER_ABSOLUTE, 0, 2, valuators);
58705b261ecSmrg
5884642e01fSmrg    OsBlockSignals();
5894642e01fSmrg#ifdef XQUARTZ
5904642e01fSmrg    darwinEvents_lock();
5914642e01fSmrg#endif
59205b261ecSmrg    for (i = 0; i < nevents; i++)
5934642e01fSmrg        mieqEnqueue(pDev, events[i].event);
5944642e01fSmrg#ifdef XQUARTZ
5954642e01fSmrg    darwinEvents_unlock();
5964642e01fSmrg#endif
5974642e01fSmrg    OsReleaseSignals();
59805b261ecSmrg}
599