xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

mipointer.c (24151B)


      1 /*
      2 
      3 Copyright 1989, 1998  The Open Group
      4 
      5 Permission to use, copy, modify, distribute, and sell this software and its
      6 documentation for any purpose is hereby granted without fee, provided that
      7 the above copyright notice appear in all copies and that both that
      8 copyright notice and this permission notice appear in supporting
      9 documentation.
     10 
     11 The above copyright notice and this permission notice shall be included in
     12 all copies or substantial portions of the Software.
     13 
     14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     20 
     21 Except as contained in this notice, the name of The Open Group shall not be
     22 used in advertising or otherwise to promote the sale, use or other dealings
     23 in 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 
     68 typedef 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 
     80 DevPrivateKeyRec miPointerScreenKeyRec;
     81 
     82 #define GetScreenPrivate(s) ((miPointerScreenPtr) \
     83     dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey))
     84 #define SetupScreen(s)	miPointerScreenPtr  pScreenPriv = GetScreenPrivate(s)
     85 
     86 DevPrivateKeyRec 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 
     93 static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
     94                                    CursorPtr pCursor);
     95 static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
     96                                      CursorPtr pCursor);
     97 static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
     98                                    CursorPtr pCursor);
     99 static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
    100                                      BoxPtr pBox);
    101 static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen,
    102                                   CursorPtr pCursor, BoxPtr pHotBox,
    103                                   BoxPtr pTopLeftBox);
    104 static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
    105                                        int x, int y, Bool generateEvent);
    106 static Bool miPointerCloseScreen(ScreenPtr pScreen);
    107 static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y);
    108 static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
    109 static void miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen);
    110 static void miPointerMoveNoEvent(DeviceIntPtr pDev, ScreenPtr pScreen, int x,
    111                                  int y);
    112 
    113 static InternalEvent *mipointermove_events;   /* for WarpPointer MotionNotifies */
    114 
    115 Bool
    116 miPointerInitialize(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  */
    161 static Bool
    162 miPointerCloseScreen(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 
    177 static Bool
    178 miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
    179 {
    180     SetupScreen(pScreen);
    181     return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor);
    182 }
    183 
    184 static Bool
    185 miPointerUnrealizeCursor(DeviceIntPtr pDev,
    186                          ScreenPtr pScreen, CursorPtr pCursor)
    187 {
    188     SetupScreen(pScreen);
    189     return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen,
    190                                                          pCursor);
    191 }
    192 
    193 static Bool
    194 miPointerDisplayCursor(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  */
    219 static void
    220 miPointerConstrainCursor(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  */
    241 static void
    242 miPointerCursorLimits(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  */
    269 static Bool
    270 miPointerSetCursorPosition(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 
    288 void
    289 miRecolorCursor(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  */
    310 static Bool
    311 miPointerDeviceInitialize(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  */
    350 static void
    351 miPointerDeviceCleanup(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 
    375 void
    376 miPointerWarpCursor(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  * Synchronize the sprite with the cursor.
    406  *
    407  * @param pDev The device to sync
    408  */
    409 void
    410 miPointerUpdateSprite(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  */
    488 void
    489 miPointerInvalidateSprite(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  */
    505 void
    506 miPointerSetScreen(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  */
    524 ScreenPtr
    525 miPointerGetScreen(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 */
    537 Bool
    538 miPointerSetWaitForUpdate(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. */
    548 static void
    549 miPointerMoveNoEvent(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  */
    594 ScreenPtr
    595 miPointerSetPosition(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 coordinates.
    703  * @param y Return value for the current y coordinate in desktop coordinates.
    704  */
    705 void
    706 miPointerGetPosition(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  */
    721 void
    722 miPointerMove(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 }