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