]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/xserver.git/blob - dix/events.c
04d7fb59b0408bf2d2aee51857ca61e9d54d436e
[glsdk/xserver.git] / dix / events.c
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 /*
78  * Copyright (c) 2003-2005, Oracle and/or its affiliates. All rights reserved.
79  *
80  * Permission is hereby granted, free of charge, to any person obtaining a
81  * copy of this software and associated documentation files (the "Software"),
82  * to deal in the Software without restriction, including without limitation
83  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
84  * and/or sell copies of the Software, and to permit persons to whom the
85  * Software is furnished to do so, subject to the following conditions:
86  *
87  * The above copyright notice and this permission notice (including the next
88  * paragraph) shall be included in all copies or substantial portions of the
89  * Software.
90  *
91  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
92  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
93  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
94  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
95  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
96  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
97  * DEALINGS IN THE SOFTWARE.
98  */
100 /** @file events.c
101  * This file handles event delivery and a big part of the server-side protocol
102  * handling (the parts for input devices).
103  */
105 #ifdef HAVE_DIX_CONFIG_H
106 #include <dix-config.h>
107 #endif
109 #include <X11/X.h>
110 #include "misc.h"
111 #include "resource.h"
112 #include <X11/Xproto.h>
113 #include "windowstr.h"
114 #include "inputstr.h"
115 #include "inpututils.h"
116 #include "scrnintstr.h"
117 #include "cursorstr.h"
119 #include "dixstruct.h"
120 #ifdef PANORAMIX
121 #include "panoramiX.h"
122 #include "panoramiXsrv.h"
123 #endif
124 #include "globals.h"
126 #include <X11/extensions/XKBproto.h>
127 #include "xkbsrv.h"
128 #include "xace.h"
130 #ifdef XSERVER_DTRACE
131 #include <sys/types.h>
132 typedef const char *string;
133 #include "Xserver-dtrace.h"
134 #endif
136 #include <X11/extensions/XIproto.h>
137 #include <X11/extensions/XI2proto.h>
138 #include <X11/extensions/XI.h>
139 #include <X11/extensions/XI2.h>
140 #include "exglobals.h"
141 #include "exevents.h"
142 #include "extnsionst.h"
144 #include "dixevents.h"
145 #include "dixgrabs.h"
146 #include "dispatch.h"
148 #include <X11/extensions/ge.h>
149 #include "geext.h"
150 #include "geint.h"
152 #include "eventstr.h"
153 #include "enterleave.h"
154 #include "eventconvert.h"
155 #include "mi.h"
157 /* Extension events type numbering starts at EXTENSION_EVENT_BASE.  */
158 #define NoSuchEvent 0x80000000  /* so doesn't match NoEventMask */
159 #define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
160 #define AllButtonsMask ( \
161         Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
162 #define MotionMask ( \
163         PointerMotionMask | Button1MotionMask | \
164         Button2MotionMask | Button3MotionMask | Button4MotionMask | \
165         Button5MotionMask | ButtonMotionMask )
166 #define PropagateMask ( \
167         KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
168         MotionMask )
169 #define PointerGrabMask ( \
170         ButtonPressMask | ButtonReleaseMask | \
171         EnterWindowMask | LeaveWindowMask | \
172         PointerMotionHintMask | KeymapStateMask | \
173         MotionMask )
174 #define AllModifiersMask ( \
175         ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
176         Mod3Mask | Mod4Mask | Mod5Mask )
177 #define LastEventMask OwnerGrabButtonMask
178 #define AllEventMasks (LastEventMask|(LastEventMask-1))
181 /* @return the core event type or 0 if the event is not a core event */
182 static inline int
183 core_get_type(const xEvent *event)
185     int type = event->u.u.type;
187     return ((type & EXTENSION_EVENT_BASE) || type == GenericEvent) ? 0 : type;
190 /* @return the XI2 event type or 0 if the event is not a XI2 event */
191 static inline int
192 xi2_get_type(const xEvent *event)
194     const xGenericEvent* e = (const xGenericEvent*)event;
196     return (e->type != GenericEvent || e->extension != IReqCode) ? 0 : e->evtype;
199 /**
200  * Used to indicate a implicit passive grab created by a ButtonPress event.
201  * See DeliverEventsToWindow().
202  */
203 #define ImplicitGrabMask (1 << 7)
205 #define WID(w) ((w) ? ((w)->drawable.id) : 0)
207 #define XE_KBPTR (xE->u.keyButtonPointer)
210 CallbackListPtr EventCallback;
211 CallbackListPtr DeviceEventCallback;
213 #define DNPMCOUNT 8
215 Mask DontPropagateMasks[DNPMCOUNT];
216 static int DontPropagateRefCnts[DNPMCOUNT];
218 static void CheckVirtualMotion( DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin);
219 static void CheckPhysLimits(DeviceIntPtr pDev,
220                             CursorPtr cursor,
221                             Bool generateEvents,
222                             Bool confineToScreen,
223                             ScreenPtr pScreen);
225 /** Key repeat hack. Do not use but in TryClientEvents */
226 extern BOOL EventIsKeyRepeat(xEvent *event);
228 /**
229  * Main input device struct.
230  *     inputInfo.pointer
231  *     is the core pointer. Referred to as "virtual core pointer", "VCP",
232  *     "core pointer" or inputInfo.pointer. The VCP is the first master
233  *     pointer device and cannot be deleted.
234  *
235  *     inputInfo.keyboard
236  *     is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
237  *     See inputInfo.pointer.
238  *
239  *     inputInfo.devices
240  *     linked list containing all devices including VCP and VCK.
241  *
242  *     inputInfo.off_devices
243  *     Devices that have not been initialized and are thus turned off.
244  *
245  *     inputInfo.numDevices
246  *     Total number of devices.
247  *
248  *     inputInfo.all_devices
249  *     Virtual device used for XIAllDevices passive grabs. This device is
250  *     not part of the inputInfo.devices list and mostly unset except for
251  *     the deviceid. It exists because passivegrabs need a valid device
252  *     reference.
253  *
254  *     inputInfo.all_master_devices
255  *     Virtual device used for XIAllMasterDevices passive grabs. This device
256  *     is not part of the inputInfo.devices list and mostly unset except for
257  *     the deviceid. It exists because passivegrabs need a valid device
258  *     reference.
259  */
260 InputInfo inputInfo;
262 EventSyncInfoRec syncEvents;
264 /**
265  * The root window the given device is currently on.
266  */
267 #define RootWindow(sprite) sprite->spriteTrace[0]
269 static xEvent* swapEvent = NULL;
270 static int swapEventLen = 0;
272 void
273 NotImplemented(xEvent *from, xEvent *to)
275     FatalError("Not implemented");
278 /**
279  * Convert the given event type from an XI event to a core event.
280  * @param[in] The XI 1.x event type.
281  * @return The matching core event type or 0 if there is none.
282  */
283 int
284 XItoCoreType(int xitype)
286     int coretype = 0;
287     if (xitype == DeviceMotionNotify)
288         coretype = MotionNotify;
289     else if (xitype == DeviceButtonPress)
290         coretype = ButtonPress;
291     else if (xitype == DeviceButtonRelease)
292         coretype = ButtonRelease;
293     else if (xitype == DeviceKeyPress)
294         coretype = KeyPress;
295     else if (xitype == DeviceKeyRelease)
296         coretype = KeyRelease;
298     return coretype;
301 /**
302  * @return true if the device owns a cursor, false if device shares a cursor
303  * sprite with another device.
304  */
305 Bool
306 DevHasCursor(DeviceIntPtr pDev)
308     return pDev->spriteInfo->spriteOwner;
311 /*
312  * @return true if a device is a pointer, check is the same as used by XI to
313  * fill the 'use' field.
314  */
315 Bool
316 IsPointerDevice(DeviceIntPtr dev)
318     return (dev->type == MASTER_POINTER) ||
319             (dev->valuator && dev->button) ||
320             (dev->valuator && !dev->key);
323 /*
324  * @return true if a device is a keyboard, check is the same as used by XI to
325  * fill the 'use' field.
326  *
327  * Some pointer devices have keys as well (e.g. multimedia keys). Try to not
328  * count them as keyboard devices.
329  */
330 Bool
331 IsKeyboardDevice(DeviceIntPtr dev)
333     return (dev->type == MASTER_KEYBOARD) ||
334             ((dev->key && dev->kbdfeed) && !IsPointerDevice(dev));
337 Bool
338 IsMaster(DeviceIntPtr dev)
340     return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
343 Bool
344 IsFloating(DeviceIntPtr dev)
346     return GetMaster(dev, MASTER_KEYBOARD) == NULL;
350 /**
351  * Max event opcode.
352  */
353 extern int lastEvent;
355 extern int DeviceMotionNotify;
357 #define CantBeFiltered NoEventMask
358 /**
359  * Event masks for each event type.
360  *
361  * One set of filters for each device, initialized by memcpy of
362  * default_filter in InitEvents.
363  *
364  * Filters are used whether a given event may be delivered to a client,
365  * usually in the form of if (window-event-mask & filter); then deliver event.
366  *
367  * One notable filter is for PointerMotion/DevicePointerMotion events. Each
368  * time a button is pressed, the filter is modified to also contain the
369  * matching ButtonXMotion mask.
370  */
371 Mask event_filters[MAXDEVICES][MAXEVENTS];
373 static const Mask default_filter[MAXEVENTS] =
375         NoSuchEvent,                   /* 0 */
376         NoSuchEvent,                   /* 1 */
377         KeyPressMask,                  /* KeyPress */
378         KeyReleaseMask,                /* KeyRelease */
379         ButtonPressMask,               /* ButtonPress */
380         ButtonReleaseMask,             /* ButtonRelease */
381         PointerMotionMask,             /* MotionNotify (initial state) */
382         EnterWindowMask,               /* EnterNotify */
383         LeaveWindowMask,               /* LeaveNotify */
384         FocusChangeMask,               /* FocusIn */
385         FocusChangeMask,               /* FocusOut */
386         KeymapStateMask,               /* KeymapNotify */
387         ExposureMask,                  /* Expose */
388         CantBeFiltered,                /* GraphicsExpose */
389         CantBeFiltered,                /* NoExpose */
390         VisibilityChangeMask,          /* VisibilityNotify */
391         SubstructureNotifyMask,        /* CreateNotify */
392         StructureAndSubMask,           /* DestroyNotify */
393         StructureAndSubMask,           /* UnmapNotify */
394         StructureAndSubMask,           /* MapNotify */
395         SubstructureRedirectMask,      /* MapRequest */
396         StructureAndSubMask,           /* ReparentNotify */
397         StructureAndSubMask,           /* ConfigureNotify */
398         SubstructureRedirectMask,      /* ConfigureRequest */
399         StructureAndSubMask,           /* GravityNotify */
400         ResizeRedirectMask,            /* ResizeRequest */
401         StructureAndSubMask,           /* CirculateNotify */
402         SubstructureRedirectMask,      /* CirculateRequest */
403         PropertyChangeMask,            /* PropertyNotify */
404         CantBeFiltered,                /* SelectionClear */
405         CantBeFiltered,                /* SelectionRequest */
406         CantBeFiltered,                /* SelectionNotify */
407         ColormapChangeMask,            /* ColormapNotify */
408         CantBeFiltered,                /* ClientMessage */
409         CantBeFiltered                 /* MappingNotify */
410 };
412 /**
413  * For the given event, return the matching event filter. This filter may then
414  * be AND'ed with the selected event mask.
415  *
416  * For XI2 events, the returned filter is simply the byte containing the event
417  * mask we're interested in. E.g. for a mask of (1 << 13), this would be
418  * byte[1].
419  *
420  * @param[in] dev The device the event belongs to, may be NULL.
421  * @param[in] event The event to get the filter for. Only the type of the
422  *                  event matters, or the extension + evtype for GenericEvents.
423  * @return The filter mask for the given event.
424  *
425  * @see GetEventMask
426  */
427 Mask
428 GetEventFilter(DeviceIntPtr dev, xEvent *event)
430     int evtype = 0;
432     if (event->u.u.type != GenericEvent)
433         return event_get_filter_from_type(dev, event->u.u.type);
434     else if ((evtype = xi2_get_type(event)))
435         return event_get_filter_from_xi2type(evtype);
436     ErrorF("[dix] Unknown event type %d. No filter\n", event->u.u.type);
437     return 0;
440 /**
441  * Return the single byte of the device's XI2 mask that contains the mask
442  * for the event_type.
443  */
444 int
445 GetXI2MaskByte(XI2Mask *mask, DeviceIntPtr dev, int event_type)
447     /* we just return the matching filter because that's the only use
448      * for this mask anyway.
449      */
450     if (xi2mask_isset(mask, dev, event_type))
451         return event_get_filter_from_xi2type(event_type);
452     else
453         return 0;
457 /**
458  * @return TRUE if the mask is set for this event from this device on the
459  * window, or FALSE otherwise.
460  */
461 Bool
462 WindowXI2MaskIsset(DeviceIntPtr dev, WindowPtr win, xEvent* ev)
464     OtherInputMasks *inputMasks = wOtherInputMasks(win);
465     int evtype;
467     if (!inputMasks || xi2_get_type(ev) == 0)
468         return 0;
470     evtype = ((xGenericEvent*)ev)->evtype;
472     return xi2mask_isset(inputMasks->xi2mask, dev, evtype);
475 Mask
476 GetEventMask(DeviceIntPtr dev, xEvent *event, InputClients* other)
478     int evtype;
480     /* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */
481     if ((evtype = xi2_get_type(event)))
482     {
483         return GetXI2MaskByte(other->xi2mask, dev, evtype);
484     } else if (core_get_type(event) != 0)
485         return other->mask[XIAllDevices];
486     else
487         return other->mask[dev->id];
491 static CARD8 criticalEvents[32] =
493     0x7c, 0x30, 0x40                    /* key, button, expose, and configure events */
494 };
496 static void
497 SyntheticMotion(DeviceIntPtr dev, int x, int y) {
498     int screenno = 0;
500 #ifdef PANORAMIX
501     if (!noPanoramiXExtension)
502         screenno = dev->spriteInfo->sprite->screen->myNum;
503 #endif
504     PostSyntheticMotion(dev, x, y, screenno,
505             (syncEvents.playingEvents) ?  syncEvents.time.milliseconds : currentTime.milliseconds);
509 #ifdef PANORAMIX
510 static void PostNewCursor(DeviceIntPtr pDev);
512 static Bool
513 XineramaSetCursorPosition(
514     DeviceIntPtr pDev,
515     int x,
516     int y,
517     Bool generateEvent
518 ){
519     ScreenPtr pScreen;
520     int i;
521     SpritePtr pSprite = pDev->spriteInfo->sprite;
523     /* x,y are in Screen 0 coordinates.  We need to decide what Screen
524        to send the message too and what the coordinates relative to
525        that screen are. */
527     pScreen = pSprite->screen;
528     x += screenInfo.screens[0]->x;
529     y += screenInfo.screens[0]->y;
531     if(!point_on_screen(pScreen, x, y))
532     {
533         FOR_NSCREENS(i)
534         {
535             if(i == pScreen->myNum)
536                 continue;
537             if(point_on_screen(screenInfo.screens[i], x, y))
538             {
539                 pScreen = screenInfo.screens[i];
540                 break;
541             }
542         }
543     }
545     pSprite->screen = pScreen;
546     pSprite->hotPhys.x = x - screenInfo.screens[0]->x;
547     pSprite->hotPhys.y = y - screenInfo.screens[0]->y;
548     x -= pScreen->x;
549     y -= pScreen->y;
551     return (*pScreen->SetCursorPosition)(pDev, pScreen, x, y, generateEvent);
555 static void
556 XineramaConstrainCursor(DeviceIntPtr pDev)
558     SpritePtr pSprite = pDev->spriteInfo->sprite;
559     ScreenPtr pScreen;
560     BoxRec newBox;
562     pScreen = pSprite->screen;
563     newBox = pSprite->physLimits;
565     /* Translate the constraining box to the screen
566        the sprite is actually on */
567     newBox.x1 += screenInfo.screens[0]->x - pScreen->x;
568     newBox.x2 += screenInfo.screens[0]->x - pScreen->x;
569     newBox.y1 += screenInfo.screens[0]->y - pScreen->y;
570     newBox.y2 += screenInfo.screens[0]->y - pScreen->y;
572     (* pScreen->ConstrainCursor)(pDev, pScreen, &newBox);
576 static Bool
577 XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
579     SpritePtr pSprite = pDev->spriteInfo->sprite;
581     if(pWin == screenInfo.screens[0]->root) {
582         int i;
583         FOR_NSCREENS(i)
584             pSprite->windows[i] = screenInfo.screens[i]->root;
585     } else {
586         PanoramiXRes *win;
587         int rc, i;
589         rc = dixLookupResourceByType((pointer *)&win, pWin->drawable.id,
590                                      XRT_WINDOW, serverClient, DixReadAccess);
591         if (rc != Success)
592             return FALSE;
594         FOR_NSCREENS(i) {
595             rc = dixLookupWindow(pSprite->windows + i, win->info[i].id,
596                                  serverClient, DixReadAccess);
597             if (rc != Success)  /* window is being unmapped */
598                 return FALSE;
599         }
600     }
601     return TRUE;
604 static void
605 XineramaConfineCursorToWindow(DeviceIntPtr pDev,
606                               WindowPtr pWin,
607                               Bool generateEvents)
609     SpritePtr pSprite = pDev->spriteInfo->sprite;
611     int x, y, off_x, off_y, i;
613     if(!XineramaSetWindowPntrs(pDev, pWin))
614         return;
616     i = PanoramiXNumScreens - 1;
618     RegionCopy(&pSprite->Reg1,
619             &pSprite->windows[i]->borderSize);
620     off_x = screenInfo.screens[i]->x;
621     off_y = screenInfo.screens[i]->y;
623     while(i--) {
624         x = off_x - screenInfo.screens[i]->x;
625         y = off_y - screenInfo.screens[i]->y;
627         if(x || y)
628             RegionTranslate(&pSprite->Reg1, x, y);
630         RegionUnion(&pSprite->Reg1, &pSprite->Reg1,
631                 &pSprite->windows[i]->borderSize);
633         off_x = screenInfo.screens[i]->x;
634         off_y = screenInfo.screens[i]->y;
635     }
637     pSprite->hotLimits = *RegionExtents(&pSprite->Reg1);
639     if(RegionNumRects(&pSprite->Reg1) > 1)
640         pSprite->hotShape = &pSprite->Reg1;
641     else
642         pSprite->hotShape = NullRegion;
644     pSprite->confined = FALSE;
645     pSprite->confineWin = (pWin == screenInfo.screens[0]->root) ? NullWindow : pWin;
647     CheckPhysLimits(pDev, pSprite->current, generateEvents, FALSE, NULL);
650 #endif  /* PANORAMIX */
652 /**
653  * Modifies the filter for the given protocol event type to the given masks.
654  *
655  * There's only two callers: UpdateDeviceState() and XI's SetMaskForExtEvent().
656  * The latter initialises masks for the matching XI events, it's a once-off
657  * setting.
658  * UDS however changes the mask for MotionNotify and DeviceMotionNotify each
659  * time a button is pressed to include the matching ButtonXMotion mask in the
660  * filter.
661  *
662  * @param[in] deviceid The device to modify the filter for.
663  * @param[in] mask The new filter mask.
664  * @param[in] event Protocol event type.
665  */
666 void
667 SetMaskForEvent(int deviceid, Mask mask, int event)
669     if (deviceid < 0 || deviceid >= MAXDEVICES)
670         FatalError("SetMaskForEvent: bogus device id");
671     event_filters[deviceid][event] = mask;
674 void
675 SetCriticalEvent(int event)
677     if (event >= MAXEVENTS)
678         FatalError("SetCriticalEvent: bogus event number");
679     criticalEvents[event >> 3] |= 1 << (event & 7);
682 void
683 ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
685     BoxRec box;
686     int x = *px, y = *py;
687     int incx = 1, incy = 1;
689     if (RegionContainsPoint(shape, x, y, &box))
690         return;
691     box = *RegionExtents(shape);
692     /* this is rather crude */
693     do {
694         x += incx;
695         if (x >= box.x2)
696         {
697             incx = -1;
698             x = *px - 1;
699         }
700         else if (x < box.x1)
701         {
702             incx = 1;
703             x = *px;
704             y += incy;
705             if (y >= box.y2)
706             {
707                 incy = -1;
708                 y = *py - 1;
709             }
710             else if (y < box.y1)
711                 return; /* should never get here! */
712         }
713     } while (!RegionContainsPoint(shape, x, y, &box));
714     *px = x;
715     *py = y;
718 static void
719 CheckPhysLimits(
720     DeviceIntPtr pDev,
721     CursorPtr cursor,
722     Bool generateEvents,
723     Bool confineToScreen, /* unused if PanoramiX on */
724     ScreenPtr pScreen)    /* unused if PanoramiX on */
726     HotSpot new;
727     SpritePtr pSprite = pDev->spriteInfo->sprite;
729     if (!cursor)
730         return;
731     new = pSprite->hotPhys;
732 #ifdef PANORAMIX
733     if (!noPanoramiXExtension)
734         /* I don't care what the DDX has to say about it */
735         pSprite->physLimits = pSprite->hotLimits;
736     else
737 #endif
738     {
739         if (pScreen)
740             new.pScreen = pScreen;
741         else
742             pScreen = new.pScreen;
743         (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits,
744                 &pSprite->physLimits);
745         pSprite->confined = confineToScreen;
746         (* pScreen->ConstrainCursor)(pDev, pScreen, &pSprite->physLimits);
747     }
749     /* constrain the pointer to those limits */
750     if (new.x < pSprite->physLimits.x1)
751         new.x = pSprite->physLimits.x1;
752     else
753         if (new.x >= pSprite->physLimits.x2)
754             new.x = pSprite->physLimits.x2 - 1;
755     if (new.y < pSprite->physLimits.y1)
756         new.y = pSprite->physLimits.y1;
757     else
758         if (new.y >= pSprite->physLimits.y2)
759             new.y = pSprite->physLimits.y2 - 1;
760     if (pSprite->hotShape)
761         ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y);
762     if ((
763 #ifdef PANORAMIX
764             noPanoramiXExtension &&
765 #endif
766             (pScreen != pSprite->hotPhys.pScreen)) ||
767         (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y))
768     {
769 #ifdef PANORAMIX
770         if (!noPanoramiXExtension)
771             XineramaSetCursorPosition (pDev, new.x, new.y, generateEvents);
772         else
773 #endif
774         {
775             if (pScreen != pSprite->hotPhys.pScreen)
776                 pSprite->hotPhys = new;
777             (*pScreen->SetCursorPosition)
778                 (pDev, pScreen, new.x, new.y, generateEvents);
779         }
780         if (!generateEvents)
781             SyntheticMotion(pDev, new.x, new.y);
782     }
784 #ifdef PANORAMIX
785     /* Tell DDX what the limits are */
786     if (!noPanoramiXExtension)
787         XineramaConstrainCursor(pDev);
788 #endif
791 static void
792 CheckVirtualMotion(
793     DeviceIntPtr pDev,
794     QdEventPtr qe,
795     WindowPtr pWin)
797     SpritePtr pSprite = pDev->spriteInfo->sprite;
798     RegionPtr reg = NULL;
799     DeviceEvent *ev = NULL;
801     if (qe)
802     {
803         ev = &qe->event->device_event;
804         switch(ev->type)
805         {
806             case ET_Motion:
807             case ET_ButtonPress:
808             case ET_ButtonRelease:
809             case ET_KeyPress:
810             case ET_KeyRelease:
811             case ET_ProximityIn:
812             case ET_ProximityOut:
813                 pSprite->hot.pScreen = qe->pScreen;
814                 pSprite->hot.x = ev->root_x;
815                 pSprite->hot.y = ev->root_y;
816                 pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo : NullWindow;
817                 break;
818             default:
819                 break;
820         }
821     }
822     if (pWin)
823     {
824         BoxRec lims;
826 #ifdef PANORAMIX
827         if (!noPanoramiXExtension) {
828             int x, y, off_x, off_y, i;
830             if(!XineramaSetWindowPntrs(pDev, pWin))
831                 return;
833             i = PanoramiXNumScreens - 1;
835             RegionCopy(&pSprite->Reg2,
836                     &pSprite->windows[i]->borderSize);
837             off_x = screenInfo.screens[i]->x;
838             off_y = screenInfo.screens[i]->y;
840             while(i--) {
841                 x = off_x - screenInfo.screens[i]->x;
842                 y = off_y - screenInfo.screens[i]->y;
844                 if(x || y)
845                     RegionTranslate(&pSprite->Reg2, x, y);
847                 RegionUnion(&pSprite->Reg2, &pSprite->Reg2,
848                         &pSprite->windows[i]->borderSize);
850                 off_x = screenInfo.screens[i]->x;
851                 off_y = screenInfo.screens[i]->y;
852             }
853         } else
854 #endif
855         {
856             if (pSprite->hot.pScreen != pWin->drawable.pScreen)
857             {
858                 pSprite->hot.pScreen = pWin->drawable.pScreen;
859                 pSprite->hot.x = pSprite->hot.y = 0;
860             }
861         }
863         lims = *RegionExtents(&pWin->borderSize);
864         if (pSprite->hot.x < lims.x1)
865             pSprite->hot.x = lims.x1;
866         else if (pSprite->hot.x >= lims.x2)
867             pSprite->hot.x = lims.x2 - 1;
868         if (pSprite->hot.y < lims.y1)
869             pSprite->hot.y = lims.y1;
870         else if (pSprite->hot.y >= lims.y2)
871             pSprite->hot.y = lims.y2 - 1;
873 #ifdef PANORAMIX
874         if (!noPanoramiXExtension)
875         {
876             if (RegionNumRects(&pSprite->Reg2) > 1)
877                 reg = &pSprite->Reg2;
879         } else
880 #endif
881         {
882             if (wBoundingShape(pWin))
883                 reg = &pWin->borderSize;
884         }
886         if (reg)
887             ConfineToShape(pDev, reg, &pSprite->hot.x, &pSprite->hot.y);
889         if (qe && ev)
890         {
891             qe->pScreen = pSprite->hot.pScreen;
892             ev->root_x = pSprite->hot.x;
893             ev->root_y = pSprite->hot.y;
894         }
895     }
896 #ifdef PANORAMIX
897     if (noPanoramiXExtension) /* No typo. Only set the root win if disabled */
898 #endif
899         RootWindow(pDev->spriteInfo->sprite) = pSprite->hot.pScreen->root;
902 static void
903 ConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
905     SpritePtr pSprite = pDev->spriteInfo->sprite;
907     if (syncEvents.playingEvents)
908     {
909         CheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin);
910         SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y);
911     }
912     else
913     {
914 #ifdef PANORAMIX
915         if(!noPanoramiXExtension) {
916             XineramaConfineCursorToWindow(pDev, pWin, generateEvents);
917             return;
918         }
919 #endif
920         pSprite->hotLimits = *RegionExtents(&pWin->borderSize);
921         pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize
922                                                : NullRegion;
923         CheckPhysLimits(pDev, pSprite->current, generateEvents,
924                         confineToScreen, pWin->drawable.pScreen);
925     }
928 Bool
929 PointerConfinedToScreen(DeviceIntPtr pDev)
931     return pDev->spriteInfo->sprite->confined;
934 /**
935  * Update the sprite cursor to the given cursor.
936  *
937  * ChangeToCursor() will display the new cursor and free the old cursor (if
938  * applicable). If the provided cursor is already the updated cursor, nothing
939  * happens.
940  */
941 static void
942 ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
944     SpritePtr pSprite = pDev->spriteInfo->sprite;
945     ScreenPtr pScreen;
947     if (cursor != pSprite->current)
948     {
949         if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
950                 (pSprite->current->bits->yhot != cursor->bits->yhot))
951             CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined,
952                             (ScreenPtr)NULL);
953 #ifdef PANORAMIX
954         /* XXX: is this really necessary?? (whot) */
955         if (!noPanoramiXExtension)
956             pScreen = pSprite->screen;
957         else
958 #endif
959             pScreen = pSprite->hotPhys.pScreen;
961         (*pScreen->DisplayCursor)(pDev, pScreen, cursor);
962         FreeCursor(pSprite->current, (Cursor)0);
963         pSprite->current = cursor;
964         pSprite->current->refcnt++;
965     }
968 /**
969  * @returns true if b is a descendent of a
970  */
971 Bool
972 IsParent(WindowPtr a, WindowPtr b)
974     for (b = b->parent; b; b = b->parent)
975         if (b == a) return TRUE;
976     return FALSE;
979 /**
980  * Update the cursor displayed on the screen.
981  *
982  * Called whenever a cursor may have changed shape or position.
983  */
984 static void
985 PostNewCursor(DeviceIntPtr pDev)
987     WindowPtr win;
988     GrabPtr grab = pDev->deviceGrab.grab;
989     SpritePtr   pSprite = pDev->spriteInfo->sprite;
990     CursorPtr   pCursor;
992     if (syncEvents.playingEvents)
993         return;
994     if (grab)
995     {
996         if (grab->cursor)
997         {
998             ChangeToCursor(pDev, grab->cursor);
999             return;
1000         }
1001         if (IsParent(grab->window, pSprite->win))
1002             win = pSprite->win;
1003         else
1004             win = grab->window;
1005     }
1006     else
1007         win = pSprite->win;
1008     for (; win; win = win->parent)
1009     {
1010         if (win->optional)
1011         {
1012             pCursor = WindowGetDeviceCursor(win, pDev);
1013             if (!pCursor && win->optional->cursor != NullCursor)
1014                 pCursor = win->optional->cursor;
1015             if (pCursor)
1016             {
1017                 ChangeToCursor(pDev, pCursor);
1018                 return;
1019             }
1020         }
1021     }
1025 /**
1026  * @param dev device which you want to know its current root window
1027  * @return root window where dev's sprite is located
1028  */
1029 WindowPtr
1030 GetCurrentRootWindow(DeviceIntPtr dev)
1032     return RootWindow(dev->spriteInfo->sprite);
1035 /**
1036  * @return window underneath the cursor sprite.
1037  */
1038 WindowPtr
1039 GetSpriteWindow(DeviceIntPtr pDev)
1041     return pDev->spriteInfo->sprite->win;
1044 /**
1045  * @return current sprite cursor.
1046  */
1047 CursorPtr
1048 GetSpriteCursor(DeviceIntPtr pDev)
1050     return pDev->spriteInfo->sprite->current;
1053 /**
1054  * Set x/y current sprite position in screen coordinates.
1055  */
1056 void
1057 GetSpritePosition(DeviceIntPtr pDev, int *px, int *py)
1059     SpritePtr pSprite = pDev->spriteInfo->sprite;
1060     *px = pSprite->hotPhys.x;
1061     *py = pSprite->hotPhys.y;
1064 #ifdef PANORAMIX
1065 int
1066 XineramaGetCursorScreen(DeviceIntPtr pDev)
1068     if(!noPanoramiXExtension) {
1069         return pDev->spriteInfo->sprite->screen->myNum;
1070     } else {
1071         return 0;
1072     }
1074 #endif /* PANORAMIX */
1076 #define TIMESLOP (5 * 60 * 1000) /* 5 minutes */
1078 static void
1079 MonthChangedOrBadTime(InternalEvent *ev)
1081     /* If the ddx/OS is careless about not processing timestamped events from
1082      * different sources in sorted order, then it's possible for time to go
1083      * backwards when it should not.  Here we ensure a decent time.
1084      */
1085     if ((currentTime.milliseconds - ev->any.time) > TIMESLOP)
1086         currentTime.months++;
1087     else
1088         ev->any.time = currentTime.milliseconds;
1091 static void
1092 NoticeTime(InternalEvent *ev)
1094     if (ev->any.time < currentTime.milliseconds)
1095         MonthChangedOrBadTime(ev);
1096     currentTime.milliseconds = ev->any.time;
1097     lastDeviceEventTime = currentTime;
1100 void
1101 NoticeEventTime(InternalEvent *ev)
1103     if (!syncEvents.playingEvents)
1104         NoticeTime(ev);
1107 /**************************************************************************
1108  *            The following procedures deal with synchronous events       *
1109  **************************************************************************/
1111 /**
1112  * EnqueueEvent is a device's processInputProc if a device is frozen.
1113  * Instead of delivering the events to the client, the event is tacked onto a
1114  * linked list for later delivery.
1115  */
1116 void
1117 EnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
1119     QdEventPtr  tail = NULL;
1120     QdEventPtr  qe;
1121     SpritePtr   pSprite = device->spriteInfo->sprite;
1122     int         eventlen;
1123     DeviceEvent *event = &ev->device_event;
1125     if (!list_is_empty(&syncEvents.pending))
1126         tail = list_last_entry(&syncEvents.pending, QdEventRec, next);
1128     NoticeTime((InternalEvent*)event);
1130     /* Fix for key repeating bug. */
1131     if (device->key != NULL && device->key->xkbInfo != NULL &&
1132         event->type == ET_KeyRelease)
1133         AccessXCancelRepeatKey(device->key->xkbInfo, event->detail.key);
1135     if (DeviceEventCallback)
1136     {
1137         DeviceEventInfoRec eventinfo;
1139         /*  The RECORD spec says that the root window field of motion events
1140          *  must be valid.  At this point, it hasn't been filled in yet, so
1141          *  we do it here.  The long expression below is necessary to get
1142          *  the current root window; the apparently reasonable alternative
1143          *  GetCurrentRootWindow()->drawable.id doesn't give you the right
1144          *  answer on the first motion event after a screen change because
1145          *  the data that GetCurrentRootWindow relies on hasn't been
1146          *  updated yet.
1147          */
1148         if (ev->any.type == ET_Motion)
1149             ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
1151         eventinfo.event = ev;
1152         eventinfo.device = device;
1153         CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
1154     }
1156     if (event->type == ET_Motion)
1157     {
1158 #ifdef PANORAMIX
1159         if(!noPanoramiXExtension) {
1160             event->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
1161             event->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
1162         }
1163 #endif
1164         pSprite->hotPhys.x = event->root_x;
1165         pSprite->hotPhys.y = event->root_y;
1166         /* do motion compression, but not if from different devices */
1167         if (tail &&
1168             (tail->event->any.type == ET_Motion) &&
1169             (tail->device == device) &&
1170             (tail->pScreen == pSprite->hotPhys.pScreen))
1171         {
1172             DeviceEvent *tailev = &tail->event->device_event;
1173             tailev->root_x = pSprite->hotPhys.x;
1174             tailev->root_y = pSprite->hotPhys.y;
1175             tailev->time = event->time;
1176             tail->months = currentTime.months;
1177             return;
1178         }
1179     }
1181     eventlen = event->length;
1183     qe = malloc(sizeof(QdEventRec) + eventlen);
1184     if (!qe)
1185         return;
1186     list_init(&qe->next);
1187     qe->device = device;
1188     qe->pScreen = pSprite->hotPhys.pScreen;
1189     qe->months = currentTime.months;
1190     qe->event = (InternalEvent *)(qe + 1);
1191     memcpy(qe->event, event, eventlen);
1192     list_append(&qe->next, &syncEvents.pending);
1195 /**
1196  * Run through the list of events queued up in syncEvents.
1197  * For each event do:
1198  * If the device for this event is not frozen anymore, take it and process it
1199  * as usually.
1200  * After that, check if there's any devices in the list that are not frozen.
1201  * If there is none, we're done. If there is at least one device that is not
1202  * frozen, then re-run from the beginning of the event queue.
1203  */
1204 void
1205 PlayReleasedEvents(void)
1207     QdEventPtr tmp;
1208     QdEventPtr qe;
1209     DeviceIntPtr dev;
1210     DeviceIntPtr pDev;
1212 restart:
1213     list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) {
1214         if (!qe->device->deviceGrab.sync.frozen)
1215         {
1216             list_del(&qe->next);
1217             pDev = qe->device;
1218             if (qe->event->any.type == ET_Motion)
1219                 CheckVirtualMotion(pDev, qe, NullWindow);
1220             syncEvents.time.months = qe->months;
1221             syncEvents.time.milliseconds = qe->event->any.time;
1222 #ifdef PANORAMIX
1223            /* Translate back to the sprite screen since processInputProc
1224               will translate from sprite screen to screen 0 upon reentry
1225               to the DIX layer */
1226             if(!noPanoramiXExtension) {
1227                 DeviceEvent *ev = &qe->event->device_event;
1228                 switch(ev->type)
1229                 {
1230                     case ET_Motion:
1231                     case ET_ButtonPress:
1232                     case ET_ButtonRelease:
1233                     case ET_KeyPress:
1234                     case ET_KeyRelease:
1235                     case ET_ProximityIn:
1236                     case ET_ProximityOut:
1237                         ev->root_x += screenInfo.screens[0]->x -
1238                             pDev->spriteInfo->sprite->screen->x;
1239                         ev->root_y += screenInfo.screens[0]->y -
1240                             pDev->spriteInfo->sprite->screen->y;
1241                         break;
1242                     default:
1243                         break;
1244                 }
1246             }
1247 #endif
1248             (*qe->device->public.processInputProc)(qe->event, qe->device);
1249             free(qe);
1250             for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; dev = dev->next)
1251                 ;
1252             if (!dev)
1253                 break;
1255             /* Playing the event may have unfrozen another device. */
1256             /* So to play it safe, restart at the head of the queue */
1257             goto restart;
1258         }
1259     }
1262 /**
1263  * Freeze or thaw the given devices. The device's processing proc is
1264  * switched to either the real processing proc (in case of thawing) or an
1265  * enqueuing processing proc (usually EnqueueEvent()).
1266  *
1267  * @param dev The device to freeze/thaw
1268  * @param frozen True to freeze or false to thaw.
1269  */
1270 static void
1271 FreezeThaw(DeviceIntPtr dev, Bool frozen)
1273     dev->deviceGrab.sync.frozen = frozen;
1274     if (frozen)
1275         dev->public.processInputProc = dev->public.enqueueInputProc;
1276     else
1277         dev->public.processInputProc = dev->public.realInputProc;
1280 /**
1281  * Unfreeze devices and replay all events to the respective clients.
1282  *
1283  * ComputeFreezes takes the first event in the device's frozen event queue. It
1284  * runs up the sprite tree (spriteTrace) and searches for the window to replay
1285  * the events from. If it is found, it checks for passive grabs one down from
1286  * the window or delivers the events.
1287  */
1288 static void
1289 ComputeFreezes(void)
1291     DeviceIntPtr replayDev = syncEvents.replayDev;
1292     WindowPtr w;
1293     GrabPtr grab;
1294     DeviceIntPtr dev;
1296     for (dev = inputInfo.devices; dev; dev = dev->next)
1297         FreezeThaw(dev, dev->deviceGrab.sync.other ||
1298                 (dev->deviceGrab.sync.state >= FROZEN));
1299     if (syncEvents.playingEvents ||
1300         (!replayDev && list_is_empty(&syncEvents.pending)))
1301         return;
1302     syncEvents.playingEvents = TRUE;
1303     if (replayDev)
1304     {
1305         DeviceEvent* event = replayDev->deviceGrab.sync.event;
1307         syncEvents.replayDev = (DeviceIntPtr)NULL;
1309         w = XYToWindow(replayDev->spriteInfo->sprite,
1310                        event->root_x, event->root_y);
1311         if (!CheckDeviceGrabs(replayDev, event, syncEvents.replayWin))
1312         {
1313             if (IsTouchEvent((InternalEvent*)event))
1314             {
1315                 InternalEvent *events = InitEventList(GetMaximumEventsNum());
1316                 int i, nev;
1317                 TouchPointInfoPtr ti = TouchFindByClientID(replayDev, event->touchid);
1318                 BUG_WARN(!ti);
1319                 nev = GetTouchOwnershipEvents(events, replayDev, ti, XIRejectTouch, ti->listeners[0].listener, 0);
1320                 for (i = 0; i < nev; i++)
1321                     mieqProcessDeviceEvent(replayDev, events + i, NULL);
1322                 ProcessInputEvents();
1323             } else if (replayDev->focus && !IsPointerEvent((InternalEvent*)event))
1324                 DeliverFocusedEvent(replayDev, (InternalEvent*)event, w);
1325             else
1326                 DeliverDeviceEvents(w, (InternalEvent*)event, NullGrab,
1327                                     NullWindow, replayDev);
1328         }
1329     }
1330     for (dev = inputInfo.devices; dev; dev = dev->next)
1331     {
1332         if (!dev->deviceGrab.sync.frozen)
1333         {
1334             PlayReleasedEvents();
1335             break;
1336         }
1337     }
1338     syncEvents.playingEvents = FALSE;
1339     for (dev = inputInfo.devices; dev; dev = dev->next)
1340     {
1341         if (DevHasCursor(dev))
1342         {
1343             /* the following may have been skipped during replay,
1344               so do it now */
1345             if ((grab = dev->deviceGrab.grab) && grab->confineTo)
1346             {
1347                 if (grab->confineTo->drawable.pScreen !=
1348                         dev->spriteInfo->sprite->hotPhys.pScreen)
1349                     dev->spriteInfo->sprite->hotPhys.x =
1350                         dev->spriteInfo->sprite->hotPhys.y = 0;
1351                 ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE);
1352             }
1353             else
1354                 ConfineCursorToWindow(dev,
1355                         dev->spriteInfo->sprite->hotPhys.pScreen->root,
1356                         TRUE, FALSE);
1357             PostNewCursor(dev);
1358         }
1359     }
1362 #ifdef RANDR
1363 void
1364 ScreenRestructured (ScreenPtr pScreen)
1366     GrabPtr grab;
1367     DeviceIntPtr pDev;
1369     for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
1370     {
1371         if (!IsFloating(pDev) && !DevHasCursor(pDev))
1372             continue;
1374         /* GrabDevice doesn't have a confineTo field, so we don't need to
1375          * worry about it. */
1376         if ((grab = pDev->deviceGrab.grab) && grab->confineTo)
1377         {
1378             if (grab->confineTo->drawable.pScreen
1379                     != pDev->spriteInfo->sprite->hotPhys.pScreen)
1380                 pDev->spriteInfo->sprite->hotPhys.x = pDev->spriteInfo->sprite->hotPhys.y = 0;
1381             ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
1382         }
1383         else
1384             ConfineCursorToWindow(pDev,
1385                     pDev->spriteInfo->sprite->hotPhys.pScreen->root,
1386                     TRUE, FALSE);
1387     }
1389 #endif
1391 static void
1392 CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
1394     GrabPtr grab = thisDev->deviceGrab.grab;
1395     DeviceIntPtr dev;
1397     if (thisMode == GrabModeSync)
1398         thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT;
1399     else
1400     {   /* free both if same client owns both */
1401         thisDev->deviceGrab.sync.state = THAWED;
1402         if (thisDev->deviceGrab.sync.other &&
1403             (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) ==
1404              CLIENT_BITS(grab->resource)))
1405             thisDev->deviceGrab.sync.other = NullGrab;
1406     }
1408     if (IsMaster(thisDev))
1409     {
1410         dev = GetPairedDevice(thisDev);
1411         if (otherMode == GrabModeSync)
1412             dev->deviceGrab.sync.other = grab;
1413         else
1414         {       /* free both if same client owns both */
1415             if (dev->deviceGrab.sync.other &&
1416                     (CLIENT_BITS(dev->deviceGrab.sync.other->resource) ==
1417                      CLIENT_BITS(grab->resource)))
1418                 dev->deviceGrab.sync.other = NullGrab;
1419         }
1420     }
1421     ComputeFreezes();
1424 /**
1425  * Save the device's master device id. This needs to be done
1426  * if a client directly grabs a slave device that is attached to a master. For
1427  * the duration of the grab, the device is detached, ungrabbing re-attaches it
1428  * though.
1429  *
1430  * We store the ID of the master device only in case the master disappears
1431  * while the device has a grab.
1432  */
1433 static void
1434 DetachFromMaster(DeviceIntPtr dev)
1436     if (IsFloating(dev))
1437         return;
1439     dev->saved_master_id = GetMaster(dev, MASTER_ATTACHED)->id;
1441     AttachDevice(NULL, dev, NULL);
1444 static void
1445 ReattachToOldMaster(DeviceIntPtr dev)
1447     DeviceIntPtr master = NULL;
1449     if (IsMaster(dev))
1450         return;
1452     dixLookupDevice(&master, dev->saved_master_id, serverClient, DixUseAccess);
1454     if (master)
1455     {
1456         AttachDevice(serverClient, dev, master);
1457         dev->saved_master_id = 0;
1458     }
1461 /**
1462  * Activate a pointer grab on the given device. A pointer grab will cause all
1463  * core pointer events of this device to be delivered to the grabbing client only.
1464  * No other device will send core events to the grab client while the grab is
1465  * on, but core events will be sent to other clients.
1466  * Can cause the cursor to change if a grab cursor is set.
1467  *
1468  * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab
1469  * is an implicit grab caused by a ButtonPress event.
1470  *
1471  * @param mouse The device to grab.
1472  * @param grab The grab structure, needs to be setup.
1473  * @param autoGrab True if the grab was caused by a button down event and not
1474  * explicitely by a client.
1475  */
1476 void
1477 ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
1478                     TimeStamp time, Bool autoGrab)
1480     GrabInfoPtr grabinfo = &mouse->deviceGrab;
1481     WindowPtr oldWin = (grabinfo->grab) ?
1482                         grabinfo->grab->window
1483                         : mouse->spriteInfo->sprite->win;
1484     Bool isPassive = autoGrab & ~ImplicitGrabMask;
1486     /* slave devices need to float for the duration of the grab. */
1487     if (grab->grabtype == XI2 &&
1488         !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse))
1489         DetachFromMaster(mouse);
1491     if (grab->confineTo)
1492     {
1493         if (grab->confineTo->drawable.pScreen
1494                 != mouse->spriteInfo->sprite->hotPhys.pScreen)
1495             mouse->spriteInfo->sprite->hotPhys.x =
1496                 mouse->spriteInfo->sprite->hotPhys.y = 0;
1497         ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE);
1498     }
1499     DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab);
1500     mouse->valuator->motionHintWindow = NullWindow;
1501     if (syncEvents.playingEvents)
1502         grabinfo->grabTime = syncEvents.time;
1503     else
1504         grabinfo->grabTime = time;
1505     if (grab->cursor)
1506         grab->cursor->refcnt++;
1507     CopyGrab(grabinfo->activeGrab, grab);
1508     grabinfo->grab = grabinfo->activeGrab;
1509     grabinfo->fromPassiveGrab = isPassive;
1510     grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
1511     PostNewCursor(mouse);
1512     CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
1515 /**
1516  * Delete grab on given device, update the sprite.
1517  *
1518  * Extension devices are set up for ActivateKeyboardGrab().
1519  */
1520 void
1521 DeactivatePointerGrab(DeviceIntPtr mouse)
1523     GrabPtr grab = mouse->deviceGrab.grab;
1524     DeviceIntPtr dev;
1525     Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
1526                         mouse->deviceGrab.implicitGrab);
1528     TouchRemovePointerGrab(mouse);
1530     mouse->valuator->motionHintWindow = NullWindow;
1531     mouse->deviceGrab.grab = NullGrab;
1532     mouse->deviceGrab.sync.state = NOT_GRABBED;
1533     mouse->deviceGrab.fromPassiveGrab = FALSE;
1535     for (dev = inputInfo.devices; dev; dev = dev->next)
1536     {
1537         if (dev->deviceGrab.sync.other == grab)
1538             dev->deviceGrab.sync.other = NullGrab;
1539     }
1540     DoEnterLeaveEvents(mouse, mouse->id, grab->window,
1541                        mouse->spriteInfo->sprite->win, NotifyUngrab);
1542     if (grab->confineTo)
1543         ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE);
1544     PostNewCursor(mouse);
1545     if (grab->cursor)
1546         FreeCursor(grab->cursor, (Cursor)0);
1548     if (!wasImplicit && grab->grabtype == XI2)
1549         ReattachToOldMaster(mouse);
1551     ComputeFreezes();
1554 /**
1555  * Activate a keyboard grab on the given device.
1556  *
1557  * Extension devices have ActivateKeyboardGrab() set as their grabbing proc.
1558  */
1559 void
1560 ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive)
1562     GrabInfoPtr grabinfo = &keybd->deviceGrab;
1563     WindowPtr oldWin;
1565     /* slave devices need to float for the duration of the grab. */
1566     if (grab->grabtype == XI2 &&
1567         !(passive & ImplicitGrabMask) &&
1568         !IsMaster(keybd))
1569         DetachFromMaster(keybd);
1571     if (grabinfo->grab)
1572         oldWin = grabinfo->grab->window;
1573     else if (keybd->focus)
1574         oldWin = keybd->focus->win;
1575     else
1576         oldWin = keybd->spriteInfo->sprite->win;
1577     if (oldWin == FollowKeyboardWin)
1578         oldWin = keybd->focus->win;
1579     if (keybd->valuator)
1580         keybd->valuator->motionHintWindow = NullWindow;
1581     DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
1582     if (syncEvents.playingEvents)
1583         grabinfo->grabTime = syncEvents.time;
1584     else
1585         grabinfo->grabTime = time;
1586     CopyGrab(grabinfo->activeGrab, grab);
1587     grabinfo->grab = grabinfo->activeGrab;
1588     grabinfo->fromPassiveGrab = passive;
1589     grabinfo->implicitGrab = passive & ImplicitGrabMask;
1590     CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
1593 /**
1594  * Delete keyboard grab for the given device.
1595  */
1596 void
1597 DeactivateKeyboardGrab(DeviceIntPtr keybd)
1599     GrabPtr grab = keybd->deviceGrab.grab;
1600     DeviceIntPtr dev;
1601     WindowPtr focusWin = keybd->focus ? keybd->focus->win
1602                                            : keybd->spriteInfo->sprite->win;
1603     Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab &&
1604                         keybd->deviceGrab.implicitGrab);
1606     if (focusWin == FollowKeyboardWin)
1607         focusWin = inputInfo.keyboard->focus->win;
1608     if (keybd->valuator)
1609         keybd->valuator->motionHintWindow = NullWindow;
1610     keybd->deviceGrab.grab = NullGrab;
1611     keybd->deviceGrab.sync.state = NOT_GRABBED;
1612     keybd->deviceGrab.fromPassiveGrab = FALSE;
1614     for (dev = inputInfo.devices; dev; dev = dev->next)
1615     {
1616         if (dev->deviceGrab.sync.other == grab)
1617             dev->deviceGrab.sync.other = NullGrab;
1618     }
1619     DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
1621     if (!wasImplicit && grab->grabtype == XI2)
1622         ReattachToOldMaster(keybd);
1624     ComputeFreezes();
1627 void
1628 AllowSome(ClientPtr client,
1629           TimeStamp time,
1630           DeviceIntPtr thisDev,
1631           int newState)
1633     Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
1634     TimeStamp grabTime;
1635     DeviceIntPtr dev;
1636     GrabInfoPtr devgrabinfo,
1637                 grabinfo = &thisDev->deviceGrab;
1639     thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
1640     thisSynced = FALSE;
1641     otherGrabbed = FALSE;
1642     othersFrozen = FALSE;
1643     grabTime = grabinfo->grabTime;
1644     for (dev = inputInfo.devices; dev; dev = dev->next)
1645     {
1646         devgrabinfo = &dev->deviceGrab;
1648         if (dev == thisDev)
1649             continue;
1650         if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
1651         {
1652             if (!(thisGrabbed || otherGrabbed) ||
1653                 (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER))
1654                 grabTime = devgrabinfo->grabTime;
1655             otherGrabbed = TRUE;
1656             if (grabinfo->sync.other == devgrabinfo->grab)
1657                 thisSynced = TRUE;
1658             if (devgrabinfo->sync.state >= FROZEN)
1659                 othersFrozen = TRUE;
1660         }
1661     }
1662     if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced))
1663         return;
1664     if ((CompareTimeStamps(time, currentTime) == LATER) ||
1665         (CompareTimeStamps(time, grabTime) == EARLIER))
1666         return;
1667     switch (newState)
1668     {
1669         case THAWED:                   /* Async */
1670             if (thisGrabbed)
1671                 grabinfo->sync.state = THAWED;
1672             if (thisSynced)
1673                 grabinfo->sync.other = NullGrab;
1674             ComputeFreezes();
1675             break;
1676         case FREEZE_NEXT_EVENT:         /* Sync */
1677             if (thisGrabbed)
1678             {
1679                 grabinfo->sync.state = FREEZE_NEXT_EVENT;
1680                 if (thisSynced)
1681                     grabinfo->sync.other = NullGrab;
1682                 ComputeFreezes();
1683             }
1684             break;
1685         case THAWED_BOTH:               /* AsyncBoth */
1686             if (othersFrozen)
1687             {
1688                 for (dev = inputInfo.devices; dev; dev = dev->next)
1689                 {
1690                     devgrabinfo = &dev->deviceGrab;
1691                     if (devgrabinfo->grab
1692                             && SameClient(devgrabinfo->grab, client))
1693                         devgrabinfo->sync.state = THAWED;
1694                     if (devgrabinfo->sync.other &&
1695                             SameClient(devgrabinfo->sync.other, client))
1696                         devgrabinfo->sync.other = NullGrab;
1697                 }
1698                 ComputeFreezes();
1699             }
1700             break;
1701         case FREEZE_BOTH_NEXT_EVENT:    /* SyncBoth */
1702             if (othersFrozen)
1703             {
1704                 for (dev = inputInfo.devices; dev; dev = dev->next)
1705                 {
1706                     devgrabinfo = &dev->deviceGrab;
1707                     if (devgrabinfo->grab
1708                             && SameClient(devgrabinfo->grab, client))
1709                         devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT;
1710                     if (devgrabinfo->sync.other
1711                             && SameClient(devgrabinfo->sync.other, client))
1712                         devgrabinfo->sync.other = NullGrab;
1713                 }
1714                 ComputeFreezes();
1715             }
1716             break;
1717         case NOT_GRABBED:               /* Replay */
1718             if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT)
1719             {
1720                 if (thisSynced)
1721                     grabinfo->sync.other = NullGrab;
1722                 syncEvents.replayDev = thisDev;
1723                 syncEvents.replayWin = grabinfo->grab->window;
1724                 (*grabinfo->DeactivateGrab)(thisDev);
1725                 syncEvents.replayDev = (DeviceIntPtr)NULL;
1726             }
1727             break;
1728         case THAW_OTHERS:               /* AsyncOthers */
1729             if (othersFrozen)
1730             {
1731                 for (dev = inputInfo.devices; dev; dev = dev->next)
1732                 {
1733                     if (dev == thisDev)
1734                         continue;
1735                     devgrabinfo = &dev->deviceGrab;
1736                     if (devgrabinfo->grab
1737                             && SameClient(devgrabinfo->grab, client))
1738                         devgrabinfo->sync.state = THAWED;
1739                     if (devgrabinfo->sync.other
1740                             && SameClient(devgrabinfo->sync.other, client))
1741                         devgrabinfo->sync.other = NullGrab;
1742                 }
1743                 ComputeFreezes();
1744             }
1745             break;
1746     }
1749 /**
1750  * Server-side protocol handling for AllowEvents request.
1751  *
1752  * Release some events from a frozen device.
1753  */
1754 int
1755 ProcAllowEvents(ClientPtr client)
1757     TimeStamp           time;
1758     DeviceIntPtr        mouse = NULL;
1759     DeviceIntPtr        keybd = NULL;
1760     REQUEST(xAllowEventsReq);
1762     REQUEST_SIZE_MATCH(xAllowEventsReq);
1763     time = ClientTimeToServerTime(stuff->time);
1765     mouse = PickPointer(client);
1766     keybd = PickKeyboard(client);
1768     switch (stuff->mode)
1769     {
1770         case ReplayPointer:
1771             AllowSome(client, time, mouse, NOT_GRABBED);
1772             break;
1773         case SyncPointer:
1774             AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
1775             break;
1776         case AsyncPointer:
1777             AllowSome(client, time, mouse, THAWED);
1778             break;
1779         case ReplayKeyboard:
1780             AllowSome(client, time, keybd, NOT_GRABBED);
1781             break;
1782         case SyncKeyboard:
1783             AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
1784             break;
1785         case AsyncKeyboard:
1786             AllowSome(client, time, keybd, THAWED);
1787             break;
1788         case SyncBoth:
1789             AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
1790             break;
1791         case AsyncBoth:
1792             AllowSome(client, time, keybd, THAWED_BOTH);
1793             break;
1794         default:
1795             client->errorValue = stuff->mode;
1796             return BadValue;
1797     }
1798     return Success;
1801 /**
1802  * Deactivate grabs from any device that has been grabbed by the client.
1803  */
1804 void
1805 ReleaseActiveGrabs(ClientPtr client)
1807     DeviceIntPtr dev;
1808     Bool    done;
1810     /* XXX CloseDownClient should remove passive grabs before
1811      * releasing active grabs.
1812      */
1813     do {
1814         done = TRUE;
1815         for (dev = inputInfo.devices; dev; dev = dev->next)
1816         {
1817             if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
1818             {
1819                 (*dev->deviceGrab.DeactivateGrab)(dev);
1820                 done = FALSE;
1821             }
1822         }
1823     } while (!done);
1826 /**************************************************************************
1827  *            The following procedures deal with delivering events        *
1828  **************************************************************************/
1830 /**
1831  * Deliver the given events to the given client.
1832  *
1833  * More than one event may be delivered at a time. This is the case with
1834  * DeviceMotionNotifies which may be followed by DeviceValuator events.
1835  *
1836  * TryClientEvents() is the last station before actually writing the events to
1837  * the socket. Anything that is not filtered here, will get delivered to the
1838  * client.
1839  * An event is only delivered if
1840  *   - mask and filter match up.
1841  *   - no other client has a grab on the device that caused the event.
1842  *
1843  *
1844  * @param client The target client to deliver to.
1845  * @param dev The device the event came from. May be NULL.
1846  * @param pEvents The events to be delivered.
1847  * @param count Number of elements in pEvents.
1848  * @param mask Event mask as set by the window.
1849  * @param filter Mask based on event type.
1850  * @param grab Possible grab on the device that caused the event.
1851  *
1852  * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
1853  * client.
1854  */
1855 int
1856 TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
1857                  int count, Mask mask, Mask filter, GrabPtr grab)
1859     int type;
1861 #ifdef DEBUG_EVENTS
1862     ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s",
1863            pEvents->u.u.type, pEvents->u.u.detail, mask,
1864            client ? client->index : -1,
1865            (client && client->clientGone) ? " (gone)" : "");
1866 #endif
1868     if (!client || client == serverClient || client->clientGone) {
1869 #ifdef DEBUG_EVENTS
1870         ErrorF(" not delivered to fake/dead client\n");
1871 #endif
1872         return 0;
1873     }
1875     if (filter != CantBeFiltered && !(mask & filter))
1876     {
1877  #ifdef DEBUG_EVENTS
1878         ErrorF(" filtered\n");
1879  #endif
1880         return 0;
1881     }
1883     if (grab && !SameClient(grab, client))
1884     {
1885 #ifdef DEBUG_EVENTS
1886         ErrorF(" not delivered due to grab\n");
1887 #endif
1888         return -1; /* don't send, but notify caller */
1889     }
1891     type = pEvents->u.u.type;
1892     if (type == MotionNotify)
1893     {
1894         if (mask & PointerMotionHintMask)
1895         {
1896             if (WID(dev->valuator->motionHintWindow) ==
1897                     pEvents->u.keyButtonPointer.event)
1898             {
1899 #ifdef DEBUG_EVENTS
1900                 ErrorF("[dix] \n");
1901                 ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
1902 #endif
1903                 return 1; /* don't send, but pretend we did */
1904             }
1905             pEvents->u.u.detail = NotifyHint;
1906         }
1907         else
1908         {
1909             pEvents->u.u.detail = NotifyNormal;
1910         }
1911     }
1912     else if (type == DeviceMotionNotify)
1913     {
1914         if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer*)pEvents,
1915                                             mask) != 0)
1916             return 1;
1917     } else if (type == KeyPress)
1918     {
1919         if (EventIsKeyRepeat(pEvents))
1920         {
1921             if (!_XkbWantsDetectableAutoRepeat(client))
1922             {
1923                 xEvent release = *pEvents;
1924                 release.u.u.type = KeyRelease;
1925                 WriteEventsToClient(client, 1, &release);
1926 #ifdef DEBUG_EVENTS
1927                 ErrorF(" (plus fake core release for repeat)");
1928 #endif
1929             } else
1930             {
1931 #ifdef DEBUG_EVENTS
1932                 ErrorF(" (detectable autorepeat for core)");
1933 #endif
1934             }
1935         }
1937     } else if (type == DeviceKeyPress)
1938     {
1939         if (EventIsKeyRepeat(pEvents))
1940         {
1941             if (!_XkbWantsDetectableAutoRepeat(client))
1942             {
1943                 deviceKeyButtonPointer release = *(deviceKeyButtonPointer *)pEvents;
1944                 release.type = DeviceKeyRelease;
1945 #ifdef DEBUG_EVENTS
1946                 ErrorF(" (plus fake xi1 release for repeat)");
1947 #endif
1948                 WriteEventsToClient(client, 1, (xEvent *) &release);
1949             }
1950             else {
1951 #ifdef DEBUG_EVENTS
1952                 ErrorF(" (detectable autorepeat for core)");
1953 #endif
1954             }
1955         }
1956     }
1958     if (BitIsOn(criticalEvents, type))
1959     {
1960         if (client->smart_priority < SMART_MAX_PRIORITY)
1961             client->smart_priority++;
1962         SetCriticalOutputPending();
1963     }
1965     WriteEventsToClient(client, count, pEvents);
1966 #ifdef DEBUG_EVENTS
1967     ErrorF("[dix]  delivered\n");
1968 #endif
1969     return 1;
1972 static BOOL
1973 ActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win,
1974                      xEvent *event, Mask deliveryMask)
1976     GrabPtr tempGrab;
1977     OtherInputMasks *inputMasks;
1978     CARD8 type = event->u.u.type;
1979     enum InputLevel grabtype;
1981     if (type == ButtonPress)
1982         grabtype = CORE;
1983     else if (type == DeviceButtonPress)
1984         grabtype = XI;
1985     else if ((type = xi2_get_type(event)) == XI_ButtonPress)
1986         grabtype = XI2;
1987     else
1988         return FALSE;
1990     tempGrab = AllocGrab();
1991     if (!tempGrab)
1992         return FALSE;
1993     tempGrab->next = NULL;
1994     tempGrab->device = dev;
1995     tempGrab->resource = client->clientAsMask;
1996     tempGrab->window = win;
1997     tempGrab->ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
1998     tempGrab->eventMask = deliveryMask;
1999     tempGrab->keyboardMode = GrabModeAsync;
2000     tempGrab->pointerMode = GrabModeAsync;
2001     tempGrab->confineTo = NullWindow;
2002     tempGrab->cursor = NullCursor;
2003     tempGrab->type = type;
2004     tempGrab->grabtype = grabtype;
2006     /* get the XI and XI2 device mask */
2007     inputMasks = wOtherInputMasks(win);
2008     tempGrab->deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id]: 0;
2010     if (inputMasks)
2011         xi2mask_merge(tempGrab->xi2mask, inputMasks->xi2mask);
2013     (*dev->deviceGrab.ActivateGrab)(dev, tempGrab,
2014                                     currentTime, TRUE | ImplicitGrabMask);
2015     FreeGrab(tempGrab);
2016     return TRUE;
2019 /**
2020  * Attempt event delivery to the client owning the window.
2021  */
2022 static enum EventDeliveryState
2023 DeliverToWindowOwner(DeviceIntPtr dev, WindowPtr win,
2024                      xEvent *events, int count, Mask filter,
2025                      GrabPtr grab)
2027     /* if nobody ever wants to see this event, skip some work */
2028     if (filter != CantBeFiltered &&
2029             !((wOtherEventMasks(win)|win->eventMask) & filter))
2030         return EVENT_SKIP;
2032     if (IsInterferingGrab(wClient(win), dev, events))
2033         return EVENT_SKIP;
2035     if (!XaceHook(XACE_RECEIVE_ACCESS, wClient(win), win, events, count))
2036     {
2037         int attempt = TryClientEvents(wClient(win), dev, events,
2038                                       count, win->eventMask,
2039                                       filter, grab);
2040         if (attempt > 0)
2041             return EVENT_DELIVERED;
2042         if (attempt < 0)
2043             return EVENT_REJECTED;
2044     }
2046     return EVENT_NOT_DELIVERED;
2050 /**
2051  * Get the list of clients that should be tried for event delivery on the
2052  * given window.
2053  *
2054  * @return 1 if the client list should be traversed, zero if the event
2055  * should be skipped.
2056  */
2057 static Bool
2058 GetClientsForDelivery(DeviceIntPtr dev, WindowPtr win,
2059                       xEvent *events, Mask filter, InputClients **clients)
2061     int rc = 0;
2063     if (core_get_type(events) != 0)
2064         *clients = (InputClients *)wOtherClients(win);
2065     else if (xi2_get_type(events) != 0)
2066     {
2067         OtherInputMasks *inputMasks = wOtherInputMasks(win);
2068         /* Has any client selected for the event? */
2069         if (!WindowXI2MaskIsset(dev, win, events))
2070             goto out;
2071         *clients = inputMasks->inputClients;
2072     } else {
2073         OtherInputMasks *inputMasks = wOtherInputMasks(win);
2074         /* Has any client selected for the event? */
2075         if (!inputMasks ||
2076             !(inputMasks->inputEvents[dev->id] & filter))
2077             goto out;
2079         *clients = inputMasks->inputClients;
2080     }
2082     rc = 1;
2083 out:
2084     return rc;
2087 /**
2088  * Try delivery on each client in inputclients, provided the event mask
2089  * accepts it and there is no interfering core grab..
2090  */
2091 static enum EventDeliveryState
2092 DeliverEventToInputClients(DeviceIntPtr dev, InputClients *inputclients,
2093                            WindowPtr win, xEvent *events,
2094                            int count, Mask filter, GrabPtr grab,
2095                            ClientPtr *client_return, Mask *mask_return)
2097     int attempt;
2098     enum EventDeliveryState rc = EVENT_NOT_DELIVERED;
2100     for (; inputclients; inputclients = inputclients->next)
2101     {
2102         Mask mask;
2103         ClientPtr client = rClient(inputclients);
2105         if (IsInterferingGrab(client, dev, events))
2106             continue;
2108         mask = GetEventMask(dev, events, inputclients);
2110         if (XaceHook(XACE_RECEIVE_ACCESS, client, win,
2111                     events, count))
2112             /* do nothing */;
2113         else if ( (attempt = TryClientEvents(client, dev,
2114                         events, count,
2115                         mask, filter, grab)) )
2116         {
2117             if (attempt > 0)
2118             {
2119                 rc = EVENT_DELIVERED;
2120                 *client_return = client;
2121                 *mask_return = mask;
2122                 /* Success overrides non-success, so if we've been
2123                  * successful on one client, return that */
2124             } else if (rc == EVENT_NOT_DELIVERED)
2125                 rc = EVENT_REJECTED;
2126         }
2127     }
2129     return rc;
2133 /**
2134  * Deliver events to clients registered on the window.
2135  *
2136  * @param client_return On successful delivery, set to the recipient.
2137  * @param mask_return On successful delivery, set to the recipient's event
2138  * mask for this event.
2139  */
2140 static enum EventDeliveryState
2141 DeliverEventToWindowMask(DeviceIntPtr dev, WindowPtr win, xEvent *events,
2142                          int count, Mask filter, GrabPtr grab,
2143                          ClientPtr *client_return, Mask *mask_return)
2145     InputClients *clients;
2147     if (!GetClientsForDelivery(dev, win, events, filter, &clients))
2148         return EVENT_SKIP;
2150     return DeliverEventToInputClients(dev, clients, win, events, count, filter,
2151                                       grab, client_return, mask_return);
2156 /**
2157  * Deliver events to a window. At this point, we do not yet know if the event
2158  * actually needs to be delivered. May activate a grab if the event is a
2159  * button press.
2160  *
2161  * Core events are always delivered to the window owner. If the filter is
2162  * something other than CantBeFiltered, the event is also delivered to other
2163  * clients with the matching mask on the window.
2164  *
2165  * More than one event may be delivered at a time. This is the case with
2166  * DeviceMotionNotifies which may be followed by DeviceValuator events.
2167  *
2168  * @param pWin The window that would get the event.
2169  * @param pEvents The events to be delivered.
2170  * @param count Number of elements in pEvents.
2171  * @param filter Mask based on event type.
2172  * @param grab Possible grab on the device that caused the event.
2173  *
2174  * @return a positive number if at least one successful delivery has been
2175  * made, 0 if no events were delivered, or a negative number if the event
2176  * has not been delivered _and_ rejected by at least one client.
2177  */
2178 int
2179 DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
2180         *pEvents, int count, Mask filter, GrabPtr grab)
2182     int deliveries = 0, nondeliveries = 0;
2183     ClientPtr client = NullClient;
2184     Mask deliveryMask = 0; /* If a grab occurs due to a button press, then
2185                               this mask is the mask of the grab. */
2186     int type = pEvents->u.u.type;
2188     /* Deliver to window owner */
2189     if ((filter == CantBeFiltered) || core_get_type(pEvents) != 0)
2190     {
2191         enum EventDeliveryState rc;
2193         rc = DeliverToWindowOwner(pDev, pWin, pEvents, count, filter, grab);
2195         switch(rc)
2196         {
2197             case EVENT_SKIP:
2198                 return 0;
2199             case EVENT_REJECTED:
2200                 nondeliveries--;
2201                 break;
2202             case EVENT_DELIVERED:
2203                 /* We delivered to the owner, with our event mask */
2204                 deliveries++;
2205                 client = wClient(pWin);
2206                 deliveryMask = pWin->eventMask;
2207                 break;
2208             case EVENT_NOT_DELIVERED:
2209                 break;
2210         }
2211     }
2213     /* CantBeFiltered means only window owner gets the event */
2214     if (filter != CantBeFiltered)
2215     {
2216         enum EventDeliveryState rc;
2218         rc = DeliverEventToWindowMask(pDev, pWin, pEvents, count, filter,
2219                                       grab, &client, &deliveryMask);
2221         switch(rc)
2222         {
2223             case EVENT_SKIP:
2224                 return 0;
2225             case EVENT_REJECTED:
2226                 nondeliveries--;
2227                 break;
2228             case EVENT_DELIVERED:
2229                 deliveries++;
2230                 break;
2231             case EVENT_NOT_DELIVERED:
2232                 break;
2233         }
2234     }
2236     if (deliveries)
2237     {
2238         /*
2239          * Note that since core events are delivered first, an implicit grab may
2240          * be activated on a core grab, stopping the XI events.
2241          */
2242         if (!grab && ActivateImplicitGrab(pDev, client, pWin, pEvents, deliveryMask))
2243             /* grab activated */;
2244         else if (type == MotionNotify)
2245             pDev->valuator->motionHintWindow = pWin;
2246         else if (type == DeviceMotionNotify || type == DeviceButtonPress)
2247                 CheckDeviceGrabAndHintWindow (pWin, type,
2248                                               (deviceKeyButtonPointer*) pEvents,
2249                                               grab, client, deliveryMask);
2250         return deliveries;
2251     }
2252     return nondeliveries;
2255 /**
2256  * Filter out raw events for XI 2.0 and XI 2.1 clients.
2257  *
2258  * If there is a grab on the device, 2.0 clients only get raw events if they
2259  * have the grab. 2.1+ clients get raw events in all cases.
2260  *
2261  * @return TRUE if the event should be discarded, FALSE otherwise.
2262  */
2263 static BOOL
2264 FilterRawEvents(const ClientPtr client, const GrabPtr grab)
2266     XIClientPtr client_xi_version;
2267     int cmp;
2269     /* device not grabbed -> don't filter */
2270     if (!grab)
2271         return FALSE;
2273     client_xi_version = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
2275     cmp = version_compare(client_xi_version->major_version,
2276                           client_xi_version->minor_version, 2, 0);
2277     /* XI 2.0: if device is grabbed, skip
2278        XI 2.1: if device is grabbed by us, skip, we've already delivered */
2279     return (cmp == 0) ? TRUE : SameClient(grab, client);
2282 /**
2283  * Deliver a raw event to the grab owner (if any) and to all root windows.
2284  *
2285  * Raw event delivery differs between XI 2.0 and XI 2.1.
2286  * XI 2.0: events delivered to the grabbing client (if any) OR to all root
2287  * windows
2288  * XI 2.1: events delivered to all root windows, regardless of grabbing
2289  * state.
2290  */
2291 void
2292 DeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
2294     GrabPtr grab = device->deviceGrab.grab;
2295     xEvent *xi;
2296     int i, rc;
2297     int filter;
2299     rc = EventToXI2((InternalEvent*)ev, (xEvent**)&xi);
2300     if (rc != Success)
2301     {
2302         ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n",
2303                 __func__, device->name, rc);
2304         return;
2305     }
2307     if (grab)
2308         DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE);
2310     filter = GetEventFilter(device, xi);
2312     for (i = 0; i < screenInfo.numScreens; i++)
2313     {
2314         WindowPtr root;
2315         InputClients *inputclients;
2317         root = screenInfo.screens[i]->root;
2318         if (!GetClientsForDelivery(device, root, xi, filter, &inputclients))
2319             continue;
2321         for (; inputclients; inputclients = inputclients->next)
2322         {
2323             ClientPtr c; /* unused */
2324             Mask m;      /* unused */
2325             InputClients ic = *inputclients;
2327             /* Because we run through the list manually, copy the actual
2328              * list, shorten the copy to only have one client and then pass
2329              * that down to DeliverEventToInputClients. This way we avoid
2330              * double events on XI 2.1 clients that have a grab on the
2331              * device.
2332              */
2333             ic.next = NULL;
2335             if (!FilterRawEvents(rClient(&ic), grab))
2336                 DeliverEventToInputClients(device, &ic, root, xi, 1,
2337                                            filter, NULL, &c, &m);
2338         }
2339     }
2341     free(xi);
2344 /* If the event goes to dontClient, don't send it and return 0.  if
2345    send works,  return 1 or if send didn't work, return 2.
2346    Only works for core events.
2347 */
2349 #ifdef PANORAMIX
2350 static int
2351 XineramaTryClientEventsResult(
2352     ClientPtr client,
2353     GrabPtr grab,
2354     Mask mask,
2355     Mask filter
2356 ){
2357     if ((client) && (client != serverClient) && (!client->clientGone) &&
2358         ((filter == CantBeFiltered) || (mask & filter)))
2359     {
2360         if (grab && !SameClient(grab, client)) return -1;
2361         else return 1;
2362     }
2363     return 0;
2365 #endif
2367 /**
2368  * Try to deliver events to the interested parties.
2369  *
2370  * @param pWin The window that would get the event.
2371  * @param pEvents The events to be delivered.
2372  * @param count Number of elements in pEvents.
2373  * @param filter Mask based on event type.
2374  * @param dontClient Don't deliver to the dontClient.
2375  */
2376 int
2377 MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
2378                            int count, Mask filter, ClientPtr dontClient)
2380     OtherClients *other;
2383     if (pWin->eventMask & filter)
2384     {
2385         if (wClient(pWin) == dontClient)
2386             return 0;
2387 #ifdef PANORAMIX
2388         if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2389             return XineramaTryClientEventsResult(
2390                         wClient(pWin), NullGrab, pWin->eventMask, filter);
2391 #endif
2392         if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
2393             return 1; /* don't send, but pretend we did */
2394         return TryClientEvents(wClient(pWin), NULL, pEvents, count,
2395                                pWin->eventMask, filter, NullGrab);
2396     }
2397     for (other = wOtherClients(pWin); other; other = other->next)
2398     {
2399         if (other->mask & filter)
2400         {
2401             if (SameClient(other, dontClient))
2402                 return 0;
2403 #ifdef PANORAMIX
2404             if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2405               return XineramaTryClientEventsResult(
2406                         rClient(other), NullGrab, other->mask, filter);
2407 #endif
2408             if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents,
2409                          count))
2410                 return 1; /* don't send, but pretend we did */
2411             return TryClientEvents(rClient(other), NULL, pEvents, count,
2412                                    other->mask, filter, NullGrab);
2413         }
2414     }
2415     return 2;
2418 static Window FindChildForEvent(SpritePtr pSprite, WindowPtr event)
2420     WindowPtr w = DeepestSpriteWin(pSprite);
2421     Window child = None;
2423     /* If the search ends up past the root should the child field be
2424        set to none or should the value in the argument be passed
2425        through. It probably doesn't matter since everyone calls
2426        this function with child == None anyway. */
2427     while (w)
2428     {
2429         /* If the source window is same as event window, child should be
2430            none.  Don't bother going all all the way back to the root. */
2432         if (w == event)
2433         {
2434             child = None;
2435             break;
2436         }
2438         if (w->parent == event)
2439         {
2440             child = w->drawable.id;
2441             break;
2442         }
2443         w = w->parent;
2444     }
2445     return child;
2448 /**
2449  * Adjust event fields to comply with the window properties.
2450  *
2451  * @param xE Event to be modified in place
2452  * @param pWin The window to get the information from.
2453  * @param child Child window setting for event (if applicable)
2454  * @param calcChild If True, calculate the child window.
2455  */
2456 void
2457 FixUpEventFromWindow(
2458     SpritePtr pSprite,
2459     xEvent *xE,
2460     WindowPtr pWin,
2461     Window child,
2462     Bool calcChild)
2464     int evtype;
2466     if (calcChild)
2467         child = FindChildForEvent(pSprite, pWin);
2469     if ((evtype = xi2_get_type(xE)))
2470     {
2471         xXIDeviceEvent* event = (xXIDeviceEvent*)xE;
2473         switch (evtype)
2474         {
2475             case XI_RawKeyPress:
2476             case XI_RawKeyRelease:
2477             case XI_RawButtonPress:
2478             case XI_RawButtonRelease:
2479             case XI_RawMotion:
2480             case XI_RawTouchBegin:
2481             case XI_RawTouchUpdate:
2482             case XI_RawTouchEnd:
2483             case XI_DeviceChanged:
2484             case XI_HierarchyChanged:
2485             case XI_PropertyEvent:
2486                 return;
2487             default:
2488                 break;
2489         }
2491         event->root = RootWindow(pSprite)->drawable.id;
2492         event->event = pWin->drawable.id;
2494         if (evtype == XI_TouchOwnership)
2495         {
2496             event->child = child;
2497             return;
2498         }
2500         if (pSprite->hot.pScreen == pWin->drawable.pScreen)
2501         {
2502             event->event_x = event->root_x - FP1616(pWin->drawable.x, 0);
2503             event->event_y = event->root_y - FP1616(pWin->drawable.y, 0);
2504             event->child = child;
2505         } else
2506         {
2507             event->event_x = 0;
2508             event->event_y = 0;
2509             event->child = None;
2510         }
2512         if (event->evtype == XI_Enter || event->evtype == XI_Leave ||
2513             event->evtype == XI_FocusIn || event->evtype == XI_FocusOut)
2514             ((xXIEnterEvent*)event)->same_screen =
2515                 (pSprite->hot.pScreen == pWin->drawable.pScreen);
2517     } else
2518     {
2519         XE_KBPTR.root = RootWindow(pSprite)->drawable.id;
2520         XE_KBPTR.event = pWin->drawable.id;
2521         if (pSprite->hot.pScreen == pWin->drawable.pScreen)
2522         {
2523             XE_KBPTR.sameScreen = xTrue;
2524             XE_KBPTR.child = child;
2525             XE_KBPTR.eventX =
2526                 XE_KBPTR.rootX - pWin->drawable.x;
2527             XE_KBPTR.eventY =
2528                 XE_KBPTR.rootY - pWin->drawable.y;
2529         }
2530         else
2531         {
2532             XE_KBPTR.sameScreen = xFalse;
2533             XE_KBPTR.child = None;
2534             XE_KBPTR.eventX = 0;
2535             XE_KBPTR.eventY = 0;
2536         }
2537     }
2540 /**
2541  * Check if a given event is deliverable at all on a given window.
2542  *
2543  * This function only checks if any client wants it, not for a specific
2544  * client.
2545  *
2546  * @param[in] dev The device this event is being sent for.
2547  * @param[in] evtype The event type of the event that is to be sent.
2548  * @param[in] win The current event window.
2549  *
2550  * @return Bitmask of ::EVENT_XI2_MASK, ::EVENT_XI1_MASK, ::EVENT_CORE_MASK, and
2551  *         ::EVENT_DONT_PROPAGATE_MASK.
2552  */
2553 int
2554 EventIsDeliverable(DeviceIntPtr dev, int evtype, WindowPtr win)
2556     int rc = 0;
2557     int filter = 0;
2558     int type;
2559     OtherInputMasks *inputMasks = wOtherInputMasks(win);
2561     if ((type = GetXI2Type(evtype)) != 0)
2562     {
2563         if (inputMasks && xi2mask_isset(inputMasks->xi2mask, dev, type))
2564             rc |= EVENT_XI2_MASK;
2565     }
2567     if ((type = GetXIType(evtype)) != 0)
2568     {
2569         filter = event_get_filter_from_type(dev, type);
2571         /* Check for XI mask */
2572         if (inputMasks &&
2573             (inputMasks->deliverableEvents[dev->id] & filter) &&
2574             (inputMasks->inputEvents[dev->id] & filter))
2575             rc |= EVENT_XI1_MASK;
2577         /* Check for XI DontPropagate mask */
2578         if (inputMasks && (inputMasks->dontPropagateMask[dev->id] & filter))
2579             rc |= EVENT_DONT_PROPAGATE_MASK;
2581     }
2583     if ((type = GetCoreType(evtype)) != 0)
2584     {
2585         filter = event_get_filter_from_type(dev, type);
2587         /* Check for core mask */
2588         if ((win->deliverableEvents & filter) &&
2589             ((wOtherEventMasks(win) | win->eventMask) & filter))
2590             rc |= EVENT_CORE_MASK;
2592         /* Check for core DontPropagate mask */
2593         if (filter & wDontPropagateMask(win))
2594             rc |= EVENT_DONT_PROPAGATE_MASK;
2595     }
2597     return rc;
2600 static int
2601 DeliverEvent(DeviceIntPtr dev, xEvent *xE, int count,
2602              WindowPtr win, Window child, GrabPtr grab)
2604     SpritePtr pSprite = dev->spriteInfo->sprite;
2605     Mask filter;
2606     int deliveries = 0;
2608     if (XaceHook(XACE_SEND_ACCESS, NULL, dev, win, xE, count) == Success) {
2609         filter = GetEventFilter(dev, xE);
2610         FixUpEventFromWindow(pSprite, xE, win, child, FALSE);
2611         deliveries = DeliverEventsToWindow(dev, win, xE, count,
2612                 filter, grab);
2613     }
2615     return deliveries;
2618 static int
2619 DeliverOneEvent(InternalEvent *event, DeviceIntPtr dev, enum InputLevel level,
2620                 WindowPtr win, Window child, GrabPtr grab)
2622     xEvent *xE = NULL;
2623     int count = 0;
2624     int deliveries = 0;
2625     int rc;
2627     switch(level)
2628     {
2629         case XI2:
2630             rc = EventToXI2(event, &xE);
2631             count = 1;
2632             break;
2633         case XI:
2634             rc = EventToXI(event, &xE, &count);
2635             break;
2636         case CORE:
2637             rc = EventToCore(event, &xE, &count);
2638             break;
2639     }
2641     if (rc == Success)
2642     {
2643         deliveries = DeliverEvent(dev, xE, count, win, child, grab);
2644         free(xE);
2645     } else
2646         BUG_WARN_MSG(rc != BadMatch, "%s: conversion to level %d failed with rc %d\n",
2647                      dev->name, level, rc);
2648     return deliveries;
2651 /**
2652  * Deliver events caused by input devices.
2653  *
2654  * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is
2655  * called directly from the processInputProc.
2656  * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call
2657  * DeliverDeviceEvents.
2658  * For focused events, DeliverFocusedEvent is called first, and _may_ call
2659  * DeliverDeviceEvents.
2660  *
2661  * @param pWin Window to deliver event to.
2662  * @param event The events to deliver, not yet in wire format.
2663  * @param grab Possible grab on a device.
2664  * @param stopAt Don't recurse up to the root window.
2665  * @param dev The device that is responsible for the event.
2666  *
2667  * @see DeliverGrabbedEvent
2668  * @see DeliverFocusedEvent
2669  */
2670 int
2671 DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
2672                     WindowPtr stopAt, DeviceIntPtr dev)
2674     Window child = None;
2675     int deliveries = 0;
2676     int mask;
2678     verify_internal_event(event);
2680     while (pWin)
2681     {
2682         if ((mask = EventIsDeliverable(dev, event->any.type, pWin)))
2683         {
2684             /* XI2 events first */
2685             if (mask & EVENT_XI2_MASK)
2686             {
2687                 deliveries = DeliverOneEvent(event, dev, XI2, pWin, child, grab);
2688                 if (deliveries > 0)
2689                     break;
2690             }
2692             /* XI events */
2693             if (mask & EVENT_XI1_MASK)
2694             {
2695                 deliveries = DeliverOneEvent(event, dev, XI, pWin, child, grab);
2696                 if (deliveries > 0)
2697                     break;
2698             }
2700             /* Core event */
2701             if ((mask & EVENT_CORE_MASK) && IsMaster(dev) && dev->coreEvents)
2702             {
2703                 deliveries = DeliverOneEvent(event, dev, CORE, pWin, child, grab);
2704                 if (deliveries > 0)
2705                     break;
2706             }
2708         }
2710         if ((deliveries < 0) || (pWin == stopAt) ||
2711             (mask & EVENT_DONT_PROPAGATE_MASK))
2712         {
2713             deliveries = 0;
2714             break;
2715         }
2717         child = pWin->drawable.id;
2718         pWin = pWin->parent;
2719     }
2721     return deliveries;
2724 /**
2725  * Deliver event to a window and it's immediate parent. Used for most window
2726  * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
2727  * propagate up the tree or extension events
2728  *
2729  * In case of a ReparentNotify event, the event will be delivered to the
2730  * otherParent as well.
2731  *
2732  * @param pWin Window to deliver events to.
2733  * @param xE Events to deliver.
2734  * @param count number of events in xE.
2735  * @param otherParent Used for ReparentNotify events.
2736  */
2737 int
2738 DeliverEvents(WindowPtr pWin, xEvent *xE, int count,
2739               WindowPtr otherParent)
2741     DeviceIntRec dummy;
2742     int     deliveries;
2744 #ifdef PANORAMIX
2745     if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2746         return count;
2747 #endif
2749     if (!count)
2750         return 0;
2752     dummy.id = XIAllDevices;
2754     switch (xE->u.u.type)
2755     {
2756         case DestroyNotify:
2757         case UnmapNotify:
2758         case MapNotify:
2759         case MapRequest:
2760         case ReparentNotify:
2761         case ConfigureNotify:
2762         case ConfigureRequest:
2763         case GravityNotify:
2764         case CirculateNotify:
2765         case CirculateRequest:
2766             xE->u.destroyNotify.event = pWin->drawable.id;
2767             break;
2768     }
2770     switch (xE->u.u.type)
2771     {
2772         case DestroyNotify:
2773         case UnmapNotify:
2774         case MapNotify:
2775         case ReparentNotify:
2776         case ConfigureNotify:
2777         case GravityNotify:
2778         case CirculateNotify:
2779             break;
2780         default:
2781         {
2782             Mask filter;
2783             filter = GetEventFilter(&dummy, xE);
2784             return DeliverEventsToWindow(&dummy, pWin, xE, count, filter,
2785                                          NullGrab);
2786         }
2787     }
2789     deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count,
2790                                        StructureNotifyMask, NullGrab);
2791     if (pWin->parent)
2792     {
2793         xE->u.destroyNotify.event = pWin->parent->drawable.id;
2794         deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count,
2795                                             SubstructureNotifyMask, NullGrab);
2796         if (xE->u.u.type == ReparentNotify)
2797         {
2798             xE->u.destroyNotify.event = otherParent->drawable.id;
2799             deliveries += DeliverEventsToWindow(&dummy,
2800                     otherParent, xE, count, SubstructureNotifyMask,
2801                                                 NullGrab);
2802         }
2803     }
2804     return deliveries;
2808 static Bool
2809 PointInBorderSize(WindowPtr pWin, int x, int y)
2811     BoxRec box;
2813     if(RegionContainsPoint(&pWin->borderSize, x, y, &box))
2814         return TRUE;
2816 #ifdef PANORAMIX
2817     if(!noPanoramiXExtension &&
2818             XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
2819         SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
2820         int i;
2822         FOR_NSCREENS_FORWARD_SKIP(i) {
2823            if(RegionContainsPoint(&pSprite->windows[i]->borderSize,
2824                                   x + screenInfo.screens[0]->x - screenInfo.screens[i]->x,
2825                                   y + screenInfo.screens[0]->y - screenInfo.screens[i]->y,
2826                                   &box))
2827                 return TRUE;
2828         }
2829     }
2830 #endif
2831     return FALSE;
2834 /**
2835  * Traversed from the root window to the window at the position x/y. While
2836  * traversing, it sets up the traversal history in the spriteTrace array.
2837  * After completing, the spriteTrace history is set in the following way:
2838  *   spriteTrace[0] ... root window
2839  *   spriteTrace[1] ... top level window that encloses x/y
2840  *       ...
2841  *   spriteTrace[spriteTraceGood - 1] ... window at x/y
2842  *
2843  * @returns the window at the given coordinates.
2844  */
2845 WindowPtr
2846 XYToWindow(SpritePtr pSprite, int x, int y)
2848     WindowPtr  pWin;
2849     BoxRec              box;
2851     pSprite->spriteTraceGood = 1;       /* root window still there */
2852     pWin = RootWindow(pSprite)->firstChild;
2853     while (pWin)
2854     {
2855         if ((pWin->mapped) &&
2856             (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
2857             (x < pWin->drawable.x + (int)pWin->drawable.width +
2858              wBorderWidth(pWin)) &&
2859             (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
2860             (y < pWin->drawable.y + (int)pWin->drawable.height +
2861              wBorderWidth (pWin))
2862             /* When a window is shaped, a further check
2863              * is made to see if the point is inside
2864              * borderSize
2865              */
2866             && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
2867             && (!wInputShape(pWin) ||
2868                 RegionContainsPoint(wInputShape(pWin),
2869                                     x - pWin->drawable.x,
2870                                     y - pWin->drawable.y, &box))
2871 #ifdef ROOTLESS
2872     /* In rootless mode windows may be offscreen, even when
2873      * they're in X's stack. (E.g. if the native window system
2874      * implements some form of virtual desktop system).
2875      */
2876                 && !pWin->rootlessUnhittable
2877 #endif
2878             )
2879         {
2880             if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize)
2881             {
2882                 pSprite->spriteTraceSize += 10;
2883                 pSprite->spriteTrace = realloc(pSprite->spriteTrace,
2884                                     pSprite->spriteTraceSize*sizeof(WindowPtr));
2885             }
2886             pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
2887             pWin = pWin->firstChild;
2888         }
2889         else
2890             pWin = pWin->nextSib;
2891     }
2892     return DeepestSpriteWin(pSprite);
2895 /**
2896  * Ungrab a currently FocusIn grabbed device and grab the device on the
2897  * given window. If the win given is the NoneWin, the device is ungrabbed if
2898  * applicable and FALSE is returned.
2899  *
2900  * @returns TRUE if the device has been grabbed, or FALSE otherwise.
2901  */
2902 BOOL
2903 ActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
2905     BOOL rc = FALSE;
2906     DeviceEvent event;
2908     if (dev->deviceGrab.grab)
2909     {
2910         if (!dev->deviceGrab.fromPassiveGrab ||
2911             dev->deviceGrab.grab->type != XI_Enter ||
2912             dev->deviceGrab.grab->window == win ||
2913             IsParent(dev->deviceGrab.grab->window, win))
2914             return FALSE;
2915         DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
2916         (*dev->deviceGrab.DeactivateGrab)(dev);
2917     }
2919     if (win == NoneWin || win == PointerRootWin)
2920         return FALSE;
2922     memset(&event, 0, sizeof(DeviceEvent));
2923     event.header = ET_Internal;
2924     event.type = ET_FocusIn;
2925     event.length = sizeof(DeviceEvent);
2926     event.time = GetTimeInMillis();
2927     event.deviceid = dev->id;
2928     event.sourceid = dev->id;
2929     event.detail.button = 0;
2930     rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE,
2931                                     TRUE) != NULL);
2932     if (rc)
2933         DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
2934     return rc;
2937 /**
2938  * Ungrab a currently Enter grabbed device and grab the device for the given
2939  * window.
2940  *
2941  * @returns TRUE if the device has been grabbed, or FALSE otherwise.
2942  */
2943 static BOOL
2944 ActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
2946     BOOL rc = FALSE;
2947     DeviceEvent event;
2949     if (dev->deviceGrab.grab)
2950     {
2951         if (!dev->deviceGrab.fromPassiveGrab ||
2952             dev->deviceGrab.grab->type != XI_Enter ||
2953             dev->deviceGrab.grab->window == win ||
2954             IsParent(dev->deviceGrab.grab->window, win))
2955             return FALSE;
2956         DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
2957         (*dev->deviceGrab.DeactivateGrab)(dev);
2958     }
2960     memset(&event, 0, sizeof(DeviceEvent));
2961     event.header = ET_Internal;
2962     event.type = ET_Enter;
2963     event.length = sizeof(DeviceEvent);
2964     event.time = GetTimeInMillis();
2965     event.deviceid = dev->id;
2966     event.sourceid = dev->id;
2967     event.detail.button = 0;
2968     rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE,
2969                                     TRUE) != NULL);
2970     if (rc)
2971         DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
2972     return rc;
2975 /**
2976  * Update the sprite coordinates based on the event. Update the cursor
2977  * position, then update the event with the new coordinates that may have been
2978  * changed. If the window underneath the sprite has changed, change to new
2979  * cursor and send enter/leave events.
2980  *
2981  * CheckMotion() will not do anything and return FALSE if the event is not a
2982  * pointer event.
2983  *
2984  * @return TRUE if the sprite has moved or FALSE otherwise.
2985  */
2986 Bool
2987 CheckMotion(DeviceEvent *ev, DeviceIntPtr pDev)
2989     WindowPtr prevSpriteWin, newSpriteWin;
2990     SpritePtr pSprite = pDev->spriteInfo->sprite;
2992     verify_internal_event((InternalEvent *)ev);
2994     prevSpriteWin = pSprite->win;
2996     if (ev && !syncEvents.playingEvents)
2997     {
2998         /* GetPointerEvents() guarantees that pointer events have the correct
2999            rootX/Y set already. */
3000         switch (ev->type)
3001         {
3002             case ET_ButtonPress:
3003             case ET_ButtonRelease:
3004             case ET_Motion:
3005             case ET_TouchBegin:
3006             case ET_TouchUpdate:
3007             case ET_TouchEnd:
3008                 break;
3009             default:
3010                 /* all other events return FALSE */
3011                 return FALSE;
3012         }
3015 #ifdef PANORAMIX
3016         if (!noPanoramiXExtension)
3017         {
3018             /* Motion events entering DIX get translated to Screen 0
3019                coordinates.  Replayed events have already been
3020                translated since they've entered DIX before */
3021             ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
3022             ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
3023         } else
3024 #endif
3025         {
3026             if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen)
3027             {
3028                 pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
3029                 RootWindow(pDev->spriteInfo->sprite) =
3030                     pSprite->hot.pScreen->root;
3031             }
3032         }
3034         pSprite->hot.x = ev->root_x;
3035         pSprite->hot.y = ev->root_y;
3036         if (pSprite->hot.x < pSprite->physLimits.x1)
3037             pSprite->hot.x = pSprite->physLimits.x1;
3038         else if (pSprite->hot.x >= pSprite->physLimits.x2)
3039             pSprite->hot.x = pSprite->physLimits.x2 - 1;
3040         if (pSprite->hot.y < pSprite->physLimits.y1)
3041             pSprite->hot.y = pSprite->physLimits.y1;
3042         else if (pSprite->hot.y >= pSprite->physLimits.y2)
3043             pSprite->hot.y = pSprite->physLimits.y2 - 1;
3044         if (pSprite->hotShape)
3045             ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y);
3046         pSprite->hotPhys = pSprite->hot;
3048         if ((pSprite->hotPhys.x != ev->root_x) ||
3049             (pSprite->hotPhys.y != ev->root_y))
3050         {
3051 #ifdef PANORAMIX
3052             if (!noPanoramiXExtension)
3053             {
3054                 XineramaSetCursorPosition(
3055                         pDev, pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
3056             } else
3057 #endif
3058             {
3059                 (*pSprite->hotPhys.pScreen->SetCursorPosition)(
3060                         pDev, pSprite->hotPhys.pScreen,
3061                         pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
3062             }
3063         }
3065         ev->root_x = pSprite->hot.x;
3066         ev->root_y = pSprite->hot.y;
3067     }
3069     newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y);
3071     if (newSpriteWin != prevSpriteWin)
3072     {
3073         int sourceid;
3074         if (!ev) {
3075             UpdateCurrentTimeIf();
3076             sourceid = pDev->id; /* when from WindowsRestructured */
3077         } else
3078             sourceid = ev->sourceid;
3080         if (prevSpriteWin != NullWindow) {
3081             if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin))
3082                 DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin,
3083                                    newSpriteWin, NotifyNormal);
3084         }
3085         /* set pSprite->win after ActivateEnterGrab, otherwise
3086            sprite window == grab_window and no enter/leave events are
3087            sent. */
3088         pSprite->win = newSpriteWin;
3089         PostNewCursor(pDev);
3090         return FALSE;
3091     }
3092     return TRUE;
3095 /**
3096  * Windows have restructured, we need to update the sprite position and the
3097  * sprite's cursor.
3098  */
3099 void
3100 WindowsRestructured(void)
3102     DeviceIntPtr pDev = inputInfo.devices;
3103     while(pDev)
3104     {
3105         if (IsMaster(pDev) || IsFloating(pDev))
3106             CheckMotion(NULL, pDev);
3107         pDev = pDev->next;
3108     }
3111 #ifdef PANORAMIX
3112 /* This was added to support reconfiguration under Xdmx.  The problem is
3113  * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin
3114  * other than 0,0, the information in the private sprite structure must
3115  * be updated accordingly, or XYToWindow (and other routines) will not
3116  * compute correctly. */
3117 void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
3119     GrabPtr   grab;
3120     DeviceIntPtr pDev;
3121     SpritePtr pSprite;
3123     if (noPanoramiXExtension) return;
3125     pDev = inputInfo.devices;
3126     while(pDev)
3127     {
3128         if (DevHasCursor(pDev))
3129         {
3130             pSprite = pDev->spriteInfo->sprite;
3131             pSprite->hot.x        -= xoff;
3132             pSprite->hot.y        -= yoff;
3134             pSprite->hotPhys.x    -= xoff;
3135             pSprite->hotPhys.y    -= yoff;
3137             pSprite->hotLimits.x1 -= xoff;
3138             pSprite->hotLimits.y1 -= yoff;
3139             pSprite->hotLimits.x2 -= xoff;
3140             pSprite->hotLimits.y2 -= yoff;
3142             if (RegionNotEmpty(&pSprite->Reg1))
3143                 RegionTranslate(&pSprite->Reg1, xoff, yoff);
3144             if (RegionNotEmpty(&pSprite->Reg2))
3145                 RegionTranslate(&pSprite->Reg2, xoff, yoff);
3147             /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
3148             if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
3149                 if (grab->confineTo->drawable.pScreen
3150                         != pSprite->hotPhys.pScreen)
3151                     pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
3152                 ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
3153             } else
3154                 ConfineCursorToWindow(
3155                         pDev,
3156                         pSprite->hotPhys.pScreen->root,
3157                         TRUE, FALSE);
3159         }
3160         pDev = pDev->next;
3161     }
3163 #endif
3165 /**
3166  * Initialize a sprite for the given device and set it to some sane values. If
3167  * the device already has a sprite alloc'd, don't realloc but just reset to
3168  * default values.
3169  * If a window is supplied, the sprite will be initialized with the window's
3170  * cursor and positioned in the center of the window's screen. The root window
3171  * is a good choice to pass in here.
3172  *
3173  * It's a good idea to call it only for pointer devices, unless you have a
3174  * really talented keyboard.
3175  *
3176  * @param pDev The device to initialize.
3177  * @param pWin The window where to generate the sprite in.
3178  *
3179  */
3180 void
3181 InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
3183     SpritePtr pSprite;
3184     ScreenPtr pScreen;
3185     CursorPtr pCursor;
3187     if (!pDev->spriteInfo->sprite)
3188     {
3189         DeviceIntPtr it;
3191         pDev->spriteInfo->sprite = (SpritePtr)calloc(1, sizeof(SpriteRec));
3192         if (!pDev->spriteInfo->sprite)
3193             FatalError("InitializeSprite: failed to allocate sprite struct");
3195         /* We may have paired another device with this device before our
3196          * device had a actual sprite. We need to check for this and reset the
3197          * sprite field for all paired devices.
3198          *
3199          * The VCK is always paired with the VCP before the VCP has a sprite.
3200          */
3201         for (it = inputInfo.devices; it; it = it->next)
3202         {
3203             if (it->spriteInfo->paired == pDev)
3204                 it->spriteInfo->sprite = pDev->spriteInfo->sprite;
3205         }
3206         if (inputInfo.keyboard->spriteInfo->paired == pDev)
3207             inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite;
3208     }
3210     pSprite = pDev->spriteInfo->sprite;
3211     pDev->spriteInfo->spriteOwner = TRUE;
3213     pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr)NULL;
3214     pSprite->hot.pScreen = pScreen;
3215     pSprite->hotPhys.pScreen = pScreen;
3216     if (pScreen)
3217     {
3218         pSprite->hotPhys.x = pScreen->width / 2;
3219         pSprite->hotPhys.y = pScreen->height / 2;
3220         pSprite->hotLimits.x2 = pScreen->width;
3221         pSprite->hotLimits.y2 = pScreen->height;
3222     }
3224     pSprite->hot = pSprite->hotPhys;
3225     pSprite->win = pWin;
3227     if (pWin)
3228     {
3229         pCursor = wCursor(pWin);
3230         pSprite->spriteTrace = (WindowPtr *)calloc(1, 32*sizeof(WindowPtr));
3231         if (!pSprite->spriteTrace)
3232             FatalError("Failed to allocate spriteTrace");
3233         pSprite->spriteTraceSize = 32;
3235         RootWindow(pDev->spriteInfo->sprite) = pWin;
3236         pSprite->spriteTraceGood = 1;
3238         pSprite->pEnqueueScreen = pScreen;
3239         pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
3241     } else {
3242         pCursor = NullCursor;
3243         pSprite->spriteTrace = NULL;
3244         pSprite->spriteTraceSize = 0;
3245         pSprite->spriteTraceGood = 0;
3246         pSprite->pEnqueueScreen = screenInfo.screens[0];
3247         pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
3248     }
3249     if (pCursor)
3250         pCursor->refcnt++;
3251     if (pSprite->current)
3252         FreeCursor(pSprite->current, None);
3253     pSprite->current = pCursor;
3255     if (pScreen)
3256     {
3257         (*pScreen->RealizeCursor) ( pDev, pScreen, pSprite->current);
3258         (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current,
3259                                    &pSprite->hotLimits, &pSprite->physLimits);
3260         pSprite->confined = FALSE;
3262         (*pScreen->ConstrainCursor) (pDev, pScreen,
3263                                      &pSprite->physLimits);
3264         (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
3265                                        pSprite->hot.y,
3266                                        FALSE);
3267         (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
3268     }
3269 #ifdef PANORAMIX
3270     if(!noPanoramiXExtension) {
3271         pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
3272         pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
3273         pSprite->hotLimits.x2 = PanoramiXPixWidth  - screenInfo.screens[0]->x;
3274         pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
3275         pSprite->physLimits = pSprite->hotLimits;
3276         pSprite->confineWin = NullWindow;
3277         pSprite->hotShape = NullRegion;
3278         pSprite->screen = pScreen;
3279         /* gotta UNINIT these someplace */
3280         RegionNull(&pSprite->Reg1);
3281         RegionNull(&pSprite->Reg2);
3282     }
3283 #endif
3286 /**
3287  * Update the mouse sprite info when the server switches from a pScreen to another.
3288  * Otherwise, the pScreen of the mouse sprite is never updated when we switch
3289  * from a pScreen to another. Never updating the pScreen of the mouse sprite
3290  * implies that windows that are in pScreen whose pScreen->myNum >0 will never
3291  * get pointer events. This is  because in CheckMotion(), sprite.hotPhys.pScreen
3292  * always points to the first pScreen it has been set by
3293  * DefineInitialRootWindow().
3294  *
3295  * Calling this function is useful for use cases where the server
3296  * has more than one pScreen.
3297  * This function is similar to DefineInitialRootWindow() but it does not
3298  * reset the mouse pointer position.
3299  * @param win must be the new pScreen we are switching to.
3300  */
3301 void
3302 UpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
3304     SpritePtr pSprite = NULL;
3305     WindowPtr win = NULL;
3306     CursorPtr pCursor;
3307     if (!pScreen)
3308         return ;
3310     if (!pDev->spriteInfo->sprite)
3311         return;
3313     pSprite = pDev->spriteInfo->sprite;
3315     win = pScreen->root;
3317     pSprite->hotPhys.pScreen = pScreen;
3318     pSprite->hot = pSprite->hotPhys;
3319     pSprite->hotLimits.x2 = pScreen->width;
3320     pSprite->hotLimits.y2 = pScreen->height;
3321     pSprite->win = win;
3322     pCursor = wCursor(win);
3323     if (pCursor)
3324         pCursor->refcnt++;
3325     if (pSprite->current)
3326         FreeCursor(pSprite->current, 0);
3327     pSprite->current = pCursor;
3328     pSprite->spriteTraceGood = 1;
3329     pSprite->spriteTrace[0] = win;
3330     (*pScreen->CursorLimits) (pDev,
3331                               pScreen,
3332                               pSprite->current,
3333                               &pSprite->hotLimits,
3334                               &pSprite->physLimits);
3335     pSprite->confined = FALSE;
3336     (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
3337     (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
3339 #ifdef PANORAMIX
3340     if(!noPanoramiXExtension) {
3341         pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
3342         pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
3343         pSprite->hotLimits.x2 = PanoramiXPixWidth  - screenInfo.screens[0]->x;
3344         pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
3345         pSprite->physLimits = pSprite->hotLimits;
3346         pSprite->screen = pScreen;
3347     }
3348 #endif
3351 /*
3352  * This does not take any shortcuts, and even ignores its argument, since
3353  * it does not happen very often, and one has to walk up the tree since
3354  * this might be a newly instantiated cursor for an intermediate window
3355  * between the one the pointer is in and the one that the last cursor was
3356  * instantiated from.
3357  */
3358 void
3359 WindowHasNewCursor(WindowPtr pWin)
3361     DeviceIntPtr pDev;
3363     for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
3364         if (DevHasCursor(pDev))
3365             PostNewCursor(pDev);
3368 void
3369 NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
3371     DeviceIntPtr ptr;
3372     SpritePtr pSprite;
3374     ptr = IsFloating(pDev) ? pDev : GetXTestDevice(GetMaster(pDev, MASTER_POINTER));
3375     pSprite = ptr->spriteInfo->sprite;
3377     pSprite->hotPhys.x = x;
3378     pSprite->hotPhys.y = y;
3379 #ifdef PANORAMIX
3380     if(!noPanoramiXExtension) {
3381         pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x;
3382         pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y;
3383         if (newScreen != pSprite->screen) {
3384             pSprite->screen = newScreen;
3385             /* Make sure we tell the DDX to update its copy of the screen */
3386             if(pSprite->confineWin)
3387                 XineramaConfineCursorToWindow(ptr,
3388                         pSprite->confineWin, TRUE);
3389             else
3390                 XineramaConfineCursorToWindow(ptr, screenInfo.screens[0]->root, TRUE);
3391             /* if the pointer wasn't confined, the DDX won't get
3392                told of the pointer warp so we reposition it here */
3393             if(!syncEvents.playingEvents)
3394                 (*pSprite->screen->SetCursorPosition)(
3395                                                       ptr,
3396                                                       pSprite->screen,
3397                     pSprite->hotPhys.x + screenInfo.screens[0]->x -
3398                         pSprite->screen->x,
3399                     pSprite->hotPhys.y + screenInfo.screens[0]->y -
3400                         pSprite->screen->y, FALSE);
3401         }
3402     } else
3403 #endif
3404     if (newScreen != pSprite->hotPhys.pScreen)
3405         ConfineCursorToWindow(ptr, newScreen->root, TRUE, FALSE);
3408 #ifdef PANORAMIX
3410 static Bool
3411 XineramaPointInWindowIsVisible(
3412     WindowPtr pWin,
3413     int x,
3414     int y
3417     BoxRec box;
3418     int i, xoff, yoff;
3420     if (!pWin->realized) return FALSE;
3422     if (RegionContainsPoint(&pWin->borderClip, x, y, &box))
3423         return TRUE;
3425     if(!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) return FALSE;
3427     xoff = x + screenInfo.screens[0]->x;
3428     yoff = y + screenInfo.screens[0]->y;
3430     FOR_NSCREENS_FORWARD_SKIP(i) {
3431         pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
3432         x = xoff - screenInfo.screens[i]->x;
3433         y = yoff - screenInfo.screens[i]->y;
3435         if(RegionContainsPoint(&pWin->borderClip, x, y, &box)
3436            && (!wInputShape(pWin) ||
3437                RegionContainsPoint(wInputShape(pWin),
3438                                    x - pWin->drawable.x,
3439                                    y - pWin->drawable.y, &box)))
3440             return TRUE;
3442     }
3444     return FALSE;
3447 static int
3448 XineramaWarpPointer(ClientPtr client)
3450     WindowPtr   dest = NULL;
3451     int         x, y, rc;
3452     DeviceIntPtr dev;
3453     SpritePtr   pSprite;
3455     REQUEST(xWarpPointerReq);
3457     if (stuff->dstWid != None) {
3458         rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
3459         if (rc != Success)
3460             return rc;
3461     }
3463     /* Post through the XTest device */
3464     dev = PickPointer(client);
3465     dev = GetXTestDevice(dev);
3466     pSprite = dev->spriteInfo->sprite;
3467     x = pSprite->hotPhys.x;
3468     y = pSprite->hotPhys.y;
3470     if (stuff->srcWid != None)
3471     {
3472         int     winX, winY;
3473         XID     winID = stuff->srcWid;
3474         WindowPtr source;
3476         rc = dixLookupWindow(&source, winID, client, DixReadAccess);
3477         if (rc != Success)
3478             return rc;
3480         winX = source->drawable.x;
3481         winY = source->drawable.y;
3482         if(source == screenInfo.screens[0]->root) {
3483             winX -= screenInfo.screens[0]->x;
3484             winY -= screenInfo.screens[0]->y;
3485         }
3486         if (x < winX + stuff->srcX ||
3487             y < winY + stuff->srcY ||
3488             (stuff->srcWidth != 0 &&
3489              winX + stuff->srcX + (int)stuff->srcWidth < x) ||
3490             (stuff->srcHeight != 0 &&
3491              winY + stuff->srcY + (int)stuff->srcHeight < y) ||
3492             !XineramaPointInWindowIsVisible(source, x, y))
3493             return Success;
3494     }
3495     if (dest) {
3496         x = dest->drawable.x;
3497         y = dest->drawable.y;
3498         if(dest == screenInfo.screens[0]->root) {
3499             x -= screenInfo.screens[0]->x;
3500             y -= screenInfo.screens[0]->y;
3501         }
3502     }
3504     x += stuff->dstX;
3505     y += stuff->dstY;
3507     if (x < pSprite->physLimits.x1)
3508         x = pSprite->physLimits.x1;
3509     else if (x >= pSprite->physLimits.x2)
3510         x = pSprite->physLimits.x2 - 1;
3511     if (y < pSprite->physLimits.y1)
3512         y = pSprite->physLimits.y1;
3513     else if (y >= pSprite->physLimits.y2)
3514         y = pSprite->physLimits.y2 - 1;
3515     if (pSprite->hotShape)
3516         ConfineToShape(dev, pSprite->hotShape, &x, &y);
3518     XineramaSetCursorPosition(dev, x, y, TRUE);
3520     return Success;
3523 #endif
3526 /**
3527  * Server-side protocol handling for WarpPointer request.
3528  * Warps the cursor position to the coordinates given in the request.
3529  */
3530 int
3531 ProcWarpPointer(ClientPtr client)
3533     WindowPtr   dest = NULL;
3534     int         x, y, rc;
3535     ScreenPtr   newScreen;
3536     DeviceIntPtr dev, tmp, xtest_dev = NULL;
3537     SpritePtr   pSprite;
3539     REQUEST(xWarpPointerReq);
3540     REQUEST_SIZE_MATCH(xWarpPointerReq);
3542     dev = PickPointer(client);
3544     for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
3545         if (GetMaster(tmp, MASTER_ATTACHED) == dev) {
3546             rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
3547             if (rc != Success)
3548                 return rc;
3549             if (IsXTestDevice(tmp, dev))
3550                 xtest_dev = tmp;
3551         }
3552     }
3554     /* Use the XTest device to actually move the pointer */
3555     dev = xtest_dev;
3556     pSprite = dev->spriteInfo->sprite;
3558 #ifdef PANORAMIX
3559     if(!noPanoramiXExtension)
3560         return XineramaWarpPointer(client);
3561 #endif
3563     if (stuff->dstWid != None) {
3564         rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess);
3565         if (rc != Success)
3566             return rc;
3567     }
3568     x = pSprite->hotPhys.x;
3569     y = pSprite->hotPhys.y;
3571     if (stuff->srcWid != None)
3572     {
3573         int     winX, winY;
3574         XID     winID = stuff->srcWid;
3575         WindowPtr source;
3577         rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess);
3578         if (rc != Success)
3579             return rc;
3581         winX = source->drawable.x;
3582         winY = source->drawable.y;
3583         if (source->drawable.pScreen != pSprite->hotPhys.pScreen ||
3584             x < winX + stuff->srcX ||
3585             y < winY + stuff->srcY ||
3586             (stuff->srcWidth != 0 &&
3587              winX + stuff->srcX + (int)stuff->srcWidth < x) ||
3588             (stuff->srcHeight != 0 &&
3589              winY + stuff->srcY + (int)stuff->srcHeight < y) ||
3590             !PointInWindowIsVisible(source, x, y))
3591             return Success;
3592     }
3593     if (dest)
3594     {
3595         x = dest->drawable.x;
3596         y = dest->drawable.y;
3597         newScreen = dest->drawable.pScreen;
3598     } else
3599         newScreen = pSprite->hotPhys.pScreen;
3601     x += stuff->dstX;
3602     y += stuff->dstY;
3604     if (x < 0)
3605         x = 0;
3606     else if (x >= newScreen->width)
3607         x = newScreen->width - 1;
3608     if (y < 0)
3609         y = 0;
3610     else if (y >= newScreen->height)
3611         y = newScreen->height - 1;
3613     if (newScreen == pSprite->hotPhys.pScreen)
3614     {
3615         if (x < pSprite->physLimits.x1)
3616             x = pSprite->physLimits.x1;
3617         else if (x >= pSprite->physLimits.x2)
3618             x = pSprite->physLimits.x2 - 1;
3619         if (y < pSprite->physLimits.y1)
3620             y = pSprite->physLimits.y1;
3621         else if (y >= pSprite->physLimits.y2)
3622             y = pSprite->physLimits.y2 - 1;
3623         if (pSprite->hotShape)
3624             ConfineToShape(dev, pSprite->hotShape, &x, &y);
3625         (*newScreen->SetCursorPosition)(dev, newScreen, x, y, TRUE);
3626     }
3627     else if (!PointerConfinedToScreen(dev))
3628     {
3629         NewCurrentScreen(dev, newScreen, x, y);
3630     }
3631     return Success;
3634 static Bool
3635 BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
3637      if(RegionNotEmpty(&pWin->borderSize))
3638         return TRUE;
3640 #ifdef PANORAMIX
3641      if(!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) {
3642         int i;
3644         FOR_NSCREENS_FORWARD_SKIP(i) {
3645             if(RegionNotEmpty(&pDev->spriteInfo->sprite->windows[i]->borderSize))
3646                 return TRUE;
3647         }
3648      }
3649 #endif
3650      return FALSE;
3653 /**
3654  * Activate the given passive grab. If the grab is activated successfully, the
3655  * event has been delivered to the client.
3656  *
3657  * @param device The device of the event to check.
3658  * @param grab The grab to check.
3659  * @param event The current device event.
3660  * @param real_event The original event, in case of touch emulation. The
3661  * real event is the one stored in the sync queue.
3662  *
3663  * @return Whether the grab has been activated.
3664  */
3665 Bool
3666 ActivatePassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event,
3667                     InternalEvent *real_event)
3670     SpritePtr pSprite = device->spriteInfo->sprite;
3671     GrabInfoPtr grabinfo = &device->deviceGrab;
3672     xEvent *xE = NULL;
3673     int count;
3674     int rc;
3676     /* The only consumers of corestate are Xi 1.x and core events, which
3677      * are guaranteed to come from DeviceEvents. */
3678     if (grab->grabtype == XI || grab->grabtype == CORE)
3679     {
3680         DeviceIntPtr gdev;
3682         event->device_event.corestate &= 0x1f00;
3684         if (grab->grabtype == CORE)
3685             gdev = GetMaster(device, KEYBOARD_OR_FLOAT);
3686         else
3687             gdev = grab->modifierDevice;
3689         if (gdev && gdev->key && gdev->key->xkbInfo)
3690             event->device_event.corestate |=
3691                 gdev->key->xkbInfo->state.grab_mods & (~0x1f00);
3692     }
3694     if (grab->grabtype == CORE)
3695     {
3696         rc = EventToCore(event, &xE, &count);
3697         if (rc != Success)
3698         {
3699             BUG_WARN_MSG(rc != BadMatch,"[dix] %s: core conversion failed"
3700                          "(%d, %d).\n", device->name, event->any.type, rc);
3701             return FALSE;
3702         }
3703     } else if (grab->grabtype == XI2)
3704     {
3705         rc = EventToXI2(event, &xE);
3706         if (rc != Success)
3707         {
3708             if (rc != BadMatch)
3709                 BUG_WARN_MSG(rc != BadMatch,"[dix] %s: XI2 conversion failed"
3710                              "(%d, %d).\n", device->name, event->any.type, rc);
3711             return FALSE;
3712         }
3713         count = 1;
3714     } else
3715     {
3716         rc = EventToXI(event, &xE, &count);
3717         if (rc != Success)
3718         {
3719             if (rc != BadMatch)
3720                 BUG_WARN_MSG(rc != BadMatch,"[dix] %s: XI conversion failed"
3721                              "(%d, %d).\n", device->name, event->any.type, rc);
3722             return FALSE;
3723         }
3724     }
3726     (*grabinfo->ActivateGrab)(device, grab,
3727                               ClientTimeToServerTime(event->any.time), TRUE);
3729     if (xE)
3730     {
3731         FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
3733         /* XXX: XACE? */
3734         TryClientEvents(rClient(grab), device, xE, count,
3735                         GetEventFilter(device, xE),
3736                         GetEventFilter(device, xE), grab);
3737     }
3739     if (grabinfo->sync.state == FROZEN_NO_EVENT)
3740         grabinfo->sync.state = FROZEN_WITH_EVENT;
3741     *grabinfo->sync.event = real_event->device_event;
3743     free(xE);
3744     return TRUE;
3747 static BOOL
3748 CoreGrabInterferes(DeviceIntPtr device, GrabPtr grab)
3750     DeviceIntPtr other;
3751     BOOL interfering = FALSE;
3753     for (other = inputInfo.devices; other; other = other->next)
3754     {
3755         GrabPtr othergrab = other->deviceGrab.grab;
3756         if (othergrab && othergrab->grabtype == CORE &&
3757                 SameClient(grab, rClient(othergrab)) &&
3758                 ((IsPointerDevice(grab->device) &&
3759                   IsPointerDevice(othergrab->device)) ||
3760                  (IsKeyboardDevice(grab->device) &&
3761                   IsKeyboardDevice(othergrab->device))))
3762         {
3763             interfering = TRUE;
3764             break;
3765         }
3766     }
3768     return interfering;
3771 enum MatchFlags {
3772     NO_MATCH    = 0x0,
3773     CORE_MATCH  = 0x1,
3774     XI_MATCH    = 0x2,
3775     XI2_MATCH   = 0x4,
3776 };
3778 /**
3779  * Match the grab against the temporary grab on the given input level.
3780  * Modifies the temporary grab pointer.
3781  *
3782  * @param grab The grab to match against
3783  * @param tmp The temporary grab to use for matching
3784  * @param level The input level we want to match on
3785  * @param event_type Wire protocol event type
3786  *
3787  * @return The respective matched flag or 0 for no match
3788  */
3789 static enum MatchFlags
3790 MatchForType(const GrabPtr grab, GrabPtr tmp, enum InputLevel level, int event_type)
3792     enum MatchFlags match;
3793     BOOL ignore_device = FALSE;
3794     int grabtype;
3795     int evtype;
3797     switch(level)
3798     {
3799         case XI2:
3800             grabtype = XI2;
3801             evtype = GetXI2Type(event_type);
3802             BUG_WARN(!evtype);
3803             match = XI2_MATCH;
3804             break;
3805         case XI:
3806             grabtype = XI;
3807             evtype = GetXIType(event_type);
3808             match = XI_MATCH;
3809             break;
3810         case CORE:
3811             grabtype = CORE;
3812             evtype = GetCoreType(event_type);
3813             match = CORE_MATCH;
3814             ignore_device = TRUE;
3815             break;
3816     }
3818     tmp->grabtype = grabtype;
3819     tmp->type = evtype;
3821     if (tmp->type && GrabMatchesSecond(tmp, grab, ignore_device))
3822         return match;
3824     return NO_MATCH;
3827 /**
3828  * Check an individual grab against an event to determine if a passive grab
3829  * should be activated.
3830  *
3831  * @param device The device of the event to check.
3832  * @param grab The grab to check.
3833  * @param event The current device event.
3834  * @param checkCore Check for core grabs too.
3835  * @param tempGrab A pre-allocated temporary grab record for matching. This
3836  *        must have the window and device values filled in.
3837  *
3838  * @return Whether the grab matches the event.
3839  */
3840 static Bool
3841 CheckPassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event,
3842                  Bool checkCore, GrabPtr tempGrab)
3844     DeviceIntPtr gdev;
3845     XkbSrvInfoPtr xkbi = NULL;
3846     enum MatchFlags match = 0;
3847     int emulated_type = 0;
3849     gdev = grab->modifierDevice;
3850     if (grab->grabtype == CORE)
3851     {
3852         gdev = GetMaster(device, KEYBOARD_OR_FLOAT);
3853     } else if (grab->grabtype == XI2)
3854     {
3855         /* if the device is an attached slave device, gdev must be the
3856          * attached master keyboard. Since the slave may have been
3857          * reattached after the grab, the modifier device may not be the
3858          * same. */
3859         if (!IsMaster(grab->device) && !IsFloating(device))
3860             gdev = GetMaster(device, MASTER_KEYBOARD);
3861     }
3863     if (gdev && gdev->key)
3864         xkbi= gdev->key->xkbInfo;
3865     tempGrab->modifierDevice = grab->modifierDevice;
3866     tempGrab->modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
3868     /* Check for XI2 and XI grabs first */
3869     match = MatchForType(grab, tempGrab, XI2, event->any.type);
3871     if (!match && IsTouchEvent(event) && (event->device_event.flags & TOUCH_POINTER_EMULATED))
3872     {
3873         emulated_type = TouchGetPointerEventType(event);
3874         match = MatchForType(grab, tempGrab, XI2, emulated_type);
3875     }
3877     if (!match)
3878         match = MatchForType(grab, tempGrab, XI, event->any.type);
3880     if (!match && emulated_type)
3881         match = MatchForType(grab, tempGrab, XI, emulated_type);
3883     if (!match && checkCore)
3884     {
3885         match = MatchForType(grab, tempGrab, CORE, event->any.type);
3886         if (!match && emulated_type)
3887             match = MatchForType(grab, tempGrab, CORE, emulated_type);
3888     }
3890     if (!match || (grab->confineTo &&
3891                    (!grab->confineTo->realized ||
3892                     !BorderSizeNotEmpty(device, grab->confineTo))))
3893         return FALSE;
3895     /* In some cases a passive core grab may exist, but the client
3896      * already has a core grab on some other device. In this case we
3897      * must not get the grab, otherwise we may never ungrab the
3898      * device.
3899      */
3901     if (grab->grabtype == CORE)
3902     {
3903         /* A passive grab may have been created for a different device
3904            than it is assigned to at this point in time.
3905            Update the grab's device and modifier device to reflect the
3906            current state.
3907            Since XGrabDeviceButton requires to specify the
3908            modifierDevice explicitly, we don't override this choice.
3909          */
3910         if (grab->type < GenericEvent)
3911         {
3912             grab->device = device;
3913             grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD);
3914         }
3916         if (CoreGrabInterferes(device, grab))
3917             return FALSE;
3918     }
3920     return TRUE;
3923 /**
3924  * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
3925  * passive grab set on the window to be activated.
3926  * If activate is true and a passive grab is found, it will be activated,
3927  * and the event will be delivered to the client.
3928  *
3929  * @param pWin The window that may be subject to a passive grab.
3930  * @param device Device that caused the event.
3931  * @param event The current device event.
3932  * @param checkCore Check for core grabs too.
3933  * @param activate If a grab is found, activate it and deliver the event.
3934  */
3936 GrabPtr
3937 CheckPassiveGrabsOnWindow(
3938     WindowPtr pWin,
3939     DeviceIntPtr device,
3940     InternalEvent *event,
3941     BOOL checkCore,
3942     BOOL activate)
3944     GrabPtr grab = wPassiveGrabs(pWin);
3945     GrabPtr tempGrab;
3947     if (!grab)
3948         return NULL;
3950     tempGrab = AllocGrab();
3952     /* Fill out the grab details, but leave the type for later before
3953      * comparing */
3954     switch (event->any.type)
3955     {
3956         case ET_KeyPress:
3957         case ET_KeyRelease:
3958             tempGrab->detail.exact = event->device_event.detail.key;
3959             break;
3960         case ET_ButtonPress:
3961         case ET_ButtonRelease:
3962         case ET_TouchBegin:
3963         case ET_TouchEnd:
3964             tempGrab->detail.exact = event->device_event.detail.button;
3965             break;
3966         default:
3967             tempGrab->detail.exact = 0;
3968             break;
3969     }
3970     tempGrab->window = pWin;
3971     tempGrab->device = device;
3972     tempGrab->detail.pMask = NULL;
3973     tempGrab->modifiersDetail.pMask = NULL;
3974     tempGrab->next = NULL;
3976     for (; grab; grab = grab->next)
3977     {
3978         if (!CheckPassiveGrab(device, grab, event, checkCore, tempGrab))
3979             continue;
3981         if (activate && !ActivatePassiveGrab(device, grab, event, event))
3982             continue;
3984         break;
3985     }
3987     FreeGrab(tempGrab);
3988     return grab;
3991 /**
3992  * CheckDeviceGrabs handles both keyboard and pointer events that may cause
3993  * a passive grab to be activated.
3994  *
3995  * If the event is a keyboard event, the ancestors of the focus window are
3996  * traced down and tried to see if they have any passive grabs to be
3997  * activated.  If the focus window itself is reached and it's descendants
3998  * contain the pointer, the ancestors of the window that the pointer is in
3999  * are then traced down starting at the focus window, otherwise no grabs are
4000  * activated.
4001  * If the event is a pointer event, the ancestors of the window that the
4002  * pointer is in are traced down starting at the root until CheckPassiveGrabs
4003  * causes a passive grab to activate or all the windows are
4004  * tried. PRH
4005  *
4006  * If a grab is activated, the event has been sent to the client already!
4007  *
4008  * The event we pass in must always be an XI event. From this, we then emulate
4009  * the core event and then check for grabs.
4010  *
4011  * @param device The device that caused the event.
4012  * @param xE The event to handle (Device{Button|Key}Press).
4013  * @param count Number of events in list.
4014  * @return TRUE if a grab has been activated or false otherwise.
4015 */
4017 Bool
4018 CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor)
4020     int i;
4021     WindowPtr pWin = NULL;
4022     FocusClassPtr focus = IsPointerEvent((InternalEvent*)event) ? NULL : device->focus;
4023     BOOL sendCore = (IsMaster(device) && device->coreEvents);
4024     Bool ret = FALSE;
4026     if (event->type != ET_ButtonPress &&
4027         event->type != ET_KeyPress)
4028         return FALSE;
4030     if (event->type == ET_ButtonPress
4031         && (device->button->buttonsDown != 1))
4032         return FALSE;
4034     if (device->deviceGrab.grab)
4035         return FALSE;
4037     i = 0;
4038     if (ancestor)
4039     {
4040         while (i < device->spriteInfo->sprite->spriteTraceGood)
4041             if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor)
4042                 break;
4043         if (i == device->spriteInfo->sprite->spriteTraceGood)
4044             goto out;
4045     }
4047     if (focus)
4048     {
4049         for (; i < focus->traceGood; i++)
4050         {
4051             pWin = focus->trace[i];
4052             if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event,
4053                                           sendCore, TRUE))
4054             {
4055                 ret = TRUE;
4056                 goto out;
4057             }
4058         }
4060         if ((focus->win == NoneWin) ||
4061             (i >= device->spriteInfo->sprite->spriteTraceGood) ||
4062             (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i-1]))
4063             goto out;
4064     }
4066     for (; i < device->spriteInfo->sprite->spriteTraceGood; i++)
4067     {
4068         pWin = device->spriteInfo->sprite->spriteTrace[i];
4069         if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event,
4070                                       sendCore, TRUE))
4071         {
4072             ret = TRUE;
4073             goto out;
4074         }
4075     }
4077 out:
4078     if (ret == TRUE && event->type == ET_KeyPress)
4079         device->deviceGrab.activatingKey = event->detail.key;
4080     return ret;
4083 /**
4084  * Called for keyboard events to deliver event to whatever client owns the
4085  * focus.
4086  *
4087  * The event is delivered to the keyboard's focus window, the root window or
4088  * to the window owning the input focus.
4089  *
4090  * @param keybd The keyboard originating the event.
4091  * @param event The event, not yet in wire format.
4092  * @param window Window underneath the sprite.
4093  */
4094 void
4095 DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
4097     DeviceIntPtr ptr;
4098     WindowPtr focus = keybd->focus->win;
4099     BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents);
4100     xEvent *core = NULL, *xE = NULL, *xi2 = NULL;
4101     int count, rc;
4102     int deliveries = 0;
4104     if (focus == FollowKeyboardWin)
4105         focus = inputInfo.keyboard->focus->win;
4106     if (!focus)
4107         return;
4108     if (focus == PointerRootWin)
4109     {
4110         DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd);
4111         return;
4112     }
4113     if ((focus == window) || IsParent(focus, window))
4114     {
4115         if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd))
4116             return;
4117     }
4119     /* just deliver it to the focus window */
4120     ptr = GetMaster(keybd, POINTER_OR_FLOAT);
4122     rc = EventToXI2(event, &xi2);
4123     if (rc == Success)
4124     {
4125         /* XXX: XACE */
4126         int filter = GetEventFilter(keybd, xi2);
4127         FixUpEventFromWindow(ptr->spriteInfo->sprite, xi2, focus, None, FALSE);
4128         deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1,
4129                                            filter, NullGrab);
4130         if (deliveries > 0)
4131             goto unwind;
4132     } else if (rc != BadMatch)
4133         ErrorF("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n",
4134                keybd->name, event->any.type, rc);
4136     rc = EventToXI(event, &xE, &count);
4137     if (rc == Success &&
4138         XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success)
4139     {
4140         FixUpEventFromWindow(ptr->spriteInfo->sprite, xE, focus, None, FALSE);
4141         deliveries = DeliverEventsToWindow(keybd, focus, xE, count,
4142                 GetEventFilter(keybd, xE),
4143                 NullGrab);
4145         if (deliveries > 0)
4146             goto unwind;
4147     } else if (rc != BadMatch)
4148         ErrorF("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n",
4149                keybd->name, event->any.type, rc);
4151     if (sendCore)
4152     {
4153         rc = EventToCore(event, &core, &count);
4154         if (rc == Success) {
4155             if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, core, count) == Success) {
4156                 FixUpEventFromWindow(keybd->spriteInfo->sprite, core, focus,
4157                                      None, FALSE);
4158                 deliveries = DeliverEventsToWindow(keybd, focus, core, count,
4159                                                    GetEventFilter(keybd, core),
4160                                                    NullGrab);
4161             }
4162         } else if (rc != BadMatch)
4163             ErrorF("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n",
4164                     keybd->name, event->any.type, rc);
4165     }
4167 unwind:
4168     free(core);
4169     free(xE);
4170     free(xi2);
4171     return;
4175 int
4176 DeliverOneGrabbedEvent(InternalEvent *event, DeviceIntPtr dev, enum InputLevel level)
4178     SpritePtr pSprite = dev->spriteInfo->sprite;
4179     int rc;
4180     xEvent *xE = NULL;
4181     int count = 0;
4182     int deliveries = 0;
4183     Mask mask;
4184     GrabInfoPtr grabinfo = &dev->deviceGrab;
4185     GrabPtr grab = grabinfo->grab;
4186     Mask filter;
4188     switch(level)
4189     {
4190         case XI2:
4191             rc = EventToXI2(event, &xE);
4192             count = 1;
4193             if (rc == Success)
4194             {
4195                 int evtype = xi2_get_type(xE);
4196                 mask = GetXI2MaskByte(grab->xi2mask, dev, evtype);
4197                 filter = GetEventFilter(dev, xE);
4198             }
4199             break;
4200         case XI:
4201             if (grabinfo->fromPassiveGrab && grabinfo->implicitGrab)
4202                 mask = grab->deviceMask;
4203             else
4204                 mask = grab->eventMask;
4205             rc = EventToXI(event, &xE, &count);
4206             if (rc == Success)
4207                 filter = GetEventFilter(dev, xE);
4208             break;
4209         case CORE:
4210             rc = EventToCore(event, &xE, &count);
4211             mask = grab->eventMask;
4212             if (rc == Success)
4213                 filter = GetEventFilter(dev, xE);
4214             break;
4215         default:
4216             BUG_WARN_MSG(1, "Invalid input level %d\n", level);
4217             return 0;
4218     }
4220     if (rc == Success)
4221     {
4222         FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
4223         if (XaceHook(XACE_SEND_ACCESS, 0, dev,
4224                     grab->window, xE, count) ||
4225                 XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
4226                     grab->window, xE, count))
4227             deliveries = 1; /* don't send, but pretend we did */
4228         else if (level != CORE || !IsInterferingGrab(rClient(grab), dev, xE))
4229         {
4230             deliveries = TryClientEvents(rClient(grab), dev,
4231                     xE, count, mask, filter,
4232                     grab);
4233         }
4234     } else
4235         BUG_WARN_MSG(rc != BadMatch, "%s: conversion to mode %d failed on %d with %d\n",
4236                 dev->name, level, event->any.type, rc);
4238     free(xE);
4239     return deliveries;
4243 /**
4244  * Deliver an event from a device that is currently grabbed. Uses
4245  * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the
4246  * grab. If not, TryClientEvents() is used.
4247  *
4248  * @param deactivateGrab True if the device's grab should be deactivated.
4249  *
4250  * @return The number of events delivered.
4251  */
4252 int
4253 DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
4254                     Bool deactivateGrab)
4256     GrabPtr grab;
4257     GrabInfoPtr grabinfo;
4258     int deliveries = 0;
4259     DeviceIntPtr dev;
4260     SpritePtr pSprite = thisDev->spriteInfo->sprite;
4261     BOOL sendCore = FALSE;
4263     grabinfo = &thisDev->deviceGrab;
4264     grab = grabinfo->grab;
4266     if (grab->ownerEvents)
4267     {
4268         WindowPtr focus;
4269         WindowPtr win;
4271         /* Hack: Some pointer device have a focus class. So we need to check
4272          * for the type of event, to see if we really want to deliver it to
4273          * the focus window. For pointer events, the answer is no.
4274          */
4275         if (IsPointerEvent(event))
4276             focus = PointerRootWin;
4277         else if (thisDev->focus)
4278         {
4279             focus = thisDev->focus->win;
4280             if (focus == FollowKeyboardWin)
4281                 focus = inputInfo.keyboard->focus->win;
4282         }
4283         else
4284             focus = PointerRootWin;
4285         if (focus == PointerRootWin)
4286         {
4287             win = pSprite->win;
4288             focus = NullWindow;
4289         } else if (focus && (focus == pSprite->win ||
4290                     IsParent(focus, pSprite->win)))
4291             win = pSprite->win;
4292         else if (focus)
4293             win = focus;
4295         deliveries = DeliverDeviceEvents(win, event, grab, focus, thisDev);
4296     }
4297     if (!deliveries)
4298     {
4299         /* XXX: In theory, we could pass the internal events through to
4300          * everything and only convert just before hitting the wire. We can't
4301          * do that yet, so DGE is the last stop for internal events. From here
4302          * onwards, we deal with core/XI events.
4303          */
4305         sendCore = (IsMaster(thisDev) && thisDev->coreEvents);
4306         /* try core event */
4307         if (sendCore && grab->grabtype == CORE)
4308         {
4309             deliveries = DeliverOneGrabbedEvent(event, thisDev, CORE);
4310         }
4312         if (!deliveries)
4313         {
4314             deliveries = DeliverOneGrabbedEvent(event, thisDev, XI2);
4315         }
4317         if (!deliveries)
4318         {
4319             deliveries = DeliverOneGrabbedEvent(event, thisDev, XI);
4320         }
4322         if (deliveries && (event->any.type == ET_Motion))
4323             thisDev->valuator->motionHintWindow = grab->window;
4324     }
4325     if (deliveries && !deactivateGrab && event->any.type != ET_Motion)
4326     {
4327         switch (grabinfo->sync.state)
4328         {
4329         case FREEZE_BOTH_NEXT_EVENT:
4330             dev = GetPairedDevice(thisDev);
4331             if (dev)
4332             {
4333                 FreezeThaw(dev, TRUE);
4334                 if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) &&
4335                     (CLIENT_BITS(grab->resource) ==
4336                      CLIENT_BITS(dev->deviceGrab.grab->resource)))
4337                     dev->deviceGrab.sync.state = FROZEN_NO_EVENT;
4338                 else
4339                     dev->deviceGrab.sync.other = grab;
4340             }
4341             /* fall through */
4342         case FREEZE_NEXT_EVENT:
4343             grabinfo->sync.state = FROZEN_WITH_EVENT;
4344             FreezeThaw(thisDev, TRUE);
4345             *grabinfo->sync.event = event->device_event;
4346             break;
4347         }
4348     }
4350     return deliveries;
4353 /* This function is used to set the key pressed or key released state -
4354    this is only used when the pressing of keys does not cause
4355    the device's processInputProc to be called, as in for example Mouse Keys.
4356 */
4357 void
4358 FixKeyState (DeviceEvent *event, DeviceIntPtr keybd)
4360     int key = event->detail.key;
4362     if (event->type == ET_KeyPress) {
4363         DebugF("FixKeyState: Key %d %s\n",key,
4364                ((event->type == ET_KeyPress) ? "down" : "up"));
4365     }
4367     if (event->type == ET_KeyPress)
4368         set_key_down(keybd, key, KEY_PROCESSED);
4369     else if (event->type == ET_KeyRelease)
4370         set_key_up(keybd, key, KEY_PROCESSED);
4371     else
4372         FatalError("Impossible keyboard event");
4375 #define AtMostOneClient \
4376         (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
4377 #define ManagerMask \
4378         (SubstructureRedirectMask | ResizeRedirectMask)
4380 /**
4381  * Recalculate which events may be deliverable for the given window.
4382  * Recalculated mask is used for quicker determination which events may be
4383  * delivered to a window.
4384  *
4385  * The otherEventMasks on a WindowOptional is the combination of all event
4386  * masks set by all clients on the window.
4387  * deliverableEventMask is the combination of the eventMask and the
4388  * otherEventMask plus the events that may be propagated to the parent.
4389  *
4390  * Traverses to siblings and parents of the window.
4391  */
4392 void
4393 RecalculateDeliverableEvents(WindowPtr pWin)
4395     OtherClients *others;
4396     WindowPtr pChild;
4398     pChild = pWin;
4399     while (1)
4400     {
4401         if (pChild->optional)
4402         {
4403             pChild->optional->otherEventMasks = 0;
4404             for (others = wOtherClients(pChild); others; others = others->next)
4405             {
4406                 pChild->optional->otherEventMasks |= others->mask;
4407             }
4408         }
4409         pChild->deliverableEvents = pChild->eventMask|
4410                                     wOtherEventMasks(pChild);
4411         if (pChild->parent)
4412             pChild->deliverableEvents |=
4413                 (pChild->parent->deliverableEvents &
4414                  ~wDontPropagateMask(pChild) & PropagateMask);
4415         if (pChild->firstChild)
4416         {
4417             pChild = pChild->firstChild;
4418             continue;
4419         }
4420         while (!pChild->nextSib && (pChild != pWin))
4421             pChild = pChild->parent;
4422         if (pChild == pWin)
4423             break;
4424         pChild = pChild->nextSib;
4425     }
4428 /**
4429  *
4430  *  \param value must conform to DeleteType
4431  */
4432 int
4433 OtherClientGone(pointer value, XID id)
4435     OtherClientsPtr other, prev;
4436     WindowPtr pWin = (WindowPtr)value;
4438     prev = 0;
4439     for (other = wOtherClients(pWin); other; other = other->next)
4440     {
4441         if (other->resource == id)
4442         {
4443             if (prev)
4444                 prev->next = other->next;
4445             else
4446             {
4447                 if (!(pWin->optional->otherClients = other->next))
4448                     CheckWindowOptionalNeed (pWin);
4449             }
4450             free(other);
4451             RecalculateDeliverableEvents(pWin);
4452             return Success;
4453         }
4454         prev = other;
4455     }
4456     FatalError("client not on event list");
4457     /*NOTREACHED*/
4458     return -1; /* make compiler happy */
4461 int
4462 EventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
4464     Mask check;
4465     OtherClients * others;
4466     DeviceIntPtr dev;
4467     int rc;
4469     if (mask & ~AllEventMasks)
4470     {
4471         client->errorValue = mask;
4472         return BadValue;
4473     }
4474     check = (mask & ManagerMask);
4475     if (check) {
4476         rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id,
4477                       RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess);
4478         if (rc != Success)
4479             return rc;
4480     }
4481     check = (mask & AtMostOneClient);
4482     if (check & (pWin->eventMask|wOtherEventMasks(pWin)))
4483     {                                  /* It is illegal for two different
4484                                           clients to select on any of the
4485                                           events for AtMostOneClient. However,
4486                                           it is OK, for some client to
4487                                           continue selecting on one of those
4488                                           events.  */
4489         if ((wClient(pWin) != client) && (check & pWin->eventMask))
4490             return BadAccess;
4491         for (others = wOtherClients (pWin); others; others = others->next)
4492         {
4493             if (!SameClient(others, client) && (check & others->mask))
4494                 return BadAccess;
4495         }
4496     }
4497     if (wClient (pWin) == client)
4498     {
4499         check = pWin->eventMask;
4500         pWin->eventMask = mask;
4501     }
4502     else
4503     {
4504         for (others = wOtherClients (pWin); others; others = others->next)
4505         {
4506             if (SameClient(others, client))
4507             {
4508                 check = others->mask;
4509                 if (mask == 0)
4510                 {
4511                     FreeResource(others->resource, RT_NONE);
4512                     return Success;
4513                 }
4514                 else
4515                     others->mask = mask;
4516                 goto maskSet;
4517             }
4518         }
4519         check = 0;
4520         if (!pWin->optional && !MakeWindowOptional (pWin))
4521             return BadAlloc;
4522         others = malloc(sizeof(OtherClients));
4523         if (!others)
4524             return BadAlloc;
4525         others->mask = mask;
4526         others->resource = FakeClientID(client->index);
4527         others->next = pWin->optional->otherClients;
4528         pWin->optional->otherClients = others;
4529         if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin))
4530             return BadAlloc;
4531     }
4532 maskSet:
4533     if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask))
4534     {
4535         for (dev = inputInfo.devices; dev; dev = dev->next)
4536         {
4537             if (dev->valuator && dev->valuator->motionHintWindow == pWin)
4538                 dev->valuator->motionHintWindow = NullWindow;
4539         }
4540     }
4541     RecalculateDeliverableEvents(pWin);
4542     return Success;
4545 int
4546 EventSuppressForWindow(WindowPtr pWin, ClientPtr client,
4547                        Mask mask, Bool *checkOptional)
4549     int i, free;
4551     if (mask & ~PropagateMask)
4552     {
4553         client->errorValue = mask;
4554         return BadValue;
4555     }
4556     if (pWin->dontPropagate)
4557         DontPropagateRefCnts[pWin->dontPropagate]--;
4558     if (!mask)
4559         i = 0;
4560     else
4561     {
4562         for (i = DNPMCOUNT, free = 0; --i > 0; )
4563         {
4564             if (!DontPropagateRefCnts[i])
4565                 free = i;
4566             else if (mask == DontPropagateMasks[i])
4567                 break;
4568         }
4569         if (!i && free)
4570         {
4571             i = free;
4572             DontPropagateMasks[i] = mask;
4573         }
4574     }
4575     if (i || !mask)
4576     {
4577         pWin->dontPropagate = i;
4578         if (i)
4579             DontPropagateRefCnts[i]++;
4580         if (pWin->optional)
4581         {
4582             pWin->optional->dontPropagateMask = mask;
4583             *checkOptional = TRUE;
4584         }
4585     }
4586     else
4587     {
4588         if (!pWin->optional && !MakeWindowOptional (pWin))
4589         {
4590             if (pWin->dontPropagate)
4591                 DontPropagateRefCnts[pWin->dontPropagate]++;
4592             return BadAlloc;
4593         }
4594         pWin->dontPropagate = 0;
4595         pWin->optional->dontPropagateMask = mask;
4596     }
4597     RecalculateDeliverableEvents(pWin);
4598     return Success;
4601 /**
4602  * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
4603  * Uses the paired keyboard to get some additional information.
4604  */
4605 void
4606 CoreEnterLeaveEvent(
4607     DeviceIntPtr mouse,
4608     int type,
4609     int mode,
4610     int detail,
4611     WindowPtr pWin,
4612     Window child)
4614     xEvent              event;
4615     WindowPtr           focus;
4616     DeviceIntPtr        keybd;
4617     GrabPtr             grab = mouse->deviceGrab.grab;
4618     Mask                mask;
4620     keybd = GetMaster(mouse, KEYBOARD_OR_FLOAT);
4622     if ((pWin == mouse->valuator->motionHintWindow) &&
4623         (detail != NotifyInferior))
4624         mouse->valuator->motionHintWindow = NullWindow;
4625     if (grab)
4626     {
4627         mask = (pWin == grab->window) ? grab->eventMask : 0;
4628         if (grab->ownerEvents)
4629             mask |= EventMaskForClient(pWin, rClient(grab));
4630     }
4631     else
4632     {
4633         mask = pWin->eventMask | wOtherEventMasks(pWin);
4634     }
4636     memset(&event, 0, sizeof(xEvent));
4637     event.u.u.type = type;
4638     event.u.u.detail = detail;
4639     event.u.enterLeave.time = currentTime.milliseconds;
4640     event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x;
4641     event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y;
4642     /* Counts on the same initial structure of crossing & button events! */
4643     FixUpEventFromWindow(mouse->spriteInfo->sprite, &event, pWin, None, FALSE);
4644     /* Enter/Leave events always set child */
4645     event.u.enterLeave.child = child;
4646     event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
4647         ELFlagSameScreen : 0;
4648     event.u.enterLeave.state = mouse->button ? (mouse->button->state & 0x1f00) : 0;
4649     if (keybd)
4650         event.u.enterLeave.state |=
4651                 XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
4652     event.u.enterLeave.mode = mode;
4653     focus = (keybd) ? keybd->focus->win : None;
4654     if ((focus != NoneWin) &&
4655             ((pWin == focus) || (focus == PointerRootWin) ||
4656              IsParent(focus, pWin)))
4657         event.u.enterLeave.flags |= ELFlagFocus;
4659     if ((mask & GetEventFilter(mouse, &event)))
4660     {
4661         if (grab)
4662             TryClientEvents(rClient(grab), mouse, &event, 1, mask,
4663                             GetEventFilter(mouse, &event), grab);
4664         else
4665             DeliverEventsToWindow(mouse, pWin, &event, 1,
4666                                   GetEventFilter(mouse, &event),
4667                                   NullGrab);
4668     }
4670     if ((type == EnterNotify) && (mask & KeymapStateMask))
4671     {
4672         xKeymapEvent ke;
4673         ClientPtr client = grab ? rClient(grab) : wClient(pWin);
4674         if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess))
4675             memset((char *)&ke.map[0], 0, 31);
4676         else
4677             memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31);
4679         ke.type = KeymapNotify;
4680         if (grab)
4681             TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1,
4682                             mask, KeymapStateMask, grab);
4683         else
4684             DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1,
4685                                   KeymapStateMask, NullGrab);
4686     }
4689 void
4690 DeviceEnterLeaveEvent(
4691     DeviceIntPtr mouse,
4692     int sourceid,
4693     int type,
4694     int mode,
4695     int detail,
4696     WindowPtr pWin,
4697     Window child)
4699     GrabPtr             grab = mouse->deviceGrab.grab;
4700     xXIEnterEvent       *event;
4701     int                 filter;
4702     int                 btlen, len, i;
4703     DeviceIntPtr        kbd;
4705     if ((mode == XINotifyPassiveGrab && type == XI_Leave) ||
4706         (mode == XINotifyPassiveUngrab && type == XI_Enter))
4707         return;
4709     btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
4710     btlen = bytes_to_int32(btlen);
4711     len = sizeof(xXIEnterEvent) + btlen * 4;
4713     event = calloc(1, len);
4714     event->type         = GenericEvent;
4715     event->extension    = IReqCode;
4716     event->evtype       = type;
4717     event->length       = (len - sizeof(xEvent))/4;
4718     event->buttons_len  = btlen;
4719     event->detail       = detail;
4720     event->time         = currentTime.milliseconds;
4721     event->deviceid     = mouse->id;
4722     event->sourceid     = sourceid;
4723     event->mode         = mode;
4724     event->root_x       = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
4725     event->root_y       = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
4727     for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
4728         if (BitIsOn(mouse->button->down, i))
4729             SetBit(&event[1], i);
4731     kbd = GetMaster(mouse, MASTER_KEYBOARD);
4732     if (kbd && kbd->key)
4733     {
4734         event->mods.base_mods = kbd->key->xkbInfo->state.base_mods;
4735         event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods;
4736         event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods;
4738         event->group.base_group = kbd->key->xkbInfo->state.base_group;
4739         event->group.latched_group = kbd->key->xkbInfo->state.latched_group;
4740         event->group.locked_group = kbd->key->xkbInfo->state.locked_group;
4741     }
4743     FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent*)event, pWin,
4744                          None, FALSE);
4746     filter = GetEventFilter(mouse, (xEvent*)event);
4748     if (grab)
4749     {
4750         Mask mask;
4751         mask = xi2mask_isset(grab->xi2mask, mouse, type);
4752         TryClientEvents(rClient(grab), mouse, (xEvent*)event, 1, mask, 1, grab);
4753     } else {
4754         if (!WindowXI2MaskIsset(mouse, pWin, (xEvent*)event))
4755             goto out;
4756         DeliverEventsToWindow(mouse, pWin, (xEvent*)event, 1, filter,
4757                               NullGrab);
4758     }
4760 out:
4761     free(event);
4764 void
4765 CoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
4767     xEvent event;
4769     memset(&event, 0, sizeof(xEvent));
4770     event.u.focus.mode = mode;
4771     event.u.u.type = type;
4772     event.u.u.detail = detail;
4773     event.u.focus.window = pWin->drawable.id;
4775     DeliverEventsToWindow(dev, pWin, &event, 1,
4776                           GetEventFilter(dev, &event), NullGrab);
4777     if ((type == FocusIn) &&
4778             ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
4779     {
4780         xKeymapEvent ke;
4781         ClientPtr client = wClient(pWin);
4782         if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess))
4783             memset((char *)&ke.map[0], 0, 31);
4784         else
4785             memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
4787         ke.type = KeymapNotify;
4788         DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1,
4789                 KeymapStateMask, NullGrab);
4790     }
4793 /**
4794  * Set the input focus to the given window. Subsequent keyboard events will be
4795  * delivered to the given window.
4796  *
4797  * Usually called from ProcSetInputFocus as result of a client request. If so,
4798  * the device is the inputInfo.keyboard.
4799  * If called from ProcXSetInputFocus as result of a client xinput request, the
4800  * device is set to the device specified by the client.
4801  *
4802  * @param client Client that requested input focus change.
4803  * @param dev Focus device.
4804  * @param focusID The window to obtain the focus. Can be PointerRoot or None.
4805  * @param revertTo Specifies where the focus reverts to when window becomes
4806  * unviewable.
4807  * @param ctime Specifies the time.
4808  * @param followOK True if pointer is allowed to follow the keyboard.
4809  */
4810 int
4811 SetInputFocus(
4812     ClientPtr client,
4813     DeviceIntPtr dev,
4814     Window focusID,
4815     CARD8 revertTo,
4816     Time ctime,
4817     Bool followOK)
4819     FocusClassPtr focus;
4820     WindowPtr focusWin;
4821     int mode, rc;
4822     TimeStamp time;
4823     DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */
4826     UpdateCurrentTime();
4827     if ((revertTo != RevertToParent) &&
4828         (revertTo != RevertToPointerRoot) &&
4829         (revertTo != RevertToNone) &&
4830         ((revertTo != RevertToFollowKeyboard) || !followOK))
4831     {
4832         client->errorValue = revertTo;
4833         return BadValue;
4834     }
4835     time = ClientTimeToServerTime(ctime);
4837     keybd = GetMaster(dev, KEYBOARD_OR_FLOAT);
4839     if ((focusID == None) || (focusID == PointerRoot))
4840         focusWin = (WindowPtr)(long)focusID;
4841     else if ((focusID == FollowKeyboard) && followOK)
4842     {
4843         focusWin = keybd->focus->win;
4844     }
4845     else {
4846         rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess);
4847         if (rc != Success)
4848             return rc;
4849         /* It is a match error to try to set the input focus to an
4850         unviewable window. */
4851         if(!focusWin->realized)
4852             return BadMatch;
4853     }
4854     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess);
4855     if (rc != Success)
4856         return Success;
4858     focus = dev->focus;
4859     if ((CompareTimeStamps(time, currentTime) == LATER) ||
4860         (CompareTimeStamps(time, focus->time) == EARLIER))
4861         return Success;
4862     mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal;
4863     if (focus->win == FollowKeyboardWin)
4864     {
4865         if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin))
4866             DoFocusEvents(dev, keybd->focus->win, focusWin, mode);
4867     } else
4868     {
4869         if (!ActivateFocusInGrab(dev, focus->win, focusWin))
4870             DoFocusEvents(dev, focus->win, focusWin, mode);
4871     }
4872     focus->time = time;
4873     focus->revert = revertTo;
4874     if (focusID == FollowKeyboard)
4875         focus->win = FollowKeyboardWin;
4876     else
4877         focus->win = focusWin;
4878     if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
4879         focus->traceGood = 0;
4880     else
4881     {
4882         int depth = 0;
4883         WindowPtr pWin;
4885         for (pWin = focusWin; pWin; pWin = pWin->parent) depth++;
4886         if (depth > focus->traceSize)
4887         {
4888             focus->traceSize = depth+1;
4889             focus->trace = realloc(focus->trace,
4890                                     focus->traceSize * sizeof(WindowPtr));
4891         }
4892         focus->traceGood = depth;
4893         for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
4894             focus->trace[depth] = pWin;
4895     }
4896     return Success;
4899 /**
4900  * Server-side protocol handling for SetInputFocus request.
4901  *
4902  * Sets the input focus for the virtual core keyboard.
4903  */
4904 int
4905 ProcSetInputFocus(ClientPtr client)
4907     DeviceIntPtr kbd = PickKeyboard(client);
4908     REQUEST(xSetInputFocusReq);
4910     REQUEST_SIZE_MATCH(xSetInputFocusReq);
4912     return SetInputFocus(client, kbd, stuff->focus,
4913                          stuff->revertTo, stuff->time, FALSE);
4916 /**
4917  * Server-side protocol handling for GetInputFocus request.
4918  *
4919  * Sends the current input focus for the client's keyboard back to the
4920  * client.
4921  */
4922 int
4923 ProcGetInputFocus(ClientPtr client)
4925     DeviceIntPtr kbd = PickKeyboard(client);
4926     xGetInputFocusReply rep;
4927     FocusClassPtr focus = kbd->focus;
4928     int rc;
4929     /* REQUEST(xReq); */
4930     REQUEST_SIZE_MATCH(xReq);
4932     rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess);
4933     if (rc != Success)
4934         return rc;
4936     memset(&rep, 0, sizeof(xGetInputFocusReply));
4937     rep.type = X_Reply;
4938     rep.length = 0;
4939     rep.sequenceNumber = client->sequence;
4940     if (focus->win == NoneWin)
4941         rep.focus = None;
4942     else if (focus->win == PointerRootWin)
4943         rep.focus = PointerRoot;
4944     else rep.focus = focus->win->drawable.id;
4945     rep.revertTo = focus->revert;
4946     WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
4947     return Success;
4950 /**
4951  * Server-side protocol handling for GrabPointer request.
4952  *
4953  * Sets an active grab on the client's ClientPointer and returns success
4954  * status to client.
4955  */
4956 int
4957 ProcGrabPointer(ClientPtr client)
4959     xGrabPointerReply rep;
4960     DeviceIntPtr device = PickPointer(client);
4961     GrabPtr grab;
4962     GrabMask mask;
4963     WindowPtr confineTo;
4964     CursorPtr oldCursor;
4965     REQUEST(xGrabPointerReq);
4966     int rc;
4968     REQUEST_SIZE_MATCH(xGrabPointerReq);
4969     UpdateCurrentTime();
4971     if (stuff->eventMask & ~PointerGrabMask)
4972     {
4973         client->errorValue = stuff->eventMask;
4974         return BadValue;
4975     }
4977     if (stuff->confineTo == None)
4978         confineTo = NullWindow;
4979     else
4980     {
4981         rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
4982                              DixSetAttrAccess);
4983         if (rc != Success)
4984             return rc;
4985     }
4987     memset(&rep, 0, sizeof(xGrabPointerReply));
4988     oldCursor = NullCursor;
4989     grab = device->deviceGrab.grab;
4991     if (grab)
4992     {
4993         if (grab->confineTo && !confineTo)
4994             ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE,
4995                                   FALSE);
4996         oldCursor = grab->cursor;
4997     }
4999     mask.core = stuff->eventMask;
5001     rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode,
5002                     stuff->grabWindow, stuff->ownerEvents, stuff->time,
5003                     &mask, CORE, stuff->cursor,
5004                     stuff->confineTo, &rep.status);
5005     if (rc != Success)
5006         return rc;
5008     if (oldCursor && rep.status == GrabSuccess)
5009         FreeCursor (oldCursor, (Cursor)0);
5011     rep.type = X_Reply;
5012     rep.sequenceNumber = client->sequence;
5013     rep.length = 0;
5014     WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
5015     return Success;
5018 /**
5019  * Server-side protocol handling for ChangeActivePointerGrab request.
5020  *
5021  * Changes properties of the grab hold by the client. If the client does not
5022  * hold an active grab on the device, nothing happens.
5023  */
5024 int
5025 ProcChangeActivePointerGrab(ClientPtr client)
5027     DeviceIntPtr device;
5028     GrabPtr      grab;
5029     CursorPtr newCursor, oldCursor;
5030     REQUEST(xChangeActivePointerGrabReq);
5031     TimeStamp time;
5033     REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
5034     if (stuff->eventMask & ~PointerGrabMask)
5035     {
5036         client->errorValue = stuff->eventMask;
5037         return BadValue;
5038     }
5039     if (stuff->cursor == None)
5040         newCursor = NullCursor;
5041     else
5042     {
5043         int rc = dixLookupResourceByType((pointer *)&newCursor, stuff->cursor,
5044                                          RT_CURSOR, client, DixUseAccess);
5045         if (rc != Success)
5046         {
5047             client->errorValue = stuff->cursor;
5048             return rc;
5049         }
5050     }
5052     device = PickPointer(client);
5053     grab = device->deviceGrab.grab;
5055     if (!grab)
5056         return Success;
5057     if (!SameClient(grab, client))
5058         return Success;
5059     time = ClientTimeToServerTime(stuff->time);
5060     if ((CompareTimeStamps(time, currentTime) == LATER) ||
5061              (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
5062         return Success;
5063     oldCursor = grab->cursor;
5064     grab->cursor = newCursor;
5065     if (newCursor)
5066         newCursor->refcnt++;
5067     PostNewCursor(device);
5068     if (oldCursor)
5069         FreeCursor(oldCursor, (Cursor)0);
5070     grab->eventMask = stuff->eventMask;
5071     return Success;
5074 /**
5075  * Server-side protocol handling for UngrabPointer request.
5076  *
5077  * Deletes a pointer grab on a device the client has grabbed.
5078  */
5079 int
5080 ProcUngrabPointer(ClientPtr client)
5082     DeviceIntPtr device = PickPointer(client);
5083     GrabPtr grab;
5084     TimeStamp time;
5085     REQUEST(xResourceReq);
5087     REQUEST_SIZE_MATCH(xResourceReq);
5088     UpdateCurrentTime();
5089     grab = device->deviceGrab.grab;
5091     time = ClientTimeToServerTime(stuff->id);
5092     if ((CompareTimeStamps(time, currentTime) != LATER) &&
5093             (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
5094             (grab) && SameClient(grab, client))
5095         (*device->deviceGrab.DeactivateGrab)(device);
5096     return Success;
5099 /**
5100  * Sets a grab on the given device.
5101  *
5102  * Called from ProcGrabKeyboard to work on the client's keyboard.
5103  * Called from ProcXGrabDevice to work on the device specified by the client.
5104  *
5105  * The parameters this_mode and other_mode represent the keyboard_mode and
5106  * pointer_mode parameters of XGrabKeyboard().
5107  * See man page for details on all the parameters
5108  *
5109  * @param client Client that owns the grab.
5110  * @param dev The device to grab.
5111  * @param this_mode GrabModeSync or GrabModeAsync
5112  * @param other_mode GrabModeSync or GrabModeAsync
5113  * @param status Return code to be returned to the caller.
5114  *
5115  * @returns Success or BadValue.
5116  */
5117 int
5118 GrabDevice(ClientPtr client, DeviceIntPtr dev,
5119            unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow,
5120            unsigned ownerEvents, Time ctime, GrabMask *mask,
5121            int grabtype, Cursor curs, Window confineToWin, CARD8 *status)
5123     WindowPtr pWin, confineTo;
5124     GrabPtr grab;
5125     TimeStamp time;
5126     Mask access_mode = DixGrabAccess;
5127     int rc;
5128     GrabInfoPtr grabInfo = &dev->deviceGrab;
5129     CursorPtr cursor;
5131     UpdateCurrentTime();
5132     if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync))
5133     {
5134         client->errorValue = keyboard_mode;
5135         return BadValue;
5136     }
5137     if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync))
5138     {
5139         client->errorValue = pointer_mode;
5140         return BadValue;
5141     }
5142     if ((ownerEvents != xFalse) && (ownerEvents != xTrue))
5143     {
5144         client->errorValue = ownerEvents;
5145         return BadValue;
5146     }
5148     rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
5149     if (rc != Success)
5150         return rc;
5152     if (confineToWin == None)
5153         confineTo = NullWindow;
5154     else
5155     {
5156         rc = dixLookupWindow(&confineTo, confineToWin, client,
5157                              DixSetAttrAccess);
5158         if (rc != Success)
5159             return rc;
5160     }
5162     if (curs == None)
5163         cursor = NullCursor;
5164     else
5165     {
5166         rc = dixLookupResourceByType((pointer *)&cursor, curs, RT_CURSOR,
5167                                client, DixUseAccess);
5168         if (rc != Success)
5169         {
5170             client->errorValue = curs;
5171             return rc;
5172         }
5173         access_mode |= DixForceAccess;
5174     }
5176     if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync)
5177         access_mode |= DixFreezeAccess;
5178     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
5179     if (rc != Success)
5180         return rc;
5182     time = ClientTimeToServerTime(ctime);
5183     grab = grabInfo->grab;
5184     if (grab && grab->grabtype != grabtype)
5185         *status = AlreadyGrabbed;
5186     if (grab && !SameClient(grab, client))
5187         *status = AlreadyGrabbed;
5188     else if ((!pWin->realized) ||
5189              (confineTo &&
5190                 !(confineTo->realized
5191                     && BorderSizeNotEmpty(dev, confineTo))))
5192         *status = GrabNotViewable;
5193     else if ((CompareTimeStamps(time, currentTime) == LATER) ||
5194              (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER))
5195         *status = GrabInvalidTime;
5196     else if (grabInfo->sync.frozen &&
5197              grabInfo->sync.other && !SameClient(grabInfo->sync.other, client))
5198         *status = GrabFrozen;
5199     else
5200     {
5201         GrabPtr tempGrab;
5203         tempGrab = AllocGrab();
5205         tempGrab->next = NULL;
5206         tempGrab->window = pWin;
5207         tempGrab->resource = client->clientAsMask;
5208         tempGrab->ownerEvents = ownerEvents;
5209         tempGrab->keyboardMode = keyboard_mode;
5210         tempGrab->pointerMode = pointer_mode;
5211         if (grabtype == CORE)
5212             tempGrab->eventMask = mask->core;
5213         else if (grabtype == XI)
5214             tempGrab->eventMask = mask->xi;
5215         else
5216             xi2mask_merge(tempGrab->xi2mask, mask->xi2mask);
5217         tempGrab->device = dev;
5218         tempGrab->cursor = cursor;
5219         tempGrab->confineTo = confineTo;
5220         tempGrab->grabtype = grabtype;
5221         (*grabInfo->ActivateGrab)(dev, tempGrab, time, FALSE);
5222         *status = GrabSuccess;
5224         FreeGrab(tempGrab);
5225     }
5226     return Success;
5229 /**
5230  * Server-side protocol handling for GrabKeyboard request.
5231  *
5232  * Grabs the client's keyboard and returns success status to client.
5233  */
5234 int
5235 ProcGrabKeyboard(ClientPtr client)
5237     xGrabKeyboardReply rep;
5238     REQUEST(xGrabKeyboardReq);
5239     int result;
5240     DeviceIntPtr keyboard = PickKeyboard(client);
5241     GrabMask mask;
5243     REQUEST_SIZE_MATCH(xGrabKeyboardReq);
5245     memset(&rep, 0, sizeof(xGrabKeyboardReply));
5246     mask.core = KeyPressMask | KeyReleaseMask;
5248     result = GrabDevice(client, keyboard, stuff->pointerMode,
5249             stuff->keyboardMode, stuff->grabWindow, stuff->ownerEvents,
5250             stuff->time, &mask, CORE, None, None,
5251             &rep.status);
5253     if (result != Success)
5254         return result;
5255     rep.type = X_Reply;
5256     rep.sequenceNumber = client->sequence;
5257     rep.length = 0;
5258     WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
5259     return Success;
5262 /**
5263  * Server-side protocol handling for UngrabKeyboard request.
5264  *
5265  * Deletes a possible grab on the client's keyboard.
5266  */
5267 int
5268 ProcUngrabKeyboard(ClientPtr client)
5270     DeviceIntPtr device = PickKeyboard(client);
5271     GrabPtr grab;
5272     TimeStamp time;
5273     REQUEST(xResourceReq);
5275     REQUEST_SIZE_MATCH(xResourceReq);
5276     UpdateCurrentTime();
5278     grab = device->deviceGrab.grab;
5280     time = ClientTimeToServerTime(stuff->id);
5281     if ((CompareTimeStamps(time, currentTime) != LATER) &&
5282         (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
5283         (grab) && SameClient(grab, client) && grab->grabtype == CORE)
5284         (*device->deviceGrab.DeactivateGrab)(device);
5285     return Success;
5288 /**
5289  * Server-side protocol handling for QueryPointer request.
5290  *
5291  * Returns the current state and position of the client's ClientPointer to the
5292  * client.
5293  */
5294 int
5295 ProcQueryPointer(ClientPtr client)
5297     xQueryPointerReply rep;
5298     WindowPtr pWin, t;
5299     DeviceIntPtr mouse = PickPointer(client);
5300     DeviceIntPtr keyboard;
5301     SpritePtr pSprite;
5302     int rc;
5303     REQUEST(xResourceReq);
5304     REQUEST_SIZE_MATCH(xResourceReq);
5306     rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
5307     if (rc != Success)
5308         return rc;
5309     rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
5310     if (rc != Success && rc != BadAccess)
5311         return rc;
5313     keyboard = GetMaster(mouse, MASTER_KEYBOARD);
5315     pSprite = mouse->spriteInfo->sprite;
5316     if (mouse->valuator->motionHintWindow)
5317         MaybeStopHint(mouse, client);
5318     memset(&rep, 0, sizeof(xQueryPointerReply));
5319     rep.type = X_Reply;
5320     rep.sequenceNumber = client->sequence;
5321     rep.mask = mouse->button ? (mouse->button->state) : 0;
5322     rep.mask |= XkbStateFieldFromRec(&keyboard->key->xkbInfo->state);
5323     rep.length = 0;
5324     rep.root = (GetCurrentRootWindow(mouse))->drawable.id;
5325     rep.rootX = pSprite->hot.x;
5326     rep.rootY = pSprite->hot.y;
5327     rep.child = None;
5328     if (pSprite->hot.pScreen == pWin->drawable.pScreen)
5329     {
5330         rep.sameScreen = xTrue;
5331         rep.winX = pSprite->hot.x - pWin->drawable.x;
5332         rep.winY = pSprite->hot.y - pWin->drawable.y;
5333         for (t = pSprite->win; t; t = t->parent)
5334             if (t->parent == pWin)
5335             {
5336                 rep.child = t->drawable.id;
5337                 break;
5338             }
5339     }
5340     else
5341     {
5342         rep.sameScreen = xFalse;
5343         rep.winX = 0;
5344         rep.winY = 0;
5345     }
5347 #ifdef PANORAMIX
5348     if(!noPanoramiXExtension) {
5349         rep.rootX += screenInfo.screens[0]->x;
5350         rep.rootY += screenInfo.screens[0]->y;
5351         if(stuff->id == rep.root) {
5352             rep.winX += screenInfo.screens[0]->x;
5353             rep.winY += screenInfo.screens[0]->y;
5354         }
5355     }
5356 #endif
5358     if (rc == BadAccess) {
5359         rep.mask = 0;
5360         rep.child = None;
5361         rep.rootX = 0;
5362         rep.rootY = 0;
5363         rep.winX = 0;
5364         rep.winY = 0;
5365     }
5367     WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
5369     return Success;
5372 /**
5373  * Initializes the device list and the DIX sprite to sane values. Allocates
5374  * trace memory used for quick window traversal.
5375  */
5376 void
5377 InitEvents(void)
5379     int i;
5380     QdEventPtr qe, tmp;
5382     inputInfo.numDevices = 0;
5383     inputInfo.devices = (DeviceIntPtr)NULL;
5384     inputInfo.off_devices = (DeviceIntPtr)NULL;
5385     inputInfo.keyboard = (DeviceIntPtr)NULL;
5386     inputInfo.pointer = (DeviceIntPtr)NULL;
5387     for (i = 0; i < MAXDEVICES; i++)
5388     {
5389         memcpy(&event_filters[i], default_filter, sizeof(default_filter));
5390     }
5392     syncEvents.replayDev = (DeviceIntPtr)NULL;
5393     syncEvents.replayWin = NullWindow;
5394     if (syncEvents.pending.next)
5395         list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next)
5396             free(qe);
5397     list_init(&syncEvents.pending);
5398     syncEvents.playingEvents = FALSE;
5399     syncEvents.time.months = 0;
5400     syncEvents.time.milliseconds = 0;   /* hardly matters */
5401     currentTime.months = 0;
5402     currentTime.milliseconds = GetTimeInMillis();
5403     lastDeviceEventTime = currentTime;
5404     for (i = 0; i < DNPMCOUNT; i++)
5405     {
5406         DontPropagateMasks[i] = 0;
5407         DontPropagateRefCnts[i] = 0;
5408     }
5410     InputEventList = InitEventList(GetMaximumEventsNum());
5411     if (!InputEventList)
5412         FatalError("[dix] Failed to allocate input event list.\n");
5415 void
5416 CloseDownEvents(void)
5418     FreeEventList(InputEventList, GetMaximumEventsNum());
5419     InputEventList = NULL;
5422 #define SEND_EVENT_BIT 0x80
5424 /**
5425  * Server-side protocol handling for SendEvent request.
5426  *
5427  * Locates the window to send the event to and forwards the event.
5428  */
5429 int
5430 ProcSendEvent(ClientPtr client)
5432     WindowPtr pWin;
5433     WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
5434     DeviceIntPtr dev = PickPointer(client);
5435     DeviceIntPtr keybd = GetMaster(dev, MASTER_KEYBOARD);
5436     SpritePtr pSprite = dev->spriteInfo->sprite;
5437     REQUEST(xSendEventReq);
5439     REQUEST_SIZE_MATCH(xSendEventReq);
5441     /* libXext and other extension libraries may set the bit indicating
5442      * that this event came from a SendEvent request so remove it
5443      * since otherwise the event type may fail the range checks
5444      * and cause an invalid BadValue error to be returned.
5445      *
5446      * This is safe to do since we later add the SendEvent bit (0x80)
5447      * back in once we send the event to the client */
5449     stuff->event.u.u.type &= ~(SEND_EVENT_BIT);
5451     /* The client's event type must be a core event type or one defined by an
5452         extension. */
5454     if ( ! ((stuff->event.u.u.type > X_Reply &&
5455              stuff->event.u.u.type < LASTEvent) ||
5456             (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
5457              stuff->event.u.u.type < (unsigned)lastEvent)))
5458     {
5459         client->errorValue = stuff->event.u.u.type;
5460         return BadValue;
5461     }
5462     if (stuff->event.u.u.type == ClientMessage &&
5463         stuff->event.u.u.detail != 8 &&
5464         stuff->event.u.u.detail != 16 &&
5465         stuff->event.u.u.detail != 32)
5466     {
5467         client->errorValue = stuff->event.u.u.detail;
5468         return BadValue;
5469     }
5470     if (stuff->eventMask & ~AllEventMasks)
5471     {
5472         client->errorValue = stuff->eventMask;
5473         return BadValue;
5474     }
5476     if (stuff->destination == PointerWindow)
5477         pWin = pSprite->win;
5478     else if (stuff->destination == InputFocus)
5479     {
5480         WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin;
5482         if (inputFocus == NoneWin)
5483             return Success;
5485         /* If the input focus is PointerRootWin, send the event to where
5486         the pointer is if possible, then perhaps propogate up to root. */
5487         if (inputFocus == PointerRootWin)
5488             inputFocus = GetCurrentRootWindow(dev);
5490         if (IsParent(inputFocus, pSprite->win))
5491         {
5492             effectiveFocus = inputFocus;
5493             pWin = pSprite->win;
5494         }
5495         else
5496             effectiveFocus = pWin = inputFocus;
5497     }
5498     else
5499         dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess);
5501     if (!pWin)
5502         return BadWindow;
5503     if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue))
5504     {
5505         client->errorValue = stuff->propagate;
5506         return BadValue;
5507     }
5508     stuff->event.u.u.type |= SEND_EVENT_BIT;
5509     if (stuff->propagate)
5510     {
5511         for (;pWin; pWin = pWin->parent)
5512         {
5513             if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin,
5514                          &stuff->event, 1))
5515                 return Success;
5516             if (DeliverEventsToWindow(dev, pWin,
5517                         &stuff->event, 1, stuff->eventMask, NullGrab))
5518                 return Success;
5519             if (pWin == effectiveFocus)
5520                 return Success;
5521             stuff->eventMask &= ~wDontPropagateMask(pWin);
5522             if (!stuff->eventMask)
5523                 break;
5524         }
5525     }
5526     else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1))
5527         DeliverEventsToWindow(dev, pWin, &stuff->event,
5528                                     1, stuff->eventMask, NullGrab);
5529     return Success;
5532 /**
5533  * Server-side protocol handling for UngrabKey request.
5534  *
5535  * Deletes a passive grab for the given key. Works on the
5536  * client's keyboard.
5537  */
5538 int
5539 ProcUngrabKey(ClientPtr client)
5541     REQUEST(xUngrabKeyReq);
5542     WindowPtr pWin;
5543     GrabPtr tempGrab;
5544     DeviceIntPtr keybd = PickKeyboard(client);
5545     int rc;
5547     REQUEST_SIZE_MATCH(xUngrabKeyReq);
5548     rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess);
5549     if (rc != Success)
5550         return rc;
5552     if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
5553          (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
5554         && (stuff->key != AnyKey))
5555     {
5556         client->errorValue = stuff->key;
5557         return BadValue;
5558     }
5559     if ((stuff->modifiers != AnyModifier) &&
5560         (stuff->modifiers & ~AllModifiersMask))
5561     {
5562         client->errorValue = stuff->modifiers;
5563         return BadValue;
5564     }
5565     tempGrab = AllocGrab();
5566     if (!tempGrab)
5567         return BadAlloc;
5568     tempGrab->resource = client->clientAsMask;
5569     tempGrab->device = keybd;
5570     tempGrab->window = pWin;
5571     tempGrab->modifiersDetail.exact = stuff->modifiers;
5572     tempGrab->modifiersDetail.pMask = NULL;
5573     tempGrab->modifierDevice = keybd;
5574     tempGrab->type = KeyPress;
5575     tempGrab->grabtype = CORE;
5576     tempGrab->detail.exact = stuff->key;
5577     tempGrab->detail.pMask = NULL;
5578     tempGrab->next = NULL;
5580     if (!DeletePassiveGrabFromList(tempGrab))
5581         rc = BadAlloc;
5583     FreeGrab(tempGrab);
5585     return rc;
5588 /**
5589  * Server-side protocol handling for GrabKey request.
5590  *
5591  * Creates a grab for the client's keyboard and adds it to the list of passive
5592  * grabs.
5593  */
5594 int
5595 ProcGrabKey(ClientPtr client)
5597     WindowPtr pWin;
5598     REQUEST(xGrabKeyReq);
5599     GrabPtr grab;
5600     DeviceIntPtr keybd = PickKeyboard(client);
5601     int rc;
5602     GrabParameters param;
5603     GrabMask mask;
5605     REQUEST_SIZE_MATCH(xGrabKeyReq);
5607     memset(&param, 0, sizeof(param));
5608     param.grabtype = CORE;
5609     param.ownerEvents = stuff->ownerEvents;
5610     param.this_device_mode = stuff->keyboardMode;
5611     param.other_devices_mode = stuff->pointerMode;
5612     param.modifiers = stuff->modifiers;
5614     rc = CheckGrabValues(client, &param);
5615     if (rc != Success)
5616         return rc;
5618     if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
5619          (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
5620         && (stuff->key != AnyKey))
5621     {
5622         client->errorValue = stuff->key;
5623         return BadValue;
5624     }
5625     rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
5626     if (rc != Success)
5627         return rc;
5630     mask.core = (KeyPressMask | KeyReleaseMask);
5632     grab = CreateGrab(client->index, keybd, keybd, pWin, CORE, &mask,
5633                       &param, KeyPress, stuff->key, NullWindow, NullCursor);
5634     if (!grab)
5635         return BadAlloc;
5636     return AddPassiveGrabToList(client, grab);
5640 /**
5641  * Server-side protocol handling for GrabButton request.
5642  *
5643  * Creates a grab for the client's ClientPointer and adds it as a passive grab
5644  * to the list.
5645  */
5646 int
5647 ProcGrabButton(ClientPtr client)
5649     WindowPtr pWin, confineTo;
5650     REQUEST(xGrabButtonReq);
5651     CursorPtr cursor;
5652     GrabPtr grab;
5653     DeviceIntPtr ptr, modifierDevice;
5654     Mask access_mode = DixGrabAccess;
5655     GrabMask mask;
5656     GrabParameters param;
5657     int rc;
5659     REQUEST_SIZE_MATCH(xGrabButtonReq);
5660     if ((stuff->pointerMode != GrabModeSync) &&
5661         (stuff->pointerMode != GrabModeAsync))
5662     {
5663         client->errorValue = stuff->pointerMode;
5664         return BadValue;
5665     }
5666     if ((stuff->keyboardMode != GrabModeSync) &&
5667         (stuff->keyboardMode != GrabModeAsync))
5668     {
5669         client->errorValue = stuff->keyboardMode;
5670         return BadValue;
5671     }
5672     if ((stuff->modifiers != AnyModifier) &&
5673         (stuff->modifiers & ~AllModifiersMask))
5674     {
5675         client->errorValue = stuff->modifiers;
5676         return BadValue;
5677     }
5678     if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
5679     {
5680         client->errorValue = stuff->ownerEvents;
5681         return BadValue;
5682     }
5683     if (stuff->eventMask & ~PointerGrabMask)
5684     {
5685         client->errorValue = stuff->eventMask;
5686         return BadValue;
5687     }
5688     rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
5689     if (rc != Success)
5690         return rc;
5691     if (stuff->confineTo == None)
5692        confineTo = NullWindow;
5693     else {
5694         rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
5695                              DixSetAttrAccess);
5696         if (rc != Success)
5697             return rc;
5698     }
5699     if (stuff->cursor == None)
5700         cursor = NullCursor;
5701     else
5702     {
5703         rc = dixLookupResourceByType((pointer *)&cursor, stuff->cursor, RT_CURSOR,
5704                                client, DixUseAccess);
5705         if (rc != Success)
5706         {
5707             client->errorValue = stuff->cursor;
5708             return rc;
5709         }
5710         access_mode |= DixForceAccess;
5711     }
5713     ptr = PickPointer(client);
5714     modifierDevice = GetMaster(ptr, MASTER_KEYBOARD);
5715     if (stuff->pointerMode == GrabModeSync ||
5716         stuff->keyboardMode == GrabModeSync)
5717         access_mode |= DixFreezeAccess;
5718     rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode);
5719     if (rc != Success)
5720         return rc;
5722     memset(&param, 0, sizeof(param));
5723     param.grabtype = CORE;
5724     param.ownerEvents = stuff->ownerEvents;
5725     param.this_device_mode = stuff->keyboardMode;
5726     param.other_devices_mode = stuff->pointerMode;
5727     param.modifiers = stuff->modifiers;
5729     mask.core = stuff->eventMask;
5731     grab = CreateGrab(client->index, ptr, modifierDevice, pWin,
5732                       CORE, &mask, &param, ButtonPress,
5733                       stuff->button, confineTo, cursor);
5734     if (!grab)
5735         return BadAlloc;
5736     return AddPassiveGrabToList(client, grab);
5739 /**
5740  * Server-side protocol handling for UngrabButton request.
5741  *
5742  * Deletes a passive grab on the client's ClientPointer from the list.
5743  */
5744 int
5745 ProcUngrabButton(ClientPtr client)
5747     REQUEST(xUngrabButtonReq);
5748     WindowPtr pWin;
5749     GrabPtr tempGrab;
5750     int rc;
5751     DeviceIntPtr ptr;
5753     REQUEST_SIZE_MATCH(xUngrabButtonReq);
5754     if ((stuff->modifiers != AnyModifier) &&
5755         (stuff->modifiers & ~AllModifiersMask))
5756     {
5757         client->errorValue = stuff->modifiers;
5758         return BadValue;
5759     }
5760     rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
5761     if (rc != Success)
5762         return rc;
5764     ptr = PickPointer(client);
5766     tempGrab = AllocGrab();
5767     if (!tempGrab)
5768         return BadAlloc;
5769     tempGrab->resource = client->clientAsMask;
5770     tempGrab->device = ptr;
5771     tempGrab->window = pWin;
5772     tempGrab->modifiersDetail.exact = stuff->modifiers;
5773     tempGrab->modifiersDetail.pMask = NULL;
5774     tempGrab->modifierDevice = GetMaster(ptr, MASTER_KEYBOARD);
5775     tempGrab->type = ButtonPress;
5776     tempGrab->detail.exact = stuff->button;
5777     tempGrab->grabtype = CORE;
5778     tempGrab->detail.pMask = NULL;
5779     tempGrab->next = NULL;
5781     if (!DeletePassiveGrabFromList(tempGrab))
5782         rc = BadAlloc;
5784     FreeGrab(tempGrab);
5785     return rc;
5788 /**
5789  * Deactivate any grab that may be on the window, remove the focus.
5790  * Delete any XInput extension events from the window too. Does not change the
5791  * window mask. Use just before the window is deleted.
5792  *
5793  * If freeResources is set, passive grabs on the window are deleted.
5794  *
5795  * @param pWin The window to delete events from.
5796  * @param freeResources True if resources associated with the window should be
5797  * deleted.
5798  */
5799 void
5800 DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
5802     WindowPtr           parent;
5803     DeviceIntPtr        mouse = inputInfo.pointer;
5804     DeviceIntPtr        keybd = inputInfo.keyboard;
5805     FocusClassPtr       focus;
5806     OtherClientsPtr     oc;
5807     GrabPtr             passive;
5808     GrabPtr             grab;
5811     /* Deactivate any grabs performed on this window, before making any
5812         input focus changes. */
5813     grab = mouse->deviceGrab.grab;
5814     if (grab &&
5815         ((grab->window == pWin) || (grab->confineTo == pWin)))
5816         (*mouse->deviceGrab.DeactivateGrab)(mouse);
5819     /* Deactivating a keyboard grab should cause focus events. */
5820     grab = keybd->deviceGrab.grab;
5821     if (grab && (grab->window == pWin))
5822         (*keybd->deviceGrab.DeactivateGrab)(keybd);
5824     /* And now the real devices */
5825     for (mouse = inputInfo.devices; mouse; mouse = mouse->next)
5826     {
5827         grab = mouse->deviceGrab.grab;
5828         if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
5829             (*mouse->deviceGrab.DeactivateGrab)(mouse);
5830     }
5833     for (keybd = inputInfo.devices; keybd; keybd = keybd->next)
5834     {
5835         if (IsKeyboardDevice(keybd))
5836         {
5837             focus = keybd->focus;
5839             /* If the focus window is a root window (ie. has no parent) then don't
5840                delete the focus from it. */
5842             if ((pWin == focus->win) && (pWin->parent != NullWindow))
5843             {
5844                 int focusEventMode = NotifyNormal;
5846                 /* If a grab is in progress, then alter the mode of focus events. */
5848                 if (keybd->deviceGrab.grab)
5849                     focusEventMode = NotifyWhileGrabbed;
5851                 switch (focus->revert)
5852                 {
5853                     case RevertToNone:
5854                         DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
5855                         focus->win = NoneWin;
5856                         focus->traceGood = 0;
5857                         break;
5858                     case RevertToParent:
5859                         parent = pWin;
5860                         do
5861                         {
5862                             parent = parent->parent;
5863                             focus->traceGood--;
5864                         } while (!parent->realized
5865                                 /* This would be a good protocol change -- windows being reparented
5866                                    during SaveSet processing would cause the focus to revert to the
5867                                    nearest enclosing window which will survive the death of the exiting
5868                                    client, instead of ending up reverting to a dying window and thence
5869                                    to None
5870                                  */
5871 #ifdef NOTDEF
5872                                  || wClient(parent)->clientGone
5873 #endif
5874                                 );
5875                         if (!ActivateFocusInGrab(keybd, pWin, parent))
5876                             DoFocusEvents(keybd, pWin, parent, focusEventMode);
5877                         focus->win = parent;
5878                         focus->revert = RevertToNone;
5879                         break;
5880                     case RevertToPointerRoot:
5881                         if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin))
5882                             DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode);
5883                         focus->win = PointerRootWin;
5884                         focus->traceGood = 0;
5885                         break;
5886                 }
5887             }
5888         }
5890         if (IsPointerDevice(keybd))
5891         {
5892             if (keybd->valuator->motionHintWindow == pWin)
5893                 keybd->valuator->motionHintWindow = NullWindow;
5894         }
5895     }
5897     if (freeResources)
5898     {
5899         if (pWin->dontPropagate)
5900             DontPropagateRefCnts[pWin->dontPropagate]--;
5901         while ( (oc = wOtherClients(pWin)) )
5902             FreeResource(oc->resource, RT_NONE);
5903         while ( (passive = wPassiveGrabs(pWin)) )
5904             FreeResource(passive->resource, RT_NONE);
5905      }
5907     DeleteWindowFromAnyExtEvents(pWin, freeResources);
5910 /**
5911  * Call this whenever some window at or below pWin has changed geometry. If
5912  * there is a grab on the window, the cursor will be re-confined into the
5913  * window.
5914  */
5915 void
5916 CheckCursorConfinement(WindowPtr pWin)
5918     GrabPtr grab;
5919     WindowPtr confineTo;
5920     DeviceIntPtr pDev;
5922 #ifdef PANORAMIX
5923     if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return;
5924 #endif
5926     for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
5927     {
5928         if (DevHasCursor(pDev))
5929         {
5930             grab = pDev->deviceGrab.grab;
5931             if (grab && (confineTo = grab->confineTo))
5932             {
5933                 if (!BorderSizeNotEmpty(pDev, confineTo))
5934                     (*pDev->deviceGrab.DeactivateGrab)(pDev);
5935                 else if ((pWin == confineTo) || IsParent(pWin, confineTo))
5936                     ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
5937             }
5938         }
5939     }
5942 Mask
5943 EventMaskForClient(WindowPtr pWin, ClientPtr client)
5945     OtherClientsPtr     other;
5947     if (wClient (pWin) == client)
5948         return pWin->eventMask;
5949     for (other = wOtherClients(pWin); other; other = other->next)
5950     {
5951         if (SameClient(other, client))
5952             return other->mask;
5953     }
5954     return 0;
5957 /**
5958  * Server-side protocol handling for RecolorCursor request.
5959  */
5960 int
5961 ProcRecolorCursor(ClientPtr client)
5963     CursorPtr pCursor;
5964     int         rc, nscr;
5965     ScreenPtr   pscr;
5966     Bool        displayed;
5967     SpritePtr   pSprite = PickPointer(client)->spriteInfo->sprite;
5968     REQUEST(xRecolorCursorReq);
5970     REQUEST_SIZE_MATCH(xRecolorCursorReq);
5971     rc = dixLookupResourceByType((pointer *)&pCursor, stuff->cursor, RT_CURSOR,
5972                            client, DixWriteAccess);
5973     if (rc != Success)
5974     {
5975         client->errorValue = stuff->cursor;
5976         return rc;
5977     }
5979     pCursor->foreRed = stuff->foreRed;
5980     pCursor->foreGreen = stuff->foreGreen;
5981     pCursor->foreBlue = stuff->foreBlue;
5983     pCursor->backRed = stuff->backRed;
5984     pCursor->backGreen = stuff->backGreen;
5985     pCursor->backBlue = stuff->backBlue;
5987     for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
5988     {
5989         pscr = screenInfo.screens[nscr];
5990 #ifdef PANORAMIX
5991         if(!noPanoramiXExtension)
5992             displayed = (pscr == pSprite->screen);
5993         else
5994 #endif
5995             displayed = (pscr == pSprite->hotPhys.pScreen);
5996         ( *pscr->RecolorCursor)(PickPointer(client), pscr, pCursor,
5997                                 (pCursor == pSprite->current) && displayed);
5998     }
5999     return Success;
6002 /**
6003  * Write the given events to a client, swapping the byte order if necessary.
6004  * To swap the byte ordering, a callback is called that has to be set up for
6005  * the given event type.
6006  *
6007  * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
6008  * can be more than one. Usually it's just one event.
6009  *
6010  * Do not modify the event structure passed in. See comment below.
6011  *
6012  * @param pClient Client to send events to.
6013  * @param count Number of events.
6014  * @param events The event list.
6015  */
6016 void
6017 WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
6019 #ifdef PANORAMIX
6020     xEvent    eventCopy;
6021 #endif
6022     xEvent    *eventTo, *eventFrom;
6023     int       i,
6024               eventlength = sizeof(xEvent);
6026     if (!pClient || pClient == serverClient || pClient->clientGone)
6027         return;
6029     for (i = 0; i < count; i++)
6030         if ((events[i].u.u.type & 0x7f) != KeymapNotify)
6031             events[i].u.u.sequenceNumber = pClient->sequence;
6033     /* Let XKB rewrite the state, as it depends on client preferences. */
6034     XkbFilterEvents(pClient, count, events);
6036 #ifdef PANORAMIX
6037     if(!noPanoramiXExtension &&
6038        (screenInfo.screens[0]->x || screenInfo.screens[0]->y))
6039     {
6040         switch(events->u.u.type) {
6041         case MotionNotify:
6042         case ButtonPress:
6043         case ButtonRelease:
6044         case KeyPress:
6045         case KeyRelease:
6046         case EnterNotify:
6047         case LeaveNotify:
6048         /*
6049            When multiple clients want the same event DeliverEventsToWindow
6050            passes the same event structure multiple times so we can't
6051            modify the one passed to us
6052         */
6053             count = 1;  /* should always be 1 */
6054             memcpy(&eventCopy, events, sizeof(xEvent));
6055             eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x;
6056             eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y;
6057             if(eventCopy.u.keyButtonPointer.event ==
6058                eventCopy.u.keyButtonPointer.root)
6059             {
6060                 eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x;
6061                 eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y;
6062             }
6063             events = &eventCopy;
6064             break;
6065         default: break;
6066         }
6067     }
6068 #endif
6070     if (EventCallback)
6071     {
6072         EventInfoRec eventinfo;
6073         eventinfo.client = pClient;
6074         eventinfo.events = events;
6075         eventinfo.count = count;
6076         CallCallbacks(&EventCallback, (pointer)&eventinfo);
6077     }
6078 #ifdef XSERVER_DTRACE
6079     if (XSERVER_SEND_EVENT_ENABLED()) {
6080         for (i = 0; i < count; i++)
6081         {
6082             XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]);
6083         }
6084     }
6085 #endif
6086     /* Just a safety check to make sure we only have one GenericEvent, it just
6087      * makes things easier for me right now. (whot) */
6088     for (i = 1; i < count; i++)
6089     {
6090         if (events[i].u.u.type == GenericEvent)
6091         {
6092             ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n");
6093             return;
6094         }
6095     }
6097     if (events->u.u.type == GenericEvent)
6098     {
6099         eventlength += ((xGenericEvent*)events)->length * 4;
6100     }
6102     if(pClient->swapped)
6103     {
6104         if (eventlength > swapEventLen)
6105         {
6106             swapEventLen = eventlength;
6107             swapEvent = realloc(swapEvent, swapEventLen);
6108             if (!swapEvent)
6109             {
6110                 FatalError("WriteEventsToClient: Out of memory.\n");
6111                 return;
6112             }
6113         }
6115         for(i = 0; i < count; i++)
6116         {
6117             eventFrom = &events[i];
6118             eventTo = swapEvent;
6120             /* Remember to strip off the leading bit of type in case
6121                this event was sent with "SendEvent." */
6122             (*EventSwapVector[eventFrom->u.u.type & 0177])
6123                 (eventFrom, eventTo);
6125             WriteToClient(pClient, eventlength, (char *)eventTo);
6126         }
6127     }
6128     else
6129     {
6130         /* only one GenericEvent, remember? that means either count is 1 and
6131          * eventlength is arbitrary or eventlength is 32 and count doesn't
6132          * matter. And we're all set. Woohoo. */
6133         WriteToClient(pClient, count * eventlength, (char *) events);
6134     }
6137 /*
6138  * Set the client pointer for the given client.
6139  *
6140  * A client can have exactly one ClientPointer. Each time a
6141  * request/reply/event is processed and the choice of devices is ambiguous
6142  * (e.g. QueryPointer request), the server will pick the ClientPointer (see
6143  * PickPointer()).
6144  * If a keyboard is needed, the first keyboard paired with the CP is used.
6145  */
6146 int
6147 SetClientPointer(ClientPtr client, DeviceIntPtr device)
6149     int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess);
6150     if (rc != Success)
6151         return rc;
6153     if (!IsMaster(device))
6154     {
6155         ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n");
6156         return BadDevice;
6157     } else if (!device->spriteInfo->spriteOwner)
6158     {
6159         ErrorF("[dix] Device %d does not have a sprite. "
6160                 "Cannot be ClientPointer\n", device->id);
6161         return BadDevice;
6162     }
6163     client->clientPtr = device;
6164     return Success;
6167 /* PickPointer will pick an appropriate pointer for the given client.
6168  *
6169  * An "appropriate device" is (in order of priority):
6170  *  1) A device the given client has a core grab on.
6171  *  2) A device set as ClientPointer for the given client.
6172  *  3) The first master device.
6173  */
6174 DeviceIntPtr
6175 PickPointer(ClientPtr client)
6177     DeviceIntPtr it = inputInfo.devices;
6179     /* First, check if the client currently has a grab on a device. Even
6180      * keyboards count. */
6181     for(it = inputInfo.devices; it; it = it->next)
6182     {
6183         GrabPtr grab = it->deviceGrab.grab;
6184         if (grab && grab->grabtype == CORE && SameClient(grab, client))
6185         {
6186             it = GetMaster(it, MASTER_POINTER);
6187             return it; /* Always return a core grabbed device */
6188         }
6189     }
6191     if (!client->clientPtr)
6192     {
6193         it = inputInfo.devices;
6194         while (it)
6195         {
6196             if (IsMaster(it) && it->spriteInfo->spriteOwner)
6197             {
6198                 client->clientPtr = it;
6199                 break;
6200             }
6201             it = it->next;
6202         }
6203     }
6204     return client->clientPtr;
6207 /* PickKeyboard will pick an appropriate keyboard for the given client by
6208  * searching the list of devices for the keyboard device that is paired with
6209  * the client's pointer.
6210  */
6211 DeviceIntPtr
6212 PickKeyboard(ClientPtr client)
6214     DeviceIntPtr ptr = PickPointer(client);
6215     DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD);
6217     if (!kbd)
6218     {
6219         ErrorF("[dix] ClientPointer not paired with a keyboard. This "
6220                 "is a bug.\n");
6221     }
6223     return kbd;
6226 /* A client that has one or more core grabs does not get core events from
6227  * devices it does not have a grab on. Legacy applications behave bad
6228  * otherwise because they are not used to it and the events interfere.
6229  * Only applies for core events.
6230  *
6231  * Return true if a core event from the device would interfere and should not
6232  * be delivered.
6233  */
6234 Bool
6235 IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event)
6237     DeviceIntPtr it = inputInfo.devices;
6239     switch(event->u.u.type)
6240     {
6241         case KeyPress:
6242         case KeyRelease:
6243         case ButtonPress:
6244         case ButtonRelease:
6245         case MotionNotify:
6246         case EnterNotify:
6247         case LeaveNotify:
6248             break;
6249         default:
6250             return FALSE;
6251     }
6253     if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
6254         return FALSE;
6256     while(it)
6257     {
6258         if (it != dev)
6259         {
6260             if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client)
6261                         && !it->deviceGrab.fromPassiveGrab)
6262             {
6263                 if ((IsPointerDevice(it) && IsPointerDevice(dev)) ||
6264                         (IsKeyboardDevice(it) && IsKeyboardDevice(dev)))
6265                     return TRUE;
6266             }
6267         }
6268         it = it->next;
6269     }
6271     return FALSE;