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
GetNextEventMask()238 GetNextEventMask()
239 {
240     lastEventMask <<= 1;
241     return lastEventMask;
242 }
243 
244 void
SetMaskForEvent(mask,event)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
SetCriticalEvent(event)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
SyntheticMotion(int x,int y)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
ConfineToShape(RegionPtr shape,int * px,int * py)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
CheckPhysLimits(CursorPtr cursor,Bool generateEvents,Bool confineToScreen,ScreenPtr pScreen)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
CheckVirtualMotion(register QdEventPtr qe,register WindowPtr pWin)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
ConfineCursorToWindow(pWin,generateEvents,confineToScreen)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
PointerConfinedToScreen()458 PointerConfinedToScreen()
459 {
460     return sprite.confined;
461 }
462 
463 static void
464 #if NeedFunctionPrototypes
ChangeToCursor(CursorPtr cursor)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
IsParent(a,b)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
PostNewCursor(void)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
GetCurrentRootWindow()528 GetCurrentRootWindow()
529 {
530     return ROOT;
531 }
532 
533 WindowPtr
GetSpriteWindow()534 GetSpriteWindow()
535 {
536     return sprite.win;
537 }
538 
539 CursorPtr
GetSpriteCursor()540 GetSpriteCursor()
541 {
542     return sprite.current;
543 }
544 
545 void
GetSpritePosition(px,py)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
MonthChangedOrBadTime(register xEvent * xE)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
NoticeEventTime(xE)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
EnqueueEvent(xE,device,count)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
PlayReleasedEvents(void)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
FreezeThaw(register DeviceIntPtr dev,Bool frozen)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
ComputeFreezes()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
CheckGrabForSyncs(thisDev,thisMode,otherMode)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
ActivatePointerGrab(mouse,grab,time,autoGrab)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
DeactivatePointerGrab(mouse)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
ActivateKeyboardGrab(keybd,grab,time,passive)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
DeactivateKeyboardGrab(keybd)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
AllowSome(client,time,thisDev,newState)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
ProcAllowEvents(client)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
ReleaseActiveGrabs(client)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
TryClientEvents(client,pEvents,count,mask,filter,grab)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
DeliverEventsToWindow(pWin,pEvents,count,filter,grab,mskidx)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
MaybeDeliverEventsToClient(pWin,pEvents,count,filter,dontClient)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
FixUpEventFromWindow(xEvent * xE,WindowPtr pWin,Window child,Bool calcChild)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
DeliverDeviceEvents(pWin,xE,grab,stopAt,dev,count)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
DeliverEvents(pWin,xE,count,otherParent)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
XYToWindow(int x,int y)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
CheckMotion(xEvent * xE)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
WindowsRestructured()1593 WindowsRestructured()
1594 {
1595     (void) CheckMotion((xEvent *)NULL);
1596 }
1597 
1598 void
DefineInitialRootWindow(win)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
WindowHasNewCursor(pWin)1631 WindowHasNewCursor(pWin)
1632     WindowPtr pWin;
1633 {
1634     PostNewCursor();
1635 }
1636 
1637 void
NewCurrentScreen(newScreen,x,y)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
ProcWarpPointer(client)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
CheckPassiveGrabsOnWindow(WindowPtr pWin,register DeviceIntPtr device,register xEvent * xE,int count)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
CheckDeviceGrabs(device,xE,checkFirst,count)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
DeliverFocusedEvent(keybd,xE,window,count)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
DeliverGrabbedEvent(xE,thisDev,deactivateGrab,count)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
CoreProcessKeyboardEvent(xE,keybd,count)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
CoreProcessPointerEvent(xE,mouse,count)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
RecalculateDeliverableEvents(pWin)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
OtherClientGone(value,id)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
EventSelectForWindow(pWin,client,mask)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
EventSuppressForWindow(pWin,client,mask,checkOptional)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
CommonAncestor(register WindowPtr a,register WindowPtr b)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
EnterLeaveEvent(int type,int mode,int detail,register WindowPtr pWin,Window child)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
EnterNotifies(WindowPtr ancestor,WindowPtr child,int mode,int detail)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
LeaveNotifies(WindowPtr child,WindowPtr ancestor,int mode,int detail)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
DoEnterLeaveEvents(WindowPtr fromWin,WindowPtr toWin,int mode)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
FocusEvent(DeviceIntPtr dev,int type,int mode,int detail,register WindowPtr pWin)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
FocusInEvents(DeviceIntPtr dev,WindowPtr ancestor,WindowPtr child,WindowPtr skipChild,int mode,int detail,Bool doAncestor)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
FocusOutEvents(DeviceIntPtr dev,WindowPtr child,WindowPtr ancestor,int mode,int detail,Bool doAncestor)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
DoFocusEvents(dev,fromWin,toWin,mode)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
SetInputFocus(ClientPtr client,DeviceIntPtr dev,Window focusID,CARD8 revertTo,Time ctime,Bool followOK)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
ProcSetInputFocus(client)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
ProcGetInputFocus(client)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
ProcGrabPointer(client)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
ProcChangeActivePointerGrab(client)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
ProcUngrabPointer(client)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
GrabDevice(client,dev,this_mode,other_mode,grabWindow,ownerEvents,ctime,mask,status)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
ProcGrabKeyboard(client)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
ProcUngrabKeyboard(client)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
ProcQueryPointer(client)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
InitEvents()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
ProcSendEvent(client)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
ProcUngrabKey(client)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
ProcGrabKey(client)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
ProcGrabButton(client)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
ProcUngrabButton(client)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
DeleteWindowFromAnyEvents(pWin,freeResources)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
CheckCursorConfinement(pWin)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
EventMaskForClient(pWin,client)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
ProcRecolorCursor(client)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
WriteEventsToClient(pClient,count,events)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 }
3838