mipointer.c revision 35c4bbdf
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
2635c4bbdfSmrg/**
2735c4bbdfSmrg * @file
2835c4bbdfSmrg * This file contains functions to move the pointer on the screen and/or
2935c4bbdfSmrg * restrict its movement. These functions are divided into two sets:
3035c4bbdfSmrg * Screen-specific functions that are used as function pointers from other
3135c4bbdfSmrg * parts of the server (and end up heavily wrapped by e.g. animcur and
3235c4bbdfSmrg * xfixes):
3335c4bbdfSmrg *      miPointerConstrainCursor
3435c4bbdfSmrg *      miPointerCursorLimits
3535c4bbdfSmrg *      miPointerDisplayCursor
3635c4bbdfSmrg *      miPointerRealizeCursor
3735c4bbdfSmrg *      miPointerUnrealizeCursor
3835c4bbdfSmrg *      miPointerSetCursorPosition
3935c4bbdfSmrg *      miRecolorCursor
4035c4bbdfSmrg *      miPointerDeviceInitialize
4135c4bbdfSmrg *      miPointerDeviceCleanup
4235c4bbdfSmrg * If wrapped, these are the last element in the wrapping chain. They may
4335c4bbdfSmrg * call into sprite-specific code through further function pointers though.
4435c4bbdfSmrg *
4535c4bbdfSmrg * The second type of functions are those that are directly called by the
4635c4bbdfSmrg * DIX, DDX and some drivers.
4735c4bbdfSmrg */
4835c4bbdfSmrg
4905b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
5005b261ecSmrg#include <dix-config.h>
5105b261ecSmrg#endif
5205b261ecSmrg
5335c4bbdfSmrg#include   <X11/X.h>
5435c4bbdfSmrg#include   <X11/Xmd.h>
5535c4bbdfSmrg#include   <X11/Xproto.h>
5635c4bbdfSmrg#include   "misc.h"
5735c4bbdfSmrg#include   "windowstr.h"
5835c4bbdfSmrg#include   "pixmapstr.h"
5935c4bbdfSmrg#include   "mi.h"
6035c4bbdfSmrg#include   "scrnintstr.h"
6135c4bbdfSmrg#include   "mipointrst.h"
6235c4bbdfSmrg#include   "cursorstr.h"
6335c4bbdfSmrg#include   "dixstruct.h"
6435c4bbdfSmrg#include   "inputstr.h"
6535c4bbdfSmrg#include   "inpututils.h"
6635c4bbdfSmrg#include   "eventstr.h"
6705b261ecSmrg
686747b715SmrgDevPrivateKeyRec miPointerScreenKeyRec;
6905b261ecSmrg
704642e01fSmrg#define GetScreenPrivate(s) ((miPointerScreenPtr) \
714642e01fSmrg    dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey))
7205b261ecSmrg#define SetupScreen(s)	miPointerScreenPtr  pScreenPriv = GetScreenPrivate(s)
7305b261ecSmrg
746747b715SmrgDevPrivateKeyRec miPointerPrivKeyRec;
754642e01fSmrg
764642e01fSmrg#define MIPOINTER(dev) \
7735c4bbdfSmrg    (IsFloating(dev) ? \
784642e01fSmrg        (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
796747b715Smrg        (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey))
804642e01fSmrg
8135c4bbdfSmrgstatic Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
824642e01fSmrg                                   CursorPtr pCursor);
8335c4bbdfSmrgstatic Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
844642e01fSmrg                                     CursorPtr pCursor);
8535c4bbdfSmrgstatic Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
864642e01fSmrg                                   CursorPtr pCursor);
874642e01fSmrgstatic void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
8835c4bbdfSmrg                                     BoxPtr pBox);
894642e01fSmrgstatic void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen,
9035c4bbdfSmrg                                  CursorPtr pCursor, BoxPtr pHotBox,
914642e01fSmrg                                  BoxPtr pTopLeftBox);
9235c4bbdfSmrgstatic Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
9335c4bbdfSmrg                                       int x, int y, Bool generateEvent);
9435c4bbdfSmrgstatic Bool miPointerCloseScreen(ScreenPtr pScreen);
9535c4bbdfSmrgstatic void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y);
964642e01fSmrgstatic Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
9735c4bbdfSmrgstatic void miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen);
9835c4bbdfSmrgstatic void miPointerMoveNoEvent(DeviceIntPtr pDev, ScreenPtr pScreen, int x,
9935c4bbdfSmrg                                 int y);
10005b261ecSmrg
10135c4bbdfSmrgstatic InternalEvent *mipointermove_events;   /* for WarpPointer MotionNotifies */
10205b261ecSmrg
1036747b715SmrgBool
10435c4bbdfSmrgmiPointerInitialize(ScreenPtr pScreen,
10535c4bbdfSmrg                    miPointerSpriteFuncPtr spriteFuncs,
10635c4bbdfSmrg                    miPointerScreenFuncPtr screenFuncs, Bool waitForUpdate)
10705b261ecSmrg{
10835c4bbdfSmrg    miPointerScreenPtr pScreenPriv;
10905b261ecSmrg
1106747b715Smrg    if (!dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0))
11135c4bbdfSmrg        return FALSE;
1126747b715Smrg
1136747b715Smrg    if (!dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0))
11435c4bbdfSmrg        return FALSE;
1156747b715Smrg
11635c4bbdfSmrg    pScreenPriv = malloc(sizeof(miPointerScreenRec));
11705b261ecSmrg    if (!pScreenPriv)
11835c4bbdfSmrg        return FALSE;
11905b261ecSmrg    pScreenPriv->spriteFuncs = spriteFuncs;
12005b261ecSmrg    pScreenPriv->screenFuncs = screenFuncs;
12105b261ecSmrg    pScreenPriv->waitForUpdate = waitForUpdate;
12205b261ecSmrg    pScreenPriv->showTransparent = FALSE;
12305b261ecSmrg    pScreenPriv->CloseScreen = pScreen->CloseScreen;
12405b261ecSmrg    pScreen->CloseScreen = miPointerCloseScreen;
1254642e01fSmrg    dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv);
12605b261ecSmrg    /*
12705b261ecSmrg     * set up screen cursor method table
12805b261ecSmrg     */
12905b261ecSmrg    pScreen->ConstrainCursor = miPointerConstrainCursor;
13005b261ecSmrg    pScreen->CursorLimits = miPointerCursorLimits;
13105b261ecSmrg    pScreen->DisplayCursor = miPointerDisplayCursor;
13205b261ecSmrg    pScreen->RealizeCursor = miPointerRealizeCursor;
13305b261ecSmrg    pScreen->UnrealizeCursor = miPointerUnrealizeCursor;
13405b261ecSmrg    pScreen->SetCursorPosition = miPointerSetCursorPosition;
13505b261ecSmrg    pScreen->RecolorCursor = miRecolorCursor;
1364642e01fSmrg    pScreen->DeviceCursorInitialize = miPointerDeviceInitialize;
1374642e01fSmrg    pScreen->DeviceCursorCleanup = miPointerDeviceCleanup;
13805b261ecSmrg
13935c4bbdfSmrg    mipointermove_events = NULL;
14005b261ecSmrg    return TRUE;
14105b261ecSmrg}
14205b261ecSmrg
14335c4bbdfSmrg/**
14435c4bbdfSmrg * Destroy screen-specific information.
14535c4bbdfSmrg *
14635c4bbdfSmrg * @param index Screen index of the screen in screenInfo.screens[]
14735c4bbdfSmrg * @param pScreen The actual screen pointer
14835c4bbdfSmrg */
14905b261ecSmrgstatic Bool
15035c4bbdfSmrgmiPointerCloseScreen(ScreenPtr pScreen)
15105b261ecSmrg{
15205b261ecSmrg    SetupScreen(pScreen);
15305b261ecSmrg
15405b261ecSmrg    pScreen->CloseScreen = pScreenPriv->CloseScreen;
15535c4bbdfSmrg    free((void *) pScreenPriv);
15635c4bbdfSmrg    FreeEventList(mipointermove_events, GetMaximumEventsNum());
15735c4bbdfSmrg    mipointermove_events = NULL;
15835c4bbdfSmrg    return (*pScreen->CloseScreen) (pScreen);
15905b261ecSmrg}
16005b261ecSmrg
16105b261ecSmrg/*
16205b261ecSmrg * DIX/DDX interface routines
16305b261ecSmrg */
16405b261ecSmrg
16505b261ecSmrgstatic Bool
16635c4bbdfSmrgmiPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
16705b261ecSmrg{
16805b261ecSmrg    SetupScreen(pScreen);
1694642e01fSmrg    return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor);
17005b261ecSmrg}
17105b261ecSmrg
17205b261ecSmrgstatic Bool
17335c4bbdfSmrgmiPointerUnrealizeCursor(DeviceIntPtr pDev,
17435c4bbdfSmrg                         ScreenPtr pScreen, CursorPtr pCursor)
17505b261ecSmrg{
17605b261ecSmrg    SetupScreen(pScreen);
17735c4bbdfSmrg    return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen,
17835c4bbdfSmrg                                                         pCursor);
17905b261ecSmrg}
18005b261ecSmrg
18105b261ecSmrgstatic Bool
18235c4bbdfSmrgmiPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
18305b261ecSmrg{
1844642e01fSmrg    miPointerPtr pPointer;
1854642e01fSmrg
1864642e01fSmrg    /* return for keyboards */
18735c4bbdfSmrg    if (!IsPointerDevice(pDev))
18835c4bbdfSmrg        return FALSE;
1894642e01fSmrg
1904642e01fSmrg    pPointer = MIPOINTER(pDev);
1914642e01fSmrg
1924642e01fSmrg    pPointer->pCursor = pCursor;
1934642e01fSmrg    pPointer->pScreen = pScreen;
1944642e01fSmrg    miPointerUpdateSprite(pDev);
19505b261ecSmrg    return TRUE;
19605b261ecSmrg}
19705b261ecSmrg
19835c4bbdfSmrg/**
19935c4bbdfSmrg * Set up the constraints for the given device. This function does not
20035c4bbdfSmrg * actually constrain the cursor but merely copies the given box to the
20135c4bbdfSmrg * internal constraint storage.
20235c4bbdfSmrg *
20335c4bbdfSmrg * @param pDev The device to constrain to the box
20435c4bbdfSmrg * @param pBox The rectangle to constrain the cursor to
20535c4bbdfSmrg * @param pScreen Used for copying screen confinement
20635c4bbdfSmrg */
20705b261ecSmrgstatic void
20835c4bbdfSmrgmiPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox)
20905b261ecSmrg{
2104642e01fSmrg    miPointerPtr pPointer;
2114642e01fSmrg
2124642e01fSmrg    pPointer = MIPOINTER(pDev);
2134642e01fSmrg
2144642e01fSmrg    pPointer->limits = *pBox;
2154642e01fSmrg    pPointer->confined = PointerConfinedToScreen(pDev);
21605b261ecSmrg}
21705b261ecSmrg
21835c4bbdfSmrg/**
21935c4bbdfSmrg * Should calculate the box for the given cursor, based on screen and the
22035c4bbdfSmrg * confinement given. But we assume that whatever box is passed in is valid
22135c4bbdfSmrg * anyway.
22235c4bbdfSmrg *
22335c4bbdfSmrg * @param pDev The device to calculate the cursor limits for
22435c4bbdfSmrg * @param pScreen The screen the confinement happens on
22535c4bbdfSmrg * @param pCursor The screen the confinement happens on
22635c4bbdfSmrg * @param pHotBox The confinement box for the cursor
22735c4bbdfSmrg * @param[out] pTopLeftBox The new confinement box, always *pHotBox.
22835c4bbdfSmrg */
22905b261ecSmrgstatic void
2304642e01fSmrgmiPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
2314642e01fSmrg                      BoxPtr pHotBox, BoxPtr pTopLeftBox)
23205b261ecSmrg{
23305b261ecSmrg    *pTopLeftBox = *pHotBox;
23405b261ecSmrg}
23505b261ecSmrg
23635c4bbdfSmrg/**
23735c4bbdfSmrg * Set the device's cursor position to the x/y position on the given screen.
23835c4bbdfSmrg * Generates and event if required.
23935c4bbdfSmrg *
24035c4bbdfSmrg * This function is called from:
24135c4bbdfSmrg *    - sprite init code to place onto initial position
24235c4bbdfSmrg *    - the various WarpPointer implementations (core, XI, Xinerama, dmx,…)
24335c4bbdfSmrg *    - during the cursor update path in CheckMotion
24435c4bbdfSmrg *    - in the Xinerama part of NewCurrentScreen
24535c4bbdfSmrg *    - when a RandR/RandR1.2 mode was applied (it may have moved the pointer, so
24635c4bbdfSmrg *      it's set back to the original pos)
24735c4bbdfSmrg *
24835c4bbdfSmrg * @param pDev The device to move
24935c4bbdfSmrg * @param pScreen The screen the device is on
25035c4bbdfSmrg * @param x The x coordinate in per-screen coordinates
25135c4bbdfSmrg * @param y The y coordinate in per-screen coordinates
25235c4bbdfSmrg * @param generateEvent True if the pointer movement should generate an
25335c4bbdfSmrg * event.
25435c4bbdfSmrg *
25535c4bbdfSmrg * @return TRUE in all cases
25635c4bbdfSmrg */
25705b261ecSmrgstatic Bool
2584642e01fSmrgmiPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
2594642e01fSmrg                           int x, int y, Bool generateEvent)
26005b261ecSmrg{
26135c4bbdfSmrg    SetupScreen(pScreen);
26235c4bbdfSmrg    miPointerPtr pPointer = MIPOINTER(pDev);
26335c4bbdfSmrg
26435c4bbdfSmrg    pPointer->generateEvent = generateEvent;
26535c4bbdfSmrg
26635c4bbdfSmrg    if (pScreen->ConstrainCursorHarder)
26735c4bbdfSmrg        pScreen->ConstrainCursorHarder(pDev, pScreen, Absolute, &x, &y);
26805b261ecSmrg
26905b261ecSmrg    /* device dependent - must pend signal and call miPointerWarpCursor */
2704642e01fSmrg    (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y);
27105b261ecSmrg    if (!generateEvent)
27235c4bbdfSmrg        miPointerUpdateSprite(pDev);
27305b261ecSmrg    return TRUE;
27405b261ecSmrg}
27505b261ecSmrg
27635c4bbdfSmrgvoid
27735c4bbdfSmrgmiRecolorCursor(DeviceIntPtr pDev, ScreenPtr pScr,
27835c4bbdfSmrg                CursorPtr pCurs, Bool displayed)
27935c4bbdfSmrg{
28035c4bbdfSmrg    /*
28135c4bbdfSmrg     * This is guaranteed to correct any color-dependent state which may have
28235c4bbdfSmrg     * been bound up in private state created by RealizeCursor
28335c4bbdfSmrg     */
28435c4bbdfSmrg    pScr->UnrealizeCursor(pDev, pScr, pCurs);
28535c4bbdfSmrg    pScr->RealizeCursor(pDev, pScr, pCurs);
28635c4bbdfSmrg    if (displayed)
28735c4bbdfSmrg        pScr->DisplayCursor(pDev, pScr, pCurs);
28835c4bbdfSmrg}
28935c4bbdfSmrg
29035c4bbdfSmrg/**
29135c4bbdfSmrg * Set up sprite information for the device.
29235c4bbdfSmrg * This function will be called once for each device after it is initialized
29335c4bbdfSmrg * in the DIX.
29435c4bbdfSmrg *
29535c4bbdfSmrg * @param pDev The newly created device
29635c4bbdfSmrg * @param pScreen The initial sprite scree.
2974642e01fSmrg */
2984642e01fSmrgstatic Bool
2994642e01fSmrgmiPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
3004642e01fSmrg{
3014642e01fSmrg    miPointerPtr pPointer;
30235c4bbdfSmrg
30335c4bbdfSmrg    SetupScreen(pScreen);
3044642e01fSmrg
3056747b715Smrg    pPointer = malloc(sizeof(miPointerRec));
3064642e01fSmrg    if (!pPointer)
3074642e01fSmrg        return FALSE;
3084642e01fSmrg
3094642e01fSmrg    pPointer->pScreen = NULL;
3104642e01fSmrg    pPointer->pSpriteScreen = NULL;
3114642e01fSmrg    pPointer->pCursor = NULL;
3124642e01fSmrg    pPointer->pSpriteCursor = NULL;
3134642e01fSmrg    pPointer->limits.x1 = 0;
3144642e01fSmrg    pPointer->limits.x2 = 32767;
3154642e01fSmrg    pPointer->limits.y1 = 0;
3164642e01fSmrg    pPointer->limits.y2 = 32767;
3174642e01fSmrg    pPointer->confined = FALSE;
3184642e01fSmrg    pPointer->x = 0;
3194642e01fSmrg    pPointer->y = 0;
32035c4bbdfSmrg    pPointer->generateEvent = FALSE;
3214642e01fSmrg
32235c4bbdfSmrg    if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize) (pDev, pScreen))) {
3236747b715Smrg        free(pPointer);
3244642e01fSmrg        return FALSE;
3254642e01fSmrg    }
3264642e01fSmrg
3274642e01fSmrg    dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer);
3284642e01fSmrg    return TRUE;
3294642e01fSmrg}
3304642e01fSmrg
33135c4bbdfSmrg/**
33235c4bbdfSmrg * Clean up after device.
33335c4bbdfSmrg * This function will be called once before the device is freed in the DIX
33435c4bbdfSmrg *
33535c4bbdfSmrg * @param pDev The device to be removed from the server
33635c4bbdfSmrg * @param pScreen Current screen of the device
3374642e01fSmrg */
3384642e01fSmrgstatic void
3394642e01fSmrgmiPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
3404642e01fSmrg{
3416747b715Smrg    SetupScreen(pScreen);
3426747b715Smrg
34335c4bbdfSmrg    if (!IsMaster(pDev) && !IsFloating(pDev))
3444642e01fSmrg        return;
3454642e01fSmrg
34635c4bbdfSmrg    (*pScreenPriv->spriteFuncs->DeviceCursorCleanup) (pDev, pScreen);
3476747b715Smrg    free(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey));
3484642e01fSmrg    dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL);
3494642e01fSmrg}
3504642e01fSmrg
35135c4bbdfSmrg/**
35235c4bbdfSmrg * Warp the pointer to the given position on the given screen. May generate
35335c4bbdfSmrg * an event, depending on whether we're coming from miPointerSetPosition.
35435c4bbdfSmrg *
35535c4bbdfSmrg * Once signals are ignored, the WarpCursor function can call this
35635c4bbdfSmrg *
35735c4bbdfSmrg * @param pDev The device to warp
35835c4bbdfSmrg * @param pScreen Screen to warp on
35935c4bbdfSmrg * @param x The x coordinate in per-screen coordinates
36035c4bbdfSmrg * @param y The y coordinate in per-screen coordinates
36135c4bbdfSmrg */
36205b261ecSmrg
3636747b715Smrgvoid
36435c4bbdfSmrgmiPointerWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
36505b261ecSmrg{
3664642e01fSmrg    miPointerPtr pPointer;
3674642e01fSmrg    BOOL changedScreen = FALSE;
3684642e01fSmrg
3696747b715Smrg    pPointer = MIPOINTER(pDev);
37005b261ecSmrg
37135c4bbdfSmrg    if (pPointer->pScreen != pScreen) {
37235c4bbdfSmrg        mieqSwitchScreen(pDev, pScreen, TRUE);
3734642e01fSmrg        changedScreen = TRUE;
3744642e01fSmrg    }
37505b261ecSmrg
37635c4bbdfSmrg    if (pPointer->generateEvent)
37735c4bbdfSmrg        miPointerMove(pDev, pScreen, x, y);
37805b261ecSmrg    else
3796747b715Smrg        miPointerMoveNoEvent(pDev, pScreen, x, y);
3804642e01fSmrg
3814642e01fSmrg    /* Don't call USFS if we use Xinerama, otherwise the root window is
3824642e01fSmrg     * updated to the second screen, and we never receive any events.
3834642e01fSmrg     * (FDO bug #18668) */
3844642e01fSmrg    if (changedScreen
3854642e01fSmrg#ifdef PANORAMIX
38635c4bbdfSmrg        && noPanoramiXExtension
3874642e01fSmrg#endif
38835c4bbdfSmrg        )
38935c4bbdfSmrg        UpdateSpriteForScreen(pDev, pScreen);
39005b261ecSmrg}
39105b261ecSmrg
39235c4bbdfSmrg/**
39335c4bbdfSmrg * Syncronize the sprite with the cursor.
39405b261ecSmrg *
39535c4bbdfSmrg * @param pDev The device to sync
39605b261ecSmrg */
39705b261ecSmrgvoid
39835c4bbdfSmrgmiPointerUpdateSprite(DeviceIntPtr pDev)
39905b261ecSmrg{
40035c4bbdfSmrg    ScreenPtr pScreen;
40135c4bbdfSmrg    miPointerScreenPtr pScreenPriv;
40235c4bbdfSmrg    CursorPtr pCursor;
40335c4bbdfSmrg    int x, y, devx, devy;
40435c4bbdfSmrg    miPointerPtr pPointer;
40505b261ecSmrg
4064642e01fSmrg    if (!pDev || !pDev->coreEvents)
40705b261ecSmrg        return;
40805b261ecSmrg
4094642e01fSmrg    pPointer = MIPOINTER(pDev);
4104642e01fSmrg
4116747b715Smrg    if (!pPointer)
4126747b715Smrg        return;
4136747b715Smrg
4144642e01fSmrg    pScreen = pPointer->pScreen;
41505b261ecSmrg    if (!pScreen)
41635c4bbdfSmrg        return;
41705b261ecSmrg
4184642e01fSmrg    x = pPointer->x;
4194642e01fSmrg    y = pPointer->y;
4204642e01fSmrg    devx = pPointer->devx;
4214642e01fSmrg    devy = pPointer->devy;
42205b261ecSmrg
42335c4bbdfSmrg    pScreenPriv = GetScreenPrivate(pScreen);
42405b261ecSmrg    /*
42505b261ecSmrg     * if the cursor has switched screens, disable the sprite
42605b261ecSmrg     * on the old screen
42705b261ecSmrg     */
42835c4bbdfSmrg    if (pScreen != pPointer->pSpriteScreen) {
42935c4bbdfSmrg        if (pPointer->pSpriteScreen) {
43035c4bbdfSmrg            miPointerScreenPtr pOldPriv;
43135c4bbdfSmrg
43235c4bbdfSmrg            pOldPriv = GetScreenPrivate(pPointer->pSpriteScreen);
43335c4bbdfSmrg            if (pPointer->pCursor) {
43435c4bbdfSmrg                (*pOldPriv->spriteFuncs->SetCursor)
43535c4bbdfSmrg                    (pDev, pPointer->pSpriteScreen, NullCursor, 0, 0);
43635c4bbdfSmrg            }
43735c4bbdfSmrg            (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen,
43835c4bbdfSmrg                                                   FALSE);
43935c4bbdfSmrg        }
44035c4bbdfSmrg        (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
44135c4bbdfSmrg        (*pScreenPriv->spriteFuncs->SetCursor)
44235c4bbdfSmrg            (pDev, pScreen, pPointer->pCursor, x, y);
44335c4bbdfSmrg        pPointer->devx = x;
44435c4bbdfSmrg        pPointer->devy = y;
44535c4bbdfSmrg        pPointer->pSpriteCursor = pPointer->pCursor;
44635c4bbdfSmrg        pPointer->pSpriteScreen = pScreen;
44705b261ecSmrg    }
44805b261ecSmrg    /*
44905b261ecSmrg     * if the cursor has changed, display the new one
45005b261ecSmrg     */
45135c4bbdfSmrg    else if (pPointer->pCursor != pPointer->pSpriteCursor) {
45235c4bbdfSmrg        pCursor = pPointer->pCursor;
45335c4bbdfSmrg        if (!pCursor ||
45435c4bbdfSmrg            (pCursor->bits->emptyMask && !pScreenPriv->showTransparent))
45535c4bbdfSmrg            pCursor = NullCursor;
45635c4bbdfSmrg        (*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y);
45735c4bbdfSmrg
45835c4bbdfSmrg        pPointer->devx = x;
45935c4bbdfSmrg        pPointer->devy = y;
46035c4bbdfSmrg        pPointer->pSpriteCursor = pPointer->pCursor;
46105b261ecSmrg    }
46235c4bbdfSmrg    else if (x != devx || y != devy) {
46335c4bbdfSmrg        pPointer->devx = x;
46435c4bbdfSmrg        pPointer->devy = y;
46535c4bbdfSmrg        if (pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
46635c4bbdfSmrg            (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
46705b261ecSmrg    }
46805b261ecSmrg}
46905b261ecSmrg
47035c4bbdfSmrg/**
47135c4bbdfSmrg * Set the device to the coordinates on the given screen.
47235c4bbdfSmrg *
47335c4bbdfSmrg * @param pDev The device to move
47435c4bbdfSmrg * @param screen_no Index of the screen to move to
47535c4bbdfSmrg * @param x The x coordinate in per-screen coordinates
47635c4bbdfSmrg * @param y The y coordinate in per-screen coordinates
47735c4bbdfSmrg */
47805b261ecSmrgvoid
47905b261ecSmrgmiPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
48005b261ecSmrg{
48135c4bbdfSmrg    ScreenPtr pScreen;
48235c4bbdfSmrg    miPointerPtr pPointer;
48305b261ecSmrg
48435c4bbdfSmrg    pPointer = MIPOINTER(pDev);
4854642e01fSmrg
48635c4bbdfSmrg    pScreen = screenInfo.screens[screen_no];
48735c4bbdfSmrg    mieqSwitchScreen(pDev, pScreen, FALSE);
48835c4bbdfSmrg    NewCurrentScreen(pDev, pScreen, x, y);
48905b261ecSmrg
49035c4bbdfSmrg    pPointer->limits.x2 = pScreen->width;
49135c4bbdfSmrg    pPointer->limits.y2 = pScreen->height;
49205b261ecSmrg}
49305b261ecSmrg
49435c4bbdfSmrg/**
49535c4bbdfSmrg * @return The current screen of the given device or NULL.
49635c4bbdfSmrg */
4976747b715SmrgScreenPtr
49805b261ecSmrgmiPointerGetScreen(DeviceIntPtr pDev)
49905b261ecSmrg{
5004642e01fSmrg    miPointerPtr pPointer = MIPOINTER(pDev);
50135c4bbdfSmrg
5024642e01fSmrg    return (pPointer) ? pPointer->pScreen : NULL;
50305b261ecSmrg}
50405b261ecSmrg
5056747b715Smrg/* Controls whether the cursor image should be updated immediately when
5066747b715Smrg   moved (FALSE) or if something else will be responsible for updating
5076747b715Smrg   it later (TRUE).  Returns current setting.
5086747b715Smrg   Caller is responsible for calling OsBlockSignal first.
5096747b715Smrg*/
5106747b715SmrgBool
5116747b715SmrgmiPointerSetWaitForUpdate(ScreenPtr pScreen, Bool wait)
51205b261ecSmrg{
5136747b715Smrg    SetupScreen(pScreen);
5146747b715Smrg    Bool prevWait = pScreenPriv->waitForUpdate;
5156747b715Smrg
5166747b715Smrg    pScreenPriv->waitForUpdate = wait;
5176747b715Smrg    return prevWait;
51805b261ecSmrg}
51905b261ecSmrg
52005b261ecSmrg/* Move the pointer on the current screen,  and update the sprite. */
52105b261ecSmrgstatic void
52235c4bbdfSmrgmiPointerMoveNoEvent(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
52305b261ecSmrg{
5244642e01fSmrg    miPointerPtr pPointer;
52535c4bbdfSmrg
52605b261ecSmrg    SetupScreen(pScreen);
52705b261ecSmrg
5284642e01fSmrg    pPointer = MIPOINTER(pDev);
5294642e01fSmrg
5304642e01fSmrg    /* Hack: We mustn't call into ->MoveCursor for anything but the
5314642e01fSmrg     * VCP, as this may cause a non-HW rendered cursor to be rendered during
5324642e01fSmrg     * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT.
5334642e01fSmrg     */
53435c4bbdfSmrg    if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer
53535c4bbdfSmrg        &&!pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen) {
53635c4bbdfSmrg        pPointer->devx = x;
53735c4bbdfSmrg        pPointer->devy = y;
53835c4bbdfSmrg        if (pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
53935c4bbdfSmrg            (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
54005b261ecSmrg    }
54105b261ecSmrg
5424642e01fSmrg    pPointer->x = x;
5434642e01fSmrg    pPointer->y = y;
5444642e01fSmrg    pPointer->pScreen = pScreen;
54505b261ecSmrg}
54605b261ecSmrg
54735c4bbdfSmrg/**
54835c4bbdfSmrg * Set the devices' cursor position to the given x/y position.
54935c4bbdfSmrg *
55035c4bbdfSmrg * This function is called during the pointer update path in
55135c4bbdfSmrg * GetPointerEvents and friends (and the same in the xwin DDX).
55235c4bbdfSmrg *
55335c4bbdfSmrg * The coordinates provided are always absolute. The parameter mode whether
55435c4bbdfSmrg * it was relative or absolute movement that landed us at those coordinates.
55535c4bbdfSmrg *
55635c4bbdfSmrg * If the cursor was constrained by a barrier, ET_Barrier* events may be
55735c4bbdfSmrg * generated and appended to the InternalEvent list provided.
55835c4bbdfSmrg *
55935c4bbdfSmrg * @param pDev The device to move
56035c4bbdfSmrg * @param mode Movement mode (Absolute or Relative)
56135c4bbdfSmrg * @param[in,out] screenx The x coordinate in desktop coordinates
56235c4bbdfSmrg * @param[in,out] screeny The y coordinate in desktop coordinates
56335c4bbdfSmrg * @param[in,out] nevents The number of events in events (before/after)
56435c4bbdfSmrg * @param[in,out] events The list of events before/after being constrained
56535c4bbdfSmrg */
56635c4bbdfSmrgScreenPtr
56735c4bbdfSmrgmiPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx,
56835c4bbdfSmrg                     double *screeny,
56935c4bbdfSmrg                     int *nevents, InternalEvent* events)
57005b261ecSmrg{
57135c4bbdfSmrg    miPointerScreenPtr pScreenPriv;
57235c4bbdfSmrg    ScreenPtr pScreen;
57335c4bbdfSmrg    ScreenPtr newScreen;
57435c4bbdfSmrg    int x, y;
57535c4bbdfSmrg    Bool switch_screen = FALSE;
57635c4bbdfSmrg    Bool should_constrain_barriers = FALSE;
57735c4bbdfSmrg    int i;
5784642e01fSmrg
57935c4bbdfSmrg    miPointerPtr pPointer;
5806747b715Smrg
5814642e01fSmrg    pPointer = MIPOINTER(pDev);
5824642e01fSmrg    pScreen = pPointer->pScreen;
58335c4bbdfSmrg
58435c4bbdfSmrg    x = trunc(*screenx);
58535c4bbdfSmrg    y = trunc(*screeny);
58635c4bbdfSmrg
58735c4bbdfSmrg    switch_screen = !point_on_screen(pScreen, x, y);
58835c4bbdfSmrg
58935c4bbdfSmrg    /* Switch to per-screen coordinates for CursorOffScreen and
59035c4bbdfSmrg     * Pointer->limits */
59135c4bbdfSmrg    x -= pScreen->x;
59235c4bbdfSmrg    y -= pScreen->y;
59335c4bbdfSmrg
59435c4bbdfSmrg    should_constrain_barriers = (mode == Relative);
59535c4bbdfSmrg
59635c4bbdfSmrg    if (should_constrain_barriers) {
59735c4bbdfSmrg        /* coordinates after clamped to a barrier */
59835c4bbdfSmrg        int constrained_x, constrained_y;
59935c4bbdfSmrg        int current_x, current_y; /* current position in per-screen coord */
60035c4bbdfSmrg
60135c4bbdfSmrg        current_x = MIPOINTER(pDev)->x - pScreen->x;
60235c4bbdfSmrg        current_y = MIPOINTER(pDev)->y - pScreen->y;
60335c4bbdfSmrg
60435c4bbdfSmrg        input_constrain_cursor(pDev, pScreen,
60535c4bbdfSmrg                               current_x, current_y, x, y,
60635c4bbdfSmrg                               &constrained_x, &constrained_y,
60735c4bbdfSmrg                               nevents, events);
60835c4bbdfSmrg
60935c4bbdfSmrg        x = constrained_x;
61035c4bbdfSmrg        y = constrained_y;
61135c4bbdfSmrg    }
61235c4bbdfSmrg
61335c4bbdfSmrg    if (switch_screen) {
61435c4bbdfSmrg        pScreenPriv = GetScreenPrivate(pScreen);
61535c4bbdfSmrg        if (!pPointer->confined) {
61635c4bbdfSmrg            newScreen = pScreen;
61735c4bbdfSmrg            (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, &x, &y);
61835c4bbdfSmrg            if (newScreen != pScreen) {
61935c4bbdfSmrg                pScreen = newScreen;
62035c4bbdfSmrg                mieqSwitchScreen(pDev, pScreen, FALSE);
62135c4bbdfSmrg                /* Smash the confine to the new screen */
6224642e01fSmrg                pPointer->limits.x2 = pScreen->width;
6234642e01fSmrg                pPointer->limits.y2 = pScreen->height;
62435c4bbdfSmrg            }
62535c4bbdfSmrg        }
62605b261ecSmrg    }
62705b261ecSmrg    /* Constrain the sprite to the current limits. */
62835c4bbdfSmrg    if (x < pPointer->limits.x1)
62935c4bbdfSmrg        x = pPointer->limits.x1;
63035c4bbdfSmrg    if (x >= pPointer->limits.x2)
63135c4bbdfSmrg        x = pPointer->limits.x2 - 1;
63235c4bbdfSmrg    if (y < pPointer->limits.y1)
63335c4bbdfSmrg        y = pPointer->limits.y1;
63435c4bbdfSmrg    if (y >= pPointer->limits.y2)
63535c4bbdfSmrg        y = pPointer->limits.y2 - 1;
63635c4bbdfSmrg
63735c4bbdfSmrg    if (pScreen->ConstrainCursorHarder)
63835c4bbdfSmrg        pScreen->ConstrainCursorHarder(pDev, pScreen, mode, &x, &y);
63935c4bbdfSmrg
64035c4bbdfSmrg    if (pPointer->x != x || pPointer->y != y || pPointer->pScreen != pScreen)
64135c4bbdfSmrg        miPointerMoveNoEvent(pDev, pScreen, x, y);
64235c4bbdfSmrg
64335c4bbdfSmrg    /* check if we generated any barrier events and if so, update root x/y
64435c4bbdfSmrg     * to the fully constrained coords */
64535c4bbdfSmrg    if (should_constrain_barriers) {
64635c4bbdfSmrg        for (i = 0; i < *nevents; i++) {
64735c4bbdfSmrg            if (events[i].any.type == ET_BarrierHit ||
64835c4bbdfSmrg                events[i].any.type == ET_BarrierLeave) {
64935c4bbdfSmrg                events[i].barrier_event.root_x = x;
65035c4bbdfSmrg                events[i].barrier_event.root_y = y;
65135c4bbdfSmrg            }
65235c4bbdfSmrg        }
65335c4bbdfSmrg    }
65405b261ecSmrg
65535c4bbdfSmrg    /* Convert to desktop coordinates again */
65635c4bbdfSmrg    x += pScreen->x;
65735c4bbdfSmrg    y += pScreen->y;
65835c4bbdfSmrg
65935c4bbdfSmrg    /* In the event we actually change screen or we get confined, we just
66035c4bbdfSmrg     * drop the float component on the floor
66135c4bbdfSmrg     * FIXME: only drop remainder for ConstrainCursorHarder, not for screen
66235c4bbdfSmrg     * crossings */
66335c4bbdfSmrg    if (x != trunc(*screenx))
66435c4bbdfSmrg        *screenx = x;
66535c4bbdfSmrg    if (y != trunc(*screeny))
66635c4bbdfSmrg        *screeny = y;
66735c4bbdfSmrg
66835c4bbdfSmrg    return pScreen;
66905b261ecSmrg}
67005b261ecSmrg
67135c4bbdfSmrg/**
67235c4bbdfSmrg * Get the current position of the device in desktop coordinates.
67335c4bbdfSmrg *
67435c4bbdfSmrg * @param x Return value for the current x coordinate in desktop coordiates.
67535c4bbdfSmrg * @param y Return value for the current y coordinate in desktop coordiates.
67635c4bbdfSmrg */
6776747b715Smrgvoid
67805b261ecSmrgmiPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
67905b261ecSmrg{
6804642e01fSmrg    *x = MIPOINTER(pDev)->x;
6814642e01fSmrg    *y = MIPOINTER(pDev)->y;
68205b261ecSmrg}
68305b261ecSmrg
6844642e01fSmrg#ifdef XQUARTZ
6854642e01fSmrg#include <pthread.h>
6864642e01fSmrgvoid darwinEvents_lock(void);
6874642e01fSmrgvoid darwinEvents_unlock(void);
6884642e01fSmrg#endif
6894642e01fSmrg
69035c4bbdfSmrg/**
69135c4bbdfSmrg * Move the device's pointer to the x/y coordinates on the given screen.
69235c4bbdfSmrg * This function generates and enqueues pointer events.
69335c4bbdfSmrg *
69435c4bbdfSmrg * @param pDev The device to move
69535c4bbdfSmrg * @param pScreen The screen the device is on
69635c4bbdfSmrg * @param x The x coordinate in per-screen coordinates
69735c4bbdfSmrg * @param y The y coordinate in per-screen coordinates
69835c4bbdfSmrg */
69905b261ecSmrgvoid
70035c4bbdfSmrgmiPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
70105b261ecSmrg{
70205b261ecSmrg    int i, nevents;
70305b261ecSmrg    int valuators[2];
7049ace9065Smrg    ValuatorMask mask;
70505b261ecSmrg
7066747b715Smrg    miPointerMoveNoEvent(pDev, pScreen, x, y);
70705b261ecSmrg
70805b261ecSmrg    /* generate motion notify */
70905b261ecSmrg    valuators[0] = x;
71005b261ecSmrg    valuators[1] = y;
71105b261ecSmrg
71235c4bbdfSmrg    if (!mipointermove_events) {
71335c4bbdfSmrg        mipointermove_events = InitEventList(GetMaximumEventsNum());
71405b261ecSmrg
71535c4bbdfSmrg        if (!mipointermove_events) {
71605b261ecSmrg            FatalError("Could not allocate event store.\n");
71705b261ecSmrg            return;
71805b261ecSmrg        }
71905b261ecSmrg    }
72005b261ecSmrg
7219ace9065Smrg    valuator_mask_set_range(&mask, 0, 2, valuators);
72235c4bbdfSmrg    nevents = GetPointerEvents(mipointermove_events, pDev, MotionNotify, 0,
72335c4bbdfSmrg                               POINTER_SCREEN | POINTER_ABSOLUTE |
72435c4bbdfSmrg                               POINTER_NORAW, &mask);
72505b261ecSmrg
7264642e01fSmrg    OsBlockSignals();
7274642e01fSmrg#ifdef XQUARTZ
7284642e01fSmrg    darwinEvents_lock();
7294642e01fSmrg#endif
73005b261ecSmrg    for (i = 0; i < nevents; i++)
73135c4bbdfSmrg        mieqEnqueue(pDev, &mipointermove_events[i]);
7324642e01fSmrg#ifdef XQUARTZ
7334642e01fSmrg    darwinEvents_unlock();
7344642e01fSmrg#endif
7354642e01fSmrg    OsReleaseSignals();
73605b261ecSmrg}
737