1 /************************************************************
3 Copyright (c) 1987 X Consortium
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:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
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.
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.
27 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
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.
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
47 ********************************************************/
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 $ */
59 #include "windowstr.h"
61 #include "scrnintstr.h"
62 #include "cursorstr.h"
64 #include "dixstruct.h"
71 #define _SECURITY_SERVER
72 #include "extensions/security.h"
77 #include "extnsionst.h"
79 #include "dixevents.h"
83 extern WindowPtr *WindowTable;
85 #define EXTENSION_EVENT_BASE 64
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 | \
98 #define PointerGrabMask ( \
99 ButtonPressMask | ButtonReleaseMask | \
100 EnterWindowMask | LeaveWindowMask | \
101 PointerMotionHintMask | KeymapStateMask | \
103 #define AllModifiersMask ( \
104 ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
105 Mod3Mask | Mod4Mask | Mod5Mask )
106 #define AllEventMasks (lastEventMask|(lastEventMask-1))
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.
111 #define Motion_Filter(class) (PointerMotionMask | \
112 (class)->state | (class)->motionMask)
115 #define WID(w) ((w) ? ((w)->drawable.id) : 0)
117 #define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
119 CallbackListPtr EventCallback;
120 CallbackListPtr DeviceEventCallback;
124 Mask DontPropagateMasks[DNPMCOUNT];
125 static int DontPropagateRefCnts[DNPMCOUNT];
128 static debug_events = 0;
133 QdEventPtr pending, *pendtail;
134 DeviceIntPtr replayDev; /* kludgy rock to put flag for */
135 WindowPtr replayWin; /* ComputeFreezes */
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.
145 static WindowPtr *spriteTrace = (WindowPtr *)NULL;
146 #define ROOT spriteTrace[0]
147 static int spriteTraceSize = 0;
148 static int spriteTraceGood;
157 BoxRec hotLimits; /* logical constraints of hot spot */
158 Bool confined; /* confined to screen */
160 RegionPtr hotShape; /* additional logical shape constraint */
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 */
168 static void DoEnterLeaveEvents(
169 #if NeedFunctionPrototypes
170 WindowPtr /*fromWin*/,
176 static WindowPtr XYToWindow(
177 #if NeedFunctionPrototypes
183 extern Bool permitOldBugs;
184 extern Bool Must_have_memory;
185 extern int lastEvent;
187 extern int DeviceMotionNotify, DeviceButtonPress, DeviceKeyPress;
190 static Mask lastEventMask;
192 #define CantBeFiltered NoEventMask
193 static Mask filters[128] =
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 */
232 static CARD8 criticalEvents[32] =
234 0x3c /* key and button events */
241 return lastEventMask;
245 SetMaskForEvent(mask, event)
249 if ((event < LASTEvent) || (event >= 128))
250 FatalError("SetMaskForEvent: bogus event number");
251 filters[event] = mask;
255 SetCriticalEvent(event)
259 FatalError("SetCriticalEvent: bogus event number");
260 criticalEvents[event >> 3] |= 1 << (event & 7);
264 #if NeedFunctionPrototypes
265 SyntheticMotion(int x, int y)
267 SyntheticMotion(x, y)
273 xE.u.keyButtonPointer.rootX = x;
274 xE.u.keyButtonPointer.rootY = y;
275 if (syncEvents.playingEvents)
276 xE.u.keyButtonPointer.time = syncEvents.time.milliseconds;
278 xE.u.keyButtonPointer.time = currentTime.milliseconds;
279 xE.u.u.type = MotionNotify;
280 (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1);
285 #if NeedFunctionPrototypes
286 ConfineToShape(RegionPtr shape, int *px, int *py)
288 ConfineToShape(shape, px, py)
294 int x = *px, y = *py;
295 int incx = 1, incy = 1;
297 if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box))
299 box = *REGION_EXTENTS(sprite.hot.pScreen, shape);
300 /* this is rather crude */
319 return; /* should never get here! */
321 } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box));
328 #if NeedFunctionPrototypes
332 Bool confineToScreen,
335 CheckPhysLimits(cursor, generateEvents, confineToScreen, pScreen)
338 Bool confineToScreen;
346 new = sprite.hotPhys;
348 new.pScreen = pScreen;
350 pScreen = new.pScreen;
351 (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits,
353 sprite.confined = confineToScreen;
354 (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits);
355 if (new.x < sprite.physLimits.x1)
356 new.x = sprite.physLimits.x1;
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;
363 if (new.y >= sprite.physLimits.y2)
364 new.y = sprite.physLimits.y2 - 1;
367 ConfineToShape(sprite.hotShape, &new.x, &new.y);
369 if ((pScreen != sprite.hotPhys.pScreen) ||
370 (new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y))
372 if (pScreen != sprite.hotPhys.pScreen)
373 sprite.hotPhys = new;
374 (*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents);
376 SyntheticMotion(new.x, new.y);
381 #if NeedFunctionPrototypes
383 register QdEventPtr qe,
384 register WindowPtr pWin)
386 CheckVirtualMotion(qe, pWin)
387 register QdEventPtr qe;
388 register WindowPtr pWin;
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 :
404 if (sprite.hot.pScreen != pWin->drawable.pScreen)
406 sprite.hot.pScreen = pWin->drawable.pScreen;
407 sprite.hot.x = sprite.hot.y = 0;
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;
419 if (wBoundingShape(pWin))
420 ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y);
424 qe->pScreen = sprite.hot.pScreen;
425 qe->event->u.keyButtonPointer.rootX = sprite.hot.x;
426 qe->event->u.keyButtonPointer.rootY = sprite.hot.y;
429 ROOT = WindowTable[sprite.hot.pScreen->myNum];
433 ConfineCursorToWindow(pWin, generateEvents, confineToScreen)
436 Bool confineToScreen;
438 ScreenPtr pScreen = pWin->drawable.pScreen;
440 if (syncEvents.playingEvents)
442 CheckVirtualMotion((QdEventPtr)NULL, pWin);
443 SyntheticMotion(sprite.hot.x, sprite.hot.y);
447 sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize);
449 sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize
452 CheckPhysLimits(sprite.current, generateEvents, confineToScreen,
458 PointerConfinedToScreen()
460 return sprite.confined;
464 #if NeedFunctionPrototypes
465 ChangeToCursor(CursorPtr cursor)
467 ChangeToCursor(cursor)
471 if (cursor != sprite.current)
473 if ((sprite.current->bits->xhot != cursor->bits->xhot) ||
474 (sprite.current->bits->yhot != cursor->bits->yhot))
475 CheckPhysLimits(cursor, FALSE, PointerConfinedToScreen(),
477 (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen,
479 sprite.current = cursor;
483 /* returns true if b is a descendent of a */
486 register WindowPtr a, b;
488 for (b = b->parent; b; b = b->parent)
489 if (b == a) return TRUE;
494 #if NeedFunctionPrototypes
500 register WindowPtr win;
501 register GrabPtr grab = inputInfo.pointer->grab;
503 if (syncEvents.playingEvents)
509 ChangeToCursor(grab->cursor);
512 if (IsParent(grab->window, sprite.win))
519 for (; win; win = win->parent)
520 if (win->optional && win->optional->cursor != NullCursor)
522 ChangeToCursor(win->optional->cursor);
528 GetCurrentRootWindow()
542 return sprite.current;
546 GetSpritePosition(px, py)
549 *px = sprite.hotPhys.x;
550 *py = sprite.hotPhys.y;
553 #define TIMESLOP (5 * 60 * 1000) /* 5 minutes */
556 #if NeedFunctionPrototypes
557 MonthChangedOrBadTime(register xEvent *xE)
559 MonthChangedOrBadTime(xE)
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.
567 if ((currentTime.milliseconds - xE->u.keyButtonPointer.time) > TIMESLOP)
568 currentTime.months++;
570 xE->u.keyButtonPointer.time = currentTime.milliseconds;
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; }
583 if (!syncEvents.playingEvents)
587 /**************************************************************************
588 * The following procedures deal with synchronous events *
589 **************************************************************************/
592 EnqueueEvent(xE, device, count)
597 register QdEventPtr tail = *syncEvents.pendtail;
598 register QdEventPtr qe;
602 if (DeviceEventCallback)
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
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);
621 if (xE->u.u.type == MotionNotify)
623 sprite.hotPhys.x = xE->u.keyButtonPointer.rootX;
624 sprite.hotPhys.y = xE->u.keyButtonPointer.rootY;
625 /* do motion compression */
627 (tail->event->u.u.type == MotionNotify) &&
628 (tail->pScreen == sprite.hotPhys.pScreen))
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;
637 qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent)));
640 qe->next = (QdEventPtr)NULL;
642 qe->pScreen = sprite.hotPhys.pScreen;
643 qe->months = currentTime.months;
644 qe->event = (xEvent *)(qe + 1);
646 for (qxE = qe->event; --count >= 0; qxE++, xE++)
649 syncEvents.pendtail = &tail->next;
650 *syncEvents.pendtail = qe;
654 #if NeedFunctionPrototypes
655 PlayReleasedEvents(void)
660 register QdEventPtr *prev, qe;
661 register DeviceIntPtr dev;
663 prev = &syncEvents.pending;
664 while ( (qe = *prev) )
666 if (!qe->device->sync.frozen)
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,
678 for (dev = inputInfo.devices; dev && dev->sync.frozen; dev = dev->next)
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;
692 #if NeedFunctionPrototypes
693 FreezeThaw(register DeviceIntPtr dev, Bool frozen)
695 FreezeThaw(dev, frozen)
696 register DeviceIntPtr dev;
700 dev->sync.frozen = frozen;
702 dev->public.processInputProc = dev->public.enqueueInputProc;
704 dev->public.processInputProc = dev->public.realInputProc;
710 register DeviceIntPtr replayDev = syncEvents.replayDev;
716 register DeviceIntPtr dev;
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))
722 syncEvents.playingEvents = TRUE;
725 xE = replayDev->sync.event;
726 count = replayDev->sync.evcount;
727 syncEvents.replayDev = (DeviceIntPtr)NULL;
729 xE->u.keyButtonPointer.rootX, xE->u.keyButtonPointer.rootY);
730 for (i = 0; i < spriteTraceGood; i++)
731 if (syncEvents.replayWin == spriteTrace[i])
733 if (!CheckDeviceGrabs(replayDev, xE, i+1, count))
734 if (replayDev->focus)
735 DeliverFocusedEvent(replayDev, xE, w, count);
737 DeliverDeviceEvents(w, xE, NullGrab, NullWindow,
741 /* must not still be in the same stack */
742 if (replayDev->focus)
743 DeliverFocusedEvent(replayDev, xE, w, count);
745 DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count);
748 for (dev = inputInfo.devices; dev; dev = dev->next)
750 if (!dev->sync.frozen)
752 PlayReleasedEvents();
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)
760 if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
761 sprite.hotPhys.x = sprite.hotPhys.y = 0;
762 ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
765 ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum],
771 CheckGrabForSyncs(thisDev, thisMode, otherMode)
772 register DeviceIntPtr thisDev;
773 Bool thisMode, otherMode;
775 register GrabPtr grab = thisDev->grab;
776 register DeviceIntPtr dev;
778 if (thisMode == GrabModeSync)
779 thisDev->sync.state = FROZEN_NO_EVENT;
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;
788 for (dev = inputInfo.devices; dev; dev = dev->next)
792 if (otherMode == GrabModeSync)
793 dev->sync.other = grab;
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;
807 ActivatePointerGrab(mouse, grab, time, autoGrab)
808 register GrabPtr grab;
809 register DeviceIntPtr mouse;
813 WindowPtr oldWin = (mouse->grab) ? mouse->grab->window
818 if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
819 sprite.hotPhys.x = sprite.hotPhys.y = 0;
820 ConfineCursorToWindow(grab->confineTo, FALSE, TRUE);
822 DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab);
823 mouse->valuator->motionHintWindow = NullWindow;
824 if (syncEvents.playingEvents)
825 mouse->grabTime = syncEvents.time;
827 mouse->grabTime = time;
829 grab->cursor->refcnt++;
830 mouse->activeGrab = *grab;
831 mouse->grab = &mouse->activeGrab;
832 mouse->fromPassiveGrab = autoGrab;
834 CheckGrabForSyncs(mouse,
835 (Bool)grab->pointerMode, (Bool)grab->keyboardMode);
839 DeactivatePointerGrab(mouse)
840 register DeviceIntPtr mouse;
842 register GrabPtr grab = mouse->grab;
843 register DeviceIntPtr dev;
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)
851 if (dev->sync.other == grab)
852 dev->sync.other = NullGrab;
854 DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab);
856 ConfineCursorToWindow(ROOT, FALSE, FALSE);
859 FreeCursor(grab->cursor, (Cursor)0);
864 ActivateKeyboardGrab(keybd, grab, time, passive)
865 register DeviceIntPtr keybd;
873 oldWin = keybd->grab->window;
874 else if (keybd->focus)
875 oldWin = keybd->focus->win;
878 if (oldWin == FollowKeyboardWin)
879 oldWin = inputInfo.keyboard->focus->win;
881 keybd->valuator->motionHintWindow = NullWindow;
882 DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
883 if (syncEvents.playingEvents)
884 keybd->grabTime = syncEvents.time;
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);
895 DeactivateKeyboardGrab(keybd)
896 register DeviceIntPtr keybd;
898 register GrabPtr grab = keybd->grab;
899 register DeviceIntPtr dev;
900 register WindowPtr focusWin = keybd->focus ? keybd->focus->win
903 if (focusWin == FollowKeyboardWin)
904 focusWin = inputInfo.keyboard->focus->win;
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)
912 if (dev->sync.other == grab)
913 dev->sync.other = NullGrab;
915 DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
920 AllowSome(client, time, thisDev, newState)
923 register DeviceIntPtr thisDev;
926 Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
928 register DeviceIntPtr dev;
930 thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client);
932 otherGrabbed = FALSE;
934 grabTime = thisDev->grabTime;
935 for (dev = inputInfo.devices; dev; dev = dev->next)
939 if (dev->grab && SameClient(dev->grab, client))
941 if (!(thisGrabbed || otherGrabbed) ||
942 (CompareTimeStamps(dev->grabTime, grabTime) == LATER))
943 grabTime = dev->grabTime;
945 if (thisDev->sync.other == dev->grab)
947 if (dev->sync.state < FROZEN)
948 othersFrozen = FALSE;
950 else if (!dev->sync.other || !SameClient(dev->sync.other, client))
951 othersFrozen = FALSE;
953 if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced))
955 if ((CompareTimeStamps(time, currentTime) == LATER) ||
956 (CompareTimeStamps(time, grabTime) == EARLIER))
960 case THAWED: /* Async */
962 thisDev->sync.state = THAWED;
964 thisDev->sync.other = NullGrab;
967 case FREEZE_NEXT_EVENT: /* Sync */
970 thisDev->sync.state = FREEZE_NEXT_EVENT;
972 thisDev->sync.other = NullGrab;
976 case THAWED_BOTH: /* AsyncBoth */
979 for (dev = inputInfo.devices; dev; dev = dev->next)
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;
989 case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */
992 for (dev = inputInfo.devices; dev; dev = dev->next)
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;
1002 case NOT_GRABBED: /* Replay */
1003 if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT)
1006 thisDev->sync.other = NullGrab;
1007 syncEvents.replayDev = thisDev;
1008 syncEvents.replayWin = thisDev->grab->window;
1009 (*thisDev->DeactivateGrab)(thisDev);
1010 syncEvents.replayDev = (DeviceIntPtr)NULL;
1013 case THAW_OTHERS: /* AsyncOthers */
1016 for (dev = inputInfo.devices; dev; dev = dev->next)
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;
1032 ProcAllowEvents(client)
1033 register ClientPtr client;
1036 DeviceIntPtr mouse = inputInfo.pointer;
1037 DeviceIntPtr keybd = inputInfo.keyboard;
1038 REQUEST(xAllowEventsReq);
1040 REQUEST_SIZE_MATCH(xAllowEventsReq);
1041 time = ClientTimeToServerTime(stuff->time);
1042 switch (stuff->mode)
1045 AllowSome(client, time, mouse, NOT_GRABBED);
1048 AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
1051 AllowSome(client, time, mouse, THAWED);
1053 case ReplayKeyboard:
1054 AllowSome(client, time, keybd, NOT_GRABBED);
1057 AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
1060 AllowSome(client, time, keybd, THAWED);
1063 AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
1066 AllowSome(client, time, keybd, THAWED_BOTH);
1069 client->errorValue = stuff->mode;
1076 ReleaseActiveGrabs(client)
1079 register DeviceIntPtr dev;
1082 /* XXX CloseDownClient should remove passive grabs before
1083 * releasing active grabs.
1087 for (dev = inputInfo.devices; dev; dev = dev->next)
1089 if (dev->grab && SameClient(dev->grab, client))
1091 (*dev->DeactivateGrab)(dev);
1098 /**************************************************************************
1099 * The following procedures deal with delivering events *
1100 **************************************************************************/
1103 TryClientEvents (client, pEvents, count, mask, filter, grab)
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);
1118 if ((client) && (client != serverClient) && (!client->clientGone) &&
1119 ((filter == CantBeFiltered) || (mask & filter)))
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)
1126 if (mask & PointerMotionHintMask)
1128 if (WID(inputInfo.pointer->valuator->motionHintWindow) ==
1129 pEvents->u.keyButtonPointer.event)
1132 if (debug_events) ErrorF("\n");
1134 return 1; /* don't send, but pretend we did */
1136 pEvents->u.u.detail = NotifyHint;
1140 pEvents->u.u.detail = NotifyNormal;
1146 if ((type == DeviceMotionNotify) &&
1147 MaybeSendDeviceMotionNotifyHint
1148 ((deviceKeyButtonPointer*)pEvents, mask) != 0)
1153 if (type != KeymapNotify)
1155 /* all extension events must have a sequence number */
1156 for (i = 0; i < count; i++)
1157 pEvents[i].u.u.sequenceNumber = client->sequence;
1160 if (BitIsOn(criticalEvents, type))
1161 SetCriticalOutputPending();
1163 WriteEventsToClient(client, count, pEvents);
1165 if (debug_events) ErrorF( " delivered\n");
1172 if (debug_events) ErrorF("\n");
1179 DeliverEventsToWindow(pWin, pEvents, count, filter, grab, mskidx)
1180 register WindowPtr pWin;
1187 int deliveries = 0, nondeliveries = 0;
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;
1195 /* CantBeFiltered means only window owner gets the event */
1196 if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE))
1198 /* if nobody ever wants to see this event, skip some work */
1199 if (filter != CantBeFiltered &&
1200 !((wOtherEventMasks(pWin)|pWin->eventMask) & filter))
1202 if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count,
1203 pWin->eventMask, filter, grab)) )
1208 client = wClient(pWin);
1209 deliveryMask = pWin->eventMask;
1214 if (filter != CantBeFiltered)
1216 if (type & EXTENSION_EVENT_BASE)
1218 OtherInputMasks *inputMasks;
1220 inputMasks = wOtherInputMasks(pWin);
1222 !(inputMasks->inputEvents[mskidx] & filter))
1224 other = inputMasks->inputClients;
1227 other = (InputClients *)wOtherClients(pWin);
1228 for (; other; other = other->next)
1230 if ( (attempt = TryClientEvents(rClient(other), pEvents, count,
1231 other->mask[mskidx], filter, grab)) )
1236 client = rClient(other);
1237 deliveryMask = other->mask[mskidx];
1243 if ((type == ButtonPress) && deliveries && (!grab))
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,
1259 else if ((type == MotionNotify) && deliveries)
1260 inputInfo.pointer->valuator->motionHintWindow = pWin;
1264 if (((type == DeviceMotionNotify) || (type == DeviceButtonPress)) &&
1266 CheckDeviceGrabAndHintWindow (pWin, type,
1267 (deviceKeyButtonPointer*) pEvents,
1268 grab, client, deliveryMask);
1273 return nondeliveries;
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.
1282 MaybeDeliverEventsToClient(pWin, pEvents, count, filter, dontClient)
1283 register WindowPtr pWin;
1287 ClientPtr dontClient;
1289 register OtherClients *other;
1291 if (pWin->eventMask & filter)
1293 if (wClient(pWin) == dontClient)
1295 return TryClientEvents(wClient(pWin), pEvents, count,
1296 pWin->eventMask, filter, NullGrab);
1298 for (other = wOtherClients(pWin); other; other = other->next)
1300 if (other->mask & filter)
1302 if (SameClient(other, dontClient))
1304 return TryClientEvents(rClient(other), pEvents, count,
1305 other->mask, filter, NullGrab);
1312 #if NeedFunctionPrototypes
1313 FixUpEventFromWindow(
1319 FixUpEventFromWindow(xE, pWin, child, calcChild)
1328 WindowPtr w=spriteTrace[spriteTraceGood-1];
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. */
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. */
1346 if (w->parent == pWin)
1348 child = w->drawable.id;
1354 xE->u.keyButtonPointer.root = ROOT->drawable.id;
1355 xE->u.keyButtonPointer.event = pWin->drawable.id;
1356 if (sprite.hot.pScreen == pWin->drawable.pScreen)
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;
1367 xE->u.keyButtonPointer.sameScreen = xFalse;
1368 xE->u.keyButtonPointer.child = None;
1369 xE->u.keyButtonPointer.eventX = 0;
1370 xE->u.keyButtonPointer.eventY = 0;
1375 DeliverDeviceEvents(pWin, xE, grab, stopAt, dev, count)
1376 register WindowPtr pWin, stopAt;
1377 register xEvent *xE;
1382 Window child = None;
1383 int type = xE->u.u.type;
1384 Mask filter = filters[type];
1387 if (type & EXTENSION_EVENT_BASE)
1389 register OtherInputMasks *inputMasks;
1390 int mskidx = dev->id;
1392 inputMasks = wOtherInputMasks(pWin);
1393 if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx]))
1397 if (inputMasks && (inputMasks->inputEvents[mskidx] & filter))
1399 FixUpEventFromWindow(xE, pWin, child, FALSE);
1400 deliveries = DeliverEventsToWindow(pWin, xE, count, filter,
1405 if ((deliveries < 0) ||
1408 (filter & inputMasks->dontPropagateMask[mskidx])))
1410 child = pWin->drawable.id;
1411 pWin = pWin->parent;
1413 inputMasks = wOtherInputMasks(pWin);
1418 if (!(filter & pWin->deliverableEvents))
1422 if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter)
1424 FixUpEventFromWindow(xE, pWin, child, FALSE);
1425 deliveries = DeliverEventsToWindow(pWin, xE, count, filter,
1430 if ((deliveries < 0) ||
1432 (filter & wDontPropagateMask(pWin)))
1434 child = pWin->drawable.id;
1435 pWin = pWin->parent;
1441 /* not useful for events that propagate up the tree or extension events */
1443 DeliverEvents(pWin, xE, count, otherParent)
1444 register WindowPtr pWin, otherParent;
1445 register xEvent *xE;
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,
1462 xE->u.destroyNotify.event = pWin->parent->drawable.id;
1463 deliveries += DeliverEventsToWindow(pWin->parent, xE, count,
1464 SubstructureNotifyMask, NullGrab,
1466 if (xE->u.u.type == ReparentNotify)
1468 xE->u.destroyNotify.event = otherParent->drawable.id;
1469 deliveries += DeliverEventsToWindow(otherParent, xE, count,
1470 SubstructureNotifyMask,
1478 #if NeedFunctionPrototypes
1479 XYToWindow(int x, int y)
1485 register WindowPtr pWin;
1490 spriteTraceGood = 1; /* root window still there */
1491 pWin = ROOT->firstChild;
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))
1502 /* When a window is shaped, a further check
1503 * is made to see if the point is inside
1506 && (!wBoundingShape(pWin) ||
1507 POINT_IN_REGION(pWin->drawable.pScreen,
1508 &pWin->borderSize, x, y, &box))
1512 if (spriteTraceGood >= spriteTraceSize)
1514 spriteTraceSize += 10;
1515 Must_have_memory = TRUE; /* XXX */
1516 spriteTrace = (WindowPtr *)xrealloc(
1517 spriteTrace, spriteTraceSize*sizeof(WindowPtr));
1518 Must_have_memory = FALSE; /* XXX */
1520 spriteTrace[spriteTraceGood++] = pWin;
1521 pWin = pWin->firstChild;
1524 pWin = pWin->nextSib;
1526 return spriteTrace[spriteTraceGood-1];
1530 #if NeedFunctionPrototypes
1531 CheckMotion(xEvent *xE)
1537 WindowPtr prevSpriteWin = sprite.win;
1539 if (xE && !syncEvents.playingEvents)
1541 if (sprite.hot.pScreen != sprite.hotPhys.pScreen)
1543 sprite.hot.pScreen = sprite.hotPhys.pScreen;
1544 ROOT = WindowTable[sprite.hot.pScreen->myNum];
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;
1557 if (sprite.hotShape)
1558 ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y);
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;
1570 sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y);
1572 if (!(sprite.win->deliverableEvents &
1573 Motion_Filter(inputInfo.pointer->button))
1574 !syncEvents.playingEvents)
1576 /* XXX Do PointerNonInterestBox here */
1579 if (sprite.win != prevSpriteWin)
1581 if (prevSpriteWin != NullWindow) {
1583 UpdateCurrentTimeIf();
1584 DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal);
1593 WindowsRestructured()
1595 (void) CheckMotion((xEvent *)NULL);
1599 DefineInitialRootWindow(win)
1600 register WindowPtr win;
1602 register ScreenPtr pScreen = win->drawable.pScreen;
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;
1611 sprite.current = wCursor (win);
1612 spriteTraceGood = 1;
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);
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.
1631 WindowHasNewCursor(pWin)
1638 NewCurrentScreen(newScreen, x, y)
1639 ScreenPtr newScreen;
1642 sprite.hotPhys.x = x;
1643 sprite.hotPhys.y = y;
1644 if (newScreen != sprite.hotPhys.pScreen)
1645 ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE);
1649 ProcWarpPointer(client)
1652 WindowPtr dest = NULL;
1654 ScreenPtr newScreen;
1656 REQUEST(xWarpPointerReq);
1658 REQUEST_SIZE_MATCH(xWarpPointerReq);
1659 if (stuff->dstWid != None)
1661 dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess);
1665 x = sprite.hotPhys.x;
1666 y = sprite.hotPhys.y;
1667 if (stuff->srcWid != None)
1670 WindowPtr source = SecurityLookupWindow(stuff->srcWid, client,
1671 SecurityReadAccess);
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))
1688 x = dest->drawable.x;
1689 y = dest->drawable.y;
1690 newScreen = dest->drawable.pScreen;
1693 newScreen = sprite.hotPhys.pScreen;
1698 else if (x >= newScreen->width)
1699 x = newScreen->width - 1;
1702 else if (y >= newScreen->height)
1703 y = newScreen->height - 1;
1705 if (newScreen == sprite.hotPhys.pScreen)
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;
1716 if (sprite.hotShape)
1717 ConfineToShape(sprite.hotShape, &x, &y);
1719 (*newScreen->SetCursorPosition)(newScreen, x, y, TRUE);
1721 else if (!PointerConfinedToScreen())
1723 NewCurrentScreen(newScreen, x, y);
1728 /* "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
1729 passive grab set on the window to be activated. */
1732 #if NeedFunctionPrototypes
1733 CheckPassiveGrabsOnWindow(
1735 register DeviceIntPtr device,
1736 register xEvent *xE,
1739 CheckPassiveGrabsOnWindow(pWin, device, xE, count)
1741 register DeviceIntPtr device;
1742 register xEvent *xE;
1746 register GrabPtr grab = wPassiveGrabs(pWin);
1748 register xEvent *dxE;
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)
1764 gdev= grab->modifierDevice;
1765 xkbi= gdev->key->xkbInfo;
1767 tempGrab.modifierDevice = grab->modifierDevice;
1768 if (device == grab->modifierDevice &&
1769 (xE->u.u.type == KeyPress
1771 || xE->u.u.type == DeviceKeyPress
1774 tempGrab.modifiersDetail.exact =
1776 (noXkbExtension?gdev->key->prev_state:xkbi->state.grab_mods);
1778 grab->modifierDevice->key->prev_state;
1781 tempGrab.modifiersDetail.exact =
1783 (noXkbExtension ? gdev->key->state : xkbi->state.grab_mods);
1785 grab->modifierDevice->key->state;
1787 if (GrabMatchesSecond(&tempGrab, grab) &&
1788 (!grab->confineTo ||
1789 (grab->confineTo->realized &&
1790 REGION_NOTEMPTY( grab->confineTo->drawable.pScreen,
1791 &grab->confineTo->borderSize))))
1794 if (!SecurityCheckDeviceAccess(wClient(pWin), device, FALSE))
1798 if (!noXkbExtension) {
1799 xE->u.keyButtonPointer.state &= 0x1f00;
1800 xE->u.keyButtonPointer.state |=
1801 tempGrab.modifiersDetail.exact&(~0x1f00);
1804 (*device->ActivateGrab)(device, grab, currentTime, TRUE);
1806 FixUpEventFromWindow(xE, grab->window, None, TRUE);
1808 (void) TryClientEvents(rClient(grab), xE, count,
1809 filters[xE->u.u.type],
1810 filters[xE->u.u.type], grab);
1812 if (device->sync.state == FROZEN_NO_EVENT)
1814 if (device->sync.evcount < count)
1816 Must_have_memory = TRUE; /* XXX */
1817 device->sync.event = (xEvent *)xrealloc(device->sync.event,
1820 Must_have_memory = FALSE; /* XXX */
1822 device->sync.evcount = count;
1823 for (dxE = device->sync.event; --count >= 0; dxE++, xE++)
1825 device->sync.state = FROZEN_WITH_EVENT;
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
1847 CheckDeviceGrabs(device, xE, checkFirst, count)
1848 register DeviceIntPtr device;
1849 register xEvent *xE;
1854 register WindowPtr pWin;
1855 register FocusClassPtr focus = device->focus;
1857 if ((xE->u.u.type == ButtonPress
1859 || xE->u.u.type == DeviceButtonPress
1861 ) && device->button->buttonsDown != 1)
1868 for (; i < focus->traceGood; i++)
1870 pWin = focus->trace[i];
1871 if (pWin->optional &&
1872 CheckPassiveGrabsOnWindow(pWin, device, xE, count))
1876 if ((focus->win == NoneWin) ||
1877 (i >= spriteTraceGood) ||
1878 ((i > checkFirst) && (pWin != spriteTrace[i-1])))
1882 for (; i < spriteTraceGood; i++)
1884 pWin = spriteTrace[i];
1885 if (pWin->optional &&
1886 CheckPassiveGrabsOnWindow(pWin, device, xE, count))
1894 DeliverFocusedEvent(keybd, xE, window, count)
1900 WindowPtr focus = keybd->focus->win;
1903 if (focus == FollowKeyboardWin)
1904 focus = inputInfo.keyboard->focus->win;
1907 if (focus == PointerRootWin)
1909 DeliverDeviceEvents(window, xE, NullGrab, NullWindow, keybd, count);
1912 if ((focus == window) || IsParent(focus, window))
1914 if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count))
1917 /* just deliver it to the focus window */
1918 FixUpEventFromWindow(xE, focus, None, FALSE);
1919 if (xE->u.u.type & EXTENSION_EVENT_BASE)
1921 (void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type],
1926 DeliverGrabbedEvent(xE, thisDev, deactivateGrab, count)
1927 register xEvent *xE;
1928 register DeviceIntPtr thisDev;
1929 Bool deactivateGrab;
1932 register GrabPtr grab = thisDev->grab;
1934 register DeviceIntPtr dev;
1935 register xEvent *dxE;
1937 if (grab->ownerEvents)
1943 focus = thisDev->focus->win;
1944 if (focus == FollowKeyboardWin)
1945 focus = inputInfo.keyboard->focus->win;
1948 focus = PointerRootWin;
1949 if (focus == PointerRootWin)
1950 deliveries = DeliverDeviceEvents(sprite.win, xE, grab, NullWindow,
1952 else if (focus && (focus == sprite.win || IsParent(focus, sprite.win)))
1953 deliveries = DeliverDeviceEvents(sprite.win, xE, grab, focus,
1956 deliveries = DeliverDeviceEvents(focus, xE, grab, focus,
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
1967 || xE->u.u.type == DeviceMotionNotify
1970 thisDev->valuator->motionHintWindow = grab->window;
1972 if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify
1974 && xE->u.u.type != DeviceMotionNotify
1977 switch (thisDev->sync.state)
1979 case FREEZE_BOTH_NEXT_EVENT:
1980 for (dev = inputInfo.devices; dev; dev = dev->next)
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;
1990 dev->sync.other = thisDev->grab;
1993 case FREEZE_NEXT_EVENT:
1994 thisDev->sync.state = FROZEN_WITH_EVENT;
1995 FreezeThaw(thisDev, TRUE);
1996 if (thisDev->sync.evcount < count)
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 */
2003 thisDev->sync.evcount = count;
2004 for (dxE = thisDev->sync.event; --count >= 0; dxE++, xE++)
2012 CoreProcessKeyboardEvent (xE, keybd, count)
2014 ProcessKeyboardEvent (xE, keybd, count)
2016 register xEvent *xE;
2017 register DeviceIntPtr keybd;
2021 register BYTE *kptr;
2023 register CARD8 modifiers;
2024 register CARD16 mask;
2025 GrabPtr grab = keybd->grab;
2026 Bool deactivateGrab = FALSE;
2027 register KeyClassPtr keyc = keybd->key;
2029 if (!syncEvents.playingEvents)
2032 if (DeviceEventCallback)
2034 DeviceEventInfoRec eventinfo;
2035 eventinfo.events = xE;
2036 eventinfo.count = count;
2037 CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
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];
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"));
2055 switch (xE->u.u.type)
2058 if (*kptr & bit) /* allow ddx to generate multiple downs */
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);
2070 inputInfo.pointer->valuator->motionHintWindow = NullWindow;
2072 keyc->prev_state = keyc->state;
2073 for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
2075 if (mask & modifiers)
2077 /* This key affects modifier "i" */
2078 keyc->modifierKeyCount[i]++;
2079 keyc->state |= mask;
2083 if (!grab && CheckDeviceGrabs(keybd, xE, 0, count))
2085 keybd->activatingKey = key;
2090 if (!(*kptr & bit)) /* guard against duplicates */
2092 inputInfo.pointer->valuator->motionHintWindow = NullWindow;
2094 keyc->prev_state = keyc->state;
2095 for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
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;
2106 if (keybd->fromPassiveGrab && (key == keybd->activatingKey))
2107 deactivateGrab = TRUE;
2110 FatalError("Impossible keyboard event");
2113 DeliverGrabbedEvent(xE, keybd, deactivateGrab, count);
2115 DeliverFocusedEvent(keybd, xE, sprite.win, count);
2117 (*keybd->DeactivateGrab)(keybd);
2122 CoreProcessPointerEvent (xE, mouse, count)
2124 ProcessPointerEvent (xE, mouse, count)
2126 register xEvent *xE;
2127 register DeviceIntPtr mouse;
2130 register GrabPtr grab = mouse->grab;
2131 Bool deactivateGrab = FALSE;
2132 register ButtonClassPtr butc = mouse->button;
2134 XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo;
2137 if (!syncEvents.playingEvents)
2139 xE->u.keyButtonPointer.state = (butc->state | (
2142 inputInfo.keyboard->key->state :
2143 xkbi->state.grab_mods)
2145 inputInfo.keyboard->key->state
2150 if (DeviceEventCallback)
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);
2162 if (xE->u.u.type != MotionNotify)
2165 register BYTE *kptr;
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)
2176 mouse->valuator->motionHintWindow = NullWindow;
2177 butc->buttonsDown++;
2178 butc->motionMask = ButtonMotionMask;
2180 xE->u.u.detail = butc->map[key];
2181 if (xE->u.u.detail == 0)
2183 if (xE->u.u.detail <= 5)
2184 butc->state |= (Button1Mask >> 1) << xE->u.u.detail;
2185 filters[MotionNotify] = Motion_Filter(butc);
2187 if (CheckDeviceGrabs(mouse, xE, 0, count))
2191 mouse->valuator->motionHintWindow = NullWindow;
2192 if (!--butc->buttonsDown)
2193 butc->motionMask = 0;
2195 xE->u.u.detail = butc->map[key];
2196 if (xE->u.u.detail == 0)
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;
2205 FatalError("bogus pointer event from ddx");
2208 else if (!CheckMotion(xE))
2211 DeliverGrabbedEvent(xE, mouse, deactivateGrab, count);
2213 DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow,
2216 (*mouse->DeactivateGrab)(mouse);
2219 #define AtMostOneClient \
2220 (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
2223 RecalculateDeliverableEvents(pWin)
2224 register WindowPtr pWin;
2226 register OtherClients *others;
2227 register WindowPtr pChild;
2232 if (pChild->optional)
2234 pChild->optional->otherEventMasks = 0;
2235 for (others = wOtherClients(pChild); others; others = others->next)
2237 pChild->optional->otherEventMasks |= others->mask;
2240 pChild->deliverableEvents = pChild->eventMask|
2241 wOtherEventMasks(pChild);
2243 pChild->deliverableEvents |=
2244 (pChild->parent->deliverableEvents &
2245 ~wDontPropagateMask(pChild) & PropagateMask);
2246 if (pChild->firstChild)
2248 pChild = pChild->firstChild;
2251 while (!pChild->nextSib && (pChild != pWin))
2252 pChild = pChild->parent;
2255 pChild = pChild->nextSib;
2260 OtherClientGone(value, id)
2261 pointer value; /* must conform to DeleteType */
2264 register OtherClientsPtr other, prev;
2265 register WindowPtr pWin = (WindowPtr)value;
2268 for (other = wOtherClients(pWin); other; other = other->next)
2270 if (other->resource == id)
2273 prev->next = other->next;
2276 if (!(pWin->optional->otherClients = other->next))
2277 CheckWindowOptionalNeed (pWin);
2280 RecalculateDeliverableEvents(pWin);
2285 FatalError("client not on event list");
2287 return -1; /* make compiler happy */
2291 EventSelectForWindow(pWin, client, mask)
2292 register WindowPtr pWin;
2293 register ClientPtr client;
2297 OtherClients * others;
2299 if (mask & ~AllEventMasks)
2301 client->errorValue = mask;
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
2312 if ((wClient(pWin) != client) && (check & pWin->eventMask))
2314 for (others = wOtherClients (pWin); others; others = others->next)
2316 if (!SameClient(others, client) && (check & others->mask))
2320 if (wClient (pWin) == client)
2322 check = pWin->eventMask;
2325 (mask & ~SGIMiscSpecialDestroyMask) | (pWin->eventMask & SGIMiscSpecialDestroyMask);
2327 pWin->eventMask = mask;
2332 for (others = wOtherClients (pWin); others; others = others->next)
2334 if (SameClient(others, client))
2336 check = others->mask;
2338 mask = (mask & ~SGIMiscSpecialDestroyMask) | (others->mask & SGIMiscSpecialDestroyMask);
2342 FreeResource(others->resource, RT_NONE);
2346 others->mask = mask;
2351 if (!pWin->optional && !MakeWindowOptional (pWin))
2353 others = (OtherClients *) xalloc(sizeof(OtherClients));
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))
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);
2375 EventSuppressForWindow(pWin, client, mask, checkOptional)
2376 register WindowPtr pWin;
2377 register ClientPtr client;
2379 Bool *checkOptional;
2381 register int i, free;
2383 if ((mask & ~PropagateMask) && !permitOldBugs)
2385 client->errorValue = mask;
2388 if (pWin->dontPropagate)
2389 DontPropagateRefCnts[pWin->dontPropagate]--;
2394 for (i = DNPMCOUNT, free = 0; --i > 0; )
2396 if (!DontPropagateRefCnts[i])
2398 else if (mask == DontPropagateMasks[i])
2404 DontPropagateMasks[i] = mask;
2409 pWin->dontPropagate = i;
2411 DontPropagateRefCnts[i]++;
2414 pWin->optional->dontPropagateMask = mask;
2415 *checkOptional = TRUE;
2420 if (!pWin->optional && !MakeWindowOptional (pWin))
2422 if (pWin->dontPropagate)
2423 DontPropagateRefCnts[pWin->dontPropagate]++;
2426 pWin->dontPropagate = 0;
2427 pWin->optional->dontPropagateMask = mask;
2429 RecalculateDeliverableEvents(pWin);
2434 #if NeedFunctionPrototypes
2436 register WindowPtr a,
2437 register WindowPtr b)
2439 CommonAncestor(a, b)
2440 register WindowPtr a, b;
2443 for (b = b->parent; b; b = b->parent)
2444 if (IsParent(b, a)) return b;
2449 #if NeedFunctionPrototypes
2454 register WindowPtr pWin,
2457 EnterLeaveEvent(type, mode, detail, pWin, child)
2458 int type, mode, detail;
2459 register WindowPtr pWin;
2464 register DeviceIntPtr keybd = inputInfo.keyboard;
2466 register DeviceIntPtr mouse = inputInfo.pointer;
2467 register GrabPtr grab = mouse->grab;
2470 if ((pWin == mouse->valuator->motionHintWindow) &&
2471 (detail != NotifyInferior))
2472 mouse->valuator->motionHintWindow = NullWindow;
2475 mask = (pWin == grab->window) ? grab->eventMask : 0;
2476 if (grab->ownerEvents)
2477 mask |= EventMaskForClient(pWin, rClient(grab));
2481 mask = pWin->eventMask | wOtherEventMasks(pWin);
2483 if (mask & filters[type])
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;
2497 if (!noXkbExtension) {
2498 event.u.enterLeave.state = mouse->button->state & 0x1f00;
2499 event.u.enterLeave.state |=
2500 XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
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;
2511 (void)TryClientEvents(rClient(grab), &event, 1, mask,
2512 filters[type], grab);
2514 (void)DeliverEventsToWindow(pWin, &event, 1, filters[type],
2517 if ((type == EnterNotify) && (mask & KeymapStateMask))
2522 ClientPtr client = grab ? rClient(grab)
2523 : clients[CLIENT_ID(pWin->drawable.id)];
2524 if (!SecurityCheckDeviceAccess(client, keybd, FALSE))
2526 bzero((char *)&ke.map[0], 31);
2530 memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31);
2531 ke.type = KeymapNotify;
2533 (void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask,
2534 KeymapStateMask, grab);
2536 (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1,
2537 KeymapStateMask, NullGrab, 0);
2542 #if NeedFunctionPrototypes
2543 EnterNotifies(WindowPtr ancestor, WindowPtr child, int mode, int detail)
2545 EnterNotifies(ancestor, child, mode, detail)
2546 WindowPtr ancestor, child;
2550 WindowPtr parent = child->parent;
2552 if (ancestor == parent)
2554 EnterNotifies(ancestor, parent, mode, detail);
2555 EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id);
2559 #if NeedFunctionPrototypes
2560 LeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail)
2562 LeaveNotifies(child, ancestor, mode, detail)
2563 WindowPtr child, ancestor;
2567 register WindowPtr pWin;
2569 if (ancestor == child)
2571 for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent)
2573 EnterLeaveEvent(LeaveNotify, mode, detail, pWin, child->drawable.id);
2579 #if NeedFunctionPrototypes
2580 DoEnterLeaveEvents(WindowPtr fromWin, WindowPtr toWin, int mode)
2582 DoEnterLeaveEvents(fromWin, toWin, mode)
2583 WindowPtr fromWin, toWin;
2587 if (fromWin == toWin)
2589 if (IsParent(fromWin, toWin))
2591 EnterLeaveEvent(LeaveNotify, mode, NotifyInferior, fromWin, None);
2592 EnterNotifies(fromWin, toWin, mode, NotifyVirtual);
2593 EnterLeaveEvent(EnterNotify, mode, NotifyAncestor, toWin, None);
2595 else if (IsParent(toWin, fromWin))
2597 EnterLeaveEvent(LeaveNotify, mode, NotifyAncestor, fromWin, None);
2598 LeaveNotifies(fromWin, toWin, mode, NotifyVirtual);
2599 EnterLeaveEvent(EnterNotify, mode, NotifyInferior, toWin, None);
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);
2613 #if NeedFunctionPrototypes
2614 FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, register WindowPtr pWin)
2616 FocusEvent(dev, type, mode, detail, pWin)
2618 int type, mode, detail;
2619 register WindowPtr pWin;
2625 if (dev != inputInfo.keyboard)
2627 DeviceFocusEvent(dev, type, mode, detail, pWin);
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,
2637 if ((type == FocusIn) &&
2638 ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
2642 ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)];
2643 if (!SecurityCheckDeviceAccess(client, dev, FALSE))
2645 bzero((char *)&ke.map[0], 31);
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);
2657 * recursive because it is easier
2658 * no-op if child not descended from ancestor
2661 #if NeedFunctionPrototypes
2664 WindowPtr ancestor, WindowPtr child, WindowPtr skipChild,
2665 int mode, int detail,
2668 FocusInEvents(dev, ancestor, child, skipChild, mode, detail, doAncestor)
2670 WindowPtr ancestor, child, skipChild;
2675 if (child == NullWindow)
2676 return ancestor == NullWindow;
2677 if (ancestor == child)
2680 FocusEvent(dev, FocusIn, mode, detail, child);
2683 if (FocusInEvents(dev, ancestor, child->parent, skipChild, mode, detail,
2686 if (child != skipChild)
2687 FocusEvent(dev, FocusIn, mode, detail, child);
2693 /* dies horribly if ancestor is not an ancestor of child */
2695 #if NeedFunctionPrototypes
2698 WindowPtr child, WindowPtr ancestor,
2699 int mode, int detail,
2702 FocusOutEvents(dev, child, ancestor, mode, detail, doAncestor)
2704 WindowPtr child, ancestor;
2710 register WindowPtr pWin;
2712 for (pWin = child; pWin != ancestor; pWin = pWin->parent)
2713 FocusEvent(dev, FocusOut, mode, detail, pWin);
2715 FocusEvent(dev, FocusOut, mode, detail, ancestor);
2719 DoFocusEvents(dev, fromWin, toWin, mode)
2721 WindowPtr fromWin, toWin;
2724 int out, in; /* for holding details for to/from
2728 if (fromWin == toWin)
2730 out = (fromWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot;
2731 in = (toWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot;
2732 /* wrong values if neither, but then not referenced */
2734 if ((toWin == NullWindow) || (toWin == PointerRootWin))
2736 if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
2738 if (fromWin == PointerRootWin)
2739 FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
2741 /* Notify all the roots */
2742 for (i=0; i<screenInfo.numScreens; i++)
2743 FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
2747 if (IsParent(fromWin, sprite.win))
2748 FocusOutEvents(dev, sprite.win, fromWin, mode, NotifyPointer,
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);
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);
2764 if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
2766 if (fromWin == PointerRootWin)
2767 FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
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);
2781 if (IsParent(toWin, fromWin))
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);
2795 if (IsParent(fromWin, toWin))
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);
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);
2833 #if NeedFunctionPrototypes
2842 SetInputFocus(client, dev, focusID, revertTo, ctime, followOK)
2851 register FocusClassPtr focus;
2852 register WindowPtr focusWin;
2856 UpdateCurrentTime();
2857 if ((revertTo != RevertToParent) &&
2858 (revertTo != RevertToPointerRoot) &&
2859 (revertTo != RevertToNone) &&
2860 ((revertTo != RevertToFollowKeyboard) || !followOK))
2862 client->errorValue = revertTo;
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)))
2875 /* It is a match error to try to set the input focus to an
2876 unviewable window. */
2878 if(!focusWin->realized)
2882 if ((CompareTimeStamps(time, currentTime) == LATER) ||
2883 (CompareTimeStamps(time, focus->time) == EARLIER))
2885 mode = (dev->grab) ? NotifyWhileGrabbed : NotifyNormal;
2886 if (focus->win == FollowKeyboardWin)
2887 DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode);
2889 DoFocusEvents(dev, focus->win, focusWin, mode);
2891 focus->revert = revertTo;
2892 if (focusID == FollowKeyboard)
2893 focus->win = FollowKeyboardWin;
2895 focus->win = focusWin;
2896 if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
2897 focus->traceGood = 0;
2901 register WindowPtr pWin;
2903 for (pWin = focusWin; pWin; pWin = pWin->parent) depth++;
2904 if (depth > focus->traceSize)
2906 focus->traceSize = depth+1;
2907 Must_have_memory = TRUE; /* XXX */
2908 focus->trace = (WindowPtr *)xrealloc(focus->trace,
2911 Must_have_memory = FALSE; /* XXX */
2913 focus->traceGood = depth;
2914 for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
2915 focus->trace[depth] = pWin;
2921 ProcSetInputFocus(client)
2924 REQUEST(xSetInputFocusReq);
2926 REQUEST_SIZE_MATCH(xSetInputFocusReq);
2928 if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE))
2931 return SetInputFocus(client, inputInfo.keyboard, stuff->focus,
2932 stuff->revertTo, stuff->time, FALSE);
2936 ProcGetInputFocus(client)
2939 xGetInputFocusReply rep;
2940 FocusClassPtr focus = inputInfo.keyboard->focus;
2942 REQUEST_SIZE_MATCH(xReq);
2945 rep.sequenceNumber = client->sequence;
2946 if (focus->win == NoneWin)
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);
2957 ProcGrabPointer(client)
2960 xGrabPointerReply rep;
2961 DeviceIntPtr device = inputInfo.pointer;
2963 WindowPtr pWin, confineTo;
2964 CursorPtr cursor, oldCursor;
2965 REQUEST(xGrabPointerReq);
2968 REQUEST_SIZE_MATCH(xGrabPointerReq);
2969 UpdateCurrentTime();
2970 if ((stuff->pointerMode != GrabModeSync) &&
2971 (stuff->pointerMode != GrabModeAsync))
2973 client->errorValue = stuff->pointerMode;
2976 if ((stuff->keyboardMode != GrabModeSync) &&
2977 (stuff->keyboardMode != GrabModeAsync))
2979 client->errorValue = stuff->keyboardMode;
2982 if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
2984 client->errorValue = stuff->ownerEvents;
2987 if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs)
2989 client->errorValue = stuff->eventMask;
2992 pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess);
2995 if (stuff->confineTo == None)
2996 confineTo = NullWindow;
2999 confineTo = SecurityLookupWindow(stuff->confineTo, client,
3000 SecurityReadAccess);
3004 if (stuff->cursor == None)
3005 cursor = NullCursor;
3008 cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
3009 RT_CURSOR, SecurityReadAccess);
3012 client->errorValue = stuff->cursor;
3016 /* at this point, some sort of reply is guaranteed. */
3017 time = ClientTimeToServerTime(stuff->time);
3019 rep.sequenceNumber = client->sequence;
3021 grab = device->grab;
3022 if ((grab) && !SameClient(grab, client))
3023 rep.status = AlreadyGrabbed;
3024 else if ((!pWin->realized) ||
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;
3040 oldCursor = NullCursor;
3043 if (grab->confineTo && !confineTo)
3044 ConfineCursorToWindow(ROOT, FALSE, FALSE);
3045 oldCursor = grab->cursor;
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);
3058 FreeCursor (oldCursor, (Cursor)0);
3059 rep.status = GrabSuccess;
3061 WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
3066 ProcChangeActivePointerGrab(client)
3069 DeviceIntPtr device = inputInfo.pointer;
3070 register GrabPtr grab = device->grab;
3071 CursorPtr newCursor, oldCursor;
3072 REQUEST(xChangeActivePointerGrabReq);
3075 REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
3076 if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs)
3078 client->errorValue = stuff->eventMask;
3081 if (stuff->cursor == None)
3082 newCursor = NullCursor;
3085 newCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
3086 RT_CURSOR, SecurityReadAccess);
3089 client->errorValue = stuff->cursor;
3095 if (!SameClient(grab, client))
3097 time = ClientTimeToServerTime(stuff->time);
3098 if ((CompareTimeStamps(time, currentTime) == LATER) ||
3099 (CompareTimeStamps(time, device->grabTime) == EARLIER))
3101 oldCursor = grab->cursor;
3102 grab->cursor = newCursor;
3104 newCursor->refcnt++;
3107 FreeCursor(oldCursor, (Cursor)0);
3108 grab->eventMask = stuff->eventMask;
3113 ProcUngrabPointer(client)
3116 DeviceIntPtr device = inputInfo.pointer;
3119 REQUEST(xResourceReq);
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);
3133 GrabDevice(client, dev, this_mode, other_mode, grabWindow, ownerEvents, ctime,
3135 register ClientPtr client;
3136 register DeviceIntPtr dev;
3138 unsigned other_mode;
3140 unsigned ownerEvents;
3145 register WindowPtr pWin;
3146 register GrabPtr grab;
3149 UpdateCurrentTime();
3150 if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync))
3152 client->errorValue = this_mode;
3155 if ((other_mode != GrabModeSync) && (other_mode != GrabModeAsync))
3157 client->errorValue = other_mode;
3160 if ((ownerEvents != xFalse) && (ownerEvents != xTrue))
3162 client->errorValue = ownerEvents;
3165 pWin = SecurityLookupWindow(grabWindow, client, SecurityReadAccess);
3168 time = ClientTimeToServerTime(ctime);
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;
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;
3198 ProcGrabKeyboard(client)
3201 xGrabKeyboardReply rep;
3202 REQUEST(xGrabKeyboardReq);
3205 REQUEST_SIZE_MATCH(xGrabKeyboardReq);
3207 if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE))
3210 rep.status = AlreadyGrabbed;
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)
3221 rep.sequenceNumber = client->sequence;
3223 WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
3228 ProcUngrabKeyboard(client)
3231 DeviceIntPtr device = inputInfo.keyboard;
3234 REQUEST(xResourceReq);
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);
3248 ProcQueryPointer(client)
3251 xQueryPointerReply rep;
3253 REQUEST(xResourceReq);
3254 DeviceIntPtr mouse = inputInfo.pointer;
3256 REQUEST_SIZE_MATCH(xResourceReq);
3257 pWin = SecurityLookupWindow(stuff->id, client, SecurityReadAccess);
3260 if (mouse->valuator->motionHintWindow)
3261 MaybeStopHint(mouse, client);
3263 rep.sequenceNumber = client->sequence;
3264 rep.mask = mouse->button->state | inputInfo.keyboard->key->state;
3266 rep.root = (ROOT)->drawable.id;
3267 rep.rootX = sprite.hot.x;
3268 rep.rootY = sprite.hot.y;
3270 if (sprite.hot.pScreen == pWin->drawable.pScreen)
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)
3278 rep.child = t->drawable.id;
3284 rep.sameScreen = xFalse;
3288 WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
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)
3306 spriteTraceSize = 32;
3307 spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr));
3309 FatalError("failed to allocate spriteTrace");
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)
3325 QdEventPtr next = syncEvents.pending->next;
3326 xfree(syncEvents.pending);
3327 syncEvents.pending = next;
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++)
3338 DontPropagateMasks[i] = 0;
3339 DontPropagateRefCnts[i] = 0;
3344 ProcSendEvent(client)
3348 WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
3349 REQUEST(xSendEventReq);
3351 REQUEST_SIZE_MATCH(xSendEventReq);
3353 /* The client's event type must be a core event type or one defined by an
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)))
3361 client->errorValue = stuff->event.u.u.type;
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 &&
3370 client->errorValue = stuff->event.u.u.detail;
3373 if ((stuff->eventMask & ~AllEventMasks) && !permitOldBugs)
3375 client->errorValue = stuff->eventMask;
3379 if (stuff->destination == PointerWindow)
3381 else if (stuff->destination == InputFocus)
3383 WindowPtr inputFocus = inputInfo.keyboard->focus->win;
3385 if (inputFocus == NoneWin)
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)
3393 if (IsParent(inputFocus, sprite.win))
3395 effectiveFocus = inputFocus;
3399 effectiveFocus = pWin = inputFocus;
3402 pWin = SecurityLookupWindow(stuff->destination, client,
3403 SecurityReadAccess);
3406 if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue))
3408 client->errorValue = stuff->propagate;
3411 stuff->event.u.u.type |= 0x80;
3412 if (stuff->propagate)
3414 for (;pWin; pWin = pWin->parent)
3416 if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask,
3419 if (pWin == effectiveFocus)
3421 stuff->eventMask &= ~wDontPropagateMask(pWin);
3422 if (!stuff->eventMask)
3427 (void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask,
3433 ProcUngrabKey(client)
3436 REQUEST(xUngrabKeyReq);
3439 DeviceIntPtr keybd = inputInfo.keyboard;
3441 REQUEST_SIZE_MATCH(xUngrabKeyReq);
3442 pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess);
3445 if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) ||
3446 (stuff->key < keybd->key->curKeySyms.minKeyCode))
3447 && (stuff->key != AnyKey))
3449 client->errorValue = stuff->key;
3452 if ((stuff->modifiers != AnyModifier) &&
3453 (stuff->modifiers & ~AllModifiersMask))
3455 client->errorValue = stuff->modifiers;
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;
3469 if (!DeletePassiveGrabFromList(&tempGrab))
3479 REQUEST(xGrabKeyReq);
3481 DeviceIntPtr keybd = inputInfo.keyboard;
3483 REQUEST_SIZE_MATCH(xGrabKeyReq);
3484 if ((stuff->ownerEvents != xTrue) && (stuff->ownerEvents != xFalse))
3486 client->errorValue = stuff->ownerEvents;
3489 if ((stuff->pointerMode != GrabModeSync) &&
3490 (stuff->pointerMode != GrabModeAsync))
3492 client->errorValue = stuff->pointerMode;
3495 if ((stuff->keyboardMode != GrabModeSync) &&
3496 (stuff->keyboardMode != GrabModeAsync))
3498 client->errorValue = stuff->keyboardMode;
3501 if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) ||
3502 (stuff->key < keybd->key->curKeySyms.minKeyCode))
3503 && (stuff->key != AnyKey))
3505 client->errorValue = stuff->key;
3508 if ((stuff->modifiers != AnyModifier) &&
3509 (stuff->modifiers & ~AllModifiersMask))
3511 client->errorValue = stuff->modifiers;
3514 pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess);
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);
3524 return AddPassiveGrabToList(grab);
3528 ProcGrabButton(client)
3531 WindowPtr pWin, confineTo;
3532 REQUEST(xGrabButtonReq);
3536 REQUEST_SIZE_MATCH(xGrabButtonReq);
3537 if ((stuff->pointerMode != GrabModeSync) &&
3538 (stuff->pointerMode != GrabModeAsync))
3540 client->errorValue = stuff->pointerMode;
3543 if ((stuff->keyboardMode != GrabModeSync) &&
3544 (stuff->keyboardMode != GrabModeAsync))
3546 client->errorValue = stuff->keyboardMode;
3549 if ((stuff->modifiers != AnyModifier) &&
3550 (stuff->modifiers & ~AllModifiersMask))
3552 client->errorValue = stuff->modifiers;
3555 if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
3557 client->errorValue = stuff->ownerEvents;
3560 if (stuff->eventMask & ~PointerGrabMask)
3562 client->errorValue = stuff->eventMask;
3565 pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess);
3568 if (stuff->confineTo == None)
3569 confineTo = NullWindow;
3572 confineTo = SecurityLookupWindow(stuff->confineTo, client,
3573 SecurityReadAccess);
3577 if (stuff->cursor == None)
3578 cursor = NullCursor;
3581 cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
3582 RT_CURSOR, SecurityReadAccess);
3585 client->errorValue = stuff->cursor;
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);
3599 return AddPassiveGrabToList(grab);
3603 ProcUngrabButton(client)
3606 REQUEST(xUngrabButtonReq);
3610 REQUEST_SIZE_MATCH(xUngrabButtonReq);
3611 if ((stuff->modifiers != AnyModifier) &&
3612 (stuff->modifiers & ~AllModifiersMask))
3614 client->errorValue = stuff->modifiers;
3617 pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess);
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;
3631 if (!DeletePassiveGrabFromList(&tempGrab))
3637 DeleteWindowFromAnyEvents(pWin, freeResources)
3642 DeviceIntPtr mouse = inputInfo.pointer;
3643 DeviceIntPtr keybd = inputInfo.keyboard;
3644 FocusClassPtr focus = keybd->focus;
3649 /* Deactivate any grabs performed on this window, before making any
3650 input focus changes. */
3653 ((mouse->grab->window == pWin) || (mouse->grab->confineTo == pWin)))
3654 (*mouse->DeactivateGrab)(mouse);
3656 /* Deactivating a keyboard grab should cause focus events. */
3658 if (keybd->grab && (keybd->grab->window == pWin))
3659 (*keybd->DeactivateGrab)(keybd);
3661 /* If the focus window is a root window (ie. has no parent) then don't
3662 delete the focus from it. */
3664 if ((pWin == focus->win) && (pWin->parent != NullWindow))
3666 int focusEventMode = NotifyNormal;
3668 /* If a grab is in progress, then alter the mode of focus events. */
3671 focusEventMode = NotifyWhileGrabbed;
3673 switch (focus->revert)
3676 DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
3677 focus->win = NoneWin;
3678 focus->traceGood = 0;
3680 case RevertToParent:
3684 parent = parent->parent;
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
3694 || clients[CLIENT_ID(parent->drawable.id)]->clientGone
3697 DoFocusEvents(keybd, pWin, parent, focusEventMode);
3698 focus->win = parent;
3699 focus->revert = RevertToNone;
3701 case RevertToPointerRoot:
3702 DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode);
3703 focus->win = PointerRootWin;
3704 focus->traceGood = 0;
3709 if (mouse->valuator->motionHintWindow == pWin)
3710 mouse->valuator->motionHintWindow = NullWindow;
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);
3722 DeleteWindowFromAnyExtEvents(pWin, freeResources);
3726 /* Call this whenever some window at or below pWin has changed geometry */
3730 CheckCursorConfinement(pWin)
3733 GrabPtr grab = inputInfo.pointer->grab;
3734 WindowPtr confineTo;
3736 if (grab && (confineTo = grab->confineTo))
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);
3747 EventMaskForClient(pWin, client)
3751 register OtherClientsPtr other;
3753 if (wClient (pWin) == client)
3754 return pWin->eventMask;
3755 for (other = wOtherClients(pWin); other; other = other->next)
3757 if (SameClient(other, client))
3764 ProcRecolorCursor(client)
3770 REQUEST(xRecolorCursorReq);
3772 REQUEST_SIZE_MATCH(xRecolorCursorReq);
3773 pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
3774 RT_CURSOR, SecurityWriteAccess);
3777 client->errorValue = stuff->cursor;
3781 pCursor->foreRed = stuff->foreRed;
3782 pCursor->foreGreen = stuff->foreGreen;
3783 pCursor->foreBlue = stuff->foreBlue;
3785 pCursor->backRed = stuff->backRed;
3786 pCursor->backGreen = stuff->backGreen;
3787 pCursor->backBlue = stuff->backBlue;
3789 for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
3791 pscr = screenInfo.screens[nscr];
3792 ( *pscr->RecolorCursor)(pscr, pCursor,
3793 (pCursor == sprite.current) &&
3794 (pscr == sprite.hotPhys.pScreen));
3800 WriteEventsToClient(pClient, count, events)
3805 xEvent eventTo, *eventFrom;
3809 if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events)))
3815 EventInfoRec eventinfo;
3816 eventinfo.client = pClient;
3817 eventinfo.events = events;
3818 eventinfo.count = count;
3819 CallCallbacks(&EventCallback, (pointer)&eventinfo);
3821 if(pClient->swapped)
3823 for(i = 0; i < count; i++)
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);
3835 (void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events);