]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/mi/mipointer.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / programs / Xserver / mi / mipointer.c
1 /*
2  * mipointer.c
3  */
4
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 $ */
7
8 /*
9
10 Copyright (c) 1989  X Consortium
11
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:
18
19 The above copyright notice and this permission notice shall be included in
20 all copies or substantial portions of the Software.
21
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.
28
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.
32 */
33
34 # define NEED_EVENTS
35 # include   "X.h"
36 # include   "Xmd.h"
37 # include   "Xproto.h"
38 # include   "misc.h"
39 # include   "windowstr.h"
40 # include   "pixmapstr.h"
41 # include   "mi.h"
42 # include   "scrnintstr.h"
43 # include   "mipointrst.h"
44 # include   "cursorstr.h"
45 # include   "dixstruct.h"
46
47 static int  miPointerScreenIndex;
48 static unsigned long miPointerGeneration = 0;
49
50 #define GetScreenPrivate(s) ((miPointerScreenPtr) ((s)->devPrivates[miPointerScreenIndex].ptr))
51 #define SetupScreen(s)  miPointerScreenPtr  pScreenPriv = GetScreenPrivate(s)
52
53 /*
54  * until more than one pointer device exists.
55  */
56
57 static miPointerRec miPointer;
58
59 static Bool miPointerRealizeCursor (),      miPointerUnrealizeCursor ();
60 static Bool miPointerDisplayCursor ();
61 static void miPointerConstrainCursor (),    miPointerPointerNonInterestBox();
62 static void miPointerCursorLimits ();
63 static Bool miPointerSetCursorPosition ();
64
65 static Bool miPointerCloseScreen();
66
67 static void miPointerMove ();
68
69 Bool
70 miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
71     ScreenPtr               pScreen;
72     miPointerSpriteFuncPtr  spriteFuncs;
73     miPointerScreenFuncPtr  screenFuncs;
74     Bool                    waitForUpdate;
75 {
76     miPointerScreenPtr  pScreenPriv;
77
78     if (miPointerGeneration != serverGeneration)
79     {
80         miPointerScreenIndex = AllocateScreenPrivateIndex();
81         if (miPointerScreenIndex < 0)
82             return FALSE;
83         miPointerGeneration = serverGeneration;
84     }
85     pScreenPriv = (miPointerScreenPtr) xalloc (sizeof (miPointerScreenRec));
86     if (!pScreenPriv)
87         return FALSE;
88     pScreenPriv->spriteFuncs = spriteFuncs;
89     pScreenPriv->screenFuncs = screenFuncs;
90     /*
91      * check for uninitialized methods
92      */
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;
101     /*
102      * set up screen cursor method table
103      */
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;
112     /*
113      * set up the pointer object
114      */
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;
124     miPointer.x = 0;
125     miPointer.y = 0;
126     miPointer.history_start = miPointer.history_end = 0;
127     return TRUE;
128 }
129
130 static Bool
131 miPointerCloseScreen (index, pScreen)
132     int         index;
133     ScreenPtr   pScreen;
134 {
135     SetupScreen(pScreen);
136
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);
144 }
145
146 /*
147  * DIX/DDX interface routines
148  */
149
150 static Bool
151 miPointerRealizeCursor (pScreen, pCursor)
152     ScreenPtr   pScreen;
153     CursorPtr   pCursor;
154 {
155     SetupScreen(pScreen);
156
157     return (*pScreenPriv->spriteFuncs->RealizeCursor) (pScreen, pCursor);
158 }
159
160 static Bool
161 miPointerUnrealizeCursor (pScreen, pCursor)
162     ScreenPtr   pScreen;
163     CursorPtr   pCursor;
164 {
165     SetupScreen(pScreen);
166
167     return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pScreen, pCursor);
168 }
169
170 static Bool
171 miPointerDisplayCursor (pScreen, pCursor)
172     ScreenPtr   pScreen;
173     CursorPtr   pCursor;
174 {
175     SetupScreen(pScreen);
176
177     miPointer.pCursor = pCursor;
178     miPointer.pScreen = pScreen;
179     miPointerUpdate ();
180     return TRUE;
181 }
182
183 static void
184 miPointerConstrainCursor (pScreen, pBox)
185     ScreenPtr   pScreen;
186     BoxPtr      pBox;
187 {
188     miPointer.limits = *pBox;
189     miPointer.confined = PointerConfinedToScreen();
190 }
191
192 /*ARGSUSED*/
193 static void
194 miPointerPointerNonInterestBox (pScreen, pBox)
195     ScreenPtr   pScreen;
196     BoxPtr      pBox;
197 {
198     /* until DIX uses this, this will remain a stub */
199 }
200
201 /*ARGSUSED*/
202 static void
203 miPointerCursorLimits(pScreen, pCursor, pHotBox, pTopLeftBox)
204     ScreenPtr   pScreen;
205     CursorPtr   pCursor;
206     BoxPtr      pHotBox;
207     BoxPtr      pTopLeftBox;
208 {
209     *pTopLeftBox = *pHotBox;
210 }
211
212 static Bool GenerateEvent;
213
214 static Bool
215 miPointerSetCursorPosition(pScreen, x, y, generateEvent)
216     ScreenPtr pScreen;
217     int       x, y;
218     Bool      generateEvent;
219 {
220     SetupScreen (pScreen);
221
222     GenerateEvent = generateEvent;
223     /* device dependent - must pend signal and call miPointerWarpCursor */
224     (*pScreenPriv->screenFuncs->WarpCursor) (pScreen, x, y);
225     if (!generateEvent)
226         miPointerUpdate();
227     return TRUE;
228 }
229
230 /* Once signals are ignored, the WarpCursor function can call this */
231
232 void
233 miPointerWarpCursor (pScreen, x, y)
234     ScreenPtr   pScreen;
235     int         x, y;
236 {
237     SetupScreen (pScreen);
238
239     if (miPointer.pScreen != pScreen)
240         (*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, TRUE);
241
242     if (GenerateEvent)
243     {
244         miPointerMove (pScreen, x, y, GetTimeInMillis()); 
245     }
246     else
247     {
248         /* everything from miPointerMove except the event and history */
249
250         if (!pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
251         {
252             miPointer.devx = x;
253             miPointer.devy = y;
254             (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
255         }
256         miPointer.x = x;
257         miPointer.y = y;
258         miPointer.pScreen = pScreen;
259     }
260 }
261
262 /*
263  * Pointer/CursorDisplay interface routines
264  */
265
266 int
267 miPointerGetMotionBufferSize ()
268 {
269     return MOTION_SIZE;
270 }
271
272 int
273 miPointerGetMotionEvents (pPtr, coords, start, stop, pScreen)
274     DeviceIntPtr    pPtr;
275     xTimecoord      *coords;
276     unsigned long   start, stop;
277     ScreenPtr       pScreen;
278 {
279     int             i;
280     int             count = 0;
281     miHistoryPtr    h;
282
283     for (i = miPointer.history_start; i != miPointer.history_end;)
284     {
285         h = &miPointer.history[i];
286         if (h->event.time >= stop)
287             break;
288         if (h->event.time >= start)
289         {
290             *coords++ = h->event;
291             count++;
292         }
293         if (++i == MOTION_SIZE) i = 0;
294     }
295     return count;
296 }
297
298     
299 /*
300  * miPointerUpdate
301  *
302  * Syncronize the sprite with the cursor - called from ProcessInputEvents
303  */
304
305 void
306 miPointerUpdate ()
307 {
308     ScreenPtr           pScreen;
309     miPointerScreenPtr  pScreenPriv;
310     int                 x, y, devx, devy;
311
312     pScreen = miPointer.pScreen;
313     x = miPointer.x;
314     y = miPointer.y;
315     devx = miPointer.devx;
316     devy = miPointer.devy;
317     if (!pScreen)
318         return;
319     pScreenPriv = GetScreenPrivate (pScreen);
320     /*
321      * if the cursor has switched screens, disable the sprite
322      * on the old screen
323      */
324     if (pScreen != miPointer.pSpriteScreen)
325     {
326         if (miPointer.pSpriteScreen)
327         {
328             miPointerScreenPtr  pOldPriv;
329         
330             pOldPriv = GetScreenPrivate (miPointer.pSpriteScreen);
331             if (miPointer.pCursor)
332             {
333                 (*pOldPriv->spriteFuncs->SetCursor)
334                                 (miPointer.pSpriteScreen, NullCursor, 0, 0);
335             }
336             (*pOldPriv->screenFuncs->CrossScreen) (miPointer.pSpriteScreen, FALSE);
337         }
338         (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
339         (*pScreenPriv->spriteFuncs->SetCursor)
340                                 (pScreen, miPointer.pCursor, x, y);
341         miPointer.devx = x;
342         miPointer.devy = y;
343         miPointer.pSpriteCursor = miPointer.pCursor;
344         miPointer.pSpriteScreen = pScreen;
345     }
346     /*
347      * if the cursor has changed, display the new one
348      */
349     else if (miPointer.pCursor != miPointer.pSpriteCursor)
350     {
351         (*pScreenPriv->spriteFuncs->SetCursor) 
352             (pScreen, miPointer.pCursor, x, y);
353         miPointer.devx = x;
354         miPointer.devy = y;
355         miPointer.pSpriteCursor = miPointer.pCursor;
356     }
357     else if (x != devx || y != devy)
358     {
359         miPointer.devx = x;
360         miPointer.devy = y;
361         (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
362     }
363 }
364
365 /*
366  * miPointerDeltaCursor.  The pointer has moved dx,dy from it's previous
367  * position.
368  */
369
370 void
371 miPointerDeltaCursor (dx, dy, time)
372     int             dx, dy;
373     unsigned long   time;
374 {
375     miPointerAbsoluteCursor (miPointer.x + dx, miPointer.y + dy, time);
376 }
377
378 /*
379  * miPointerAbsoluteCursor.  The pointer has moved to x,y
380  */
381
382 void
383 miPointerAbsoluteCursor (x, y, time)
384     int             x, y;
385     unsigned long   time;
386 {
387     miPointerScreenPtr  pScreenPriv;
388     ScreenPtr           pScreen;
389     ScreenPtr           newScreen;
390
391     pScreen = miPointer.pScreen;
392     if (!pScreen)
393         return;     /* called before ready */
394     if (x < 0 || x >= pScreen->width || y < 0 || y >= pScreen->height)
395     {
396         pScreenPriv = GetScreenPrivate (pScreen);
397         if (!miPointer.confined)
398         {
399             newScreen = pScreen;
400             (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, &x, &y);
401             if (newScreen != pScreen)
402             {
403                 pScreen = newScreen;
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;
409             }
410         }
411     }
412     /*
413      * constrain the hot-spot to the current
414      * limits
415      */
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)
425         return;
426     miPointerMove (pScreen, x, y, time);
427 }
428
429 void
430 miPointerPosition (x, y)
431     int     *x, *y;
432 {
433     *x = miPointer.x;
434     *y = miPointer.y;
435 }
436
437 /*
438  * miPointerMove.  The pointer has moved to x,y on current screen
439  */
440
441 static void
442 miPointerMove (pScreen, x, y, time)
443     ScreenPtr       pScreen;
444     int             x, y;
445     unsigned long   time;
446 {
447     SetupScreen(pScreen);
448     xEvent              xE;
449     miHistoryPtr        history;
450     int                 prev, end, start;
451
452     if (!pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
453     {
454         miPointer.devx = x;
455         miPointer.devy = y;
456         (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
457     }
458     miPointer.x = x;
459     miPointer.y = y;
460     miPointer.pScreen = pScreen;
461
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);
467
468     end = miPointer.history_end;
469     start = miPointer.history_start;
470     prev = end - 1;
471     if (end == 0)
472         prev = MOTION_SIZE - 1;
473     history = &miPointer.history[prev];
474     if (end == start || history->event.time != time)
475     {
476         history = &miPointer.history[end];
477         if (++end == MOTION_SIZE) 
478             end = 0;
479         if (end == start)
480         {
481             start = end + 1;
482             if (start == MOTION_SIZE)
483                 start = 0;
484             miPointer.history_start = start;
485         }
486         miPointer.history_end = end;
487     }
488     history->event.x = x;
489     history->event.y = y;
490     history->event.time = time;
491     history->pScreen = pScreen;
492 }
493
494 void
495 _miRegisterPointerDevice (pScreen, pDevice)
496     ScreenPtr   pScreen;
497     DeviceIntPtr pDevice;
498 {
499     miPointer.pPointer = (DevicePtr)pDevice;
500 }
501
502 /* obsolete: for binary compatibility */
503 #ifdef miRegisterPointerDevice
504 #undef miRegisterPointerDevice
505 void
506 miRegisterPointerDevice (pScreen, pDevice)
507     ScreenPtr   pScreen;
508     DevicePtr pDevice;
509 {
510     miPointer.pPointer = pDevice;
511 }
512 #endif /* miRegisterPointerDevice */