1706f2543Smrg/* 2706f2543Smrg 3706f2543SmrgCopyright 1989, 1998 The Open Group 4706f2543Smrg 5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its 6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that 7706f2543Smrgthe above copyright notice appear in all copies and that both that 8706f2543Smrgcopyright notice and this permission notice appear in supporting 9706f2543Smrgdocumentation. 10706f2543Smrg 11706f2543SmrgThe above copyright notice and this permission notice shall be included in 12706f2543Smrgall copies or substantial portions of the Software. 13706f2543Smrg 14706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20706f2543Smrg 21706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be 22706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings 23706f2543Smrgin this Software without prior written authorization from The Open Group. 24706f2543Smrg*/ 25706f2543Smrg 26706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 27706f2543Smrg#include <dix-config.h> 28706f2543Smrg#endif 29706f2543Smrg 30706f2543Smrg# include <X11/X.h> 31706f2543Smrg# include <X11/Xmd.h> 32706f2543Smrg# include <X11/Xproto.h> 33706f2543Smrg# include "misc.h" 34706f2543Smrg# include "windowstr.h" 35706f2543Smrg# include "pixmapstr.h" 36706f2543Smrg# include "mi.h" 37706f2543Smrg# include "scrnintstr.h" 38706f2543Smrg# include "mipointrst.h" 39706f2543Smrg# include "cursorstr.h" 40706f2543Smrg# include "dixstruct.h" 41706f2543Smrg# include "inputstr.h" 42706f2543Smrg# include "inpututils.h" 43706f2543Smrg 44bc1411c9Smrg# include "eventstr.h" 45bc1411c9Smrg 46706f2543SmrgDevPrivateKeyRec miPointerScreenKeyRec; 47706f2543Smrg 48706f2543Smrg#define GetScreenPrivate(s) ((miPointerScreenPtr) \ 49706f2543Smrg dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey)) 50706f2543Smrg#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s) 51706f2543Smrg 52706f2543SmrgDevPrivateKeyRec miPointerPrivKeyRec; 53706f2543Smrg 54706f2543Smrg#define MIPOINTER(dev) \ 55706f2543Smrg ((!IsMaster(dev) && !dev->u.master) ? \ 56706f2543Smrg (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \ 57706f2543Smrg (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey)) 58706f2543Smrg 59706f2543Smrgstatic Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 60706f2543Smrg CursorPtr pCursor); 61706f2543Smrgstatic Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 62706f2543Smrg CursorPtr pCursor); 63706f2543Smrgstatic Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 64706f2543Smrg CursorPtr pCursor); 65706f2543Smrgstatic void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 66706f2543Smrg BoxPtr pBox); 67706f2543Smrgstatic void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, 68706f2543Smrg CursorPtr pCursor, BoxPtr pHotBox, 69706f2543Smrg BoxPtr pTopLeftBox); 70706f2543Smrgstatic Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, 71706f2543Smrg int x, int y, 72706f2543Smrg Bool generateEvent); 73706f2543Smrgstatic Bool miPointerCloseScreen(int index, ScreenPtr pScreen); 74706f2543Smrgstatic void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, 75706f2543Smrg int x, int y); 76706f2543Smrgstatic Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen); 77706f2543Smrgstatic void miPointerDeviceCleanup(DeviceIntPtr pDev, 78706f2543Smrg ScreenPtr pScreen); 79706f2543Smrgstatic void miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); 80706f2543Smrg 81706f2543Smrgstatic EventList* events; /* for WarpPointer MotionNotifies */ 82706f2543Smrg 83706f2543SmrgBool 84706f2543SmrgmiPointerInitialize (ScreenPtr pScreen, 85706f2543Smrg miPointerSpriteFuncPtr spriteFuncs, 86706f2543Smrg miPointerScreenFuncPtr screenFuncs, 87706f2543Smrg Bool waitForUpdate) 88706f2543Smrg{ 89706f2543Smrg miPointerScreenPtr pScreenPriv; 90706f2543Smrg 91706f2543Smrg if (!dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0)) 92706f2543Smrg return FALSE; 93706f2543Smrg 94706f2543Smrg if (!dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0)) 95706f2543Smrg return FALSE; 96706f2543Smrg 97706f2543Smrg pScreenPriv = malloc(sizeof (miPointerScreenRec)); 98706f2543Smrg if (!pScreenPriv) 99706f2543Smrg return FALSE; 100706f2543Smrg pScreenPriv->spriteFuncs = spriteFuncs; 101706f2543Smrg pScreenPriv->screenFuncs = screenFuncs; 102706f2543Smrg /* 103706f2543Smrg * check for uninitialized methods 104706f2543Smrg */ 105706f2543Smrg if (!screenFuncs->EnqueueEvent) 106706f2543Smrg screenFuncs->EnqueueEvent = mieqEnqueue; 107706f2543Smrg if (!screenFuncs->NewEventScreen) 108706f2543Smrg screenFuncs->NewEventScreen = mieqSwitchScreen; 109706f2543Smrg pScreenPriv->waitForUpdate = waitForUpdate; 110706f2543Smrg pScreenPriv->showTransparent = FALSE; 111706f2543Smrg pScreenPriv->CloseScreen = pScreen->CloseScreen; 112706f2543Smrg pScreen->CloseScreen = miPointerCloseScreen; 113706f2543Smrg dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv); 114706f2543Smrg /* 115706f2543Smrg * set up screen cursor method table 116706f2543Smrg */ 117706f2543Smrg pScreen->ConstrainCursor = miPointerConstrainCursor; 118706f2543Smrg pScreen->CursorLimits = miPointerCursorLimits; 119706f2543Smrg pScreen->DisplayCursor = miPointerDisplayCursor; 120706f2543Smrg pScreen->RealizeCursor = miPointerRealizeCursor; 121706f2543Smrg pScreen->UnrealizeCursor = miPointerUnrealizeCursor; 122706f2543Smrg pScreen->SetCursorPosition = miPointerSetCursorPosition; 123706f2543Smrg pScreen->RecolorCursor = miRecolorCursor; 124706f2543Smrg pScreen->DeviceCursorInitialize = miPointerDeviceInitialize; 125706f2543Smrg pScreen->DeviceCursorCleanup = miPointerDeviceCleanup; 126706f2543Smrg 127706f2543Smrg events = NULL; 128706f2543Smrg return TRUE; 129706f2543Smrg} 130706f2543Smrg 131706f2543Smrgstatic Bool 132706f2543SmrgmiPointerCloseScreen (int index, ScreenPtr pScreen) 133706f2543Smrg{ 134706f2543Smrg#if 0 135706f2543Smrg miPointerPtr pPointer; 136706f2543Smrg DeviceIntPtr pDev; 137706f2543Smrg#endif 138706f2543Smrg 139706f2543Smrg SetupScreen(pScreen); 140706f2543Smrg 141706f2543Smrg#if 0 142706f2543Smrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) 143706f2543Smrg { 144706f2543Smrg if (DevHasCursor(pDev)) 145706f2543Smrg { 146706f2543Smrg pPointer = MIPOINTER(pDev); 147706f2543Smrg 148706f2543Smrg if (pScreen == pPointer->pScreen) 149706f2543Smrg pPointer->pScreen = 0; 150706f2543Smrg if (pScreen == pPointer->pSpriteScreen) 151706f2543Smrg pPointer->pSpriteScreen = 0; 152706f2543Smrg } 153706f2543Smrg } 154706f2543Smrg 155706f2543Smrg if (MIPOINTER(inputInfo.pointer)->pScreen == pScreen) 156706f2543Smrg MIPOINTER(inputInfo.pointer)->pScreen = 0; 157706f2543Smrg if (MIPOINTER(inputInfo.pointer)->pSpriteScreen == pScreen) 158706f2543Smrg MIPOINTER(inputInfo.pointer)->pSpriteScreen = 0; 159706f2543Smrg#endif 160706f2543Smrg 161706f2543Smrg pScreen->CloseScreen = pScreenPriv->CloseScreen; 162706f2543Smrg free((pointer) pScreenPriv); 163706f2543Smrg FreeEventList(events, GetMaximumEventsNum()); 164706f2543Smrg events = NULL; 165706f2543Smrg return (*pScreen->CloseScreen) (index, pScreen); 166706f2543Smrg} 167706f2543Smrg 168706f2543Smrg/* 169706f2543Smrg * DIX/DDX interface routines 170706f2543Smrg */ 171706f2543Smrg 172706f2543Smrgstatic Bool 173706f2543SmrgmiPointerRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 174706f2543Smrg{ 175706f2543Smrg SetupScreen(pScreen); 176706f2543Smrg return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor); 177706f2543Smrg} 178706f2543Smrg 179706f2543Smrgstatic Bool 180706f2543SmrgmiPointerUnrealizeCursor (DeviceIntPtr pDev, 181706f2543Smrg ScreenPtr pScreen, 182706f2543Smrg CursorPtr pCursor) 183706f2543Smrg{ 184706f2543Smrg SetupScreen(pScreen); 185706f2543Smrg return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor); 186706f2543Smrg} 187706f2543Smrg 188706f2543Smrgstatic Bool 189706f2543SmrgmiPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 190706f2543Smrg{ 191706f2543Smrg miPointerPtr pPointer; 192706f2543Smrg 193706f2543Smrg /* return for keyboards */ 194706f2543Smrg if ((IsMaster(pDev) && !DevHasCursor(pDev)) || 195706f2543Smrg (!IsMaster(pDev) && pDev->u.master && !DevHasCursor(pDev->u.master))) 196706f2543Smrg return FALSE; 197706f2543Smrg 198706f2543Smrg pPointer = MIPOINTER(pDev); 199706f2543Smrg 200706f2543Smrg pPointer->pCursor = pCursor; 201706f2543Smrg pPointer->pScreen = pScreen; 202706f2543Smrg miPointerUpdateSprite(pDev); 203706f2543Smrg return TRUE; 204706f2543Smrg} 205706f2543Smrg 206706f2543Smrgstatic void 207706f2543SmrgmiPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox) 208706f2543Smrg{ 209706f2543Smrg miPointerPtr pPointer; 210706f2543Smrg 211706f2543Smrg pPointer = MIPOINTER(pDev); 212706f2543Smrg 213706f2543Smrg pPointer->limits = *pBox; 214706f2543Smrg pPointer->confined = PointerConfinedToScreen(pDev); 215706f2543Smrg} 216706f2543Smrg 217706f2543Smrg/*ARGSUSED*/ 218706f2543Smrgstatic void 219706f2543SmrgmiPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, 220706f2543Smrg BoxPtr pHotBox, BoxPtr pTopLeftBox) 221706f2543Smrg{ 222706f2543Smrg *pTopLeftBox = *pHotBox; 223706f2543Smrg} 224706f2543Smrg 225706f2543Smrgstatic Bool GenerateEvent; 226706f2543Smrg 227706f2543Smrgstatic Bool 228706f2543SmrgmiPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, 229706f2543Smrg int x, int y, Bool generateEvent) 230706f2543Smrg{ 231706f2543Smrg SetupScreen (pScreen); 232706f2543Smrg 233706f2543Smrg GenerateEvent = generateEvent; 234706f2543Smrg /* device dependent - must pend signal and call miPointerWarpCursor */ 235706f2543Smrg (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y); 236706f2543Smrg if (!generateEvent) 237706f2543Smrg miPointerUpdateSprite(pDev); 238706f2543Smrg return TRUE; 239706f2543Smrg} 240706f2543Smrg 241706f2543Smrg/* Set up sprite information for the device. 242706f2543Smrg This function will be called once for each device after it is initialized 243706f2543Smrg in the DIX. 244706f2543Smrg */ 245706f2543Smrgstatic Bool 246706f2543SmrgmiPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) 247706f2543Smrg{ 248706f2543Smrg miPointerPtr pPointer; 249706f2543Smrg SetupScreen (pScreen); 250706f2543Smrg 251706f2543Smrg pPointer = malloc(sizeof(miPointerRec)); 252706f2543Smrg if (!pPointer) 253706f2543Smrg return FALSE; 254706f2543Smrg 255706f2543Smrg pPointer->pScreen = NULL; 256706f2543Smrg pPointer->pSpriteScreen = NULL; 257706f2543Smrg pPointer->pCursor = NULL; 258706f2543Smrg pPointer->pSpriteCursor = NULL; 259706f2543Smrg pPointer->limits.x1 = 0; 260706f2543Smrg pPointer->limits.x2 = 32767; 261706f2543Smrg pPointer->limits.y1 = 0; 262706f2543Smrg pPointer->limits.y2 = 32767; 263706f2543Smrg pPointer->confined = FALSE; 264706f2543Smrg pPointer->x = 0; 265706f2543Smrg pPointer->y = 0; 266706f2543Smrg 267706f2543Smrg if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen))) 268706f2543Smrg { 269706f2543Smrg free(pPointer); 270706f2543Smrg return FALSE; 271706f2543Smrg } 272706f2543Smrg 273706f2543Smrg dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer); 274706f2543Smrg return TRUE; 275706f2543Smrg} 276706f2543Smrg 277706f2543Smrg/* Clean up after device. 278706f2543Smrg This function will be called once before the device is freed in the DIX 279706f2543Smrg */ 280706f2543Smrgstatic void 281706f2543SmrgmiPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) 282706f2543Smrg{ 283706f2543Smrg SetupScreen(pScreen); 284706f2543Smrg 285706f2543Smrg if (!IsMaster(pDev) && pDev->u.master) 286706f2543Smrg return; 287706f2543Smrg 288706f2543Smrg (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen); 289706f2543Smrg free(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey)); 290706f2543Smrg dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL); 291706f2543Smrg} 292706f2543Smrg 293706f2543Smrg 294706f2543Smrg/* Once signals are ignored, the WarpCursor function can call this */ 295706f2543Smrg 296706f2543Smrgvoid 297706f2543SmrgmiPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 298706f2543Smrg{ 299706f2543Smrg miPointerPtr pPointer; 300706f2543Smrg BOOL changedScreen = FALSE; 301706f2543Smrg 302706f2543Smrg SetupScreen (pScreen); 303706f2543Smrg pPointer = MIPOINTER(pDev); 304706f2543Smrg 305706f2543Smrg if (pPointer->pScreen != pScreen) 306706f2543Smrg { 307706f2543Smrg (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE); 308706f2543Smrg changedScreen = TRUE; 309706f2543Smrg } 310706f2543Smrg 311706f2543Smrg if (GenerateEvent) 312706f2543Smrg miPointerMove (pDev, pScreen, x, y); 313706f2543Smrg else 314706f2543Smrg miPointerMoveNoEvent(pDev, pScreen, x, y); 315706f2543Smrg 316706f2543Smrg /* Don't call USFS if we use Xinerama, otherwise the root window is 317706f2543Smrg * updated to the second screen, and we never receive any events. 318706f2543Smrg * (FDO bug #18668) */ 319706f2543Smrg if (changedScreen 320706f2543Smrg#ifdef PANORAMIX 321706f2543Smrg && noPanoramiXExtension 322706f2543Smrg#endif 323bc1411c9Smrg ) { 324bc1411c9Smrg DeviceIntPtr master = GetMaster(pDev, MASTER_POINTER); 325bc1411c9Smrg /* Hack for CVE-2023-5380: if we're moving 326bc1411c9Smrg * screens PointerWindows[] keeps referring to the 327bc1411c9Smrg * old window. If that gets destroyed we have a UAF 328bc1411c9Smrg * bug later. Only happens when jumping from a window 329bc1411c9Smrg * to the root window on the other screen. 330bc1411c9Smrg * Enter/Leave events are incorrect for that case but 331bc1411c9Smrg * too niche to fix. 332bc1411c9Smrg */ 333bc1411c9Smrg LeaveWindow(pDev); 334bc1411c9Smrg if (master) 335bc1411c9Smrg LeaveWindow(master); 336bc1411c9Smrg UpdateSpriteForScreen(pDev, pScreen); 337bc1411c9Smrg } 338706f2543Smrg} 339706f2543Smrg 340706f2543Smrg/* 341706f2543Smrg * Pointer/CursorDisplay interface routines 342706f2543Smrg */ 343706f2543Smrg 344706f2543Smrg/* 345706f2543Smrg * miPointerUpdateSprite 346706f2543Smrg * 347706f2543Smrg * Syncronize the sprite with the cursor - called from ProcessInputEvents 348706f2543Smrg */ 349706f2543Smrg 350706f2543Smrgvoid 351706f2543SmrgmiPointerUpdateSprite (DeviceIntPtr pDev) 352706f2543Smrg{ 353706f2543Smrg ScreenPtr pScreen; 354706f2543Smrg miPointerScreenPtr pScreenPriv; 355706f2543Smrg CursorPtr pCursor; 356706f2543Smrg int x, y, devx, devy; 357706f2543Smrg miPointerPtr pPointer; 358706f2543Smrg 359706f2543Smrg if (!pDev || !pDev->coreEvents) 360706f2543Smrg return; 361706f2543Smrg 362706f2543Smrg pPointer = MIPOINTER(pDev); 363706f2543Smrg 364706f2543Smrg if (!pPointer) 365706f2543Smrg return; 366706f2543Smrg 367706f2543Smrg pScreen = pPointer->pScreen; 368706f2543Smrg if (!pScreen) 369706f2543Smrg return; 370706f2543Smrg 371706f2543Smrg x = pPointer->x; 372706f2543Smrg y = pPointer->y; 373706f2543Smrg devx = pPointer->devx; 374706f2543Smrg devy = pPointer->devy; 375706f2543Smrg 376706f2543Smrg pScreenPriv = GetScreenPrivate (pScreen); 377706f2543Smrg /* 378706f2543Smrg * if the cursor has switched screens, disable the sprite 379706f2543Smrg * on the old screen 380706f2543Smrg */ 381706f2543Smrg if (pScreen != pPointer->pSpriteScreen) 382706f2543Smrg { 383706f2543Smrg if (pPointer->pSpriteScreen) 384706f2543Smrg { 385706f2543Smrg miPointerScreenPtr pOldPriv; 386706f2543Smrg 387706f2543Smrg pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen); 388706f2543Smrg if (pPointer->pCursor) 389706f2543Smrg { 390706f2543Smrg (*pOldPriv->spriteFuncs->SetCursor) 391706f2543Smrg (pDev, pPointer->pSpriteScreen, NullCursor, 0, 0); 392706f2543Smrg } 393706f2543Smrg (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE); 394706f2543Smrg } 395706f2543Smrg (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE); 396706f2543Smrg (*pScreenPriv->spriteFuncs->SetCursor) 397706f2543Smrg (pDev, pScreen, pPointer->pCursor, x, y); 398706f2543Smrg pPointer->devx = x; 399706f2543Smrg pPointer->devy = y; 400706f2543Smrg pPointer->pSpriteCursor = pPointer->pCursor; 401706f2543Smrg pPointer->pSpriteScreen = pScreen; 402706f2543Smrg } 403706f2543Smrg /* 404706f2543Smrg * if the cursor has changed, display the new one 405706f2543Smrg */ 406706f2543Smrg else if (pPointer->pCursor != pPointer->pSpriteCursor) 407706f2543Smrg { 408706f2543Smrg pCursor = pPointer->pCursor; 409706f2543Smrg if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent)) 410706f2543Smrg pCursor = NullCursor; 411706f2543Smrg (*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y); 412706f2543Smrg 413706f2543Smrg pPointer->devx = x; 414706f2543Smrg pPointer->devy = y; 415706f2543Smrg pPointer->pSpriteCursor = pPointer->pCursor; 416706f2543Smrg } 417706f2543Smrg else if (x != devx || y != devy) 418706f2543Smrg { 419706f2543Smrg pPointer->devx = x; 420706f2543Smrg pPointer->devy = y; 421706f2543Smrg if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) 422706f2543Smrg (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); 423706f2543Smrg } 424706f2543Smrg} 425706f2543Smrg 426706f2543Smrgvoid 427706f2543SmrgmiPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y) 428706f2543Smrg{ 429706f2543Smrg miPointerScreenPtr pScreenPriv; 430706f2543Smrg ScreenPtr pScreen; 431706f2543Smrg miPointerPtr pPointer; 432706f2543Smrg 433706f2543Smrg pPointer = MIPOINTER(pDev); 434706f2543Smrg 435706f2543Smrg pScreen = screenInfo.screens[screen_no]; 436706f2543Smrg pScreenPriv = GetScreenPrivate (pScreen); 437706f2543Smrg (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE); 438706f2543Smrg NewCurrentScreen (pDev, pScreen, x, y); 439706f2543Smrg 440706f2543Smrg pPointer->limits.x2 = pScreen->width; 441706f2543Smrg pPointer->limits.y2 = pScreen->height; 442706f2543Smrg} 443706f2543Smrg 444706f2543SmrgScreenPtr 445706f2543SmrgmiPointerCurrentScreen (void) 446706f2543Smrg{ 447706f2543Smrg return miPointerGetScreen(inputInfo.pointer); 448706f2543Smrg} 449706f2543Smrg 450706f2543SmrgScreenPtr 451706f2543SmrgmiPointerGetScreen(DeviceIntPtr pDev) 452706f2543Smrg{ 453706f2543Smrg miPointerPtr pPointer = MIPOINTER(pDev); 454706f2543Smrg return (pPointer) ? pPointer->pScreen : NULL; 455706f2543Smrg} 456706f2543Smrg 457706f2543Smrg/* Controls whether the cursor image should be updated immediately when 458706f2543Smrg moved (FALSE) or if something else will be responsible for updating 459706f2543Smrg it later (TRUE). Returns current setting. 460706f2543Smrg Caller is responsible for calling OsBlockSignal first. 461706f2543Smrg*/ 462706f2543SmrgBool 463706f2543SmrgmiPointerSetWaitForUpdate(ScreenPtr pScreen, Bool wait) 464706f2543Smrg{ 465706f2543Smrg SetupScreen(pScreen); 466706f2543Smrg Bool prevWait = pScreenPriv->waitForUpdate; 467706f2543Smrg 468706f2543Smrg pScreenPriv->waitForUpdate = wait; 469706f2543Smrg return prevWait; 470706f2543Smrg} 471706f2543Smrg 472706f2543Smrg 473706f2543Smrg/* Move the pointer on the current screen, and update the sprite. */ 474706f2543Smrgstatic void 475706f2543SmrgmiPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, 476706f2543Smrg int x, int y) 477706f2543Smrg{ 478706f2543Smrg miPointerPtr pPointer; 479706f2543Smrg SetupScreen(pScreen); 480706f2543Smrg 481706f2543Smrg pPointer = MIPOINTER(pDev); 482706f2543Smrg 483706f2543Smrg /* Hack: We mustn't call into ->MoveCursor for anything but the 484706f2543Smrg * VCP, as this may cause a non-HW rendered cursor to be rendered during 485706f2543Smrg * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT. 486706f2543Smrg */ 487706f2543Smrg if ((pDev == inputInfo.pointer || (!IsMaster(pDev) && pDev->u.master == inputInfo.pointer)) 488706f2543Smrg && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen) 489706f2543Smrg { 490706f2543Smrg pPointer->devx = x; 491706f2543Smrg pPointer->devy = y; 492706f2543Smrg if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) 493706f2543Smrg (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); 494706f2543Smrg } 495706f2543Smrg 496706f2543Smrg pPointer->x = x; 497706f2543Smrg pPointer->y = y; 498706f2543Smrg pPointer->pScreen = pScreen; 499706f2543Smrg} 500706f2543Smrg 501706f2543Smrgvoid 502706f2543SmrgmiPointerSetPosition(DeviceIntPtr pDev, int *x, int *y) 503706f2543Smrg{ 504706f2543Smrg miPointerScreenPtr pScreenPriv; 505706f2543Smrg ScreenPtr pScreen; 506706f2543Smrg ScreenPtr newScreen; 507706f2543Smrg 508706f2543Smrg miPointerPtr pPointer; 509706f2543Smrg 510706f2543Smrg if (!pDev || !pDev->coreEvents) 511706f2543Smrg return; 512706f2543Smrg 513706f2543Smrg pPointer = MIPOINTER(pDev); 514706f2543Smrg pScreen = pPointer->pScreen; 515706f2543Smrg if (!pScreen) 516706f2543Smrg return; /* called before ready */ 517706f2543Smrg 518706f2543Smrg if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height) 519706f2543Smrg { 520706f2543Smrg pScreenPriv = GetScreenPrivate (pScreen); 521706f2543Smrg if (!pPointer->confined) 522706f2543Smrg { 523706f2543Smrg newScreen = pScreen; 524706f2543Smrg (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y); 525706f2543Smrg if (newScreen != pScreen) 526706f2543Smrg { 527706f2543Smrg pScreen = newScreen; 528706f2543Smrg (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, 529706f2543Smrg FALSE); 530706f2543Smrg /* Smash the confine to the new screen */ 531706f2543Smrg pPointer->limits.x2 = pScreen->width; 532706f2543Smrg pPointer->limits.y2 = pScreen->height; 533706f2543Smrg } 534706f2543Smrg } 535706f2543Smrg } 536706f2543Smrg /* Constrain the sprite to the current limits. */ 537706f2543Smrg if (*x < pPointer->limits.x1) 538706f2543Smrg *x = pPointer->limits.x1; 539706f2543Smrg if (*x >= pPointer->limits.x2) 540706f2543Smrg *x = pPointer->limits.x2 - 1; 541706f2543Smrg if (*y < pPointer->limits.y1) 542706f2543Smrg *y = pPointer->limits.y1; 543706f2543Smrg if (*y >= pPointer->limits.y2) 544706f2543Smrg *y = pPointer->limits.y2 - 1; 545706f2543Smrg 546706f2543Smrg if (pPointer->x == *x && pPointer->y == *y && 547706f2543Smrg pPointer->pScreen == pScreen) 548706f2543Smrg return; 549706f2543Smrg 550706f2543Smrg miPointerMoveNoEvent(pDev, pScreen, *x, *y); 551706f2543Smrg} 552706f2543Smrg 553706f2543Smrgvoid 554706f2543SmrgmiPointerGetPosition(DeviceIntPtr pDev, int *x, int *y) 555706f2543Smrg{ 556706f2543Smrg *x = MIPOINTER(pDev)->x; 557706f2543Smrg *y = MIPOINTER(pDev)->y; 558706f2543Smrg} 559706f2543Smrg 560706f2543Smrg#ifdef XQUARTZ 561706f2543Smrg#include <pthread.h> 562706f2543Smrgvoid darwinEvents_lock(void); 563706f2543Smrgvoid darwinEvents_unlock(void); 564706f2543Smrg#endif 565706f2543Smrg 566706f2543Smrgvoid 567706f2543SmrgmiPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 568706f2543Smrg{ 569706f2543Smrg int i, nevents; 570706f2543Smrg int valuators[2]; 571706f2543Smrg ValuatorMask mask; 572706f2543Smrg 573706f2543Smrg miPointerMoveNoEvent(pDev, pScreen, x, y); 574706f2543Smrg 575706f2543Smrg /* generate motion notify */ 576706f2543Smrg valuators[0] = x; 577706f2543Smrg valuators[1] = y; 578706f2543Smrg 579706f2543Smrg if (!events) 580706f2543Smrg { 581706f2543Smrg events = InitEventList(GetMaximumEventsNum()); 582706f2543Smrg 583706f2543Smrg if (!events) 584706f2543Smrg { 585706f2543Smrg FatalError("Could not allocate event store.\n"); 586706f2543Smrg return; 587706f2543Smrg } 588706f2543Smrg } 589706f2543Smrg 590706f2543Smrg valuator_mask_set_range(&mask, 0, 2, valuators); 591706f2543Smrg nevents = GetPointerEvents(events, pDev, MotionNotify, 0, 592706f2543Smrg POINTER_SCREEN | POINTER_ABSOLUTE | POINTER_NORAW, &mask); 593706f2543Smrg 594706f2543Smrg OsBlockSignals(); 595706f2543Smrg#ifdef XQUARTZ 596706f2543Smrg darwinEvents_lock(); 597706f2543Smrg#endif 598706f2543Smrg for (i = 0; i < nevents; i++) 599706f2543Smrg mieqEnqueue(pDev, (InternalEvent*)events[i].event); 600706f2543Smrg#ifdef XQUARTZ 601706f2543Smrg darwinEvents_unlock(); 602706f2543Smrg#endif 603706f2543Smrg OsReleaseSignals(); 604706f2543Smrg} 605