5 /* $XConsortium: mipointer.c,v 5.24 94/04/17 20:27:39 dpw Exp $ */
6 /* $XFree86: xc/programs/Xserver/mi/mipointer.c,v 3.1 1996/03/10 12:12:44 dawes Exp $ */
10 Copyright (c) 1989 X Consortium
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
19 The above copyright notice and this permission notice shall be included in
20 all copies or substantial portions of the Software.
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 Except as contained in this notice, the name of the X Consortium shall not be
30 used in advertising or otherwise to promote the sale, use or other dealings
31 in this Software without prior written authorization from the X Consortium.
39 # include "windowstr.h"
40 # include "pixmapstr.h"
42 # include "scrnintstr.h"
43 # include "mipointrst.h"
44 # include "cursorstr.h"
45 # include "dixstruct.h"
47 static int miPointerScreenIndex;
48 static unsigned long miPointerGeneration = 0;
50 #define GetScreenPrivate(s) ((miPointerScreenPtr) ((s)->devPrivates[miPointerScreenIndex].ptr))
51 #define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s)
54 * until more than one pointer device exists.
57 static miPointerRec miPointer;
59 static Bool miPointerRealizeCursor (), miPointerUnrealizeCursor ();
60 static Bool miPointerDisplayCursor ();
61 static void miPointerConstrainCursor (), miPointerPointerNonInterestBox();
62 static void miPointerCursorLimits ();
63 static Bool miPointerSetCursorPosition ();
65 static Bool miPointerCloseScreen();
67 static void miPointerMove ();
70 miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
72 miPointerSpriteFuncPtr spriteFuncs;
73 miPointerScreenFuncPtr screenFuncs;
76 miPointerScreenPtr pScreenPriv;
78 if (miPointerGeneration != serverGeneration)
80 miPointerScreenIndex = AllocateScreenPrivateIndex();
81 if (miPointerScreenIndex < 0)
83 miPointerGeneration = serverGeneration;
85 pScreenPriv = (miPointerScreenPtr) xalloc (sizeof (miPointerScreenRec));
88 pScreenPriv->spriteFuncs = spriteFuncs;
89 pScreenPriv->screenFuncs = screenFuncs;
91 * check for uninitialized methods
93 if (!screenFuncs->EnqueueEvent)
94 screenFuncs->EnqueueEvent = mieqEnqueue;
95 if (!screenFuncs->NewEventScreen)
96 screenFuncs->NewEventScreen = mieqSwitchScreen;
97 pScreenPriv->waitForUpdate = waitForUpdate;
98 pScreenPriv->CloseScreen = pScreen->CloseScreen;
99 pScreen->CloseScreen = miPointerCloseScreen;
100 pScreen->devPrivates[miPointerScreenIndex].ptr = (pointer) pScreenPriv;
102 * set up screen cursor method table
104 pScreen->ConstrainCursor = miPointerConstrainCursor;
105 pScreen->CursorLimits = miPointerCursorLimits;
106 pScreen->DisplayCursor = miPointerDisplayCursor;
107 pScreen->RealizeCursor = miPointerRealizeCursor;
108 pScreen->UnrealizeCursor = miPointerUnrealizeCursor;
109 pScreen->SetCursorPosition = miPointerSetCursorPosition;
110 pScreen->RecolorCursor = miRecolorCursor;
111 pScreen->PointerNonInterestBox = miPointerPointerNonInterestBox;
113 * set up the pointer object
115 miPointer.pScreen = NULL;
116 miPointer.pSpriteScreen = NULL;
117 miPointer.pCursor = NULL;
118 miPointer.pSpriteCursor = NULL;
119 miPointer.limits.x1 = 0;
120 miPointer.limits.x2 = 32767;
121 miPointer.limits.y1 = 0;
122 miPointer.limits.y2 = 32767;
123 miPointer.confined = FALSE;
126 miPointer.history_start = miPointer.history_end = 0;
131 miPointerCloseScreen (index, pScreen)
135 SetupScreen(pScreen);
137 if (pScreen == miPointer.pScreen)
138 miPointer.pScreen = 0;
139 if (pScreen == miPointer.pSpriteScreen)
140 miPointer.pSpriteScreen = 0;
141 pScreen->CloseScreen = pScreenPriv->CloseScreen;
142 xfree ((pointer) pScreenPriv);
143 return (*pScreen->CloseScreen) (index, pScreen);
147 * DIX/DDX interface routines
151 miPointerRealizeCursor (pScreen, pCursor)
155 SetupScreen(pScreen);
157 return (*pScreenPriv->spriteFuncs->RealizeCursor) (pScreen, pCursor);
161 miPointerUnrealizeCursor (pScreen, pCursor)
165 SetupScreen(pScreen);
167 return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pScreen, pCursor);
171 miPointerDisplayCursor (pScreen, pCursor)
175 SetupScreen(pScreen);
177 miPointer.pCursor = pCursor;
178 miPointer.pScreen = pScreen;
184 miPointerConstrainCursor (pScreen, pBox)
188 miPointer.limits = *pBox;
189 miPointer.confined = PointerConfinedToScreen();
194 miPointerPointerNonInterestBox (pScreen, pBox)
198 /* until DIX uses this, this will remain a stub */
203 miPointerCursorLimits(pScreen, pCursor, pHotBox, pTopLeftBox)
209 *pTopLeftBox = *pHotBox;
212 static Bool GenerateEvent;
215 miPointerSetCursorPosition(pScreen, x, y, generateEvent)
220 SetupScreen (pScreen);
222 GenerateEvent = generateEvent;
223 /* device dependent - must pend signal and call miPointerWarpCursor */
224 (*pScreenPriv->screenFuncs->WarpCursor) (pScreen, x, y);
230 /* Once signals are ignored, the WarpCursor function can call this */
233 miPointerWarpCursor (pScreen, x, y)
237 SetupScreen (pScreen);
239 if (miPointer.pScreen != pScreen)
240 (*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, TRUE);
244 miPointerMove (pScreen, x, y, GetTimeInMillis());
248 /* everything from miPointerMove except the event and history */
250 if (!pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
254 (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
258 miPointer.pScreen = pScreen;
263 * Pointer/CursorDisplay interface routines
267 miPointerGetMotionBufferSize ()
273 miPointerGetMotionEvents (pPtr, coords, start, stop, pScreen)
276 unsigned long start, stop;
283 for (i = miPointer.history_start; i != miPointer.history_end;)
285 h = &miPointer.history[i];
286 if (h->event.time >= stop)
288 if (h->event.time >= start)
290 *coords++ = h->event;
293 if (++i == MOTION_SIZE) i = 0;
302 * Syncronize the sprite with the cursor - called from ProcessInputEvents
309 miPointerScreenPtr pScreenPriv;
310 int x, y, devx, devy;
312 pScreen = miPointer.pScreen;
315 devx = miPointer.devx;
316 devy = miPointer.devy;
319 pScreenPriv = GetScreenPrivate (pScreen);
321 * if the cursor has switched screens, disable the sprite
324 if (pScreen != miPointer.pSpriteScreen)
326 if (miPointer.pSpriteScreen)
328 miPointerScreenPtr pOldPriv;
330 pOldPriv = GetScreenPrivate (miPointer.pSpriteScreen);
331 if (miPointer.pCursor)
333 (*pOldPriv->spriteFuncs->SetCursor)
334 (miPointer.pSpriteScreen, NullCursor, 0, 0);
336 (*pOldPriv->screenFuncs->CrossScreen) (miPointer.pSpriteScreen, FALSE);
338 (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
339 (*pScreenPriv->spriteFuncs->SetCursor)
340 (pScreen, miPointer.pCursor, x, y);
343 miPointer.pSpriteCursor = miPointer.pCursor;
344 miPointer.pSpriteScreen = pScreen;
347 * if the cursor has changed, display the new one
349 else if (miPointer.pCursor != miPointer.pSpriteCursor)
351 (*pScreenPriv->spriteFuncs->SetCursor)
352 (pScreen, miPointer.pCursor, x, y);
355 miPointer.pSpriteCursor = miPointer.pCursor;
357 else if (x != devx || y != devy)
361 (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
366 * miPointerDeltaCursor. The pointer has moved dx,dy from it's previous
371 miPointerDeltaCursor (dx, dy, time)
375 miPointerAbsoluteCursor (miPointer.x + dx, miPointer.y + dy, time);
379 * miPointerAbsoluteCursor. The pointer has moved to x,y
383 miPointerAbsoluteCursor (x, y, time)
387 miPointerScreenPtr pScreenPriv;
391 pScreen = miPointer.pScreen;
393 return; /* called before ready */
394 if (x < 0 || x >= pScreen->width || y < 0 || y >= pScreen->height)
396 pScreenPriv = GetScreenPrivate (pScreen);
397 if (!miPointer.confined)
400 (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, &x, &y);
401 if (newScreen != pScreen)
404 (*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE);
405 pScreenPriv = GetScreenPrivate (pScreen);
406 /* Smash the confine to the new screen */
407 miPointer.limits.x2 = pScreen->width;
408 miPointer.limits.y2 = pScreen->height;
413 * constrain the hot-spot to the current
416 if (x < miPointer.limits.x1)
417 x = miPointer.limits.x1;
418 if (x >= miPointer.limits.x2)
419 x = miPointer.limits.x2 - 1;
420 if (y < miPointer.limits.y1)
421 y = miPointer.limits.y1;
422 if (y >= miPointer.limits.y2)
423 y = miPointer.limits.y2 - 1;
424 if (miPointer.x == x && miPointer.y == y && miPointer.pScreen == pScreen)
426 miPointerMove (pScreen, x, y, time);
430 miPointerPosition (x, y)
438 * miPointerMove. The pointer has moved to x,y on current screen
442 miPointerMove (pScreen, x, y, time)
447 SetupScreen(pScreen);
449 miHistoryPtr history;
450 int prev, end, start;
452 if (!pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
456 (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
460 miPointer.pScreen = pScreen;
462 xE.u.u.type = MotionNotify;
463 xE.u.keyButtonPointer.rootX = x;
464 xE.u.keyButtonPointer.rootY = y;
465 xE.u.keyButtonPointer.time = time;
466 (*pScreenPriv->screenFuncs->EnqueueEvent) (&xE);
468 end = miPointer.history_end;
469 start = miPointer.history_start;
472 prev = MOTION_SIZE - 1;
473 history = &miPointer.history[prev];
474 if (end == start || history->event.time != time)
476 history = &miPointer.history[end];
477 if (++end == MOTION_SIZE)
482 if (start == MOTION_SIZE)
484 miPointer.history_start = start;
486 miPointer.history_end = end;
488 history->event.x = x;
489 history->event.y = y;
490 history->event.time = time;
491 history->pScreen = pScreen;
495 _miRegisterPointerDevice (pScreen, pDevice)
497 DeviceIntPtr pDevice;
499 miPointer.pPointer = (DevicePtr)pDevice;
502 /* obsolete: for binary compatibility */
503 #ifdef miRegisterPointerDevice
504 #undef miRegisterPointerDevice
506 miRegisterPointerDevice (pScreen, pDevice)
510 miPointer.pPointer = pDevice;
512 #endif /* miRegisterPointerDevice */