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