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