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