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