1 /*
3 Copyright 1989, 1998 The Open Group
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.
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
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.
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 */
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 */
49 #ifdef HAVE_DIX_CONFIG_H
50 #include <dix-config.h>
51 #endif
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"
68 DevPrivateKeyRec miPointerScreenKeyRec;
70 #define GetScreenPrivate(s) ((miPointerScreenPtr) \
71 dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey))
72 #define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s)
74 DevPrivateKeyRec miPointerPrivKeyRec;
76 #define MIPOINTER(dev) \
77 (IsFloating(dev) ? \
78 (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
79 (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey))
81 static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
82 CursorPtr pCursor);
83 static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
84 CursorPtr pCursor);
85 static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
86 CursorPtr pCursor);
87 static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
88 BoxPtr pBox);
89 static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen,
90 CursorPtr pCursor, BoxPtr pHotBox,
91 BoxPtr pTopLeftBox);
92 static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
93 int x, int y,
94 Bool generateEvent);
95 static Bool miPointerCloseScreen(int index, ScreenPtr pScreen);
96 static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen,
97 int x, int y);
98 static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
99 static void miPointerDeviceCleanup(DeviceIntPtr pDev,
100 ScreenPtr pScreen);
101 static void miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y);
103 static InternalEvent* events; /* for WarpPointer MotionNotifies */
105 Bool
106 miPointerInitialize (ScreenPtr pScreen,
107 miPointerSpriteFuncPtr spriteFuncs,
108 miPointerScreenFuncPtr screenFuncs,
109 Bool waitForUpdate)
110 {
111 miPointerScreenPtr pScreenPriv;
113 if (!dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0))
114 return FALSE;
116 if (!dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0))
117 return FALSE;
119 pScreenPriv = malloc(sizeof (miPointerScreenRec));
120 if (!pScreenPriv)
121 return FALSE;
122 pScreenPriv->spriteFuncs = spriteFuncs;
123 pScreenPriv->screenFuncs = screenFuncs;
124 /*
125 * check for uninitialized methods
126 */
127 if (!screenFuncs->EnqueueEvent)
128 screenFuncs->EnqueueEvent = mieqEnqueue;
129 if (!screenFuncs->NewEventScreen)
130 screenFuncs->NewEventScreen = mieqSwitchScreen;
131 pScreenPriv->waitForUpdate = waitForUpdate;
132 pScreenPriv->showTransparent = FALSE;
133 pScreenPriv->CloseScreen = pScreen->CloseScreen;
134 pScreen->CloseScreen = miPointerCloseScreen;
135 dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv);
136 /*
137 * set up screen cursor method table
138 */
139 pScreen->ConstrainCursor = miPointerConstrainCursor;
140 pScreen->CursorLimits = miPointerCursorLimits;
141 pScreen->DisplayCursor = miPointerDisplayCursor;
142 pScreen->RealizeCursor = miPointerRealizeCursor;
143 pScreen->UnrealizeCursor = miPointerUnrealizeCursor;
144 pScreen->SetCursorPosition = miPointerSetCursorPosition;
145 pScreen->RecolorCursor = miRecolorCursor;
146 pScreen->DeviceCursorInitialize = miPointerDeviceInitialize;
147 pScreen->DeviceCursorCleanup = miPointerDeviceCleanup;
149 events = NULL;
150 return TRUE;
151 }
153 /**
154 * Destroy screen-specific information.
155 *
156 * @param index Screen index of the screen in screenInfo.screens[]
157 * @param pScreen The actual screen pointer
158 */
159 static Bool
160 miPointerCloseScreen (int index, ScreenPtr pScreen)
161 {
162 SetupScreen(pScreen);
164 pScreen->CloseScreen = pScreenPriv->CloseScreen;
165 free((pointer) pScreenPriv);
166 FreeEventList(events, GetMaximumEventsNum());
167 events = NULL;
168 return (*pScreen->CloseScreen) (index, pScreen);
169 }
171 /*
172 * DIX/DDX interface routines
173 */
175 static Bool
176 miPointerRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
177 {
178 SetupScreen(pScreen);
179 return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor);
180 }
182 static Bool
183 miPointerUnrealizeCursor (DeviceIntPtr pDev,
184 ScreenPtr pScreen,
185 CursorPtr pCursor)
186 {
187 SetupScreen(pScreen);
188 return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor);
189 }
191 static Bool
192 miPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
193 {
194 miPointerPtr pPointer;
196 /* return for keyboards */
197 if (!IsPointerDevice(pDev))
198 return FALSE;
200 pPointer = MIPOINTER(pDev);
202 pPointer->pCursor = pCursor;
203 pPointer->pScreen = pScreen;
204 miPointerUpdateSprite(pDev);
205 return TRUE;
206 }
208 /**
209 * Set up the constraints for the given device. This function does not
210 * actually constrain the cursor but merely copies the given box to the
211 * internal constraint storage.
212 *
213 * @param pDev The device to constrain to the box
214 * @param pBox The rectangle to constrain the cursor to
215 * @param pScreen Used for copying screen confinement
216 */
217 static void
218 miPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox)
219 {
220 miPointerPtr pPointer;
222 pPointer = MIPOINTER(pDev);
224 pPointer->limits = *pBox;
225 pPointer->confined = PointerConfinedToScreen(pDev);
226 }
228 /**
229 * Should calculate the box for the given cursor, based on screen and the
230 * confinement given. But we assume that whatever box is passed in is valid
231 * anyway.
232 *
233 * @param pDev The device to calculate the cursor limits for
234 * @param pScreen The screen the confinement happens on
235 * @param pCursor The screen the confinement happens on
236 * @param pHotBox The confinement box for the cursor
237 * @param[out] pTopLeftBox The new confinement box, always *pHotBox.
238 */
239 static void
240 miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
241 BoxPtr pHotBox, BoxPtr pTopLeftBox)
242 {
243 *pTopLeftBox = *pHotBox;
244 }
246 /**
247 * Set the device's cursor position to the x/y position on the given screen.
248 * Generates and event if required.
249 *
250 * This function is called from:
251 * - sprite init code to place onto initial position
252 * - the various WarpPointer implementations (core, XI, Xinerama, dmx,…)
253 * - during the cursor update path in CheckMotion
254 * - in the Xinerama part of NewCurrentScreen
255 * - when a RandR/RandR1.2 mode was applied (it may have moved the pointer, so
256 * it's set back to the original pos)
257 *
258 * @param pDev The device to move
259 * @param pScreen The screen the device is on
260 * @param x The x coordinate in per-screen coordinates
261 * @param y The y coordinate in per-screen coordinates
262 * @param generateEvent True if the pointer movement should generate an
263 * event.
264 *
265 * @return TRUE in all cases
266 */
267 static Bool
268 miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
269 int x, int y, Bool generateEvent)
270 {
271 SetupScreen (pScreen);
272 miPointerPtr pPointer = MIPOINTER(pDev);
274 pPointer->generateEvent = generateEvent;
276 if (pScreen->ConstrainCursorHarder)
277 pScreen->ConstrainCursorHarder(pDev, pScreen, Absolute, &x, &y);
279 /* device dependent - must pend signal and call miPointerWarpCursor */
280 (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y);
281 if (!generateEvent)
282 miPointerUpdateSprite(pDev);
283 return TRUE;
284 }
286 /**
287 * Set up sprite information for the device.
288 * This function will be called once for each device after it is initialized
289 * in the DIX.
290 *
291 * @param pDev The newly created device
292 * @param pScreen The initial sprite scree.
293 */
294 static Bool
295 miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
296 {
297 miPointerPtr pPointer;
298 SetupScreen (pScreen);
300 pPointer = malloc(sizeof(miPointerRec));
301 if (!pPointer)
302 return FALSE;
304 pPointer->pScreen = NULL;
305 pPointer->pSpriteScreen = NULL;
306 pPointer->pCursor = NULL;
307 pPointer->pSpriteCursor = NULL;
308 pPointer->limits.x1 = 0;
309 pPointer->limits.x2 = 32767;
310 pPointer->limits.y1 = 0;
311 pPointer->limits.y2 = 32767;
312 pPointer->confined = FALSE;
313 pPointer->x = 0;
314 pPointer->y = 0;
315 pPointer->generateEvent = FALSE;
317 if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen)))
318 {
319 free(pPointer);
320 return FALSE;
321 }
323 dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer);
324 return TRUE;
325 }
327 /**
328 * Clean up after device.
329 * This function will be called once before the device is freed in the DIX
330 *
331 * @param pDev The device to be removed from the server
332 * @param pScreen Current screen of the device
333 */
334 static void
335 miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
336 {
337 SetupScreen(pScreen);
339 if (!IsMaster(pDev) && !IsFloating(pDev))
340 return;
342 (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
343 free(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey));
344 dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL);
345 }
348 /**
349 * Warp the pointer to the given position on the given screen. May generate
350 * an event, depending on whether we're coming from miPointerSetPosition.
351 *
352 * Once signals are ignored, the WarpCursor function can call this
353 *
354 * @param pDev The device to warp
355 * @param pScreen Screen to warp on
356 * @param x The x coordinate in per-screen coordinates
357 * @param y The y coordinate in per-screen coordinates
358 */
360 void
361 miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
362 {
363 miPointerPtr pPointer;
364 BOOL changedScreen = FALSE;
366 SetupScreen (pScreen);
367 pPointer = MIPOINTER(pDev);
369 if (pPointer->pScreen != pScreen)
370 {
371 (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE);
372 changedScreen = TRUE;
373 }
375 if (pPointer->generateEvent)
376 miPointerMove (pDev, pScreen, x, y);
377 else
378 miPointerMoveNoEvent(pDev, pScreen, x, y);
380 /* Don't call USFS if we use Xinerama, otherwise the root window is
381 * updated to the second screen, and we never receive any events.
382 * (FDO bug #18668) */
383 if (changedScreen
384 #ifdef PANORAMIX
385 && noPanoramiXExtension
386 #endif
387 )
388 UpdateSpriteForScreen (pDev, pScreen) ;
389 }
391 /**
392 * Syncronize the sprite with the cursor.
393 *
394 * @param pDev The device to sync
395 */
396 void
397 miPointerUpdateSprite (DeviceIntPtr pDev)
398 {
399 ScreenPtr pScreen;
400 miPointerScreenPtr pScreenPriv;
401 CursorPtr pCursor;
402 int x, y, devx, devy;
403 miPointerPtr pPointer;
405 if (!pDev || !pDev->coreEvents)
406 return;
408 pPointer = MIPOINTER(pDev);
410 if (!pPointer)
411 return;
413 pScreen = pPointer->pScreen;
414 if (!pScreen)
415 return;
417 x = pPointer->x;
418 y = pPointer->y;
419 devx = pPointer->devx;
420 devy = pPointer->devy;
422 pScreenPriv = GetScreenPrivate (pScreen);
423 /*
424 * if the cursor has switched screens, disable the sprite
425 * on the old screen
426 */
427 if (pScreen != pPointer->pSpriteScreen)
428 {
429 if (pPointer->pSpriteScreen)
430 {
431 miPointerScreenPtr pOldPriv;
433 pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen);
434 if (pPointer->pCursor)
435 {
436 (*pOldPriv->spriteFuncs->SetCursor)
437 (pDev, pPointer->pSpriteScreen, NullCursor, 0, 0);
438 }
439 (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE);
440 }
441 (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
442 (*pScreenPriv->spriteFuncs->SetCursor)
443 (pDev, pScreen, pPointer->pCursor, x, y);
444 pPointer->devx = x;
445 pPointer->devy = y;
446 pPointer->pSpriteCursor = pPointer->pCursor;
447 pPointer->pSpriteScreen = pScreen;
448 }
449 /*
450 * if the cursor has changed, display the new one
451 */
452 else if (pPointer->pCursor != pPointer->pSpriteCursor)
453 {
454 pCursor = pPointer->pCursor;
455 if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent))
456 pCursor = NullCursor;
457 (*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y);
459 pPointer->devx = x;
460 pPointer->devy = y;
461 pPointer->pSpriteCursor = pPointer->pCursor;
462 }
463 else if (x != devx || y != devy)
464 {
465 pPointer->devx = x;
466 pPointer->devy = y;
467 if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
468 (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
469 }
470 }
472 /**
473 * Set the device to the coordinates on the given screen.
474 *
475 * @param pDev The device to move
476 * @param screen_no Index of the screen to move to
477 * @param x The x coordinate in per-screen coordinates
478 * @param y The y coordinate in per-screen coordinates
479 */
480 void
481 miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
482 {
483 miPointerScreenPtr pScreenPriv;
484 ScreenPtr pScreen;
485 miPointerPtr pPointer;
487 pPointer = MIPOINTER(pDev);
489 pScreen = screenInfo.screens[screen_no];
490 pScreenPriv = GetScreenPrivate (pScreen);
491 (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE);
492 NewCurrentScreen (pDev, pScreen, x, y);
494 pPointer->limits.x2 = pScreen->width;
495 pPointer->limits.y2 = pScreen->height;
496 }
498 /**
499 * @return The current screen of the VCP
500 */
501 ScreenPtr
502 miPointerCurrentScreen (void)
503 {
504 return miPointerGetScreen(inputInfo.pointer);
505 }
507 /**
508 * @return The current screen of the given device or NULL.
509 */
510 ScreenPtr
511 miPointerGetScreen(DeviceIntPtr pDev)
512 {
513 miPointerPtr pPointer = MIPOINTER(pDev);
514 return (pPointer) ? pPointer->pScreen : NULL;
515 }
517 /* Controls whether the cursor image should be updated immediately when
518 moved (FALSE) or if something else will be responsible for updating
519 it later (TRUE). Returns current setting.
520 Caller is responsible for calling OsBlockSignal first.
521 */
522 Bool
523 miPointerSetWaitForUpdate(ScreenPtr pScreen, Bool wait)
524 {
525 SetupScreen(pScreen);
526 Bool prevWait = pScreenPriv->waitForUpdate;
528 pScreenPriv->waitForUpdate = wait;
529 return prevWait;
530 }
533 /* Move the pointer on the current screen, and update the sprite. */
534 static void
535 miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen,
536 int x, int y)
537 {
538 miPointerPtr pPointer;
539 SetupScreen(pScreen);
541 pPointer = MIPOINTER(pDev);
543 /* Hack: We mustn't call into ->MoveCursor for anything but the
544 * VCP, as this may cause a non-HW rendered cursor to be rendered during
545 * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT.
546 */
547 if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer
548 && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
549 {
550 pPointer->devx = x;
551 pPointer->devy = y;
552 if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
553 (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
554 }
556 pPointer->x = x;
557 pPointer->y = y;
558 pPointer->pScreen = pScreen;
559 }
561 /**
562 * Set the devices' cursor position to the given x/y position.
563 *
564 * This function is called during the pointer update path in
565 * GetPointerEvents and friends (and the same in the xwin DDX).
566 *
567 * The coordinates provided are always absolute. The parameter mode whether
568 * it was relative or absolute movement that landed us at those coordinates.
569 *
570 * @param pDev The device to move
571 * @param mode Movement mode (Absolute or Relative)
572 * @param[in,out] x The x coordiante in screen coordinates (in regards to total
573 * desktop size)
574 * @param[in,out] y The y coordiante in screen coordinates (in regards to total
575 * desktop size)
576 */
577 void
578 miPointerSetPosition(DeviceIntPtr pDev, int mode, int *x, int *y)
579 {
580 miPointerScreenPtr pScreenPriv;
581 ScreenPtr pScreen;
582 ScreenPtr newScreen;
584 miPointerPtr pPointer;
586 if (!pDev || !pDev->coreEvents)
587 return;
589 pPointer = MIPOINTER(pDev);
590 pScreen = pPointer->pScreen;
591 if (!pScreen)
592 return; /* called before ready */
594 if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
595 {
596 pScreenPriv = GetScreenPrivate (pScreen);
597 if (!pPointer->confined)
598 {
599 newScreen = pScreen;
600 (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y);
601 if (newScreen != pScreen)
602 {
603 pScreen = newScreen;
604 (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen,
605 FALSE);
606 /* Smash the confine to the new screen */
607 pPointer->limits.x2 = pScreen->width;
608 pPointer->limits.y2 = pScreen->height;
609 }
610 }
611 }
612 /* Constrain the sprite to the current limits. */
613 if (*x < pPointer->limits.x1)
614 *x = pPointer->limits.x1;
615 if (*x >= pPointer->limits.x2)
616 *x = pPointer->limits.x2 - 1;
617 if (*y < pPointer->limits.y1)
618 *y = pPointer->limits.y1;
619 if (*y >= pPointer->limits.y2)
620 *y = pPointer->limits.y2 - 1;
622 if (pScreen->ConstrainCursorHarder)
623 pScreen->ConstrainCursorHarder(pDev, pScreen, mode, x, y);
625 if (pPointer->x == *x && pPointer->y == *y &&
626 pPointer->pScreen == pScreen)
627 return;
629 miPointerMoveNoEvent(pDev, pScreen, *x, *y);
630 }
632 /**
633 * Get the current position of the device in desktop coordinates.
634 *
635 * @param x Return value for the current x coordinate in desktop coordiates.
636 * @param y Return value for the current y coordinate in desktop coordiates.
637 */
638 void
639 miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
640 {
641 *x = MIPOINTER(pDev)->x;
642 *y = MIPOINTER(pDev)->y;
643 }
645 #ifdef XQUARTZ
646 #include <pthread.h>
647 void darwinEvents_lock(void);
648 void darwinEvents_unlock(void);
649 #endif
651 /**
652 * Move the device's pointer to the x/y coordinates on the given screen.
653 * This function generates and enqueues pointer events.
654 *
655 * @param pDev The device to move
656 * @param pScreen The screen the device is on
657 * @param x The x coordinate in per-screen coordinates
658 * @param y The y coordinate in per-screen coordinates
659 */
660 void
661 miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
662 {
663 int i, nevents;
664 int valuators[2];
665 ValuatorMask mask;
667 miPointerMoveNoEvent(pDev, pScreen, x, y);
669 /* generate motion notify */
670 valuators[0] = x;
671 valuators[1] = y;
673 if (!events)
674 {
675 events = InitEventList(GetMaximumEventsNum());
677 if (!events)
678 {
679 FatalError("Could not allocate event store.\n");
680 return;
681 }
682 }
684 valuator_mask_set_range(&mask, 0, 2, valuators);
685 nevents = GetPointerEvents(events, pDev, MotionNotify, 0,
686 POINTER_SCREEN | POINTER_ABSOLUTE | POINTER_NORAW, &mask);
688 OsBlockSignals();
689 #ifdef XQUARTZ
690 darwinEvents_lock();
691 #endif
692 for (i = 0; i < nevents; i++)
693 mieqEnqueue(pDev, &events[i]);
694 #ifdef XQUARTZ
695 darwinEvents_unlock();
696 #endif
697 OsReleaseSignals();
698 }