First import
[xorg_rtime.git] / xorg-server-1.4 / dix / events.c
blob7b4cab06d581e919a28f46bef2b126e8290c16b4
1 /************************************************************
3 Copyright 1987, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
26 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
28 All Rights Reserved
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted,
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in
34 supporting documentation, and that the name of Digital not be
35 used in advertising or publicity pertaining to distribution of the
36 software without specific, written prior permission.
38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44 SOFTWARE.
46 ********************************************************/
48 /* The panoramix components contained the following notice */
49 /*****************************************************************
51 Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
53 Permission is hereby granted, free of charge, to any person obtaining a copy
54 of this software and associated documentation files (the "Software"), to deal
55 in the Software without restriction, including without limitation the rights
56 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
57 copies of the Software.
59 The above copyright notice and this permission notice shall be included in
60 all copies or substantial portions of the Software.
62 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
65 DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
66 BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
67 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
68 IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
70 Except as contained in this notice, the name of Digital Equipment Corporation
71 shall not be used in advertising or otherwise to promote the sale, use or other
72 dealings in this Software without prior written authorization from Digital
73 Equipment Corporation.
75 ******************************************************************/
77 /*****************************************************************
79 Copyright 2003-2005 Sun Microsystems, Inc.
81 All rights reserved.
83 Permission is hereby granted, free of charge, to any person obtaining a
84 copy of this software and associated documentation files (the
85 "Software"), to deal in the Software without restriction, including
86 without limitation the rights to use, copy, modify, merge, publish,
87 distribute, and/or sell copies of the Software, and to permit persons
88 to whom the Software is furnished to do so, provided that the above
89 copyright notice(s) and this permission notice appear in all copies of
90 the Software and that both the above copyright notice(s) and this
91 permission notice appear in supporting documentation.
93 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
94 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
95 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
96 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
97 HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
98 INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
99 FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
100 NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
101 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
103 Except as contained in this notice, the name of a copyright holder
104 shall not be used in advertising or otherwise to promote the sale, use
105 or other dealings in this Software without prior written authorization
106 of the copyright holder.
108 ******************************************************************/
110 /** @file
111 * This file handles event delivery and a big part of the server-side protocol
112 * handling (the parts for input devices).
115 #ifdef HAVE_DIX_CONFIG_H
116 #include <dix-config.h>
117 #endif
119 #include <X11/X.h>
120 #include <X11/keysym.h>
121 #include "misc.h"
122 #include "resource.h"
123 #define NEED_EVENTS
124 #define NEED_REPLIES
125 #include <X11/Xproto.h>
126 #include "windowstr.h"
127 #include "inputstr.h"
128 #include "scrnintstr.h"
129 #include "cursorstr.h"
131 #include "dixstruct.h"
132 #ifdef PANORAMIX
133 #include "panoramiX.h"
134 #include "panoramiXsrv.h"
135 #endif
136 #include "globals.h"
138 #ifdef XKB
139 #include <X11/extensions/XKBproto.h>
140 #include <xkbsrv.h>
141 extern Bool XkbFilterEvents(ClientPtr, int, xEvent *);
142 #endif
144 #include "xace.h"
146 #ifdef XSERVER_DTRACE
147 #include <sys/types.h>
148 typedef const char *string;
149 #include "Xserver-dtrace.h"
150 #endif
152 #ifdef XEVIE
153 extern WindowPtr *WindowTable;
154 extern int xevieFlag;
155 extern int xevieClientIndex;
156 extern DeviceIntPtr xeviemouse;
157 extern DeviceIntPtr xeviekb;
158 extern Mask xevieMask;
159 extern Mask xevieFilters[128];
160 extern int xevieEventSent;
161 extern int xevieKBEventSent;
162 int xeviegrabState = 0;
163 #endif
165 #include <X11/extensions/XIproto.h>
166 #include "exglobals.h"
167 #include "exevents.h"
168 #include "exglobals.h"
169 #include "extnsionst.h"
171 #include "dixevents.h"
172 #include "dixgrabs.h"
173 #include "dispatch.h"
175 * Extension events type numbering starts at EXTENSION_EVENT_BASE.
177 #define EXTENSION_EVENT_BASE 64
179 #define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */
180 #define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
181 #define AllButtonsMask ( \
182 Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
183 #define MotionMask ( \
184 PointerMotionMask | Button1MotionMask | \
185 Button2MotionMask | Button3MotionMask | Button4MotionMask | \
186 Button5MotionMask | ButtonMotionMask )
187 #define PropagateMask ( \
188 KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
189 MotionMask )
190 #define PointerGrabMask ( \
191 ButtonPressMask | ButtonReleaseMask | \
192 EnterWindowMask | LeaveWindowMask | \
193 PointerMotionHintMask | KeymapStateMask | \
194 MotionMask )
195 #define AllModifiersMask ( \
196 ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
197 Mod3Mask | Mod4Mask | Mod5Mask )
198 #define AllEventMasks (lastEventMask|(lastEventMask-1))
200 * The following relies on the fact that the Button<n>MotionMasks are equal
201 * to the corresponding Button<n>Masks from the current modifier/button state.
203 #define Motion_Filter(class) (PointerMotionMask | \
204 (class)->state | (class)->motionMask)
207 #define WID(w) ((w) ? ((w)->drawable.id) : 0)
209 #define XE_KBPTR (xE->u.keyButtonPointer)
212 #define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
214 _X_EXPORT CallbackListPtr EventCallback;
215 _X_EXPORT CallbackListPtr DeviceEventCallback;
217 #define DNPMCOUNT 8
219 Mask DontPropagateMasks[DNPMCOUNT];
220 static int DontPropagateRefCnts[DNPMCOUNT];
223 * Main input device struct.
224 * inputInfo.pointer
225 * is the core pointer. Referred to as "virtual core pointer", "VCP",
226 * "core pointer" or inputInfo.pointer. There is exactly one core pointer,
227 * but multiple devices may send core events. If a device generates core
228 * events, those events will appear to originate from the core pointer.
230 * inputInfo.keyboard
231 * is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
232 * See inputInfo.pointer.
234 * inputInfo.devices
235 * linked list containing all devices including VCK and VCP. The VCK will
236 * always be the first entry, the VCP the second entry in the device list.
238 * inputInfo.off_devices
239 * Devices that have not been initialized and are thus turned off.
241 * inputInfo.numDevices
242 * Total number of devices.
244 _X_EXPORT InputInfo inputInfo;
246 static struct {
247 QdEventPtr pending, *pendtail;
248 DeviceIntPtr replayDev; /* kludgy rock to put flag for */
249 WindowPtr replayWin; /* ComputeFreezes */
250 Bool playingEvents;
251 TimeStamp time;
252 } syncEvents;
255 * The window trace information is used to avoid having to compute all the
256 * windows between the root and the current pointer window each time a button
257 * or key goes down. The grabs on each of those windows must be checked.
259 * @see XYToWindow() for a documentation on how the array is set up.
261 static WindowPtr *spriteTrace = (WindowPtr *)NULL;
262 #define ROOT spriteTrace[0]
263 static int spriteTraceSize = 0;
264 static int spriteTraceGood;
267 * DIX sprite information. This is the sprite as seen from the DIX. It does
268 * not represent the actual sprite rendered to the screen.
271 static struct {
272 CursorPtr current;
273 BoxRec hotLimits; /* logical constraints of hot spot */
274 Bool confined; /* confined to screen */
275 #if defined(SHAPE) || defined(PANORAMIX)
276 RegionPtr hotShape; /* additional logical shape constraint */
277 #endif
278 BoxRec physLimits; /* physical constraints of hot spot */
279 WindowPtr win; /* window of logical position */
280 HotSpot hot; /* logical pointer position */
281 HotSpot hotPhys; /* physical pointer position */
282 #ifdef PANORAMIX
283 ScreenPtr screen; /* all others are in Screen 0 coordinates */
284 RegionRec Reg1; /* Region 1 for confining motion */
285 RegionRec Reg2; /* Region 2 for confining virtual motion */
286 WindowPtr windows[MAXSCREENS];
287 WindowPtr confineWin; /* confine window */
288 #endif
289 } sprite; /* info about the cursor sprite */
291 #ifdef XEVIE
292 _X_EXPORT WindowPtr xeviewin;
293 _X_EXPORT HotSpot xeviehot;
294 #endif
296 static void DoEnterLeaveEvents(
297 WindowPtr fromWin,
298 WindowPtr toWin,
299 int mode
302 static WindowPtr XYToWindow(
303 int x,
304 int y
308 * Max event opcode.
310 extern int lastEvent;
312 static Mask lastEventMask;
314 #ifdef XINPUT
315 extern int DeviceMotionNotify;
316 #endif
318 #define CantBeFiltered NoEventMask
319 static Mask filters[128] =
321 NoSuchEvent, /* 0 */
322 NoSuchEvent, /* 1 */
323 KeyPressMask, /* KeyPress */
324 KeyReleaseMask, /* KeyRelease */
325 ButtonPressMask, /* ButtonPress */
326 ButtonReleaseMask, /* ButtonRelease */
327 PointerMotionMask, /* MotionNotify (initial state) */
328 EnterWindowMask, /* EnterNotify */
329 LeaveWindowMask, /* LeaveNotify */
330 FocusChangeMask, /* FocusIn */
331 FocusChangeMask, /* FocusOut */
332 KeymapStateMask, /* KeymapNotify */
333 ExposureMask, /* Expose */
334 CantBeFiltered, /* GraphicsExpose */
335 CantBeFiltered, /* NoExpose */
336 VisibilityChangeMask, /* VisibilityNotify */
337 SubstructureNotifyMask, /* CreateNotify */
338 StructureAndSubMask, /* DestroyNotify */
339 StructureAndSubMask, /* UnmapNotify */
340 StructureAndSubMask, /* MapNotify */
341 SubstructureRedirectMask, /* MapRequest */
342 StructureAndSubMask, /* ReparentNotify */
343 StructureAndSubMask, /* ConfigureNotify */
344 SubstructureRedirectMask, /* ConfigureRequest */
345 StructureAndSubMask, /* GravityNotify */
346 ResizeRedirectMask, /* ResizeRequest */
347 StructureAndSubMask, /* CirculateNotify */
348 SubstructureRedirectMask, /* CirculateRequest */
349 PropertyChangeMask, /* PropertyNotify */
350 CantBeFiltered, /* SelectionClear */
351 CantBeFiltered, /* SelectionRequest */
352 CantBeFiltered, /* SelectionNotify */
353 ColormapChangeMask, /* ColormapNotify */
354 CantBeFiltered, /* ClientMessage */
355 CantBeFiltered /* MappingNotify */
358 static CARD8 criticalEvents[32] =
360 0x7c /* key and button events */
363 #ifdef PANORAMIX
364 static void ConfineToShape(RegionPtr shape, int *px, int *py);
365 static void PostNewCursor(void);
367 #define SyntheticMotion(x, y) \
368 PostSyntheticMotion(x, y, noPanoramiXExtension ? 0 : \
369 sprite.screen->myNum, \
370 syncEvents.playingEvents ? \
371 syncEvents.time.milliseconds : \
372 currentTime.milliseconds);
374 static Bool
375 XineramaSetCursorPosition(
376 int x,
377 int y,
378 Bool generateEvent
380 ScreenPtr pScreen;
381 BoxRec box;
382 int i;
384 /* x,y are in Screen 0 coordinates. We need to decide what Screen
385 to send the message too and what the coordinates relative to
386 that screen are. */
388 pScreen = sprite.screen;
389 x += panoramiXdataPtr[0].x;
390 y += panoramiXdataPtr[0].y;
392 if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum],
393 x, y, &box))
395 FOR_NSCREENS(i)
397 if(i == pScreen->myNum)
398 continue;
399 if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box))
401 pScreen = screenInfo.screens[i];
402 break;
407 sprite.screen = pScreen;
408 sprite.hotPhys.x = x - panoramiXdataPtr[0].x;
409 sprite.hotPhys.y = y - panoramiXdataPtr[0].y;
410 x -= panoramiXdataPtr[pScreen->myNum].x;
411 y -= panoramiXdataPtr[pScreen->myNum].y;
413 return (*pScreen->SetCursorPosition)(pScreen, x, y, generateEvent);
417 static void
418 XineramaConstrainCursor(void)
420 ScreenPtr pScreen = sprite.screen;
421 BoxRec newBox = sprite.physLimits;
423 /* Translate the constraining box to the screen
424 the sprite is actually on */
425 newBox.x1 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x;
426 newBox.x2 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x;
427 newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
428 newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
430 (* pScreen->ConstrainCursor)(pScreen, &newBox);
433 static void
434 XineramaCheckPhysLimits(
435 CursorPtr cursor,
436 Bool generateEvents
438 HotSpot new;
440 if (!cursor)
441 return;
443 new = sprite.hotPhys;
445 /* I don't care what the DDX has to say about it */
446 sprite.physLimits = sprite.hotLimits;
448 /* constrain the pointer to those limits */
449 if (new.x < sprite.physLimits.x1)
450 new.x = sprite.physLimits.x1;
451 else
452 if (new.x >= sprite.physLimits.x2)
453 new.x = sprite.physLimits.x2 - 1;
454 if (new.y < sprite.physLimits.y1)
455 new.y = sprite.physLimits.y1;
456 else
457 if (new.y >= sprite.physLimits.y2)
458 new.y = sprite.physLimits.y2 - 1;
460 if (sprite.hotShape) /* more work if the shape is a mess */
461 ConfineToShape(sprite.hotShape, &new.x, &new.y);
463 if((new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y))
465 XineramaSetCursorPosition (new.x, new.y, generateEvents);
466 if (!generateEvents)
467 SyntheticMotion(new.x, new.y);
470 /* Tell DDX what the limits are */
471 XineramaConstrainCursor();
475 static Bool
476 XineramaSetWindowPntrs(WindowPtr pWin)
478 if(pWin == WindowTable[0]) {
479 memcpy(sprite.windows, WindowTable,
480 PanoramiXNumScreens*sizeof(WindowPtr));
481 } else {
482 PanoramiXRes *win;
483 int i;
485 win = (PanoramiXRes*)LookupIDByType(pWin->drawable.id, XRT_WINDOW);
487 if(!win)
488 return FALSE;
490 for(i = 0; i < PanoramiXNumScreens; i++) {
491 sprite.windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW);
492 if(!sprite.windows[i]) /* window is being unmapped */
493 return FALSE;
496 return TRUE;
499 static void
500 XineramaCheckVirtualMotion(
501 QdEventPtr qe,
502 WindowPtr pWin
505 if (qe)
507 sprite.hot.pScreen = qe->pScreen; /* should always be Screen 0 */
508 sprite.hot.x = qe->event->u.keyButtonPointer.rootX;
509 sprite.hot.y = qe->event->u.keyButtonPointer.rootY;
510 pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo :
511 NullWindow;
513 if (pWin)
515 int x, y, off_x, off_y, i;
516 BoxRec lims;
518 if(!XineramaSetWindowPntrs(pWin))
519 return;
521 i = PanoramiXNumScreens - 1;
523 REGION_COPY(sprite.screen, &sprite.Reg2,
524 &sprite.windows[i]->borderSize);
525 off_x = panoramiXdataPtr[i].x;
526 off_y = panoramiXdataPtr[i].y;
528 while(i--) {
529 x = off_x - panoramiXdataPtr[i].x;
530 y = off_y - panoramiXdataPtr[i].y;
532 if(x || y)
533 REGION_TRANSLATE(sprite.screen, &sprite.Reg2, x, y);
535 REGION_UNION(sprite.screen, &sprite.Reg2, &sprite.Reg2,
536 &sprite.windows[i]->borderSize);
538 off_x = panoramiXdataPtr[i].x;
539 off_y = panoramiXdataPtr[i].y;
542 lims = *REGION_EXTENTS(sprite.screen, &sprite.Reg2);
544 if (sprite.hot.x < lims.x1)
545 sprite.hot.x = lims.x1;
546 else if (sprite.hot.x >= lims.x2)
547 sprite.hot.x = lims.x2 - 1;
548 if (sprite.hot.y < lims.y1)
549 sprite.hot.y = lims.y1;
550 else if (sprite.hot.y >= lims.y2)
551 sprite.hot.y = lims.y2 - 1;
553 if (REGION_NUM_RECTS(&sprite.Reg2) > 1)
554 ConfineToShape(&sprite.Reg2, &sprite.hot.x, &sprite.hot.y);
556 if (qe)
558 qe->pScreen = sprite.hot.pScreen;
559 qe->event->u.keyButtonPointer.rootX = sprite.hot.x;
560 qe->event->u.keyButtonPointer.rootY = sprite.hot.y;
563 #ifdef XEVIE
564 xeviehot.x = sprite.hot.x;
565 xeviehot.y = sprite.hot.y;
566 #endif
570 static Bool
571 XineramaCheckMotion(xEvent *xE)
573 WindowPtr prevSpriteWin = sprite.win;
575 if (xE && !syncEvents.playingEvents)
577 /* Motion events entering DIX get translated to Screen 0
578 coordinates. Replayed events have already been
579 translated since they've entered DIX before */
580 XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x -
581 panoramiXdataPtr[0].x;
582 XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y -
583 panoramiXdataPtr[0].y;
584 sprite.hot.x = XE_KBPTR.rootX;
585 sprite.hot.y = XE_KBPTR.rootY;
586 if (sprite.hot.x < sprite.physLimits.x1)
587 sprite.hot.x = sprite.physLimits.x1;
588 else if (sprite.hot.x >= sprite.physLimits.x2)
589 sprite.hot.x = sprite.physLimits.x2 - 1;
590 if (sprite.hot.y < sprite.physLimits.y1)
591 sprite.hot.y = sprite.physLimits.y1;
592 else if (sprite.hot.y >= sprite.physLimits.y2)
593 sprite.hot.y = sprite.physLimits.y2 - 1;
595 if (sprite.hotShape)
596 ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y);
598 sprite.hotPhys = sprite.hot;
599 if ((sprite.hotPhys.x != XE_KBPTR.rootX) ||
600 (sprite.hotPhys.y != XE_KBPTR.rootY))
602 XineramaSetCursorPosition(
603 sprite.hotPhys.x, sprite.hotPhys.y, FALSE);
605 XE_KBPTR.rootX = sprite.hot.x;
606 XE_KBPTR.rootY = sprite.hot.y;
609 #ifdef XEVIE
610 xeviehot.x = sprite.hot.x;
611 xeviehot.y = sprite.hot.y;
612 xeviewin =
613 #endif
614 sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y);
616 if (sprite.win != prevSpriteWin)
618 if (prevSpriteWin != NullWindow) {
619 if (!xE)
620 UpdateCurrentTimeIf();
621 DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal);
623 PostNewCursor();
624 return FALSE;
626 return TRUE;
630 static void
631 XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents)
634 if (syncEvents.playingEvents)
636 XineramaCheckVirtualMotion((QdEventPtr)NULL, pWin);
637 SyntheticMotion(sprite.hot.x, sprite.hot.y);
639 else
641 int x, y, off_x, off_y, i;
643 if(!XineramaSetWindowPntrs(pWin))
644 return;
646 i = PanoramiXNumScreens - 1;
648 REGION_COPY(sprite.screen, &sprite.Reg1,
649 &sprite.windows[i]->borderSize);
650 off_x = panoramiXdataPtr[i].x;
651 off_y = panoramiXdataPtr[i].y;
653 while(i--) {
654 x = off_x - panoramiXdataPtr[i].x;
655 y = off_y - panoramiXdataPtr[i].y;
657 if(x || y)
658 REGION_TRANSLATE(sprite.screen, &sprite.Reg1, x, y);
660 REGION_UNION(sprite.screen, &sprite.Reg1, &sprite.Reg1,
661 &sprite.windows[i]->borderSize);
663 off_x = panoramiXdataPtr[i].x;
664 off_y = panoramiXdataPtr[i].y;
667 sprite.hotLimits = *REGION_EXTENTS(sprite.screen, &sprite.Reg1);
669 if(REGION_NUM_RECTS(&sprite.Reg1) > 1)
670 sprite.hotShape = &sprite.Reg1;
671 else
672 sprite.hotShape = NullRegion;
674 sprite.confined = FALSE;
675 sprite.confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin;
677 XineramaCheckPhysLimits(sprite.current, generateEvents);
682 static void
683 XineramaChangeToCursor(CursorPtr cursor)
685 if (cursor != sprite.current)
687 if ((sprite.current->bits->xhot != cursor->bits->xhot) ||
688 (sprite.current->bits->yhot != cursor->bits->yhot))
689 XineramaCheckPhysLimits(cursor, FALSE);
690 (*sprite.screen->DisplayCursor)(sprite.screen, cursor);
691 FreeCursor(sprite.current, (Cursor)0);
692 sprite.current = cursor;
693 sprite.current->refcnt++;
697 #else
698 #define SyntheticMotion(x, y) \
699 PostSyntheticMotion(x, y, \
700 0, \
701 syncEvents.playingEvents ? \
702 syncEvents.time.milliseconds : \
703 currentTime.milliseconds);
705 #endif /* PANORAMIX */
707 void
708 SetMaskForEvent(Mask mask, int event)
710 if ((event < LASTEvent) || (event >= 128))
711 FatalError("SetMaskForEvent: bogus event number");
712 filters[event] = mask;
715 _X_EXPORT void
716 SetCriticalEvent(int event)
718 if (event >= 128)
719 FatalError("SetCriticalEvent: bogus event number");
720 criticalEvents[event >> 3] |= 1 << (event & 7);
723 #ifdef SHAPE
724 static void
725 ConfineToShape(RegionPtr shape, int *px, int *py)
727 BoxRec box;
728 int x = *px, y = *py;
729 int incx = 1, incy = 1;
731 if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box))
732 return;
733 box = *REGION_EXTENTS(sprite.hot.pScreen, shape);
734 /* this is rather crude */
735 do {
736 x += incx;
737 if (x >= box.x2)
739 incx = -1;
740 x = *px - 1;
742 else if (x < box.x1)
744 incx = 1;
745 x = *px;
746 y += incy;
747 if (y >= box.y2)
749 incy = -1;
750 y = *py - 1;
752 else if (y < box.y1)
753 return; /* should never get here! */
755 } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box));
756 *px = x;
757 *py = y;
759 #endif
761 static void
762 CheckPhysLimits(
763 CursorPtr cursor,
764 Bool generateEvents,
765 Bool confineToScreen,
766 ScreenPtr pScreen)
768 HotSpot new;
770 if (!cursor)
771 return;
772 new = sprite.hotPhys;
773 if (pScreen)
774 new.pScreen = pScreen;
775 else
776 pScreen = new.pScreen;
777 (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits,
778 &sprite.physLimits);
779 sprite.confined = confineToScreen;
780 (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits);
781 if (new.x < sprite.physLimits.x1)
782 new.x = sprite.physLimits.x1;
783 else
784 if (new.x >= sprite.physLimits.x2)
785 new.x = sprite.physLimits.x2 - 1;
786 if (new.y < sprite.physLimits.y1)
787 new.y = sprite.physLimits.y1;
788 else
789 if (new.y >= sprite.physLimits.y2)
790 new.y = sprite.physLimits.y2 - 1;
791 #ifdef SHAPE
792 if (sprite.hotShape)
793 ConfineToShape(sprite.hotShape, &new.x, &new.y);
794 #endif
795 if ((pScreen != sprite.hotPhys.pScreen) ||
796 (new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y))
798 if (pScreen != sprite.hotPhys.pScreen)
799 sprite.hotPhys = new;
800 (*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents);
801 if (!generateEvents)
802 SyntheticMotion(new.x, new.y);
806 static void
807 CheckVirtualMotion(
808 QdEventPtr qe,
809 WindowPtr pWin)
811 #ifdef PANORAMIX
812 if(!noPanoramiXExtension) {
813 XineramaCheckVirtualMotion(qe, pWin);
814 return;
816 #endif
817 if (qe)
819 sprite.hot.pScreen = qe->pScreen;
820 sprite.hot.x = qe->event->u.keyButtonPointer.rootX;
821 sprite.hot.y = qe->event->u.keyButtonPointer.rootY;
822 pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo :
823 NullWindow;
825 if (pWin)
827 BoxRec lims;
829 if (sprite.hot.pScreen != pWin->drawable.pScreen)
831 sprite.hot.pScreen = pWin->drawable.pScreen;
832 sprite.hot.x = sprite.hot.y = 0;
834 lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize);
835 if (sprite.hot.x < lims.x1)
836 sprite.hot.x = lims.x1;
837 else if (sprite.hot.x >= lims.x2)
838 sprite.hot.x = lims.x2 - 1;
839 if (sprite.hot.y < lims.y1)
840 sprite.hot.y = lims.y1;
841 else if (sprite.hot.y >= lims.y2)
842 sprite.hot.y = lims.y2 - 1;
843 #ifdef SHAPE
844 if (wBoundingShape(pWin))
845 ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y);
846 #endif
847 if (qe)
849 qe->pScreen = sprite.hot.pScreen;
850 qe->event->u.keyButtonPointer.rootX = sprite.hot.x;
851 qe->event->u.keyButtonPointer.rootY = sprite.hot.y;
854 #ifdef XEVIE
855 xeviehot.x = sprite.hot.x;
856 xeviehot.y = sprite.hot.y;
857 #endif
858 ROOT = WindowTable[sprite.hot.pScreen->myNum];
861 static void
862 ConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
864 ScreenPtr pScreen = pWin->drawable.pScreen;
866 #ifdef PANORAMIX
867 if(!noPanoramiXExtension) {
868 XineramaConfineCursorToWindow(pWin, generateEvents);
869 return;
871 #endif
873 if (syncEvents.playingEvents)
875 CheckVirtualMotion((QdEventPtr)NULL, pWin);
876 SyntheticMotion(sprite.hot.x, sprite.hot.y);
878 else
880 sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize);
881 #ifdef SHAPE
882 sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize
883 : NullRegion;
884 #endif
885 CheckPhysLimits(sprite.current, generateEvents, confineToScreen,
886 pScreen);
890 _X_EXPORT Bool
891 PointerConfinedToScreen(void)
893 return sprite.confined;
897 * Update the sprite cursor to the given cursor.
899 * ChangeToCursor() will display the new cursor and free the old cursor (if
900 * applicable). If the provided cursor is already the updated cursor, nothing
901 * happens.
903 static void
904 ChangeToCursor(CursorPtr cursor)
906 #ifdef PANORAMIX
907 if(!noPanoramiXExtension) {
908 XineramaChangeToCursor(cursor);
909 return;
911 #endif
913 if (cursor != sprite.current)
915 if ((sprite.current->bits->xhot != cursor->bits->xhot) ||
916 (sprite.current->bits->yhot != cursor->bits->yhot))
917 CheckPhysLimits(cursor, FALSE, sprite.confined,
918 (ScreenPtr)NULL);
919 (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen,
920 cursor);
921 FreeCursor(sprite.current, (Cursor)0);
922 sprite.current = cursor;
923 sprite.current->refcnt++;
928 * @returns true if b is a descendent of a
930 Bool
931 IsParent(WindowPtr a, WindowPtr b)
933 for (b = b->parent; b; b = b->parent)
934 if (b == a) return TRUE;
935 return FALSE;
939 * Update the cursor displayed on the screen.
941 * Called whenever a cursor may have changed shape or position.
943 static void
944 PostNewCursor(void)
946 WindowPtr win;
947 GrabPtr grab = inputInfo.pointer->grab;
949 if (syncEvents.playingEvents)
950 return;
951 if (grab)
953 if (grab->cursor)
955 ChangeToCursor(grab->cursor);
956 return;
958 if (IsParent(grab->window, sprite.win))
959 win = sprite.win;
960 else
961 win = grab->window;
963 else
964 win = sprite.win;
965 for (; win; win = win->parent)
966 if (win->optional && win->optional->cursor != NullCursor)
968 ChangeToCursor(win->optional->cursor);
969 return;
974 * @return root window of current active screen.
976 _X_EXPORT WindowPtr
977 GetCurrentRootWindow(void)
979 return ROOT;
983 * @return window underneath the cursor sprite.
985 _X_EXPORT WindowPtr
986 GetSpriteWindow(void)
988 return sprite.win;
992 * @return current sprite cursor.
994 _X_EXPORT CursorPtr
995 GetSpriteCursor(void)
997 return sprite.current;
1001 * Set x/y current sprite position in screen coordinates.
1003 _X_EXPORT void
1004 GetSpritePosition(int *px, int *py)
1006 *px = sprite.hotPhys.x;
1007 *py = sprite.hotPhys.y;
1010 #ifdef PANORAMIX
1011 _X_EXPORT int
1012 XineramaGetCursorScreen(void)
1014 if(!noPanoramiXExtension) {
1015 return sprite.screen->myNum;
1016 } else {
1017 return 0;
1020 #endif /* PANORAMIX */
1022 #define TIMESLOP (5 * 60 * 1000) /* 5 minutes */
1024 static void
1025 MonthChangedOrBadTime(xEvent *xE)
1027 /* If the ddx/OS is careless about not processing timestamped events from
1028 * different sources in sorted order, then it's possible for time to go
1029 * backwards when it should not. Here we ensure a decent time.
1031 if ((currentTime.milliseconds - XE_KBPTR.time) > TIMESLOP)
1032 currentTime.months++;
1033 else
1034 XE_KBPTR.time = currentTime.milliseconds;
1037 #define NoticeTime(xE) { \
1038 if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \
1039 MonthChangedOrBadTime(xE); \
1040 currentTime.milliseconds = (xE)->u.keyButtonPointer.time; \
1041 lastDeviceEventTime = currentTime; }
1043 void
1044 NoticeEventTime(xEvent *xE)
1046 if (!syncEvents.playingEvents)
1047 NoticeTime(xE);
1050 /**************************************************************************
1051 * The following procedures deal with synchronous events *
1052 **************************************************************************/
1054 void
1055 EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
1057 QdEventPtr tail = *syncEvents.pendtail;
1058 QdEventPtr qe;
1059 xEvent *qxE;
1061 NoticeTime(xE);
1063 #ifdef XKB
1064 /* Fix for key repeating bug. */
1065 if (device->key != NULL && device->key->xkbInfo != NULL &&
1066 xE->u.u.type == KeyRelease)
1067 AccessXCancelRepeatKey(device->key->xkbInfo, xE->u.u.detail);
1068 #endif
1070 if (DeviceEventCallback)
1072 DeviceEventInfoRec eventinfo;
1073 /* The RECORD spec says that the root window field of motion events
1074 * must be valid. At this point, it hasn't been filled in yet, so
1075 * we do it here. The long expression below is necessary to get
1076 * the current root window; the apparently reasonable alternative
1077 * GetCurrentRootWindow()->drawable.id doesn't give you the right
1078 * answer on the first motion event after a screen change because
1079 * the data that GetCurrentRootWindow relies on hasn't been
1080 * updated yet.
1082 if (xE->u.u.type == MotionNotify)
1083 XE_KBPTR.root =
1084 WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id;
1085 eventinfo.events = xE;
1086 eventinfo.count = count;
1087 CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
1089 if (xE->u.u.type == MotionNotify)
1091 #ifdef PANORAMIX
1092 if(!noPanoramiXExtension) {
1093 XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x -
1094 panoramiXdataPtr[0].x;
1095 XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y -
1096 panoramiXdataPtr[0].y;
1098 #endif
1099 sprite.hotPhys.x = XE_KBPTR.rootX;
1100 sprite.hotPhys.y = XE_KBPTR.rootY;
1101 /* do motion compression */
1102 if (tail &&
1103 (tail->event->u.u.type == MotionNotify) &&
1104 (tail->pScreen == sprite.hotPhys.pScreen))
1106 tail->event->u.keyButtonPointer.rootX = sprite.hotPhys.x;
1107 tail->event->u.keyButtonPointer.rootY = sprite.hotPhys.y;
1108 tail->event->u.keyButtonPointer.time = XE_KBPTR.time;
1109 tail->months = currentTime.months;
1110 return;
1113 qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent)));
1114 if (!qe)
1115 return;
1116 qe->next = (QdEventPtr)NULL;
1117 qe->device = device;
1118 qe->pScreen = sprite.hotPhys.pScreen;
1119 qe->months = currentTime.months;
1120 qe->event = (xEvent *)(qe + 1);
1121 qe->evcount = count;
1122 for (qxE = qe->event; --count >= 0; qxE++, xE++)
1123 *qxE = *xE;
1124 if (tail)
1125 syncEvents.pendtail = &tail->next;
1126 *syncEvents.pendtail = qe;
1129 static void
1130 PlayReleasedEvents(void)
1132 QdEventPtr *prev, qe;
1133 DeviceIntPtr dev;
1135 prev = &syncEvents.pending;
1136 while ( (qe = *prev) )
1138 if (!qe->device->sync.frozen)
1140 *prev = qe->next;
1141 if (*syncEvents.pendtail == *prev)
1142 syncEvents.pendtail = prev;
1143 if (qe->event->u.u.type == MotionNotify)
1144 CheckVirtualMotion(qe, NullWindow);
1145 syncEvents.time.months = qe->months;
1146 syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time;
1147 #ifdef PANORAMIX
1148 /* Translate back to the sprite screen since processInputProc
1149 will translate from sprite screen to screen 0 upon reentry
1150 to the DIX layer */
1151 if(!noPanoramiXExtension) {
1152 qe->event->u.keyButtonPointer.rootX +=
1153 panoramiXdataPtr[0].x -
1154 panoramiXdataPtr[sprite.screen->myNum].x;
1155 qe->event->u.keyButtonPointer.rootY +=
1156 panoramiXdataPtr[0].y -
1157 panoramiXdataPtr[sprite.screen->myNum].y;
1159 #endif
1160 (*qe->device->public.processInputProc)(qe->event, qe->device,
1161 qe->evcount);
1162 xfree(qe);
1163 for (dev = inputInfo.devices; dev && dev->sync.frozen; dev = dev->next)
1165 if (!dev)
1166 break;
1167 /* Playing the event may have unfrozen another device. */
1168 /* So to play it safe, restart at the head of the queue */
1169 prev = &syncEvents.pending;
1171 else
1172 prev = &qe->next;
1176 static void
1177 FreezeThaw(DeviceIntPtr dev, Bool frozen)
1179 dev->sync.frozen = frozen;
1180 if (frozen)
1181 dev->public.processInputProc = dev->public.enqueueInputProc;
1182 else
1183 dev->public.processInputProc = dev->public.realInputProc;
1186 void
1187 ComputeFreezes(void)
1189 DeviceIntPtr replayDev = syncEvents.replayDev;
1190 int i;
1191 WindowPtr w;
1192 xEvent *xE;
1193 int count;
1194 GrabPtr grab;
1195 DeviceIntPtr dev;
1197 for (dev = inputInfo.devices; dev; dev = dev->next)
1198 FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN));
1199 if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
1200 return;
1201 syncEvents.playingEvents = TRUE;
1202 if (replayDev)
1204 xE = replayDev->sync.event;
1205 count = replayDev->sync.evcount;
1206 syncEvents.replayDev = (DeviceIntPtr)NULL;
1208 w = XYToWindow( XE_KBPTR.rootX, XE_KBPTR.rootY);
1209 for (i = 0; i < spriteTraceGood; i++)
1211 if (syncEvents.replayWin == spriteTrace[i])
1213 if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) {
1214 if (replayDev->focus)
1215 DeliverFocusedEvent(replayDev, xE, w, count);
1216 else
1217 DeliverDeviceEvents(w, xE, NullGrab, NullWindow,
1218 replayDev, count);
1220 goto playmore;
1223 /* must not still be in the same stack */
1224 if (replayDev->focus)
1225 DeliverFocusedEvent(replayDev, xE, w, count);
1226 else
1227 DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count);
1229 playmore:
1230 for (dev = inputInfo.devices; dev; dev = dev->next)
1232 if (!dev->sync.frozen)
1234 PlayReleasedEvents();
1235 break;
1238 syncEvents.playingEvents = FALSE;
1239 /* the following may have been skipped during replay, so do it now */
1240 if ((grab = inputInfo.pointer->grab) && grab->confineTo)
1242 if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
1243 sprite.hotPhys.x = sprite.hotPhys.y = 0;
1244 ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
1246 else
1247 ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum],
1248 TRUE, FALSE);
1249 PostNewCursor();
1252 #ifdef RANDR
1253 void
1254 ScreenRestructured (ScreenPtr pScreen)
1256 GrabPtr grab;
1258 if ((grab = inputInfo.pointer->grab) && grab->confineTo)
1260 if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
1261 sprite.hotPhys.x = sprite.hotPhys.y = 0;
1262 ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
1264 else
1265 ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum],
1266 TRUE, FALSE);
1268 #endif
1270 void
1271 CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
1273 GrabPtr grab = thisDev->grab;
1274 DeviceIntPtr dev;
1276 if (thisMode == GrabModeSync)
1277 thisDev->sync.state = FROZEN_NO_EVENT;
1278 else
1279 { /* free both if same client owns both */
1280 thisDev->sync.state = THAWED;
1281 if (thisDev->sync.other &&
1282 (CLIENT_BITS(thisDev->sync.other->resource) ==
1283 CLIENT_BITS(grab->resource)))
1284 thisDev->sync.other = NullGrab;
1286 for (dev = inputInfo.devices; dev; dev = dev->next)
1288 if (dev != thisDev)
1290 if (otherMode == GrabModeSync)
1291 dev->sync.other = grab;
1292 else
1293 { /* free both if same client owns both */
1294 if (dev->sync.other &&
1295 (CLIENT_BITS(dev->sync.other->resource) ==
1296 CLIENT_BITS(grab->resource)))
1297 dev->sync.other = NullGrab;
1301 ComputeFreezes();
1305 * Activate a pointer grab on the given device. A pointer grab will cause all
1306 * core pointer events to be delivered to the grabbing client only. Can cause
1307 * the cursor to change if a grab cursor is set.
1309 * As a pointer grab can only be issued on the core devices, mouse is always
1310 * inputInfo.pointer. Extension devices are set up for ActivateKeyboardGrab().
1312 * @param mouse The device to grab.
1313 * @param grab The grab structure, needs to be setup.
1314 * @param autoGrab True if the grab was caused by a button down event and not
1315 * explicitely by a client.
1317 void
1318 ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
1319 TimeStamp time, Bool autoGrab)
1321 WindowPtr oldWin = (mouse->grab) ? mouse->grab->window
1322 : sprite.win;
1324 if (grab->confineTo)
1326 if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
1327 sprite.hotPhys.x = sprite.hotPhys.y = 0;
1328 ConfineCursorToWindow(grab->confineTo, FALSE, TRUE);
1330 DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab);
1331 mouse->valuator->motionHintWindow = NullWindow;
1332 if (syncEvents.playingEvents)
1333 mouse->grabTime = syncEvents.time;
1334 else
1335 mouse->grabTime = time;
1336 if (grab->cursor)
1337 grab->cursor->refcnt++;
1338 mouse->activeGrab = *grab;
1339 mouse->grab = &mouse->activeGrab;
1340 mouse->fromPassiveGrab = autoGrab;
1341 PostNewCursor();
1342 CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
1346 * Delete grab on given device, update the sprite.
1348 * As a pointer grab can only be issued on the core devices, mouse is always
1349 * inputInfo.pointer. Extension devices are set up for ActivateKeyboardGrab().
1351 void
1352 DeactivatePointerGrab(DeviceIntPtr mouse)
1354 GrabPtr grab = mouse->grab;
1355 DeviceIntPtr dev;
1357 mouse->valuator->motionHintWindow = NullWindow;
1358 mouse->grab = NullGrab;
1359 mouse->sync.state = NOT_GRABBED;
1360 mouse->fromPassiveGrab = FALSE;
1361 for (dev = inputInfo.devices; dev; dev = dev->next)
1363 if (dev->sync.other == grab)
1364 dev->sync.other = NullGrab;
1366 DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab);
1367 if (grab->confineTo)
1368 ConfineCursorToWindow(ROOT, FALSE, FALSE);
1369 PostNewCursor();
1370 if (grab->cursor)
1371 FreeCursor(grab->cursor, (Cursor)0);
1372 ComputeFreezes();
1376 * Activate a keyboard grab on the given device.
1378 * Extension devices have ActivateKeyboardGrab() set as their grabbing proc.
1380 void
1381 ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive)
1383 WindowPtr oldWin;
1385 if (keybd->grab)
1386 oldWin = keybd->grab->window;
1387 else if (keybd->focus)
1388 oldWin = keybd->focus->win;
1389 else
1390 oldWin = sprite.win;
1391 if (oldWin == FollowKeyboardWin)
1392 oldWin = inputInfo.keyboard->focus->win;
1393 if (keybd->valuator)
1394 keybd->valuator->motionHintWindow = NullWindow;
1395 DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
1396 if (syncEvents.playingEvents)
1397 keybd->grabTime = syncEvents.time;
1398 else
1399 keybd->grabTime = time;
1400 keybd->activeGrab = *grab;
1401 keybd->grab = &keybd->activeGrab;
1402 keybd->fromPassiveGrab = passive;
1403 CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
1407 * Delete keyboard grab for the given device.
1409 void
1410 DeactivateKeyboardGrab(DeviceIntPtr keybd)
1412 GrabPtr grab = keybd->grab;
1413 DeviceIntPtr dev;
1414 WindowPtr focusWin = keybd->focus ? keybd->focus->win
1415 : sprite.win;
1417 if (focusWin == FollowKeyboardWin)
1418 focusWin = inputInfo.keyboard->focus->win;
1419 if (keybd->valuator)
1420 keybd->valuator->motionHintWindow = NullWindow;
1421 keybd->grab = NullGrab;
1422 keybd->sync.state = NOT_GRABBED;
1423 keybd->fromPassiveGrab = FALSE;
1424 for (dev = inputInfo.devices; dev; dev = dev->next)
1426 if (dev->sync.other == grab)
1427 dev->sync.other = NullGrab;
1429 DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
1430 ComputeFreezes();
1433 void
1434 AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState)
1436 Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
1437 TimeStamp grabTime;
1438 DeviceIntPtr dev;
1440 thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client);
1441 thisSynced = FALSE;
1442 otherGrabbed = FALSE;
1443 othersFrozen = TRUE;
1444 grabTime = thisDev->grabTime;
1445 for (dev = inputInfo.devices; dev; dev = dev->next)
1447 if (dev == thisDev)
1448 continue;
1449 if (dev->grab && SameClient(dev->grab, client))
1451 if (!(thisGrabbed || otherGrabbed) ||
1452 (CompareTimeStamps(dev->grabTime, grabTime) == LATER))
1453 grabTime = dev->grabTime;
1454 otherGrabbed = TRUE;
1455 if (thisDev->sync.other == dev->grab)
1456 thisSynced = TRUE;
1457 if (dev->sync.state < FROZEN)
1458 othersFrozen = FALSE;
1460 else if (!dev->sync.other || !SameClient(dev->sync.other, client))
1461 othersFrozen = FALSE;
1463 if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced))
1464 return;
1465 if ((CompareTimeStamps(time, currentTime) == LATER) ||
1466 (CompareTimeStamps(time, grabTime) == EARLIER))
1467 return;
1468 switch (newState)
1470 case THAWED: /* Async */
1471 if (thisGrabbed)
1472 thisDev->sync.state = THAWED;
1473 if (thisSynced)
1474 thisDev->sync.other = NullGrab;
1475 ComputeFreezes();
1476 break;
1477 case FREEZE_NEXT_EVENT: /* Sync */
1478 if (thisGrabbed)
1480 thisDev->sync.state = FREEZE_NEXT_EVENT;
1481 if (thisSynced)
1482 thisDev->sync.other = NullGrab;
1483 ComputeFreezes();
1485 break;
1486 case THAWED_BOTH: /* AsyncBoth */
1487 if (othersFrozen)
1489 for (dev = inputInfo.devices; dev; dev = dev->next)
1491 if (dev->grab && SameClient(dev->grab, client))
1492 dev->sync.state = THAWED;
1493 if (dev->sync.other && SameClient(dev->sync.other, client))
1494 dev->sync.other = NullGrab;
1496 ComputeFreezes();
1498 break;
1499 case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */
1500 if (othersFrozen)
1502 for (dev = inputInfo.devices; dev; dev = dev->next)
1504 if (dev->grab && SameClient(dev->grab, client))
1505 dev->sync.state = FREEZE_BOTH_NEXT_EVENT;
1506 if (dev->sync.other && SameClient(dev->sync.other, client))
1507 dev->sync.other = NullGrab;
1509 ComputeFreezes();
1511 break;
1512 case NOT_GRABBED: /* Replay */
1513 if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT)
1515 if (thisSynced)
1516 thisDev->sync.other = NullGrab;
1517 syncEvents.replayDev = thisDev;
1518 syncEvents.replayWin = thisDev->grab->window;
1519 (*thisDev->DeactivateGrab)(thisDev);
1520 syncEvents.replayDev = (DeviceIntPtr)NULL;
1522 break;
1523 case THAW_OTHERS: /* AsyncOthers */
1524 if (othersFrozen)
1526 for (dev = inputInfo.devices; dev; dev = dev->next)
1528 if (dev == thisDev)
1529 continue;
1530 if (dev->grab && SameClient(dev->grab, client))
1531 dev->sync.state = THAWED;
1532 if (dev->sync.other && SameClient(dev->sync.other, client))
1533 dev->sync.other = NullGrab;
1535 ComputeFreezes();
1537 break;
1542 * Server-side protocol handling for AllowEvents request.
1544 * Release some events from a frozen device. Only applicable for core devices.
1547 ProcAllowEvents(ClientPtr client)
1549 TimeStamp time;
1550 DeviceIntPtr mouse = inputInfo.pointer;
1551 DeviceIntPtr keybd = inputInfo.keyboard;
1552 REQUEST(xAllowEventsReq);
1554 REQUEST_SIZE_MATCH(xAllowEventsReq);
1555 time = ClientTimeToServerTime(stuff->time);
1556 switch (stuff->mode)
1558 case ReplayPointer:
1559 AllowSome(client, time, mouse, NOT_GRABBED);
1560 break;
1561 case SyncPointer:
1562 AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
1563 break;
1564 case AsyncPointer:
1565 AllowSome(client, time, mouse, THAWED);
1566 break;
1567 case ReplayKeyboard:
1568 AllowSome(client, time, keybd, NOT_GRABBED);
1569 break;
1570 case SyncKeyboard:
1571 AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
1572 break;
1573 case AsyncKeyboard:
1574 AllowSome(client, time, keybd, THAWED);
1575 break;
1576 case SyncBoth:
1577 AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
1578 break;
1579 case AsyncBoth:
1580 AllowSome(client, time, keybd, THAWED_BOTH);
1581 break;
1582 default:
1583 client->errorValue = stuff->mode;
1584 return BadValue;
1586 return Success;
1590 * Deactivate grabs from any device that has been grabbed by the client.
1592 void
1593 ReleaseActiveGrabs(ClientPtr client)
1595 DeviceIntPtr dev;
1596 Bool done;
1598 /* XXX CloseDownClient should remove passive grabs before
1599 * releasing active grabs.
1601 do {
1602 done = TRUE;
1603 for (dev = inputInfo.devices; dev; dev = dev->next)
1605 if (dev->grab && SameClient(dev->grab, client))
1607 (*dev->DeactivateGrab)(dev);
1608 done = FALSE;
1611 } while (!done);
1614 /**************************************************************************
1615 * The following procedures deal with delivering events *
1616 **************************************************************************/
1619 * Deliver the given events to the given client.
1621 * More than one event may be delivered at a time. This is the case with
1622 * DeviceMotionNotifies which may be followed by DeviceValuator events.
1624 * TryClientEvents() is the last station before actually writing the events to
1625 * the socket. Anything that is not filtered here, will get delivered to the
1626 * client.
1627 * An event is only delivered if
1628 * - mask and filter match up.
1629 * - no other client has a grab on the device that caused the event.
1632 * @param client The target client to deliver to.
1633 * @param pEvents The events to be delivered.
1634 * @param count Number of elements in pEvents.
1635 * @param mask Event mask as set by the window.
1636 * @param filter Mask based on event type.
1637 * @param grab Possible grab on the device that caused the event.
1639 * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
1640 * client.
1642 _X_EXPORT int
1643 TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask,
1644 Mask filter, GrabPtr grab)
1646 int i;
1647 int type;
1649 #ifdef DEBUG_EVENTS
1650 ErrorF("Event([%d, %d], mask=0x%x), client=%d",
1651 pEvents->u.u.type, pEvents->u.u.detail, mask, client->index);
1652 #endif
1653 if ((client) && (client != serverClient) && (!client->clientGone) &&
1654 ((filter == CantBeFiltered) || (mask & filter)))
1656 if (grab && !SameClient(grab, client))
1657 return -1; /* don't send, but notify caller */
1658 type = pEvents->u.u.type;
1659 if (type == MotionNotify)
1661 if (mask & PointerMotionHintMask)
1663 if (WID(inputInfo.pointer->valuator->motionHintWindow) ==
1664 pEvents->u.keyButtonPointer.event)
1666 #ifdef DEBUG_EVENTS
1667 ErrorF("\n");
1668 ErrorF("motionHintWindow == keyButtonPointer.event\n");
1669 #endif
1670 return 1; /* don't send, but pretend we did */
1672 pEvents->u.u.detail = NotifyHint;
1674 else
1676 pEvents->u.u.detail = NotifyNormal;
1679 #ifdef XINPUT
1680 else
1682 if ((type == DeviceMotionNotify) &&
1683 MaybeSendDeviceMotionNotifyHint
1684 ((deviceKeyButtonPointer*)pEvents, mask) != 0)
1685 return 1;
1687 #endif
1688 type &= 0177;
1689 if (type != KeymapNotify)
1691 /* all extension events must have a sequence number */
1692 for (i = 0; i < count; i++)
1693 pEvents[i].u.u.sequenceNumber = client->sequence;
1696 if (BitIsOn(criticalEvents, type))
1698 #ifdef SMART_SCHEDULE
1699 if (client->smart_priority < SMART_MAX_PRIORITY)
1700 client->smart_priority++;
1701 #endif
1702 SetCriticalOutputPending();
1705 WriteEventsToClient(client, count, pEvents);
1706 #ifdef DEBUG_EVENTS
1707 ErrorF( " delivered\n");
1708 #endif
1709 return 1;
1711 else
1713 #ifdef DEBUG_EVENTS
1714 ErrorF("\n");
1715 #endif
1716 return 0;
1721 * Deliver events to a window. At this point, we do not yet know if the event
1722 * actually needs to be delivered. May activate a grab if the event is a
1723 * button press.
1725 * More than one event may be delivered at a time. This is the case with
1726 * DeviceMotionNotifies which may be followed by DeviceValuator events.
1728 * @param pWin The window that would get the event.
1729 * @param pEvents The events to be delivered.
1730 * @param count Number of elements in pEvents.
1731 * @param filter Mask based on event type.
1732 * @param grab Possible grab on the device that caused the event.
1733 * @param mskidx Mask index, depending on device that caused event.
1735 * @return Number of events delivered to various clients.
1738 DeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count,
1739 Mask filter, GrabPtr grab, int mskidx)
1741 int deliveries = 0, nondeliveries = 0;
1742 int attempt;
1743 InputClients *other;
1744 ClientPtr client = NullClient;
1745 Mask deliveryMask = 0; /* If a grab occurs due to a button press, then
1746 this mask is the mask of the grab. */
1747 int type = pEvents->u.u.type;
1749 /* CantBeFiltered means only window owner gets the event */
1750 if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE))
1752 /* if nobody ever wants to see this event, skip some work */
1753 if (filter != CantBeFiltered &&
1754 !((wOtherEventMasks(pWin)|pWin->eventMask) & filter))
1755 return 0;
1756 if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count,
1757 pWin->eventMask, filter, grab)) )
1759 if (attempt > 0)
1761 deliveries++;
1762 client = wClient(pWin);
1763 deliveryMask = pWin->eventMask;
1764 } else
1765 nondeliveries--;
1768 if (filter != CantBeFiltered)
1770 if (type & EXTENSION_EVENT_BASE)
1772 OtherInputMasks *inputMasks;
1774 inputMasks = wOtherInputMasks(pWin);
1775 if (!inputMasks ||
1776 !(inputMasks->inputEvents[mskidx] & filter))
1777 return 0;
1778 other = inputMasks->inputClients;
1780 else
1781 other = (InputClients *)wOtherClients(pWin);
1782 for (; other; other = other->next)
1784 if ( (attempt = TryClientEvents(rClient(other), pEvents, count,
1785 other->mask[mskidx], filter, grab)) )
1787 if (attempt > 0)
1789 deliveries++;
1790 client = rClient(other);
1791 deliveryMask = other->mask[mskidx];
1792 } else
1793 nondeliveries--;
1797 if ((type == ButtonPress) && deliveries && (!grab))
1799 GrabRec tempGrab;
1801 tempGrab.device = inputInfo.pointer;
1802 tempGrab.resource = client->clientAsMask;
1803 tempGrab.window = pWin;
1804 tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
1805 tempGrab.eventMask = deliveryMask;
1806 tempGrab.keyboardMode = GrabModeAsync;
1807 tempGrab.pointerMode = GrabModeAsync;
1808 tempGrab.confineTo = NullWindow;
1809 tempGrab.cursor = NullCursor;
1810 (*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab,
1811 currentTime, TRUE);
1813 else if ((type == MotionNotify) && deliveries)
1814 inputInfo.pointer->valuator->motionHintWindow = pWin;
1815 #ifdef XINPUT
1816 else
1818 if (((type == DeviceMotionNotify)
1819 #ifdef XKB
1820 || (type == DeviceButtonPress)
1821 #endif
1822 ) && deliveries)
1823 CheckDeviceGrabAndHintWindow (pWin, type,
1824 (deviceKeyButtonPointer*) pEvents,
1825 grab, client, deliveryMask);
1827 #endif
1828 if (deliveries)
1829 return deliveries;
1830 return nondeliveries;
1833 /* If the event goes to dontClient, don't send it and return 0. if
1834 send works, return 1 or if send didn't work, return 2.
1835 Only works for core events.
1838 #ifdef PANORAMIX
1839 static int
1840 XineramaTryClientEventsResult(
1841 ClientPtr client,
1842 GrabPtr grab,
1843 Mask mask,
1844 Mask filter
1846 if ((client) && (client != serverClient) && (!client->clientGone) &&
1847 ((filter == CantBeFiltered) || (mask & filter)))
1849 if (grab && !SameClient(grab, client)) return -1;
1850 else return 1;
1852 return 0;
1854 #endif
1857 * Try to deliver events to the interested parties.
1859 * @param pWin The window that would get the event.
1860 * @param pEvents The events to be delivered.
1861 * @param count Number of elements in pEvents.
1862 * @param filter Mask based on event type.
1863 * @param dontClient Don't deliver to the dontClient.
1866 MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
1867 int count, Mask filter, ClientPtr dontClient)
1869 OtherClients *other;
1872 if (pWin->eventMask & filter)
1874 if (wClient(pWin) == dontClient)
1875 return 0;
1876 #ifdef PANORAMIX
1877 if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
1878 return XineramaTryClientEventsResult(
1879 wClient(pWin), NullGrab, pWin->eventMask, filter);
1880 #endif
1881 return TryClientEvents(wClient(pWin), pEvents, count,
1882 pWin->eventMask, filter, NullGrab);
1884 for (other = wOtherClients(pWin); other; other = other->next)
1886 if (other->mask & filter)
1888 if (SameClient(other, dontClient))
1889 return 0;
1890 #ifdef PANORAMIX
1891 if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
1892 return XineramaTryClientEventsResult(
1893 rClient(other), NullGrab, other->mask, filter);
1894 #endif
1895 return TryClientEvents(rClient(other), pEvents, count,
1896 other->mask, filter, NullGrab);
1899 return 2;
1903 * Adjust event fields to comply with the window properties.
1905 * @param xE Event to be modified in place
1906 * @param pWin The window to get the information from.
1907 * @param child Child window setting for event (if applicable)
1908 * @param calcChild If True, calculate the child window.
1910 static void
1911 FixUpEventFromWindow(
1912 xEvent *xE,
1913 WindowPtr pWin,
1914 Window child,
1915 Bool calcChild)
1917 if (calcChild)
1919 WindowPtr w=spriteTrace[spriteTraceGood-1];
1920 /* If the search ends up past the root should the child field be
1921 set to none or should the value in the argument be passed
1922 through. It probably doesn't matter since everyone calls
1923 this function with child == None anyway. */
1925 while (w)
1927 /* If the source window is same as event window, child should be
1928 none. Don't bother going all all the way back to the root. */
1930 if (w == pWin)
1932 child = None;
1933 break;
1936 if (w->parent == pWin)
1938 child = w->drawable.id;
1939 break;
1941 w = w->parent;
1944 XE_KBPTR.root = ROOT->drawable.id;
1945 XE_KBPTR.event = pWin->drawable.id;
1946 if (sprite.hot.pScreen == pWin->drawable.pScreen)
1948 XE_KBPTR.sameScreen = xTrue;
1949 XE_KBPTR.child = child;
1950 XE_KBPTR.eventX =
1951 XE_KBPTR.rootX - pWin->drawable.x;
1952 XE_KBPTR.eventY =
1953 XE_KBPTR.rootY - pWin->drawable.y;
1955 else
1957 XE_KBPTR.sameScreen = xFalse;
1958 XE_KBPTR.child = None;
1959 XE_KBPTR.eventX = 0;
1960 XE_KBPTR.eventY = 0;
1965 * Deliver events caused by input devices. Called for all core input events
1966 * and XI events. No filtering of events happens before DeliverDeviceEvents(),
1967 * it will be called for any event that comes out of the event queue.
1969 * For all core events, dev is either inputInfo.pointer or inputInfo.keyboard.
1970 * For all extension events, dev is the device that caused the event.
1972 * @param pWin Window to deliver event to.
1973 * @param xE Events to deliver.
1974 * @param grab Possible grab on a device.
1975 * @param stopAt Don't recurse up to the root window.
1976 * @param dev The device that is responsible for the event.
1977 * @param count number of events in xE.
1981 DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab,
1982 WindowPtr stopAt, DeviceIntPtr dev, int count)
1984 Window child = None;
1985 int type = xE->u.u.type;
1986 Mask filter = filters[type];
1987 int deliveries = 0;
1989 if (type & EXTENSION_EVENT_BASE)
1991 OtherInputMasks *inputMasks;
1992 int mskidx = dev->id;
1994 inputMasks = wOtherInputMasks(pWin);
1995 if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx]))
1996 return 0;
1997 while (pWin)
1999 if (inputMasks && (inputMasks->inputEvents[mskidx] & filter))
2001 FixUpEventFromWindow(xE, pWin, child, FALSE);
2002 deliveries = DeliverEventsToWindow(pWin, xE, count, filter,
2003 grab, mskidx);
2004 if (deliveries > 0)
2005 return deliveries;
2007 if ((deliveries < 0) ||
2008 (pWin == stopAt) ||
2009 (inputMasks &&
2010 (filter & inputMasks->dontPropagateMask[mskidx])))
2011 return 0;
2012 child = pWin->drawable.id;
2013 pWin = pWin->parent;
2014 if (pWin)
2015 inputMasks = wOtherInputMasks(pWin);
2018 else
2020 if (!(filter & pWin->deliverableEvents))
2021 return 0;
2022 while (pWin)
2024 if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter)
2026 FixUpEventFromWindow(xE, pWin, child, FALSE);
2027 deliveries = DeliverEventsToWindow(pWin, xE, count, filter,
2028 grab, 0);
2029 if (deliveries > 0)
2030 return deliveries;
2032 if ((deliveries < 0) ||
2033 (pWin == stopAt) ||
2034 (filter & wDontPropagateMask(pWin)))
2035 return 0;
2036 child = pWin->drawable.id;
2037 pWin = pWin->parent;
2040 return 0;
2044 * Deliver event to a window and it's immediate parent. Used for most window
2045 * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
2046 * propagate up the tree or extension events
2048 * In case of a ReparentNotify event, the event will be delivered to the
2049 * otherParent as well.
2051 * @param pWin Window to deliver events to.
2052 * @param xE Events to deliver.
2053 * @param count number of events in xE.
2054 * @param otherParent Used for ReparentNotify events.
2056 _X_EXPORT int
2057 DeliverEvents(WindowPtr pWin, xEvent *xE, int count,
2058 WindowPtr otherParent)
2060 Mask filter;
2061 int deliveries;
2063 #ifdef PANORAMIX
2064 if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2065 return count;
2066 #endif
2068 if (!count)
2069 return 0;
2070 filter = filters[xE->u.u.type];
2071 if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify))
2072 xE->u.destroyNotify.event = pWin->drawable.id;
2073 if (filter != StructureAndSubMask)
2074 return DeliverEventsToWindow(pWin, xE, count, filter, NullGrab, 0);
2075 deliveries = DeliverEventsToWindow(pWin, xE, count, StructureNotifyMask,
2076 NullGrab, 0);
2077 if (pWin->parent)
2079 xE->u.destroyNotify.event = pWin->parent->drawable.id;
2080 deliveries += DeliverEventsToWindow(pWin->parent, xE, count,
2081 SubstructureNotifyMask, NullGrab,
2083 if (xE->u.u.type == ReparentNotify)
2085 xE->u.destroyNotify.event = otherParent->drawable.id;
2086 deliveries += DeliverEventsToWindow(otherParent, xE, count,
2087 SubstructureNotifyMask,
2088 NullGrab, 0);
2091 return deliveries;
2095 static Bool
2096 PointInBorderSize(WindowPtr pWin, int x, int y)
2098 BoxRec box;
2100 if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box))
2101 return TRUE;
2103 #ifdef PANORAMIX
2104 if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) {
2105 int i;
2107 for(i = 1; i < PanoramiXNumScreens; i++) {
2108 if(POINT_IN_REGION(sprite.screen,
2109 &sprite.windows[i]->borderSize,
2110 x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x,
2111 y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y,
2112 &box))
2113 return TRUE;
2116 #endif
2117 return FALSE;
2121 * Traversed from the root window to the window at the position x/y. While
2122 * traversing, it sets up the traversal history in the spriteTrace array.
2123 * After completing, the spriteTrace history is set in the following way:
2124 * spriteTrace[0] ... root window
2125 * spriteTrace[1] ... top level window that encloses x/y
2126 * ...
2127 * spriteTrace[spriteTraceGood - 1] ... window at x/y
2129 * @returns the window at the given coordinates.
2131 static WindowPtr
2132 XYToWindow(int x, int y)
2134 WindowPtr pWin;
2135 BoxRec box;
2137 spriteTraceGood = 1; /* root window still there */
2138 pWin = ROOT->firstChild;
2139 while (pWin)
2141 if ((pWin->mapped) &&
2142 (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
2143 (x < pWin->drawable.x + (int)pWin->drawable.width +
2144 wBorderWidth(pWin)) &&
2145 (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
2146 (y < pWin->drawable.y + (int)pWin->drawable.height +
2147 wBorderWidth (pWin))
2148 #ifdef SHAPE
2149 /* When a window is shaped, a further check
2150 * is made to see if the point is inside
2151 * borderSize
2153 && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
2154 && (!wInputShape(pWin) ||
2155 POINT_IN_REGION(pWin->drawable.pScreen,
2156 wInputShape(pWin),
2157 x - pWin->drawable.x,
2158 y - pWin->drawable.y, &box))
2159 #endif
2162 if (spriteTraceGood >= spriteTraceSize)
2164 spriteTraceSize += 10;
2165 Must_have_memory = TRUE; /* XXX */
2166 spriteTrace = (WindowPtr *)xrealloc(
2167 spriteTrace, spriteTraceSize*sizeof(WindowPtr));
2168 Must_have_memory = FALSE; /* XXX */
2170 spriteTrace[spriteTraceGood++] = pWin;
2171 pWin = pWin->firstChild;
2173 else
2174 pWin = pWin->nextSib;
2176 return spriteTrace[spriteTraceGood-1];
2180 * Update the sprite coordinates based on the event. Update the cursor
2181 * position, then update the event with the new coordinates that may have been
2182 * changed. If the window underneath the sprite has changed, change to new
2183 * cursor and send enter/leave events.
2185 static Bool
2186 CheckMotion(xEvent *xE)
2188 WindowPtr prevSpriteWin = sprite.win;
2190 #ifdef PANORAMIX
2191 if(!noPanoramiXExtension)
2192 return XineramaCheckMotion(xE);
2193 #endif
2195 if (xE && !syncEvents.playingEvents)
2197 if (sprite.hot.pScreen != sprite.hotPhys.pScreen)
2199 sprite.hot.pScreen = sprite.hotPhys.pScreen;
2200 ROOT = WindowTable[sprite.hot.pScreen->myNum];
2202 sprite.hot.x = XE_KBPTR.rootX;
2203 sprite.hot.y = XE_KBPTR.rootY;
2204 if (sprite.hot.x < sprite.physLimits.x1)
2205 sprite.hot.x = sprite.physLimits.x1;
2206 else if (sprite.hot.x >= sprite.physLimits.x2)
2207 sprite.hot.x = sprite.physLimits.x2 - 1;
2208 if (sprite.hot.y < sprite.physLimits.y1)
2209 sprite.hot.y = sprite.physLimits.y1;
2210 else if (sprite.hot.y >= sprite.physLimits.y2)
2211 sprite.hot.y = sprite.physLimits.y2 - 1;
2212 #ifdef SHAPE
2213 if (sprite.hotShape)
2214 ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y);
2215 #endif
2216 #ifdef XEVIE
2217 xeviehot.x = sprite.hot.x;
2218 xeviehot.y = sprite.hot.y;
2219 #endif
2220 sprite.hotPhys = sprite.hot;
2221 if ((sprite.hotPhys.x != XE_KBPTR.rootX) ||
2222 (sprite.hotPhys.y != XE_KBPTR.rootY))
2224 (*sprite.hotPhys.pScreen->SetCursorPosition)(
2225 sprite.hotPhys.pScreen,
2226 sprite.hotPhys.x, sprite.hotPhys.y, FALSE);
2228 XE_KBPTR.rootX = sprite.hot.x;
2229 XE_KBPTR.rootY = sprite.hot.y;
2232 #ifdef XEVIE
2233 xeviewin =
2234 #endif
2235 sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y);
2236 #ifdef notyet
2237 if (!(sprite.win->deliverableEvents &
2238 Motion_Filter(inputInfo.pointer->button))
2239 !syncEvents.playingEvents)
2241 /* XXX Do PointerNonInterestBox here */
2243 #endif
2244 if (sprite.win != prevSpriteWin)
2246 if (prevSpriteWin != NullWindow) {
2247 if (!xE)
2248 UpdateCurrentTimeIf();
2249 DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal);
2251 PostNewCursor();
2252 return FALSE;
2254 return TRUE;
2258 * Windows have restructured, we need to update the sprite position and the
2259 * sprite's cursor.
2261 _X_EXPORT void
2262 WindowsRestructured(void)
2264 (void) CheckMotion((xEvent *)NULL);
2267 #ifdef PANORAMIX
2268 /* This was added to support reconfiguration under Xdmx. The problem is
2269 * that if the 0th screen (i.e., WindowTable[0]) is moved to an origin
2270 * other than 0,0, the information in the private sprite structure must
2271 * be updated accordingly, or XYToWindow (and other routines) will not
2272 * compute correctly. */
2273 void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
2275 GrabPtr grab;
2277 if (noPanoramiXExtension) return;
2279 sprite.hot.x -= xoff;
2280 sprite.hot.y -= yoff;
2282 sprite.hotPhys.x -= xoff;
2283 sprite.hotPhys.y -= yoff;
2285 sprite.hotLimits.x1 -= xoff;
2286 sprite.hotLimits.y1 -= yoff;
2287 sprite.hotLimits.x2 -= xoff;
2288 sprite.hotLimits.y2 -= yoff;
2290 if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg1))
2291 REGION_TRANSLATE(sprite.screen, &sprite.Reg1, xoff, yoff);
2292 if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg2))
2293 REGION_TRANSLATE(sprite.screen, &sprite.Reg2, xoff, yoff);
2295 /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
2296 if ((grab = inputInfo.pointer->grab) && grab->confineTo) {
2297 if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
2298 sprite.hotPhys.x = sprite.hotPhys.y = 0;
2299 ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
2300 } else
2301 ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum],
2302 TRUE, FALSE);
2304 #endif
2307 * Set the given window to sane values, display the cursor in the center of
2308 * the screen. Called from main() with the root window on the first screen.
2310 void
2311 DefineInitialRootWindow(WindowPtr win)
2313 ScreenPtr pScreen = win->drawable.pScreen;
2315 sprite.hotPhys.pScreen = pScreen;
2316 sprite.hotPhys.x = pScreen->width / 2;
2317 sprite.hotPhys.y = pScreen->height / 2;
2318 sprite.hot = sprite.hotPhys;
2319 sprite.hotLimits.x2 = pScreen->width;
2320 sprite.hotLimits.y2 = pScreen->height;
2321 #ifdef XEVIE
2322 xeviewin =
2323 #endif
2324 sprite.win = win;
2325 sprite.current = wCursor (win);
2326 sprite.current->refcnt++;
2327 spriteTraceGood = 1;
2328 ROOT = win;
2329 (*pScreen->CursorLimits) (
2330 pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits);
2331 sprite.confined = FALSE;
2332 (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits);
2333 (*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE);
2334 (*pScreen->DisplayCursor) (pScreen, sprite.current);
2336 #ifdef PANORAMIX
2337 if(!noPanoramiXExtension) {
2338 sprite.hotLimits.x1 = -panoramiXdataPtr[0].x;
2339 sprite.hotLimits.y1 = -panoramiXdataPtr[0].y;
2340 sprite.hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x;
2341 sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
2342 sprite.physLimits = sprite.hotLimits;
2343 sprite.confineWin = NullWindow;
2344 #ifdef SHAPE
2345 sprite.hotShape = NullRegion;
2346 #endif
2347 sprite.screen = pScreen;
2348 /* gotta UNINIT these someplace */
2349 REGION_NULL(pScreen, &sprite.Reg1);
2350 REGION_NULL(pScreen, &sprite.Reg2);
2352 #endif
2356 * This does not take any shortcuts, and even ignores its argument, since
2357 * it does not happen very often, and one has to walk up the tree since
2358 * this might be a newly instantiated cursor for an intermediate window
2359 * between the one the pointer is in and the one that the last cursor was
2360 * instantiated from.
2362 void
2363 WindowHasNewCursor(WindowPtr pWin)
2365 PostNewCursor();
2368 _X_EXPORT void
2369 NewCurrentScreen(ScreenPtr newScreen, int x, int y)
2371 sprite.hotPhys.x = x;
2372 sprite.hotPhys.y = y;
2373 #ifdef PANORAMIX
2374 if(!noPanoramiXExtension) {
2375 sprite.hotPhys.x += panoramiXdataPtr[newScreen->myNum].x -
2376 panoramiXdataPtr[0].x;
2377 sprite.hotPhys.y += panoramiXdataPtr[newScreen->myNum].y -
2378 panoramiXdataPtr[0].y;
2379 if (newScreen != sprite.screen) {
2380 sprite.screen = newScreen;
2381 /* Make sure we tell the DDX to update its copy of the screen */
2382 if(sprite.confineWin)
2383 XineramaConfineCursorToWindow(sprite.confineWin, TRUE);
2384 else
2385 XineramaConfineCursorToWindow(WindowTable[0], TRUE);
2386 /* if the pointer wasn't confined, the DDX won't get
2387 told of the pointer warp so we reposition it here */
2388 if(!syncEvents.playingEvents)
2389 (*sprite.screen->SetCursorPosition)(sprite.screen,
2390 sprite.hotPhys.x + panoramiXdataPtr[0].x -
2391 panoramiXdataPtr[sprite.screen->myNum].x,
2392 sprite.hotPhys.y + panoramiXdataPtr[0].y -
2393 panoramiXdataPtr[sprite.screen->myNum].y, FALSE);
2395 } else
2396 #endif
2397 if (newScreen != sprite.hotPhys.pScreen)
2398 ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE);
2401 #ifdef PANORAMIX
2403 static Bool
2404 XineramaPointInWindowIsVisible(
2405 WindowPtr pWin,
2406 int x,
2407 int y
2410 ScreenPtr pScreen = pWin->drawable.pScreen;
2411 BoxRec box;
2412 int i, xoff, yoff;
2414 if (!pWin->realized) return FALSE;
2416 if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box))
2417 return TRUE;
2419 if(!XineramaSetWindowPntrs(pWin)) return FALSE;
2421 xoff = x + panoramiXdataPtr[0].x;
2422 yoff = y + panoramiXdataPtr[0].y;
2424 for(i = 1; i < PanoramiXNumScreens; i++) {
2425 pWin = sprite.windows[i];
2426 pScreen = pWin->drawable.pScreen;
2427 x = xoff - panoramiXdataPtr[i].x;
2428 y = yoff - panoramiXdataPtr[i].y;
2430 if(POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)
2431 && (!wInputShape(pWin) ||
2432 POINT_IN_REGION(pWin->drawable.pScreen,
2433 wInputShape(pWin),
2434 x - pWin->drawable.x,
2435 y - pWin->drawable.y, &box)))
2436 return TRUE;
2440 return FALSE;
2443 static int
2444 XineramaWarpPointer(ClientPtr client)
2446 WindowPtr dest = NULL;
2447 int x, y, rc;
2449 REQUEST(xWarpPointerReq);
2452 if (stuff->dstWid != None) {
2453 rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
2454 if (rc != Success)
2455 return rc;
2457 x = sprite.hotPhys.x;
2458 y = sprite.hotPhys.y;
2460 if (stuff->srcWid != None)
2462 int winX, winY;
2463 XID winID = stuff->srcWid;
2464 WindowPtr source;
2466 rc = dixLookupWindow(&source, winID, client, DixReadAccess);
2467 if (rc != Success)
2468 return rc;
2470 winX = source->drawable.x;
2471 winY = source->drawable.y;
2472 if(source == WindowTable[0]) {
2473 winX -= panoramiXdataPtr[0].x;
2474 winY -= panoramiXdataPtr[0].y;
2476 if (x < winX + stuff->srcX ||
2477 y < winY + stuff->srcY ||
2478 (stuff->srcWidth != 0 &&
2479 winX + stuff->srcX + (int)stuff->srcWidth < x) ||
2480 (stuff->srcHeight != 0 &&
2481 winY + stuff->srcY + (int)stuff->srcHeight < y) ||
2482 !XineramaPointInWindowIsVisible(source, x, y))
2483 return Success;
2485 if (dest) {
2486 x = dest->drawable.x;
2487 y = dest->drawable.y;
2488 if(dest == WindowTable[0]) {
2489 x -= panoramiXdataPtr[0].x;
2490 y -= panoramiXdataPtr[0].y;
2494 x += stuff->dstX;
2495 y += stuff->dstY;
2497 if (x < sprite.physLimits.x1)
2498 x = sprite.physLimits.x1;
2499 else if (x >= sprite.physLimits.x2)
2500 x = sprite.physLimits.x2 - 1;
2501 if (y < sprite.physLimits.y1)
2502 y = sprite.physLimits.y1;
2503 else if (y >= sprite.physLimits.y2)
2504 y = sprite.physLimits.y2 - 1;
2505 if (sprite.hotShape)
2506 ConfineToShape(sprite.hotShape, &x, &y);
2508 XineramaSetCursorPosition(x, y, TRUE);
2510 return Success;
2513 #endif
2517 * Server-side protocol handling for WarpPointer request.
2518 * Warps the cursor position to the coordinates given in the request.
2521 ProcWarpPointer(ClientPtr client)
2523 WindowPtr dest = NULL;
2524 int x, y, rc;
2525 ScreenPtr newScreen;
2527 REQUEST(xWarpPointerReq);
2529 REQUEST_SIZE_MATCH(xWarpPointerReq);
2531 #ifdef PANORAMIX
2532 if(!noPanoramiXExtension)
2533 return XineramaWarpPointer(client);
2534 #endif
2536 if (stuff->dstWid != None) {
2537 rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
2538 if (rc != Success)
2539 return rc;
2541 x = sprite.hotPhys.x;
2542 y = sprite.hotPhys.y;
2544 if (stuff->srcWid != None)
2546 int winX, winY;
2547 XID winID = stuff->srcWid;
2548 WindowPtr source;
2550 rc = dixLookupWindow(&source, winID, client, DixReadAccess);
2551 if (rc != Success)
2552 return rc;
2554 winX = source->drawable.x;
2555 winY = source->drawable.y;
2556 if (source->drawable.pScreen != sprite.hotPhys.pScreen ||
2557 x < winX + stuff->srcX ||
2558 y < winY + stuff->srcY ||
2559 (stuff->srcWidth != 0 &&
2560 winX + stuff->srcX + (int)stuff->srcWidth < x) ||
2561 (stuff->srcHeight != 0 &&
2562 winY + stuff->srcY + (int)stuff->srcHeight < y) ||
2563 !PointInWindowIsVisible(source, x, y))
2564 return Success;
2566 if (dest)
2568 x = dest->drawable.x;
2569 y = dest->drawable.y;
2570 newScreen = dest->drawable.pScreen;
2571 } else
2572 newScreen = sprite.hotPhys.pScreen;
2574 x += stuff->dstX;
2575 y += stuff->dstY;
2577 if (x < 0)
2578 x = 0;
2579 else if (x >= newScreen->width)
2580 x = newScreen->width - 1;
2581 if (y < 0)
2582 y = 0;
2583 else if (y >= newScreen->height)
2584 y = newScreen->height - 1;
2586 if (newScreen == sprite.hotPhys.pScreen)
2588 if (x < sprite.physLimits.x1)
2589 x = sprite.physLimits.x1;
2590 else if (x >= sprite.physLimits.x2)
2591 x = sprite.physLimits.x2 - 1;
2592 if (y < sprite.physLimits.y1)
2593 y = sprite.physLimits.y1;
2594 else if (y >= sprite.physLimits.y2)
2595 y = sprite.physLimits.y2 - 1;
2596 #if defined(SHAPE)
2597 if (sprite.hotShape)
2598 ConfineToShape(sprite.hotShape, &x, &y);
2599 #endif
2600 (*newScreen->SetCursorPosition)(newScreen, x, y, TRUE);
2602 else if (!PointerConfinedToScreen())
2604 NewCurrentScreen(newScreen, x, y);
2606 return Success;
2609 static Bool
2610 BorderSizeNotEmpty(WindowPtr pWin)
2612 if(REGION_NOTEMPTY(sprite.hotPhys.pScreen, &pWin->borderSize))
2613 return TRUE;
2615 #ifdef PANORAMIX
2616 if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) {
2617 int i;
2619 for(i = 1; i < PanoramiXNumScreens; i++) {
2620 if(REGION_NOTEMPTY(sprite.screen, &sprite.windows[i]->borderSize))
2621 return TRUE;
2624 #endif
2625 return FALSE;
2628 /**
2629 * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
2630 * passive grab set on the window to be activated.
2631 * If a passive grab is activated, the event will be delivered to the client.
2633 * @param pWin The window that may be subject to a passive grab.
2634 * @param device Device that caused the event.
2635 * @param xE List of events (multiple ones for DeviceMotionNotify)
2636 * @count number of elements in xE.
2639 static Bool
2640 CheckPassiveGrabsOnWindow(
2641 WindowPtr pWin,
2642 DeviceIntPtr device,
2643 xEvent *xE,
2644 int count)
2646 GrabPtr grab = wPassiveGrabs(pWin);
2647 GrabRec tempGrab;
2648 xEvent *dxE;
2650 if (!grab)
2651 return FALSE;
2652 tempGrab.window = pWin;
2653 tempGrab.device = device;
2654 tempGrab.type = xE->u.u.type;
2655 tempGrab.detail.exact = xE->u.u.detail;
2656 tempGrab.detail.pMask = NULL;
2657 tempGrab.modifiersDetail.pMask = NULL;
2658 for (; grab; grab = grab->next)
2660 #ifdef XKB
2661 DeviceIntPtr gdev;
2662 XkbSrvInfoPtr xkbi;
2664 gdev= grab->modifierDevice;
2665 xkbi= gdev->key->xkbInfo;
2666 #endif
2667 tempGrab.modifierDevice = grab->modifierDevice;
2668 if ((device == grab->modifierDevice) &&
2669 ((xE->u.u.type == KeyPress)
2670 #if defined(XINPUT) && defined(XKB)
2671 || (xE->u.u.type == DeviceKeyPress)
2672 #endif
2674 tempGrab.modifiersDetail.exact =
2675 #ifdef XKB
2676 (noXkbExtension?gdev->key->prev_state:xkbi->state.grab_mods);
2677 #else
2678 grab->modifierDevice->key->prev_state;
2679 #endif
2680 else
2681 tempGrab.modifiersDetail.exact =
2682 #ifdef XKB
2683 (noXkbExtension ? gdev->key->state : xkbi->state.grab_mods);
2684 #else
2685 grab->modifierDevice->key->state;
2686 #endif
2687 if (GrabMatchesSecond(&tempGrab, grab) &&
2688 (!grab->confineTo ||
2689 (grab->confineTo->realized &&
2690 BorderSizeNotEmpty(grab->confineTo))))
2692 if (!XaceHook(XACE_DEVICE_ACCESS, wClient(pWin), device, FALSE))
2693 return FALSE;
2694 #ifdef XKB
2695 if (!noXkbExtension) {
2696 XE_KBPTR.state &= 0x1f00;
2697 XE_KBPTR.state |=
2698 tempGrab.modifiersDetail.exact&(~0x1f00);
2700 #endif
2701 (*device->ActivateGrab)(device, grab, currentTime, TRUE);
2703 FixUpEventFromWindow(xE, grab->window, None, TRUE);
2705 (void) TryClientEvents(rClient(grab), xE, count,
2706 filters[xE->u.u.type],
2707 filters[xE->u.u.type], grab);
2709 if (device->sync.state == FROZEN_NO_EVENT)
2711 if (device->sync.evcount < count)
2713 Must_have_memory = TRUE; /* XXX */
2714 device->sync.event = (xEvent *)xrealloc(device->sync.event,
2715 count*
2716 sizeof(xEvent));
2717 Must_have_memory = FALSE; /* XXX */
2719 device->sync.evcount = count;
2720 for (dxE = device->sync.event; --count >= 0; dxE++, xE++)
2721 *dxE = *xE;
2722 device->sync.state = FROZEN_WITH_EVENT;
2724 return TRUE;
2727 return FALSE;
2731 * CheckDeviceGrabs handles both keyboard and pointer events that may cause
2732 * a passive grab to be activated.
2734 * If the event is a keyboard event, the ancestors of the focus window are
2735 * traced down and tried to see if they have any passive grabs to be
2736 * activated. If the focus window itself is reached and it's descendants
2737 * contain the pointer, the ancestors of the window that the pointer is in
2738 * are then traced down starting at the focus window, otherwise no grabs are
2739 * activated.
2740 * If the event is a pointer event, the ancestors of the window that the
2741 * pointer is in are traced down starting at the root until CheckPassiveGrabs
2742 * causes a passive grab to activate or all the windows are
2743 * tried. PRH
2745 * If a grab is activated, the event has been sent to the client already!
2747 * @param device The device that caused the event.
2748 * @param xE The event to handle (most likely {Device}ButtonPress).
2749 * @param count Number of events in list.
2750 * @return TRUE if a grab has been activated or false otherwise.
2753 Bool
2754 CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE,
2755 int checkFirst, int count)
2757 int i;
2758 WindowPtr pWin = NULL;
2759 FocusClassPtr focus = device->focus;
2761 if (((xE->u.u.type == ButtonPress)
2762 #if defined(XINPUT) && defined(XKB)
2763 || (xE->u.u.type == DeviceButtonPress)
2764 #endif
2765 ) && (device->button->buttonsDown != 1))
2766 return FALSE;
2768 i = checkFirst;
2770 if (focus)
2772 for (; i < focus->traceGood; i++)
2774 pWin = focus->trace[i];
2775 if (pWin->optional &&
2776 CheckPassiveGrabsOnWindow(pWin, device, xE, count))
2777 return TRUE;
2780 if ((focus->win == NoneWin) ||
2781 (i >= spriteTraceGood) ||
2782 ((i > checkFirst) && (pWin != spriteTrace[i-1])))
2783 return FALSE;
2786 for (; i < spriteTraceGood; i++)
2788 pWin = spriteTrace[i];
2789 if (pWin->optional &&
2790 CheckPassiveGrabsOnWindow(pWin, device, xE, count))
2791 return TRUE;
2794 return FALSE;
2798 * Called for keyboard events to deliver event to whatever client owns the
2799 * focus. Event is delivered to the keyboard's focus window, the root window
2800 * or to the window owning the input focus.
2802 * @param keybd The keyboard originating the event.
2803 * @param xE The event list.
2804 * @param window Window underneath the sprite.
2805 * @param count number of events in xE.
2807 void
2808 DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
2810 WindowPtr focus = keybd->focus->win;
2811 int mskidx = 0;
2813 if (focus == FollowKeyboardWin)
2814 focus = inputInfo.keyboard->focus->win;
2815 if (!focus)
2816 return;
2817 if (focus == PointerRootWin)
2819 DeliverDeviceEvents(window, xE, NullGrab, NullWindow, keybd, count);
2820 return;
2822 if ((focus == window) || IsParent(focus, window))
2824 if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count))
2825 return;
2827 /* just deliver it to the focus window */
2828 FixUpEventFromWindow(xE, focus, None, FALSE);
2829 if (xE->u.u.type & EXTENSION_EVENT_BASE)
2830 mskidx = keybd->id;
2831 (void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type],
2832 NullGrab, mskidx);
2836 * Deliver an event from a device that is currently grabbed. Uses
2837 * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the
2838 * grab. If not, TryClientEvents() is used.
2840 * @param deactivateGrab True if the device's grab should be deactivated.
2842 void
2843 DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
2844 Bool deactivateGrab, int count)
2846 GrabPtr grab = thisDev->grab;
2847 int deliveries = 0;
2848 DeviceIntPtr dev;
2849 xEvent *dxE;
2851 if (grab->ownerEvents)
2853 WindowPtr focus;
2855 if (thisDev->focus)
2857 focus = thisDev->focus->win;
2858 if (focus == FollowKeyboardWin)
2859 focus = inputInfo.keyboard->focus->win;
2861 else
2862 focus = PointerRootWin;
2863 if (focus == PointerRootWin)
2864 deliveries = DeliverDeviceEvents(sprite.win, xE, grab, NullWindow,
2865 thisDev, count);
2866 else if (focus && (focus == sprite.win || IsParent(focus, sprite.win)))
2867 deliveries = DeliverDeviceEvents(sprite.win, xE, grab, focus,
2868 thisDev, count);
2869 else if (focus)
2870 deliveries = DeliverDeviceEvents(focus, xE, grab, focus,
2871 thisDev, count);
2873 if (!deliveries)
2875 FixUpEventFromWindow(xE, grab->window, None, TRUE);
2876 deliveries = TryClientEvents(rClient(grab), xE, count,
2877 (Mask)grab->eventMask,
2878 filters[xE->u.u.type], grab);
2879 if (deliveries && (xE->u.u.type == MotionNotify
2880 #ifdef XINPUT
2881 || xE->u.u.type == DeviceMotionNotify
2882 #endif
2884 thisDev->valuator->motionHintWindow = grab->window;
2886 if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify
2887 #ifdef XINPUT
2888 && xE->u.u.type != DeviceMotionNotify
2889 #endif
2891 switch (thisDev->sync.state)
2893 case FREEZE_BOTH_NEXT_EVENT:
2894 for (dev = inputInfo.devices; dev; dev = dev->next)
2896 if (dev == thisDev)
2897 continue;
2898 FreezeThaw(dev, TRUE);
2899 if ((dev->sync.state == FREEZE_BOTH_NEXT_EVENT) &&
2900 (CLIENT_BITS(dev->grab->resource) ==
2901 CLIENT_BITS(thisDev->grab->resource)))
2902 dev->sync.state = FROZEN_NO_EVENT;
2903 else
2904 dev->sync.other = thisDev->grab;
2906 /* fall through */
2907 case FREEZE_NEXT_EVENT:
2908 thisDev->sync.state = FROZEN_WITH_EVENT;
2909 FreezeThaw(thisDev, TRUE);
2910 if (thisDev->sync.evcount < count)
2912 Must_have_memory = TRUE; /* XXX */
2913 thisDev->sync.event = (xEvent *)xrealloc(thisDev->sync.event,
2914 count*sizeof(xEvent));
2915 Must_have_memory = FALSE; /* XXX */
2917 thisDev->sync.evcount = count;
2918 for (dxE = thisDev->sync.event; --count >= 0; dxE++, xE++)
2919 *dxE = *xE;
2920 break;
2925 * Main keyboard event processing function for core keyboard events.
2926 * Updates the events fields from the current pointer state and delivers the
2927 * event.
2929 * For key events, xE will always be a single event.
2931 * @param xE Event list
2932 * @param keybd The device that caused an event.
2933 * @param count Number of elements in xE.
2935 void
2936 #ifdef XKB
2937 CoreProcessKeyboardEvent (xEvent *xE, DeviceIntPtr keybd, int count)
2938 #else
2939 ProcessKeyboardEvent (xEvent *xE, DeviceIntPtr keybd, int count)
2940 #endif
2942 int key, bit;
2943 BYTE *kptr;
2944 int i;
2945 CARD8 modifiers;
2946 CARD16 mask;
2947 GrabPtr grab = keybd->grab;
2948 Bool deactivateGrab = FALSE;
2949 KeyClassPtr keyc = keybd->key;
2950 #ifdef XEVIE
2951 static Window rootWin = 0;
2953 if(!xeviegrabState && xevieFlag && clients[xevieClientIndex] &&
2954 (xevieMask & xevieFilters[xE->u.u.type])) {
2955 key = xE->u.u.detail;
2956 kptr = &keyc->down[key >> 3];
2957 bit = 1 << (key & 7);
2958 if((xE->u.u.type == KeyPress && (*kptr & bit)) ||
2959 (xE->u.u.type == KeyRelease && !(*kptr & bit)))
2960 {} else {
2961 #ifdef XKB
2962 if(!noXkbExtension)
2963 xevieKBEventSent = 1;
2964 #endif
2965 if(!xevieKBEventSent)
2967 xeviekb = keybd;
2968 if(!rootWin) {
2969 rootWin = GetCurrentRootWindow()->drawable.id;
2971 xE->u.keyButtonPointer.event = xeviewin->drawable.id;
2972 xE->u.keyButtonPointer.root = rootWin;
2973 xE->u.keyButtonPointer.child = (xeviewin->firstChild) ? xeviewin->firstChild->
2974 drawable.id:0;
2975 xE->u.keyButtonPointer.rootX = xeviehot.x;
2976 xE->u.keyButtonPointer.rootY = xeviehot.y;
2977 xE->u.keyButtonPointer.state = keyc->state;
2978 WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE);
2979 #ifdef XKB
2980 if(noXkbExtension)
2981 #endif
2982 return;
2983 } else {
2984 xevieKBEventSent = 0;
2988 #endif
2990 if (!syncEvents.playingEvents)
2992 NoticeTime(xE);
2993 if (DeviceEventCallback)
2995 DeviceEventInfoRec eventinfo;
2996 eventinfo.events = xE;
2997 eventinfo.count = count;
2998 CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
3001 #ifdef XEVIE
3002 /* fix for bug5094030: don't change the state bit if the event is from XEvIE client */
3003 if(!(!xeviegrabState && xevieFlag && clients[xevieClientIndex] &&
3004 (xevieMask & xevieFilters[xE->u.u.type]
3005 #ifdef XKB
3006 && !noXkbExtension
3007 #endif
3009 #endif
3010 XE_KBPTR.state = (keyc->state | inputInfo.pointer->button->state);
3011 XE_KBPTR.rootX = sprite.hot.x;
3012 XE_KBPTR.rootY = sprite.hot.y;
3013 key = xE->u.u.detail;
3014 kptr = &keyc->down[key >> 3];
3015 bit = 1 << (key & 7);
3016 modifiers = keyc->modifierMap[key];
3017 #if defined(XKB) && defined(XEVIE)
3018 if(!noXkbExtension && !xeviegrabState &&
3019 xevieFlag && clients[xevieClientIndex] &&
3020 (xevieMask & xevieFilters[xE->u.u.type])) {
3021 switch(xE->u.u.type) {
3022 case KeyPress: *kptr &= ~bit; break;
3023 case KeyRelease: *kptr |= bit; break;
3026 #endif
3028 switch (xE->u.u.type)
3030 case KeyPress:
3031 if (*kptr & bit) /* allow ddx to generate multiple downs */
3033 if (!modifiers)
3035 xE->u.u.type = KeyRelease;
3036 (*keybd->public.processInputProc)(xE, keybd, count);
3037 xE->u.u.type = KeyPress;
3038 /* release can have side effects, don't fall through */
3039 (*keybd->public.processInputProc)(xE, keybd, count);
3041 return;
3043 inputInfo.pointer->valuator->motionHintWindow = NullWindow;
3044 *kptr |= bit;
3045 keyc->prev_state = keyc->state;
3046 for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
3048 if (mask & modifiers)
3050 /* This key affects modifier "i" */
3051 keyc->modifierKeyCount[i]++;
3052 keyc->state |= mask;
3053 modifiers &= ~mask;
3056 if (!grab && CheckDeviceGrabs(keybd, xE, 0, count))
3058 keybd->activatingKey = key;
3059 return;
3061 break;
3062 case KeyRelease:
3063 if (!(*kptr & bit)) /* guard against duplicates */
3064 return;
3065 inputInfo.pointer->valuator->motionHintWindow = NullWindow;
3066 *kptr &= ~bit;
3067 keyc->prev_state = keyc->state;
3068 for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
3070 if (mask & modifiers) {
3071 /* This key affects modifier "i" */
3072 if (--keyc->modifierKeyCount[i] <= 0) {
3073 keyc->state &= ~mask;
3074 keyc->modifierKeyCount[i] = 0;
3076 modifiers &= ~mask;
3079 if (keybd->fromPassiveGrab && (key == keybd->activatingKey))
3080 deactivateGrab = TRUE;
3081 break;
3082 default:
3083 FatalError("Impossible keyboard event");
3085 if (grab)
3086 DeliverGrabbedEvent(xE, keybd, deactivateGrab, count);
3087 else
3088 DeliverFocusedEvent(keybd, xE, sprite.win, count);
3089 if (deactivateGrab)
3090 (*keybd->DeactivateGrab)(keybd);
3092 XaceHook(XACE_KEY_AVAIL, xE, keybd, count);
3095 #ifdef XKB
3096 /* This function is used to set the key pressed or key released state -
3097 this is only used when the pressing of keys does not cause
3098 CoreProcessKeyEvent to be called, as in for example Mouse Keys.
3100 void
3101 FixKeyState (xEvent *xE, DeviceIntPtr keybd)
3103 int key, bit;
3104 BYTE *kptr;
3105 KeyClassPtr keyc = keybd->key;
3107 key = xE->u.u.detail;
3108 kptr = &keyc->down[key >> 3];
3109 bit = 1 << (key & 7);
3111 if (((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) {
3112 DebugF("FixKeyState: Key %d %s\n",key,
3113 (xE->u.u.type==KeyPress?"down":"up"));
3116 switch (xE->u.u.type)
3118 case KeyPress:
3119 *kptr |= bit;
3120 break;
3121 case KeyRelease:
3122 *kptr &= ~bit;
3123 break;
3124 default:
3125 FatalError("Impossible keyboard event");
3128 #endif
3130 /**
3131 * Main pointer event processing function for core pointer events.
3132 * For motion events: update the sprite.
3133 * For all other events: Update the event fields based on the current sprite
3134 * state.
3136 * For core pointer events, xE will always be a single event.
3138 * @param xE Event list
3139 * @param mouse The device that caused an event.
3140 * @param count Number of elements in xE.
3142 void
3143 #ifdef XKB
3144 CoreProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
3145 #else
3146 ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
3147 #endif
3149 GrabPtr grab = mouse->grab;
3150 Bool deactivateGrab = FALSE;
3151 ButtonClassPtr butc = mouse->button;
3152 #ifdef XKB
3153 XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo;
3154 #endif
3155 #ifdef XEVIE
3156 if(xevieFlag && clients[xevieClientIndex] && !xeviegrabState &&
3157 (xevieMask & xevieFilters[xE->u.u.type])) {
3158 if(xevieEventSent)
3159 xevieEventSent = 0;
3160 else {
3161 xeviemouse = mouse;
3162 WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE);
3163 return;
3166 #endif
3168 if (!syncEvents.playingEvents)
3169 NoticeTime(xE)
3170 XE_KBPTR.state = (butc->state | (
3171 #ifdef XKB
3172 (noXkbExtension ?
3173 inputInfo.keyboard->key->state :
3174 xkbi->state.grab_mods)
3175 #else
3176 inputInfo.keyboard->key->state
3177 #endif
3180 NoticeTime(xE);
3181 if (DeviceEventCallback)
3183 DeviceEventInfoRec eventinfo;
3184 /* see comment in EnqueueEvents regarding the next three lines */
3185 if (xE->u.u.type == MotionNotify)
3186 XE_KBPTR.root =
3187 WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id;
3188 eventinfo.events = xE;
3189 eventinfo.count = count;
3190 CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
3193 if (xE->u.u.type != MotionNotify)
3195 int key;
3196 BYTE *kptr;
3197 int bit;
3199 XE_KBPTR.rootX = sprite.hot.x;
3200 XE_KBPTR.rootY = sprite.hot.y;
3202 key = xE->u.u.detail;
3203 kptr = &butc->down[key >> 3];
3204 bit = 1 << (key & 7);
3205 switch (xE->u.u.type)
3207 case ButtonPress:
3208 mouse->valuator->motionHintWindow = NullWindow;
3209 if (!(*kptr & bit))
3210 butc->buttonsDown++;
3211 butc->motionMask = ButtonMotionMask;
3212 *kptr |= bit;
3213 if (xE->u.u.detail == 0)
3214 return;
3215 if (xE->u.u.detail <= 5)
3216 butc->state |= (Button1Mask >> 1) << xE->u.u.detail;
3217 filters[MotionNotify] = Motion_Filter(butc);
3218 if (!grab)
3219 if (CheckDeviceGrabs(mouse, xE, 0, count))
3220 return;
3221 break;
3222 case ButtonRelease:
3223 mouse->valuator->motionHintWindow = NullWindow;
3224 if (*kptr & bit)
3225 --butc->buttonsDown;
3226 if (!butc->buttonsDown)
3227 butc->motionMask = 0;
3228 *kptr &= ~bit;
3229 if (xE->u.u.detail == 0)
3230 return;
3231 if (xE->u.u.detail <= 5)
3232 butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
3233 filters[MotionNotify] = Motion_Filter(butc);
3234 if (!butc->state && mouse->fromPassiveGrab)
3235 deactivateGrab = TRUE;
3236 break;
3237 default:
3238 FatalError("bogus pointer event from ddx");
3241 else if (!CheckMotion(xE))
3242 return;
3243 if (grab)
3244 DeliverGrabbedEvent(xE, mouse, deactivateGrab, count);
3245 else
3246 DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow,
3247 mouse, count);
3248 if (deactivateGrab)
3249 (*mouse->DeactivateGrab)(mouse);
3252 #define AtMostOneClient \
3253 (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
3256 * Recalculate which events may be deliverable for the given window.
3257 * Recalculated mask is used for quicker determination which events may be
3258 * delivered to a window.
3260 * The otherEventMasks on a WindowOptional is the combination of all event
3261 * masks set by all clients on the window.
3262 * deliverableEventMask is the combination of the eventMask and the
3263 * otherEventMask.
3265 * Traverses to siblings and parents of the window.
3267 void
3268 RecalculateDeliverableEvents(pWin)
3269 WindowPtr pWin;
3271 OtherClients *others;
3272 WindowPtr pChild;
3274 pChild = pWin;
3275 while (1)
3277 if (pChild->optional)
3279 pChild->optional->otherEventMasks = 0;
3280 for (others = wOtherClients(pChild); others; others = others->next)
3282 pChild->optional->otherEventMasks |= others->mask;
3285 pChild->deliverableEvents = pChild->eventMask|
3286 wOtherEventMasks(pChild);
3287 if (pChild->parent)
3288 pChild->deliverableEvents |=
3289 (pChild->parent->deliverableEvents &
3290 ~wDontPropagateMask(pChild) & PropagateMask);
3291 if (pChild->firstChild)
3293 pChild = pChild->firstChild;
3294 continue;
3296 while (!pChild->nextSib && (pChild != pWin))
3297 pChild = pChild->parent;
3298 if (pChild == pWin)
3299 break;
3300 pChild = pChild->nextSib;
3306 * \param value must conform to DeleteType
3309 OtherClientGone(pointer value, XID id)
3311 OtherClientsPtr other, prev;
3312 WindowPtr pWin = (WindowPtr)value;
3314 prev = 0;
3315 for (other = wOtherClients(pWin); other; other = other->next)
3317 if (other->resource == id)
3319 if (prev)
3320 prev->next = other->next;
3321 else
3323 if (!(pWin->optional->otherClients = other->next))
3324 CheckWindowOptionalNeed (pWin);
3326 xfree(other);
3327 RecalculateDeliverableEvents(pWin);
3328 return(Success);
3330 prev = other;
3332 FatalError("client not on event list");
3333 /*NOTREACHED*/
3334 return -1; /* make compiler happy */
3338 EventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
3340 Mask check;
3341 OtherClients * others;
3343 if (mask & ~AllEventMasks)
3345 client->errorValue = mask;
3346 return BadValue;
3348 check = (mask & AtMostOneClient);
3349 if (check & (pWin->eventMask|wOtherEventMasks(pWin)))
3350 { /* It is illegal for two different
3351 clients to select on any of the
3352 events for AtMostOneClient. However,
3353 it is OK, for some client to
3354 continue selecting on one of those
3355 events. */
3356 if ((wClient(pWin) != client) && (check & pWin->eventMask))
3357 return BadAccess;
3358 for (others = wOtherClients (pWin); others; others = others->next)
3360 if (!SameClient(others, client) && (check & others->mask))
3361 return BadAccess;
3364 if (wClient (pWin) == client)
3366 check = pWin->eventMask;
3367 pWin->eventMask = mask;
3369 else
3371 for (others = wOtherClients (pWin); others; others = others->next)
3373 if (SameClient(others, client))
3375 check = others->mask;
3376 if (mask == 0)
3378 FreeResource(others->resource, RT_NONE);
3379 return Success;
3381 else
3382 others->mask = mask;
3383 goto maskSet;
3386 check = 0;
3387 if (!pWin->optional && !MakeWindowOptional (pWin))
3388 return BadAlloc;
3389 others = (OtherClients *) xalloc(sizeof(OtherClients));
3390 if (!others)
3391 return BadAlloc;
3392 others->mask = mask;
3393 others->resource = FakeClientID(client->index);
3394 others->next = pWin->optional->otherClients;
3395 pWin->optional->otherClients = others;
3396 if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin))
3397 return BadAlloc;
3399 maskSet:
3400 if ((inputInfo.pointer->valuator->motionHintWindow == pWin) &&
3401 (mask & PointerMotionHintMask) &&
3402 !(check & PointerMotionHintMask) &&
3403 !inputInfo.pointer->grab)
3404 inputInfo.pointer->valuator->motionHintWindow = NullWindow;
3405 RecalculateDeliverableEvents(pWin);
3406 return Success;
3410 EventSuppressForWindow(WindowPtr pWin, ClientPtr client,
3411 Mask mask, Bool *checkOptional)
3413 int i, free;
3415 if (mask & ~PropagateMask)
3417 client->errorValue = mask;
3418 return BadValue;
3420 if (pWin->dontPropagate)
3421 DontPropagateRefCnts[pWin->dontPropagate]--;
3422 if (!mask)
3423 i = 0;
3424 else
3426 for (i = DNPMCOUNT, free = 0; --i > 0; )
3428 if (!DontPropagateRefCnts[i])
3429 free = i;
3430 else if (mask == DontPropagateMasks[i])
3431 break;
3433 if (!i && free)
3435 i = free;
3436 DontPropagateMasks[i] = mask;
3439 if (i || !mask)
3441 pWin->dontPropagate = i;
3442 if (i)
3443 DontPropagateRefCnts[i]++;
3444 if (pWin->optional)
3446 pWin->optional->dontPropagateMask = mask;
3447 *checkOptional = TRUE;
3450 else
3452 if (!pWin->optional && !MakeWindowOptional (pWin))
3454 if (pWin->dontPropagate)
3455 DontPropagateRefCnts[pWin->dontPropagate]++;
3456 return BadAlloc;
3458 pWin->dontPropagate = 0;
3459 pWin->optional->dontPropagateMask = mask;
3461 RecalculateDeliverableEvents(pWin);
3462 return Success;
3466 * @return The window that is the first ancestor of both a and b.
3468 static WindowPtr
3469 CommonAncestor(
3470 WindowPtr a,
3471 WindowPtr b)
3473 for (b = b->parent; b; b = b->parent)
3474 if (IsParent(b, a)) return b;
3475 return NullWindow;
3479 * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
3480 * The core devices are used to fill in the event fields.
3482 static void
3483 EnterLeaveEvent(
3484 int type,
3485 int mode,
3486 int detail,
3487 WindowPtr pWin,
3488 Window child)
3490 xEvent event;
3491 DeviceIntPtr keybd = inputInfo.keyboard;
3492 WindowPtr focus;
3493 DeviceIntPtr mouse = inputInfo.pointer;
3494 GrabPtr grab = mouse->grab;
3495 Mask mask;
3497 if ((pWin == mouse->valuator->motionHintWindow) &&
3498 (detail != NotifyInferior))
3499 mouse->valuator->motionHintWindow = NullWindow;
3500 if (grab)
3502 mask = (pWin == grab->window) ? grab->eventMask : 0;
3503 if (grab->ownerEvents)
3504 mask |= EventMaskForClient(pWin, rClient(grab));
3506 else
3508 mask = pWin->eventMask | wOtherEventMasks(pWin);
3510 if (mask & filters[type])
3512 event.u.u.type = type;
3513 event.u.u.detail = detail;
3514 event.u.enterLeave.time = currentTime.milliseconds;
3515 event.u.enterLeave.rootX = sprite.hot.x;
3516 event.u.enterLeave.rootY = sprite.hot.y;
3517 /* Counts on the same initial structure of crossing & button events! */
3518 FixUpEventFromWindow(&event, pWin, None, FALSE);
3519 /* Enter/Leave events always set child */
3520 event.u.enterLeave.child = child;
3521 event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
3522 ELFlagSameScreen : 0;
3523 #ifdef XKB
3524 if (!noXkbExtension) {
3525 event.u.enterLeave.state = mouse->button->state & 0x1f00;
3526 event.u.enterLeave.state |=
3527 XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
3528 } else
3529 #endif
3530 event.u.enterLeave.state = keybd->key->state | mouse->button->state;
3531 event.u.enterLeave.mode = mode;
3532 focus = keybd->focus->win;
3533 if ((focus != NoneWin) &&
3534 ((pWin == focus) || (focus == PointerRootWin) ||
3535 IsParent(focus, pWin)))
3536 event.u.enterLeave.flags |= ELFlagFocus;
3537 if (grab)
3538 (void)TryClientEvents(rClient(grab), &event, 1, mask,
3539 filters[type], grab);
3540 else
3541 (void)DeliverEventsToWindow(pWin, &event, 1, filters[type],
3542 NullGrab, 0);
3544 if ((type == EnterNotify) && (mask & KeymapStateMask))
3546 xKeymapEvent ke;
3547 ClientPtr client = grab ? rClient(grab)
3548 : clients[CLIENT_ID(pWin->drawable.id)];
3549 if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, FALSE))
3550 memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31);
3551 else
3552 bzero((char *)&ke.map[0], 31);
3554 ke.type = KeymapNotify;
3555 if (grab)
3556 (void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask,
3557 KeymapStateMask, grab);
3558 else
3559 (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1,
3560 KeymapStateMask, NullGrab, 0);
3565 * Send enter notifies to all parent windows up to ancestor.
3566 * This function recurses.
3568 static void
3569 EnterNotifies(WindowPtr ancestor, WindowPtr child, int mode, int detail)
3571 WindowPtr parent = child->parent;
3573 if (ancestor == parent)
3574 return;
3575 EnterNotifies(ancestor, parent, mode, detail);
3576 EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id);
3581 * Send leave notifies to all parent windows up to ancestor.
3582 * This function recurses.
3584 static void
3585 LeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail)
3587 WindowPtr pWin;
3589 if (ancestor == child)
3590 return;
3591 for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent)
3593 EnterLeaveEvent(LeaveNotify, mode, detail, pWin, child->drawable.id);
3594 child = pWin;
3599 * Figure out if enter/leave events are necessary and send them to the
3600 * appropriate windows.
3602 * @param fromWin Window the sprite moved out of.
3603 * @param toWin Window the sprite moved into.
3605 static void
3606 DoEnterLeaveEvents(WindowPtr fromWin, WindowPtr toWin, int mode)
3608 if (fromWin == toWin)
3609 return;
3610 if (IsParent(fromWin, toWin))
3612 EnterLeaveEvent(LeaveNotify, mode, NotifyInferior, fromWin, None);
3613 EnterNotifies(fromWin, toWin, mode, NotifyVirtual);
3614 EnterLeaveEvent(EnterNotify, mode, NotifyAncestor, toWin, None);
3616 else if (IsParent(toWin, fromWin))
3618 EnterLeaveEvent(LeaveNotify, mode, NotifyAncestor, fromWin, None);
3619 LeaveNotifies(fromWin, toWin, mode, NotifyVirtual);
3620 EnterLeaveEvent(EnterNotify, mode, NotifyInferior, toWin, None);
3622 else
3623 { /* neither fromWin nor toWin is descendent of the other */
3624 WindowPtr common = CommonAncestor(toWin, fromWin);
3625 /* common == NullWindow ==> different screens */
3626 EnterLeaveEvent(LeaveNotify, mode, NotifyNonlinear, fromWin, None);
3627 LeaveNotifies(fromWin, common, mode, NotifyNonlinearVirtual);
3628 EnterNotifies(common, toWin, mode, NotifyNonlinearVirtual);
3629 EnterLeaveEvent(EnterNotify, mode, NotifyNonlinear, toWin, None);
3633 static void
3634 FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
3636 xEvent event;
3638 #ifdef XINPUT
3639 if (dev != inputInfo.keyboard)
3641 DeviceFocusEvent(dev, type, mode, detail, pWin);
3642 return;
3644 #endif
3645 event.u.focus.mode = mode;
3646 event.u.u.type = type;
3647 event.u.u.detail = detail;
3648 event.u.focus.window = pWin->drawable.id;
3649 (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], NullGrab,
3651 if ((type == FocusIn) &&
3652 ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
3654 xKeymapEvent ke;
3655 ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)];
3656 if (XaceHook(XACE_DEVICE_ACCESS, client, dev, FALSE))
3657 memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
3658 else
3659 bzero((char *)&ke.map[0], 31);
3661 ke.type = KeymapNotify;
3662 (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1,
3663 KeymapStateMask, NullGrab, 0);
3668 * recursive because it is easier
3669 * no-op if child not descended from ancestor
3671 static Bool
3672 FocusInEvents(
3673 DeviceIntPtr dev,
3674 WindowPtr ancestor, WindowPtr child, WindowPtr skipChild,
3675 int mode, int detail,
3676 Bool doAncestor)
3678 if (child == NullWindow)
3679 return ancestor == NullWindow;
3680 if (ancestor == child)
3682 if (doAncestor)
3683 FocusEvent(dev, FocusIn, mode, detail, child);
3684 return TRUE;
3686 if (FocusInEvents(dev, ancestor, child->parent, skipChild, mode, detail,
3687 doAncestor))
3689 if (child != skipChild)
3690 FocusEvent(dev, FocusIn, mode, detail, child);
3691 return TRUE;
3693 return FALSE;
3696 /* dies horribly if ancestor is not an ancestor of child */
3697 static void
3698 FocusOutEvents(
3699 DeviceIntPtr dev,
3700 WindowPtr child, WindowPtr ancestor,
3701 int mode, int detail,
3702 Bool doAncestor)
3704 WindowPtr pWin;
3706 for (pWin = child; pWin != ancestor; pWin = pWin->parent)
3707 FocusEvent(dev, FocusOut, mode, detail, pWin);
3708 if (doAncestor)
3709 FocusEvent(dev, FocusOut, mode, detail, ancestor);
3712 void
3713 DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
3715 int out, in; /* for holding details for to/from
3716 PointerRoot/None */
3717 int i;
3719 if (fromWin == toWin)
3720 return;
3721 out = (fromWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot;
3722 in = (toWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot;
3723 /* wrong values if neither, but then not referenced */
3725 if ((toWin == NullWindow) || (toWin == PointerRootWin))
3727 if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
3729 if (fromWin == PointerRootWin)
3730 FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
3731 TRUE);
3732 /* Notify all the roots */
3733 #ifdef PANORAMIX
3734 if ( !noPanoramiXExtension )
3735 FocusEvent(dev, FocusOut, mode, out, WindowTable[0]);
3736 else
3737 #endif
3738 for (i=0; i<screenInfo.numScreens; i++)
3739 FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
3741 else
3743 if (IsParent(fromWin, sprite.win))
3744 FocusOutEvents(dev, sprite.win, fromWin, mode, NotifyPointer,
3745 FALSE);
3746 FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
3747 /* next call catches the root too, if the screen changed */
3748 FocusOutEvents(dev, fromWin->parent, NullWindow, mode,
3749 NotifyNonlinearVirtual, FALSE);
3751 /* Notify all the roots */
3752 #ifdef PANORAMIX
3753 if ( !noPanoramiXExtension )
3754 FocusEvent(dev, FocusIn, mode, in, WindowTable[0]);
3755 else
3756 #endif
3757 for (i=0; i<screenInfo.numScreens; i++)
3758 FocusEvent(dev, FocusIn, mode, in, WindowTable[i]);
3759 if (toWin == PointerRootWin)
3760 (void)FocusInEvents(dev, ROOT, sprite.win, NullWindow, mode,
3761 NotifyPointer, TRUE);
3763 else
3765 if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
3767 if (fromWin == PointerRootWin)
3768 FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
3769 TRUE);
3770 #ifdef PANORAMIX
3771 if ( !noPanoramiXExtension )
3772 FocusEvent(dev, FocusOut, mode, out, WindowTable[0]);
3773 else
3774 #endif
3775 for (i=0; i<screenInfo.numScreens; i++)
3776 FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
3777 if (toWin->parent != NullWindow)
3778 (void)FocusInEvents(dev, ROOT, toWin, toWin, mode,
3779 NotifyNonlinearVirtual, TRUE);
3780 FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
3781 if (IsParent(toWin, sprite.win))
3782 (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode,
3783 NotifyPointer, FALSE);
3785 else
3787 if (IsParent(toWin, fromWin))
3789 FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin);
3790 FocusOutEvents(dev, fromWin->parent, toWin, mode,
3791 NotifyVirtual, FALSE);
3792 FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin);
3793 if ((IsParent(toWin, sprite.win)) &&
3794 (sprite.win != fromWin) &&
3795 (!IsParent(fromWin, sprite.win)) &&
3796 (!IsParent(sprite.win, fromWin)))
3797 (void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
3798 mode, NotifyPointer, FALSE);
3800 else
3801 if (IsParent(fromWin, toWin))
3803 if ((IsParent(fromWin, sprite.win)) &&
3804 (sprite.win != fromWin) &&
3805 (!IsParent(toWin, sprite.win)) &&
3806 (!IsParent(sprite.win, toWin)))
3807 FocusOutEvents(dev, sprite.win, fromWin, mode,
3808 NotifyPointer, FALSE);
3809 FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin);
3810 (void)FocusInEvents(dev, fromWin, toWin, toWin, mode,
3811 NotifyVirtual, FALSE);
3812 FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin);
3814 else
3816 /* neither fromWin or toWin is child of other */
3817 WindowPtr common = CommonAncestor(toWin, fromWin);
3818 /* common == NullWindow ==> different screens */
3819 if (IsParent(fromWin, sprite.win))
3820 FocusOutEvents(dev, sprite.win, fromWin, mode,
3821 NotifyPointer, FALSE);
3822 FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
3823 if (fromWin->parent != NullWindow)
3824 FocusOutEvents(dev, fromWin->parent, common, mode,
3825 NotifyNonlinearVirtual, FALSE);
3826 if (toWin->parent != NullWindow)
3827 (void)FocusInEvents(dev, common, toWin, toWin, mode,
3828 NotifyNonlinearVirtual, FALSE);
3829 FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
3830 if (IsParent(toWin, sprite.win))
3831 (void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
3832 mode, NotifyPointer, FALSE);
3839 * Set the input focus to the given window. Subsequent keyboard events will be
3840 * delivered to the given window.
3842 * Usually called from ProcSetInputFocus as result of a client request. If so,
3843 * the device is the inputInfo.keyboard.
3844 * If called from ProcXSetInputFocus as result of a client xinput request, the
3845 * device is set to the device specified by the client.
3847 * @param client Client that requested input focus change.
3848 * @param dev Focus device.
3849 * @param focusID The window to obtain the focus. Can be PointerRoot or None.
3850 * @param revertTo Specifies where the focus reverts to when window becomes
3851 * unviewable.
3852 * @param ctime Specifies the time.
3853 * @param followOK True if pointer is allowed to follow the keyboard.
3856 SetInputFocus(
3857 ClientPtr client,
3858 DeviceIntPtr dev,
3859 Window focusID,
3860 CARD8 revertTo,
3861 Time ctime,
3862 Bool followOK)
3864 FocusClassPtr focus;
3865 WindowPtr focusWin;
3866 int mode, rc;
3867 TimeStamp time;
3869 UpdateCurrentTime();
3870 if ((revertTo != RevertToParent) &&
3871 (revertTo != RevertToPointerRoot) &&
3872 (revertTo != RevertToNone) &&
3873 ((revertTo != RevertToFollowKeyboard) || !followOK))
3875 client->errorValue = revertTo;
3876 return BadValue;
3878 time = ClientTimeToServerTime(ctime);
3879 if ((focusID == None) || (focusID == PointerRoot))
3880 focusWin = (WindowPtr)(long)focusID;
3881 else if ((focusID == FollowKeyboard) && followOK)
3882 focusWin = inputInfo.keyboard->focus->win;
3883 else {
3884 rc = dixLookupWindow(&focusWin, focusID, client, DixReadAccess);
3885 if (rc != Success)
3886 return rc;
3887 /* It is a match error to try to set the input focus to an
3888 unviewable window. */
3889 if(!focusWin->realized)
3890 return(BadMatch);
3892 focus = dev->focus;
3893 if ((CompareTimeStamps(time, currentTime) == LATER) ||
3894 (CompareTimeStamps(time, focus->time) == EARLIER))
3895 return Success;
3896 mode = (dev->grab) ? NotifyWhileGrabbed : NotifyNormal;
3897 if (focus->win == FollowKeyboardWin)
3898 DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode);
3899 else
3900 DoFocusEvents(dev, focus->win, focusWin, mode);
3901 focus->time = time;
3902 focus->revert = revertTo;
3903 if (focusID == FollowKeyboard)
3904 focus->win = FollowKeyboardWin;
3905 else
3906 focus->win = focusWin;
3907 if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
3908 focus->traceGood = 0;
3909 else
3911 int depth = 0;
3912 WindowPtr pWin;
3914 for (pWin = focusWin; pWin; pWin = pWin->parent) depth++;
3915 if (depth > focus->traceSize)
3917 focus->traceSize = depth+1;
3918 Must_have_memory = TRUE; /* XXX */
3919 focus->trace = (WindowPtr *)xrealloc(focus->trace,
3920 focus->traceSize *
3921 sizeof(WindowPtr));
3922 Must_have_memory = FALSE; /* XXX */
3924 focus->traceGood = depth;
3925 for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
3926 focus->trace[depth] = pWin;
3928 return Success;
3932 * Server-side protocol handling for SetInputFocus request.
3934 * Sets the input focus for the virtual core keyboard.
3937 ProcSetInputFocus(client)
3938 ClientPtr client;
3940 REQUEST(xSetInputFocusReq);
3942 REQUEST_SIZE_MATCH(xSetInputFocusReq);
3944 if (!XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, TRUE))
3945 return Success;
3947 return SetInputFocus(client, inputInfo.keyboard, stuff->focus,
3948 stuff->revertTo, stuff->time, FALSE);
3952 * Server-side protocol handling for GetInputFocus request.
3954 * Sends the current input focus for the virtual core keyboard back to the
3955 * client.
3958 ProcGetInputFocus(ClientPtr client)
3960 xGetInputFocusReply rep;
3961 /* REQUEST(xReq); */
3962 FocusClassPtr focus = inputInfo.keyboard->focus;
3964 REQUEST_SIZE_MATCH(xReq);
3965 rep.type = X_Reply;
3966 rep.length = 0;
3967 rep.sequenceNumber = client->sequence;
3968 if (focus->win == NoneWin)
3969 rep.focus = None;
3970 else if (focus->win == PointerRootWin)
3971 rep.focus = PointerRoot;
3972 else rep.focus = focus->win->drawable.id;
3973 rep.revertTo = focus->revert;
3974 WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
3975 return Success;
3979 * Server-side protocol handling for Grabpointer request.
3981 * Sets an active grab on the inputInfo.pointer and returns success status to
3982 * client.
3985 ProcGrabPointer(ClientPtr client)
3987 xGrabPointerReply rep;
3988 DeviceIntPtr device = inputInfo.pointer;
3989 GrabPtr grab;
3990 WindowPtr pWin, confineTo;
3991 CursorPtr cursor, oldCursor;
3992 REQUEST(xGrabPointerReq);
3993 TimeStamp time;
3994 int rc;
3996 REQUEST_SIZE_MATCH(xGrabPointerReq);
3997 UpdateCurrentTime();
3998 if ((stuff->pointerMode != GrabModeSync) &&
3999 (stuff->pointerMode != GrabModeAsync))
4001 client->errorValue = stuff->pointerMode;
4002 return BadValue;
4004 if ((stuff->keyboardMode != GrabModeSync) &&
4005 (stuff->keyboardMode != GrabModeAsync))
4007 client->errorValue = stuff->keyboardMode;
4008 return BadValue;
4010 if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
4012 client->errorValue = stuff->ownerEvents;
4013 return BadValue;
4015 if (stuff->eventMask & ~PointerGrabMask)
4017 client->errorValue = stuff->eventMask;
4018 return BadValue;
4020 rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
4021 if (rc != Success)
4022 return rc;
4023 if (stuff->confineTo == None)
4024 confineTo = NullWindow;
4025 else
4027 rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
4028 DixReadAccess);
4029 if (rc != Success)
4030 return rc;
4032 if (stuff->cursor == None)
4033 cursor = NullCursor;
4034 else
4036 cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
4037 RT_CURSOR, DixReadAccess);
4038 if (!cursor)
4040 client->errorValue = stuff->cursor;
4041 return BadCursor;
4044 /* at this point, some sort of reply is guaranteed. */
4045 time = ClientTimeToServerTime(stuff->time);
4046 rep.type = X_Reply;
4047 rep.sequenceNumber = client->sequence;
4048 rep.length = 0;
4049 grab = device->grab;
4050 if ((grab) && !SameClient(grab, client))
4051 rep.status = AlreadyGrabbed;
4052 else if ((!pWin->realized) ||
4053 (confineTo &&
4054 !(confineTo->realized && BorderSizeNotEmpty(confineTo))))
4055 rep.status = GrabNotViewable;
4056 else if (device->sync.frozen &&
4057 device->sync.other && !SameClient(device->sync.other, client))
4058 rep.status = GrabFrozen;
4059 else if ((CompareTimeStamps(time, currentTime) == LATER) ||
4060 (CompareTimeStamps(time, device->grabTime) == EARLIER))
4061 rep.status = GrabInvalidTime;
4062 else
4064 GrabRec tempGrab;
4066 oldCursor = NullCursor;
4067 if (grab)
4069 if (grab->confineTo && !confineTo)
4070 ConfineCursorToWindow(ROOT, FALSE, FALSE);
4071 oldCursor = grab->cursor;
4073 tempGrab.cursor = cursor;
4074 tempGrab.resource = client->clientAsMask;
4075 tempGrab.ownerEvents = stuff->ownerEvents;
4076 tempGrab.eventMask = stuff->eventMask;
4077 tempGrab.confineTo = confineTo;
4078 tempGrab.window = pWin;
4079 tempGrab.keyboardMode = stuff->keyboardMode;
4080 tempGrab.pointerMode = stuff->pointerMode;
4081 tempGrab.device = device;
4082 (*device->ActivateGrab)(device, &tempGrab, time, FALSE);
4083 if (oldCursor)
4084 FreeCursor (oldCursor, (Cursor)0);
4085 rep.status = GrabSuccess;
4087 WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
4088 return Success;
4092 * Server-side protocol handling for ChangeActivePointerGrab request.
4094 * Changes properties of the grab hold by the client. If the client does not
4095 * hold an active grab on the device, nothing happens.
4097 * Works on the core pointer only.
4100 ProcChangeActivePointerGrab(ClientPtr client)
4102 DeviceIntPtr device = inputInfo.pointer;
4103 GrabPtr grab = device->grab;
4104 CursorPtr newCursor, oldCursor;
4105 REQUEST(xChangeActivePointerGrabReq);
4106 TimeStamp time;
4108 REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
4109 if (stuff->eventMask & ~PointerGrabMask)
4111 client->errorValue = stuff->eventMask;
4112 return BadValue;
4114 if (stuff->cursor == None)
4115 newCursor = NullCursor;
4116 else
4118 newCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
4119 RT_CURSOR, DixReadAccess);
4120 if (!newCursor)
4122 client->errorValue = stuff->cursor;
4123 return BadCursor;
4126 if (!grab)
4127 return Success;
4128 if (!SameClient(grab, client))
4129 return Success;
4130 time = ClientTimeToServerTime(stuff->time);
4131 if ((CompareTimeStamps(time, currentTime) == LATER) ||
4132 (CompareTimeStamps(time, device->grabTime) == EARLIER))
4133 return Success;
4134 oldCursor = grab->cursor;
4135 grab->cursor = newCursor;
4136 if (newCursor)
4137 newCursor->refcnt++;
4138 PostNewCursor();
4139 if (oldCursor)
4140 FreeCursor(oldCursor, (Cursor)0);
4141 grab->eventMask = stuff->eventMask;
4142 return Success;
4146 * Server-side protocol handling for UngrabPointer request.
4148 * Deletes the pointer grab on the core pointer device.
4151 ProcUngrabPointer(ClientPtr client)
4153 DeviceIntPtr device = inputInfo.pointer;
4154 GrabPtr grab;
4155 TimeStamp time;
4156 REQUEST(xResourceReq);
4158 REQUEST_SIZE_MATCH(xResourceReq);
4159 UpdateCurrentTime();
4160 grab = device->grab;
4161 time = ClientTimeToServerTime(stuff->id);
4162 if ((CompareTimeStamps(time, currentTime) != LATER) &&
4163 (CompareTimeStamps(time, device->grabTime) != EARLIER) &&
4164 (grab) && SameClient(grab, client))
4165 (*device->DeactivateGrab)(device);
4166 return Success;
4170 * Sets a grab on the given device.
4172 * Called from ProcGrabKeyboard to work on the inputInfo.keyboard.
4173 * Called from ProcXGrabDevice to work on the device specified by the client.
4175 * The parameters this_mode and other_mode represent the keyboard_mode and
4176 * pointer_mode parameters of XGrabKeyboard().
4177 * See man page for details on all the parameters
4179 * @param client Client that owns the grab.
4180 * @param dev The device to grab.
4181 * @param this_mode GrabModeSync or GrabModeAsync
4182 * @param other_mode GrabModeSync or GrabModeAsync
4183 * @param status Return code to be returned to the caller.
4185 * @returns Success or BadValue.
4188 GrabDevice(ClientPtr client, DeviceIntPtr dev,
4189 unsigned this_mode, unsigned other_mode, Window grabWindow,
4190 unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status)
4192 WindowPtr pWin;
4193 GrabPtr grab;
4194 TimeStamp time;
4195 int rc;
4197 UpdateCurrentTime();
4198 if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync))
4200 client->errorValue = this_mode;
4201 return BadValue;
4203 if ((other_mode != GrabModeSync) && (other_mode != GrabModeAsync))
4205 client->errorValue = other_mode;
4206 return BadValue;
4208 if ((ownerEvents != xFalse) && (ownerEvents != xTrue))
4210 client->errorValue = ownerEvents;
4211 return BadValue;
4213 rc = dixLookupWindow(&pWin, grabWindow, client, DixReadAccess);
4214 if (rc != Success)
4215 return rc;
4216 time = ClientTimeToServerTime(ctime);
4217 grab = dev->grab;
4218 if (grab && !SameClient(grab, client))
4219 *status = AlreadyGrabbed;
4220 else if (!pWin->realized)
4221 *status = GrabNotViewable;
4222 else if ((CompareTimeStamps(time, currentTime) == LATER) ||
4223 (CompareTimeStamps(time, dev->grabTime) == EARLIER))
4224 *status = GrabInvalidTime;
4225 else if (dev->sync.frozen &&
4226 dev->sync.other && !SameClient(dev->sync.other, client))
4227 *status = GrabFrozen;
4228 else
4230 GrabRec tempGrab;
4232 tempGrab.window = pWin;
4233 tempGrab.resource = client->clientAsMask;
4234 tempGrab.ownerEvents = ownerEvents;
4235 tempGrab.keyboardMode = this_mode;
4236 tempGrab.pointerMode = other_mode;
4237 tempGrab.eventMask = mask;
4238 tempGrab.device = dev;
4239 (*dev->ActivateGrab)(dev, &tempGrab, time, FALSE);
4240 *status = GrabSuccess;
4242 return Success;
4246 * Server-side protocol handling for GrabKeyboard request.
4248 * Grabs the inputInfo.keyboad and returns success status to client.
4251 ProcGrabKeyboard(ClientPtr client)
4253 xGrabKeyboardReply rep;
4254 REQUEST(xGrabKeyboardReq);
4255 int result;
4257 REQUEST_SIZE_MATCH(xGrabKeyboardReq);
4259 if (XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, TRUE))
4260 result = GrabDevice(client, inputInfo.keyboard, stuff->keyboardMode,
4261 stuff->pointerMode, stuff->grabWindow,
4262 stuff->ownerEvents, stuff->time,
4263 KeyPressMask | KeyReleaseMask, &rep.status);
4264 else {
4265 result = Success;
4266 rep.status = AlreadyGrabbed;
4269 if (result != Success)
4270 return result;
4271 rep.type = X_Reply;
4272 rep.sequenceNumber = client->sequence;
4273 rep.length = 0;
4274 WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
4275 return Success;
4279 * Server-side protocol handling for UngrabKeyboard request.
4281 * Deletes a possible grab on the inputInfo.keyboard.
4284 ProcUngrabKeyboard(ClientPtr client)
4286 DeviceIntPtr device = inputInfo.keyboard;
4287 GrabPtr grab;
4288 TimeStamp time;
4289 REQUEST(xResourceReq);
4291 REQUEST_SIZE_MATCH(xResourceReq);
4292 UpdateCurrentTime();
4293 grab = device->grab;
4294 time = ClientTimeToServerTime(stuff->id);
4295 if ((CompareTimeStamps(time, currentTime) != LATER) &&
4296 (CompareTimeStamps(time, device->grabTime) != EARLIER) &&
4297 (grab) && SameClient(grab, client))
4298 (*device->DeactivateGrab)(device);
4299 return Success;
4303 * Server-side protocol handling for QueryPointer request.
4305 * Returns the current state and position of the core pointer to the client.
4308 ProcQueryPointer(ClientPtr client)
4310 xQueryPointerReply rep;
4311 WindowPtr pWin, t;
4312 REQUEST(xResourceReq);
4313 DeviceIntPtr mouse = inputInfo.pointer;
4314 int rc;
4316 REQUEST_SIZE_MATCH(xResourceReq);
4317 rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
4318 if (rc != Success)
4319 return rc;
4320 if (mouse->valuator->motionHintWindow)
4321 MaybeStopHint(mouse, client);
4322 rep.type = X_Reply;
4323 rep.sequenceNumber = client->sequence;
4324 rep.mask = mouse->button->state | inputInfo.keyboard->key->state;
4325 rep.length = 0;
4326 rep.root = (ROOT)->drawable.id;
4327 rep.rootX = sprite.hot.x;
4328 rep.rootY = sprite.hot.y;
4329 rep.child = None;
4330 if (sprite.hot.pScreen == pWin->drawable.pScreen)
4332 rep.sameScreen = xTrue;
4333 rep.winX = sprite.hot.x - pWin->drawable.x;
4334 rep.winY = sprite.hot.y - pWin->drawable.y;
4335 for (t = sprite.win; t; t = t->parent)
4336 if (t->parent == pWin)
4338 rep.child = t->drawable.id;
4339 break;
4342 else
4344 rep.sameScreen = xFalse;
4345 rep.winX = 0;
4346 rep.winY = 0;
4349 #ifdef PANORAMIX
4350 if(!noPanoramiXExtension) {
4351 rep.rootX += panoramiXdataPtr[0].x;
4352 rep.rootY += panoramiXdataPtr[0].y;
4353 if(stuff->id == rep.root) {
4354 rep.winX += panoramiXdataPtr[0].x;
4355 rep.winY += panoramiXdataPtr[0].y;
4358 #endif
4360 WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
4362 return(Success);
4366 * Initializes the device list and the DIX sprite to sane values. Allocates
4367 * trace memory used for quick window traversal.
4369 void
4370 InitEvents(void)
4372 int i;
4374 sprite.hot.pScreen = sprite.hotPhys.pScreen = (ScreenPtr)NULL;
4375 inputInfo.numDevices = 0;
4376 inputInfo.devices = (DeviceIntPtr)NULL;
4377 inputInfo.off_devices = (DeviceIntPtr)NULL;
4378 inputInfo.keyboard = (DeviceIntPtr)NULL;
4379 inputInfo.pointer = (DeviceIntPtr)NULL;
4380 if (spriteTraceSize == 0)
4382 spriteTraceSize = 32;
4383 spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr));
4384 if (!spriteTrace)
4385 FatalError("failed to allocate spriteTrace");
4387 spriteTraceGood = 0;
4388 lastEventMask = OwnerGrabButtonMask;
4389 filters[MotionNotify] = PointerMotionMask;
4390 #ifdef XEVIE
4391 xeviewin =
4392 #endif
4393 sprite.win = NullWindow;
4394 sprite.current = NullCursor;
4395 sprite.hotLimits.x1 = 0;
4396 sprite.hotLimits.y1 = 0;
4397 sprite.hotLimits.x2 = 0;
4398 sprite.hotLimits.y2 = 0;
4399 sprite.confined = FALSE;
4400 syncEvents.replayDev = (DeviceIntPtr)NULL;
4401 syncEvents.replayWin = NullWindow;
4402 while (syncEvents.pending)
4404 QdEventPtr next = syncEvents.pending->next;
4405 xfree(syncEvents.pending);
4406 syncEvents.pending = next;
4408 syncEvents.pendtail = &syncEvents.pending;
4409 syncEvents.playingEvents = FALSE;
4410 syncEvents.time.months = 0;
4411 syncEvents.time.milliseconds = 0; /* hardly matters */
4412 currentTime.months = 0;
4413 currentTime.milliseconds = GetTimeInMillis();
4414 lastDeviceEventTime = currentTime;
4415 for (i = 0; i < DNPMCOUNT; i++)
4417 DontPropagateMasks[i] = 0;
4418 DontPropagateRefCnts[i] = 0;
4422 void
4423 CloseDownEvents(void)
4425 xfree(spriteTrace);
4426 spriteTrace = NULL;
4427 spriteTraceSize = 0;
4431 * Server-side protocol handling for SendEvent request.
4433 * Locates the window to send the event to and forwards the event.
4436 ProcSendEvent(ClientPtr client)
4438 WindowPtr pWin;
4439 WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
4440 REQUEST(xSendEventReq);
4442 REQUEST_SIZE_MATCH(xSendEventReq);
4444 /* The client's event type must be a core event type or one defined by an
4445 extension. */
4447 if ( ! ((stuff->event.u.u.type > X_Reply &&
4448 stuff->event.u.u.type < LASTEvent) ||
4449 (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
4450 stuff->event.u.u.type < (unsigned)lastEvent)))
4452 client->errorValue = stuff->event.u.u.type;
4453 return BadValue;
4455 if (stuff->event.u.u.type == ClientMessage &&
4456 stuff->event.u.u.detail != 8 &&
4457 stuff->event.u.u.detail != 16 &&
4458 stuff->event.u.u.detail != 32)
4460 client->errorValue = stuff->event.u.u.detail;
4461 return BadValue;
4463 if (stuff->eventMask & ~AllEventMasks)
4465 client->errorValue = stuff->eventMask;
4466 return BadValue;
4469 if (stuff->destination == PointerWindow)
4470 pWin = sprite.win;
4471 else if (stuff->destination == InputFocus)
4473 WindowPtr inputFocus = inputInfo.keyboard->focus->win;
4475 if (inputFocus == NoneWin)
4476 return Success;
4478 /* If the input focus is PointerRootWin, send the event to where
4479 the pointer is if possible, then perhaps propogate up to root. */
4480 if (inputFocus == PointerRootWin)
4481 inputFocus = ROOT;
4483 if (IsParent(inputFocus, sprite.win))
4485 effectiveFocus = inputFocus;
4486 pWin = sprite.win;
4488 else
4489 effectiveFocus = pWin = inputFocus;
4491 else
4492 dixLookupWindow(&pWin, stuff->destination, client, DixReadAccess);
4494 if (!pWin)
4495 return BadWindow;
4496 if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue))
4498 client->errorValue = stuff->propagate;
4499 return BadValue;
4501 stuff->event.u.u.type |= 0x80;
4502 if (stuff->propagate)
4504 for (;pWin; pWin = pWin->parent)
4506 if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask,
4507 NullGrab, 0))
4508 return Success;
4509 if (pWin == effectiveFocus)
4510 return Success;
4511 stuff->eventMask &= ~wDontPropagateMask(pWin);
4512 if (!stuff->eventMask)
4513 break;
4516 else
4517 (void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask,
4518 NullGrab, 0);
4519 return Success;
4523 * Server-side protocol handling for UngrabKey request.
4525 * Deletes a passive grab for the given key. Only works on the
4526 * inputInfo.keyboard.
4529 ProcUngrabKey(ClientPtr client)
4531 REQUEST(xUngrabKeyReq);
4532 WindowPtr pWin;
4533 GrabRec tempGrab;
4534 DeviceIntPtr keybd = inputInfo.keyboard;
4535 int rc;
4537 REQUEST_SIZE_MATCH(xUngrabKeyReq);
4538 rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
4539 if (rc != Success)
4540 return rc;
4542 if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) ||
4543 (stuff->key < keybd->key->curKeySyms.minKeyCode))
4544 && (stuff->key != AnyKey))
4546 client->errorValue = stuff->key;
4547 return BadValue;
4549 if ((stuff->modifiers != AnyModifier) &&
4550 (stuff->modifiers & ~AllModifiersMask))
4552 client->errorValue = stuff->modifiers;
4553 return BadValue;
4555 tempGrab.resource = client->clientAsMask;
4556 tempGrab.device = keybd;
4557 tempGrab.window = pWin;
4558 tempGrab.modifiersDetail.exact = stuff->modifiers;
4559 tempGrab.modifiersDetail.pMask = NULL;
4560 tempGrab.modifierDevice = inputInfo.keyboard;
4561 tempGrab.type = KeyPress;
4562 tempGrab.detail.exact = stuff->key;
4563 tempGrab.detail.pMask = NULL;
4565 if (!DeletePassiveGrabFromList(&tempGrab))
4566 return(BadAlloc);
4567 return(Success);
4571 * Server-side protocol handling for GrabKey request.
4573 * Creates a grab for the inputInfo.keyboard and adds it to the list of
4574 * passive grabs.
4577 ProcGrabKey(ClientPtr client)
4579 WindowPtr pWin;
4580 REQUEST(xGrabKeyReq);
4581 GrabPtr grab;
4582 DeviceIntPtr keybd = inputInfo.keyboard;
4583 int rc;
4585 REQUEST_SIZE_MATCH(xGrabKeyReq);
4586 if ((stuff->ownerEvents != xTrue) && (stuff->ownerEvents != xFalse))
4588 client->errorValue = stuff->ownerEvents;
4589 return(BadValue);
4591 if ((stuff->pointerMode != GrabModeSync) &&
4592 (stuff->pointerMode != GrabModeAsync))
4594 client->errorValue = stuff->pointerMode;
4595 return BadValue;
4597 if ((stuff->keyboardMode != GrabModeSync) &&
4598 (stuff->keyboardMode != GrabModeAsync))
4600 client->errorValue = stuff->keyboardMode;
4601 return BadValue;
4603 if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) ||
4604 (stuff->key < keybd->key->curKeySyms.minKeyCode))
4605 && (stuff->key != AnyKey))
4607 client->errorValue = stuff->key;
4608 return BadValue;
4610 if ((stuff->modifiers != AnyModifier) &&
4611 (stuff->modifiers & ~AllModifiersMask))
4613 client->errorValue = stuff->modifiers;
4614 return BadValue;
4616 rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
4617 if (rc != Success)
4618 return rc;
4620 grab = CreateGrab(client->index, keybd, pWin,
4621 (Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents,
4622 (Bool)stuff->keyboardMode, (Bool)stuff->pointerMode,
4623 keybd, stuff->modifiers, KeyPress, stuff->key,
4624 NullWindow, NullCursor);
4625 if (!grab)
4626 return BadAlloc;
4627 return AddPassiveGrabToList(grab);
4632 * Server-side protocol handling for GrabButton request.
4634 * Creates a grab for the inputInfo.pointer and adds it as a passive grab to
4635 * the list.
4638 ProcGrabButton(ClientPtr client)
4640 WindowPtr pWin, confineTo;
4641 REQUEST(xGrabButtonReq);
4642 CursorPtr cursor;
4643 GrabPtr grab;
4644 int rc;
4646 REQUEST_SIZE_MATCH(xGrabButtonReq);
4647 if ((stuff->pointerMode != GrabModeSync) &&
4648 (stuff->pointerMode != GrabModeAsync))
4650 client->errorValue = stuff->pointerMode;
4651 return BadValue;
4653 if ((stuff->keyboardMode != GrabModeSync) &&
4654 (stuff->keyboardMode != GrabModeAsync))
4656 client->errorValue = stuff->keyboardMode;
4657 return BadValue;
4659 if ((stuff->modifiers != AnyModifier) &&
4660 (stuff->modifiers & ~AllModifiersMask))
4662 client->errorValue = stuff->modifiers;
4663 return BadValue;
4665 if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
4667 client->errorValue = stuff->ownerEvents;
4668 return BadValue;
4670 if (stuff->eventMask & ~PointerGrabMask)
4672 client->errorValue = stuff->eventMask;
4673 return BadValue;
4675 rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
4676 if (rc != Success)
4677 return rc;
4678 if (stuff->confineTo == None)
4679 confineTo = NullWindow;
4680 else {
4681 rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
4682 DixReadAccess);
4683 if (rc != Success)
4684 return rc;
4686 if (stuff->cursor == None)
4687 cursor = NullCursor;
4688 else
4690 cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
4691 RT_CURSOR, DixReadAccess);
4692 if (!cursor)
4694 client->errorValue = stuff->cursor;
4695 return BadCursor;
4700 grab = CreateGrab(client->index, inputInfo.pointer, pWin,
4701 (Mask)stuff->eventMask, (Bool)stuff->ownerEvents,
4702 (Bool) stuff->keyboardMode, (Bool)stuff->pointerMode,
4703 inputInfo.keyboard, stuff->modifiers, ButtonPress,
4704 stuff->button, confineTo, cursor);
4705 if (!grab)
4706 return BadAlloc;
4707 return AddPassiveGrabToList(grab);
4711 * Server-side protocol handling for UngrabButton request.
4713 * Deletes a passive grab on the inputInfo.pointer from the list.
4716 ProcUngrabButton(ClientPtr client)
4718 REQUEST(xUngrabButtonReq);
4719 WindowPtr pWin;
4720 GrabRec tempGrab;
4721 int rc;
4723 REQUEST_SIZE_MATCH(xUngrabButtonReq);
4724 if ((stuff->modifiers != AnyModifier) &&
4725 (stuff->modifiers & ~AllModifiersMask))
4727 client->errorValue = stuff->modifiers;
4728 return BadValue;
4730 rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
4731 if (rc != Success)
4732 return rc;
4733 tempGrab.resource = client->clientAsMask;
4734 tempGrab.device = inputInfo.pointer;
4735 tempGrab.window = pWin;
4736 tempGrab.modifiersDetail.exact = stuff->modifiers;
4737 tempGrab.modifiersDetail.pMask = NULL;
4738 tempGrab.modifierDevice = inputInfo.keyboard;
4739 tempGrab.type = ButtonPress;
4740 tempGrab.detail.exact = stuff->button;
4741 tempGrab.detail.pMask = NULL;
4743 if (!DeletePassiveGrabFromList(&tempGrab))
4744 return(BadAlloc);
4745 return(Success);
4749 * Deactivate any grab that may be on the window, remove the focus.
4750 * Delete any XInput extension events from the window too. Does not change the
4751 * window mask. Use just before the window is deleted.
4753 * If freeResources is set, passive grabs on the window are deleted.
4755 * @param pWin The window to delete events from.
4756 * @param freeResources True if resources associated with the window should be
4757 * deleted.
4759 void
4760 DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
4762 WindowPtr parent;
4763 DeviceIntPtr mouse = inputInfo.pointer;
4764 DeviceIntPtr keybd = inputInfo.keyboard;
4765 FocusClassPtr focus = keybd->focus;
4766 OtherClientsPtr oc;
4767 GrabPtr passive;
4770 /* Deactivate any grabs performed on this window, before making any
4771 input focus changes. */
4773 if (mouse->grab &&
4774 ((mouse->grab->window == pWin) || (mouse->grab->confineTo == pWin)))
4775 (*mouse->DeactivateGrab)(mouse);
4777 /* Deactivating a keyboard grab should cause focus events. */
4779 if (keybd->grab && (keybd->grab->window == pWin))
4780 (*keybd->DeactivateGrab)(keybd);
4782 /* If the focus window is a root window (ie. has no parent) then don't
4783 delete the focus from it. */
4785 if ((pWin == focus->win) && (pWin->parent != NullWindow))
4787 int focusEventMode = NotifyNormal;
4789 /* If a grab is in progress, then alter the mode of focus events. */
4791 if (keybd->grab)
4792 focusEventMode = NotifyWhileGrabbed;
4794 switch (focus->revert)
4796 case RevertToNone:
4797 DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
4798 focus->win = NoneWin;
4799 focus->traceGood = 0;
4800 break;
4801 case RevertToParent:
4802 parent = pWin;
4805 parent = parent->parent;
4806 focus->traceGood--;
4807 } while (!parent->realized
4808 /* This would be a good protocol change -- windows being reparented
4809 during SaveSet processing would cause the focus to revert to the
4810 nearest enclosing window which will survive the death of the exiting
4811 client, instead of ending up reverting to a dying window and thence
4812 to None
4814 #ifdef NOTDEF
4815 || clients[CLIENT_ID(parent->drawable.id)]->clientGone
4816 #endif
4818 DoFocusEvents(keybd, pWin, parent, focusEventMode);
4819 focus->win = parent;
4820 focus->revert = RevertToNone;
4821 break;
4822 case RevertToPointerRoot:
4823 DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode);
4824 focus->win = PointerRootWin;
4825 focus->traceGood = 0;
4826 break;
4830 if (mouse->valuator->motionHintWindow == pWin)
4831 mouse->valuator->motionHintWindow = NullWindow;
4833 if (freeResources)
4835 if (pWin->dontPropagate)
4836 DontPropagateRefCnts[pWin->dontPropagate]--;
4837 while ( (oc = wOtherClients(pWin)) )
4838 FreeResource(oc->resource, RT_NONE);
4839 while ( (passive = wPassiveGrabs(pWin)) )
4840 FreeResource(passive->resource, RT_NONE);
4842 #ifdef XINPUT
4843 DeleteWindowFromAnyExtEvents(pWin, freeResources);
4844 #endif
4848 * Call this whenever some window at or below pWin has changed geometry. If
4849 * there is a grab on the window, the cursor will be re-confined into the
4850 * window.
4852 _X_EXPORT void
4853 CheckCursorConfinement(WindowPtr pWin)
4855 GrabPtr grab = inputInfo.pointer->grab;
4856 WindowPtr confineTo;
4858 #ifdef PANORAMIX
4859 if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return;
4860 #endif
4862 if (grab && (confineTo = grab->confineTo))
4864 if (!BorderSizeNotEmpty(confineTo))
4865 (*inputInfo.pointer->DeactivateGrab)(inputInfo.pointer);
4866 else if ((pWin == confineTo) || IsParent(pWin, confineTo))
4867 ConfineCursorToWindow(confineTo, TRUE, TRUE);
4871 Mask
4872 EventMaskForClient(WindowPtr pWin, ClientPtr client)
4874 OtherClientsPtr other;
4876 if (wClient (pWin) == client)
4877 return pWin->eventMask;
4878 for (other = wOtherClients(pWin); other; other = other->next)
4880 if (SameClient(other, client))
4881 return other->mask;
4883 return 0;
4887 * Server-side protocol handling for RecolorCursor request.
4890 ProcRecolorCursor(ClientPtr client)
4892 CursorPtr pCursor;
4893 int nscr;
4894 ScreenPtr pscr;
4895 Bool displayed;
4896 REQUEST(xRecolorCursorReq);
4898 REQUEST_SIZE_MATCH(xRecolorCursorReq);
4899 pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
4900 RT_CURSOR, DixWriteAccess);
4901 if ( !pCursor)
4903 client->errorValue = stuff->cursor;
4904 return (BadCursor);
4907 pCursor->foreRed = stuff->foreRed;
4908 pCursor->foreGreen = stuff->foreGreen;
4909 pCursor->foreBlue = stuff->foreBlue;
4911 pCursor->backRed = stuff->backRed;
4912 pCursor->backGreen = stuff->backGreen;
4913 pCursor->backBlue = stuff->backBlue;
4915 for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
4917 pscr = screenInfo.screens[nscr];
4918 #ifdef PANORAMIX
4919 if(!noPanoramiXExtension)
4920 displayed = (pscr == sprite.screen);
4921 else
4922 #endif
4923 displayed = (pscr == sprite.hotPhys.pScreen);
4924 ( *pscr->RecolorCursor)(pscr, pCursor,
4925 (pCursor == sprite.current) && displayed);
4927 return (Success);
4931 * Write the given events to a client, swapping the byte order if necessary.
4932 * To swap the byte ordering, a callback is called that has to be set up for
4933 * the given event type.
4935 * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
4936 * can be more than one. Usually it's just one event.
4938 * Do not modify the event structure passed in. See comment below.
4940 * @param pClient Client to send events to.
4941 * @param count Number of events.
4942 * @param events The event list.
4944 _X_EXPORT void
4945 WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
4947 #ifdef PANORAMIX
4948 xEvent eventCopy;
4949 #endif
4950 xEvent eventTo, *eventFrom;
4951 int i;
4953 #ifdef XKB
4954 if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events)))
4955 return;
4956 #endif
4958 #ifdef PANORAMIX
4959 if(!noPanoramiXExtension &&
4960 (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y))
4962 switch(events->u.u.type) {
4963 case MotionNotify:
4964 case ButtonPress:
4965 case ButtonRelease:
4966 case KeyPress:
4967 case KeyRelease:
4968 case EnterNotify:
4969 case LeaveNotify:
4971 When multiple clients want the same event DeliverEventsToWindow
4972 passes the same event structure multiple times so we can't
4973 modify the one passed to us
4975 count = 1; /* should always be 1 */
4976 memcpy(&eventCopy, events, sizeof(xEvent));
4977 eventCopy.u.keyButtonPointer.rootX += panoramiXdataPtr[0].x;
4978 eventCopy.u.keyButtonPointer.rootY += panoramiXdataPtr[0].y;
4979 if(eventCopy.u.keyButtonPointer.event ==
4980 eventCopy.u.keyButtonPointer.root)
4982 eventCopy.u.keyButtonPointer.eventX += panoramiXdataPtr[0].x;
4983 eventCopy.u.keyButtonPointer.eventY += panoramiXdataPtr[0].y;
4985 events = &eventCopy;
4986 break;
4987 default: break;
4990 #endif
4992 if (EventCallback)
4994 EventInfoRec eventinfo;
4995 eventinfo.client = pClient;
4996 eventinfo.events = events;
4997 eventinfo.count = count;
4998 CallCallbacks(&EventCallback, (pointer)&eventinfo);
5000 #ifdef XSERVER_DTRACE
5001 if (XSERVER_SEND_EVENT_ENABLED()) {
5002 for (i = 0; i < count; i++)
5004 XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]);
5007 #endif
5008 if(pClient->swapped)
5010 for(i = 0; i < count; i++)
5012 eventFrom = &events[i];
5013 /* Remember to strip off the leading bit of type in case
5014 this event was sent with "SendEvent." */
5015 (*EventSwapVector[eventFrom->u.u.type & 0177])
5016 (eventFrom, &eventTo);
5017 (void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo);
5020 else
5022 (void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events);