mipointer.c revision 1b5d61b8
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 681b5d61b8Smrgtypedef struct { 691b5d61b8Smrg ScreenPtr pScreen; /* current screen */ 701b5d61b8Smrg ScreenPtr pSpriteScreen; /* screen containing current sprite */ 711b5d61b8Smrg CursorPtr pCursor; /* current cursor */ 721b5d61b8Smrg CursorPtr pSpriteCursor; /* cursor on screen */ 731b5d61b8Smrg BoxRec limits; /* current constraints */ 741b5d61b8Smrg Bool confined; /* pointer can't change screens */ 751b5d61b8Smrg int x, y; /* hot spot location */ 761b5d61b8Smrg int devx, devy; /* sprite position */ 771b5d61b8Smrg Bool generateEvent; /* generate an event during warping? */ 781b5d61b8Smrg} miPointerRec, *miPointerPtr; 791b5d61b8Smrg 806747b715SmrgDevPrivateKeyRec miPointerScreenKeyRec; 8105b261ecSmrg 824642e01fSmrg#define GetScreenPrivate(s) ((miPointerScreenPtr) \ 834642e01fSmrg dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey)) 8405b261ecSmrg#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s) 8505b261ecSmrg 866747b715SmrgDevPrivateKeyRec miPointerPrivKeyRec; 874642e01fSmrg 884642e01fSmrg#define MIPOINTER(dev) \ 8935c4bbdfSmrg (IsFloating(dev) ? \ 904642e01fSmrg (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \ 916747b715Smrg (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey)) 924642e01fSmrg 9335c4bbdfSmrgstatic Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 944642e01fSmrg CursorPtr pCursor); 9535c4bbdfSmrgstatic Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 964642e01fSmrg CursorPtr pCursor); 9735c4bbdfSmrgstatic Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 984642e01fSmrg CursorPtr pCursor); 994642e01fSmrgstatic void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 10035c4bbdfSmrg BoxPtr pBox); 1014642e01fSmrgstatic void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, 10235c4bbdfSmrg CursorPtr pCursor, BoxPtr pHotBox, 1034642e01fSmrg BoxPtr pTopLeftBox); 10435c4bbdfSmrgstatic Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, 10535c4bbdfSmrg int x, int y, Bool generateEvent); 10635c4bbdfSmrgstatic Bool miPointerCloseScreen(ScreenPtr pScreen); 10735c4bbdfSmrgstatic void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); 1084642e01fSmrgstatic Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen); 10935c4bbdfSmrgstatic void miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen); 11035c4bbdfSmrgstatic void miPointerMoveNoEvent(DeviceIntPtr pDev, ScreenPtr pScreen, int x, 11135c4bbdfSmrg int y); 11205b261ecSmrg 11335c4bbdfSmrgstatic InternalEvent *mipointermove_events; /* for WarpPointer MotionNotifies */ 11405b261ecSmrg 1156747b715SmrgBool 11635c4bbdfSmrgmiPointerInitialize(ScreenPtr pScreen, 11735c4bbdfSmrg miPointerSpriteFuncPtr spriteFuncs, 11835c4bbdfSmrg miPointerScreenFuncPtr screenFuncs, Bool waitForUpdate) 11905b261ecSmrg{ 12035c4bbdfSmrg miPointerScreenPtr pScreenPriv; 12105b261ecSmrg 1226747b715Smrg if (!dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0)) 12335c4bbdfSmrg return FALSE; 1246747b715Smrg 1256747b715Smrg if (!dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0)) 12635c4bbdfSmrg return FALSE; 1276747b715Smrg 12835c4bbdfSmrg pScreenPriv = malloc(sizeof(miPointerScreenRec)); 12905b261ecSmrg if (!pScreenPriv) 13035c4bbdfSmrg return FALSE; 13105b261ecSmrg pScreenPriv->spriteFuncs = spriteFuncs; 13205b261ecSmrg pScreenPriv->screenFuncs = screenFuncs; 13305b261ecSmrg pScreenPriv->waitForUpdate = waitForUpdate; 13405b261ecSmrg pScreenPriv->showTransparent = FALSE; 13505b261ecSmrg pScreenPriv->CloseScreen = pScreen->CloseScreen; 13605b261ecSmrg pScreen->CloseScreen = miPointerCloseScreen; 1374642e01fSmrg dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv); 13805b261ecSmrg /* 13905b261ecSmrg * set up screen cursor method table 14005b261ecSmrg */ 14105b261ecSmrg pScreen->ConstrainCursor = miPointerConstrainCursor; 14205b261ecSmrg pScreen->CursorLimits = miPointerCursorLimits; 14305b261ecSmrg pScreen->DisplayCursor = miPointerDisplayCursor; 14405b261ecSmrg pScreen->RealizeCursor = miPointerRealizeCursor; 14505b261ecSmrg pScreen->UnrealizeCursor = miPointerUnrealizeCursor; 14605b261ecSmrg pScreen->SetCursorPosition = miPointerSetCursorPosition; 14705b261ecSmrg pScreen->RecolorCursor = miRecolorCursor; 1484642e01fSmrg pScreen->DeviceCursorInitialize = miPointerDeviceInitialize; 1494642e01fSmrg pScreen->DeviceCursorCleanup = miPointerDeviceCleanup; 15005b261ecSmrg 15135c4bbdfSmrg mipointermove_events = NULL; 15205b261ecSmrg return TRUE; 15305b261ecSmrg} 15405b261ecSmrg 15535c4bbdfSmrg/** 15635c4bbdfSmrg * Destroy screen-specific information. 15735c4bbdfSmrg * 15835c4bbdfSmrg * @param index Screen index of the screen in screenInfo.screens[] 15935c4bbdfSmrg * @param pScreen The actual screen pointer 16035c4bbdfSmrg */ 16105b261ecSmrgstatic Bool 16235c4bbdfSmrgmiPointerCloseScreen(ScreenPtr pScreen) 16305b261ecSmrg{ 16405b261ecSmrg SetupScreen(pScreen); 16505b261ecSmrg 16605b261ecSmrg pScreen->CloseScreen = pScreenPriv->CloseScreen; 16735c4bbdfSmrg free((void *) pScreenPriv); 16835c4bbdfSmrg FreeEventList(mipointermove_events, GetMaximumEventsNum()); 16935c4bbdfSmrg mipointermove_events = NULL; 17035c4bbdfSmrg return (*pScreen->CloseScreen) (pScreen); 17105b261ecSmrg} 17205b261ecSmrg 17305b261ecSmrg/* 17405b261ecSmrg * DIX/DDX interface routines 17505b261ecSmrg */ 17605b261ecSmrg 17705b261ecSmrgstatic Bool 17835c4bbdfSmrgmiPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 17905b261ecSmrg{ 18005b261ecSmrg SetupScreen(pScreen); 1814642e01fSmrg return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor); 18205b261ecSmrg} 18305b261ecSmrg 18405b261ecSmrgstatic Bool 18535c4bbdfSmrgmiPointerUnrealizeCursor(DeviceIntPtr pDev, 18635c4bbdfSmrg ScreenPtr pScreen, CursorPtr pCursor) 18705b261ecSmrg{ 18805b261ecSmrg SetupScreen(pScreen); 18935c4bbdfSmrg return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, 19035c4bbdfSmrg pCursor); 19105b261ecSmrg} 19205b261ecSmrg 19305b261ecSmrgstatic Bool 19435c4bbdfSmrgmiPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 19505b261ecSmrg{ 1964642e01fSmrg miPointerPtr pPointer; 1974642e01fSmrg 1984642e01fSmrg /* return for keyboards */ 19935c4bbdfSmrg if (!IsPointerDevice(pDev)) 20035c4bbdfSmrg return FALSE; 2014642e01fSmrg 2024642e01fSmrg pPointer = MIPOINTER(pDev); 2034642e01fSmrg 2044642e01fSmrg pPointer->pCursor = pCursor; 2054642e01fSmrg pPointer->pScreen = pScreen; 2064642e01fSmrg miPointerUpdateSprite(pDev); 20705b261ecSmrg return TRUE; 20805b261ecSmrg} 20905b261ecSmrg 21035c4bbdfSmrg/** 21135c4bbdfSmrg * Set up the constraints for the given device. This function does not 21235c4bbdfSmrg * actually constrain the cursor but merely copies the given box to the 21335c4bbdfSmrg * internal constraint storage. 21435c4bbdfSmrg * 21535c4bbdfSmrg * @param pDev The device to constrain to the box 21635c4bbdfSmrg * @param pBox The rectangle to constrain the cursor to 21735c4bbdfSmrg * @param pScreen Used for copying screen confinement 21835c4bbdfSmrg */ 21905b261ecSmrgstatic void 22035c4bbdfSmrgmiPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox) 22105b261ecSmrg{ 2224642e01fSmrg miPointerPtr pPointer; 2234642e01fSmrg 2244642e01fSmrg pPointer = MIPOINTER(pDev); 2254642e01fSmrg 2264642e01fSmrg pPointer->limits = *pBox; 2274642e01fSmrg pPointer->confined = PointerConfinedToScreen(pDev); 22805b261ecSmrg} 22905b261ecSmrg 23035c4bbdfSmrg/** 23135c4bbdfSmrg * Should calculate the box for the given cursor, based on screen and the 23235c4bbdfSmrg * confinement given. But we assume that whatever box is passed in is valid 23335c4bbdfSmrg * anyway. 23435c4bbdfSmrg * 23535c4bbdfSmrg * @param pDev The device to calculate the cursor limits for 23635c4bbdfSmrg * @param pScreen The screen the confinement happens on 23735c4bbdfSmrg * @param pCursor The screen the confinement happens on 23835c4bbdfSmrg * @param pHotBox The confinement box for the cursor 23935c4bbdfSmrg * @param[out] pTopLeftBox The new confinement box, always *pHotBox. 24035c4bbdfSmrg */ 24105b261ecSmrgstatic void 2424642e01fSmrgmiPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, 2434642e01fSmrg BoxPtr pHotBox, BoxPtr pTopLeftBox) 24405b261ecSmrg{ 24505b261ecSmrg *pTopLeftBox = *pHotBox; 24605b261ecSmrg} 24705b261ecSmrg 24835c4bbdfSmrg/** 24935c4bbdfSmrg * Set the device's cursor position to the x/y position on the given screen. 25035c4bbdfSmrg * Generates and event if required. 25135c4bbdfSmrg * 25235c4bbdfSmrg * This function is called from: 25335c4bbdfSmrg * - sprite init code to place onto initial position 25435c4bbdfSmrg * - the various WarpPointer implementations (core, XI, Xinerama, dmx,…) 25535c4bbdfSmrg * - during the cursor update path in CheckMotion 25635c4bbdfSmrg * - in the Xinerama part of NewCurrentScreen 25735c4bbdfSmrg * - when a RandR/RandR1.2 mode was applied (it may have moved the pointer, so 25835c4bbdfSmrg * it's set back to the original pos) 25935c4bbdfSmrg * 26035c4bbdfSmrg * @param pDev The device to move 26135c4bbdfSmrg * @param pScreen The screen the device is on 26235c4bbdfSmrg * @param x The x coordinate in per-screen coordinates 26335c4bbdfSmrg * @param y The y coordinate in per-screen coordinates 26435c4bbdfSmrg * @param generateEvent True if the pointer movement should generate an 26535c4bbdfSmrg * event. 26635c4bbdfSmrg * 26735c4bbdfSmrg * @return TRUE in all cases 26835c4bbdfSmrg */ 26905b261ecSmrgstatic Bool 2704642e01fSmrgmiPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, 2714642e01fSmrg int x, int y, Bool generateEvent) 27205b261ecSmrg{ 27335c4bbdfSmrg SetupScreen(pScreen); 27435c4bbdfSmrg miPointerPtr pPointer = MIPOINTER(pDev); 27535c4bbdfSmrg 27635c4bbdfSmrg pPointer->generateEvent = generateEvent; 27735c4bbdfSmrg 27835c4bbdfSmrg if (pScreen->ConstrainCursorHarder) 27935c4bbdfSmrg pScreen->ConstrainCursorHarder(pDev, pScreen, Absolute, &x, &y); 28005b261ecSmrg 28105b261ecSmrg /* device dependent - must pend signal and call miPointerWarpCursor */ 2824642e01fSmrg (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y); 28305b261ecSmrg if (!generateEvent) 28435c4bbdfSmrg miPointerUpdateSprite(pDev); 28505b261ecSmrg return TRUE; 28605b261ecSmrg} 28705b261ecSmrg 28835c4bbdfSmrgvoid 28935c4bbdfSmrgmiRecolorCursor(DeviceIntPtr pDev, ScreenPtr pScr, 29035c4bbdfSmrg CursorPtr pCurs, Bool displayed) 29135c4bbdfSmrg{ 29235c4bbdfSmrg /* 29335c4bbdfSmrg * This is guaranteed to correct any color-dependent state which may have 29435c4bbdfSmrg * been bound up in private state created by RealizeCursor 29535c4bbdfSmrg */ 29635c4bbdfSmrg pScr->UnrealizeCursor(pDev, pScr, pCurs); 29735c4bbdfSmrg pScr->RealizeCursor(pDev, pScr, pCurs); 29835c4bbdfSmrg if (displayed) 29935c4bbdfSmrg pScr->DisplayCursor(pDev, pScr, pCurs); 30035c4bbdfSmrg} 30135c4bbdfSmrg 30235c4bbdfSmrg/** 30335c4bbdfSmrg * Set up sprite information for the device. 30435c4bbdfSmrg * This function will be called once for each device after it is initialized 30535c4bbdfSmrg * in the DIX. 30635c4bbdfSmrg * 30735c4bbdfSmrg * @param pDev The newly created device 30835c4bbdfSmrg * @param pScreen The initial sprite scree. 3094642e01fSmrg */ 3104642e01fSmrgstatic Bool 3114642e01fSmrgmiPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) 3124642e01fSmrg{ 3134642e01fSmrg miPointerPtr pPointer; 31435c4bbdfSmrg 31535c4bbdfSmrg SetupScreen(pScreen); 3164642e01fSmrg 3176747b715Smrg pPointer = malloc(sizeof(miPointerRec)); 3184642e01fSmrg if (!pPointer) 3194642e01fSmrg return FALSE; 3204642e01fSmrg 3214642e01fSmrg pPointer->pScreen = NULL; 3224642e01fSmrg pPointer->pSpriteScreen = NULL; 3234642e01fSmrg pPointer->pCursor = NULL; 3244642e01fSmrg pPointer->pSpriteCursor = NULL; 3254642e01fSmrg pPointer->limits.x1 = 0; 3264642e01fSmrg pPointer->limits.x2 = 32767; 3274642e01fSmrg pPointer->limits.y1 = 0; 3284642e01fSmrg pPointer->limits.y2 = 32767; 3294642e01fSmrg pPointer->confined = FALSE; 3304642e01fSmrg pPointer->x = 0; 3314642e01fSmrg pPointer->y = 0; 33235c4bbdfSmrg pPointer->generateEvent = FALSE; 3334642e01fSmrg 33435c4bbdfSmrg if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize) (pDev, pScreen))) { 3356747b715Smrg free(pPointer); 3364642e01fSmrg return FALSE; 3374642e01fSmrg } 3384642e01fSmrg 3394642e01fSmrg dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer); 3404642e01fSmrg return TRUE; 3414642e01fSmrg} 3424642e01fSmrg 34335c4bbdfSmrg/** 34435c4bbdfSmrg * Clean up after device. 34535c4bbdfSmrg * This function will be called once before the device is freed in the DIX 34635c4bbdfSmrg * 34735c4bbdfSmrg * @param pDev The device to be removed from the server 34835c4bbdfSmrg * @param pScreen Current screen of the device 3494642e01fSmrg */ 3504642e01fSmrgstatic void 3514642e01fSmrgmiPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) 3524642e01fSmrg{ 3536747b715Smrg SetupScreen(pScreen); 3546747b715Smrg 35535c4bbdfSmrg if (!IsMaster(pDev) && !IsFloating(pDev)) 3564642e01fSmrg return; 3574642e01fSmrg 35835c4bbdfSmrg (*pScreenPriv->spriteFuncs->DeviceCursorCleanup) (pDev, pScreen); 3596747b715Smrg free(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey)); 3604642e01fSmrg dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL); 3614642e01fSmrg} 3624642e01fSmrg 36335c4bbdfSmrg/** 36435c4bbdfSmrg * Warp the pointer to the given position on the given screen. May generate 36535c4bbdfSmrg * an event, depending on whether we're coming from miPointerSetPosition. 36635c4bbdfSmrg * 36735c4bbdfSmrg * Once signals are ignored, the WarpCursor function can call this 36835c4bbdfSmrg * 36935c4bbdfSmrg * @param pDev The device to warp 37035c4bbdfSmrg * @param pScreen Screen to warp on 37135c4bbdfSmrg * @param x The x coordinate in per-screen coordinates 37235c4bbdfSmrg * @param y The y coordinate in per-screen coordinates 37335c4bbdfSmrg */ 37405b261ecSmrg 3756747b715Smrgvoid 37635c4bbdfSmrgmiPointerWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 37705b261ecSmrg{ 3784642e01fSmrg miPointerPtr pPointer; 3794642e01fSmrg BOOL changedScreen = FALSE; 3804642e01fSmrg 3816747b715Smrg pPointer = MIPOINTER(pDev); 38205b261ecSmrg 38335c4bbdfSmrg if (pPointer->pScreen != pScreen) { 38435c4bbdfSmrg mieqSwitchScreen(pDev, pScreen, TRUE); 3854642e01fSmrg changedScreen = TRUE; 3864642e01fSmrg } 38705b261ecSmrg 38835c4bbdfSmrg if (pPointer->generateEvent) 38935c4bbdfSmrg miPointerMove(pDev, pScreen, x, y); 39005b261ecSmrg else 3916747b715Smrg miPointerMoveNoEvent(pDev, pScreen, x, y); 3924642e01fSmrg 3934642e01fSmrg /* Don't call USFS if we use Xinerama, otherwise the root window is 3944642e01fSmrg * updated to the second screen, and we never receive any events. 3954642e01fSmrg * (FDO bug #18668) */ 3964642e01fSmrg if (changedScreen 3974642e01fSmrg#ifdef PANORAMIX 39835c4bbdfSmrg && noPanoramiXExtension 3994642e01fSmrg#endif 40035c4bbdfSmrg ) 40135c4bbdfSmrg UpdateSpriteForScreen(pDev, pScreen); 40205b261ecSmrg} 40305b261ecSmrg 40435c4bbdfSmrg/** 40535c4bbdfSmrg * Syncronize the sprite with the cursor. 40605b261ecSmrg * 40735c4bbdfSmrg * @param pDev The device to sync 40805b261ecSmrg */ 40905b261ecSmrgvoid 41035c4bbdfSmrgmiPointerUpdateSprite(DeviceIntPtr pDev) 41105b261ecSmrg{ 41235c4bbdfSmrg ScreenPtr pScreen; 41335c4bbdfSmrg miPointerScreenPtr pScreenPriv; 41435c4bbdfSmrg CursorPtr pCursor; 41535c4bbdfSmrg int x, y, devx, devy; 41635c4bbdfSmrg miPointerPtr pPointer; 41705b261ecSmrg 4184642e01fSmrg if (!pDev || !pDev->coreEvents) 41905b261ecSmrg return; 42005b261ecSmrg 4214642e01fSmrg pPointer = MIPOINTER(pDev); 4224642e01fSmrg 4236747b715Smrg if (!pPointer) 4246747b715Smrg return; 4256747b715Smrg 4264642e01fSmrg pScreen = pPointer->pScreen; 42705b261ecSmrg if (!pScreen) 42835c4bbdfSmrg return; 42905b261ecSmrg 4304642e01fSmrg x = pPointer->x; 4314642e01fSmrg y = pPointer->y; 4324642e01fSmrg devx = pPointer->devx; 4334642e01fSmrg devy = pPointer->devy; 43405b261ecSmrg 43535c4bbdfSmrg pScreenPriv = GetScreenPrivate(pScreen); 43605b261ecSmrg /* 43705b261ecSmrg * if the cursor has switched screens, disable the sprite 43805b261ecSmrg * on the old screen 43905b261ecSmrg */ 44035c4bbdfSmrg if (pScreen != pPointer->pSpriteScreen) { 44135c4bbdfSmrg if (pPointer->pSpriteScreen) { 44235c4bbdfSmrg miPointerScreenPtr pOldPriv; 44335c4bbdfSmrg 44435c4bbdfSmrg pOldPriv = GetScreenPrivate(pPointer->pSpriteScreen); 44535c4bbdfSmrg if (pPointer->pCursor) { 44635c4bbdfSmrg (*pOldPriv->spriteFuncs->SetCursor) 44735c4bbdfSmrg (pDev, pPointer->pSpriteScreen, NullCursor, 0, 0); 44835c4bbdfSmrg } 44935c4bbdfSmrg (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, 45035c4bbdfSmrg FALSE); 45135c4bbdfSmrg } 45235c4bbdfSmrg (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE); 45335c4bbdfSmrg (*pScreenPriv->spriteFuncs->SetCursor) 45435c4bbdfSmrg (pDev, pScreen, pPointer->pCursor, x, y); 45535c4bbdfSmrg pPointer->devx = x; 45635c4bbdfSmrg pPointer->devy = y; 45735c4bbdfSmrg pPointer->pSpriteCursor = pPointer->pCursor; 45835c4bbdfSmrg pPointer->pSpriteScreen = pScreen; 45905b261ecSmrg } 46005b261ecSmrg /* 46105b261ecSmrg * if the cursor has changed, display the new one 46205b261ecSmrg */ 46335c4bbdfSmrg else if (pPointer->pCursor != pPointer->pSpriteCursor) { 46435c4bbdfSmrg pCursor = pPointer->pCursor; 46535c4bbdfSmrg if (!pCursor || 46635c4bbdfSmrg (pCursor->bits->emptyMask && !pScreenPriv->showTransparent)) 46735c4bbdfSmrg pCursor = NullCursor; 46835c4bbdfSmrg (*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y); 46935c4bbdfSmrg 47035c4bbdfSmrg pPointer->devx = x; 47135c4bbdfSmrg pPointer->devy = y; 47235c4bbdfSmrg pPointer->pSpriteCursor = pPointer->pCursor; 47305b261ecSmrg } 47435c4bbdfSmrg else if (x != devx || y != devy) { 47535c4bbdfSmrg pPointer->devx = x; 47635c4bbdfSmrg pPointer->devy = y; 47735c4bbdfSmrg if (pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) 47835c4bbdfSmrg (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); 47905b261ecSmrg } 48005b261ecSmrg} 48105b261ecSmrg 4821b5d61b8Smrg/** 4831b5d61b8Smrg * Invalidate the current sprite and force it to be reloaded on next cursor setting 4841b5d61b8Smrg * operation 4851b5d61b8Smrg * 4861b5d61b8Smrg * @param pDev The device to invalidate the sprite fore 4871b5d61b8Smrg */ 4881b5d61b8Smrgvoid 4891b5d61b8SmrgmiPointerInvalidateSprite(DeviceIntPtr pDev) 4901b5d61b8Smrg{ 4911b5d61b8Smrg miPointerPtr pPointer; 4921b5d61b8Smrg 4931b5d61b8Smrg pPointer = MIPOINTER(pDev); 4941b5d61b8Smrg pPointer->pSpriteCursor = (CursorPtr) 1; 4951b5d61b8Smrg} 4961b5d61b8Smrg 49735c4bbdfSmrg/** 49835c4bbdfSmrg * Set the device to the coordinates on the given screen. 49935c4bbdfSmrg * 50035c4bbdfSmrg * @param pDev The device to move 50135c4bbdfSmrg * @param screen_no Index of the screen to move to 50235c4bbdfSmrg * @param x The x coordinate in per-screen coordinates 50335c4bbdfSmrg * @param y The y coordinate in per-screen coordinates 50435c4bbdfSmrg */ 50505b261ecSmrgvoid 50605b261ecSmrgmiPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y) 50705b261ecSmrg{ 50835c4bbdfSmrg ScreenPtr pScreen; 50935c4bbdfSmrg miPointerPtr pPointer; 51005b261ecSmrg 51135c4bbdfSmrg pPointer = MIPOINTER(pDev); 5124642e01fSmrg 51335c4bbdfSmrg pScreen = screenInfo.screens[screen_no]; 51435c4bbdfSmrg mieqSwitchScreen(pDev, pScreen, FALSE); 51535c4bbdfSmrg NewCurrentScreen(pDev, pScreen, x, y); 51605b261ecSmrg 51735c4bbdfSmrg pPointer->limits.x2 = pScreen->width; 51835c4bbdfSmrg pPointer->limits.y2 = pScreen->height; 51905b261ecSmrg} 52005b261ecSmrg 52135c4bbdfSmrg/** 52235c4bbdfSmrg * @return The current screen of the given device or NULL. 52335c4bbdfSmrg */ 5246747b715SmrgScreenPtr 52505b261ecSmrgmiPointerGetScreen(DeviceIntPtr pDev) 52605b261ecSmrg{ 5274642e01fSmrg miPointerPtr pPointer = MIPOINTER(pDev); 52835c4bbdfSmrg 5294642e01fSmrg return (pPointer) ? pPointer->pScreen : NULL; 53005b261ecSmrg} 53105b261ecSmrg 5326747b715Smrg/* Controls whether the cursor image should be updated immediately when 5336747b715Smrg moved (FALSE) or if something else will be responsible for updating 5346747b715Smrg it later (TRUE). Returns current setting. 5356747b715Smrg Caller is responsible for calling OsBlockSignal first. 5366747b715Smrg*/ 5376747b715SmrgBool 5386747b715SmrgmiPointerSetWaitForUpdate(ScreenPtr pScreen, Bool wait) 53905b261ecSmrg{ 5406747b715Smrg SetupScreen(pScreen); 5416747b715Smrg Bool prevWait = pScreenPriv->waitForUpdate; 5426747b715Smrg 5436747b715Smrg pScreenPriv->waitForUpdate = wait; 5446747b715Smrg return prevWait; 54505b261ecSmrg} 54605b261ecSmrg 54705b261ecSmrg/* Move the pointer on the current screen, and update the sprite. */ 54805b261ecSmrgstatic void 54935c4bbdfSmrgmiPointerMoveNoEvent(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 55005b261ecSmrg{ 5514642e01fSmrg miPointerPtr pPointer; 55235c4bbdfSmrg 55305b261ecSmrg SetupScreen(pScreen); 55405b261ecSmrg 5554642e01fSmrg pPointer = MIPOINTER(pDev); 5564642e01fSmrg 5574642e01fSmrg /* Hack: We mustn't call into ->MoveCursor for anything but the 5581b5d61b8Smrg * VCP, as this may cause a non-HW rendered cursor to be rendered while 5591b5d61b8Smrg * not holding the input lock. This would race with building the command 5601b5d61b8Smrg * buffer for other rendering. 5614642e01fSmrg */ 56235c4bbdfSmrg if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer 56335c4bbdfSmrg &&!pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen) { 56435c4bbdfSmrg pPointer->devx = x; 56535c4bbdfSmrg pPointer->devy = y; 56635c4bbdfSmrg if (pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) 56735c4bbdfSmrg (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); 56805b261ecSmrg } 56905b261ecSmrg 5704642e01fSmrg pPointer->x = x; 5714642e01fSmrg pPointer->y = y; 5724642e01fSmrg pPointer->pScreen = pScreen; 57305b261ecSmrg} 57405b261ecSmrg 57535c4bbdfSmrg/** 57635c4bbdfSmrg * Set the devices' cursor position to the given x/y position. 57735c4bbdfSmrg * 57835c4bbdfSmrg * This function is called during the pointer update path in 57935c4bbdfSmrg * GetPointerEvents and friends (and the same in the xwin DDX). 58035c4bbdfSmrg * 58135c4bbdfSmrg * The coordinates provided are always absolute. The parameter mode whether 58235c4bbdfSmrg * it was relative or absolute movement that landed us at those coordinates. 58335c4bbdfSmrg * 58435c4bbdfSmrg * If the cursor was constrained by a barrier, ET_Barrier* events may be 58535c4bbdfSmrg * generated and appended to the InternalEvent list provided. 58635c4bbdfSmrg * 58735c4bbdfSmrg * @param pDev The device to move 58835c4bbdfSmrg * @param mode Movement mode (Absolute or Relative) 58935c4bbdfSmrg * @param[in,out] screenx The x coordinate in desktop coordinates 59035c4bbdfSmrg * @param[in,out] screeny The y coordinate in desktop coordinates 59135c4bbdfSmrg * @param[in,out] nevents The number of events in events (before/after) 59235c4bbdfSmrg * @param[in,out] events The list of events before/after being constrained 59335c4bbdfSmrg */ 59435c4bbdfSmrgScreenPtr 59535c4bbdfSmrgmiPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx, 59635c4bbdfSmrg double *screeny, 59735c4bbdfSmrg int *nevents, InternalEvent* events) 59805b261ecSmrg{ 59935c4bbdfSmrg miPointerScreenPtr pScreenPriv; 60035c4bbdfSmrg ScreenPtr pScreen; 60135c4bbdfSmrg ScreenPtr newScreen; 60235c4bbdfSmrg int x, y; 60335c4bbdfSmrg Bool switch_screen = FALSE; 60435c4bbdfSmrg Bool should_constrain_barriers = FALSE; 60535c4bbdfSmrg int i; 6064642e01fSmrg 60735c4bbdfSmrg miPointerPtr pPointer; 6086747b715Smrg 6094642e01fSmrg pPointer = MIPOINTER(pDev); 6104642e01fSmrg pScreen = pPointer->pScreen; 61135c4bbdfSmrg 61235c4bbdfSmrg x = trunc(*screenx); 61335c4bbdfSmrg y = trunc(*screeny); 61435c4bbdfSmrg 61535c4bbdfSmrg switch_screen = !point_on_screen(pScreen, x, y); 61635c4bbdfSmrg 61735c4bbdfSmrg /* Switch to per-screen coordinates for CursorOffScreen and 61835c4bbdfSmrg * Pointer->limits */ 61935c4bbdfSmrg x -= pScreen->x; 62035c4bbdfSmrg y -= pScreen->y; 62135c4bbdfSmrg 62235c4bbdfSmrg should_constrain_barriers = (mode == Relative); 62335c4bbdfSmrg 62435c4bbdfSmrg if (should_constrain_barriers) { 62535c4bbdfSmrg /* coordinates after clamped to a barrier */ 62635c4bbdfSmrg int constrained_x, constrained_y; 62735c4bbdfSmrg int current_x, current_y; /* current position in per-screen coord */ 62835c4bbdfSmrg 62935c4bbdfSmrg current_x = MIPOINTER(pDev)->x - pScreen->x; 63035c4bbdfSmrg current_y = MIPOINTER(pDev)->y - pScreen->y; 63135c4bbdfSmrg 63235c4bbdfSmrg input_constrain_cursor(pDev, pScreen, 63335c4bbdfSmrg current_x, current_y, x, y, 63435c4bbdfSmrg &constrained_x, &constrained_y, 63535c4bbdfSmrg nevents, events); 63635c4bbdfSmrg 63735c4bbdfSmrg x = constrained_x; 63835c4bbdfSmrg y = constrained_y; 63935c4bbdfSmrg } 64035c4bbdfSmrg 64135c4bbdfSmrg if (switch_screen) { 64235c4bbdfSmrg pScreenPriv = GetScreenPrivate(pScreen); 64335c4bbdfSmrg if (!pPointer->confined) { 64435c4bbdfSmrg newScreen = pScreen; 64535c4bbdfSmrg (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, &x, &y); 64635c4bbdfSmrg if (newScreen != pScreen) { 64735c4bbdfSmrg pScreen = newScreen; 64835c4bbdfSmrg mieqSwitchScreen(pDev, pScreen, FALSE); 64935c4bbdfSmrg /* Smash the confine to the new screen */ 6504642e01fSmrg pPointer->limits.x2 = pScreen->width; 6514642e01fSmrg pPointer->limits.y2 = pScreen->height; 65235c4bbdfSmrg } 65335c4bbdfSmrg } 65405b261ecSmrg } 65505b261ecSmrg /* Constrain the sprite to the current limits. */ 65635c4bbdfSmrg if (x < pPointer->limits.x1) 65735c4bbdfSmrg x = pPointer->limits.x1; 65835c4bbdfSmrg if (x >= pPointer->limits.x2) 65935c4bbdfSmrg x = pPointer->limits.x2 - 1; 66035c4bbdfSmrg if (y < pPointer->limits.y1) 66135c4bbdfSmrg y = pPointer->limits.y1; 66235c4bbdfSmrg if (y >= pPointer->limits.y2) 66335c4bbdfSmrg y = pPointer->limits.y2 - 1; 66435c4bbdfSmrg 66535c4bbdfSmrg if (pScreen->ConstrainCursorHarder) 66635c4bbdfSmrg pScreen->ConstrainCursorHarder(pDev, pScreen, mode, &x, &y); 66735c4bbdfSmrg 66835c4bbdfSmrg if (pPointer->x != x || pPointer->y != y || pPointer->pScreen != pScreen) 66935c4bbdfSmrg miPointerMoveNoEvent(pDev, pScreen, x, y); 67035c4bbdfSmrg 67135c4bbdfSmrg /* check if we generated any barrier events and if so, update root x/y 67235c4bbdfSmrg * to the fully constrained coords */ 67335c4bbdfSmrg if (should_constrain_barriers) { 67435c4bbdfSmrg for (i = 0; i < *nevents; i++) { 67535c4bbdfSmrg if (events[i].any.type == ET_BarrierHit || 67635c4bbdfSmrg events[i].any.type == ET_BarrierLeave) { 67735c4bbdfSmrg events[i].barrier_event.root_x = x; 67835c4bbdfSmrg events[i].barrier_event.root_y = y; 67935c4bbdfSmrg } 68035c4bbdfSmrg } 68135c4bbdfSmrg } 68205b261ecSmrg 68335c4bbdfSmrg /* Convert to desktop coordinates again */ 68435c4bbdfSmrg x += pScreen->x; 68535c4bbdfSmrg y += pScreen->y; 68635c4bbdfSmrg 68735c4bbdfSmrg /* In the event we actually change screen or we get confined, we just 68835c4bbdfSmrg * drop the float component on the floor 68935c4bbdfSmrg * FIXME: only drop remainder for ConstrainCursorHarder, not for screen 69035c4bbdfSmrg * crossings */ 69135c4bbdfSmrg if (x != trunc(*screenx)) 69235c4bbdfSmrg *screenx = x; 69335c4bbdfSmrg if (y != trunc(*screeny)) 69435c4bbdfSmrg *screeny = y; 69535c4bbdfSmrg 69635c4bbdfSmrg return pScreen; 69705b261ecSmrg} 69805b261ecSmrg 69935c4bbdfSmrg/** 70035c4bbdfSmrg * Get the current position of the device in desktop coordinates. 70135c4bbdfSmrg * 70235c4bbdfSmrg * @param x Return value for the current x coordinate in desktop coordiates. 70335c4bbdfSmrg * @param y Return value for the current y coordinate in desktop coordiates. 70435c4bbdfSmrg */ 7056747b715Smrgvoid 70605b261ecSmrgmiPointerGetPosition(DeviceIntPtr pDev, int *x, int *y) 70705b261ecSmrg{ 7084642e01fSmrg *x = MIPOINTER(pDev)->x; 7094642e01fSmrg *y = MIPOINTER(pDev)->y; 71005b261ecSmrg} 71105b261ecSmrg 71235c4bbdfSmrg/** 71335c4bbdfSmrg * Move the device's pointer to the x/y coordinates on the given screen. 71435c4bbdfSmrg * This function generates and enqueues pointer events. 71535c4bbdfSmrg * 71635c4bbdfSmrg * @param pDev The device to move 71735c4bbdfSmrg * @param pScreen The screen the device is on 71835c4bbdfSmrg * @param x The x coordinate in per-screen coordinates 71935c4bbdfSmrg * @param y The y coordinate in per-screen coordinates 72035c4bbdfSmrg */ 72105b261ecSmrgvoid 72235c4bbdfSmrgmiPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 72305b261ecSmrg{ 72405b261ecSmrg int i, nevents; 72505b261ecSmrg int valuators[2]; 7269ace9065Smrg ValuatorMask mask; 72705b261ecSmrg 7286747b715Smrg miPointerMoveNoEvent(pDev, pScreen, x, y); 72905b261ecSmrg 73005b261ecSmrg /* generate motion notify */ 73105b261ecSmrg valuators[0] = x; 73205b261ecSmrg valuators[1] = y; 73305b261ecSmrg 73435c4bbdfSmrg if (!mipointermove_events) { 73535c4bbdfSmrg mipointermove_events = InitEventList(GetMaximumEventsNum()); 73605b261ecSmrg 73735c4bbdfSmrg if (!mipointermove_events) { 73805b261ecSmrg FatalError("Could not allocate event store.\n"); 73905b261ecSmrg return; 74005b261ecSmrg } 74105b261ecSmrg } 74205b261ecSmrg 7439ace9065Smrg valuator_mask_set_range(&mask, 0, 2, valuators); 74435c4bbdfSmrg nevents = GetPointerEvents(mipointermove_events, pDev, MotionNotify, 0, 74535c4bbdfSmrg POINTER_SCREEN | POINTER_ABSOLUTE | 74635c4bbdfSmrg POINTER_NORAW, &mask); 74705b261ecSmrg 7481b5d61b8Smrg input_lock(); 74905b261ecSmrg for (i = 0; i < nevents; i++) 75035c4bbdfSmrg mieqEnqueue(pDev, &mipointermove_events[i]); 7511b5d61b8Smrg input_unlock(); 75205b261ecSmrg} 753