]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/dix/events.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / programs / Xserver / dix / events.c
1 /************************************************************
2
3 Copyright (c) 1987  X Consortium
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of the X Consortium shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from the X Consortium.
25
26
27 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
28
29                         All Rights Reserved
30
31 Permission to use, copy, modify, and distribute this software and its 
32 documentation for any purpose and without fee is hereby granted, 
33 provided that the above copyright notice appear in all copies and that
34 both that copyright notice and this permission notice appear in 
35 supporting documentation, and that the name of Digital not be
36 used in advertising or publicity pertaining to distribution of the
37 software without specific, written prior permission.  
38
39 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45 SOFTWARE.
46
47 ********************************************************/
48
49
50 /* $XConsortium: events.c /main/187 1996/09/25 00:47:41 dpw $ */
51 /* $XFree86: xc/programs/Xserver/dix/events.c,v 3.11 1996/12/24 02:23:45 dawes Exp $ */
52
53 #include "X.h"
54 #include "misc.h"
55 #include "resource.h"
56 #define NEED_EVENTS
57 #define NEED_REPLIES
58 #include "Xproto.h"
59 #include "windowstr.h"
60 #include "inputstr.h"
61 #include "scrnintstr.h"
62 #include "cursorstr.h"
63
64 #include "dixstruct.h"
65
66 #ifdef XKB
67 #include "XKBsrv.h"
68 #endif
69
70 #ifdef XCSECURITY
71 #define _SECURITY_SERVER
72 #include "extensions/security.h"
73 #endif
74
75 #include "XIproto.h"
76 #include "exevents.h"
77 #include "extnsionst.h"
78
79 #include "dixevents.h"
80 #include "dixgrabs.h"
81 #include "dispatch.h"
82
83 extern WindowPtr *WindowTable;
84
85 #define EXTENSION_EVENT_BASE  64
86
87 #define NoSuchEvent 0x80000000  /* so doesn't match NoEventMask */
88 #define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
89 #define AllButtonsMask ( \
90         Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
91 #define MotionMask ( \
92         PointerMotionMask | Button1MotionMask | \
93         Button2MotionMask | Button3MotionMask | Button4MotionMask | \
94         Button5MotionMask | ButtonMotionMask )
95 #define PropagateMask ( \
96         KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
97         MotionMask )
98 #define PointerGrabMask ( \
99         ButtonPressMask | ButtonReleaseMask | \
100         EnterWindowMask | LeaveWindowMask | \
101         PointerMotionHintMask | KeymapStateMask | \
102         MotionMask )
103 #define AllModifiersMask ( \
104         ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
105         Mod3Mask | Mod4Mask | Mod5Mask )
106 #define AllEventMasks (lastEventMask|(lastEventMask-1))
107 /*
108  * The following relies on the fact that the Button<n>MotionMasks are equal
109  * to the corresponding Button<n>Masks from the current modifier/button state.
110  */
111 #define Motion_Filter(class) (PointerMotionMask | \
112                               (class)->state | (class)->motionMask)
113
114
115 #define WID(w) ((w) ? ((w)->drawable.id) : 0)
116
117 #define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
118
119 CallbackListPtr EventCallback;
120 CallbackListPtr DeviceEventCallback;
121
122 #define DNPMCOUNT 8
123
124 Mask DontPropagateMasks[DNPMCOUNT];
125 static int DontPropagateRefCnts[DNPMCOUNT];
126
127 #ifdef DEBUG
128 static debug_events = 0;
129 #endif
130 InputInfo inputInfo;
131
132 static struct {
133     QdEventPtr          pending, *pendtail;
134     DeviceIntPtr        replayDev;      /* kludgy rock to put flag for */
135     WindowPtr           replayWin;      /*   ComputeFreezes            */
136     Bool                playingEvents;
137     TimeStamp           time;
138 } syncEvents;
139
140 /*
141  * The window trace information is used to avoid having to compute all the
142  * windows between the root and the current pointer window each time a button
143  * or key goes down. The grabs on each of those windows must be checked.
144  */
145 static WindowPtr *spriteTrace = (WindowPtr *)NULL;
146 #define ROOT spriteTrace[0]
147 static int spriteTraceSize = 0;
148 static int spriteTraceGood;
149
150 typedef struct {
151     int         x, y;
152     ScreenPtr   pScreen;
153 } HotSpot;
154
155 static  struct {
156     CursorPtr   current;
157     BoxRec      hotLimits;      /* logical constraints of hot spot */
158     Bool        confined;       /* confined to screen */
159 #ifdef SHAPE
160     RegionPtr   hotShape;       /* additional logical shape constraint */
161 #endif
162     BoxRec      physLimits;     /* physical constraints of hot spot */
163     WindowPtr   win;            /* window of logical position */
164     HotSpot     hot;            /* logical pointer position */
165     HotSpot     hotPhys;        /* physical pointer position */
166 } sprite;                       /* info about the cursor sprite */
167
168 static void DoEnterLeaveEvents(
169 #if NeedFunctionPrototypes
170     WindowPtr /*fromWin*/,
171     WindowPtr /*toWin*/,
172     int /*mode*/
173 #endif
174 );
175
176 static WindowPtr XYToWindow(
177 #if NeedFunctionPrototypes
178     int /*x*/,
179     int /*y*/
180 #endif
181 );
182
183 extern Bool permitOldBugs;
184 extern Bool Must_have_memory;
185 extern int lastEvent;
186 #ifdef XINPUT
187 extern int DeviceMotionNotify, DeviceButtonPress, DeviceKeyPress;
188 #endif
189
190 static Mask lastEventMask;
191
192 #define CantBeFiltered NoEventMask
193 static Mask filters[128] =
194 {
195         NoSuchEvent,                   /* 0 */
196         NoSuchEvent,                   /* 1 */
197         KeyPressMask,                  /* KeyPress */
198         KeyReleaseMask,                /* KeyRelease */
199         ButtonPressMask,               /* ButtonPress */
200         ButtonReleaseMask,             /* ButtonRelease */
201         PointerMotionMask,             /* MotionNotify (initial state) */
202         EnterWindowMask,               /* EnterNotify */
203         LeaveWindowMask,               /* LeaveNotify */
204         FocusChangeMask,               /* FocusIn */
205         FocusChangeMask,               /* FocusOut */
206         KeymapStateMask,               /* KeymapNotify */
207         ExposureMask,                  /* Expose */
208         CantBeFiltered,                /* GraphicsExpose */
209         CantBeFiltered,                /* NoExpose */
210         VisibilityChangeMask,          /* VisibilityNotify */
211         SubstructureNotifyMask,        /* CreateNotify */
212         StructureAndSubMask,           /* DestroyNotify */
213         StructureAndSubMask,           /* UnmapNotify */
214         StructureAndSubMask,           /* MapNotify */
215         SubstructureRedirectMask,      /* MapRequest */
216         StructureAndSubMask,           /* ReparentNotify */
217         StructureAndSubMask,           /* ConfigureNotify */
218         SubstructureRedirectMask,      /* ConfigureRequest */
219         StructureAndSubMask,           /* GravityNotify */
220         ResizeRedirectMask,            /* ResizeRequest */
221         StructureAndSubMask,           /* CirculateNotify */
222         SubstructureRedirectMask,      /* CirculateRequest */
223         PropertyChangeMask,            /* PropertyNotify */
224         CantBeFiltered,                /* SelectionClear */
225         CantBeFiltered,                /* SelectionRequest */
226         CantBeFiltered,                /* SelectionNotify */
227         ColormapChangeMask,            /* ColormapNotify */
228         CantBeFiltered,                /* ClientMessage */
229         CantBeFiltered                 /* MappingNotify */
230 };
231
232 static CARD8 criticalEvents[32] =
233 {
234     0x3c                                /* key and button events */
235 };
236
237 Mask
238 GetNextEventMask()
239 {
240     lastEventMask <<= 1;
241     return lastEventMask;
242 }
243
244 void
245 SetMaskForEvent(mask, event)
246     Mask mask;
247     int event;
248 {
249     if ((event < LASTEvent) || (event >= 128))
250         FatalError("SetMaskForEvent: bogus event number");
251     filters[event] = mask;
252 }
253
254 void
255 SetCriticalEvent(event)
256     int event;
257 {
258     if (event >= 128)
259         FatalError("SetCriticalEvent: bogus event number");
260     criticalEvents[event >> 3] |= 1 << (event & 7);
261 }
262
263 static void
264 #if NeedFunctionPrototypes
265 SyntheticMotion(int x, int y)
266 #else
267 SyntheticMotion(x, y)
268     int x, y;
269 #endif
270 {
271     xEvent xE;
272
273     xE.u.keyButtonPointer.rootX = x;
274     xE.u.keyButtonPointer.rootY = y;
275     if (syncEvents.playingEvents)
276         xE.u.keyButtonPointer.time = syncEvents.time.milliseconds;
277     else
278         xE.u.keyButtonPointer.time = currentTime.milliseconds;
279     xE.u.u.type = MotionNotify;
280     (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1);
281 }
282
283 #ifdef SHAPE
284 static void
285 #if NeedFunctionPrototypes
286 ConfineToShape(RegionPtr shape, int *px, int *py)
287 #else
288 ConfineToShape(shape, px, py)
289     RegionPtr shape;
290     int *px, *py;
291 #endif
292 {
293     BoxRec box;
294     int x = *px, y = *py;
295     int incx = 1, incy = 1;
296
297     if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box))
298         return;
299     box = *REGION_EXTENTS(sprite.hot.pScreen, shape);
300     /* this is rather crude */
301     do {
302         x += incx;
303         if (x >= box.x2)
304         {
305             incx = -1;
306             x = *px - 1;
307         }
308         else if (x < box.x1)
309         {
310             incx = 1;
311             x = *px;
312             y += incy;
313             if (y >= box.y2)
314             {
315                 incy = -1;
316                 y = *py - 1;
317             }
318             else if (y < box.y1)
319                 return; /* should never get here! */
320         }
321     } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box));
322     *px = x;
323     *py = y;
324 }
325 #endif
326
327 static void
328 #if NeedFunctionPrototypes
329 CheckPhysLimits(
330     CursorPtr cursor,
331     Bool generateEvents,
332     Bool confineToScreen,
333     ScreenPtr pScreen)
334 #else
335 CheckPhysLimits(cursor, generateEvents, confineToScreen, pScreen)
336     CursorPtr cursor;
337     Bool generateEvents;
338     Bool confineToScreen;
339     ScreenPtr pScreen;
340 #endif
341 {
342     HotSpot new;
343
344     if (!cursor)
345         return;
346     new = sprite.hotPhys;
347     if (pScreen)
348         new.pScreen = pScreen;
349     else
350         pScreen = new.pScreen;
351     (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits,
352                               &sprite.physLimits);
353     sprite.confined = confineToScreen;
354     (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits);
355     if (new.x < sprite.physLimits.x1)
356         new.x = sprite.physLimits.x1;
357     else
358         if (new.x >= sprite.physLimits.x2)
359             new.x = sprite.physLimits.x2 - 1;
360     if (new.y < sprite.physLimits.y1)
361         new.y = sprite.physLimits.y1;
362     else
363         if (new.y >= sprite.physLimits.y2)
364             new.y = sprite.physLimits.y2 - 1;
365 #ifdef SHAPE
366     if (sprite.hotShape)
367         ConfineToShape(sprite.hotShape, &new.x, &new.y);
368 #endif
369     if ((pScreen != sprite.hotPhys.pScreen) ||
370         (new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y))
371     {
372         if (pScreen != sprite.hotPhys.pScreen)
373             sprite.hotPhys = new;
374         (*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents);
375         if (!generateEvents)
376             SyntheticMotion(new.x, new.y);
377     }
378 }
379
380 static void
381 #if NeedFunctionPrototypes
382 CheckVirtualMotion(
383     register QdEventPtr qe,
384     register WindowPtr pWin)
385 #else
386 CheckVirtualMotion(qe, pWin)
387     register QdEventPtr qe;
388     register WindowPtr pWin;
389 #endif
390 {
391
392     if (qe)
393     {
394         sprite.hot.pScreen = qe->pScreen;
395         sprite.hot.x = qe->event->u.keyButtonPointer.rootX;
396         sprite.hot.y = qe->event->u.keyButtonPointer.rootY;
397         pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo :
398                                          NullWindow;
399     }
400     if (pWin)
401     {
402         BoxRec lims;
403
404         if (sprite.hot.pScreen != pWin->drawable.pScreen)
405         {
406             sprite.hot.pScreen = pWin->drawable.pScreen;
407             sprite.hot.x = sprite.hot.y = 0;
408         }
409         lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize);
410         if (sprite.hot.x < lims.x1)
411             sprite.hot.x = lims.x1;
412         else if (sprite.hot.x >= lims.x2)
413             sprite.hot.x = lims.x2 - 1;
414         if (sprite.hot.y < lims.y1)
415             sprite.hot.y = lims.y1;
416         else if (sprite.hot.y >= lims.y2)
417             sprite.hot.y = lims.y2 - 1;
418 #ifdef SHAPE
419         if (wBoundingShape(pWin))
420             ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y);
421 #endif
422         if (qe)
423         {
424             qe->pScreen = sprite.hot.pScreen;
425             qe->event->u.keyButtonPointer.rootX = sprite.hot.x;
426             qe->event->u.keyButtonPointer.rootY = sprite.hot.y;
427         }
428     }
429     ROOT = WindowTable[sprite.hot.pScreen->myNum];
430 }
431
432 void
433 ConfineCursorToWindow(pWin, generateEvents, confineToScreen)
434     WindowPtr pWin;
435     Bool generateEvents;
436     Bool confineToScreen;
437 {
438     ScreenPtr pScreen = pWin->drawable.pScreen;
439
440     if (syncEvents.playingEvents)
441     {
442         CheckVirtualMotion((QdEventPtr)NULL, pWin);
443         SyntheticMotion(sprite.hot.x, sprite.hot.y);
444     }
445     else
446     {
447         sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize);
448 #ifdef SHAPE
449         sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize
450                                                : NullRegion;
451 #endif
452         CheckPhysLimits(sprite.current, generateEvents, confineToScreen,
453                         pScreen);
454     }
455 }
456
457 Bool
458 PointerConfinedToScreen()
459 {
460     return sprite.confined;
461 }
462
463 static void
464 #if NeedFunctionPrototypes
465 ChangeToCursor(CursorPtr cursor)
466 #else
467 ChangeToCursor(cursor)
468     CursorPtr cursor;
469 #endif
470 {
471     if (cursor != sprite.current)
472     {
473         if ((sprite.current->bits->xhot != cursor->bits->xhot) ||
474                 (sprite.current->bits->yhot != cursor->bits->yhot))
475             CheckPhysLimits(cursor, FALSE, PointerConfinedToScreen(),
476                             (ScreenPtr)NULL);
477         (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen,
478                                                   cursor);
479         sprite.current = cursor;
480     }
481 }
482
483 /* returns true if b is a descendent of a */
484 Bool
485 IsParent(a, b)
486     register WindowPtr a, b;
487 {
488     for (b = b->parent; b; b = b->parent)
489         if (b == a) return TRUE;
490     return FALSE;
491 }
492
493 static void
494 #if NeedFunctionPrototypes
495 PostNewCursor(void)
496 #else
497 PostNewCursor()
498 #endif
499 {
500     register    WindowPtr win;
501     register    GrabPtr grab = inputInfo.pointer->grab;
502
503     if (syncEvents.playingEvents)
504         return;
505     if (grab)
506     {
507         if (grab->cursor)
508         {
509             ChangeToCursor(grab->cursor);
510             return;
511         }
512         if (IsParent(grab->window, sprite.win))
513             win = sprite.win;
514         else
515             win = grab->window;
516     }
517     else
518         win = sprite.win;
519     for (; win; win = win->parent)
520         if (win->optional && win->optional->cursor != NullCursor)
521         {
522             ChangeToCursor(win->optional->cursor);
523             return;
524         }
525 }
526
527 WindowPtr
528 GetCurrentRootWindow()
529 {
530     return ROOT;
531 }
532
533 WindowPtr
534 GetSpriteWindow()
535 {
536     return sprite.win;
537 }
538
539 CursorPtr
540 GetSpriteCursor()
541 {
542     return sprite.current;
543 }
544
545 void
546 GetSpritePosition(px, py)
547     int *px, *py;
548 {
549     *px = sprite.hotPhys.x;
550     *py = sprite.hotPhys.y;
551 }
552
553 #define TIMESLOP (5 * 60 * 1000) /* 5 minutes */
554
555 static void
556 #if NeedFunctionPrototypes
557 MonthChangedOrBadTime(register xEvent *xE)
558 #else
559 MonthChangedOrBadTime(xE)
560     register xEvent *xE;
561 #endif
562 {
563     /* If the ddx/OS is careless about not processing timestamped events from
564      * different sources in sorted order, then it's possible for time to go
565      * backwards when it should not.  Here we ensure a decent time.
566      */
567     if ((currentTime.milliseconds - xE->u.keyButtonPointer.time) > TIMESLOP)
568         currentTime.months++;
569     else
570         xE->u.keyButtonPointer.time = currentTime.milliseconds;
571 }
572
573 #define NoticeTime(xE) { \
574     if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \
575         MonthChangedOrBadTime(xE); \
576     currentTime.milliseconds = (xE)->u.keyButtonPointer.time; \
577     lastDeviceEventTime = currentTime; }
578
579 void
580 NoticeEventTime(xE)
581     register xEvent *xE;
582 {
583     if (!syncEvents.playingEvents)
584         NoticeTime(xE);
585 }
586
587 /**************************************************************************
588  *            The following procedures deal with synchronous events       *
589  **************************************************************************/
590
591 void
592 EnqueueEvent(xE, device, count)
593     xEvent              *xE;
594     DeviceIntPtr        device;
595     int                 count;
596 {
597     register QdEventPtr tail = *syncEvents.pendtail;
598     register QdEventPtr qe;
599     xEvent              *qxE;
600
601     NoticeTime(xE);
602     if (DeviceEventCallback)
603     {
604         DeviceEventInfoRec eventinfo;
605         /*  The RECORD spec says that the root window field of motion events
606          *  must be valid.  At this point, it hasn't been filled in yet, so
607          *  we do it here.  The long expression below is necessary to get
608          *  the current root window; the apparently reasonable alternative
609          *  GetCurrentRootWindow()->drawable.id doesn't give you the right
610          *  answer on the first motion event after a screen change because
611          *  the data that GetCurrentRootWindow relies on hasn't been
612          *  updated yet.
613          */
614         if (xE->u.u.type == MotionNotify)
615             xE->u.keyButtonPointer.root =
616                 WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id;
617         eventinfo.events = xE;
618         eventinfo.count = count;
619         CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
620     }
621     if (xE->u.u.type == MotionNotify)
622     {
623         sprite.hotPhys.x = xE->u.keyButtonPointer.rootX;
624         sprite.hotPhys.y = xE->u.keyButtonPointer.rootY;
625         /* do motion compression */
626         if (tail &&
627             (tail->event->u.u.type == MotionNotify) &&
628             (tail->pScreen == sprite.hotPhys.pScreen))
629         {
630             tail->event->u.keyButtonPointer.rootX = sprite.hotPhys.x;
631             tail->event->u.keyButtonPointer.rootY = sprite.hotPhys.y;
632             tail->event->u.keyButtonPointer.time = xE->u.keyButtonPointer.time;
633             tail->months = currentTime.months;
634             return;
635         }
636     }
637     qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent)));
638     if (!qe)
639         return;
640     qe->next = (QdEventPtr)NULL;
641     qe->device = device;
642     qe->pScreen = sprite.hotPhys.pScreen;
643     qe->months = currentTime.months;
644     qe->event = (xEvent *)(qe + 1);
645     qe->evcount = count;
646     for (qxE = qe->event; --count >= 0; qxE++, xE++)
647         *qxE = *xE;
648     if (tail)
649         syncEvents.pendtail = &tail->next;
650     *syncEvents.pendtail = qe;
651 }
652
653 static void
654 #if NeedFunctionPrototypes
655 PlayReleasedEvents(void)
656 #else
657 PlayReleasedEvents()
658 #endif
659 {
660     register QdEventPtr *prev, qe;
661     register DeviceIntPtr dev;
662
663     prev = &syncEvents.pending;
664     while ( (qe = *prev) )
665     {
666         if (!qe->device->sync.frozen)
667         {
668             *prev = qe->next;
669             if (*syncEvents.pendtail == *prev)
670                 syncEvents.pendtail = prev;
671             if (qe->event->u.u.type == MotionNotify)
672                 CheckVirtualMotion(qe, NullWindow);
673             syncEvents.time.months = qe->months;
674             syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time;
675             (*qe->device->public.processInputProc)(qe->event, qe->device,
676                                                    qe->evcount);
677             xfree(qe);
678             for (dev = inputInfo.devices; dev && dev->sync.frozen; dev = dev->next)
679                 ;
680             if (!dev)
681                 break;
682             /* Playing the event may have unfrozen another device. */
683             /* So to play it safe, restart at the head of the queue */
684             prev = &syncEvents.pending;
685         }
686         else
687             prev = &qe->next;
688     } 
689 }
690
691 static void
692 #if NeedFunctionPrototypes
693 FreezeThaw(register DeviceIntPtr dev, Bool frozen)
694 #else
695 FreezeThaw(dev, frozen)
696     register DeviceIntPtr dev;
697     Bool frozen;
698 #endif
699 {
700     dev->sync.frozen = frozen;
701     if (frozen)
702         dev->public.processInputProc = dev->public.enqueueInputProc;
703     else
704         dev->public.processInputProc = dev->public.realInputProc;
705 }
706
707 void
708 ComputeFreezes()
709 {
710     register DeviceIntPtr replayDev = syncEvents.replayDev;
711     register int i;
712     WindowPtr w;
713     register xEvent *xE;
714     int count;
715     GrabPtr grab;
716     register DeviceIntPtr dev;
717
718     for (dev = inputInfo.devices; dev; dev = dev->next)
719         FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN));
720     if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
721         return;
722     syncEvents.playingEvents = TRUE;
723     if (replayDev)
724     {
725         xE = replayDev->sync.event;
726         count = replayDev->sync.evcount;
727         syncEvents.replayDev = (DeviceIntPtr)NULL;
728         w = XYToWindow(
729             xE->u.keyButtonPointer.rootX, xE->u.keyButtonPointer.rootY);
730         for (i = 0; i < spriteTraceGood; i++)
731             if (syncEvents.replayWin == spriteTrace[i])
732             {
733                 if (!CheckDeviceGrabs(replayDev, xE, i+1, count))
734                     if (replayDev->focus)
735                         DeliverFocusedEvent(replayDev, xE, w, count);
736                     else
737                         DeliverDeviceEvents(w, xE, NullGrab, NullWindow,
738                                             replayDev, count);
739                 goto playmore;
740             }
741         /* must not still be in the same stack */
742         if (replayDev->focus)
743             DeliverFocusedEvent(replayDev, xE, w, count);
744         else
745             DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count);
746     }
747 playmore:
748     for (dev = inputInfo.devices; dev; dev = dev->next)
749     {
750         if (!dev->sync.frozen)
751         {
752             PlayReleasedEvents();
753             break;
754         }
755     }
756     syncEvents.playingEvents = FALSE;
757     /* the following may have been skipped during replay, so do it now */
758     if ((grab = inputInfo.pointer->grab) && grab->confineTo)
759     {
760         if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
761             sprite.hotPhys.x = sprite.hotPhys.y = 0;
762         ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
763     }
764     else
765         ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum],
766                               TRUE, FALSE);
767     PostNewCursor();
768 }
769
770 void
771 CheckGrabForSyncs(thisDev, thisMode, otherMode)
772     register DeviceIntPtr thisDev;
773     Bool thisMode, otherMode;
774 {
775     register GrabPtr grab = thisDev->grab;
776     register DeviceIntPtr dev;
777
778     if (thisMode == GrabModeSync)
779         thisDev->sync.state = FROZEN_NO_EVENT;
780     else
781     {   /* free both if same client owns both */
782         thisDev->sync.state = THAWED;
783         if (thisDev->sync.other &&
784             (CLIENT_BITS(thisDev->sync.other->resource) ==
785              CLIENT_BITS(grab->resource)))
786             thisDev->sync.other = NullGrab;
787     }
788     for (dev = inputInfo.devices; dev; dev = dev->next)
789     {
790         if (dev != thisDev)
791         {
792             if (otherMode == GrabModeSync)
793                 dev->sync.other = grab;
794             else
795             {   /* free both if same client owns both */
796                 if (dev->sync.other &&
797                     (CLIENT_BITS(dev->sync.other->resource) ==
798                      CLIENT_BITS(grab->resource)))
799                     dev->sync.other = NullGrab;
800             }
801         }
802     }
803     ComputeFreezes();
804 }
805
806 void
807 ActivatePointerGrab(mouse, grab, time, autoGrab)
808     register GrabPtr grab;
809     register DeviceIntPtr mouse;
810     TimeStamp time;
811     Bool autoGrab;
812 {
813     WindowPtr oldWin = (mouse->grab) ? mouse->grab->window
814                                      : sprite.win;
815
816     if (grab->confineTo)
817     {
818         if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
819             sprite.hotPhys.x = sprite.hotPhys.y = 0;
820         ConfineCursorToWindow(grab->confineTo, FALSE, TRUE);
821     }
822     DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab);
823     mouse->valuator->motionHintWindow = NullWindow;
824     if (syncEvents.playingEvents)
825         mouse->grabTime = syncEvents.time;
826     else
827         mouse->grabTime = time;
828     if (grab->cursor)
829         grab->cursor->refcnt++;
830     mouse->activeGrab = *grab;
831     mouse->grab = &mouse->activeGrab;
832     mouse->fromPassiveGrab = autoGrab;
833     PostNewCursor();
834     CheckGrabForSyncs(mouse,
835                       (Bool)grab->pointerMode, (Bool)grab->keyboardMode);
836 }
837
838 void
839 DeactivatePointerGrab(mouse)
840     register DeviceIntPtr mouse;
841 {
842     register GrabPtr grab = mouse->grab;
843     register DeviceIntPtr dev;
844
845     mouse->valuator->motionHintWindow = NullWindow;
846     mouse->grab = NullGrab;
847     mouse->sync.state = NOT_GRABBED;
848     mouse->fromPassiveGrab = FALSE;
849     for (dev = inputInfo.devices; dev; dev = dev->next)
850     {
851         if (dev->sync.other == grab)
852             dev->sync.other = NullGrab;
853     }
854     DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab);
855     if (grab->confineTo)
856         ConfineCursorToWindow(ROOT, FALSE, FALSE);
857     PostNewCursor();
858     if (grab->cursor)
859         FreeCursor(grab->cursor, (Cursor)0);
860     ComputeFreezes();
861 }
862
863 void
864 ActivateKeyboardGrab(keybd, grab, time, passive)
865     register DeviceIntPtr keybd;
866     GrabPtr grab;
867     TimeStamp time;
868     Bool passive;
869 {
870     WindowPtr oldWin;
871
872     if (keybd->grab)
873         oldWin = keybd->grab->window;
874     else if (keybd->focus)
875         oldWin = keybd->focus->win;
876     else
877         oldWin = sprite.win;
878     if (oldWin == FollowKeyboardWin)
879         oldWin = inputInfo.keyboard->focus->win;
880     if (keybd->valuator)
881         keybd->valuator->motionHintWindow = NullWindow;
882     DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
883     if (syncEvents.playingEvents)
884         keybd->grabTime = syncEvents.time;
885     else
886         keybd->grabTime = time;
887     keybd->activeGrab = *grab;
888     keybd->grab = &keybd->activeGrab;
889     keybd->fromPassiveGrab = passive;
890     CheckGrabForSyncs(keybd,
891                       (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
892 }
893
894 void
895 DeactivateKeyboardGrab(keybd)
896     register DeviceIntPtr keybd;
897 {
898     register GrabPtr grab = keybd->grab;
899     register DeviceIntPtr dev;
900     register WindowPtr focusWin = keybd->focus ? keybd->focus->win
901                                                : sprite.win;
902
903     if (focusWin == FollowKeyboardWin)
904         focusWin = inputInfo.keyboard->focus->win;
905     if (keybd->valuator)
906         keybd->valuator->motionHintWindow = NullWindow;
907     keybd->grab = NullGrab;
908     keybd->sync.state = NOT_GRABBED;
909     keybd->fromPassiveGrab = FALSE;
910     for (dev = inputInfo.devices; dev; dev = dev->next)
911     {
912         if (dev->sync.other == grab)
913             dev->sync.other = NullGrab;
914     }
915     DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
916     ComputeFreezes();
917 }
918
919 void
920 AllowSome(client, time, thisDev, newState)
921     ClientPtr           client;
922     TimeStamp           time;
923     register DeviceIntPtr thisDev;
924     int                 newState;
925 {
926     Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
927     TimeStamp grabTime;
928     register DeviceIntPtr dev;
929
930     thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client);
931     thisSynced = FALSE;
932     otherGrabbed = FALSE;
933     othersFrozen = TRUE;
934     grabTime = thisDev->grabTime;
935     for (dev = inputInfo.devices; dev; dev = dev->next)
936     {
937         if (dev == thisDev)
938             continue;
939         if (dev->grab && SameClient(dev->grab, client))
940         {
941             if (!(thisGrabbed || otherGrabbed) ||
942                 (CompareTimeStamps(dev->grabTime, grabTime) == LATER))
943                 grabTime = dev->grabTime;
944             otherGrabbed = TRUE;
945             if (thisDev->sync.other == dev->grab)
946                 thisSynced = TRUE;
947             if (dev->sync.state < FROZEN)
948                 othersFrozen = FALSE;
949         }
950         else if (!dev->sync.other || !SameClient(dev->sync.other, client))
951             othersFrozen = FALSE;
952     }
953     if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced))
954         return;
955     if ((CompareTimeStamps(time, currentTime) == LATER) ||
956         (CompareTimeStamps(time, grabTime) == EARLIER))
957         return;
958     switch (newState)
959     {
960         case THAWED:                   /* Async */
961             if (thisGrabbed)
962                 thisDev->sync.state = THAWED;
963             if (thisSynced)
964                 thisDev->sync.other = NullGrab;
965             ComputeFreezes();
966             break;
967         case FREEZE_NEXT_EVENT:         /* Sync */
968             if (thisGrabbed)
969             {
970                 thisDev->sync.state = FREEZE_NEXT_EVENT;
971                 if (thisSynced)
972                     thisDev->sync.other = NullGrab;
973                 ComputeFreezes();
974             }
975             break;
976         case THAWED_BOTH:               /* AsyncBoth */
977             if (othersFrozen)
978             {
979                 for (dev = inputInfo.devices; dev; dev = dev->next)
980                 {
981                     if (dev->grab && SameClient(dev->grab, client))
982                         dev->sync.state = THAWED;
983                     if (dev->sync.other && SameClient(dev->sync.other, client))
984                         dev->sync.other = NullGrab;
985                 }
986                 ComputeFreezes();
987             }
988             break;
989         case FREEZE_BOTH_NEXT_EVENT:    /* SyncBoth */
990             if (othersFrozen)
991             {
992                 for (dev = inputInfo.devices; dev; dev = dev->next)
993                 {
994                     if (dev->grab && SameClient(dev->grab, client))
995                         dev->sync.state = FREEZE_BOTH_NEXT_EVENT;
996                     if (dev->sync.other && SameClient(dev->sync.other, client))
997                         dev->sync.other = NullGrab;
998                 }
999                 ComputeFreezes();
1000             }
1001             break;
1002         case NOT_GRABBED:               /* Replay */
1003             if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT)
1004             {
1005                 if (thisSynced)
1006                     thisDev->sync.other = NullGrab;
1007                 syncEvents.replayDev = thisDev;
1008                 syncEvents.replayWin = thisDev->grab->window;
1009                 (*thisDev->DeactivateGrab)(thisDev);
1010                 syncEvents.replayDev = (DeviceIntPtr)NULL;
1011             }
1012             break;
1013         case THAW_OTHERS:               /* AsyncOthers */
1014             if (othersFrozen)
1015             {
1016                 for (dev = inputInfo.devices; dev; dev = dev->next)
1017                 {
1018                     if (dev == thisDev)
1019                         continue;
1020                     if (dev->grab && SameClient(dev->grab, client))
1021                         dev->sync.state = THAWED;
1022                     if (dev->sync.other && SameClient(dev->sync.other, client))
1023                         dev->sync.other = NullGrab;
1024                 }
1025                 ComputeFreezes();
1026             }
1027             break;
1028     }
1029 }
1030
1031 int
1032 ProcAllowEvents(client)
1033     register ClientPtr client;
1034 {
1035     TimeStamp           time;
1036     DeviceIntPtr        mouse = inputInfo.pointer;
1037     DeviceIntPtr        keybd = inputInfo.keyboard;
1038     REQUEST(xAllowEventsReq);
1039
1040     REQUEST_SIZE_MATCH(xAllowEventsReq);
1041     time = ClientTimeToServerTime(stuff->time);
1042     switch (stuff->mode)
1043     {
1044         case ReplayPointer:
1045             AllowSome(client, time, mouse, NOT_GRABBED);
1046             break;
1047         case SyncPointer: 
1048             AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
1049             break;
1050         case AsyncPointer: 
1051             AllowSome(client, time, mouse, THAWED);
1052             break;
1053         case ReplayKeyboard: 
1054             AllowSome(client, time, keybd, NOT_GRABBED);
1055             break;
1056         case SyncKeyboard: 
1057             AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
1058             break;
1059         case AsyncKeyboard: 
1060             AllowSome(client, time, keybd, THAWED);
1061             break;
1062         case SyncBoth:
1063             AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
1064             break;
1065         case AsyncBoth:
1066             AllowSome(client, time, keybd, THAWED_BOTH);
1067             break;
1068         default: 
1069             client->errorValue = stuff->mode;
1070             return BadValue;
1071     }
1072     return Success;
1073 }
1074
1075 void
1076 ReleaseActiveGrabs(client)
1077     ClientPtr client;
1078 {
1079     register DeviceIntPtr dev;
1080     Bool    done;
1081
1082     /* XXX CloseDownClient should remove passive grabs before
1083      * releasing active grabs.
1084      */
1085     do {
1086         done = TRUE;
1087         for (dev = inputInfo.devices; dev; dev = dev->next)
1088         {
1089             if (dev->grab && SameClient(dev->grab, client))
1090             {
1091                 (*dev->DeactivateGrab)(dev);
1092                 done = FALSE;
1093             }
1094         }
1095     } while (!done);
1096 }
1097
1098 /**************************************************************************
1099  *            The following procedures deal with delivering events        *
1100  **************************************************************************/
1101
1102 int
1103 TryClientEvents (client, pEvents, count, mask, filter, grab)
1104     ClientPtr client;
1105     GrabPtr grab;
1106     xEvent *pEvents;
1107     int count;
1108     Mask mask, filter;
1109 {
1110     int i;
1111     int type;
1112
1113 #ifdef DEBUG
1114     if (debug_events) ErrorF(
1115         "Event([%d, %d], mask=0x%x), client=%d",
1116         pEvents->u.u.type, pEvents->u.u.detail, mask, client->index);
1117 #endif
1118     if ((client) && (client != serverClient) && (!client->clientGone) &&
1119         ((filter == CantBeFiltered) || (mask & filter)))
1120     {
1121         if (grab && !SameClient(grab, client))
1122             return -1; /* don't send, but notify caller */
1123         type = pEvents->u.u.type;
1124         if (type == MotionNotify)
1125         {
1126             if (mask & PointerMotionHintMask)
1127             {
1128                 if (WID(inputInfo.pointer->valuator->motionHintWindow) ==
1129                     pEvents->u.keyButtonPointer.event)
1130                 {
1131 #ifdef DEBUG
1132                     if (debug_events) ErrorF("\n");
1133 #endif
1134                     return 1; /* don't send, but pretend we did */
1135                 }
1136                 pEvents->u.u.detail = NotifyHint;
1137             }
1138             else
1139             {
1140                 pEvents->u.u.detail = NotifyNormal;
1141             }
1142         }
1143 #ifdef XINPUT
1144         else
1145         {
1146             if ((type == DeviceMotionNotify) &&
1147                 MaybeSendDeviceMotionNotifyHint
1148                         ((deviceKeyButtonPointer*)pEvents, mask) != 0)
1149                 return 1;
1150         }
1151 #endif
1152         type &= 0177;
1153         if (type != KeymapNotify)
1154         {
1155             /* all extension events must have a sequence number */
1156             for (i = 0; i < count; i++)
1157                 pEvents[i].u.u.sequenceNumber = client->sequence;
1158         }
1159
1160         if (BitIsOn(criticalEvents, type))
1161             SetCriticalOutputPending();
1162
1163         WriteEventsToClient(client, count, pEvents);
1164 #ifdef DEBUG
1165         if (debug_events) ErrorF(  " delivered\n");
1166 #endif
1167         return 1;
1168     }
1169     else
1170     {
1171 #ifdef DEBUG
1172         if (debug_events) ErrorF("\n");
1173 #endif
1174         return 0;
1175     }
1176 }
1177
1178 int
1179 DeliverEventsToWindow(pWin, pEvents, count, filter, grab, mskidx)
1180     register WindowPtr pWin;
1181     GrabPtr grab;
1182     xEvent *pEvents;
1183     int count;
1184     Mask filter;
1185     int mskidx;
1186 {
1187     int deliveries = 0, nondeliveries = 0;
1188     int attempt;
1189     register InputClients *other;
1190     ClientPtr client = NullClient;
1191     Mask deliveryMask;  /* If a grab occurs due to a button press, then
1192                               this mask is the mask of the grab. */
1193     int type = pEvents->u.u.type;
1194
1195     /* CantBeFiltered means only window owner gets the event */
1196     if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE))
1197     {
1198         /* if nobody ever wants to see this event, skip some work */
1199         if (filter != CantBeFiltered &&
1200             !((wOtherEventMasks(pWin)|pWin->eventMask) & filter))
1201             return 0;
1202         if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count,
1203                                       pWin->eventMask, filter, grab)) )
1204         {
1205             if (attempt > 0)
1206             {
1207                 deliveries++;
1208                 client = wClient(pWin);
1209                 deliveryMask = pWin->eventMask;
1210             } else
1211                 nondeliveries--;
1212         }
1213     }
1214     if (filter != CantBeFiltered)
1215     {
1216         if (type & EXTENSION_EVENT_BASE)
1217         {
1218             OtherInputMasks *inputMasks;
1219
1220             inputMasks = wOtherInputMasks(pWin);
1221             if (!inputMasks ||
1222                 !(inputMasks->inputEvents[mskidx] & filter))
1223                 return 0;
1224             other = inputMasks->inputClients;
1225         }
1226         else
1227             other = (InputClients *)wOtherClients(pWin);
1228         for (; other; other = other->next)
1229         {
1230             if ( (attempt = TryClientEvents(rClient(other), pEvents, count,
1231                                           other->mask[mskidx], filter, grab)) )
1232             {
1233                 if (attempt > 0)
1234                 {
1235                     deliveries++;
1236                     client = rClient(other);
1237                     deliveryMask = other->mask[mskidx];
1238                 } else
1239                     nondeliveries--;
1240             }
1241         }
1242     }
1243     if ((type == ButtonPress) && deliveries && (!grab))
1244     {
1245         GrabRec tempGrab;
1246
1247         tempGrab.device = inputInfo.pointer;
1248         tempGrab.resource = client->clientAsMask;
1249         tempGrab.window = pWin;
1250         tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
1251         tempGrab.eventMask = deliveryMask;
1252         tempGrab.keyboardMode = GrabModeAsync;
1253         tempGrab.pointerMode = GrabModeAsync;
1254         tempGrab.confineTo = NullWindow;
1255         tempGrab.cursor = NullCursor;
1256         (*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab,
1257                                            currentTime, TRUE);
1258     }
1259     else if ((type == MotionNotify) && deliveries)
1260         inputInfo.pointer->valuator->motionHintWindow = pWin;
1261 #ifdef XINPUT
1262     else
1263     {
1264         if (((type == DeviceMotionNotify) || (type == DeviceButtonPress)) &&
1265             deliveries)
1266             CheckDeviceGrabAndHintWindow (pWin, type,
1267                                           (deviceKeyButtonPointer*) pEvents,
1268                                           grab, client, deliveryMask);
1269     }
1270 #endif
1271     if (deliveries)
1272         return deliveries;
1273     return nondeliveries;
1274 }
1275
1276 /* If the event goes to dontClient, don't send it and return 0.  if
1277    send works,  return 1 or if send didn't work, return 2.
1278    Only works for core events.
1279 */
1280
1281 int
1282 MaybeDeliverEventsToClient(pWin, pEvents, count, filter, dontClient)
1283     register WindowPtr pWin;
1284     xEvent *pEvents;
1285     int count;
1286     Mask filter;
1287     ClientPtr dontClient;
1288 {
1289     register OtherClients *other;
1290
1291     if (pWin->eventMask & filter)
1292     {
1293         if (wClient(pWin) == dontClient)
1294             return 0;
1295         return TryClientEvents(wClient(pWin), pEvents, count,
1296                                pWin->eventMask, filter, NullGrab);
1297     }
1298     for (other = wOtherClients(pWin); other; other = other->next)
1299     {
1300         if (other->mask & filter)
1301         {
1302             if (SameClient(other, dontClient))
1303                 return 0;
1304             return TryClientEvents(rClient(other), pEvents, count,
1305                                    other->mask, filter, NullGrab);
1306         }
1307     }
1308     return 2;
1309 }
1310
1311 static void
1312 #if NeedFunctionPrototypes
1313 FixUpEventFromWindow(
1314     xEvent *xE,
1315     WindowPtr pWin,
1316     Window child,
1317     Bool calcChild)
1318 #else
1319 FixUpEventFromWindow(xE, pWin, child, calcChild)
1320     xEvent *xE;
1321     WindowPtr pWin;
1322     Window child;
1323     Bool calcChild;
1324 #endif
1325 {
1326     if (calcChild)
1327     {
1328         WindowPtr w=spriteTrace[spriteTraceGood-1];
1329
1330         /* If the search ends up past the root should the child field be 
1331                 set to none or should the value in the argument be passed 
1332                 through. It probably doesn't matter since everyone calls 
1333                 this function with child == None anyway. */
1334
1335         while (w) 
1336         {
1337             /* If the source window is same as event window, child should be
1338                 none.  Don't bother going all all the way back to the root. */
1339
1340             if (w == pWin)
1341             { 
1342                 child = None;
1343                 break;
1344             }
1345             
1346             if (w->parent == pWin)
1347             {
1348                 child = w->drawable.id;
1349                 break;
1350             }
1351             w = w->parent;
1352         }           
1353     }
1354     xE->u.keyButtonPointer.root = ROOT->drawable.id;
1355     xE->u.keyButtonPointer.event = pWin->drawable.id;
1356     if (sprite.hot.pScreen == pWin->drawable.pScreen)
1357     {
1358         xE->u.keyButtonPointer.sameScreen = xTrue;
1359         xE->u.keyButtonPointer.child = child;
1360         xE->u.keyButtonPointer.eventX =
1361             xE->u.keyButtonPointer.rootX - pWin->drawable.x;
1362         xE->u.keyButtonPointer.eventY =
1363             xE->u.keyButtonPointer.rootY - pWin->drawable.y;
1364     }
1365     else
1366     {
1367         xE->u.keyButtonPointer.sameScreen = xFalse;
1368         xE->u.keyButtonPointer.child = None;
1369         xE->u.keyButtonPointer.eventX = 0;
1370         xE->u.keyButtonPointer.eventY = 0;
1371     }
1372 }
1373
1374 int
1375 DeliverDeviceEvents(pWin, xE, grab, stopAt, dev, count)
1376     register WindowPtr pWin, stopAt;
1377     register xEvent *xE;
1378     GrabPtr grab;
1379     DeviceIntPtr dev;
1380     int count;
1381 {
1382     Window child = None;
1383     int type = xE->u.u.type;
1384     Mask filter = filters[type];
1385     int deliveries = 0;
1386
1387     if (type & EXTENSION_EVENT_BASE)
1388     {
1389         register OtherInputMasks *inputMasks;
1390         int mskidx = dev->id;
1391
1392         inputMasks = wOtherInputMasks(pWin);
1393         if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx]))
1394             return 0;
1395         while (pWin)
1396         {
1397             if (inputMasks && (inputMasks->inputEvents[mskidx] & filter))
1398             {
1399                 FixUpEventFromWindow(xE, pWin, child, FALSE);
1400                 deliveries = DeliverEventsToWindow(pWin, xE, count, filter,
1401                                                    grab, mskidx);
1402                 if (deliveries > 0)
1403                     return deliveries;
1404             }
1405             if ((deliveries < 0) ||
1406                 (pWin == stopAt) ||
1407                 (inputMasks &&
1408                  (filter & inputMasks->dontPropagateMask[mskidx])))
1409                 return 0;
1410             child = pWin->drawable.id;
1411             pWin = pWin->parent;
1412             if (pWin)
1413                 inputMasks = wOtherInputMasks(pWin);
1414         }
1415     }
1416     else
1417     {
1418         if (!(filter & pWin->deliverableEvents))
1419             return 0;
1420         while (pWin)
1421         {
1422             if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter)
1423             {
1424                 FixUpEventFromWindow(xE, pWin, child, FALSE);
1425                 deliveries = DeliverEventsToWindow(pWin, xE, count, filter,
1426                                                    grab, 0);
1427                 if (deliveries > 0)
1428                     return deliveries;
1429             }
1430             if ((deliveries < 0) ||
1431                 (pWin == stopAt) ||
1432                 (filter & wDontPropagateMask(pWin)))
1433                 return 0;
1434             child = pWin->drawable.id;
1435             pWin = pWin->parent;
1436         }
1437     }
1438     return 0;
1439 }
1440
1441 /* not useful for events that propagate up the tree or extension events */
1442 int
1443 DeliverEvents(pWin, xE, count, otherParent)
1444     register WindowPtr pWin, otherParent;
1445     register xEvent *xE;
1446     int count;
1447 {
1448     Mask filter;
1449     int     deliveries;
1450
1451     if (!count)
1452         return 0;
1453     filter = filters[xE->u.u.type];
1454     if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify))
1455         xE->u.destroyNotify.event = pWin->drawable.id;
1456     if (filter != StructureAndSubMask)
1457         return DeliverEventsToWindow(pWin, xE, count, filter, NullGrab, 0);
1458     deliveries = DeliverEventsToWindow(pWin, xE, count, StructureNotifyMask,
1459                                        NullGrab, 0);
1460     if (pWin->parent)
1461     {
1462         xE->u.destroyNotify.event = pWin->parent->drawable.id;
1463         deliveries += DeliverEventsToWindow(pWin->parent, xE, count,
1464                                             SubstructureNotifyMask, NullGrab,
1465                                             0);
1466         if (xE->u.u.type == ReparentNotify)
1467         {
1468             xE->u.destroyNotify.event = otherParent->drawable.id;
1469             deliveries += DeliverEventsToWindow(otherParent, xE, count,
1470                                                 SubstructureNotifyMask,
1471                                                 NullGrab, 0);
1472         }
1473     }
1474     return deliveries;
1475 }
1476
1477 static WindowPtr 
1478 #if NeedFunctionPrototypes
1479 XYToWindow(int x, int y)
1480 #else
1481 XYToWindow(x, y)
1482         int x, y;
1483 #endif
1484 {
1485     register WindowPtr  pWin;
1486 #ifdef SHAPE
1487     BoxRec              box;
1488 #endif
1489
1490     spriteTraceGood = 1;        /* root window still there */
1491     pWin = ROOT->firstChild;
1492     while (pWin)
1493     {
1494         if ((pWin->mapped) &&
1495                 (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
1496                 (x < pWin->drawable.x + (int)pWin->drawable.width +
1497                     wBorderWidth(pWin)) &&
1498                 (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
1499                 (y < pWin->drawable.y + (int)pWin->drawable.height +
1500                     wBorderWidth (pWin))
1501 #ifdef SHAPE
1502                 /* When a window is shaped, a further check
1503                  * is made to see if the point is inside
1504                  * borderSize
1505                  */
1506                 && (!wBoundingShape(pWin) ||
1507                     POINT_IN_REGION(pWin->drawable.pScreen, 
1508                             &pWin->borderSize, x, y, &box))
1509 #endif
1510                 )
1511         {
1512             if (spriteTraceGood >= spriteTraceSize)
1513             {
1514                 spriteTraceSize += 10;
1515                 Must_have_memory = TRUE; /* XXX */
1516                 spriteTrace = (WindowPtr *)xrealloc(
1517                     spriteTrace, spriteTraceSize*sizeof(WindowPtr));
1518                 Must_have_memory = FALSE; /* XXX */
1519             }
1520             spriteTrace[spriteTraceGood++] = pWin;
1521             pWin = pWin->firstChild;
1522         }
1523         else
1524             pWin = pWin->nextSib;
1525     }
1526     return spriteTrace[spriteTraceGood-1];
1527 }
1528
1529 static Bool
1530 #if NeedFunctionPrototypes
1531 CheckMotion(xEvent *xE)
1532 #else
1533 CheckMotion(xE)
1534     xEvent *xE;
1535 #endif
1536 {
1537     WindowPtr prevSpriteWin = sprite.win;
1538
1539     if (xE && !syncEvents.playingEvents)
1540     {
1541         if (sprite.hot.pScreen != sprite.hotPhys.pScreen)
1542         {
1543             sprite.hot.pScreen = sprite.hotPhys.pScreen;
1544             ROOT = WindowTable[sprite.hot.pScreen->myNum];
1545         }
1546         sprite.hot.x = xE->u.keyButtonPointer.rootX;
1547         sprite.hot.y = xE->u.keyButtonPointer.rootY;
1548         if (sprite.hot.x < sprite.physLimits.x1)
1549             sprite.hot.x = sprite.physLimits.x1;
1550         else if (sprite.hot.x >= sprite.physLimits.x2)
1551             sprite.hot.x = sprite.physLimits.x2 - 1;
1552         if (sprite.hot.y < sprite.physLimits.y1)
1553             sprite.hot.y = sprite.physLimits.y1;
1554         else if (sprite.hot.y >= sprite.physLimits.y2)
1555             sprite.hot.y = sprite.physLimits.y2 - 1;
1556 #ifdef SHAPE
1557         if (sprite.hotShape)
1558             ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y);
1559 #endif
1560         sprite.hotPhys = sprite.hot;
1561         if ((sprite.hotPhys.x != xE->u.keyButtonPointer.rootX) ||
1562             (sprite.hotPhys.y != xE->u.keyButtonPointer.rootY))
1563             (*sprite.hotPhys.pScreen->SetCursorPosition)(
1564                 sprite.hotPhys.pScreen,
1565                 sprite.hotPhys.x, sprite.hotPhys.y, FALSE);
1566         xE->u.keyButtonPointer.rootX = sprite.hot.x;
1567         xE->u.keyButtonPointer.rootY = sprite.hot.y;
1568     }
1569
1570     sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y);
1571 #ifdef notyet
1572     if (!(sprite.win->deliverableEvents &
1573           Motion_Filter(inputInfo.pointer->button))
1574         !syncEvents.playingEvents)
1575     {
1576         /* XXX Do PointerNonInterestBox here */
1577     }
1578 #endif
1579     if (sprite.win != prevSpriteWin)
1580     {
1581         if (prevSpriteWin != NullWindow) {
1582             if (!xE)
1583                 UpdateCurrentTimeIf();
1584             DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal);
1585         }
1586         PostNewCursor();
1587         return FALSE;
1588     }
1589     return TRUE;
1590 }
1591
1592 void
1593 WindowsRestructured()
1594 {
1595     (void) CheckMotion((xEvent *)NULL);
1596 }
1597
1598 void
1599 DefineInitialRootWindow(win)
1600     register WindowPtr win;
1601 {
1602     register ScreenPtr pScreen = win->drawable.pScreen;
1603
1604     sprite.hotPhys.pScreen = pScreen;
1605     sprite.hotPhys.x = pScreen->width / 2;
1606     sprite.hotPhys.y = pScreen->height / 2;
1607     sprite.hot = sprite.hotPhys;
1608     sprite.hotLimits.x2 = pScreen->width;
1609     sprite.hotLimits.y2 = pScreen->height;
1610     sprite.win = win;
1611     sprite.current = wCursor (win);
1612     spriteTraceGood = 1;
1613     ROOT = win;
1614     (*pScreen->CursorLimits) (
1615         pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits);
1616     sprite.confined = FALSE;
1617     (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits);
1618     (*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE);
1619     (*pScreen->DisplayCursor) (pScreen, sprite.current);
1620 }
1621
1622 /*
1623  * This does not take any shortcuts, and even ignores its argument, since
1624  * it does not happen very often, and one has to walk up the tree since
1625  * this might be a newly instantiated cursor for an intermediate window
1626  * between the one the pointer is in and the one that the last cursor was
1627  * instantiated from.
1628  */
1629 /*ARGSUSED*/
1630 void
1631 WindowHasNewCursor(pWin)
1632     WindowPtr pWin;
1633 {
1634     PostNewCursor();
1635 }
1636
1637 void
1638 NewCurrentScreen(newScreen, x, y)
1639     ScreenPtr newScreen;
1640     int x,y;
1641 {
1642     sprite.hotPhys.x = x;
1643     sprite.hotPhys.y = y;
1644     if (newScreen != sprite.hotPhys.pScreen)
1645         ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE);
1646 }
1647
1648 int
1649 ProcWarpPointer(client)
1650     ClientPtr client;
1651 {
1652     WindowPtr   dest = NULL;
1653     int         x, y;
1654     ScreenPtr   newScreen;
1655
1656     REQUEST(xWarpPointerReq);
1657
1658     REQUEST_SIZE_MATCH(xWarpPointerReq);
1659     if (stuff->dstWid != None)
1660     {
1661         dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess);
1662         if (!dest)
1663             return BadWindow;
1664     }
1665     x = sprite.hotPhys.x;
1666     y = sprite.hotPhys.y;
1667     if (stuff->srcWid != None)
1668     {
1669         int     winX, winY;
1670         WindowPtr source = SecurityLookupWindow(stuff->srcWid, client,
1671                                                 SecurityReadAccess);
1672         if (!source)
1673             return BadWindow;
1674         winX = source->drawable.x;
1675         winY = source->drawable.y;
1676         if (source->drawable.pScreen != sprite.hotPhys.pScreen ||
1677             x < winX + stuff->srcX ||
1678             y < winY + stuff->srcY ||
1679             (stuff->srcWidth != 0 &&
1680              winX + stuff->srcX + (int)stuff->srcWidth < x) ||
1681             (stuff->srcHeight != 0 &&
1682              winY + stuff->srcY + (int)stuff->srcHeight < y) ||
1683             !PointInWindowIsVisible(source, x, y))
1684             return Success;
1685     }
1686     if (dest)
1687     {
1688         x = dest->drawable.x;
1689         y = dest->drawable.y;
1690         newScreen = dest->drawable.pScreen;
1691     }
1692     else
1693         newScreen = sprite.hotPhys.pScreen;
1694     x += stuff->dstX;
1695     y += stuff->dstY;
1696     if (x < 0)
1697         x = 0;
1698     else if (x >= newScreen->width)
1699         x = newScreen->width - 1;
1700     if (y < 0)
1701         y = 0;
1702     else if (y >= newScreen->height)
1703         y = newScreen->height - 1;
1704
1705     if (newScreen == sprite.hotPhys.pScreen)
1706     {
1707         if (x < sprite.physLimits.x1)
1708             x = sprite.physLimits.x1;
1709         else if (x >= sprite.physLimits.x2)
1710             x = sprite.physLimits.x2 - 1;
1711         if (y < sprite.physLimits.y1)
1712             y = sprite.physLimits.y1;
1713         else if (y >= sprite.physLimits.y2)
1714             y = sprite.physLimits.y2 - 1;
1715 #ifdef SHAPE
1716         if (sprite.hotShape)
1717             ConfineToShape(sprite.hotShape, &x, &y);
1718 #endif
1719         (*newScreen->SetCursorPosition)(newScreen, x, y, TRUE);
1720     }
1721     else if (!PointerConfinedToScreen())
1722     {
1723         NewCurrentScreen(newScreen, x, y);
1724     }
1725     return Success;
1726 }
1727
1728 /* "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
1729         passive grab set on the window to be activated. */
1730
1731 static Bool
1732 #if NeedFunctionPrototypes
1733 CheckPassiveGrabsOnWindow(
1734     WindowPtr pWin,
1735     register DeviceIntPtr device,
1736     register xEvent *xE,
1737     int count)
1738 #else
1739 CheckPassiveGrabsOnWindow(pWin, device, xE, count)
1740     WindowPtr pWin;
1741     register DeviceIntPtr device;
1742     register xEvent *xE;
1743     int count;
1744 #endif
1745 {
1746     register GrabPtr grab = wPassiveGrabs(pWin);
1747     GrabRec tempGrab;
1748     register xEvent *dxE;
1749
1750     if (!grab)
1751         return FALSE;
1752     tempGrab.window = pWin;
1753     tempGrab.device = device;
1754     tempGrab.type = xE->u.u.type;
1755     tempGrab.detail.exact = xE->u.u.detail;
1756     tempGrab.detail.pMask = NULL;
1757     tempGrab.modifiersDetail.pMask = NULL;
1758     for (; grab; grab = grab->next)
1759     {
1760 #ifdef XKB
1761         DeviceIntPtr    gdev;
1762         XkbSrvInfoPtr   xkbi;
1763
1764         gdev= grab->modifierDevice;
1765         xkbi= gdev->key->xkbInfo;
1766 #endif
1767         tempGrab.modifierDevice = grab->modifierDevice;
1768         if (device == grab->modifierDevice &&
1769             (xE->u.u.type == KeyPress
1770 #ifdef XINPUT
1771              || xE->u.u.type == DeviceKeyPress
1772 #endif
1773              ))
1774             tempGrab.modifiersDetail.exact =
1775 #ifdef XKB
1776                 (noXkbExtension?gdev->key->prev_state:xkbi->state.grab_mods);
1777 #else
1778                 grab->modifierDevice->key->prev_state;
1779 #endif
1780         else
1781             tempGrab.modifiersDetail.exact =
1782 #ifdef XKB
1783                 (noXkbExtension ? gdev->key->state : xkbi->state.grab_mods);
1784 #else
1785                 grab->modifierDevice->key->state;
1786 #endif
1787         if (GrabMatchesSecond(&tempGrab, grab) &&
1788             (!grab->confineTo ||
1789              (grab->confineTo->realized &&
1790               REGION_NOTEMPTY( grab->confineTo->drawable.pScreen, 
1791                 &grab->confineTo->borderSize))))
1792         {
1793 #ifdef XCSECURITY
1794             if (!SecurityCheckDeviceAccess(wClient(pWin), device, FALSE))
1795                 return FALSE;
1796 #endif
1797 #ifdef XKB
1798             if (!noXkbExtension) {
1799                 xE->u.keyButtonPointer.state &= 0x1f00;
1800                 xE->u.keyButtonPointer.state |=
1801                                 tempGrab.modifiersDetail.exact&(~0x1f00);
1802             }
1803 #endif
1804             (*device->ActivateGrab)(device, grab, currentTime, TRUE);
1805  
1806             FixUpEventFromWindow(xE, grab->window, None, TRUE);
1807
1808             (void) TryClientEvents(rClient(grab), xE, count,
1809                                    filters[xE->u.u.type],
1810                                    filters[xE->u.u.type],  grab);
1811
1812             if (device->sync.state == FROZEN_NO_EVENT)
1813             {
1814                 if (device->sync.evcount < count)
1815                 {
1816                     Must_have_memory = TRUE; /* XXX */
1817                     device->sync.event = (xEvent *)xrealloc(device->sync.event,
1818                                                             count*
1819                                                             sizeof(xEvent));
1820                     Must_have_memory = FALSE; /* XXX */
1821                 }
1822                 device->sync.evcount = count;
1823                 for (dxE = device->sync.event; --count >= 0; dxE++, xE++)
1824                     *dxE = *xE;
1825                 device->sync.state = FROZEN_WITH_EVENT;
1826             }   
1827             return TRUE;
1828         }
1829     }
1830     return FALSE;
1831 }
1832
1833 /*
1834 "CheckDeviceGrabs" handles both keyboard and pointer events that may cause
1835 a passive grab to be activated.  If the event is a keyboard event, the
1836 ancestors of the focus window are traced down and tried to see if they have
1837 any passive grabs to be activated.  If the focus window itself is reached and
1838 it's descendants contain they pointer, the ancestors of the window that the
1839 pointer is in are then traced down starting at the focus window, otherwise no
1840 grabs are activated.  If the event is a pointer event, the ancestors of the
1841 window that the pointer is in are traced down starting at the root until
1842 CheckPassiveGrabs causes a passive grab to activate or all the windows are
1843 tried. PRH
1844 */
1845
1846 Bool
1847 CheckDeviceGrabs(device, xE, checkFirst, count)
1848     register DeviceIntPtr device;
1849     register xEvent *xE;
1850     int checkFirst;
1851     int count;
1852 {
1853     register int i;
1854     register WindowPtr pWin;
1855     register FocusClassPtr focus = device->focus;
1856
1857     if ((xE->u.u.type == ButtonPress
1858 #ifdef XINPUT
1859          || xE->u.u.type == DeviceButtonPress
1860 #endif
1861          ) && device->button->buttonsDown != 1)
1862         return FALSE;
1863
1864     i = checkFirst;
1865
1866     if (focus)
1867     {
1868         for (; i < focus->traceGood; i++)
1869         {
1870             pWin = focus->trace[i];
1871             if (pWin->optional &&
1872                 CheckPassiveGrabsOnWindow(pWin, device, xE, count))
1873                 return TRUE;
1874         }
1875   
1876         if ((focus->win == NoneWin) ||
1877             (i >= spriteTraceGood) ||
1878             ((i > checkFirst) && (pWin != spriteTrace[i-1])))
1879             return FALSE;
1880     }
1881         
1882     for (; i < spriteTraceGood; i++)
1883     {
1884         pWin = spriteTrace[i];
1885         if (pWin->optional &&
1886             CheckPassiveGrabsOnWindow(pWin, device, xE, count))
1887             return TRUE;
1888     }
1889
1890     return FALSE;
1891 }
1892
1893 void
1894 DeliverFocusedEvent(keybd, xE, window, count)
1895     xEvent *xE;
1896     DeviceIntPtr keybd;
1897     WindowPtr window;
1898     int count;
1899 {
1900     WindowPtr focus = keybd->focus->win;
1901     int mskidx = 0;
1902
1903     if (focus == FollowKeyboardWin)
1904         focus = inputInfo.keyboard->focus->win;
1905     if (!focus)
1906         return;
1907     if (focus == PointerRootWin)
1908     {
1909         DeliverDeviceEvents(window, xE, NullGrab, NullWindow, keybd, count);
1910         return;
1911     }
1912     if ((focus == window) || IsParent(focus, window))
1913     {
1914         if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count))
1915             return;
1916     }
1917     /* just deliver it to the focus window */
1918     FixUpEventFromWindow(xE, focus, None, FALSE);
1919     if (xE->u.u.type & EXTENSION_EVENT_BASE)
1920         mskidx = keybd->id;
1921     (void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type],
1922                                 NullGrab, mskidx);
1923 }
1924
1925 void
1926 DeliverGrabbedEvent(xE, thisDev, deactivateGrab, count)
1927     register xEvent *xE;
1928     register DeviceIntPtr thisDev;
1929     Bool deactivateGrab;
1930     int count;
1931 {
1932     register GrabPtr grab = thisDev->grab;
1933     int deliveries = 0;
1934     register DeviceIntPtr dev;
1935     register xEvent *dxE;
1936
1937     if (grab->ownerEvents)
1938     {
1939         WindowPtr focus;
1940
1941         if (thisDev->focus)
1942         {
1943             focus = thisDev->focus->win;
1944             if (focus == FollowKeyboardWin)
1945                 focus = inputInfo.keyboard->focus->win;
1946         }
1947         else
1948             focus = PointerRootWin;
1949         if (focus == PointerRootWin)
1950             deliveries = DeliverDeviceEvents(sprite.win, xE, grab, NullWindow,
1951                                              thisDev, count);
1952         else if (focus && (focus == sprite.win || IsParent(focus, sprite.win)))
1953             deliveries = DeliverDeviceEvents(sprite.win, xE, grab, focus,
1954                                              thisDev, count);
1955         else if (focus)
1956             deliveries = DeliverDeviceEvents(focus, xE, grab, focus,
1957                                              thisDev, count);
1958     }
1959     if (!deliveries)
1960     {
1961         FixUpEventFromWindow(xE, grab->window, None, TRUE);
1962         deliveries = TryClientEvents(rClient(grab), xE, count,
1963                                      (Mask)grab->eventMask,
1964                                      filters[xE->u.u.type], grab);
1965         if (deliveries && (xE->u.u.type == MotionNotify
1966 #ifdef XINPUT
1967                            || xE->u.u.type == DeviceMotionNotify
1968 #endif
1969                            ))
1970             thisDev->valuator->motionHintWindow = grab->window;
1971     }
1972     if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify
1973 #ifdef XINPUT
1974                                           && xE->u.u.type != DeviceMotionNotify
1975 #endif
1976                                           ))
1977         switch (thisDev->sync.state)
1978         {
1979         case FREEZE_BOTH_NEXT_EVENT:
1980             for (dev = inputInfo.devices; dev; dev = dev->next)
1981             {
1982                 if (dev == thisDev)
1983                     continue;
1984                 FreezeThaw(dev, TRUE);
1985                 if ((dev->sync.state == FREEZE_BOTH_NEXT_EVENT) &&
1986                     (CLIENT_BITS(dev->grab->resource) ==
1987                      CLIENT_BITS(thisDev->grab->resource)))
1988                     dev->sync.state = FROZEN_NO_EVENT;
1989                 else
1990                     dev->sync.other = thisDev->grab;
1991             }
1992             /* fall through */
1993         case FREEZE_NEXT_EVENT:
1994             thisDev->sync.state = FROZEN_WITH_EVENT;
1995             FreezeThaw(thisDev, TRUE);
1996             if (thisDev->sync.evcount < count)
1997             {
1998                 Must_have_memory = TRUE; /* XXX */
1999                 thisDev->sync.event = (xEvent *)xrealloc(thisDev->sync.event,
2000                                                          count*sizeof(xEvent));
2001                 Must_have_memory = FALSE; /* XXX */
2002             }
2003             thisDev->sync.evcount = count;
2004             for (dxE = thisDev->sync.event; --count >= 0; dxE++, xE++)
2005                 *dxE = *xE;
2006             break;
2007         }
2008 }
2009
2010 void
2011 #ifdef XKB
2012 CoreProcessKeyboardEvent (xE, keybd, count)
2013 #else
2014 ProcessKeyboardEvent (xE, keybd, count)
2015 #endif
2016     register xEvent *xE;
2017     register DeviceIntPtr keybd;
2018     int count;
2019 {
2020     int             key, bit;
2021     register BYTE   *kptr;
2022     register int    i;
2023     register CARD8  modifiers;
2024     register CARD16 mask;
2025     GrabPtr         grab = keybd->grab;
2026     Bool            deactivateGrab = FALSE;
2027     register KeyClassPtr keyc = keybd->key;
2028
2029     if (!syncEvents.playingEvents)
2030     {
2031         NoticeTime(xE);
2032         if (DeviceEventCallback)
2033         {
2034             DeviceEventInfoRec eventinfo;
2035             eventinfo.events = xE;
2036             eventinfo.count = count;
2037             CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
2038         }
2039     }
2040     xE->u.keyButtonPointer.state = (keyc->state |
2041                                     inputInfo.pointer->button->state);
2042     xE->u.keyButtonPointer.rootX = sprite.hot.x;
2043     xE->u.keyButtonPointer.rootY = sprite.hot.y;
2044     key = xE->u.u.detail;
2045     kptr = &keyc->down[key >> 3];
2046     bit = 1 << (key & 7);
2047     modifiers = keyc->modifierMap[key];
2048 #ifdef DEBUG
2049     if ((xkbDebugFlags&0x4)&&
2050         ((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) {
2051         ErrorF("CoreProcessKbdEvent: Key %d %s\n",key,
2052                         (xE->u.u.type==KeyPress?"down":"up"));
2053     }
2054 #endif
2055     switch (xE->u.u.type)
2056     {
2057         case KeyPress: 
2058             if (*kptr & bit) /* allow ddx to generate multiple downs */
2059             {   
2060                 if (!modifiers)
2061                 {
2062                     xE->u.u.type = KeyRelease;
2063                     (*keybd->public.processInputProc)(xE, keybd, count);
2064                     xE->u.u.type = KeyPress;
2065                     /* release can have side effects, don't fall through */
2066                     (*keybd->public.processInputProc)(xE, keybd, count);
2067                 }
2068                 return;
2069             }
2070             inputInfo.pointer->valuator->motionHintWindow = NullWindow;
2071             *kptr |= bit;
2072             keyc->prev_state = keyc->state;
2073             for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
2074             {
2075                 if (mask & modifiers)
2076                 {
2077                     /* This key affects modifier "i" */
2078                     keyc->modifierKeyCount[i]++;
2079                     keyc->state |= mask;
2080                     modifiers &= ~mask;
2081                 }
2082             }
2083             if (!grab && CheckDeviceGrabs(keybd, xE, 0, count))
2084             {
2085                 keybd->activatingKey = key;
2086                 return;
2087             }
2088             break;
2089         case KeyRelease: 
2090             if (!(*kptr & bit)) /* guard against duplicates */
2091                 return;
2092             inputInfo.pointer->valuator->motionHintWindow = NullWindow;
2093             *kptr &= ~bit;
2094             keyc->prev_state = keyc->state;
2095             for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
2096             {
2097                 if (mask & modifiers) {
2098                     /* This key affects modifier "i" */
2099                     if (--keyc->modifierKeyCount[i] <= 0) {
2100                         keyc->state &= ~mask;
2101                         keyc->modifierKeyCount[i] = 0;
2102                     }
2103                     modifiers &= ~mask;
2104                 }
2105             }
2106             if (keybd->fromPassiveGrab && (key == keybd->activatingKey))
2107                 deactivateGrab = TRUE;
2108             break;
2109         default: 
2110             FatalError("Impossible keyboard event");
2111     }
2112     if (grab)
2113         DeliverGrabbedEvent(xE, keybd, deactivateGrab, count);
2114     else
2115         DeliverFocusedEvent(keybd, xE, sprite.win, count);
2116     if (deactivateGrab)
2117         (*keybd->DeactivateGrab)(keybd);
2118 }
2119
2120 void
2121 #ifdef XKB
2122 CoreProcessPointerEvent (xE, mouse, count)
2123 #else
2124 ProcessPointerEvent (xE, mouse, count)
2125 #endif
2126     register xEvent             *xE;
2127     register DeviceIntPtr       mouse;
2128     int                         count;
2129 {
2130     register GrabPtr    grab = mouse->grab;
2131     Bool                deactivateGrab = FALSE;
2132     register ButtonClassPtr butc = mouse->button;
2133 #ifdef XKB
2134     XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo;
2135 #endif
2136
2137     if (!syncEvents.playingEvents)
2138         NoticeTime(xE)
2139     xE->u.keyButtonPointer.state = (butc->state | (
2140 #ifdef XKB
2141                         (noXkbExtension ?
2142                                 inputInfo.keyboard->key->state :
2143                                 xkbi->state.grab_mods)
2144 #else
2145                         inputInfo.keyboard->key->state
2146 #endif
2147                                     ));
2148     {
2149         NoticeTime(xE);
2150         if (DeviceEventCallback)
2151         {
2152             DeviceEventInfoRec eventinfo;
2153             /* see comment in EnqueueEvents regarding the next three lines */
2154             if (xE->u.u.type == MotionNotify)
2155                 xE->u.keyButtonPointer.root =
2156                     WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id;
2157             eventinfo.events = xE;
2158             eventinfo.count = count;
2159             CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
2160         }
2161     }
2162     if (xE->u.u.type != MotionNotify)
2163     {
2164         register int  key;
2165         register BYTE *kptr;
2166         int           bit;
2167
2168         xE->u.keyButtonPointer.rootX = sprite.hot.x;
2169         xE->u.keyButtonPointer.rootY = sprite.hot.y;
2170         key = xE->u.u.detail;
2171         kptr = &butc->down[key >> 3];
2172         bit = 1 << (key & 7);
2173         switch (xE->u.u.type)
2174         {
2175         case ButtonPress: 
2176             mouse->valuator->motionHintWindow = NullWindow;
2177             butc->buttonsDown++;
2178             butc->motionMask = ButtonMotionMask;
2179             *kptr |= bit;
2180             xE->u.u.detail = butc->map[key];
2181             if (xE->u.u.detail == 0)
2182                 return;
2183             if (xE->u.u.detail <= 5)
2184                 butc->state |= (Button1Mask >> 1) << xE->u.u.detail;
2185             filters[MotionNotify] = Motion_Filter(butc);
2186             if (!grab)
2187                 if (CheckDeviceGrabs(mouse, xE, 0, count))
2188                     return;
2189             break;
2190         case ButtonRelease: 
2191             mouse->valuator->motionHintWindow = NullWindow;
2192             if (!--butc->buttonsDown)
2193                 butc->motionMask = 0;
2194             *kptr &= ~bit;
2195             xE->u.u.detail = butc->map[key];
2196             if (xE->u.u.detail == 0)
2197                 return;
2198             if (xE->u.u.detail <= 5)
2199                 butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
2200             filters[MotionNotify] = Motion_Filter(butc);
2201             if (!butc->state && mouse->fromPassiveGrab)
2202                 deactivateGrab = TRUE;
2203             break;
2204         default: 
2205             FatalError("bogus pointer event from ddx");
2206         }
2207     }
2208     else if (!CheckMotion(xE))
2209         return;
2210     if (grab)
2211         DeliverGrabbedEvent(xE, mouse, deactivateGrab, count);
2212     else
2213         DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow,
2214                             mouse, count);
2215     if (deactivateGrab)
2216         (*mouse->DeactivateGrab)(mouse);
2217 }
2218
2219 #define AtMostOneClient \
2220         (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
2221
2222 void
2223 RecalculateDeliverableEvents(pWin)
2224     register WindowPtr pWin;
2225 {
2226     register OtherClients *others;
2227     register WindowPtr pChild;
2228
2229     pChild = pWin;
2230     while (1)
2231     {
2232         if (pChild->optional)
2233         {
2234             pChild->optional->otherEventMasks = 0;
2235             for (others = wOtherClients(pChild); others; others = others->next)
2236             {
2237                 pChild->optional->otherEventMasks |= others->mask;
2238             }
2239         }
2240         pChild->deliverableEvents = pChild->eventMask|
2241                                     wOtherEventMasks(pChild);
2242         if (pChild->parent)
2243             pChild->deliverableEvents |=
2244                 (pChild->parent->deliverableEvents &
2245                  ~wDontPropagateMask(pChild) & PropagateMask);
2246         if (pChild->firstChild)
2247         {
2248             pChild = pChild->firstChild;
2249             continue;
2250         }
2251         while (!pChild->nextSib && (pChild != pWin))
2252             pChild = pChild->parent;
2253         if (pChild == pWin)
2254             break;
2255         pChild = pChild->nextSib;
2256     }
2257 }
2258
2259 int
2260 OtherClientGone(value, id)
2261     pointer value; /* must conform to DeleteType */
2262     XID   id;
2263 {
2264     register OtherClientsPtr other, prev;
2265     register WindowPtr pWin = (WindowPtr)value;
2266
2267     prev = 0;
2268     for (other = wOtherClients(pWin); other; other = other->next)
2269     {
2270         if (other->resource == id)
2271         {
2272             if (prev)
2273                 prev->next = other->next;
2274             else
2275             {
2276                 if (!(pWin->optional->otherClients = other->next))
2277                     CheckWindowOptionalNeed (pWin);
2278             }
2279             xfree(other);
2280             RecalculateDeliverableEvents(pWin);
2281             return(Success);
2282         }
2283         prev = other;
2284     }
2285     FatalError("client not on event list");
2286     /*NOTREACHED*/
2287     return -1; /* make compiler happy */
2288 }
2289
2290 int
2291 EventSelectForWindow(pWin, client, mask)
2292     register WindowPtr pWin;
2293     register ClientPtr client;
2294     Mask mask;
2295 {
2296     Mask check;
2297     OtherClients * others;
2298
2299     if (mask & ~AllEventMasks)
2300     {
2301         client->errorValue = mask;
2302         return BadValue;
2303     }
2304     check = (mask & AtMostOneClient);
2305     if (check & (pWin->eventMask|wOtherEventMasks(pWin)))
2306     {                                  /* It is illegal for two different
2307                                           clients to select on any of the
2308                                           events for AtMostOneClient. However,
2309                                           it is OK, for some client to
2310                                           continue selecting on one of those
2311                                           events.  */
2312         if ((wClient(pWin) != client) && (check & pWin->eventMask))
2313             return BadAccess;
2314         for (others = wOtherClients (pWin); others; others = others->next)
2315         {
2316             if (!SameClient(others, client) && (check & others->mask))
2317                 return BadAccess;
2318         }
2319     }
2320     if (wClient (pWin) == client)
2321     {
2322         check = pWin->eventMask;
2323 #if SGIMISC
2324         pWin->eventMask =
2325             (mask & ~SGIMiscSpecialDestroyMask) | (pWin->eventMask & SGIMiscSpecialDestroyMask);
2326 #else
2327         pWin->eventMask = mask;
2328 #endif
2329     }
2330     else
2331     {
2332         for (others = wOtherClients (pWin); others; others = others->next)
2333         {
2334             if (SameClient(others, client))
2335             {
2336                 check = others->mask;
2337 #if SGIMISC
2338                 mask = (mask & ~SGIMiscSpecialDestroyMask) | (others->mask & SGIMiscSpecialDestroyMask);
2339 #endif
2340                 if (mask == 0)
2341                 {
2342                     FreeResource(others->resource, RT_NONE);
2343                     return Success;
2344                 }
2345                 else
2346                     others->mask = mask;
2347                 goto maskSet;
2348             }
2349         }
2350         check = 0;
2351         if (!pWin->optional && !MakeWindowOptional (pWin))
2352             return BadAlloc;
2353         others = (OtherClients *) xalloc(sizeof(OtherClients));
2354         if (!others)
2355             return BadAlloc;
2356         others->mask = mask;
2357         others->resource = FakeClientID(client->index);
2358         others->next = pWin->optional->otherClients;
2359         pWin->optional->otherClients = others;
2360         if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin))
2361             return BadAlloc;
2362     }
2363 maskSet: 
2364     if ((inputInfo.pointer->valuator->motionHintWindow == pWin) &&
2365         (mask & PointerMotionHintMask) &&
2366         !(check & PointerMotionHintMask) &&
2367         !inputInfo.pointer->grab)
2368         inputInfo.pointer->valuator->motionHintWindow = NullWindow;
2369     RecalculateDeliverableEvents(pWin);
2370     return Success;
2371 }
2372
2373 /*ARGSUSED*/
2374 int
2375 EventSuppressForWindow(pWin, client, mask, checkOptional)
2376     register WindowPtr pWin;
2377     register ClientPtr client;
2378     Mask mask;
2379     Bool *checkOptional;
2380 {
2381     register int i, free;
2382
2383     if ((mask & ~PropagateMask) && !permitOldBugs)
2384     {
2385         client->errorValue = mask;
2386         return BadValue;
2387     }
2388     if (pWin->dontPropagate)
2389         DontPropagateRefCnts[pWin->dontPropagate]--;
2390     if (!mask)
2391         i = 0;
2392     else
2393     {
2394         for (i = DNPMCOUNT, free = 0; --i > 0; )
2395         {
2396             if (!DontPropagateRefCnts[i])
2397                 free = i;
2398             else if (mask == DontPropagateMasks[i])
2399                 break;
2400         }
2401         if (!i && free)
2402         {
2403             i = free;
2404             DontPropagateMasks[i] = mask;
2405         }
2406     }
2407     if (i || !mask)
2408     {
2409         pWin->dontPropagate = i;
2410         if (i)
2411             DontPropagateRefCnts[i]++;
2412         if (pWin->optional)
2413         {
2414             pWin->optional->dontPropagateMask = mask;
2415             *checkOptional = TRUE;
2416         }
2417     }
2418     else
2419     {
2420         if (!pWin->optional && !MakeWindowOptional (pWin))
2421         {
2422             if (pWin->dontPropagate)
2423                 DontPropagateRefCnts[pWin->dontPropagate]++;
2424             return BadAlloc;
2425         }
2426         pWin->dontPropagate = 0;
2427         pWin->optional->dontPropagateMask = mask;
2428     }
2429     RecalculateDeliverableEvents(pWin);
2430     return Success;
2431 }
2432
2433 static WindowPtr 
2434 #if NeedFunctionPrototypes
2435 CommonAncestor(
2436     register WindowPtr a,
2437     register WindowPtr b)
2438 #else
2439 CommonAncestor(a, b)
2440     register WindowPtr a, b;
2441 #endif
2442 {
2443     for (b = b->parent; b; b = b->parent)
2444         if (IsParent(b, a)) return b;
2445     return NullWindow;
2446 }
2447
2448 static void
2449 #if NeedFunctionPrototypes
2450 EnterLeaveEvent(
2451     int type,
2452     int mode,
2453     int detail,
2454     register WindowPtr pWin,
2455     Window child)
2456 #else
2457 EnterLeaveEvent(type, mode, detail, pWin, child)
2458     int type, mode, detail;
2459     register WindowPtr pWin;
2460     Window child;
2461 #endif
2462 {
2463     xEvent              event;
2464     register DeviceIntPtr keybd = inputInfo.keyboard;
2465     WindowPtr           focus;
2466     register DeviceIntPtr mouse = inputInfo.pointer;
2467     register GrabPtr    grab = mouse->grab;
2468     Mask                mask;
2469
2470     if ((pWin == mouse->valuator->motionHintWindow) &&
2471         (detail != NotifyInferior))
2472         mouse->valuator->motionHintWindow = NullWindow;
2473     if (grab)
2474     {
2475         mask = (pWin == grab->window) ? grab->eventMask : 0;
2476         if (grab->ownerEvents)
2477             mask |= EventMaskForClient(pWin, rClient(grab));
2478     }
2479     else
2480     {
2481         mask = pWin->eventMask | wOtherEventMasks(pWin);
2482     }
2483     if (mask & filters[type])
2484     {
2485         event.u.u.type = type;
2486         event.u.u.detail = detail;
2487         event.u.enterLeave.time = currentTime.milliseconds;
2488         event.u.enterLeave.rootX = sprite.hot.x;
2489         event.u.enterLeave.rootY = sprite.hot.y;
2490         /* Counts on the same initial structure of crossing & button events! */
2491         FixUpEventFromWindow(&event, pWin, None, FALSE);
2492         /* Enter/Leave events always set child */
2493         event.u.enterLeave.child = child;
2494         event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
2495                                             ELFlagSameScreen : 0;
2496 #ifdef XKB
2497         if (!noXkbExtension) {
2498             event.u.enterLeave.state = mouse->button->state & 0x1f00;
2499             event.u.enterLeave.state |= 
2500                         XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
2501         } else
2502 #endif
2503         event.u.enterLeave.state = keybd->key->state | mouse->button->state;
2504         event.u.enterLeave.mode = mode;
2505         focus = keybd->focus->win;
2506         if ((focus != NoneWin) &&
2507             ((pWin == focus) || (focus == PointerRootWin) ||
2508              IsParent(focus, pWin)))
2509             event.u.enterLeave.flags |= ELFlagFocus;
2510         if (grab)
2511             (void)TryClientEvents(rClient(grab), &event, 1, mask,
2512                                   filters[type], grab);
2513         else
2514             (void)DeliverEventsToWindow(pWin, &event, 1, filters[type],
2515                                         NullGrab, 0);
2516     }
2517     if ((type == EnterNotify) && (mask & KeymapStateMask))
2518     {
2519         xKeymapEvent ke;
2520
2521 #ifdef XCSECURITY
2522         ClientPtr client = grab ? rClient(grab)
2523                                 : clients[CLIENT_ID(pWin->drawable.id)];
2524         if (!SecurityCheckDeviceAccess(client, keybd, FALSE))
2525         {
2526             bzero((char *)&ke.map[0], 31);
2527         }
2528         else
2529 #endif
2530         memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31);
2531         ke.type = KeymapNotify;
2532         if (grab)
2533             (void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask,
2534                                   KeymapStateMask, grab);
2535         else
2536             (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1,
2537                                         KeymapStateMask, NullGrab, 0);
2538     }
2539 }
2540
2541 static void
2542 #if NeedFunctionPrototypes
2543 EnterNotifies(WindowPtr ancestor, WindowPtr child, int mode, int detail)
2544 #else
2545 EnterNotifies(ancestor, child, mode, detail)
2546     WindowPtr ancestor, child;
2547     int mode, detail;
2548 #endif
2549 {
2550     WindowPtr   parent = child->parent;
2551
2552     if (ancestor == parent)
2553         return;
2554     EnterNotifies(ancestor, parent, mode, detail);
2555     EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id);
2556 }
2557
2558 static void
2559 #if NeedFunctionPrototypes
2560 LeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail)
2561 #else
2562 LeaveNotifies(child, ancestor, mode, detail)
2563     WindowPtr child, ancestor;
2564     int detail, mode;
2565 #endif
2566 {
2567     register WindowPtr  pWin;
2568
2569     if (ancestor == child)
2570         return;
2571     for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent)
2572     {
2573         EnterLeaveEvent(LeaveNotify, mode, detail, pWin, child->drawable.id);
2574         child = pWin;
2575     }
2576 }
2577
2578 static void
2579 #if NeedFunctionPrototypes
2580 DoEnterLeaveEvents(WindowPtr fromWin, WindowPtr toWin, int mode)
2581 #else
2582 DoEnterLeaveEvents(fromWin, toWin, mode)
2583     WindowPtr fromWin, toWin;
2584     int mode;
2585 #endif
2586 {
2587     if (fromWin == toWin)
2588         return;
2589     if (IsParent(fromWin, toWin))
2590     {
2591         EnterLeaveEvent(LeaveNotify, mode, NotifyInferior, fromWin, None);
2592         EnterNotifies(fromWin, toWin, mode, NotifyVirtual);
2593         EnterLeaveEvent(EnterNotify, mode, NotifyAncestor, toWin, None);
2594     }
2595     else if (IsParent(toWin, fromWin))
2596     {
2597         EnterLeaveEvent(LeaveNotify, mode, NotifyAncestor, fromWin, None);
2598         LeaveNotifies(fromWin, toWin, mode, NotifyVirtual);
2599         EnterLeaveEvent(EnterNotify, mode, NotifyInferior, toWin, None);
2600     }
2601     else
2602     { /* neither fromWin nor toWin is descendent of the other */
2603         WindowPtr common = CommonAncestor(toWin, fromWin);
2604         /* common == NullWindow ==> different screens */
2605         EnterLeaveEvent(LeaveNotify, mode, NotifyNonlinear, fromWin, None);
2606         LeaveNotifies(fromWin, common, mode, NotifyNonlinearVirtual);
2607         EnterNotifies(common, toWin, mode, NotifyNonlinearVirtual);
2608         EnterLeaveEvent(EnterNotify, mode, NotifyNonlinear, toWin, None);
2609     }
2610 }
2611
2612 static void
2613 #if NeedFunctionPrototypes
2614 FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, register WindowPtr pWin)
2615 #else
2616 FocusEvent(dev, type, mode, detail, pWin)
2617     DeviceIntPtr dev;
2618     int type, mode, detail;
2619     register WindowPtr pWin;
2620 #endif
2621 {
2622     xEvent event;
2623
2624 #ifdef XINPUT
2625     if (dev != inputInfo.keyboard)
2626     {
2627         DeviceFocusEvent(dev, type, mode, detail, pWin);
2628         return;
2629     }
2630 #endif
2631     event.u.focus.mode = mode;
2632     event.u.u.type = type;
2633     event.u.u.detail = detail;
2634     event.u.focus.window = pWin->drawable.id;
2635     (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], NullGrab,
2636                                 0);
2637     if ((type == FocusIn) &&
2638         ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
2639     {
2640         xKeymapEvent ke;
2641 #ifdef XCSECURITY
2642         ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)];
2643         if (!SecurityCheckDeviceAccess(client, dev, FALSE))
2644         {
2645             bzero((char *)&ke.map[0], 31);
2646         }
2647         else
2648 #endif
2649         memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
2650         ke.type = KeymapNotify;
2651         (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1,
2652                                     KeymapStateMask, NullGrab, 0);
2653     }
2654 }
2655
2656  /*
2657   * recursive because it is easier
2658   * no-op if child not descended from ancestor
2659   */
2660 static Bool
2661 #if NeedFunctionPrototypes
2662 FocusInEvents(
2663     DeviceIntPtr dev,
2664     WindowPtr ancestor, WindowPtr child, WindowPtr skipChild,
2665     int mode, int detail,
2666     Bool doAncestor)
2667 #else
2668 FocusInEvents(dev, ancestor, child, skipChild, mode, detail, doAncestor)
2669     DeviceIntPtr dev;
2670     WindowPtr ancestor, child, skipChild;
2671     int mode, detail;
2672     Bool doAncestor;
2673 #endif
2674 {
2675     if (child == NullWindow)
2676         return ancestor == NullWindow;
2677     if (ancestor == child)
2678     {
2679         if (doAncestor)
2680             FocusEvent(dev, FocusIn, mode, detail, child);
2681         return TRUE;
2682     }
2683     if (FocusInEvents(dev, ancestor, child->parent, skipChild, mode, detail,
2684                       doAncestor))
2685     {
2686         if (child != skipChild)
2687             FocusEvent(dev, FocusIn, mode, detail, child);
2688         return TRUE;
2689     }
2690     return FALSE;
2691 }
2692
2693 /* dies horribly if ancestor is not an ancestor of child */
2694 static void
2695 #if NeedFunctionPrototypes
2696 FocusOutEvents(
2697     DeviceIntPtr dev,
2698     WindowPtr child, WindowPtr ancestor,
2699     int mode, int detail,
2700     Bool doAncestor)
2701 #else
2702 FocusOutEvents(dev, child, ancestor, mode, detail, doAncestor)
2703     DeviceIntPtr dev;
2704     WindowPtr child, ancestor;
2705     int mode;
2706     int detail;
2707     Bool doAncestor;
2708 #endif
2709 {
2710     register WindowPtr  pWin;
2711
2712     for (pWin = child; pWin != ancestor; pWin = pWin->parent)
2713         FocusEvent(dev, FocusOut, mode, detail, pWin);
2714     if (doAncestor)
2715         FocusEvent(dev, FocusOut, mode, detail, ancestor);
2716 }
2717
2718 void
2719 DoFocusEvents(dev, fromWin, toWin, mode)
2720     DeviceIntPtr dev;
2721     WindowPtr fromWin, toWin;
2722     int mode;
2723 {
2724     int     out, in;                   /* for holding details for to/from
2725                                           PointerRoot/None */
2726     int     i;
2727
2728     if (fromWin == toWin)
2729         return;
2730     out = (fromWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot;
2731     in = (toWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot;
2732  /* wrong values if neither, but then not referenced */
2733
2734     if ((toWin == NullWindow) || (toWin == PointerRootWin))
2735     {
2736         if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
2737         {
2738             if (fromWin == PointerRootWin)
2739                 FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
2740                                TRUE);
2741             /* Notify all the roots */
2742             for (i=0; i<screenInfo.numScreens; i++)
2743                 FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
2744         }
2745         else
2746         {
2747             if (IsParent(fromWin, sprite.win))
2748               FocusOutEvents(dev, sprite.win, fromWin, mode, NotifyPointer,
2749                              FALSE);
2750             FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
2751             /* next call catches the root too, if the screen changed */
2752             FocusOutEvents(dev, fromWin->parent, NullWindow, mode,
2753                            NotifyNonlinearVirtual, FALSE);
2754         }
2755         /* Notify all the roots */
2756         for (i=0; i<screenInfo.numScreens; i++)
2757             FocusEvent(dev, FocusIn, mode, in, WindowTable[i]);
2758         if (toWin == PointerRootWin)
2759             (void)FocusInEvents(dev, ROOT, sprite.win, NullWindow, mode,
2760                                 NotifyPointer, TRUE);
2761     }
2762     else
2763     {
2764         if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
2765         {
2766             if (fromWin == PointerRootWin)
2767                 FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
2768                                TRUE);
2769             for (i=0; i<screenInfo.numScreens; i++)
2770               FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
2771             if (toWin->parent != NullWindow)
2772               (void)FocusInEvents(dev, ROOT, toWin, toWin, mode,
2773                                   NotifyNonlinearVirtual, TRUE);
2774             FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
2775             if (IsParent(toWin, sprite.win))
2776                (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode,
2777                                    NotifyPointer, FALSE);
2778         }
2779         else
2780         {
2781             if (IsParent(toWin, fromWin))
2782             {
2783                 FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin);
2784                 FocusOutEvents(dev, fromWin->parent, toWin, mode,
2785                                NotifyVirtual, FALSE);
2786                 FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin);
2787                 if ((IsParent(toWin, sprite.win)) &&
2788                         (sprite.win != fromWin) &&
2789                         (!IsParent(fromWin, sprite.win)) &&
2790                         (!IsParent(sprite.win, fromWin)))
2791                     (void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
2792                                         mode, NotifyPointer, FALSE);
2793             }
2794             else
2795                 if (IsParent(fromWin, toWin))
2796                 {
2797                     if ((IsParent(fromWin, sprite.win)) &&
2798                             (sprite.win != fromWin) &&
2799                             (!IsParent(toWin, sprite.win)) &&
2800                             (!IsParent(sprite.win, toWin)))
2801                         FocusOutEvents(dev, sprite.win, fromWin, mode,
2802                                        NotifyPointer, FALSE);
2803                     FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin);
2804                     (void)FocusInEvents(dev, fromWin, toWin, toWin, mode,
2805                                         NotifyVirtual, FALSE);
2806                     FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin);
2807                 }
2808                 else
2809                 {
2810                 /* neither fromWin or toWin is child of other */
2811                     WindowPtr common = CommonAncestor(toWin, fromWin);
2812                 /* common == NullWindow ==> different screens */
2813                     if (IsParent(fromWin, sprite.win))
2814                         FocusOutEvents(dev, sprite.win, fromWin, mode,
2815                                        NotifyPointer, FALSE);
2816                     FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
2817                     if (fromWin->parent != NullWindow)
2818                       FocusOutEvents(dev, fromWin->parent, common, mode,
2819                                      NotifyNonlinearVirtual, FALSE);
2820                     if (toWin->parent != NullWindow)
2821                       (void)FocusInEvents(dev, common, toWin, toWin, mode,
2822                                           NotifyNonlinearVirtual, FALSE);
2823                     FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
2824                     if (IsParent(toWin, sprite.win))
2825                         (void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
2826                                             mode, NotifyPointer, FALSE);
2827                 }
2828         }
2829     }
2830 }
2831
2832 int
2833 #if NeedFunctionPrototypes
2834 SetInputFocus(
2835     ClientPtr client,
2836     DeviceIntPtr dev,
2837     Window focusID,
2838     CARD8 revertTo,
2839     Time ctime,
2840     Bool followOK)
2841 #else
2842 SetInputFocus(client, dev, focusID, revertTo, ctime, followOK)
2843     ClientPtr client;
2844     DeviceIntPtr dev;
2845     Window focusID;
2846     CARD8 revertTo;
2847     Time ctime;
2848     Bool followOK;
2849 #endif
2850 {
2851     register FocusClassPtr focus;
2852     register WindowPtr focusWin;
2853     int mode;
2854     TimeStamp time;
2855
2856     UpdateCurrentTime();
2857     if ((revertTo != RevertToParent) &&
2858         (revertTo != RevertToPointerRoot) &&
2859         (revertTo != RevertToNone) &&
2860         ((revertTo != RevertToFollowKeyboard) || !followOK))
2861     {
2862         client->errorValue = revertTo;
2863         return BadValue;
2864     }
2865     time = ClientTimeToServerTime(ctime);
2866     if ((focusID == None) || (focusID == PointerRoot))
2867         focusWin = (WindowPtr)focusID;
2868     else if ((focusID == FollowKeyboard) && followOK)
2869         focusWin = inputInfo.keyboard->focus->win;
2870     else if (!(focusWin = SecurityLookupWindow(focusID, client,
2871                                                SecurityReadAccess)))
2872         return BadWindow;
2873     else
2874     {
2875         /* It is a match error to try to set the input focus to an 
2876         unviewable window. */
2877
2878         if(!focusWin->realized)
2879             return(BadMatch);
2880     }
2881     focus = dev->focus;
2882     if ((CompareTimeStamps(time, currentTime) == LATER) ||
2883         (CompareTimeStamps(time, focus->time) == EARLIER))
2884         return Success;
2885     mode = (dev->grab) ? NotifyWhileGrabbed : NotifyNormal;
2886     if (focus->win == FollowKeyboardWin)
2887         DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode);
2888     else
2889         DoFocusEvents(dev, focus->win, focusWin, mode);
2890     focus->time = time;
2891     focus->revert = revertTo;
2892     if (focusID == FollowKeyboard)
2893         focus->win = FollowKeyboardWin;
2894     else
2895         focus->win = focusWin;
2896     if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
2897         focus->traceGood = 0;
2898     else
2899     {
2900         int depth = 0;
2901         register WindowPtr pWin;
2902
2903         for (pWin = focusWin; pWin; pWin = pWin->parent) depth++;
2904         if (depth > focus->traceSize)
2905         {
2906             focus->traceSize = depth+1;
2907             Must_have_memory = TRUE; /* XXX */
2908             focus->trace = (WindowPtr *)xrealloc(focus->trace,
2909                                                  focus->traceSize *
2910                                                  sizeof(WindowPtr));
2911             Must_have_memory = FALSE; /* XXX */
2912         }
2913         focus->traceGood = depth;
2914         for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) 
2915             focus->trace[depth] = pWin;
2916     }
2917     return Success;
2918 }
2919
2920 int
2921 ProcSetInputFocus(client)
2922     ClientPtr client;
2923 {
2924     REQUEST(xSetInputFocusReq);
2925
2926     REQUEST_SIZE_MATCH(xSetInputFocusReq);
2927 #ifdef XCSECURITY
2928     if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE))
2929         return Success;
2930 #endif
2931     return SetInputFocus(client, inputInfo.keyboard, stuff->focus,
2932                          stuff->revertTo, stuff->time, FALSE);
2933 }
2934
2935 int
2936 ProcGetInputFocus(client)
2937     ClientPtr client;
2938 {
2939     xGetInputFocusReply rep;
2940     FocusClassPtr focus = inputInfo.keyboard->focus;
2941
2942     REQUEST_SIZE_MATCH(xReq);
2943     rep.type = X_Reply;
2944     rep.length = 0;
2945     rep.sequenceNumber = client->sequence;
2946     if (focus->win == NoneWin)
2947         rep.focus = None;
2948     else if (focus->win == PointerRootWin)
2949         rep.focus = PointerRoot;
2950     else rep.focus = focus->win->drawable.id;
2951     rep.revertTo = focus->revert;
2952     WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
2953     return Success;
2954 }
2955
2956 int
2957 ProcGrabPointer(client)
2958     ClientPtr client;
2959 {
2960     xGrabPointerReply rep;
2961     DeviceIntPtr device = inputInfo.pointer;
2962     GrabPtr grab;
2963     WindowPtr pWin, confineTo;
2964     CursorPtr cursor, oldCursor;
2965     REQUEST(xGrabPointerReq);
2966     TimeStamp time;
2967
2968     REQUEST_SIZE_MATCH(xGrabPointerReq);
2969     UpdateCurrentTime();
2970     if ((stuff->pointerMode != GrabModeSync) &&
2971         (stuff->pointerMode != GrabModeAsync))
2972     {
2973         client->errorValue = stuff->pointerMode;
2974         return BadValue;
2975     }
2976     if ((stuff->keyboardMode != GrabModeSync) &&
2977         (stuff->keyboardMode != GrabModeAsync))
2978     {
2979         client->errorValue = stuff->keyboardMode;
2980         return BadValue;
2981     }
2982     if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
2983     {
2984         client->errorValue = stuff->ownerEvents;
2985         return BadValue;
2986     }
2987     if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs)
2988     {
2989         client->errorValue = stuff->eventMask;
2990         return BadValue;
2991     }
2992     pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess);
2993     if (!pWin)
2994         return BadWindow;
2995     if (stuff->confineTo == None)
2996         confineTo = NullWindow;
2997     else
2998     {
2999         confineTo = SecurityLookupWindow(stuff->confineTo, client,
3000                                          SecurityReadAccess);
3001         if (!confineTo)
3002             return BadWindow;
3003     }
3004     if (stuff->cursor == None)
3005         cursor = NullCursor;
3006     else
3007     {
3008         cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
3009                                                 RT_CURSOR, SecurityReadAccess);
3010         if (!cursor)
3011         {
3012             client->errorValue = stuff->cursor;
3013             return BadCursor;
3014         }
3015     }
3016         /* at this point, some sort of reply is guaranteed. */
3017     time = ClientTimeToServerTime(stuff->time);
3018     rep.type = X_Reply;
3019     rep.sequenceNumber = client->sequence;
3020     rep.length = 0;
3021     grab = device->grab;
3022     if ((grab) && !SameClient(grab, client))
3023         rep.status = AlreadyGrabbed;
3024     else if ((!pWin->realized) ||
3025              (confineTo &&
3026                 !(confineTo->realized &&
3027                   REGION_NOTEMPTY( confineTo->drawable.pScreen, 
3028                         &confineTo->borderSize))))
3029         rep.status = GrabNotViewable;
3030     else if (device->sync.frozen &&
3031              device->sync.other && !SameClient(device->sync.other, client))
3032         rep.status = GrabFrozen;
3033     else if ((CompareTimeStamps(time, currentTime) == LATER) ||
3034              (CompareTimeStamps(time, device->grabTime) == EARLIER))
3035         rep.status = GrabInvalidTime;
3036     else
3037     {
3038         GrabRec tempGrab;
3039
3040         oldCursor = NullCursor;
3041         if (grab)
3042         {
3043             if (grab->confineTo && !confineTo)
3044                 ConfineCursorToWindow(ROOT, FALSE, FALSE);
3045             oldCursor = grab->cursor;
3046         }
3047         tempGrab.cursor = cursor;
3048         tempGrab.resource = client->clientAsMask;
3049         tempGrab.ownerEvents = stuff->ownerEvents;
3050         tempGrab.eventMask = stuff->eventMask;
3051         tempGrab.confineTo = confineTo;
3052         tempGrab.window = pWin;
3053         tempGrab.keyboardMode = stuff->keyboardMode;
3054         tempGrab.pointerMode = stuff->pointerMode;
3055         tempGrab.device = device;
3056         (*device->ActivateGrab)(device, &tempGrab, time, FALSE);
3057         if (oldCursor)
3058             FreeCursor (oldCursor, (Cursor)0);
3059         rep.status = GrabSuccess;
3060     }
3061     WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
3062     return Success;
3063 }
3064
3065 int
3066 ProcChangeActivePointerGrab(client)
3067     ClientPtr client;
3068 {
3069     DeviceIntPtr device = inputInfo.pointer;
3070     register GrabPtr grab = device->grab;
3071     CursorPtr newCursor, oldCursor;
3072     REQUEST(xChangeActivePointerGrabReq);
3073     TimeStamp time;
3074
3075     REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
3076     if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs)
3077     {
3078         client->errorValue = stuff->eventMask;
3079         return BadValue;
3080     }
3081     if (stuff->cursor == None)
3082         newCursor = NullCursor;
3083     else
3084     {
3085         newCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
3086                                                 RT_CURSOR, SecurityReadAccess);
3087         if (!newCursor)
3088         {
3089             client->errorValue = stuff->cursor;
3090             return BadCursor;
3091         }
3092     }
3093     if (!grab)
3094         return Success;
3095     if (!SameClient(grab, client))
3096         return Success;
3097     time = ClientTimeToServerTime(stuff->time);
3098     if ((CompareTimeStamps(time, currentTime) == LATER) ||
3099              (CompareTimeStamps(time, device->grabTime) == EARLIER))
3100         return Success;
3101     oldCursor = grab->cursor;
3102     grab->cursor = newCursor;
3103     if (newCursor)
3104         newCursor->refcnt++;
3105     PostNewCursor();
3106     if (oldCursor)
3107         FreeCursor(oldCursor, (Cursor)0);
3108     grab->eventMask = stuff->eventMask;
3109     return Success;
3110 }
3111
3112 int
3113 ProcUngrabPointer(client)
3114     ClientPtr client;
3115 {
3116     DeviceIntPtr device = inputInfo.pointer;
3117     GrabPtr grab;
3118     TimeStamp time;
3119     REQUEST(xResourceReq);
3120
3121     REQUEST_SIZE_MATCH(xResourceReq);
3122     UpdateCurrentTime();
3123     grab = device->grab;
3124     time = ClientTimeToServerTime(stuff->id);
3125     if ((CompareTimeStamps(time, currentTime) != LATER) &&
3126             (CompareTimeStamps(time, device->grabTime) != EARLIER) &&
3127             (grab) && SameClient(grab, client))
3128         (*device->DeactivateGrab)(device);
3129     return Success;
3130 }
3131
3132 int
3133 GrabDevice(client, dev, this_mode, other_mode, grabWindow, ownerEvents, ctime,
3134            mask, status)
3135     register ClientPtr client;
3136     register DeviceIntPtr dev;
3137     unsigned this_mode;
3138     unsigned other_mode;
3139     Window grabWindow;
3140     unsigned ownerEvents;
3141     Time ctime;
3142     Mask mask;
3143     CARD8 *status;
3144 {
3145     register WindowPtr pWin;
3146     register GrabPtr grab;
3147     TimeStamp time;
3148
3149     UpdateCurrentTime();
3150     if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync))
3151     {
3152         client->errorValue = this_mode;
3153         return BadValue;
3154     }
3155     if ((other_mode != GrabModeSync) && (other_mode != GrabModeAsync))
3156     {
3157         client->errorValue = other_mode;
3158         return BadValue;
3159     }
3160     if ((ownerEvents != xFalse) && (ownerEvents != xTrue))
3161     {
3162         client->errorValue = ownerEvents;
3163         return BadValue;
3164     }
3165     pWin = SecurityLookupWindow(grabWindow, client, SecurityReadAccess);
3166     if (!pWin)
3167         return BadWindow;
3168     time = ClientTimeToServerTime(ctime);
3169     grab = dev->grab;
3170     if (grab && !SameClient(grab, client))
3171         *status = AlreadyGrabbed;
3172     else if (!pWin->realized)
3173         *status = GrabNotViewable;
3174     else if ((CompareTimeStamps(time, currentTime) == LATER) ||
3175              (CompareTimeStamps(time, dev->grabTime) == EARLIER))
3176         *status = GrabInvalidTime;
3177     else if (dev->sync.frozen &&
3178              dev->sync.other && !SameClient(dev->sync.other, client))
3179         *status = GrabFrozen;
3180     else
3181     {
3182         GrabRec tempGrab;
3183
3184         tempGrab.window = pWin;
3185         tempGrab.resource = client->clientAsMask;
3186         tempGrab.ownerEvents = ownerEvents;
3187         tempGrab.keyboardMode = this_mode;
3188         tempGrab.pointerMode = other_mode;
3189         tempGrab.eventMask = mask;
3190         tempGrab.device = dev;
3191         (*dev->ActivateGrab)(dev, &tempGrab, time, FALSE);
3192         *status = GrabSuccess;
3193     }
3194     return Success;
3195 }
3196
3197 int
3198 ProcGrabKeyboard(client)
3199     ClientPtr client;
3200 {
3201     xGrabKeyboardReply rep;
3202     REQUEST(xGrabKeyboardReq);
3203     int result;
3204
3205     REQUEST_SIZE_MATCH(xGrabKeyboardReq);
3206 #ifdef XCSECURITY
3207     if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE))
3208     {
3209         result = Success;
3210         rep.status = AlreadyGrabbed;
3211     }
3212     else
3213 #endif
3214     result = GrabDevice(client, inputInfo.keyboard, stuff->keyboardMode,
3215                         stuff->pointerMode, stuff->grabWindow,
3216                         stuff->ownerEvents, stuff->time,
3217                         KeyPressMask | KeyReleaseMask, &rep.status);
3218     if (result != Success)
3219         return result;
3220     rep.type = X_Reply;
3221     rep.sequenceNumber = client->sequence;
3222     rep.length = 0;
3223     WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
3224     return Success;
3225 }
3226
3227 int
3228 ProcUngrabKeyboard(client)
3229     ClientPtr client;
3230 {
3231     DeviceIntPtr device = inputInfo.keyboard;
3232     GrabPtr grab;
3233     TimeStamp time;
3234     REQUEST(xResourceReq);
3235
3236     REQUEST_SIZE_MATCH(xResourceReq);
3237     UpdateCurrentTime();
3238     grab = device->grab;
3239     time = ClientTimeToServerTime(stuff->id);
3240     if ((CompareTimeStamps(time, currentTime) != LATER) &&
3241         (CompareTimeStamps(time, device->grabTime) != EARLIER) &&
3242         (grab) && SameClient(grab, client))
3243         (*device->DeactivateGrab)(device);
3244     return Success;
3245 }
3246
3247 int
3248 ProcQueryPointer(client)
3249     ClientPtr client;
3250 {
3251     xQueryPointerReply rep;
3252     WindowPtr pWin, t;
3253     REQUEST(xResourceReq);
3254     DeviceIntPtr mouse = inputInfo.pointer;
3255
3256     REQUEST_SIZE_MATCH(xResourceReq);
3257     pWin = SecurityLookupWindow(stuff->id, client, SecurityReadAccess);
3258     if (!pWin)
3259         return BadWindow;
3260     if (mouse->valuator->motionHintWindow)
3261         MaybeStopHint(mouse, client);
3262     rep.type = X_Reply;
3263     rep.sequenceNumber = client->sequence;
3264     rep.mask = mouse->button->state | inputInfo.keyboard->key->state;
3265     rep.length = 0;
3266     rep.root = (ROOT)->drawable.id;
3267     rep.rootX = sprite.hot.x;
3268     rep.rootY = sprite.hot.y;
3269     rep.child = None;
3270     if (sprite.hot.pScreen == pWin->drawable.pScreen)
3271     {
3272         rep.sameScreen = xTrue;
3273         rep.winX = sprite.hot.x - pWin->drawable.x;
3274         rep.winY = sprite.hot.y - pWin->drawable.y;
3275         for (t = sprite.win; t; t = t->parent)
3276             if (t->parent == pWin)
3277             {
3278                 rep.child = t->drawable.id;
3279                 break;
3280             }
3281     }
3282     else
3283     {
3284         rep.sameScreen = xFalse;
3285         rep.winX = 0;
3286         rep.winY = 0;
3287     }
3288     WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
3289
3290     return(Success);    
3291 }
3292
3293 void
3294 InitEvents()
3295 {
3296     int i;
3297
3298     sprite.hot.pScreen = sprite.hotPhys.pScreen = (ScreenPtr)NULL;
3299     inputInfo.numDevices = 0;
3300     inputInfo.devices = (DeviceIntPtr)NULL;
3301     inputInfo.off_devices = (DeviceIntPtr)NULL;
3302     inputInfo.keyboard = (DeviceIntPtr)NULL;
3303     inputInfo.pointer = (DeviceIntPtr)NULL;
3304     if (spriteTraceSize == 0)
3305     {
3306         spriteTraceSize = 32;
3307         spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr));
3308         if (!spriteTrace)
3309             FatalError("failed to allocate spriteTrace");
3310     }
3311     spriteTraceGood = 0;
3312     lastEventMask = OwnerGrabButtonMask;
3313     filters[MotionNotify] = PointerMotionMask;
3314     sprite.win = NullWindow;
3315     sprite.current = NullCursor;
3316     sprite.hotLimits.x1 = 0;
3317     sprite.hotLimits.y1 = 0;
3318     sprite.hotLimits.x2 = 0;
3319     sprite.hotLimits.y2 = 0;
3320     sprite.confined = FALSE;
3321     syncEvents.replayDev = (DeviceIntPtr)NULL;
3322     syncEvents.replayWin = NullWindow;
3323     while (syncEvents.pending)
3324     {
3325         QdEventPtr next = syncEvents.pending->next;
3326         xfree(syncEvents.pending);
3327         syncEvents.pending = next;
3328     }
3329     syncEvents.pendtail = &syncEvents.pending;
3330     syncEvents.playingEvents = FALSE;
3331     syncEvents.time.months = 0;
3332     syncEvents.time.milliseconds = 0;   /* hardly matters */
3333     currentTime.months = 0;
3334     currentTime.milliseconds = GetTimeInMillis();
3335     lastDeviceEventTime = currentTime;
3336     for (i = 0; i < DNPMCOUNT; i++)
3337     {
3338         DontPropagateMasks[i] = 0;
3339         DontPropagateRefCnts[i] = 0;
3340     }
3341 }
3342
3343 int
3344 ProcSendEvent(client)
3345     ClientPtr client;
3346 {
3347     WindowPtr pWin;
3348     WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
3349     REQUEST(xSendEventReq);
3350
3351     REQUEST_SIZE_MATCH(xSendEventReq);
3352
3353     /* The client's event type must be a core event type or one defined by an
3354         extension. */
3355
3356     if ( ! ((stuff->event.u.u.type > X_Reply &&
3357              stuff->event.u.u.type < LASTEvent) || 
3358             (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
3359              stuff->event.u.u.type < (unsigned)lastEvent)))
3360     {
3361         client->errorValue = stuff->event.u.u.type;
3362         return BadValue;
3363     }
3364     if (stuff->event.u.u.type == ClientMessage &&
3365         stuff->event.u.u.detail != 8 &&
3366         stuff->event.u.u.detail != 16 &&
3367         stuff->event.u.u.detail != 32 &&
3368         !permitOldBugs)
3369     {
3370         client->errorValue = stuff->event.u.u.detail;
3371         return BadValue;
3372     }
3373     if ((stuff->eventMask & ~AllEventMasks) && !permitOldBugs)
3374     {
3375         client->errorValue = stuff->eventMask;
3376         return BadValue;
3377     }
3378
3379     if (stuff->destination == PointerWindow)
3380         pWin = sprite.win;
3381     else if (stuff->destination == InputFocus)
3382     {
3383         WindowPtr inputFocus = inputInfo.keyboard->focus->win;
3384
3385         if (inputFocus == NoneWin)
3386             return Success;
3387
3388         /* If the input focus is PointerRootWin, send the event to where
3389         the pointer is if possible, then perhaps propogate up to root. */
3390         if (inputFocus == PointerRootWin)
3391             inputFocus = ROOT;
3392
3393         if (IsParent(inputFocus, sprite.win))
3394         {
3395             effectiveFocus = inputFocus;
3396             pWin = sprite.win;
3397         }
3398         else
3399             effectiveFocus = pWin = inputFocus;
3400     }
3401     else
3402         pWin = SecurityLookupWindow(stuff->destination, client,
3403                                     SecurityReadAccess);
3404     if (!pWin)
3405         return BadWindow;
3406     if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue))
3407     {
3408         client->errorValue = stuff->propagate;
3409         return BadValue;
3410     }
3411     stuff->event.u.u.type |= 0x80;
3412     if (stuff->propagate)
3413     {
3414         for (;pWin; pWin = pWin->parent)
3415         {
3416             if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask,
3417                                       NullGrab, 0))
3418                 return Success;
3419             if (pWin == effectiveFocus)
3420                 return Success;
3421             stuff->eventMask &= ~wDontPropagateMask(pWin);
3422             if (!stuff->eventMask)
3423                 break;
3424         }
3425     }
3426     else
3427         (void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask,
3428                                     NullGrab, 0);
3429     return Success;
3430 }
3431
3432 int
3433 ProcUngrabKey(client)
3434     ClientPtr client;
3435 {
3436     REQUEST(xUngrabKeyReq);
3437     WindowPtr pWin;
3438     GrabRec tempGrab;
3439     DeviceIntPtr keybd = inputInfo.keyboard;
3440
3441     REQUEST_SIZE_MATCH(xUngrabKeyReq);
3442     pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess);
3443     if (!pWin)
3444         return BadWindow;
3445     if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) ||
3446          (stuff->key < keybd->key->curKeySyms.minKeyCode))
3447         && (stuff->key != AnyKey))
3448     {
3449         client->errorValue = stuff->key;
3450         return BadValue;
3451     }
3452     if ((stuff->modifiers != AnyModifier) &&
3453         (stuff->modifiers & ~AllModifiersMask))
3454     {
3455         client->errorValue = stuff->modifiers;
3456         return BadValue;
3457     }
3458
3459     tempGrab.resource = client->clientAsMask;
3460     tempGrab.device = keybd;
3461     tempGrab.window = pWin;
3462     tempGrab.modifiersDetail.exact = stuff->modifiers;
3463     tempGrab.modifiersDetail.pMask = NULL;
3464     tempGrab.modifierDevice = inputInfo.keyboard;
3465     tempGrab.type = KeyPress;
3466     tempGrab.detail.exact = stuff->key;
3467     tempGrab.detail.pMask = NULL;
3468
3469     if (!DeletePassiveGrabFromList(&tempGrab))
3470         return(BadAlloc);
3471     return(Success);
3472 }
3473
3474 int
3475 ProcGrabKey(client)
3476     ClientPtr client;
3477 {
3478     WindowPtr pWin;
3479     REQUEST(xGrabKeyReq);
3480     GrabPtr grab;
3481     DeviceIntPtr keybd = inputInfo.keyboard;
3482
3483     REQUEST_SIZE_MATCH(xGrabKeyReq);
3484     if ((stuff->ownerEvents != xTrue) && (stuff->ownerEvents != xFalse))
3485     {
3486         client->errorValue = stuff->ownerEvents;
3487         return(BadValue);
3488     }
3489     if ((stuff->pointerMode != GrabModeSync) &&
3490         (stuff->pointerMode != GrabModeAsync))
3491     {
3492         client->errorValue = stuff->pointerMode;
3493         return BadValue;
3494     }
3495     if ((stuff->keyboardMode != GrabModeSync) &&
3496         (stuff->keyboardMode != GrabModeAsync))
3497     {
3498         client->errorValue = stuff->keyboardMode;
3499         return BadValue;
3500     }
3501     if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) ||
3502          (stuff->key < keybd->key->curKeySyms.minKeyCode))
3503         && (stuff->key != AnyKey))
3504     {
3505         client->errorValue = stuff->key;
3506         return BadValue;
3507     }
3508     if ((stuff->modifiers != AnyModifier) &&
3509         (stuff->modifiers & ~AllModifiersMask))
3510     {
3511         client->errorValue = stuff->modifiers;
3512         return BadValue;
3513     }
3514     pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess);
3515     if (!pWin)
3516         return BadWindow;
3517
3518     grab = CreateGrab(client->index, keybd, pWin, 
3519         (Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents,
3520         (Bool)stuff->keyboardMode, (Bool)stuff->pointerMode,
3521         keybd, stuff->modifiers, KeyPress, stuff->key, NullWindow, NullCursor);
3522     if (!grab)
3523         return BadAlloc;
3524     return AddPassiveGrabToList(grab);
3525 }
3526
3527 int
3528 ProcGrabButton(client)
3529     ClientPtr client;
3530 {
3531     WindowPtr pWin, confineTo;
3532     REQUEST(xGrabButtonReq);
3533     CursorPtr cursor;
3534     GrabPtr grab;
3535
3536     REQUEST_SIZE_MATCH(xGrabButtonReq);
3537     if ((stuff->pointerMode != GrabModeSync) &&
3538         (stuff->pointerMode != GrabModeAsync))
3539     {
3540         client->errorValue = stuff->pointerMode;
3541         return BadValue;
3542     }
3543     if ((stuff->keyboardMode != GrabModeSync) &&
3544         (stuff->keyboardMode != GrabModeAsync))
3545     {
3546         client->errorValue = stuff->keyboardMode;
3547         return BadValue;
3548     }
3549     if ((stuff->modifiers != AnyModifier) &&
3550         (stuff->modifiers & ~AllModifiersMask))
3551     {
3552         client->errorValue = stuff->modifiers;
3553         return BadValue;
3554     }
3555     if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
3556     {
3557         client->errorValue = stuff->ownerEvents;
3558         return BadValue;
3559     }
3560     if (stuff->eventMask & ~PointerGrabMask)
3561     {
3562         client->errorValue = stuff->eventMask;
3563         return BadValue;
3564     }
3565     pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess);
3566     if (!pWin)
3567         return BadWindow;
3568     if (stuff->confineTo == None)
3569         confineTo = NullWindow;
3570     else
3571     {
3572         confineTo = SecurityLookupWindow(stuff->confineTo, client,
3573                                          SecurityReadAccess);
3574         if (!confineTo)
3575             return BadWindow;
3576     }
3577     if (stuff->cursor == None)
3578         cursor = NullCursor;
3579     else
3580     {
3581         cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
3582                                                 RT_CURSOR, SecurityReadAccess);
3583         if (!cursor)
3584         {
3585             client->errorValue = stuff->cursor;
3586             return BadCursor;
3587         }
3588     }
3589
3590     grab = CreateGrab(client->index, inputInfo.pointer, pWin, 
3591         permitOldBugs ? (Mask)(stuff->eventMask |
3592                                ButtonPressMask | ButtonReleaseMask) :
3593                         (Mask)stuff->eventMask,
3594         (Bool)stuff->ownerEvents, (Bool) stuff->keyboardMode,
3595         (Bool)stuff->pointerMode, inputInfo.keyboard, stuff->modifiers,
3596         ButtonPress, stuff->button, confineTo, cursor);
3597     if (!grab)
3598         return BadAlloc;
3599     return AddPassiveGrabToList(grab);
3600 }
3601
3602 int
3603 ProcUngrabButton(client)
3604     ClientPtr client;
3605 {
3606     REQUEST(xUngrabButtonReq);
3607     WindowPtr pWin;
3608     GrabRec tempGrab;
3609
3610     REQUEST_SIZE_MATCH(xUngrabButtonReq);
3611     if ((stuff->modifiers != AnyModifier) &&
3612         (stuff->modifiers & ~AllModifiersMask))
3613     {
3614         client->errorValue = stuff->modifiers;
3615         return BadValue;
3616     }
3617     pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess);
3618     if (!pWin)
3619         return BadWindow;
3620
3621     tempGrab.resource = client->clientAsMask;
3622     tempGrab.device = inputInfo.pointer;
3623     tempGrab.window = pWin;
3624     tempGrab.modifiersDetail.exact = stuff->modifiers;
3625     tempGrab.modifiersDetail.pMask = NULL;
3626     tempGrab.modifierDevice = inputInfo.keyboard;
3627     tempGrab.type = ButtonPress;
3628     tempGrab.detail.exact = stuff->button;
3629     tempGrab.detail.pMask = NULL;
3630
3631     if (!DeletePassiveGrabFromList(&tempGrab))
3632         return(BadAlloc);
3633     return(Success);
3634 }
3635
3636 void
3637 DeleteWindowFromAnyEvents(pWin, freeResources)
3638     WindowPtr           pWin;
3639     Bool                freeResources;
3640 {
3641     WindowPtr           parent;
3642     DeviceIntPtr        mouse = inputInfo.pointer;
3643     DeviceIntPtr        keybd = inputInfo.keyboard;
3644     FocusClassPtr       focus = keybd->focus;
3645     OtherClientsPtr     oc;
3646     GrabPtr             passive;
3647
3648
3649     /* Deactivate any grabs performed on this window, before making any
3650         input focus changes. */
3651
3652     if (mouse->grab &&
3653         ((mouse->grab->window == pWin) || (mouse->grab->confineTo == pWin)))
3654         (*mouse->DeactivateGrab)(mouse);
3655
3656     /* Deactivating a keyboard grab should cause focus events. */
3657
3658     if (keybd->grab && (keybd->grab->window == pWin))
3659         (*keybd->DeactivateGrab)(keybd);
3660
3661     /* If the focus window is a root window (ie. has no parent) then don't 
3662         delete the focus from it. */
3663     
3664     if ((pWin == focus->win) && (pWin->parent != NullWindow))
3665     {
3666         int focusEventMode = NotifyNormal;
3667
3668         /* If a grab is in progress, then alter the mode of focus events. */
3669
3670         if (keybd->grab)
3671             focusEventMode = NotifyWhileGrabbed;
3672
3673         switch (focus->revert)
3674         {
3675         case RevertToNone:
3676             DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
3677             focus->win = NoneWin;
3678             focus->traceGood = 0;
3679             break;
3680         case RevertToParent:
3681             parent = pWin;
3682             do
3683             {
3684                 parent = parent->parent;
3685                 focus->traceGood--;
3686             } while (!parent->realized
3687 /* This would be a good protocol change -- windows being reparented
3688    during SaveSet processing would cause the focus to revert to the
3689    nearest enclosing window which will survive the death of the exiting
3690    client, instead of ending up reverting to a dying window and thence
3691    to None
3692  */
3693 #ifdef NOTDEF
3694               || clients[CLIENT_ID(parent->drawable.id)]->clientGone
3695 #endif
3696                 );
3697             DoFocusEvents(keybd, pWin, parent, focusEventMode);
3698             focus->win = parent;
3699             focus->revert = RevertToNone;
3700             break;
3701         case RevertToPointerRoot:
3702             DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode);
3703             focus->win = PointerRootWin;
3704             focus->traceGood = 0;
3705             break;
3706         }
3707     }
3708
3709     if (mouse->valuator->motionHintWindow == pWin)
3710         mouse->valuator->motionHintWindow = NullWindow;
3711
3712     if (freeResources)
3713     {
3714         if (pWin->dontPropagate)
3715             DontPropagateRefCnts[pWin->dontPropagate]--;
3716         while ( (oc = wOtherClients(pWin)) )
3717             FreeResource(oc->resource, RT_NONE);
3718         while ( (passive = wPassiveGrabs(pWin)) )
3719             FreeResource(passive->resource, RT_NONE);
3720      }
3721 #ifdef XINPUT
3722     DeleteWindowFromAnyExtEvents(pWin, freeResources);
3723 #endif
3724 }
3725
3726 /* Call this whenever some window at or below pWin has changed geometry */
3727
3728 /*ARGSUSED*/
3729 void
3730 CheckCursorConfinement(pWin)
3731     WindowPtr pWin;
3732 {
3733     GrabPtr grab = inputInfo.pointer->grab;
3734     WindowPtr confineTo;
3735
3736     if (grab && (confineTo = grab->confineTo))
3737     {
3738         if (!REGION_NOTEMPTY( confineTo->drawable.pScreen, 
3739                         &confineTo->borderSize))
3740             (*inputInfo.pointer->DeactivateGrab)(inputInfo.pointer);
3741         else if ((pWin == confineTo) || IsParent(pWin, confineTo))
3742             ConfineCursorToWindow(confineTo, TRUE, TRUE);
3743     }
3744 }
3745
3746 Mask
3747 EventMaskForClient(pWin, client)
3748     WindowPtr           pWin;
3749     ClientPtr           client;
3750 {
3751     register OtherClientsPtr    other;
3752
3753     if (wClient (pWin) == client)
3754         return pWin->eventMask;
3755     for (other = wOtherClients(pWin); other; other = other->next)
3756     {
3757         if (SameClient(other, client))
3758             return other->mask;
3759     }
3760     return 0;
3761 }
3762
3763 int
3764 ProcRecolorCursor(client)
3765     ClientPtr client;
3766 {
3767     CursorPtr pCursor;
3768     int         nscr;
3769     ScreenPtr   pscr;
3770     REQUEST(xRecolorCursorReq);
3771
3772     REQUEST_SIZE_MATCH(xRecolorCursorReq);
3773     pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
3774                                         RT_CURSOR, SecurityWriteAccess);
3775     if ( !pCursor) 
3776     {
3777         client->errorValue = stuff->cursor;
3778         return (BadCursor);
3779     }
3780
3781     pCursor->foreRed = stuff->foreRed;
3782     pCursor->foreGreen = stuff->foreGreen;
3783     pCursor->foreBlue = stuff->foreBlue;
3784
3785     pCursor->backRed = stuff->backRed;
3786     pCursor->backGreen = stuff->backGreen;
3787     pCursor->backBlue = stuff->backBlue;
3788
3789     for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
3790     {
3791         pscr = screenInfo.screens[nscr];
3792         ( *pscr->RecolorCursor)(pscr, pCursor,
3793                                 (pCursor == sprite.current) &&
3794                                 (pscr == sprite.hotPhys.pScreen));
3795     }
3796     return (Success);
3797 }
3798
3799 void
3800 WriteEventsToClient(pClient, count, events)
3801     ClientPtr   pClient;
3802     int         count;
3803     xEvent      *events;
3804 {
3805     xEvent    eventTo, *eventFrom;
3806     int       i;
3807
3808 #ifdef XKB
3809     if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events)))
3810         return;
3811 #endif
3812
3813     if (EventCallback)
3814     {
3815         EventInfoRec eventinfo;
3816         eventinfo.client = pClient;
3817         eventinfo.events = events;
3818         eventinfo.count = count;
3819         CallCallbacks(&EventCallback, (pointer)&eventinfo);
3820     }
3821     if(pClient->swapped)
3822     {
3823         for(i = 0; i < count; i++)
3824         {
3825             eventFrom = &events[i];
3826             /* Remember to strip off the leading bit of type in case
3827                this event was sent with "SendEvent." */
3828             (*EventSwapVector[eventFrom->u.u.type & 0177])
3829                 (eventFrom, &eventTo);
3830             (void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo);
3831         }
3832     }
3833     else
3834     {
3835         (void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events);
3836     }
3837 }