mipointer.c revision 1b5d61b8
1/* 2 3Copyright 1989, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24*/ 25 26/** 27 * @file 28 * This file contains functions to move the pointer on the screen and/or 29 * restrict its movement. These functions are divided into two sets: 30 * Screen-specific functions that are used as function pointers from other 31 * parts of the server (and end up heavily wrapped by e.g. animcur and 32 * xfixes): 33 * miPointerConstrainCursor 34 * miPointerCursorLimits 35 * miPointerDisplayCursor 36 * miPointerRealizeCursor 37 * miPointerUnrealizeCursor 38 * miPointerSetCursorPosition 39 * miRecolorCursor 40 * miPointerDeviceInitialize 41 * miPointerDeviceCleanup 42 * If wrapped, these are the last element in the wrapping chain. They may 43 * call into sprite-specific code through further function pointers though. 44 * 45 * The second type of functions are those that are directly called by the 46 * DIX, DDX and some drivers. 47 */ 48 49#ifdef HAVE_DIX_CONFIG_H 50#include <dix-config.h> 51#endif 52 53#include <X11/X.h> 54#include <X11/Xmd.h> 55#include <X11/Xproto.h> 56#include "misc.h" 57#include "windowstr.h" 58#include "pixmapstr.h" 59#include "mi.h" 60#include "scrnintstr.h" 61#include "mipointrst.h" 62#include "cursorstr.h" 63#include "dixstruct.h" 64#include "inputstr.h" 65#include "inpututils.h" 66#include "eventstr.h" 67 68typedef struct { 69 ScreenPtr pScreen; /* current screen */ 70 ScreenPtr pSpriteScreen; /* screen containing current sprite */ 71 CursorPtr pCursor; /* current cursor */ 72 CursorPtr pSpriteCursor; /* cursor on screen */ 73 BoxRec limits; /* current constraints */ 74 Bool confined; /* pointer can't change screens */ 75 int x, y; /* hot spot location */ 76 int devx, devy; /* sprite position */ 77 Bool generateEvent; /* generate an event during warping? */ 78} miPointerRec, *miPointerPtr; 79 80DevPrivateKeyRec miPointerScreenKeyRec; 81 82#define GetScreenPrivate(s) ((miPointerScreenPtr) \ 83 dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey)) 84#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s) 85 86DevPrivateKeyRec miPointerPrivKeyRec; 87 88#define MIPOINTER(dev) \ 89 (IsFloating(dev) ? \ 90 (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \ 91 (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey)) 92 93static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 94 CursorPtr pCursor); 95static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 96 CursorPtr pCursor); 97static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 98 CursorPtr pCursor); 99static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 100 BoxPtr pBox); 101static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, 102 CursorPtr pCursor, BoxPtr pHotBox, 103 BoxPtr pTopLeftBox); 104static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, 105 int x, int y, Bool generateEvent); 106static Bool miPointerCloseScreen(ScreenPtr pScreen); 107static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); 108static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen); 109static void miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen); 110static void miPointerMoveNoEvent(DeviceIntPtr pDev, ScreenPtr pScreen, int x, 111 int y); 112 113static InternalEvent *mipointermove_events; /* for WarpPointer MotionNotifies */ 114 115Bool 116miPointerInitialize(ScreenPtr pScreen, 117 miPointerSpriteFuncPtr spriteFuncs, 118 miPointerScreenFuncPtr screenFuncs, Bool waitForUpdate) 119{ 120 miPointerScreenPtr pScreenPriv; 121 122 if (!dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0)) 123 return FALSE; 124 125 if (!dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0)) 126 return FALSE; 127 128 pScreenPriv = malloc(sizeof(miPointerScreenRec)); 129 if (!pScreenPriv) 130 return FALSE; 131 pScreenPriv->spriteFuncs = spriteFuncs; 132 pScreenPriv->screenFuncs = screenFuncs; 133 pScreenPriv->waitForUpdate = waitForUpdate; 134 pScreenPriv->showTransparent = FALSE; 135 pScreenPriv->CloseScreen = pScreen->CloseScreen; 136 pScreen->CloseScreen = miPointerCloseScreen; 137 dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv); 138 /* 139 * set up screen cursor method table 140 */ 141 pScreen->ConstrainCursor = miPointerConstrainCursor; 142 pScreen->CursorLimits = miPointerCursorLimits; 143 pScreen->DisplayCursor = miPointerDisplayCursor; 144 pScreen->RealizeCursor = miPointerRealizeCursor; 145 pScreen->UnrealizeCursor = miPointerUnrealizeCursor; 146 pScreen->SetCursorPosition = miPointerSetCursorPosition; 147 pScreen->RecolorCursor = miRecolorCursor; 148 pScreen->DeviceCursorInitialize = miPointerDeviceInitialize; 149 pScreen->DeviceCursorCleanup = miPointerDeviceCleanup; 150 151 mipointermove_events = NULL; 152 return TRUE; 153} 154 155/** 156 * Destroy screen-specific information. 157 * 158 * @param index Screen index of the screen in screenInfo.screens[] 159 * @param pScreen The actual screen pointer 160 */ 161static Bool 162miPointerCloseScreen(ScreenPtr pScreen) 163{ 164 SetupScreen(pScreen); 165 166 pScreen->CloseScreen = pScreenPriv->CloseScreen; 167 free((void *) pScreenPriv); 168 FreeEventList(mipointermove_events, GetMaximumEventsNum()); 169 mipointermove_events = NULL; 170 return (*pScreen->CloseScreen) (pScreen); 171} 172 173/* 174 * DIX/DDX interface routines 175 */ 176 177static Bool 178miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 179{ 180 SetupScreen(pScreen); 181 return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor); 182} 183 184static Bool 185miPointerUnrealizeCursor(DeviceIntPtr pDev, 186 ScreenPtr pScreen, CursorPtr pCursor) 187{ 188 SetupScreen(pScreen); 189 return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, 190 pCursor); 191} 192 193static Bool 194miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) 195{ 196 miPointerPtr pPointer; 197 198 /* return for keyboards */ 199 if (!IsPointerDevice(pDev)) 200 return FALSE; 201 202 pPointer = MIPOINTER(pDev); 203 204 pPointer->pCursor = pCursor; 205 pPointer->pScreen = pScreen; 206 miPointerUpdateSprite(pDev); 207 return TRUE; 208} 209 210/** 211 * Set up the constraints for the given device. This function does not 212 * actually constrain the cursor but merely copies the given box to the 213 * internal constraint storage. 214 * 215 * @param pDev The device to constrain to the box 216 * @param pBox The rectangle to constrain the cursor to 217 * @param pScreen Used for copying screen confinement 218 */ 219static void 220miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox) 221{ 222 miPointerPtr pPointer; 223 224 pPointer = MIPOINTER(pDev); 225 226 pPointer->limits = *pBox; 227 pPointer->confined = PointerConfinedToScreen(pDev); 228} 229 230/** 231 * Should calculate the box for the given cursor, based on screen and the 232 * confinement given. But we assume that whatever box is passed in is valid 233 * anyway. 234 * 235 * @param pDev The device to calculate the cursor limits for 236 * @param pScreen The screen the confinement happens on 237 * @param pCursor The screen the confinement happens on 238 * @param pHotBox The confinement box for the cursor 239 * @param[out] pTopLeftBox The new confinement box, always *pHotBox. 240 */ 241static void 242miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, 243 BoxPtr pHotBox, BoxPtr pTopLeftBox) 244{ 245 *pTopLeftBox = *pHotBox; 246} 247 248/** 249 * Set the device's cursor position to the x/y position on the given screen. 250 * Generates and event if required. 251 * 252 * This function is called from: 253 * - sprite init code to place onto initial position 254 * - the various WarpPointer implementations (core, XI, Xinerama, dmx,…) 255 * - during the cursor update path in CheckMotion 256 * - in the Xinerama part of NewCurrentScreen 257 * - when a RandR/RandR1.2 mode was applied (it may have moved the pointer, so 258 * it's set back to the original pos) 259 * 260 * @param pDev The device to move 261 * @param pScreen The screen the device is on 262 * @param x The x coordinate in per-screen coordinates 263 * @param y The y coordinate in per-screen coordinates 264 * @param generateEvent True if the pointer movement should generate an 265 * event. 266 * 267 * @return TRUE in all cases 268 */ 269static Bool 270miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, 271 int x, int y, Bool generateEvent) 272{ 273 SetupScreen(pScreen); 274 miPointerPtr pPointer = MIPOINTER(pDev); 275 276 pPointer->generateEvent = generateEvent; 277 278 if (pScreen->ConstrainCursorHarder) 279 pScreen->ConstrainCursorHarder(pDev, pScreen, Absolute, &x, &y); 280 281 /* device dependent - must pend signal and call miPointerWarpCursor */ 282 (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y); 283 if (!generateEvent) 284 miPointerUpdateSprite(pDev); 285 return TRUE; 286} 287 288void 289miRecolorCursor(DeviceIntPtr pDev, ScreenPtr pScr, 290 CursorPtr pCurs, Bool displayed) 291{ 292 /* 293 * This is guaranteed to correct any color-dependent state which may have 294 * been bound up in private state created by RealizeCursor 295 */ 296 pScr->UnrealizeCursor(pDev, pScr, pCurs); 297 pScr->RealizeCursor(pDev, pScr, pCurs); 298 if (displayed) 299 pScr->DisplayCursor(pDev, pScr, pCurs); 300} 301 302/** 303 * Set up sprite information for the device. 304 * This function will be called once for each device after it is initialized 305 * in the DIX. 306 * 307 * @param pDev The newly created device 308 * @param pScreen The initial sprite scree. 309 */ 310static Bool 311miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) 312{ 313 miPointerPtr pPointer; 314 315 SetupScreen(pScreen); 316 317 pPointer = malloc(sizeof(miPointerRec)); 318 if (!pPointer) 319 return FALSE; 320 321 pPointer->pScreen = NULL; 322 pPointer->pSpriteScreen = NULL; 323 pPointer->pCursor = NULL; 324 pPointer->pSpriteCursor = NULL; 325 pPointer->limits.x1 = 0; 326 pPointer->limits.x2 = 32767; 327 pPointer->limits.y1 = 0; 328 pPointer->limits.y2 = 32767; 329 pPointer->confined = FALSE; 330 pPointer->x = 0; 331 pPointer->y = 0; 332 pPointer->generateEvent = FALSE; 333 334 if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize) (pDev, pScreen))) { 335 free(pPointer); 336 return FALSE; 337 } 338 339 dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer); 340 return TRUE; 341} 342 343/** 344 * Clean up after device. 345 * This function will be called once before the device is freed in the DIX 346 * 347 * @param pDev The device to be removed from the server 348 * @param pScreen Current screen of the device 349 */ 350static void 351miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) 352{ 353 SetupScreen(pScreen); 354 355 if (!IsMaster(pDev) && !IsFloating(pDev)) 356 return; 357 358 (*pScreenPriv->spriteFuncs->DeviceCursorCleanup) (pDev, pScreen); 359 free(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey)); 360 dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL); 361} 362 363/** 364 * Warp the pointer to the given position on the given screen. May generate 365 * an event, depending on whether we're coming from miPointerSetPosition. 366 * 367 * Once signals are ignored, the WarpCursor function can call this 368 * 369 * @param pDev The device to warp 370 * @param pScreen Screen to warp on 371 * @param x The x coordinate in per-screen coordinates 372 * @param y The y coordinate in per-screen coordinates 373 */ 374 375void 376miPointerWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 377{ 378 miPointerPtr pPointer; 379 BOOL changedScreen = FALSE; 380 381 pPointer = MIPOINTER(pDev); 382 383 if (pPointer->pScreen != pScreen) { 384 mieqSwitchScreen(pDev, pScreen, TRUE); 385 changedScreen = TRUE; 386 } 387 388 if (pPointer->generateEvent) 389 miPointerMove(pDev, pScreen, x, y); 390 else 391 miPointerMoveNoEvent(pDev, pScreen, x, y); 392 393 /* Don't call USFS if we use Xinerama, otherwise the root window is 394 * updated to the second screen, and we never receive any events. 395 * (FDO bug #18668) */ 396 if (changedScreen 397#ifdef PANORAMIX 398 && noPanoramiXExtension 399#endif 400 ) 401 UpdateSpriteForScreen(pDev, pScreen); 402} 403 404/** 405 * Syncronize the sprite with the cursor. 406 * 407 * @param pDev The device to sync 408 */ 409void 410miPointerUpdateSprite(DeviceIntPtr pDev) 411{ 412 ScreenPtr pScreen; 413 miPointerScreenPtr pScreenPriv; 414 CursorPtr pCursor; 415 int x, y, devx, devy; 416 miPointerPtr pPointer; 417 418 if (!pDev || !pDev->coreEvents) 419 return; 420 421 pPointer = MIPOINTER(pDev); 422 423 if (!pPointer) 424 return; 425 426 pScreen = pPointer->pScreen; 427 if (!pScreen) 428 return; 429 430 x = pPointer->x; 431 y = pPointer->y; 432 devx = pPointer->devx; 433 devy = pPointer->devy; 434 435 pScreenPriv = GetScreenPrivate(pScreen); 436 /* 437 * if the cursor has switched screens, disable the sprite 438 * on the old screen 439 */ 440 if (pScreen != pPointer->pSpriteScreen) { 441 if (pPointer->pSpriteScreen) { 442 miPointerScreenPtr pOldPriv; 443 444 pOldPriv = GetScreenPrivate(pPointer->pSpriteScreen); 445 if (pPointer->pCursor) { 446 (*pOldPriv->spriteFuncs->SetCursor) 447 (pDev, pPointer->pSpriteScreen, NullCursor, 0, 0); 448 } 449 (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, 450 FALSE); 451 } 452 (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE); 453 (*pScreenPriv->spriteFuncs->SetCursor) 454 (pDev, pScreen, pPointer->pCursor, x, y); 455 pPointer->devx = x; 456 pPointer->devy = y; 457 pPointer->pSpriteCursor = pPointer->pCursor; 458 pPointer->pSpriteScreen = pScreen; 459 } 460 /* 461 * if the cursor has changed, display the new one 462 */ 463 else if (pPointer->pCursor != pPointer->pSpriteCursor) { 464 pCursor = pPointer->pCursor; 465 if (!pCursor || 466 (pCursor->bits->emptyMask && !pScreenPriv->showTransparent)) 467 pCursor = NullCursor; 468 (*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y); 469 470 pPointer->devx = x; 471 pPointer->devy = y; 472 pPointer->pSpriteCursor = pPointer->pCursor; 473 } 474 else if (x != devx || y != devy) { 475 pPointer->devx = x; 476 pPointer->devy = y; 477 if (pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) 478 (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); 479 } 480} 481 482/** 483 * Invalidate the current sprite and force it to be reloaded on next cursor setting 484 * operation 485 * 486 * @param pDev The device to invalidate the sprite fore 487 */ 488void 489miPointerInvalidateSprite(DeviceIntPtr pDev) 490{ 491 miPointerPtr pPointer; 492 493 pPointer = MIPOINTER(pDev); 494 pPointer->pSpriteCursor = (CursorPtr) 1; 495} 496 497/** 498 * Set the device to the coordinates on the given screen. 499 * 500 * @param pDev The device to move 501 * @param screen_no Index of the screen to move to 502 * @param x The x coordinate in per-screen coordinates 503 * @param y The y coordinate in per-screen coordinates 504 */ 505void 506miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y) 507{ 508 ScreenPtr pScreen; 509 miPointerPtr pPointer; 510 511 pPointer = MIPOINTER(pDev); 512 513 pScreen = screenInfo.screens[screen_no]; 514 mieqSwitchScreen(pDev, pScreen, FALSE); 515 NewCurrentScreen(pDev, pScreen, x, y); 516 517 pPointer->limits.x2 = pScreen->width; 518 pPointer->limits.y2 = pScreen->height; 519} 520 521/** 522 * @return The current screen of the given device or NULL. 523 */ 524ScreenPtr 525miPointerGetScreen(DeviceIntPtr pDev) 526{ 527 miPointerPtr pPointer = MIPOINTER(pDev); 528 529 return (pPointer) ? pPointer->pScreen : NULL; 530} 531 532/* Controls whether the cursor image should be updated immediately when 533 moved (FALSE) or if something else will be responsible for updating 534 it later (TRUE). Returns current setting. 535 Caller is responsible for calling OsBlockSignal first. 536*/ 537Bool 538miPointerSetWaitForUpdate(ScreenPtr pScreen, Bool wait) 539{ 540 SetupScreen(pScreen); 541 Bool prevWait = pScreenPriv->waitForUpdate; 542 543 pScreenPriv->waitForUpdate = wait; 544 return prevWait; 545} 546 547/* Move the pointer on the current screen, and update the sprite. */ 548static void 549miPointerMoveNoEvent(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 550{ 551 miPointerPtr pPointer; 552 553 SetupScreen(pScreen); 554 555 pPointer = MIPOINTER(pDev); 556 557 /* Hack: We mustn't call into ->MoveCursor for anything but the 558 * VCP, as this may cause a non-HW rendered cursor to be rendered while 559 * not holding the input lock. This would race with building the command 560 * buffer for other rendering. 561 */ 562 if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer 563 &&!pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen) { 564 pPointer->devx = x; 565 pPointer->devy = y; 566 if (pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) 567 (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); 568 } 569 570 pPointer->x = x; 571 pPointer->y = y; 572 pPointer->pScreen = pScreen; 573} 574 575/** 576 * Set the devices' cursor position to the given x/y position. 577 * 578 * This function is called during the pointer update path in 579 * GetPointerEvents and friends (and the same in the xwin DDX). 580 * 581 * The coordinates provided are always absolute. The parameter mode whether 582 * it was relative or absolute movement that landed us at those coordinates. 583 * 584 * If the cursor was constrained by a barrier, ET_Barrier* events may be 585 * generated and appended to the InternalEvent list provided. 586 * 587 * @param pDev The device to move 588 * @param mode Movement mode (Absolute or Relative) 589 * @param[in,out] screenx The x coordinate in desktop coordinates 590 * @param[in,out] screeny The y coordinate in desktop coordinates 591 * @param[in,out] nevents The number of events in events (before/after) 592 * @param[in,out] events The list of events before/after being constrained 593 */ 594ScreenPtr 595miPointerSetPosition(DeviceIntPtr pDev, int mode, double *screenx, 596 double *screeny, 597 int *nevents, InternalEvent* events) 598{ 599 miPointerScreenPtr pScreenPriv; 600 ScreenPtr pScreen; 601 ScreenPtr newScreen; 602 int x, y; 603 Bool switch_screen = FALSE; 604 Bool should_constrain_barriers = FALSE; 605 int i; 606 607 miPointerPtr pPointer; 608 609 pPointer = MIPOINTER(pDev); 610 pScreen = pPointer->pScreen; 611 612 x = trunc(*screenx); 613 y = trunc(*screeny); 614 615 switch_screen = !point_on_screen(pScreen, x, y); 616 617 /* Switch to per-screen coordinates for CursorOffScreen and 618 * Pointer->limits */ 619 x -= pScreen->x; 620 y -= pScreen->y; 621 622 should_constrain_barriers = (mode == Relative); 623 624 if (should_constrain_barriers) { 625 /* coordinates after clamped to a barrier */ 626 int constrained_x, constrained_y; 627 int current_x, current_y; /* current position in per-screen coord */ 628 629 current_x = MIPOINTER(pDev)->x - pScreen->x; 630 current_y = MIPOINTER(pDev)->y - pScreen->y; 631 632 input_constrain_cursor(pDev, pScreen, 633 current_x, current_y, x, y, 634 &constrained_x, &constrained_y, 635 nevents, events); 636 637 x = constrained_x; 638 y = constrained_y; 639 } 640 641 if (switch_screen) { 642 pScreenPriv = GetScreenPrivate(pScreen); 643 if (!pPointer->confined) { 644 newScreen = pScreen; 645 (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, &x, &y); 646 if (newScreen != pScreen) { 647 pScreen = newScreen; 648 mieqSwitchScreen(pDev, pScreen, FALSE); 649 /* Smash the confine to the new screen */ 650 pPointer->limits.x2 = pScreen->width; 651 pPointer->limits.y2 = pScreen->height; 652 } 653 } 654 } 655 /* Constrain the sprite to the current limits. */ 656 if (x < pPointer->limits.x1) 657 x = pPointer->limits.x1; 658 if (x >= pPointer->limits.x2) 659 x = pPointer->limits.x2 - 1; 660 if (y < pPointer->limits.y1) 661 y = pPointer->limits.y1; 662 if (y >= pPointer->limits.y2) 663 y = pPointer->limits.y2 - 1; 664 665 if (pScreen->ConstrainCursorHarder) 666 pScreen->ConstrainCursorHarder(pDev, pScreen, mode, &x, &y); 667 668 if (pPointer->x != x || pPointer->y != y || pPointer->pScreen != pScreen) 669 miPointerMoveNoEvent(pDev, pScreen, x, y); 670 671 /* check if we generated any barrier events and if so, update root x/y 672 * to the fully constrained coords */ 673 if (should_constrain_barriers) { 674 for (i = 0; i < *nevents; i++) { 675 if (events[i].any.type == ET_BarrierHit || 676 events[i].any.type == ET_BarrierLeave) { 677 events[i].barrier_event.root_x = x; 678 events[i].barrier_event.root_y = y; 679 } 680 } 681 } 682 683 /* Convert to desktop coordinates again */ 684 x += pScreen->x; 685 y += pScreen->y; 686 687 /* In the event we actually change screen or we get confined, we just 688 * drop the float component on the floor 689 * FIXME: only drop remainder for ConstrainCursorHarder, not for screen 690 * crossings */ 691 if (x != trunc(*screenx)) 692 *screenx = x; 693 if (y != trunc(*screeny)) 694 *screeny = y; 695 696 return pScreen; 697} 698 699/** 700 * Get the current position of the device in desktop coordinates. 701 * 702 * @param x Return value for the current x coordinate in desktop coordiates. 703 * @param y Return value for the current y coordinate in desktop coordiates. 704 */ 705void 706miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y) 707{ 708 *x = MIPOINTER(pDev)->x; 709 *y = MIPOINTER(pDev)->y; 710} 711 712/** 713 * Move the device's pointer to the x/y coordinates on the given screen. 714 * This function generates and enqueues pointer events. 715 * 716 * @param pDev The device to move 717 * @param pScreen The screen the device is on 718 * @param x The x coordinate in per-screen coordinates 719 * @param y The y coordinate in per-screen coordinates 720 */ 721void 722miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 723{ 724 int i, nevents; 725 int valuators[2]; 726 ValuatorMask mask; 727 728 miPointerMoveNoEvent(pDev, pScreen, x, y); 729 730 /* generate motion notify */ 731 valuators[0] = x; 732 valuators[1] = y; 733 734 if (!mipointermove_events) { 735 mipointermove_events = InitEventList(GetMaximumEventsNum()); 736 737 if (!mipointermove_events) { 738 FatalError("Could not allocate event store.\n"); 739 return; 740 } 741 } 742 743 valuator_mask_set_range(&mask, 0, 2, valuators); 744 nevents = GetPointerEvents(mipointermove_events, pDev, MotionNotify, 0, 745 POINTER_SCREEN | POINTER_ABSOLUTE | 746 POINTER_NORAW, &mask); 747 748 input_lock(); 749 for (i = 0; i < nevents; i++) 750 mieqEnqueue(pDev, &mipointermove_events[i]); 751 input_unlock(); 752} 753