mipointer.c revision 6747b715
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# include   <X11/X.h>
3105b261ecSmrg# include   <X11/Xmd.h>
3205b261ecSmrg# include   <X11/Xproto.h>
3305b261ecSmrg# include   "misc.h"
3405b261ecSmrg# include   "windowstr.h"
3505b261ecSmrg# include   "pixmapstr.h"
3605b261ecSmrg# include   "mi.h"
3705b261ecSmrg# include   "scrnintstr.h"
3805b261ecSmrg# include   "mipointrst.h"
3905b261ecSmrg# include   "cursorstr.h"
4005b261ecSmrg# include   "dixstruct.h"
4105b261ecSmrg# include   "inputstr.h"
4205b261ecSmrg
436747b715SmrgDevPrivateKeyRec miPointerScreenKeyRec;
4405b261ecSmrg
454642e01fSmrg#define GetScreenPrivate(s) ((miPointerScreenPtr) \
464642e01fSmrg    dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey))
4705b261ecSmrg#define SetupScreen(s)	miPointerScreenPtr  pScreenPriv = GetScreenPrivate(s)
4805b261ecSmrg
496747b715SmrgDevPrivateKeyRec miPointerPrivKeyRec;
504642e01fSmrg
514642e01fSmrg#define MIPOINTER(dev) \
526747b715Smrg    ((!IsMaster(dev) && !dev->u.master) ? \
534642e01fSmrg        (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
546747b715Smrg        (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey))
554642e01fSmrg
564642e01fSmrgstatic Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
574642e01fSmrg                                   CursorPtr pCursor);
584642e01fSmrgstatic Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
594642e01fSmrg                                     CursorPtr pCursor);
604642e01fSmrgstatic Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
614642e01fSmrg                                   CursorPtr pCursor);
624642e01fSmrgstatic void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
634642e01fSmrg                                     BoxPtr pBox);
644642e01fSmrgstatic void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen,
654642e01fSmrg                                  CursorPtr pCursor, BoxPtr pHotBox,
664642e01fSmrg                                  BoxPtr pTopLeftBox);
674642e01fSmrgstatic Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
684642e01fSmrg                                       int x, int y,
6905b261ecSmrg				       Bool generateEvent);
7005b261ecSmrgstatic Bool miPointerCloseScreen(int index, ScreenPtr pScreen);
714642e01fSmrgstatic void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen,
724642e01fSmrg                          int x, int y);
734642e01fSmrgstatic Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
744642e01fSmrgstatic void miPointerDeviceCleanup(DeviceIntPtr pDev,
754642e01fSmrg                                   ScreenPtr pScreen);
766747b715Smrgstatic void miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y);
7705b261ecSmrg
784642e01fSmrgstatic EventList* events; /* for WarpPointer MotionNotifies */
7905b261ecSmrg
806747b715SmrgBool
814642e01fSmrgmiPointerInitialize (ScreenPtr                  pScreen,
824642e01fSmrg                     miPointerSpriteFuncPtr     spriteFuncs,
834642e01fSmrg                     miPointerScreenFuncPtr     screenFuncs,
844642e01fSmrg                     Bool                       waitForUpdate)
8505b261ecSmrg{
8605b261ecSmrg    miPointerScreenPtr	pScreenPriv;
8705b261ecSmrg
886747b715Smrg    if (!dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0))
896747b715Smrg	return FALSE;
906747b715Smrg
916747b715Smrg    if (!dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0))
926747b715Smrg	return FALSE;
936747b715Smrg
946747b715Smrg    pScreenPriv = malloc(sizeof (miPointerScreenRec));
9505b261ecSmrg    if (!pScreenPriv)
9605b261ecSmrg	return FALSE;
9705b261ecSmrg    pScreenPriv->spriteFuncs = spriteFuncs;
9805b261ecSmrg    pScreenPriv->screenFuncs = screenFuncs;
9905b261ecSmrg    /*
10005b261ecSmrg     * check for uninitialized methods
10105b261ecSmrg     */
10205b261ecSmrg    if (!screenFuncs->EnqueueEvent)
10305b261ecSmrg	screenFuncs->EnqueueEvent = mieqEnqueue;
10405b261ecSmrg    if (!screenFuncs->NewEventScreen)
10505b261ecSmrg	screenFuncs->NewEventScreen = mieqSwitchScreen;
10605b261ecSmrg    pScreenPriv->waitForUpdate = waitForUpdate;
10705b261ecSmrg    pScreenPriv->showTransparent = FALSE;
10805b261ecSmrg    pScreenPriv->CloseScreen = pScreen->CloseScreen;
10905b261ecSmrg    pScreen->CloseScreen = miPointerCloseScreen;
1104642e01fSmrg    dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv);
11105b261ecSmrg    /*
11205b261ecSmrg     * set up screen cursor method table
11305b261ecSmrg     */
11405b261ecSmrg    pScreen->ConstrainCursor = miPointerConstrainCursor;
11505b261ecSmrg    pScreen->CursorLimits = miPointerCursorLimits;
11605b261ecSmrg    pScreen->DisplayCursor = miPointerDisplayCursor;
11705b261ecSmrg    pScreen->RealizeCursor = miPointerRealizeCursor;
11805b261ecSmrg    pScreen->UnrealizeCursor = miPointerUnrealizeCursor;
11905b261ecSmrg    pScreen->SetCursorPosition = miPointerSetCursorPosition;
12005b261ecSmrg    pScreen->RecolorCursor = miRecolorCursor;
1214642e01fSmrg    pScreen->DeviceCursorInitialize = miPointerDeviceInitialize;
1224642e01fSmrg    pScreen->DeviceCursorCleanup = miPointerDeviceCleanup;
12305b261ecSmrg
12405b261ecSmrg    events = NULL;
12505b261ecSmrg    return TRUE;
12605b261ecSmrg}
12705b261ecSmrg
12805b261ecSmrgstatic Bool
1294642e01fSmrgmiPointerCloseScreen (int index, ScreenPtr pScreen)
13005b261ecSmrg{
1314642e01fSmrg#if 0
1324642e01fSmrg    miPointerPtr pPointer;
1334642e01fSmrg    DeviceIntPtr pDev;
1344642e01fSmrg#endif
1354642e01fSmrg
13605b261ecSmrg    SetupScreen(pScreen);
13705b261ecSmrg
1384642e01fSmrg#if 0
1394642e01fSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
1404642e01fSmrg    {
1414642e01fSmrg        if (DevHasCursor(pDev))
1424642e01fSmrg        {
1434642e01fSmrg            pPointer = MIPOINTER(pDev);
1444642e01fSmrg
1454642e01fSmrg            if (pScreen == pPointer->pScreen)
1464642e01fSmrg                pPointer->pScreen = 0;
1474642e01fSmrg            if (pScreen == pPointer->pSpriteScreen)
1484642e01fSmrg                pPointer->pSpriteScreen = 0;
1494642e01fSmrg        }
1504642e01fSmrg    }
1514642e01fSmrg
1524642e01fSmrg    if (MIPOINTER(inputInfo.pointer)->pScreen == pScreen)
1534642e01fSmrg        MIPOINTER(inputInfo.pointer)->pScreen = 0;
1544642e01fSmrg    if (MIPOINTER(inputInfo.pointer)->pSpriteScreen == pScreen)
1554642e01fSmrg        MIPOINTER(inputInfo.pointer)->pSpriteScreen = 0;
1564642e01fSmrg#endif
1574642e01fSmrg
15805b261ecSmrg    pScreen->CloseScreen = pScreenPriv->CloseScreen;
1596747b715Smrg    free((pointer) pScreenPriv);
1604642e01fSmrg    FreeEventList(events, GetMaximumEventsNum());
16105b261ecSmrg    events = NULL;
16205b261ecSmrg    return (*pScreen->CloseScreen) (index, pScreen);
16305b261ecSmrg}
16405b261ecSmrg
16505b261ecSmrg/*
16605b261ecSmrg * DIX/DDX interface routines
16705b261ecSmrg */
16805b261ecSmrg
16905b261ecSmrgstatic Bool
1704642e01fSmrgmiPointerRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
17105b261ecSmrg{
17205b261ecSmrg    SetupScreen(pScreen);
1734642e01fSmrg    return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor);
17405b261ecSmrg}
17505b261ecSmrg
17605b261ecSmrgstatic Bool
1774642e01fSmrgmiPointerUnrealizeCursor (DeviceIntPtr  pDev,
1784642e01fSmrg                          ScreenPtr     pScreen,
1794642e01fSmrg                          CursorPtr     pCursor)
18005b261ecSmrg{
18105b261ecSmrg    SetupScreen(pScreen);
1824642e01fSmrg    return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor);
18305b261ecSmrg}
18405b261ecSmrg
18505b261ecSmrgstatic Bool
1864642e01fSmrgmiPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
18705b261ecSmrg{
1884642e01fSmrg    miPointerPtr pPointer;
1894642e01fSmrg
1904642e01fSmrg    /* return for keyboards */
1916747b715Smrg    if ((IsMaster(pDev) && !DevHasCursor(pDev)) ||
1926747b715Smrg        (!IsMaster(pDev) && pDev->u.master && !DevHasCursor(pDev->u.master)))
1934642e01fSmrg            return FALSE;
1944642e01fSmrg
1954642e01fSmrg    pPointer = MIPOINTER(pDev);
1964642e01fSmrg
1974642e01fSmrg    pPointer->pCursor = pCursor;
1984642e01fSmrg    pPointer->pScreen = pScreen;
1994642e01fSmrg    miPointerUpdateSprite(pDev);
20005b261ecSmrg    return TRUE;
20105b261ecSmrg}
20205b261ecSmrg
20305b261ecSmrgstatic void
2044642e01fSmrgmiPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox)
20505b261ecSmrg{
2064642e01fSmrg    miPointerPtr pPointer;
2074642e01fSmrg
2084642e01fSmrg    pPointer = MIPOINTER(pDev);
2094642e01fSmrg
2104642e01fSmrg    pPointer->limits = *pBox;
2114642e01fSmrg    pPointer->confined = PointerConfinedToScreen(pDev);
21205b261ecSmrg}
21305b261ecSmrg
21405b261ecSmrg/*ARGSUSED*/
21505b261ecSmrgstatic void
2164642e01fSmrgmiPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
2174642e01fSmrg                      BoxPtr pHotBox, BoxPtr pTopLeftBox)
21805b261ecSmrg{
21905b261ecSmrg    *pTopLeftBox = *pHotBox;
22005b261ecSmrg}
22105b261ecSmrg
22205b261ecSmrgstatic Bool GenerateEvent;
22305b261ecSmrg
22405b261ecSmrgstatic Bool
2254642e01fSmrgmiPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
2264642e01fSmrg                           int x, int y, Bool generateEvent)
22705b261ecSmrg{
22805b261ecSmrg    SetupScreen (pScreen);
22905b261ecSmrg
23005b261ecSmrg    GenerateEvent = generateEvent;
23105b261ecSmrg    /* device dependent - must pend signal and call miPointerWarpCursor */
2324642e01fSmrg    (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y);
23305b261ecSmrg    if (!generateEvent)
2344642e01fSmrg	miPointerUpdateSprite(pDev);
23505b261ecSmrg    return TRUE;
23605b261ecSmrg}
23705b261ecSmrg
2384642e01fSmrg/* Set up sprite information for the device.
2394642e01fSmrg   This function will be called once for each device after it is initialized
2404642e01fSmrg   in the DIX.
2414642e01fSmrg */
2424642e01fSmrgstatic Bool
2434642e01fSmrgmiPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
2444642e01fSmrg{
2454642e01fSmrg    miPointerPtr pPointer;
2464642e01fSmrg    SetupScreen (pScreen);
2474642e01fSmrg
2486747b715Smrg    pPointer = malloc(sizeof(miPointerRec));
2494642e01fSmrg    if (!pPointer)
2504642e01fSmrg        return FALSE;
2514642e01fSmrg
2524642e01fSmrg    pPointer->pScreen = NULL;
2534642e01fSmrg    pPointer->pSpriteScreen = NULL;
2544642e01fSmrg    pPointer->pCursor = NULL;
2554642e01fSmrg    pPointer->pSpriteCursor = NULL;
2564642e01fSmrg    pPointer->limits.x1 = 0;
2574642e01fSmrg    pPointer->limits.x2 = 32767;
2584642e01fSmrg    pPointer->limits.y1 = 0;
2594642e01fSmrg    pPointer->limits.y2 = 32767;
2604642e01fSmrg    pPointer->confined = FALSE;
2614642e01fSmrg    pPointer->x = 0;
2624642e01fSmrg    pPointer->y = 0;
2634642e01fSmrg
2644642e01fSmrg    if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen)))
2654642e01fSmrg    {
2666747b715Smrg        free(pPointer);
2674642e01fSmrg        return FALSE;
2684642e01fSmrg    }
2694642e01fSmrg
2704642e01fSmrg    dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer);
2714642e01fSmrg    return TRUE;
2724642e01fSmrg}
2734642e01fSmrg
2744642e01fSmrg/* Clean up after device.
2754642e01fSmrg   This function will be called once before the device is freed in the DIX
2764642e01fSmrg */
2774642e01fSmrgstatic void
2784642e01fSmrgmiPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
2794642e01fSmrg{
2806747b715Smrg    SetupScreen(pScreen);
2816747b715Smrg
2826747b715Smrg    if (!IsMaster(pDev) && pDev->u.master)
2834642e01fSmrg        return;
2844642e01fSmrg
2854642e01fSmrg    (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
2866747b715Smrg    free(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey));
2874642e01fSmrg    dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL);
2884642e01fSmrg}
2894642e01fSmrg
2904642e01fSmrg
29105b261ecSmrg/* Once signals are ignored, the WarpCursor function can call this */
29205b261ecSmrg
2936747b715Smrgvoid
2944642e01fSmrgmiPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
29505b261ecSmrg{
2964642e01fSmrg    miPointerPtr pPointer;
2974642e01fSmrg    BOOL changedScreen = FALSE;
2984642e01fSmrg
29905b261ecSmrg    SetupScreen (pScreen);
3006747b715Smrg    pPointer = MIPOINTER(pDev);
30105b261ecSmrg
3024642e01fSmrg    if (pPointer->pScreen != pScreen)
3034642e01fSmrg    {
3044642e01fSmrg	(*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE);
3054642e01fSmrg        changedScreen = TRUE;
3064642e01fSmrg    }
30705b261ecSmrg
30805b261ecSmrg    if (GenerateEvent)
3094642e01fSmrg	miPointerMove (pDev, pScreen, x, y);
31005b261ecSmrg    else
3116747b715Smrg        miPointerMoveNoEvent(pDev, pScreen, x, y);
3124642e01fSmrg
3134642e01fSmrg    /* Don't call USFS if we use Xinerama, otherwise the root window is
3144642e01fSmrg     * updated to the second screen, and we never receive any events.
3154642e01fSmrg     * (FDO bug #18668) */
3164642e01fSmrg    if (changedScreen
3174642e01fSmrg#ifdef PANORAMIX
3184642e01fSmrg            && noPanoramiXExtension
3194642e01fSmrg#endif
3204642e01fSmrg       )
3214642e01fSmrg        UpdateSpriteForScreen (pDev, pScreen) ;
32205b261ecSmrg}
32305b261ecSmrg
32405b261ecSmrg/*
32505b261ecSmrg * Pointer/CursorDisplay interface routines
32605b261ecSmrg */
32705b261ecSmrg
32805b261ecSmrg/*
3294642e01fSmrg * miPointerUpdateSprite
33005b261ecSmrg *
33105b261ecSmrg * Syncronize the sprite with the cursor - called from ProcessInputEvents
33205b261ecSmrg */
33305b261ecSmrg
33405b261ecSmrgvoid
33505b261ecSmrgmiPointerUpdateSprite (DeviceIntPtr pDev)
33605b261ecSmrg{
33705b261ecSmrg    ScreenPtr		pScreen;
33805b261ecSmrg    miPointerScreenPtr	pScreenPriv;
33905b261ecSmrg    CursorPtr		pCursor;
34005b261ecSmrg    int			x, y, devx, devy;
3414642e01fSmrg    miPointerPtr        pPointer;
34205b261ecSmrg
3434642e01fSmrg    if (!pDev || !pDev->coreEvents)
34405b261ecSmrg        return;
34505b261ecSmrg
3464642e01fSmrg    pPointer = MIPOINTER(pDev);
3474642e01fSmrg
3486747b715Smrg    if (!pPointer)
3496747b715Smrg        return;
3506747b715Smrg
3514642e01fSmrg    pScreen = pPointer->pScreen;
35205b261ecSmrg    if (!pScreen)
35305b261ecSmrg	return;
35405b261ecSmrg
3554642e01fSmrg    x = pPointer->x;
3564642e01fSmrg    y = pPointer->y;
3574642e01fSmrg    devx = pPointer->devx;
3584642e01fSmrg    devy = pPointer->devy;
35905b261ecSmrg
36005b261ecSmrg    pScreenPriv = GetScreenPrivate (pScreen);
36105b261ecSmrg    /*
36205b261ecSmrg     * if the cursor has switched screens, disable the sprite
36305b261ecSmrg     * on the old screen
36405b261ecSmrg     */
3654642e01fSmrg    if (pScreen != pPointer->pSpriteScreen)
36605b261ecSmrg    {
3674642e01fSmrg	if (pPointer->pSpriteScreen)
36805b261ecSmrg	{
36905b261ecSmrg	    miPointerScreenPtr  pOldPriv;
37005b261ecSmrg
3714642e01fSmrg	    pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen);
3724642e01fSmrg	    if (pPointer->pCursor)
37305b261ecSmrg	    {
37405b261ecSmrg	    	(*pOldPriv->spriteFuncs->SetCursor)
3754642e01fSmrg			    	(pDev, pPointer->pSpriteScreen, NullCursor, 0, 0);
37605b261ecSmrg	    }
3774642e01fSmrg	    (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE);
37805b261ecSmrg	}
37905b261ecSmrg	(*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
38005b261ecSmrg	(*pScreenPriv->spriteFuncs->SetCursor)
3814642e01fSmrg				(pDev, pScreen, pPointer->pCursor, x, y);
3824642e01fSmrg	pPointer->devx = x;
3834642e01fSmrg	pPointer->devy = y;
3844642e01fSmrg	pPointer->pSpriteCursor = pPointer->pCursor;
3854642e01fSmrg	pPointer->pSpriteScreen = pScreen;
38605b261ecSmrg    }
38705b261ecSmrg    /*
38805b261ecSmrg     * if the cursor has changed, display the new one
38905b261ecSmrg     */
3904642e01fSmrg    else if (pPointer->pCursor != pPointer->pSpriteCursor)
39105b261ecSmrg    {
3924642e01fSmrg	pCursor = pPointer->pCursor;
3934642e01fSmrg	if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent))
39405b261ecSmrg	    pCursor = NullCursor;
3954642e01fSmrg	(*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y);
39605b261ecSmrg
3974642e01fSmrg	pPointer->devx = x;
3984642e01fSmrg	pPointer->devy = y;
3994642e01fSmrg	pPointer->pSpriteCursor = pPointer->pCursor;
40005b261ecSmrg    }
40105b261ecSmrg    else if (x != devx || y != devy)
40205b261ecSmrg    {
4034642e01fSmrg	pPointer->devx = x;
4044642e01fSmrg	pPointer->devy = y;
4054642e01fSmrg	if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
4064642e01fSmrg	    (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
40705b261ecSmrg    }
40805b261ecSmrg}
40905b261ecSmrg
41005b261ecSmrgvoid
41105b261ecSmrgmiPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
41205b261ecSmrg{
41305b261ecSmrg	miPointerScreenPtr pScreenPriv;
41405b261ecSmrg	ScreenPtr pScreen;
4154642e01fSmrg        miPointerPtr pPointer;
4164642e01fSmrg
4174642e01fSmrg        pPointer = MIPOINTER(pDev);
41805b261ecSmrg
41905b261ecSmrg	pScreen = screenInfo.screens[screen_no];
42005b261ecSmrg	pScreenPriv = GetScreenPrivate (pScreen);
4214642e01fSmrg	(*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE);
4224642e01fSmrg	NewCurrentScreen (pDev, pScreen, x, y);
4234642e01fSmrg
4244642e01fSmrg        pPointer->limits.x2 = pScreen->width;
4254642e01fSmrg        pPointer->limits.y2 = pScreen->height;
42605b261ecSmrg}
42705b261ecSmrg
4286747b715SmrgScreenPtr
4296747b715SmrgmiPointerCurrentScreen (void)
43005b261ecSmrg{
43105b261ecSmrg    return miPointerGetScreen(inputInfo.pointer);
43205b261ecSmrg}
43305b261ecSmrg
4346747b715SmrgScreenPtr
43505b261ecSmrgmiPointerGetScreen(DeviceIntPtr pDev)
43605b261ecSmrg{
4374642e01fSmrg    miPointerPtr pPointer = MIPOINTER(pDev);
4384642e01fSmrg    return (pPointer) ? pPointer->pScreen : NULL;
43905b261ecSmrg}
44005b261ecSmrg
4416747b715Smrg/* Controls whether the cursor image should be updated immediately when
4426747b715Smrg   moved (FALSE) or if something else will be responsible for updating
4436747b715Smrg   it later (TRUE).  Returns current setting.
4446747b715Smrg   Caller is responsible for calling OsBlockSignal first.
4456747b715Smrg*/
4466747b715SmrgBool
4476747b715SmrgmiPointerSetWaitForUpdate(ScreenPtr pScreen, Bool wait)
44805b261ecSmrg{
4496747b715Smrg    SetupScreen(pScreen);
4506747b715Smrg    Bool prevWait = pScreenPriv->waitForUpdate;
4516747b715Smrg
4526747b715Smrg    pScreenPriv->waitForUpdate = wait;
4536747b715Smrg    return prevWait;
45405b261ecSmrg}
45505b261ecSmrg
4566747b715Smrg
45705b261ecSmrg/* Move the pointer on the current screen,  and update the sprite. */
45805b261ecSmrgstatic void
4596747b715SmrgmiPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen,
4604642e01fSmrg                int x, int y)
46105b261ecSmrg{
4624642e01fSmrg    miPointerPtr pPointer;
46305b261ecSmrg    SetupScreen(pScreen);
46405b261ecSmrg
4654642e01fSmrg    pPointer = MIPOINTER(pDev);
4664642e01fSmrg
4674642e01fSmrg    /* Hack: We mustn't call into ->MoveCursor for anything but the
4684642e01fSmrg     * VCP, as this may cause a non-HW rendered cursor to be rendered during
4694642e01fSmrg     * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT.
4704642e01fSmrg     */
4716747b715Smrg    if ((pDev == inputInfo.pointer || (!IsMaster(pDev) && pDev->u.master == inputInfo.pointer))
4724642e01fSmrg        && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
47305b261ecSmrg    {
4744642e01fSmrg	pPointer->devx = x;
4754642e01fSmrg	pPointer->devy = y;
4764642e01fSmrg	if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
4774642e01fSmrg	    (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
47805b261ecSmrg    }
47905b261ecSmrg
4804642e01fSmrg    pPointer->x = x;
4814642e01fSmrg    pPointer->y = y;
4824642e01fSmrg    pPointer->pScreen = pScreen;
48305b261ecSmrg}
48405b261ecSmrg
4856747b715Smrgvoid
4864642e01fSmrgmiPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
48705b261ecSmrg{
48805b261ecSmrg    miPointerScreenPtr	pScreenPriv;
48905b261ecSmrg    ScreenPtr		pScreen;
49005b261ecSmrg    ScreenPtr		newScreen;
49105b261ecSmrg
4924642e01fSmrg    miPointerPtr        pPointer;
4934642e01fSmrg
4946747b715Smrg    if (!pDev || !pDev->coreEvents)
4956747b715Smrg        return;
4966747b715Smrg
4974642e01fSmrg    pPointer = MIPOINTER(pDev);
4984642e01fSmrg    pScreen = pPointer->pScreen;
49905b261ecSmrg    if (!pScreen)
50005b261ecSmrg	return;	    /* called before ready */
50105b261ecSmrg
50205b261ecSmrg    if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
50305b261ecSmrg    {
50405b261ecSmrg	pScreenPriv = GetScreenPrivate (pScreen);
5054642e01fSmrg	if (!pPointer->confined)
50605b261ecSmrg	{
50705b261ecSmrg	    newScreen = pScreen;
50805b261ecSmrg	    (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y);
50905b261ecSmrg	    if (newScreen != pScreen)
51005b261ecSmrg	    {
51105b261ecSmrg		pScreen = newScreen;
5124642e01fSmrg		(*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen,
5134642e01fSmrg							     FALSE);
51405b261ecSmrg		pScreenPriv = GetScreenPrivate (pScreen);
51505b261ecSmrg	    	/* Smash the confine to the new screen */
5164642e01fSmrg                pPointer->limits.x2 = pScreen->width;
5174642e01fSmrg                pPointer->limits.y2 = pScreen->height;
51805b261ecSmrg	    }
51905b261ecSmrg	}
52005b261ecSmrg    }
52105b261ecSmrg    /* Constrain the sprite to the current limits. */
5224642e01fSmrg    if (*x < pPointer->limits.x1)
5234642e01fSmrg	*x = pPointer->limits.x1;
5244642e01fSmrg    if (*x >= pPointer->limits.x2)
5254642e01fSmrg	*x = pPointer->limits.x2 - 1;
5264642e01fSmrg    if (*y < pPointer->limits.y1)
5274642e01fSmrg	*y = pPointer->limits.y1;
5284642e01fSmrg    if (*y >= pPointer->limits.y2)
5294642e01fSmrg	*y = pPointer->limits.y2 - 1;
5304642e01fSmrg
5314642e01fSmrg    if (pPointer->x == *x && pPointer->y == *y &&
5324642e01fSmrg            pPointer->pScreen == pScreen)
5334642e01fSmrg        return;
53405b261ecSmrg
5356747b715Smrg    miPointerMoveNoEvent(pDev, pScreen, *x, *y);
53605b261ecSmrg}
53705b261ecSmrg
5386747b715Smrgvoid
53905b261ecSmrgmiPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
54005b261ecSmrg{
5414642e01fSmrg    *x = MIPOINTER(pDev)->x;
5424642e01fSmrg    *y = MIPOINTER(pDev)->y;
54305b261ecSmrg}
54405b261ecSmrg
5454642e01fSmrg#ifdef XQUARTZ
5464642e01fSmrg#include <pthread.h>
5474642e01fSmrgvoid darwinEvents_lock(void);
5484642e01fSmrgvoid darwinEvents_unlock(void);
5494642e01fSmrg#endif
5504642e01fSmrg
55105b261ecSmrgvoid
5524642e01fSmrgmiPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
55305b261ecSmrg{
55405b261ecSmrg    int i, nevents;
55505b261ecSmrg    int valuators[2];
55605b261ecSmrg
5576747b715Smrg    miPointerMoveNoEvent(pDev, pScreen, x, y);
55805b261ecSmrg
55905b261ecSmrg    /* generate motion notify */
56005b261ecSmrg    valuators[0] = x;
56105b261ecSmrg    valuators[1] = y;
56205b261ecSmrg
56305b261ecSmrg    if (!events)
56405b261ecSmrg    {
5654642e01fSmrg        events = InitEventList(GetMaximumEventsNum());
56605b261ecSmrg
56705b261ecSmrg        if (!events)
56805b261ecSmrg        {
56905b261ecSmrg            FatalError("Could not allocate event store.\n");
57005b261ecSmrg            return;
57105b261ecSmrg        }
57205b261ecSmrg    }
57305b261ecSmrg
5744642e01fSmrg    nevents = GetPointerEvents(events, pDev, MotionNotify, 0, POINTER_SCREEN | POINTER_ABSOLUTE, 0, 2, valuators);
57505b261ecSmrg
5764642e01fSmrg    OsBlockSignals();
5774642e01fSmrg#ifdef XQUARTZ
5784642e01fSmrg    darwinEvents_lock();
5794642e01fSmrg#endif
58005b261ecSmrg    for (i = 0; i < nevents; i++)
5816747b715Smrg        mieqEnqueue(pDev, (InternalEvent*)events[i].event);
5824642e01fSmrg#ifdef XQUARTZ
5834642e01fSmrg    darwinEvents_unlock();
5844642e01fSmrg#endif
5854642e01fSmrg    OsReleaseSignals();
58605b261ecSmrg}
587