]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/xserver.git/blob - dix/events.c
Imported Upstream version 1.11.4
[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"
156 /* Extension events type numbering starts at EXTENSION_EVENT_BASE.  */
157 #define NoSuchEvent 0x80000000  /* so doesn't match NoEventMask */
158 #define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
159 #define AllButtonsMask ( \
160         Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
161 #define MotionMask ( \
162         PointerMotionMask | Button1MotionMask | \
163         Button2MotionMask | Button3MotionMask | Button4MotionMask | \
164         Button5MotionMask | ButtonMotionMask )
165 #define PropagateMask ( \
166         KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
167         MotionMask )
168 #define PointerGrabMask ( \
169         ButtonPressMask | ButtonReleaseMask | \
170         EnterWindowMask | LeaveWindowMask | \
171         PointerMotionHintMask | KeymapStateMask | \
172         MotionMask )
173 #define AllModifiersMask ( \
174         ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
175         Mod3Mask | Mod4Mask | Mod5Mask )
176 #define LastEventMask OwnerGrabButtonMask
177 #define AllEventMasks (LastEventMask|(LastEventMask-1))
180 /* @return the core event type or 0 if the event is not a core event */
181 static inline int
182 core_get_type(const xEvent *event)
184     int type = event->u.u.type;
186     return ((type & EXTENSION_EVENT_BASE) || type == GenericEvent) ? 0 : type;
189 /* @return the XI2 event type or 0 if the event is not a XI2 event */
190 static inline int
191 xi2_get_type(const xEvent *event)
193     xGenericEvent* e = (xGenericEvent*)event;
195     return (e->type != GenericEvent || e->extension != IReqCode) ? 0 : e->evtype;
198 /**
199  * Used to indicate a implicit passive grab created by a ButtonPress event.
200  * See DeliverEventsToWindow().
201  */
202 #define ImplicitGrabMask (1 << 7)
204 #define WID(w) ((w) ? ((w)->drawable.id) : 0)
206 #define XE_KBPTR (xE->u.keyButtonPointer)
209 CallbackListPtr EventCallback;
210 CallbackListPtr DeviceEventCallback;
212 #define DNPMCOUNT 8
214 Mask DontPropagateMasks[DNPMCOUNT];
215 static int DontPropagateRefCnts[DNPMCOUNT];
217 static void CheckVirtualMotion( DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin);
218 static void CheckPhysLimits(DeviceIntPtr pDev,
219                             CursorPtr cursor,
220                             Bool generateEvents,
221                             Bool confineToScreen,
222                             ScreenPtr pScreen);
224 /** Key repeat hack. Do not use but in TryClientEvents */
225 extern BOOL EventIsKeyRepeat(xEvent *event);
227 /**
228  * Main input device struct.
229  *     inputInfo.pointer
230  *     is the core pointer. Referred to as "virtual core pointer", "VCP",
231  *     "core pointer" or inputInfo.pointer. The VCP is the first master
232  *     pointer device and cannot be deleted.
233  *
234  *     inputInfo.keyboard
235  *     is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
236  *     See inputInfo.pointer.
237  *
238  *     inputInfo.devices
239  *     linked list containing all devices including VCP and VCK.
240  *
241  *     inputInfo.off_devices
242  *     Devices that have not been initialized and are thus turned off.
243  *
244  *     inputInfo.numDevices
245  *     Total number of devices.
246  *
247  *     inputInfo.all_devices
248  *     Virtual device used for XIAllDevices passive grabs. This device is
249  *     not part of the inputInfo.devices list and mostly unset except for
250  *     the deviceid. It exists because passivegrabs need a valid device
251  *     reference.
252  *
253  *     inputInfo.all_master_devices
254  *     Virtual device used for XIAllMasterDevices passive grabs. This device
255  *     is not part of the inputInfo.devices list and mostly unset except for
256  *     the deviceid. It exists because passivegrabs need a valid device
257  *     reference.
258  */
259 InputInfo inputInfo;
261 EventSyncInfoRec syncEvents;
263 /**
264  * The root window the given device is currently on.
265  */
266 #define RootWindow(sprite) sprite->spriteTrace[0]
268 static xEvent* swapEvent = NULL;
269 static int swapEventLen = 0;
271 void
272 NotImplemented(xEvent *from, xEvent *to)
274     FatalError("Not implemented");
277 /**
278  * Convert the given event type from an XI event to a core event.
279  * @param[in] The XI 1.x event type.
280  * @return The matching core event type or 0 if there is none.
281  */
282 int
283 XItoCoreType(int xitype)
285     int coretype = 0;
286     if (xitype == DeviceMotionNotify)
287         coretype = MotionNotify;
288     else if (xitype == DeviceButtonPress)
289         coretype = ButtonPress;
290     else if (xitype == DeviceButtonRelease)
291         coretype = ButtonRelease;
292     else if (xitype == DeviceKeyPress)
293         coretype = KeyPress;
294     else if (xitype == DeviceKeyRelease)
295         coretype = KeyRelease;
297     return coretype;
300 /**
301  * @return true if the device owns a cursor, false if device shares a cursor
302  * sprite with another device.
303  */
304 Bool
305 DevHasCursor(DeviceIntPtr pDev)
307     return pDev->spriteInfo->spriteOwner;
310 /*
311  * @return true if a device is a pointer, check is the same as used by XI to
312  * fill the 'use' field.
313  */
314 Bool
315 IsPointerDevice(DeviceIntPtr dev)
317     return (dev->type == MASTER_POINTER) ||
318             (dev->valuator && dev->button) ||
319             (dev->valuator && !dev->key);
322 /*
323  * @return true if a device is a keyboard, check is the same as used by XI to
324  * fill the 'use' field.
325  *
326  * Some pointer devices have keys as well (e.g. multimedia keys). Try to not
327  * count them as keyboard devices.
328  */
329 Bool
330 IsKeyboardDevice(DeviceIntPtr dev)
332     return (dev->type == MASTER_KEYBOARD) ||
333             ((dev->key && dev->kbdfeed) && !IsPointerDevice(dev));
336 Bool
337 IsMaster(DeviceIntPtr dev)
339     return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
342 Bool
343 IsFloating(DeviceIntPtr dev)
345     return GetMaster(dev, MASTER_KEYBOARD) == NULL;
349 /**
350  * Max event opcode.
351  */
352 extern int lastEvent;
354 extern int DeviceMotionNotify;
356 #define CantBeFiltered NoEventMask
357 /**
358  * Event masks for each event type.
359  *
360  * One set of filters for each device, initialized by memcpy of
361  * default_filter in InitEvents.
362  *
363  * Filters are used whether a given event may be delivered to a client,
364  * usually in the form of if (window-event-mask & filter); then deliver event.
365  *
366  * One notable filter is for PointerMotion/DevicePointerMotion events. Each
367  * time a button is pressed, the filter is modified to also contain the
368  * matching ButtonXMotion mask.
369  */
370 static Mask filters[MAXDEVICES][128];
372 static const Mask default_filter[128] =
374         NoSuchEvent,                   /* 0 */
375         NoSuchEvent,                   /* 1 */
376         KeyPressMask,                  /* KeyPress */
377         KeyReleaseMask,                /* KeyRelease */
378         ButtonPressMask,               /* ButtonPress */
379         ButtonReleaseMask,             /* ButtonRelease */
380         PointerMotionMask,             /* MotionNotify (initial state) */
381         EnterWindowMask,               /* EnterNotify */
382         LeaveWindowMask,               /* LeaveNotify */
383         FocusChangeMask,               /* FocusIn */
384         FocusChangeMask,               /* FocusOut */
385         KeymapStateMask,               /* KeymapNotify */
386         ExposureMask,                  /* Expose */
387         CantBeFiltered,                /* GraphicsExpose */
388         CantBeFiltered,                /* NoExpose */
389         VisibilityChangeMask,          /* VisibilityNotify */
390         SubstructureNotifyMask,        /* CreateNotify */
391         StructureAndSubMask,           /* DestroyNotify */
392         StructureAndSubMask,           /* UnmapNotify */
393         StructureAndSubMask,           /* MapNotify */
394         SubstructureRedirectMask,      /* MapRequest */
395         StructureAndSubMask,           /* ReparentNotify */
396         StructureAndSubMask,           /* ConfigureNotify */
397         SubstructureRedirectMask,      /* ConfigureRequest */
398         StructureAndSubMask,           /* GravityNotify */
399         ResizeRedirectMask,            /* ResizeRequest */
400         StructureAndSubMask,           /* CirculateNotify */
401         SubstructureRedirectMask,      /* CirculateRequest */
402         PropertyChangeMask,            /* PropertyNotify */
403         CantBeFiltered,                /* SelectionClear */
404         CantBeFiltered,                /* SelectionRequest */
405         CantBeFiltered,                /* SelectionNotify */
406         ColormapChangeMask,            /* ColormapNotify */
407         CantBeFiltered,                /* ClientMessage */
408         CantBeFiltered                 /* MappingNotify */
409 };
411 /**
412  * For the given event, return the matching event filter. This filter may then
413  * be AND'ed with the selected event mask.
414  *
415  * For XI2 events, the returned filter is simply the byte containing the event
416  * mask we're interested in. E.g. for a mask of (1 << 13), this would be
417  * byte[1].
418  *
419  * @param[in] dev The device the event belongs to, may be NULL.
420  * @param[in] event The event to get the filter for. Only the type of the
421  *                  event matters, or the extension + evtype for GenericEvents.
422  * @return The filter mask for the given event.
423  *
424  * @see GetEventMask
425  */
426 Mask
427 GetEventFilter(DeviceIntPtr dev, xEvent *event)
429     int evtype = 0;
431     if (event->u.u.type != GenericEvent)
432         return filters[dev ? dev->id : 0][event->u.u.type];
433     else if ((evtype = xi2_get_type(event)))
434         return (1 << (evtype % 8));
435     ErrorF("[dix] Unknown event type %d. No filter\n", event->u.u.type);
436     return 0;
439 /**
440  * Return the windows complete XI2 mask for the given XI2 event type.
441  */
442 Mask
443 GetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev)
445     OtherInputMasks *inputMasks = wOtherInputMasks(win);
446     int filter;
447     int evtype;
449     if (!inputMasks || xi2_get_type(ev) == 0)
450         return 0;
452     evtype = ((xGenericEvent*)ev)->evtype;
453     filter = GetEventFilter(dev, ev);
455     return ((inputMasks->xi2mask[dev->id][evtype/8] & filter) ||
456             inputMasks->xi2mask[XIAllDevices][evtype/8] ||
457             (inputMasks->xi2mask[XIAllMasterDevices][evtype/8] && IsMaster(dev)));
460 Mask
461 GetEventMask(DeviceIntPtr dev, xEvent *event, InputClients* other)
463     int evtype;
465     /* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */
466     if ((evtype = xi2_get_type(event)))
467     {
468         int byte = evtype / 8;
469         return (other->xi2mask[dev->id][byte] |
470                 other->xi2mask[XIAllDevices][byte] |
471                 (IsMaster(dev)? other->xi2mask[XIAllMasterDevices][byte] : 0));
472     } else if (core_get_type(event) != 0)
473         return other->mask[XIAllDevices];
474     else
475         return other->mask[dev->id];
479 static CARD8 criticalEvents[32] =
481     0x7c, 0x30, 0x40                    /* key, button, expose, and configure events */
482 };
484 static void
485 SyntheticMotion(DeviceIntPtr dev, int x, int y) {
486     int screenno = 0;
488 #ifdef PANORAMIX
489     if (!noPanoramiXExtension)
490         screenno = dev->spriteInfo->sprite->screen->myNum;
491 #endif
492     PostSyntheticMotion(dev, x, y, screenno,
493             (syncEvents.playingEvents) ?  syncEvents.time.milliseconds : currentTime.milliseconds);
497 #ifdef PANORAMIX
498 static void PostNewCursor(DeviceIntPtr pDev);
500 static Bool
501 pointOnScreen(ScreenPtr pScreen, int x, int y)
503     return x >= pScreen->x && x < pScreen->x + pScreen->width &&
504            y >= pScreen->y && y < pScreen->y + pScreen->height;
507 static Bool
508 XineramaSetCursorPosition(
509     DeviceIntPtr pDev,
510     int x,
511     int y,
512     Bool generateEvent
513 ){
514     ScreenPtr pScreen;
515     int i;
516     SpritePtr pSprite = pDev->spriteInfo->sprite;
518     /* x,y are in Screen 0 coordinates.  We need to decide what Screen
519        to send the message too and what the coordinates relative to
520        that screen are. */
522     pScreen = pSprite->screen;
523     x += screenInfo.screens[0]->x;
524     y += screenInfo.screens[0]->y;
526     if(!pointOnScreen(pScreen, x, y))
527     {
528         FOR_NSCREENS(i)
529         {
530             if(i == pScreen->myNum)
531                 continue;
532             if(pointOnScreen(screenInfo.screens[i], x, y))
533             {
534                 pScreen = screenInfo.screens[i];
535                 break;
536             }
537         }
538     }
540     pSprite->screen = pScreen;
541     pSprite->hotPhys.x = x - screenInfo.screens[0]->x;
542     pSprite->hotPhys.y = y - screenInfo.screens[0]->y;
543     x -= pScreen->x;
544     y -= pScreen->y;
546     return (*pScreen->SetCursorPosition)(pDev, pScreen, x, y, generateEvent);
550 static void
551 XineramaConstrainCursor(DeviceIntPtr pDev)
553     SpritePtr pSprite = pDev->spriteInfo->sprite;
554     ScreenPtr pScreen;
555     BoxRec newBox;
557     pScreen = pSprite->screen;
558     newBox = pSprite->physLimits;
560     /* Translate the constraining box to the screen
561        the sprite is actually on */
562     newBox.x1 += screenInfo.screens[0]->x - pScreen->x;
563     newBox.x2 += screenInfo.screens[0]->x - pScreen->x;
564     newBox.y1 += screenInfo.screens[0]->y - pScreen->y;
565     newBox.y2 += screenInfo.screens[0]->y - pScreen->y;
567     (* pScreen->ConstrainCursor)(pDev, pScreen, &newBox);
571 static Bool
572 XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
574     SpritePtr pSprite = pDev->spriteInfo->sprite;
576     if(pWin == screenInfo.screens[0]->root) {
577         int i;
578         FOR_NSCREENS(i)
579             pSprite->windows[i] = screenInfo.screens[i]->root;
580     } else {
581         PanoramiXRes *win;
582         int rc, i;
584         rc = dixLookupResourceByType((pointer *)&win, pWin->drawable.id,
585                                      XRT_WINDOW, serverClient, DixReadAccess);
586         if (rc != Success)
587             return FALSE;
589         FOR_NSCREENS(i) {
590             rc = dixLookupWindow(pSprite->windows + i, win->info[i].id,
591                                  serverClient, DixReadAccess);
592             if (rc != Success)  /* window is being unmapped */
593                 return FALSE;
594         }
595     }
596     return TRUE;
599 static void
600 XineramaConfineCursorToWindow(DeviceIntPtr pDev,
601                               WindowPtr pWin,
602                               Bool generateEvents)
604     SpritePtr pSprite = pDev->spriteInfo->sprite;
606     int x, y, off_x, off_y, i;
608     if(!XineramaSetWindowPntrs(pDev, pWin))
609         return;
611     i = PanoramiXNumScreens - 1;
613     RegionCopy(&pSprite->Reg1,
614             &pSprite->windows[i]->borderSize);
615     off_x = screenInfo.screens[i]->x;
616     off_y = screenInfo.screens[i]->y;
618     while(i--) {
619         x = off_x - screenInfo.screens[i]->x;
620         y = off_y - screenInfo.screens[i]->y;
622         if(x || y)
623             RegionTranslate(&pSprite->Reg1, x, y);
625         RegionUnion(&pSprite->Reg1, &pSprite->Reg1,
626                 &pSprite->windows[i]->borderSize);
628         off_x = screenInfo.screens[i]->x;
629         off_y = screenInfo.screens[i]->y;
630     }
632     pSprite->hotLimits = *RegionExtents(&pSprite->Reg1);
634     if(RegionNumRects(&pSprite->Reg1) > 1)
635         pSprite->hotShape = &pSprite->Reg1;
636     else
637         pSprite->hotShape = NullRegion;
639     pSprite->confined = FALSE;
640     pSprite->confineWin = (pWin == screenInfo.screens[0]->root) ? NullWindow : pWin;
642     CheckPhysLimits(pDev, pSprite->current, generateEvents, FALSE, NULL);
645 #endif  /* PANORAMIX */
647 /**
648  * Modifies the filter for the given protocol event type to the given masks.
649  *
650  * There's only two callers: UpdateDeviceState() and XI's SetMaskForExtEvent().
651  * The latter initialises masks for the matching XI events, it's a once-off
652  * setting.
653  * UDS however changes the mask for MotionNotify and DeviceMotionNotify each
654  * time a button is pressed to include the matching ButtonXMotion mask in the
655  * filter.
656  *
657  * @param[in] deviceid The device to modify the filter for.
658  * @param[in] mask The new filter mask.
659  * @param[in] event Protocol event type.
660  */
661 void
662 SetMaskForEvent(int deviceid, Mask mask, int event)
664     if (deviceid < 0 || deviceid >= MAXDEVICES)
665         FatalError("SetMaskForEvent: bogus device id");
666     filters[deviceid][event] = mask;
669 void
670 SetCriticalEvent(int event)
672     if (event >= 128)
673         FatalError("SetCriticalEvent: bogus event number");
674     criticalEvents[event >> 3] |= 1 << (event & 7);
677 void
678 ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
680     BoxRec box;
681     int x = *px, y = *py;
682     int incx = 1, incy = 1;
683     SpritePtr pSprite;
685     pSprite = pDev->spriteInfo->sprite;
686     if (RegionContainsPoint(shape, x, y, &box))
687         return;
688     box = *RegionExtents(shape);
689     /* this is rather crude */
690     do {
691         x += incx;
692         if (x >= box.x2)
693         {
694             incx = -1;
695             x = *px - 1;
696         }
697         else if (x < box.x1)
698         {
699             incx = 1;
700             x = *px;
701             y += incy;
702             if (y >= box.y2)
703             {
704                 incy = -1;
705                 y = *py - 1;
706             }
707             else if (y < box.y1)
708                 return; /* should never get here! */
709         }
710     } while (!RegionContainsPoint(shape, x, y, &box));
711     *px = x;
712     *py = y;
715 static void
716 CheckPhysLimits(
717     DeviceIntPtr pDev,
718     CursorPtr cursor,
719     Bool generateEvents,
720     Bool confineToScreen, /* unused if PanoramiX on */
721     ScreenPtr pScreen)    /* unused if PanoramiX on */
723     HotSpot new;
724     SpritePtr pSprite = pDev->spriteInfo->sprite;
726     if (!cursor)
727         return;
728     new = pSprite->hotPhys;
729 #ifdef PANORAMIX
730     if (!noPanoramiXExtension)
731         /* I don't care what the DDX has to say about it */
732         pSprite->physLimits = pSprite->hotLimits;
733     else
734 #endif
735     {
736         if (pScreen)
737             new.pScreen = pScreen;
738         else
739             pScreen = new.pScreen;
740         (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits,
741                 &pSprite->physLimits);
742         pSprite->confined = confineToScreen;
743         (* pScreen->ConstrainCursor)(pDev, pScreen, &pSprite->physLimits);
744     }
746     /* constrain the pointer to those limits */
747     if (new.x < pSprite->physLimits.x1)
748         new.x = pSprite->physLimits.x1;
749     else
750         if (new.x >= pSprite->physLimits.x2)
751             new.x = pSprite->physLimits.x2 - 1;
752     if (new.y < pSprite->physLimits.y1)
753         new.y = pSprite->physLimits.y1;
754     else
755         if (new.y >= pSprite->physLimits.y2)
756             new.y = pSprite->physLimits.y2 - 1;
757     if (pSprite->hotShape)
758         ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y);
759     if ((
760 #ifdef PANORAMIX
761             noPanoramiXExtension &&
762 #endif
763             (pScreen != pSprite->hotPhys.pScreen)) ||
764         (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y))
765     {
766 #ifdef PANORAMIX
767         if (!noPanoramiXExtension)
768             XineramaSetCursorPosition (pDev, new.x, new.y, generateEvents);
769         else
770 #endif
771         {
772             if (pScreen != pSprite->hotPhys.pScreen)
773                 pSprite->hotPhys = new;
774             (*pScreen->SetCursorPosition)
775                 (pDev, pScreen, new.x, new.y, generateEvents);
776         }
777         if (!generateEvents)
778             SyntheticMotion(pDev, new.x, new.y);
779     }
781 #ifdef PANORAMIX
782     /* Tell DDX what the limits are */
783     if (!noPanoramiXExtension)
784         XineramaConstrainCursor(pDev);
785 #endif
788 static void
789 CheckVirtualMotion(
790     DeviceIntPtr pDev,
791     QdEventPtr qe,
792     WindowPtr pWin)
794     SpritePtr pSprite = pDev->spriteInfo->sprite;
795     RegionPtr reg = NULL;
796     DeviceEvent *ev = NULL;
798     if (qe)
799     {
800         ev = &qe->event->device_event;
801         switch(ev->type)
802         {
803             case ET_Motion:
804             case ET_ButtonPress:
805             case ET_ButtonRelease:
806             case ET_KeyPress:
807             case ET_KeyRelease:
808             case ET_ProximityIn:
809             case ET_ProximityOut:
810                 pSprite->hot.pScreen = qe->pScreen;
811                 pSprite->hot.x = ev->root_x;
812                 pSprite->hot.y = ev->root_y;
813                 pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo : NullWindow;
814                 break;
815             default:
816                 break;
817         }
818     }
819     if (pWin)
820     {
821         BoxRec lims;
823 #ifdef PANORAMIX
824         if (!noPanoramiXExtension) {
825             int x, y, off_x, off_y, i;
827             if(!XineramaSetWindowPntrs(pDev, pWin))
828                 return;
830             i = PanoramiXNumScreens - 1;
832             RegionCopy(&pSprite->Reg2,
833                     &pSprite->windows[i]->borderSize);
834             off_x = screenInfo.screens[i]->x;
835             off_y = screenInfo.screens[i]->y;
837             while(i--) {
838                 x = off_x - screenInfo.screens[i]->x;
839                 y = off_y - screenInfo.screens[i]->y;
841                 if(x || y)
842                     RegionTranslate(&pSprite->Reg2, x, y);
844                 RegionUnion(&pSprite->Reg2, &pSprite->Reg2,
845                         &pSprite->windows[i]->borderSize);
847                 off_x = screenInfo.screens[i]->x;
848                 off_y = screenInfo.screens[i]->y;
849             }
850         } else
851 #endif
852         {
853             if (pSprite->hot.pScreen != pWin->drawable.pScreen)
854             {
855                 pSprite->hot.pScreen = pWin->drawable.pScreen;
856                 pSprite->hot.x = pSprite->hot.y = 0;
857             }
858         }
860         lims = *RegionExtents(&pWin->borderSize);
861         if (pSprite->hot.x < lims.x1)
862             pSprite->hot.x = lims.x1;
863         else if (pSprite->hot.x >= lims.x2)
864             pSprite->hot.x = lims.x2 - 1;
865         if (pSprite->hot.y < lims.y1)
866             pSprite->hot.y = lims.y1;
867         else if (pSprite->hot.y >= lims.y2)
868             pSprite->hot.y = lims.y2 - 1;
870 #ifdef PANORAMIX
871         if (!noPanoramiXExtension)
872         {
873             if (RegionNumRects(&pSprite->Reg2) > 1)
874                 reg = &pSprite->Reg2;
876         } else
877 #endif
878         {
879             if (wBoundingShape(pWin))
880                 reg = &pWin->borderSize;
881         }
883         if (reg)
884             ConfineToShape(pDev, reg, &pSprite->hot.x, &pSprite->hot.y);
886         if (qe && ev)
887         {
888             qe->pScreen = pSprite->hot.pScreen;
889             ev->root_x = pSprite->hot.x;
890             ev->root_y = pSprite->hot.y;
891         }
892     }
893 #ifdef PANORAMIX
894     if (noPanoramiXExtension) /* No typo. Only set the root win if disabled */
895 #endif
896         RootWindow(pDev->spriteInfo->sprite) = pSprite->hot.pScreen->root;
899 static void
900 ConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
902     SpritePtr pSprite = pDev->spriteInfo->sprite;
904     if (syncEvents.playingEvents)
905     {
906         CheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin);
907         SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y);
908     }
909     else
910     {
911 #ifdef PANORAMIX
912         if(!noPanoramiXExtension) {
913             XineramaConfineCursorToWindow(pDev, pWin, generateEvents);
914             return;
915         }
916 #endif
917         pSprite->hotLimits = *RegionExtents(&pWin->borderSize);
918         pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize
919                                                : NullRegion;
920         CheckPhysLimits(pDev, pSprite->current, generateEvents,
921                         confineToScreen, pWin->drawable.pScreen);
922     }
925 Bool
926 PointerConfinedToScreen(DeviceIntPtr pDev)
928     return pDev->spriteInfo->sprite->confined;
931 /**
932  * Update the sprite cursor to the given cursor.
933  *
934  * ChangeToCursor() will display the new cursor and free the old cursor (if
935  * applicable). If the provided cursor is already the updated cursor, nothing
936  * happens.
937  */
938 static void
939 ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
941     SpritePtr pSprite = pDev->spriteInfo->sprite;
942     ScreenPtr pScreen;
944     if (cursor != pSprite->current)
945     {
946         if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
947                 (pSprite->current->bits->yhot != cursor->bits->yhot))
948             CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined,
949                             (ScreenPtr)NULL);
950 #ifdef PANORAMIX
951         /* XXX: is this really necessary?? (whot) */
952         if (!noPanoramiXExtension)
953             pScreen = pSprite->screen;
954         else
955 #endif
956             pScreen = pSprite->hotPhys.pScreen;
958         (*pScreen->DisplayCursor)(pDev, pScreen, cursor);
959         FreeCursor(pSprite->current, (Cursor)0);
960         pSprite->current = cursor;
961         pSprite->current->refcnt++;
962     }
965 /**
966  * @returns true if b is a descendent of a
967  */
968 Bool
969 IsParent(WindowPtr a, WindowPtr b)
971     for (b = b->parent; b; b = b->parent)
972         if (b == a) return TRUE;
973     return FALSE;
976 /**
977  * Update the cursor displayed on the screen.
978  *
979  * Called whenever a cursor may have changed shape or position.
980  */
981 static void
982 PostNewCursor(DeviceIntPtr pDev)
984     WindowPtr win;
985     GrabPtr grab = pDev->deviceGrab.grab;
986     SpritePtr   pSprite = pDev->spriteInfo->sprite;
987     CursorPtr   pCursor;
989     if (syncEvents.playingEvents)
990         return;
991     if (grab)
992     {
993         if (grab->cursor)
994         {
995             ChangeToCursor(pDev, grab->cursor);
996             return;
997         }
998         if (IsParent(grab->window, pSprite->win))
999             win = pSprite->win;
1000         else
1001             win = grab->window;
1002     }
1003     else
1004         win = pSprite->win;
1005     for (; win; win = win->parent)
1006     {
1007         if (win->optional)
1008         {
1009             pCursor = WindowGetDeviceCursor(win, pDev);
1010             if (!pCursor && win->optional->cursor != NullCursor)
1011                 pCursor = win->optional->cursor;
1012             if (pCursor)
1013             {
1014                 ChangeToCursor(pDev, pCursor);
1015                 return;
1016             }
1017         }
1018     }
1022 /**
1023  * @param dev device which you want to know its current root window
1024  * @return root window where dev's sprite is located
1025  */
1026 WindowPtr
1027 GetCurrentRootWindow(DeviceIntPtr dev)
1029     return RootWindow(dev->spriteInfo->sprite);
1032 /**
1033  * @return window underneath the cursor sprite.
1034  */
1035 WindowPtr
1036 GetSpriteWindow(DeviceIntPtr pDev)
1038     return pDev->spriteInfo->sprite->win;
1041 /**
1042  * @return current sprite cursor.
1043  */
1044 CursorPtr
1045 GetSpriteCursor(DeviceIntPtr pDev)
1047     return pDev->spriteInfo->sprite->current;
1050 /**
1051  * Set x/y current sprite position in screen coordinates.
1052  */
1053 void
1054 GetSpritePosition(DeviceIntPtr pDev, int *px, int *py)
1056     SpritePtr pSprite = pDev->spriteInfo->sprite;
1057     *px = pSprite->hotPhys.x;
1058     *py = pSprite->hotPhys.y;
1061 #ifdef PANORAMIX
1062 int
1063 XineramaGetCursorScreen(DeviceIntPtr pDev)
1065     if(!noPanoramiXExtension) {
1066         return pDev->spriteInfo->sprite->screen->myNum;
1067     } else {
1068         return 0;
1069     }
1071 #endif /* PANORAMIX */
1073 #define TIMESLOP (5 * 60 * 1000) /* 5 minutes */
1075 static void
1076 MonthChangedOrBadTime(InternalEvent *ev)
1078     /* If the ddx/OS is careless about not processing timestamped events from
1079      * different sources in sorted order, then it's possible for time to go
1080      * backwards when it should not.  Here we ensure a decent time.
1081      */
1082     if ((currentTime.milliseconds - ev->any.time) > TIMESLOP)
1083         currentTime.months++;
1084     else
1085         ev->any.time = currentTime.milliseconds;
1088 static void
1089 NoticeTime(InternalEvent *ev)
1091     if (ev->any.time < currentTime.milliseconds)
1092         MonthChangedOrBadTime(ev);
1093     currentTime.milliseconds = ev->any.time;
1094     lastDeviceEventTime = currentTime;
1097 void
1098 NoticeEventTime(InternalEvent *ev)
1100     if (!syncEvents.playingEvents)
1101         NoticeTime(ev);
1104 /**************************************************************************
1105  *            The following procedures deal with synchronous events       *
1106  **************************************************************************/
1108 /**
1109  * EnqueueEvent is a device's processInputProc if a device is frozen.
1110  * Instead of delivering the events to the client, the event is tacked onto a
1111  * linked list for later delivery.
1112  */
1113 void
1114 EnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
1116     QdEventPtr  tail = *syncEvents.pendtail;
1117     QdEventPtr  qe;
1118     SpritePtr   pSprite = device->spriteInfo->sprite;
1119     int         eventlen;
1120     DeviceEvent *event = &ev->device_event;
1122     NoticeTime((InternalEvent*)event);
1124     /* Fix for key repeating bug. */
1125     if (device->key != NULL && device->key->xkbInfo != NULL &&
1126         event->type == ET_KeyRelease)
1127         AccessXCancelRepeatKey(device->key->xkbInfo, event->detail.key);
1129     if (DeviceEventCallback)
1130     {
1131         DeviceEventInfoRec eventinfo;
1133         /*  The RECORD spec says that the root window field of motion events
1134          *  must be valid.  At this point, it hasn't been filled in yet, so
1135          *  we do it here.  The long expression below is necessary to get
1136          *  the current root window; the apparently reasonable alternative
1137          *  GetCurrentRootWindow()->drawable.id doesn't give you the right
1138          *  answer on the first motion event after a screen change because
1139          *  the data that GetCurrentRootWindow relies on hasn't been
1140          *  updated yet.
1141          */
1142         if (ev->any.type == ET_Motion)
1143             ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
1145         eventinfo.event = ev;
1146         eventinfo.device = device;
1147         CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
1148     }
1150     if (event->type == ET_Motion)
1151     {
1152 #ifdef PANORAMIX
1153         if(!noPanoramiXExtension) {
1154             event->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
1155             event->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
1156         }
1157 #endif
1158         pSprite->hotPhys.x = event->root_x;
1159         pSprite->hotPhys.y = event->root_y;
1160         /* do motion compression, but not if from different devices */
1161         if (tail &&
1162             (tail->event->any.type == ET_Motion) &&
1163             (tail->device == device) &&
1164             (tail->pScreen == pSprite->hotPhys.pScreen))
1165         {
1166             DeviceEvent *tailev = &tail->event->device_event;
1167             tailev->root_x = pSprite->hotPhys.x;
1168             tailev->root_y = pSprite->hotPhys.y;
1169             tailev->time = event->time;
1170             tail->months = currentTime.months;
1171             return;
1172         }
1173     }
1175     eventlen = event->length;
1177     qe = malloc(sizeof(QdEventRec) + eventlen);
1178     if (!qe)
1179         return;
1180     qe->next = (QdEventPtr)NULL;
1181     qe->device = device;
1182     qe->pScreen = pSprite->hotPhys.pScreen;
1183     qe->months = currentTime.months;
1184     qe->event = (InternalEvent *)(qe + 1);
1185     memcpy(qe->event, event, eventlen);
1186     if (tail)
1187         syncEvents.pendtail = &tail->next;
1188     *syncEvents.pendtail = qe;
1191 /**
1192  * Run through the list of events queued up in syncEvents.
1193  * For each event do:
1194  * If the device for this event is not frozen anymore, take it and process it
1195  * as usually.
1196  * After that, check if there's any devices in the list that are not frozen.
1197  * If there is none, we're done. If there is at least one device that is not
1198  * frozen, then re-run from the beginning of the event queue.
1199  */
1200 static void
1201 PlayReleasedEvents(void)
1203     QdEventPtr *prev, qe;
1204     DeviceIntPtr dev;
1205     DeviceIntPtr pDev;
1207     prev = &syncEvents.pending;
1208     while ( (qe = *prev) )
1209     {
1210         if (!qe->device->deviceGrab.sync.frozen)
1211         {
1212             *prev = qe->next;
1213             pDev = qe->device;
1214             if (*syncEvents.pendtail == *prev)
1215                 syncEvents.pendtail = prev;
1216             if (qe->event->any.type == ET_Motion)
1217                 CheckVirtualMotion(pDev, qe, NullWindow);
1218             syncEvents.time.months = qe->months;
1219             syncEvents.time.milliseconds = qe->event->any.time;
1220 #ifdef PANORAMIX
1221            /* Translate back to the sprite screen since processInputProc
1222               will translate from sprite screen to screen 0 upon reentry
1223               to the DIX layer */
1224             if(!noPanoramiXExtension) {
1225                 DeviceEvent *ev = &qe->event->device_event;
1226                 switch(ev->type)
1227                 {
1228                     case ET_Motion:
1229                     case ET_ButtonPress:
1230                     case ET_ButtonRelease:
1231                     case ET_KeyPress:
1232                     case ET_KeyRelease:
1233                     case ET_ProximityIn:
1234                     case ET_ProximityOut:
1235                         ev->root_x += screenInfo.screens[0]->x -
1236                             pDev->spriteInfo->sprite->screen->x;
1237                         ev->root_y += screenInfo.screens[0]->y -
1238                             pDev->spriteInfo->sprite->screen->y;
1239                         break;
1240                     default:
1241                         break;
1242                 }
1244             }
1245 #endif
1246             (*qe->device->public.processInputProc)(qe->event, qe->device);
1247             free(qe);
1248             for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; dev = dev->next)
1249                 ;
1250             if (!dev)
1251                 break;
1252             /* Playing the event may have unfrozen another device. */
1253             /* So to play it safe, restart at the head of the queue */
1254             prev = &syncEvents.pending;
1255         }
1256         else
1257             prev = &qe->next;
1258     }
1261 /**
1262  * Freeze or thaw the given devices. The device's processing proc is
1263  * switched to either the real processing proc (in case of thawing) or an
1264  * enqueuing processing proc (usually EnqueueEvent()).
1265  *
1266  * @param dev The device to freeze/thaw
1267  * @param frozen True to freeze or false to thaw.
1268  */
1269 static void
1270 FreezeThaw(DeviceIntPtr dev, Bool frozen)
1272     dev->deviceGrab.sync.frozen = frozen;
1273     if (frozen)
1274         dev->public.processInputProc = dev->public.enqueueInputProc;
1275     else
1276         dev->public.processInputProc = dev->public.realInputProc;
1279 /**
1280  * Unfreeze devices and replay all events to the respective clients.
1281  *
1282  * ComputeFreezes takes the first event in the device's frozen event queue. It
1283  * runs up the sprite tree (spriteTrace) and searches for the window to replay
1284  * the events from. If it is found, it checks for passive grabs one down from
1285  * the window or delivers the events.
1286  */
1287 static void
1288 ComputeFreezes(void)
1290     DeviceIntPtr replayDev = syncEvents.replayDev;
1291     WindowPtr w;
1292     GrabPtr grab;
1293     DeviceIntPtr dev;
1295     for (dev = inputInfo.devices; dev; dev = dev->next)
1296         FreezeThaw(dev, dev->deviceGrab.sync.other ||
1297                 (dev->deviceGrab.sync.state >= FROZEN));
1298     if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
1299         return;
1300     syncEvents.playingEvents = TRUE;
1301     if (replayDev)
1302     {
1303         DeviceEvent* event = replayDev->deviceGrab.sync.event;
1305         syncEvents.replayDev = (DeviceIntPtr)NULL;
1307         w = XYToWindow(replayDev->spriteInfo->sprite,
1308                        event->root_x, event->root_y);
1309         if (!CheckDeviceGrabs(replayDev, event, syncEvents.replayWin))
1310         {
1311             if (replayDev->focus && !IsPointerEvent((InternalEvent*)event))
1312                 DeliverFocusedEvent(replayDev, (InternalEvent*)event, w);
1313             else
1314                 DeliverDeviceEvents(w, (InternalEvent*)event, NullGrab,
1315                                     NullWindow, replayDev);
1316         }
1317     }
1318     for (dev = inputInfo.devices; dev; dev = dev->next)
1319     {
1320         if (!dev->deviceGrab.sync.frozen)
1321         {
1322             PlayReleasedEvents();
1323             break;
1324         }
1325     }
1326     syncEvents.playingEvents = FALSE;
1327     for (dev = inputInfo.devices; dev; dev = dev->next)
1328     {
1329         if (DevHasCursor(dev))
1330         {
1331             /* the following may have been skipped during replay,
1332               so do it now */
1333             if ((grab = dev->deviceGrab.grab) && grab->confineTo)
1334             {
1335                 if (grab->confineTo->drawable.pScreen !=
1336                         dev->spriteInfo->sprite->hotPhys.pScreen)
1337                     dev->spriteInfo->sprite->hotPhys.x =
1338                         dev->spriteInfo->sprite->hotPhys.y = 0;
1339                 ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE);
1340             }
1341             else
1342                 ConfineCursorToWindow(dev,
1343                         dev->spriteInfo->sprite->hotPhys.pScreen->root,
1344                         TRUE, FALSE);
1345             PostNewCursor(dev);
1346         }
1347     }
1350 #ifdef RANDR
1351 void
1352 ScreenRestructured (ScreenPtr pScreen)
1354     GrabPtr grab;
1355     DeviceIntPtr pDev;
1357     for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
1358     {
1359         if (!IsFloating(pDev) && !DevHasCursor(pDev))
1360             continue;
1362         /* GrabDevice doesn't have a confineTo field, so we don't need to
1363          * worry about it. */
1364         if ((grab = pDev->deviceGrab.grab) && grab->confineTo)
1365         {
1366             if (grab->confineTo->drawable.pScreen
1367                     != pDev->spriteInfo->sprite->hotPhys.pScreen)
1368                 pDev->spriteInfo->sprite->hotPhys.x = pDev->spriteInfo->sprite->hotPhys.y = 0;
1369             ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
1370         }
1371         else
1372             ConfineCursorToWindow(pDev,
1373                     pDev->spriteInfo->sprite->hotPhys.pScreen->root,
1374                     TRUE, FALSE);
1375     }
1377 #endif
1379 static void
1380 CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
1382     GrabPtr grab = thisDev->deviceGrab.grab;
1383     DeviceIntPtr dev;
1385     if (thisMode == GrabModeSync)
1386         thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT;
1387     else
1388     {   /* free both if same client owns both */
1389         thisDev->deviceGrab.sync.state = THAWED;
1390         if (thisDev->deviceGrab.sync.other &&
1391             (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) ==
1392              CLIENT_BITS(grab->resource)))
1393             thisDev->deviceGrab.sync.other = NullGrab;
1394     }
1396     if (IsMaster(thisDev))
1397     {
1398         dev = GetPairedDevice(thisDev);
1399         if (otherMode == GrabModeSync)
1400             dev->deviceGrab.sync.other = grab;
1401         else
1402         {       /* free both if same client owns both */
1403             if (dev->deviceGrab.sync.other &&
1404                     (CLIENT_BITS(dev->deviceGrab.sync.other->resource) ==
1405                      CLIENT_BITS(grab->resource)))
1406                 dev->deviceGrab.sync.other = NullGrab;
1407         }
1408     }
1409     ComputeFreezes();
1412 /**
1413  * Save the device's master device id. This needs to be done
1414  * if a client directly grabs a slave device that is attached to a master. For
1415  * the duration of the grab, the device is detached, ungrabbing re-attaches it
1416  * though.
1417  *
1418  * We store the ID of the master device only in case the master disappears
1419  * while the device has a grab.
1420  */
1421 static void
1422 DetachFromMaster(DeviceIntPtr dev)
1424     if (IsFloating(dev))
1425         return;
1427     dev->saved_master_id = GetMaster(dev, MASTER_ATTACHED)->id;
1429     AttachDevice(NULL, dev, NULL);
1432 static void
1433 ReattachToOldMaster(DeviceIntPtr dev)
1435     DeviceIntPtr master = NULL;
1437     if (IsMaster(dev))
1438         return;
1440     dixLookupDevice(&master, dev->saved_master_id, serverClient, DixUseAccess);
1442     if (master)
1443     {
1444         AttachDevice(serverClient, dev, master);
1445         dev->saved_master_id = 0;
1446     }
1449 /**
1450  * Activate a pointer grab on the given device. A pointer grab will cause all
1451  * core pointer events of this device to be delivered to the grabbing client only.
1452  * No other device will send core events to the grab client while the grab is
1453  * on, but core events will be sent to other clients.
1454  * Can cause the cursor to change if a grab cursor is set.
1455  *
1456  * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab
1457  * is an implicit grab caused by a ButtonPress event.
1458  *
1459  * @param mouse The device to grab.
1460  * @param grab The grab structure, needs to be setup.
1461  * @param autoGrab True if the grab was caused by a button down event and not
1462  * explicitely by a client.
1463  */
1464 void
1465 ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
1466                     TimeStamp time, Bool autoGrab)
1468     GrabInfoPtr grabinfo = &mouse->deviceGrab;
1469     WindowPtr oldWin = (grabinfo->grab) ?
1470                         grabinfo->grab->window
1471                         : mouse->spriteInfo->sprite->win;
1472     Bool isPassive = autoGrab & ~ImplicitGrabMask;
1474     /* slave devices need to float for the duration of the grab. */
1475     if (grab->grabtype == GRABTYPE_XI2 &&
1476         !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse))
1477         DetachFromMaster(mouse);
1479     if (grab->confineTo)
1480     {
1481         if (grab->confineTo->drawable.pScreen
1482                 != mouse->spriteInfo->sprite->hotPhys.pScreen)
1483             mouse->spriteInfo->sprite->hotPhys.x =
1484                 mouse->spriteInfo->sprite->hotPhys.y = 0;
1485         ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE);
1486     }
1487     DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab);
1488     mouse->valuator->motionHintWindow = NullWindow;
1489     if (syncEvents.playingEvents)
1490         grabinfo->grabTime = syncEvents.time;
1491     else
1492         grabinfo->grabTime = time;
1493     if (grab->cursor)
1494         grab->cursor->refcnt++;
1495     grabinfo->activeGrab = *grab;
1496     grabinfo->grab = &grabinfo->activeGrab;
1497     grabinfo->fromPassiveGrab = isPassive;
1498     grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
1499     PostNewCursor(mouse);
1500     CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
1503 /**
1504  * Delete grab on given device, update the sprite.
1505  *
1506  * Extension devices are set up for ActivateKeyboardGrab().
1507  */
1508 void
1509 DeactivatePointerGrab(DeviceIntPtr mouse)
1511     GrabPtr grab = mouse->deviceGrab.grab;
1512     DeviceIntPtr dev;
1513     Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
1514                         mouse->deviceGrab.implicitGrab);
1516     mouse->valuator->motionHintWindow = NullWindow;
1517     mouse->deviceGrab.grab = NullGrab;
1518     mouse->deviceGrab.sync.state = NOT_GRABBED;
1519     mouse->deviceGrab.fromPassiveGrab = FALSE;
1521     for (dev = inputInfo.devices; dev; dev = dev->next)
1522     {
1523         if (dev->deviceGrab.sync.other == grab)
1524             dev->deviceGrab.sync.other = NullGrab;
1525     }
1526     DoEnterLeaveEvents(mouse, mouse->id, grab->window,
1527                        mouse->spriteInfo->sprite->win, NotifyUngrab);
1528     if (grab->confineTo)
1529         ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE);
1530     PostNewCursor(mouse);
1531     if (grab->cursor)
1532         FreeCursor(grab->cursor, (Cursor)0);
1534     if (!wasImplicit && grab->grabtype == GRABTYPE_XI2)
1535         ReattachToOldMaster(mouse);
1537     ComputeFreezes();
1540 /**
1541  * Activate a keyboard grab on the given device.
1542  *
1543  * Extension devices have ActivateKeyboardGrab() set as their grabbing proc.
1544  */
1545 void
1546 ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive)
1548     GrabInfoPtr grabinfo = &keybd->deviceGrab;
1549     WindowPtr oldWin;
1551     /* slave devices need to float for the duration of the grab. */
1552     if (grab->grabtype == GRABTYPE_XI2 &&
1553         !(passive & ImplicitGrabMask) &&
1554         !IsMaster(keybd))
1555         DetachFromMaster(keybd);
1557     if (grabinfo->grab)
1558         oldWin = grabinfo->grab->window;
1559     else if (keybd->focus)
1560         oldWin = keybd->focus->win;
1561     else
1562         oldWin = keybd->spriteInfo->sprite->win;
1563     if (oldWin == FollowKeyboardWin)
1564         oldWin = keybd->focus->win;
1565     if (keybd->valuator)
1566         keybd->valuator->motionHintWindow = NullWindow;
1567     DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
1568     if (syncEvents.playingEvents)
1569         grabinfo->grabTime = syncEvents.time;
1570     else
1571         grabinfo->grabTime = time;
1572     grabinfo->activeGrab = *grab;
1573     grabinfo->grab = &grabinfo->activeGrab;
1574     grabinfo->fromPassiveGrab = passive;
1575     grabinfo->implicitGrab = passive & ImplicitGrabMask;
1576     CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
1579 /**
1580  * Delete keyboard grab for the given device.
1581  */
1582 void
1583 DeactivateKeyboardGrab(DeviceIntPtr keybd)
1585     GrabPtr grab = keybd->deviceGrab.grab;
1586     DeviceIntPtr dev;
1587     WindowPtr focusWin = keybd->focus ? keybd->focus->win
1588                                            : keybd->spriteInfo->sprite->win;
1589     Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab &&
1590                         keybd->deviceGrab.implicitGrab);
1592     if (focusWin == FollowKeyboardWin)
1593         focusWin = inputInfo.keyboard->focus->win;
1594     if (keybd->valuator)
1595         keybd->valuator->motionHintWindow = NullWindow;
1596     keybd->deviceGrab.grab = NullGrab;
1597     keybd->deviceGrab.sync.state = NOT_GRABBED;
1598     keybd->deviceGrab.fromPassiveGrab = FALSE;
1600     for (dev = inputInfo.devices; dev; dev = dev->next)
1601     {
1602         if (dev->deviceGrab.sync.other == grab)
1603             dev->deviceGrab.sync.other = NullGrab;
1604     }
1605     DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
1607     if (!wasImplicit && grab->grabtype == GRABTYPE_XI2)
1608         ReattachToOldMaster(keybd);
1610     ComputeFreezes();
1613 void
1614 AllowSome(ClientPtr client,
1615           TimeStamp time,
1616           DeviceIntPtr thisDev,
1617           int newState)
1619     Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
1620     TimeStamp grabTime;
1621     DeviceIntPtr dev;
1622     GrabInfoPtr devgrabinfo,
1623                 grabinfo = &thisDev->deviceGrab;
1625     thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
1626     thisSynced = FALSE;
1627     otherGrabbed = FALSE;
1628     othersFrozen = FALSE;
1629     grabTime = grabinfo->grabTime;
1630     for (dev = inputInfo.devices; dev; dev = dev->next)
1631     {
1632         devgrabinfo = &dev->deviceGrab;
1634         if (dev == thisDev)
1635             continue;
1636         if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
1637         {
1638             if (!(thisGrabbed || otherGrabbed) ||
1639                 (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER))
1640                 grabTime = devgrabinfo->grabTime;
1641             otherGrabbed = TRUE;
1642             if (grabinfo->sync.other == devgrabinfo->grab)
1643                 thisSynced = TRUE;
1644             if (devgrabinfo->sync.state >= FROZEN)
1645                 othersFrozen = TRUE;
1646         }
1647     }
1648     if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced))
1649         return;
1650     if ((CompareTimeStamps(time, currentTime) == LATER) ||
1651         (CompareTimeStamps(time, grabTime) == EARLIER))
1652         return;
1653     switch (newState)
1654     {
1655         case THAWED:                   /* Async */
1656             if (thisGrabbed)
1657                 grabinfo->sync.state = THAWED;
1658             if (thisSynced)
1659                 grabinfo->sync.other = NullGrab;
1660             ComputeFreezes();
1661             break;
1662         case FREEZE_NEXT_EVENT:         /* Sync */
1663             if (thisGrabbed)
1664             {
1665                 grabinfo->sync.state = FREEZE_NEXT_EVENT;
1666                 if (thisSynced)
1667                     grabinfo->sync.other = NullGrab;
1668                 ComputeFreezes();
1669             }
1670             break;
1671         case THAWED_BOTH:               /* AsyncBoth */
1672             if (othersFrozen)
1673             {
1674                 for (dev = inputInfo.devices; dev; dev = dev->next)
1675                 {
1676                     devgrabinfo = &dev->deviceGrab;
1677                     if (devgrabinfo->grab
1678                             && SameClient(devgrabinfo->grab, client))
1679                         devgrabinfo->sync.state = THAWED;
1680                     if (devgrabinfo->sync.other &&
1681                             SameClient(devgrabinfo->sync.other, client))
1682                         devgrabinfo->sync.other = NullGrab;
1683                 }
1684                 ComputeFreezes();
1685             }
1686             break;
1687         case FREEZE_BOTH_NEXT_EVENT:    /* SyncBoth */
1688             if (othersFrozen)
1689             {
1690                 for (dev = inputInfo.devices; dev; dev = dev->next)
1691                 {
1692                     devgrabinfo = &dev->deviceGrab;
1693                     if (devgrabinfo->grab
1694                             && SameClient(devgrabinfo->grab, client))
1695                         devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT;
1696                     if (devgrabinfo->sync.other
1697                             && SameClient(devgrabinfo->sync.other, client))
1698                         devgrabinfo->sync.other = NullGrab;
1699                 }
1700                 ComputeFreezes();
1701             }
1702             break;
1703         case NOT_GRABBED:               /* Replay */
1704             if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT)
1705             {
1706                 if (thisSynced)
1707                     grabinfo->sync.other = NullGrab;
1708                 syncEvents.replayDev = thisDev;
1709                 syncEvents.replayWin = grabinfo->grab->window;
1710                 (*grabinfo->DeactivateGrab)(thisDev);
1711                 syncEvents.replayDev = (DeviceIntPtr)NULL;
1712             }
1713             break;
1714         case THAW_OTHERS:               /* AsyncOthers */
1715             if (othersFrozen)
1716             {
1717                 for (dev = inputInfo.devices; dev; dev = dev->next)
1718                 {
1719                     if (dev == thisDev)
1720                         continue;
1721                     devgrabinfo = &dev->deviceGrab;
1722                     if (devgrabinfo->grab
1723                             && SameClient(devgrabinfo->grab, client))
1724                         devgrabinfo->sync.state = THAWED;
1725                     if (devgrabinfo->sync.other
1726                             && SameClient(devgrabinfo->sync.other, client))
1727                         devgrabinfo->sync.other = NullGrab;
1728                 }
1729                 ComputeFreezes();
1730             }
1731             break;
1732     }
1735 /**
1736  * Server-side protocol handling for AllowEvents request.
1737  *
1738  * Release some events from a frozen device.
1739  */
1740 int
1741 ProcAllowEvents(ClientPtr client)
1743     TimeStamp           time;
1744     DeviceIntPtr        mouse = NULL;
1745     DeviceIntPtr        keybd = NULL;
1746     REQUEST(xAllowEventsReq);
1748     REQUEST_SIZE_MATCH(xAllowEventsReq);
1749     time = ClientTimeToServerTime(stuff->time);
1751     mouse = PickPointer(client);
1752     keybd = PickKeyboard(client);
1754     switch (stuff->mode)
1755     {
1756         case ReplayPointer:
1757             AllowSome(client, time, mouse, NOT_GRABBED);
1758             break;
1759         case SyncPointer:
1760             AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
1761             break;
1762         case AsyncPointer:
1763             AllowSome(client, time, mouse, THAWED);
1764             break;
1765         case ReplayKeyboard:
1766             AllowSome(client, time, keybd, NOT_GRABBED);
1767             break;
1768         case SyncKeyboard:
1769             AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
1770             break;
1771         case AsyncKeyboard:
1772             AllowSome(client, time, keybd, THAWED);
1773             break;
1774         case SyncBoth:
1775             AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
1776             break;
1777         case AsyncBoth:
1778             AllowSome(client, time, keybd, THAWED_BOTH);
1779             break;
1780         default:
1781             client->errorValue = stuff->mode;
1782             return BadValue;
1783     }
1784     return Success;
1787 /**
1788  * Deactivate grabs from any device that has been grabbed by the client.
1789  */
1790 void
1791 ReleaseActiveGrabs(ClientPtr client)
1793     DeviceIntPtr dev;
1794     Bool    done;
1796     /* XXX CloseDownClient should remove passive grabs before
1797      * releasing active grabs.
1798      */
1799     do {
1800         done = TRUE;
1801         for (dev = inputInfo.devices; dev; dev = dev->next)
1802         {
1803             if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
1804             {
1805                 (*dev->deviceGrab.DeactivateGrab)(dev);
1806                 done = FALSE;
1807             }
1808         }
1809     } while (!done);
1812 /**************************************************************************
1813  *            The following procedures deal with delivering events        *
1814  **************************************************************************/
1816 /**
1817  * Deliver the given events to the given client.
1818  *
1819  * More than one event may be delivered at a time. This is the case with
1820  * DeviceMotionNotifies which may be followed by DeviceValuator events.
1821  *
1822  * TryClientEvents() is the last station before actually writing the events to
1823  * the socket. Anything that is not filtered here, will get delivered to the
1824  * client.
1825  * An event is only delivered if
1826  *   - mask and filter match up.
1827  *   - no other client has a grab on the device that caused the event.
1828  *
1829  *
1830  * @param client The target client to deliver to.
1831  * @param dev The device the event came from. May be NULL.
1832  * @param pEvents The events to be delivered.
1833  * @param count Number of elements in pEvents.
1834  * @param mask Event mask as set by the window.
1835  * @param filter Mask based on event type.
1836  * @param grab Possible grab on the device that caused the event.
1837  *
1838  * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
1839  * client.
1840  */
1841 int
1842 TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
1843                  int count, Mask mask, Mask filter, GrabPtr grab)
1845     int type;
1847 #ifdef DEBUG_EVENTS
1848     ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s",
1849            pEvents->u.u.type, pEvents->u.u.detail, mask,
1850            client ? client->index : -1,
1851            (client && client->clientGone) ? " (gone)" : "");
1852 #endif
1854     if (!client || client == serverClient || client->clientGone) {
1855 #ifdef DEBUG_EVENTS
1856         ErrorF(" not delivered to fake/dead client\n");
1857 #endif
1858         return 0;
1859     }
1861     if (filter != CantBeFiltered && !(mask & filter))
1862     {
1863  #ifdef DEBUG_EVENTS
1864         ErrorF(" filtered\n");
1865  #endif
1866         return 0;
1867     }
1869     if (grab && !SameClient(grab, client))
1870     {
1871 #ifdef DEBUG_EVENTS
1872         ErrorF(" not delivered due to grab\n");
1873 #endif
1874         return -1; /* don't send, but notify caller */
1875     }
1877     type = pEvents->u.u.type;
1878     if (type == MotionNotify)
1879     {
1880         if (mask & PointerMotionHintMask)
1881         {
1882             if (WID(dev->valuator->motionHintWindow) ==
1883                     pEvents->u.keyButtonPointer.event)
1884             {
1885 #ifdef DEBUG_EVENTS
1886                 ErrorF("[dix] \n");
1887                 ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
1888 #endif
1889                 return 1; /* don't send, but pretend we did */
1890             }
1891             pEvents->u.u.detail = NotifyHint;
1892         }
1893         else
1894         {
1895             pEvents->u.u.detail = NotifyNormal;
1896         }
1897     }
1898     else if (type == DeviceMotionNotify)
1899     {
1900         if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer*)pEvents,
1901                                             mask) != 0)
1902             return 1;
1903     } else if (type == KeyPress)
1904     {
1905         if (EventIsKeyRepeat(pEvents))
1906         {
1907             if (!_XkbWantsDetectableAutoRepeat(client))
1908             {
1909                 xEvent release = *pEvents;
1910                 release.u.u.type = KeyRelease;
1911                 WriteEventsToClient(client, 1, &release);
1912 #ifdef DEBUG_EVENTS
1913                 ErrorF(" (plus fake core release for repeat)");
1914 #endif
1915             } else
1916             {
1917 #ifdef DEBUG_EVENTS
1918                 ErrorF(" (detectable autorepeat for core)");
1919 #endif
1920             }
1921         }
1923     } else if (type == DeviceKeyPress)
1924     {
1925         if (EventIsKeyRepeat(pEvents))
1926         {
1927             if (!_XkbWantsDetectableAutoRepeat(client))
1928             {
1929                 deviceKeyButtonPointer release = *(deviceKeyButtonPointer *)pEvents;
1930                 release.type = DeviceKeyRelease;
1931 #ifdef DEBUG_EVENTS
1932                 ErrorF(" (plus fake xi1 release for repeat)");
1933 #endif
1934                 WriteEventsToClient(client, 1, (xEvent *) &release);
1935             }
1936             else {
1937 #ifdef DEBUG_EVENTS
1938                 ErrorF(" (detectable autorepeat for core)");
1939 #endif
1940             }
1941         }
1942     }
1944     if (BitIsOn(criticalEvents, type))
1945     {
1946         if (client->smart_priority < SMART_MAX_PRIORITY)
1947             client->smart_priority++;
1948         SetCriticalOutputPending();
1949     }
1951     WriteEventsToClient(client, count, pEvents);
1952 #ifdef DEBUG_EVENTS
1953     ErrorF("[dix]  delivered\n");
1954 #endif
1955     return 1;
1958 static BOOL
1959 ActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win,
1960                      xEvent *event, Mask deliveryMask)
1962     GrabRec tempGrab;
1963     OtherInputMasks *inputMasks;
1964     CARD8 type = event->u.u.type;
1965     GrabType grabtype;
1967     if (type == ButtonPress)
1968         grabtype = GRABTYPE_CORE;
1969     else if (type == DeviceButtonPress)
1970         grabtype = GRABTYPE_XI;
1971     else if ((type = xi2_get_type(event)) == XI_ButtonPress)
1972         grabtype = GRABTYPE_XI2;
1973     else
1974         return FALSE;
1976     memset(&tempGrab, 0, sizeof(GrabRec));
1977     tempGrab.next = NULL;
1978     tempGrab.device = dev;
1979     tempGrab.resource = client->clientAsMask;
1980     tempGrab.window = win;
1981     tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
1982     tempGrab.eventMask = deliveryMask;
1983     tempGrab.keyboardMode = GrabModeAsync;
1984     tempGrab.pointerMode = GrabModeAsync;
1985     tempGrab.confineTo = NullWindow;
1986     tempGrab.cursor = NullCursor;
1987     tempGrab.type = type;
1988     tempGrab.grabtype = grabtype;
1990     /* get the XI and XI2 device mask */
1991     inputMasks = wOtherInputMasks(win);
1992     tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id]: 0;
1994     if (inputMasks)
1995         memcpy(tempGrab.xi2mask, inputMasks->xi2mask,
1996                sizeof(tempGrab.xi2mask));
1998     (*dev->deviceGrab.ActivateGrab)(dev, &tempGrab,
1999                                     currentTime, TRUE | ImplicitGrabMask);
2000     return TRUE;
2003 enum EventDeliveryState {
2004     EVENT_DELIVERED,     /**< Event has been delivered to a client  */
2005     EVENT_NOT_DELIVERED, /**< Event was not delivered to any client */
2006     EVENT_SKIP,          /**< Event can be discarded by the caller  */
2007     EVENT_REJECTED,      /**< Event was rejected for delivery to the client */
2008 };
2010 /**
2011  * Attempt event delivery to the client owning the window.
2012  */
2013 static enum EventDeliveryState
2014 DeliverToWindowOwner(DeviceIntPtr dev, WindowPtr win,
2015                      xEvent *events, int count, Mask filter,
2016                      GrabPtr grab)
2018     /* if nobody ever wants to see this event, skip some work */
2019     if (filter != CantBeFiltered &&
2020             !((wOtherEventMasks(win)|win->eventMask) & filter))
2021         return EVENT_SKIP;
2023     if (IsInterferingGrab(wClient(win), dev, events))
2024         return EVENT_SKIP;
2026     if (!XaceHook(XACE_RECEIVE_ACCESS, wClient(win), win, events, count))
2027     {
2028         int attempt = TryClientEvents(wClient(win), dev, events,
2029                                       count, win->eventMask,
2030                                       filter, grab);
2031         if (attempt > 0)
2032             return EVENT_DELIVERED;
2033         if (attempt < 0)
2034             return EVENT_REJECTED;
2035     }
2037     return EVENT_NOT_DELIVERED;
2041 /**
2042  * Get the list of clients that should be tried for event delivery on the
2043  * given window.
2044  *
2045  * @return 1 if the client list should be traversed, zero if the event
2046  * should be skipped.
2047  */
2048 static Bool
2049 GetClientsForDelivery(DeviceIntPtr dev, WindowPtr win,
2050                       xEvent *events, Mask filter, InputClients **clients)
2052     int rc = 0;
2054     if (core_get_type(events) != 0)
2055         *clients = (InputClients *)wOtherClients(win);
2056     else if (xi2_get_type(events) != 0)
2057     {
2058         OtherInputMasks *inputMasks = wOtherInputMasks(win);
2059         /* Has any client selected for the event? */
2060         if (!GetWindowXI2Mask(dev, win, events))
2061             goto out;
2062         *clients = inputMasks->inputClients;
2063     } else {
2064         OtherInputMasks *inputMasks = wOtherInputMasks(win);
2065         /* Has any client selected for the event? */
2066         if (!inputMasks ||
2067             !(inputMasks->inputEvents[dev->id] & filter))
2068             goto out;
2070         *clients = inputMasks->inputClients;
2071     }
2073     rc = 1;
2074 out:
2075     return rc;
2078 /**
2079  * Try delivery on each client in inputclients, provided the event mask
2080  * accepts it and there is no interfering core grab..
2081  */
2082 static enum EventDeliveryState
2083 DeliverEventToInputClients(DeviceIntPtr dev, InputClients *inputclients,
2084                            WindowPtr win, xEvent *events,
2085                            int count, Mask filter, GrabPtr grab,
2086                            ClientPtr *client_return, Mask *mask_return)
2088     int attempt;
2089     enum EventDeliveryState rc = EVENT_NOT_DELIVERED;
2091     for (; inputclients; inputclients = inputclients->next)
2092     {
2093         Mask mask;
2094         ClientPtr client = rClient(inputclients);
2096         if (IsInterferingGrab(client, dev, events))
2097             continue;
2099         mask = GetEventMask(dev, events, inputclients);
2101         if (XaceHook(XACE_RECEIVE_ACCESS, client, win,
2102                     events, count))
2103             /* do nothing */;
2104         else if ( (attempt = TryClientEvents(client, dev,
2105                         events, count,
2106                         mask, filter, grab)) )
2107         {
2108             if (attempt > 0)
2109             {
2110                 rc = EVENT_DELIVERED;
2111                 *client_return = client;
2112                 *mask_return = mask;
2113                 /* Success overrides non-success, so if we've been
2114                  * successful on one client, return that */
2115             } else if (rc == EVENT_NOT_DELIVERED)
2116                 rc = EVENT_REJECTED;
2117         }
2118     }
2120     return rc;
2124 /**
2125  * Deliver events to clients registered on the window.
2126  *
2127  * @param client_return On successful delivery, set to the recipient.
2128  * @param mask_return On successful delivery, set to the recipient's event
2129  * mask for this event.
2130  */
2131 static enum EventDeliveryState
2132 DeliverEventToWindowMask(DeviceIntPtr dev, WindowPtr win, xEvent *events,
2133                          int count, Mask filter, GrabPtr grab,
2134                          ClientPtr *client_return, Mask *mask_return)
2136     InputClients *clients;
2138     if (!GetClientsForDelivery(dev, win, events, filter, &clients))
2139         return EVENT_SKIP;
2141     return DeliverEventToInputClients(dev, clients, win, events, count, filter,
2142                                       grab, client_return, mask_return);
2147 /**
2148  * Deliver events to a window. At this point, we do not yet know if the event
2149  * actually needs to be delivered. May activate a grab if the event is a
2150  * button press.
2151  *
2152  * Core events are always delivered to the window owner. If the filter is
2153  * something other than CantBeFiltered, the event is also delivered to other
2154  * clients with the matching mask on the window.
2155  *
2156  * More than one event may be delivered at a time. This is the case with
2157  * DeviceMotionNotifies which may be followed by DeviceValuator events.
2158  *
2159  * @param pWin The window that would get the event.
2160  * @param pEvents The events to be delivered.
2161  * @param count Number of elements in pEvents.
2162  * @param filter Mask based on event type.
2163  * @param grab Possible grab on the device that caused the event.
2164  *
2165  * @return a positive number if at least one successful delivery has been
2166  * made, 0 if no events were delivered, or a negative number if the event
2167  * has not been delivered _and_ rejected by at least one client.
2168  */
2169 int
2170 DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
2171         *pEvents, int count, Mask filter, GrabPtr grab)
2173     int deliveries = 0, nondeliveries = 0;
2174     ClientPtr client = NullClient;
2175     Mask deliveryMask = 0; /* If a grab occurs due to a button press, then
2176                               this mask is the mask of the grab. */
2177     int type = pEvents->u.u.type;
2179     /* Deliver to window owner */
2180     if ((filter == CantBeFiltered) || core_get_type(pEvents) != 0)
2181     {
2182         enum EventDeliveryState rc;
2184         rc = DeliverToWindowOwner(pDev, pWin, pEvents, count, filter, grab);
2186         switch(rc)
2187         {
2188             case EVENT_SKIP:
2189                 return 0;
2190             case EVENT_REJECTED:
2191                 nondeliveries--;
2192                 break;
2193             case EVENT_DELIVERED:
2194                 /* We delivered to the owner, with our event mask */
2195                 deliveries++;
2196                 client = wClient(pWin);
2197                 deliveryMask = pWin->eventMask;
2198                 break;
2199             case EVENT_NOT_DELIVERED:
2200                 break;
2201         }
2202     }
2204     /* CantBeFiltered means only window owner gets the event */
2205     if (filter != CantBeFiltered)
2206     {
2207         enum EventDeliveryState rc;
2209         rc = DeliverEventToWindowMask(pDev, pWin, pEvents, count, filter,
2210                                       grab, &client, &deliveryMask);
2212         switch(rc)
2213         {
2214             case EVENT_SKIP:
2215                 return 0;
2216             case EVENT_REJECTED:
2217                 nondeliveries--;
2218                 break;
2219             case EVENT_DELIVERED:
2220                 deliveries++;
2221                 break;
2222             case EVENT_NOT_DELIVERED:
2223                 break;
2224         }
2225     }
2227     if (deliveries)
2228     {
2229         /*
2230          * Note that since core events are delivered first, an implicit grab may
2231          * be activated on a core grab, stopping the XI events.
2232          */
2233         if (!grab && ActivateImplicitGrab(pDev, client, pWin, pEvents, deliveryMask))
2234             /* grab activated */;
2235         else if (type == MotionNotify)
2236             pDev->valuator->motionHintWindow = pWin;
2237         else if (type == DeviceMotionNotify || type == DeviceButtonPress)
2238                 CheckDeviceGrabAndHintWindow (pWin, type,
2239                                               (deviceKeyButtonPointer*) pEvents,
2240                                               grab, client, deliveryMask);
2241         return deliveries;
2242     }
2243     return nondeliveries;
2246 void
2247 DeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
2249     GrabPtr grab = device->deviceGrab.grab;
2251     if (grab)
2252         DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE);
2253     else { /* deliver to all root windows */
2254         xEvent *xi;
2255         int i;
2256         int filter;
2258         i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi);
2259         if (i != Success)
2260         {
2261             ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n",
2262                     __func__, device->name, i);
2263             return;
2264         }
2266         filter = GetEventFilter(device, xi);
2268         for (i = 0; i < screenInfo.numScreens; i++)
2269             DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1,
2270                                   filter, NullGrab);
2271         free(xi);
2272     }
2275 /* If the event goes to dontClient, don't send it and return 0.  if
2276    send works,  return 1 or if send didn't work, return 2.
2277    Only works for core events.
2278 */
2280 #ifdef PANORAMIX
2281 static int
2282 XineramaTryClientEventsResult(
2283     ClientPtr client,
2284     GrabPtr grab,
2285     Mask mask,
2286     Mask filter
2287 ){
2288     if ((client) && (client != serverClient) && (!client->clientGone) &&
2289         ((filter == CantBeFiltered) || (mask & filter)))
2290     {
2291         if (grab && !SameClient(grab, client)) return -1;
2292         else return 1;
2293     }
2294     return 0;
2296 #endif
2298 /**
2299  * Try to deliver events to the interested parties.
2300  *
2301  * @param pWin The window that would get the event.
2302  * @param pEvents The events to be delivered.
2303  * @param count Number of elements in pEvents.
2304  * @param filter Mask based on event type.
2305  * @param dontClient Don't deliver to the dontClient.
2306  */
2307 int
2308 MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
2309                            int count, Mask filter, ClientPtr dontClient)
2311     OtherClients *other;
2314     if (pWin->eventMask & filter)
2315     {
2316         if (wClient(pWin) == dontClient)
2317             return 0;
2318 #ifdef PANORAMIX
2319         if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2320             return XineramaTryClientEventsResult(
2321                         wClient(pWin), NullGrab, pWin->eventMask, filter);
2322 #endif
2323         if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
2324             return 1; /* don't send, but pretend we did */
2325         return TryClientEvents(wClient(pWin), NULL, pEvents, count,
2326                                pWin->eventMask, filter, NullGrab);
2327     }
2328     for (other = wOtherClients(pWin); other; other = other->next)
2329     {
2330         if (other->mask & filter)
2331         {
2332             if (SameClient(other, dontClient))
2333                 return 0;
2334 #ifdef PANORAMIX
2335             if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2336               return XineramaTryClientEventsResult(
2337                         rClient(other), NullGrab, other->mask, filter);
2338 #endif
2339             if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents,
2340                          count))
2341                 return 1; /* don't send, but pretend we did */
2342             return TryClientEvents(rClient(other), NULL, pEvents, count,
2343                                    other->mask, filter, NullGrab);
2344         }
2345     }
2346     return 2;
2349 static Window FindChildForEvent(SpritePtr pSprite, WindowPtr event)
2351     WindowPtr w = DeepestSpriteWin(pSprite);
2352     Window child = None;
2354     /* If the search ends up past the root should the child field be
2355        set to none or should the value in the argument be passed
2356        through. It probably doesn't matter since everyone calls
2357        this function with child == None anyway. */
2358     while (w)
2359     {
2360         /* If the source window is same as event window, child should be
2361            none.  Don't bother going all all the way back to the root. */
2363         if (w == event)
2364         {
2365             child = None;
2366             break;
2367         }
2369         if (w->parent == event)
2370         {
2371             child = w->drawable.id;
2372             break;
2373         }
2374         w = w->parent;
2375     }
2376     return child;
2379 /**
2380  * Adjust event fields to comply with the window properties.
2381  *
2382  * @param xE Event to be modified in place
2383  * @param pWin The window to get the information from.
2384  * @param child Child window setting for event (if applicable)
2385  * @param calcChild If True, calculate the child window.
2386  */
2387 void
2388 FixUpEventFromWindow(
2389     SpritePtr pSprite,
2390     xEvent *xE,
2391     WindowPtr pWin,
2392     Window child,
2393     Bool calcChild)
2395     int evtype;
2397     if (calcChild)
2398         child = FindChildForEvent(pSprite, pWin);
2400     if ((evtype = xi2_get_type(xE)))
2401     {
2402         xXIDeviceEvent* event = (xXIDeviceEvent*)xE;
2404         switch (evtype)
2405         {
2406             case XI_RawKeyPress:
2407             case XI_RawKeyRelease:
2408             case XI_RawButtonPress:
2409             case XI_RawButtonRelease:
2410             case XI_RawMotion:
2411             case XI_DeviceChanged:
2412             case XI_HierarchyChanged:
2413             case XI_PropertyEvent:
2414                 return;
2415             default:
2416                 break;
2417         }
2419         event->root = RootWindow(pSprite)->drawable.id;
2420         event->event = pWin->drawable.id;
2421         if (pSprite->hot.pScreen == pWin->drawable.pScreen)
2422         {
2423             event->event_x = event->root_x - FP1616(pWin->drawable.x, 0);
2424             event->event_y = event->root_y - FP1616(pWin->drawable.y, 0);
2425             event->child = child;
2426         } else
2427         {
2428             event->event_x = 0;
2429             event->event_y = 0;
2430             event->child = None;
2431         }
2433         if (event->evtype == XI_Enter || event->evtype == XI_Leave ||
2434             event->evtype == XI_FocusIn || event->evtype == XI_FocusOut)
2435             ((xXIEnterEvent*)event)->same_screen =
2436                 (pSprite->hot.pScreen == pWin->drawable.pScreen);
2438     } else
2439     {
2440         XE_KBPTR.root = RootWindow(pSprite)->drawable.id;
2441         XE_KBPTR.event = pWin->drawable.id;
2442         if (pSprite->hot.pScreen == pWin->drawable.pScreen)
2443         {
2444             XE_KBPTR.sameScreen = xTrue;
2445             XE_KBPTR.child = child;
2446             XE_KBPTR.eventX =
2447                 XE_KBPTR.rootX - pWin->drawable.x;
2448             XE_KBPTR.eventY =
2449                 XE_KBPTR.rootY - pWin->drawable.y;
2450         }
2451         else
2452         {
2453             XE_KBPTR.sameScreen = xFalse;
2454             XE_KBPTR.child = None;
2455             XE_KBPTR.eventX = 0;
2456             XE_KBPTR.eventY = 0;
2457         }
2458     }
2461 /**
2462  * Check if a given event is deliverable at all on a given window.
2463  *
2464  * This function only checks if any client wants it, not for a specific
2465  * client.
2466  *
2467  * @param[in] dev The device this event is being sent for.
2468  * @param[in] event The event that is to be sent.
2469  * @param[in] win The current event window.
2470  *
2471  * @return Bitmask of ::EVENT_XI2_MASK, ::EVENT_XI1_MASK, ::EVENT_CORE_MASK, and
2472  *         ::EVENT_DONT_PROPAGATE_MASK.
2473  */
2474 int
2475 EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win)
2477     int rc = 0;
2478     int filter = 0;
2479     int type;
2480     OtherInputMasks *inputMasks = wOtherInputMasks(win);
2481     xEvent ev;
2483     /* XXX: this makes me gag */
2484     type = GetXI2Type(event);
2485     ev.u.u.type = GenericEvent; /* GetEventFilter only cares about type and evtype*/
2486     ((xGenericEvent*)&ev)->extension = IReqCode;
2487     ((xGenericEvent*)&ev)->evtype = type;
2488     filter = GetEventFilter(dev, &ev);
2489     if (type && inputMasks &&
2490         ((inputMasks->xi2mask[XIAllDevices][type/8] & filter) ||
2491          ((inputMasks->xi2mask[XIAllMasterDevices][type/8] & filter) && IsMaster(dev)) ||
2492          (inputMasks->xi2mask[dev->id][type/8] & filter)))
2493         rc |= EVENT_XI2_MASK;
2495     type = GetXIType(event);
2496     ev.u.u.type = type;
2497     filter = GetEventFilter(dev, &ev);
2499     /* Check for XI mask */
2500     if (type && inputMasks &&
2501         (inputMasks->deliverableEvents[dev->id] & filter) &&
2502         (inputMasks->inputEvents[dev->id] & filter))
2503         rc |= EVENT_XI1_MASK;
2505     /* Check for XI DontPropagate mask */
2506     if (type && inputMasks &&
2507         (inputMasks->dontPropagateMask[dev->id] & filter))
2508         rc |= EVENT_DONT_PROPAGATE_MASK;
2510     /* Check for core mask */
2511     type = GetCoreType(event);
2512     if (type && (win->deliverableEvents & filter) &&
2513         ((wOtherEventMasks(win) | win->eventMask) & filter))
2514         rc |= EVENT_CORE_MASK;
2516     /* Check for core DontPropagate mask */
2517     if (type && (filter & wDontPropagateMask(win)))
2518         rc |= EVENT_DONT_PROPAGATE_MASK;
2520     return rc;
2523 /**
2524  * Deliver events caused by input devices.
2525  *
2526  * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is
2527  * called directly from the processInputProc.
2528  * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call
2529  * DeliverDeviceEvents.
2530  * For focused events, DeliverFocusedEvent is called first, and _may_ call
2531  * DeliverDeviceEvents.
2532  *
2533  * @param pWin Window to deliver event to.
2534  * @param event The events to deliver, not yet in wire format.
2535  * @param grab Possible grab on a device.
2536  * @param stopAt Don't recurse up to the root window.
2537  * @param dev The device that is responsible for the event.
2538  *
2539  * @see DeliverGrabbedEvent
2540  * @see DeliverFocusedEvent
2541  */
2542 int
2543 DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
2544                     WindowPtr stopAt, DeviceIntPtr dev)
2546     SpritePtr pSprite = dev->spriteInfo->sprite;
2547     Window child = None;
2548     Mask filter;
2549     int deliveries = 0;
2550     xEvent *xE = NULL, *core = NULL;
2551     int rc, mask, count = 0;
2553     verify_internal_event(event);
2555     while (pWin)
2556     {
2557         if ((mask = EventIsDeliverable(dev, event, pWin)))
2558         {
2559             /* XI2 events first */
2560             if (mask & EVENT_XI2_MASK)
2561             {
2562                 xEvent *xi2 = NULL;
2563                 rc = EventToXI2(event, &xi2);
2564                 if (rc == Success)
2565                 {
2566                     /* XXX: XACE */
2567                     filter = GetEventFilter(dev, xi2);
2568                     FixUpEventFromWindow(pSprite, xi2, pWin, child, FALSE);
2569                     deliveries = DeliverEventsToWindow(dev, pWin, xi2, 1,
2570                                                        filter, grab);
2571                     free(xi2);
2572                     if (deliveries > 0)
2573                         goto unwind;
2574                 } else if (rc != BadMatch)
2575                     ErrorF("[dix] %s: XI2 conversion failed in DDE (%d).\n",
2576                             dev->name, rc);
2577             }
2579             /* XI events */
2580             if (mask & EVENT_XI1_MASK)
2581             {
2582                 rc = EventToXI(event, &xE, &count);
2583                 if (rc == Success) {
2584                     if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count) == Success) {
2585                         filter = GetEventFilter(dev, xE);
2586                         FixUpEventFromWindow(pSprite, xE, pWin, child, FALSE);
2587                         deliveries = DeliverEventsToWindow(dev, pWin, xE, count,
2588                                                            filter, grab);
2589                         if (deliveries > 0)
2590                             goto unwind;
2591                     }
2592                 } else if (rc != BadMatch)
2593                     ErrorF("[dix] %s: XI conversion failed in DDE (%d, %d). Skipping delivery.\n",
2594                             dev->name, event->any.type, rc);
2595             }
2597             /* Core event */
2598             if ((mask & EVENT_CORE_MASK) && IsMaster(dev) && dev->coreEvents)
2599             {
2600                 rc = EventToCore(event, &core, &count);
2601                 if (rc == Success) {
2602                     if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, core, count) == Success) {
2603                         filter = GetEventFilter(dev, core);
2604                         FixUpEventFromWindow(pSprite, core, pWin, child, FALSE);
2605                         deliveries = DeliverEventsToWindow(dev, pWin, core,
2606                                                            count, filter, grab);
2607                         if (deliveries > 0)
2608                             goto unwind;
2609                     }
2610                 } else if (rc != BadMatch)
2611                         ErrorF("[dix] %s: Core conversion failed in DDE (%d, %d).\n",
2612                                 dev->name, event->any.type, rc);
2613             }
2615             if ((deliveries < 0) || (pWin == stopAt) ||
2616                 (mask & EVENT_DONT_PROPAGATE_MASK))
2617             {
2618                 deliveries = 0;
2619                 goto unwind;
2620             }
2621         }
2623         child = pWin->drawable.id;
2624         pWin = pWin->parent;
2625     }
2627 unwind:
2628     free(core);
2629     free(xE);
2630     return deliveries;
2633 /**
2634  * Deliver event to a window and it's immediate parent. Used for most window
2635  * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
2636  * propagate up the tree or extension events
2637  *
2638  * In case of a ReparentNotify event, the event will be delivered to the
2639  * otherParent as well.
2640  *
2641  * @param pWin Window to deliver events to.
2642  * @param xE Events to deliver.
2643  * @param count number of events in xE.
2644  * @param otherParent Used for ReparentNotify events.
2645  */
2646 int
2647 DeliverEvents(WindowPtr pWin, xEvent *xE, int count,
2648               WindowPtr otherParent)
2650     DeviceIntRec dummy;
2651     int     deliveries;
2653 #ifdef PANORAMIX
2654     if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2655         return count;
2656 #endif
2658     if (!count)
2659         return 0;
2661     dummy.id = XIAllDevices;
2663     switch (xE->u.u.type)
2664     {
2665         case DestroyNotify:
2666         case UnmapNotify:
2667         case MapNotify:
2668         case MapRequest:
2669         case ReparentNotify:
2670         case ConfigureNotify:
2671         case ConfigureRequest:
2672         case GravityNotify:
2673         case CirculateNotify:
2674         case CirculateRequest:
2675             xE->u.destroyNotify.event = pWin->drawable.id;
2676             break;
2677     }
2679     switch (xE->u.u.type)
2680     {
2681         case DestroyNotify:
2682         case UnmapNotify:
2683         case MapNotify:
2684         case ReparentNotify:
2685         case ConfigureNotify:
2686         case GravityNotify:
2687         case CirculateNotify:
2688             break;
2689         default:
2690         {
2691             Mask filter;
2692             filter = GetEventFilter(&dummy, xE);
2693             return DeliverEventsToWindow(&dummy, pWin, xE, count, filter,
2694                                          NullGrab);
2695         }
2696     }
2698     deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count,
2699                                        StructureNotifyMask, NullGrab);
2700     if (pWin->parent)
2701     {
2702         xE->u.destroyNotify.event = pWin->parent->drawable.id;
2703         deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count,
2704                                             SubstructureNotifyMask, NullGrab);
2705         if (xE->u.u.type == ReparentNotify)
2706         {
2707             xE->u.destroyNotify.event = otherParent->drawable.id;
2708             deliveries += DeliverEventsToWindow(&dummy,
2709                     otherParent, xE, count, SubstructureNotifyMask,
2710                                                 NullGrab);
2711         }
2712     }
2713     return deliveries;
2717 static Bool
2718 PointInBorderSize(WindowPtr pWin, int x, int y)
2720     BoxRec box;
2722     if(RegionContainsPoint(&pWin->borderSize, x, y, &box))
2723         return TRUE;
2725 #ifdef PANORAMIX
2726     if(!noPanoramiXExtension &&
2727             XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
2728         SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
2729         int i;
2731         FOR_NSCREENS_FORWARD_SKIP(i) {
2732            if(RegionContainsPoint(&pSprite->windows[i]->borderSize,
2733                                   x + screenInfo.screens[0]->x - screenInfo.screens[i]->x,
2734                                   y + screenInfo.screens[0]->y - screenInfo.screens[i]->y,
2735                                   &box))
2736                 return TRUE;
2737         }
2738     }
2739 #endif
2740     return FALSE;
2743 /**
2744  * Traversed from the root window to the window at the position x/y. While
2745  * traversing, it sets up the traversal history in the spriteTrace array.
2746  * After completing, the spriteTrace history is set in the following way:
2747  *   spriteTrace[0] ... root window
2748  *   spriteTrace[1] ... top level window that encloses x/y
2749  *       ...
2750  *   spriteTrace[spriteTraceGood - 1] ... window at x/y
2751  *
2752  * @returns the window at the given coordinates.
2753  */
2754 WindowPtr
2755 XYToWindow(SpritePtr pSprite, int x, int y)
2757     WindowPtr  pWin;
2758     BoxRec              box;
2760     pSprite->spriteTraceGood = 1;       /* root window still there */
2761     pWin = RootWindow(pSprite)->firstChild;
2762     while (pWin)
2763     {
2764         if ((pWin->mapped) &&
2765             (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
2766             (x < pWin->drawable.x + (int)pWin->drawable.width +
2767              wBorderWidth(pWin)) &&
2768             (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
2769             (y < pWin->drawable.y + (int)pWin->drawable.height +
2770              wBorderWidth (pWin))
2771             /* When a window is shaped, a further check
2772              * is made to see if the point is inside
2773              * borderSize
2774              */
2775             && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
2776             && (!wInputShape(pWin) ||
2777                 RegionContainsPoint(wInputShape(pWin),
2778                                     x - pWin->drawable.x,
2779                                     y - pWin->drawable.y, &box))
2780 #ifdef ROOTLESS
2781     /* In rootless mode windows may be offscreen, even when
2782      * they're in X's stack. (E.g. if the native window system
2783      * implements some form of virtual desktop system).
2784      */
2785                 && !pWin->rootlessUnhittable
2786 #endif
2787             )
2788         {
2789             if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize)
2790             {
2791                 pSprite->spriteTraceSize += 10;
2792                 pSprite->spriteTrace = realloc(pSprite->spriteTrace,
2793                                     pSprite->spriteTraceSize*sizeof(WindowPtr));
2794             }
2795             pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
2796             pWin = pWin->firstChild;
2797         }
2798         else
2799             pWin = pWin->nextSib;
2800     }
2801     return DeepestSpriteWin(pSprite);
2804 /**
2805  * Ungrab a currently FocusIn grabbed device and grab the device on the
2806  * given window. If the win given is the NoneWin, the device is ungrabbed if
2807  * applicable and FALSE is returned.
2808  *
2809  * @returns TRUE if the device has been grabbed, or FALSE otherwise.
2810  */
2811 BOOL
2812 ActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
2814     BOOL rc = FALSE;
2815     DeviceEvent event;
2817     if (dev->deviceGrab.grab)
2818     {
2819         if (!dev->deviceGrab.fromPassiveGrab ||
2820             dev->deviceGrab.grab->type != XI_Enter ||
2821             dev->deviceGrab.grab->window == win ||
2822             IsParent(dev->deviceGrab.grab->window, win))
2823             return FALSE;
2824         DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
2825         (*dev->deviceGrab.DeactivateGrab)(dev);
2826     }
2828     if (win == NoneWin || win == PointerRootWin)
2829         return FALSE;
2831     memset(&event, 0, sizeof(DeviceEvent));
2832     event.header = ET_Internal;
2833     event.type = ET_FocusIn;
2834     event.length = sizeof(DeviceEvent);
2835     event.time = GetTimeInMillis();
2836     event.deviceid = dev->id;
2837     event.sourceid = dev->id;
2838     event.detail.button = 0;
2839     rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE,
2840                                     TRUE) != NULL);
2841     if (rc)
2842         DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
2843     return rc;
2846 /**
2847  * Ungrab a currently Enter grabbed device and grab the device for the given
2848  * window.
2849  *
2850  * @returns TRUE if the device has been grabbed, or FALSE otherwise.
2851  */
2852 static BOOL
2853 ActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
2855     BOOL rc = FALSE;
2856     DeviceEvent event;
2858     if (dev->deviceGrab.grab)
2859     {
2860         if (!dev->deviceGrab.fromPassiveGrab ||
2861             dev->deviceGrab.grab->type != XI_Enter ||
2862             dev->deviceGrab.grab->window == win ||
2863             IsParent(dev->deviceGrab.grab->window, win))
2864             return FALSE;
2865         DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
2866         (*dev->deviceGrab.DeactivateGrab)(dev);
2867     }
2869     memset(&event, 0, sizeof(DeviceEvent));
2870     event.header = ET_Internal;
2871     event.type = ET_Enter;
2872     event.length = sizeof(DeviceEvent);
2873     event.time = GetTimeInMillis();
2874     event.deviceid = dev->id;
2875     event.sourceid = dev->id;
2876     event.detail.button = 0;
2877     rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE,
2878                                     TRUE) != NULL);
2879     if (rc)
2880         DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
2881     return rc;
2884 /**
2885  * Update the sprite coordinates based on the event. Update the cursor
2886  * position, then update the event with the new coordinates that may have been
2887  * changed. If the window underneath the sprite has changed, change to new
2888  * cursor and send enter/leave events.
2889  *
2890  * CheckMotion() will not do anything and return FALSE if the event is not a
2891  * pointer event.
2892  *
2893  * @return TRUE if the sprite has moved or FALSE otherwise.
2894  */
2895 Bool
2896 CheckMotion(DeviceEvent *ev, DeviceIntPtr pDev)
2898     WindowPtr prevSpriteWin, newSpriteWin;
2899     SpritePtr pSprite = pDev->spriteInfo->sprite;
2901     verify_internal_event((InternalEvent *)ev);
2903     prevSpriteWin = pSprite->win;
2905     if (ev && !syncEvents.playingEvents)
2906     {
2907         /* GetPointerEvents() guarantees that pointer events have the correct
2908            rootX/Y set already. */
2909         switch (ev->type)
2910         {
2911             case ET_ButtonPress:
2912             case ET_ButtonRelease:
2913             case ET_Motion:
2914                 break;
2915             default:
2916                 /* all other events return FALSE */
2917                 return FALSE;
2918         }
2921 #ifdef PANORAMIX
2922         if (!noPanoramiXExtension)
2923         {
2924             /* Motion events entering DIX get translated to Screen 0
2925                coordinates.  Replayed events have already been
2926                translated since they've entered DIX before */
2927             ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
2928             ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
2929         } else
2930 #endif
2931         {
2932             if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen)
2933             {
2934                 pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
2935                 RootWindow(pDev->spriteInfo->sprite) =
2936                     pSprite->hot.pScreen->root;
2937             }
2938         }
2940         pSprite->hot.x = ev->root_x;
2941         pSprite->hot.y = ev->root_y;
2942         if (pSprite->hot.x < pSprite->physLimits.x1)
2943             pSprite->hot.x = pSprite->physLimits.x1;
2944         else if (pSprite->hot.x >= pSprite->physLimits.x2)
2945             pSprite->hot.x = pSprite->physLimits.x2 - 1;
2946         if (pSprite->hot.y < pSprite->physLimits.y1)
2947             pSprite->hot.y = pSprite->physLimits.y1;
2948         else if (pSprite->hot.y >= pSprite->physLimits.y2)
2949             pSprite->hot.y = pSprite->physLimits.y2 - 1;
2950         if (pSprite->hotShape)
2951             ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y);
2952         pSprite->hotPhys = pSprite->hot;
2954         if ((pSprite->hotPhys.x != ev->root_x) ||
2955             (pSprite->hotPhys.y != ev->root_y))
2956         {
2957 #ifdef PANORAMIX
2958             if (!noPanoramiXExtension)
2959             {
2960                 XineramaSetCursorPosition(
2961                         pDev, pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
2962             } else
2963 #endif
2964             {
2965                 (*pSprite->hotPhys.pScreen->SetCursorPosition)(
2966                         pDev, pSprite->hotPhys.pScreen,
2967                         pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
2968             }
2969         }
2971         ev->root_x = pSprite->hot.x;
2972         ev->root_y = pSprite->hot.y;
2973     }
2975     newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y);
2977     if (newSpriteWin != prevSpriteWin)
2978     {
2979         int sourceid;
2980         if (!ev) {
2981             UpdateCurrentTimeIf();
2982             sourceid = pDev->id; /* when from WindowsRestructured */
2983         } else
2984             sourceid = ev->sourceid;
2986         if (prevSpriteWin != NullWindow) {
2987             if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin))
2988                 DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin,
2989                                    newSpriteWin, NotifyNormal);
2990         }
2991         /* set pSprite->win after ActivateEnterGrab, otherwise
2992            sprite window == grab_window and no enter/leave events are
2993            sent. */
2994         pSprite->win = newSpriteWin;
2995         PostNewCursor(pDev);
2996         return FALSE;
2997     }
2998     return TRUE;
3001 /**
3002  * Windows have restructured, we need to update the sprite position and the
3003  * sprite's cursor.
3004  */
3005 void
3006 WindowsRestructured(void)
3008     DeviceIntPtr pDev = inputInfo.devices;
3009     while(pDev)
3010     {
3011         if (IsMaster(pDev) || IsFloating(pDev))
3012             CheckMotion(NULL, pDev);
3013         pDev = pDev->next;
3014     }
3017 #ifdef PANORAMIX
3018 /* This was added to support reconfiguration under Xdmx.  The problem is
3019  * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin
3020  * other than 0,0, the information in the private sprite structure must
3021  * be updated accordingly, or XYToWindow (and other routines) will not
3022  * compute correctly. */
3023 void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
3025     GrabPtr   grab;
3026     DeviceIntPtr pDev;
3027     SpritePtr pSprite;
3029     if (noPanoramiXExtension) return;
3031     pDev = inputInfo.devices;
3032     while(pDev)
3033     {
3034         if (DevHasCursor(pDev))
3035         {
3036             pSprite = pDev->spriteInfo->sprite;
3037             pSprite->hot.x        -= xoff;
3038             pSprite->hot.y        -= yoff;
3040             pSprite->hotPhys.x    -= xoff;
3041             pSprite->hotPhys.y    -= yoff;
3043             pSprite->hotLimits.x1 -= xoff;
3044             pSprite->hotLimits.y1 -= yoff;
3045             pSprite->hotLimits.x2 -= xoff;
3046             pSprite->hotLimits.y2 -= yoff;
3048             if (RegionNotEmpty(&pSprite->Reg1))
3049                 RegionTranslate(&pSprite->Reg1, xoff, yoff);
3050             if (RegionNotEmpty(&pSprite->Reg2))
3051                 RegionTranslate(&pSprite->Reg2, xoff, yoff);
3053             /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
3054             if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
3055                 if (grab->confineTo->drawable.pScreen
3056                         != pSprite->hotPhys.pScreen)
3057                     pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
3058                 ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
3059             } else
3060                 ConfineCursorToWindow(
3061                         pDev,
3062                         pSprite->hotPhys.pScreen->root,
3063                         TRUE, FALSE);
3065         }
3066         pDev = pDev->next;
3067     }
3069 #endif
3071 /**
3072  * Initialize a sprite for the given device and set it to some sane values. If
3073  * the device already has a sprite alloc'd, don't realloc but just reset to
3074  * default values.
3075  * If a window is supplied, the sprite will be initialized with the window's
3076  * cursor and positioned in the center of the window's screen. The root window
3077  * is a good choice to pass in here.
3078  *
3079  * It's a good idea to call it only for pointer devices, unless you have a
3080  * really talented keyboard.
3081  *
3082  * @param pDev The device to initialize.
3083  * @param pWin The window where to generate the sprite in.
3084  *
3085  */
3086 void
3087 InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
3089     SpritePtr pSprite;
3090     ScreenPtr pScreen;
3091     CursorPtr pCursor;
3093     if (!pDev->spriteInfo->sprite)
3094     {
3095         DeviceIntPtr it;
3097         pDev->spriteInfo->sprite = (SpritePtr)calloc(1, sizeof(SpriteRec));
3098         if (!pDev->spriteInfo->sprite)
3099             FatalError("InitializeSprite: failed to allocate sprite struct");
3101         /* We may have paired another device with this device before our
3102          * device had a actual sprite. We need to check for this and reset the
3103          * sprite field for all paired devices.
3104          *
3105          * The VCK is always paired with the VCP before the VCP has a sprite.
3106          */
3107         for (it = inputInfo.devices; it; it = it->next)
3108         {
3109             if (it->spriteInfo->paired == pDev)
3110                 it->spriteInfo->sprite = pDev->spriteInfo->sprite;
3111         }
3112         if (inputInfo.keyboard->spriteInfo->paired == pDev)
3113             inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite;
3114     }
3116     pSprite = pDev->spriteInfo->sprite;
3117     pDev->spriteInfo->spriteOwner = TRUE;
3119     pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr)NULL;
3120     pSprite->hot.pScreen = pScreen;
3121     pSprite->hotPhys.pScreen = pScreen;
3122     if (pScreen)
3123     {
3124         pSprite->hotPhys.x = pScreen->width / 2;
3125         pSprite->hotPhys.y = pScreen->height / 2;
3126         pSprite->hotLimits.x2 = pScreen->width;
3127         pSprite->hotLimits.y2 = pScreen->height;
3128     }
3130     pSprite->hot = pSprite->hotPhys;
3131     pSprite->win = pWin;
3133     if (pWin)
3134     {
3135         pCursor = wCursor(pWin);
3136         pSprite->spriteTrace = (WindowPtr *)calloc(1, 32*sizeof(WindowPtr));
3137         if (!pSprite->spriteTrace)
3138             FatalError("Failed to allocate spriteTrace");
3139         pSprite->spriteTraceSize = 32;
3141         RootWindow(pDev->spriteInfo->sprite) = pWin;
3142         pSprite->spriteTraceGood = 1;
3144         pSprite->pEnqueueScreen = pScreen;
3145         pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
3147     } else {
3148         pCursor = NullCursor;
3149         pSprite->spriteTrace = NULL;
3150         pSprite->spriteTraceSize = 0;
3151         pSprite->spriteTraceGood = 0;
3152         pSprite->pEnqueueScreen = screenInfo.screens[0];
3153         pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
3154     }
3155     if (pCursor)
3156         pCursor->refcnt++;
3157     if (pSprite->current)
3158         FreeCursor(pSprite->current, None);
3159     pSprite->current = pCursor;
3161     if (pScreen)
3162     {
3163         (*pScreen->RealizeCursor) ( pDev, pScreen, pSprite->current);
3164         (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current,
3165                                    &pSprite->hotLimits, &pSprite->physLimits);
3166         pSprite->confined = FALSE;
3168         (*pScreen->ConstrainCursor) (pDev, pScreen,
3169                                      &pSprite->physLimits);
3170         (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
3171                                        pSprite->hot.y,
3172                                        FALSE);
3173         (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
3174     }
3175 #ifdef PANORAMIX
3176     if(!noPanoramiXExtension) {
3177         pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
3178         pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
3179         pSprite->hotLimits.x2 = PanoramiXPixWidth  - screenInfo.screens[0]->x;
3180         pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
3181         pSprite->physLimits = pSprite->hotLimits;
3182         pSprite->confineWin = NullWindow;
3183         pSprite->hotShape = NullRegion;
3184         pSprite->screen = pScreen;
3185         /* gotta UNINIT these someplace */
3186         RegionNull(&pSprite->Reg1);
3187         RegionNull(&pSprite->Reg2);
3188     }
3189 #endif
3192 /**
3193  * Update the mouse sprite info when the server switches from a pScreen to another.
3194  * Otherwise, the pScreen of the mouse sprite is never updated when we switch
3195  * from a pScreen to another. Never updating the pScreen of the mouse sprite
3196  * implies that windows that are in pScreen whose pScreen->myNum >0 will never
3197  * get pointer events. This is  because in CheckMotion(), sprite.hotPhys.pScreen
3198  * always points to the first pScreen it has been set by
3199  * DefineInitialRootWindow().
3200  *
3201  * Calling this function is useful for use cases where the server
3202  * has more than one pScreen.
3203  * This function is similar to DefineInitialRootWindow() but it does not
3204  * reset the mouse pointer position.
3205  * @param win must be the new pScreen we are switching to.
3206  */
3207 void
3208 UpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
3210     SpritePtr pSprite = NULL;
3211     WindowPtr win = NULL;
3212     CursorPtr pCursor;
3213     if (!pScreen)
3214         return ;
3216     if (!pDev->spriteInfo->sprite)
3217         return;
3219     pSprite = pDev->spriteInfo->sprite;
3221     win = pScreen->root;
3223     pSprite->hotPhys.pScreen = pScreen;
3224     pSprite->hot = pSprite->hotPhys;
3225     pSprite->hotLimits.x2 = pScreen->width;
3226     pSprite->hotLimits.y2 = pScreen->height;
3227     pSprite->win = win;
3228     pCursor = wCursor(win);
3229     if (pCursor)
3230         pCursor->refcnt++;
3231     if (pSprite->current)
3232         FreeCursor(pSprite->current, 0);
3233     pSprite->current = pCursor;
3234     pSprite->spriteTraceGood = 1;
3235     pSprite->spriteTrace[0] = win;
3236     (*pScreen->CursorLimits) (pDev,
3237                               pScreen,
3238                               pSprite->current,
3239                               &pSprite->hotLimits,
3240                               &pSprite->physLimits);
3241     pSprite->confined = FALSE;
3242     (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
3243     (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
3245 #ifdef PANORAMIX
3246     if(!noPanoramiXExtension) {
3247         pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
3248         pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
3249         pSprite->hotLimits.x2 = PanoramiXPixWidth  - screenInfo.screens[0]->x;
3250         pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
3251         pSprite->physLimits = pSprite->hotLimits;
3252         pSprite->screen = pScreen;
3253     }
3254 #endif
3257 /*
3258  * This does not take any shortcuts, and even ignores its argument, since
3259  * it does not happen very often, and one has to walk up the tree since
3260  * this might be a newly instantiated cursor for an intermediate window
3261  * between the one the pointer is in and the one that the last cursor was
3262  * instantiated from.
3263  */
3264 void
3265 WindowHasNewCursor(WindowPtr pWin)
3267     DeviceIntPtr pDev;
3269     for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
3270         if (DevHasCursor(pDev))
3271             PostNewCursor(pDev);
3274 void
3275 NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
3277     SpritePtr pSprite = pDev->spriteInfo->sprite;
3279     pSprite->hotPhys.x = x;
3280     pSprite->hotPhys.y = y;
3281 #ifdef PANORAMIX
3282     if(!noPanoramiXExtension) {
3283         pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x;
3284         pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y;
3285         if (newScreen != pSprite->screen) {
3286             pSprite->screen = newScreen;
3287             /* Make sure we tell the DDX to update its copy of the screen */
3288             if(pSprite->confineWin)
3289                 XineramaConfineCursorToWindow(pDev,
3290                         pSprite->confineWin, TRUE);
3291             else
3292                 XineramaConfineCursorToWindow(pDev, screenInfo.screens[0]->root, TRUE);
3293             /* if the pointer wasn't confined, the DDX won't get
3294                told of the pointer warp so we reposition it here */
3295             if(!syncEvents.playingEvents)
3296                 (*pSprite->screen->SetCursorPosition)(
3297                                                       pDev,
3298                                                       pSprite->screen,
3299                     pSprite->hotPhys.x + screenInfo.screens[0]->x -
3300                         pSprite->screen->x,
3301                     pSprite->hotPhys.y + screenInfo.screens[0]->y -
3302                         pSprite->screen->y, FALSE);
3303         }
3304     } else
3305 #endif
3306     if (newScreen != pSprite->hotPhys.pScreen)
3307         ConfineCursorToWindow(pDev, newScreen->root, TRUE, FALSE);
3310 #ifdef PANORAMIX
3312 static Bool
3313 XineramaPointInWindowIsVisible(
3314     WindowPtr pWin,
3315     int x,
3316     int y
3319     BoxRec box;
3320     int i, xoff, yoff;
3322     if (!pWin->realized) return FALSE;
3324     if (RegionContainsPoint(&pWin->borderClip, x, y, &box))
3325         return TRUE;
3327     if(!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) return FALSE;
3329     xoff = x + screenInfo.screens[0]->x;
3330     yoff = y + screenInfo.screens[0]->y;
3332     FOR_NSCREENS_FORWARD_SKIP(i) {
3333         pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
3334         x = xoff - screenInfo.screens[i]->x;
3335         y = yoff - screenInfo.screens[i]->y;
3337         if(RegionContainsPoint(&pWin->borderClip, x, y, &box)
3338            && (!wInputShape(pWin) ||
3339                RegionContainsPoint(wInputShape(pWin),
3340                                    x - pWin->drawable.x,
3341                                    y - pWin->drawable.y, &box)))
3342             return TRUE;
3344     }
3346     return FALSE;
3349 static int
3350 XineramaWarpPointer(ClientPtr client)
3352     WindowPtr   dest = NULL;
3353     int         x, y, rc;
3354     SpritePtr   pSprite = PickPointer(client)->spriteInfo->sprite;
3356     REQUEST(xWarpPointerReq);
3359     if (stuff->dstWid != None) {
3360         rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
3361         if (rc != Success)
3362             return rc;
3363     }
3364     x = pSprite->hotPhys.x;
3365     y = pSprite->hotPhys.y;
3367     if (stuff->srcWid != None)
3368     {
3369         int     winX, winY;
3370         XID     winID = stuff->srcWid;
3371         WindowPtr source;
3373         rc = dixLookupWindow(&source, winID, client, DixReadAccess);
3374         if (rc != Success)
3375             return rc;
3377         winX = source->drawable.x;
3378         winY = source->drawable.y;
3379         if(source == screenInfo.screens[0]->root) {
3380             winX -= screenInfo.screens[0]->x;
3381             winY -= screenInfo.screens[0]->y;
3382         }
3383         if (x < winX + stuff->srcX ||
3384             y < winY + stuff->srcY ||
3385             (stuff->srcWidth != 0 &&
3386              winX + stuff->srcX + (int)stuff->srcWidth < x) ||
3387             (stuff->srcHeight != 0 &&
3388              winY + stuff->srcY + (int)stuff->srcHeight < y) ||
3389             !XineramaPointInWindowIsVisible(source, x, y))
3390             return Success;
3391     }
3392     if (dest) {
3393         x = dest->drawable.x;
3394         y = dest->drawable.y;
3395         if(dest == screenInfo.screens[0]->root) {
3396             x -= screenInfo.screens[0]->x;
3397             y -= screenInfo.screens[0]->y;
3398         }
3399     }
3401     x += stuff->dstX;
3402     y += stuff->dstY;
3404     if (x < pSprite->physLimits.x1)
3405         x = pSprite->physLimits.x1;
3406     else if (x >= pSprite->physLimits.x2)
3407         x = pSprite->physLimits.x2 - 1;
3408     if (y < pSprite->physLimits.y1)
3409         y = pSprite->physLimits.y1;
3410     else if (y >= pSprite->physLimits.y2)
3411         y = pSprite->physLimits.y2 - 1;
3412     if (pSprite->hotShape)
3413         ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
3415     XineramaSetCursorPosition(PickPointer(client), x, y, TRUE);
3417     return Success;
3420 #endif
3423 /**
3424  * Server-side protocol handling for WarpPointer request.
3425  * Warps the cursor position to the coordinates given in the request.
3426  */
3427 int
3428 ProcWarpPointer(ClientPtr client)
3430     WindowPtr   dest = NULL;
3431     int         x, y, rc;
3432     ScreenPtr   newScreen;
3433     DeviceIntPtr dev, tmp;
3434     SpritePtr   pSprite;
3436     REQUEST(xWarpPointerReq);
3437     REQUEST_SIZE_MATCH(xWarpPointerReq);
3439     dev = PickPointer(client);
3441     for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
3442         if (GetMaster(tmp, MASTER_ATTACHED) == dev) {
3443             rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
3444             if (rc != Success)
3445                 return rc;
3446         }
3447     }
3449     if (dev->lastSlave)
3450         dev = dev->lastSlave;
3451     pSprite = dev->spriteInfo->sprite;
3453 #ifdef PANORAMIX
3454     if(!noPanoramiXExtension)
3455         return XineramaWarpPointer(client);
3456 #endif
3458     if (stuff->dstWid != None) {
3459         rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess);
3460         if (rc != Success)
3461             return rc;
3462     }
3463     x = pSprite->hotPhys.x;
3464     y = pSprite->hotPhys.y;
3466     if (stuff->srcWid != None)
3467     {
3468         int     winX, winY;
3469         XID     winID = stuff->srcWid;
3470         WindowPtr source;
3472         rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess);
3473         if (rc != Success)
3474             return rc;
3476         winX = source->drawable.x;
3477         winY = source->drawable.y;
3478         if (source->drawable.pScreen != pSprite->hotPhys.pScreen ||
3479             x < winX + stuff->srcX ||
3480             y < winY + stuff->srcY ||
3481             (stuff->srcWidth != 0 &&
3482              winX + stuff->srcX + (int)stuff->srcWidth < x) ||
3483             (stuff->srcHeight != 0 &&
3484              winY + stuff->srcY + (int)stuff->srcHeight < y) ||
3485             !PointInWindowIsVisible(source, x, y))
3486             return Success;
3487     }
3488     if (dest)
3489     {
3490         x = dest->drawable.x;
3491         y = dest->drawable.y;
3492         newScreen = dest->drawable.pScreen;
3493     } else
3494         newScreen = pSprite->hotPhys.pScreen;
3496     x += stuff->dstX;
3497     y += stuff->dstY;
3499     if (x < 0)
3500         x = 0;
3501     else if (x >= newScreen->width)
3502         x = newScreen->width - 1;
3503     if (y < 0)
3504         y = 0;
3505     else if (y >= newScreen->height)
3506         y = newScreen->height - 1;
3508     if (newScreen == pSprite->hotPhys.pScreen)
3509     {
3510         if (x < pSprite->physLimits.x1)
3511             x = pSprite->physLimits.x1;
3512         else if (x >= pSprite->physLimits.x2)
3513             x = pSprite->physLimits.x2 - 1;
3514         if (y < pSprite->physLimits.y1)
3515             y = pSprite->physLimits.y1;
3516         else if (y >= pSprite->physLimits.y2)
3517             y = pSprite->physLimits.y2 - 1;
3518         if (pSprite->hotShape)
3519             ConfineToShape(dev, pSprite->hotShape, &x, &y);
3520         (*newScreen->SetCursorPosition)(dev, newScreen, x, y, TRUE);
3521     }
3522     else if (!PointerConfinedToScreen(dev))
3523     {
3524         NewCurrentScreen(dev, newScreen, x, y);
3525     }
3526     return Success;
3529 static Bool
3530 BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
3532      if(RegionNotEmpty(&pWin->borderSize))
3533         return TRUE;
3535 #ifdef PANORAMIX
3536      if(!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) {
3537         int i;
3539         FOR_NSCREENS_FORWARD_SKIP(i) {
3540             if(RegionNotEmpty(&pDev->spriteInfo->sprite->windows[i]->borderSize))
3541                 return TRUE;
3542         }
3543      }
3544 #endif
3545      return FALSE;
3548 /**
3549  * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
3550  * passive grab set on the window to be activated.
3551  * If activate is true and a passive grab is found, it will be activated,
3552  * and the event will be delivered to the client.
3553  *
3554  * @param pWin The window that may be subject to a passive grab.
3555  * @param device Device that caused the event.
3556  * @param event The current device event.
3557  * @param checkCore Check for core grabs too.
3558  * @param activate If a grab is found, activate it and deliver the event.
3559  */
3561 GrabPtr
3562 CheckPassiveGrabsOnWindow(
3563     WindowPtr pWin,
3564     DeviceIntPtr device,
3565     InternalEvent *event,
3566     BOOL checkCore,
3567     BOOL activate)
3569     SpritePtr pSprite = device->spriteInfo->sprite;
3570     GrabPtr grab = wPassiveGrabs(pWin);
3571     GrabRec tempGrab;
3572     GrabInfoPtr grabinfo;
3573 #define CORE_MATCH      0x1
3574 #define XI_MATCH        0x2
3575 #define XI2_MATCH        0x4
3576     int match = 0;
3578     if (!grab)
3579         return NULL;
3580     /* Fill out the grab details, but leave the type for later before
3581      * comparing */
3582     switch (event->any.type)
3583     {
3584         case ET_KeyPress:
3585         case ET_KeyRelease:
3586             tempGrab.detail.exact = event->device_event.detail.key;
3587             break;
3588         case ET_ButtonPress:
3589         case ET_ButtonRelease:
3590             tempGrab.detail.exact = event->device_event.detail.button;
3591             break;
3592         default:
3593             tempGrab.detail.exact = 0;
3594             break;
3595     }
3596     tempGrab.window = pWin;
3597     tempGrab.device = device;
3598     tempGrab.detail.pMask = NULL;
3599     tempGrab.modifiersDetail.pMask = NULL;
3600     tempGrab.next = NULL;
3601     for (; grab; grab = grab->next)
3602     {
3603         DeviceIntPtr    gdev;
3604         XkbSrvInfoPtr   xkbi = NULL;
3605         xEvent *xE = NULL;
3606         int count, rc;
3608         gdev= grab->modifierDevice;
3609         if (grab->grabtype == GRABTYPE_CORE)
3610         {
3611             if (IsPointerDevice(device))
3612                 gdev = GetPairedDevice(device);
3613             else
3614                 gdev = device;
3615         } else if (grab->grabtype == GRABTYPE_XI2)
3616         {
3617             /* if the device is an attached slave device, gdev must be the
3618              * attached master keyboard. Since the slave may have been
3619              * reattached after the grab, the modifier device may not be the
3620              * same. */
3621             if (!IsMaster(grab->device) && !IsFloating(device))
3622                 gdev = GetMaster(device, MASTER_KEYBOARD);
3623         }
3626         if (gdev && gdev->key)
3627             xkbi= gdev->key->xkbInfo;
3628         tempGrab.modifierDevice = grab->modifierDevice;
3629         tempGrab.modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
3631         /* Check for XI2 and XI grabs first */
3632         tempGrab.type = GetXI2Type(event);
3633         tempGrab.grabtype = GRABTYPE_XI2;
3634         if (GrabMatchesSecond(&tempGrab, grab, FALSE))
3635             match = XI2_MATCH;
3637         if (!match)
3638         {
3639             tempGrab.grabtype = GRABTYPE_XI;
3640             if ((tempGrab.type = GetXIType(event)) &&
3641                 (GrabMatchesSecond(&tempGrab, grab, FALSE)))
3642                 match = XI_MATCH;
3643         }
3645         /* Check for a core grab (ignore the device when comparing) */
3646         if (!match && checkCore)
3647         {
3648             tempGrab.grabtype = GRABTYPE_CORE;
3649             if ((tempGrab.type = GetCoreType(event)) &&
3650                 (GrabMatchesSecond(&tempGrab, grab, TRUE)))
3651                 match = CORE_MATCH;
3652         }
3654         if (!match || (grab->confineTo &&
3655                        (!grab->confineTo->realized ||
3656                         !BorderSizeNotEmpty(device, grab->confineTo))))
3657             continue;
3659         grabinfo = &device->deviceGrab;
3660         /* In some cases a passive core grab may exist, but the client
3661          * already has a core grab on some other device. In this case we
3662          * must not get the grab, otherwise we may never ungrab the
3663          * device.
3664          */
3666         if (grab->grabtype == GRABTYPE_CORE)
3667         {
3668             DeviceIntPtr other;
3669             BOOL interfering = FALSE;
3671             /* A passive grab may have been created for a different device
3672                than it is assigned to at this point in time.
3673                Update the grab's device and modifier device to reflect the
3674                current state.
3675                Since XGrabDeviceButton requires to specify the
3676                modifierDevice explicitly, we don't override this choice.
3677                */
3678             if (tempGrab.type < GenericEvent)
3679             {
3680                 grab->device = device;
3681                 grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD);
3682             }
3684             for (other = inputInfo.devices; other; other = other->next)
3685             {
3686                 GrabPtr othergrab = other->deviceGrab.grab;
3687                 if (othergrab && othergrab->grabtype == GRABTYPE_CORE &&
3688                     SameClient(grab, rClient(othergrab)) &&
3689                     ((IsPointerDevice(grab->device) &&
3690                      IsPointerDevice(othergrab->device)) ||
3691                      (IsKeyboardDevice(grab->device) &&
3692                       IsKeyboardDevice(othergrab->device))))
3693                 {
3694                     interfering = TRUE;
3695                     break;
3696                 }
3697             }
3698             if (interfering)
3699                 continue;
3700         }
3702         if (!activate)
3703         {
3704             return grab;
3705         }
3706         else if (!GetXIType(event) && !GetCoreType(event))
3707         {
3708             ErrorF("Event type %d in CheckPassiveGrabsOnWindow is neither"
3709                    " XI 1.x nor core\n", event->any.type);
3710             return NULL;
3711         }
3713         /* The only consumers of corestate are Xi 1.x and core events, which
3714          * are guaranteed to come from DeviceEvents. */
3715         if (match & (XI_MATCH | CORE_MATCH))
3716         {
3717             event->device_event.corestate &= 0x1f00;
3718             event->device_event.corestate |= tempGrab.modifiersDetail.exact &
3719                                               (~0x1f00);
3720         }
3722         if (match & CORE_MATCH)
3723         {
3724             rc = EventToCore(event, &xE, &count);
3725             if (rc != Success)
3726             {
3727                 if (rc != BadMatch)
3728                     ErrorF("[dix] %s: core conversion failed in CPGFW "
3729                             "(%d, %d).\n", device->name, event->any.type, rc);
3730                 continue;
3731             }
3732         } else if (match & XI2_MATCH)
3733         {
3734             rc = EventToXI2(event, &xE);
3735             if (rc != Success)
3736             {
3737                 if (rc != BadMatch)
3738                     ErrorF("[dix] %s: XI2 conversion failed in CPGFW "
3739                             "(%d, %d).\n", device->name, event->any.type, rc);
3740                 continue;
3741             }
3742             count = 1;
3743         } else
3744         {
3745             rc = EventToXI(event, &xE, &count);
3746             if (rc != Success)
3747             {
3748                 if (rc != BadMatch)
3749                     ErrorF("[dix] %s: XI conversion failed in CPGFW "
3750                             "(%d, %d).\n", device->name, event->any.type, rc);
3751                 continue;
3752             }
3753         }
3755         (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
3757         if (xE)
3758         {
3759             FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
3761             /* XXX: XACE? */
3762             TryClientEvents(rClient(grab), device, xE, count,
3763                             GetEventFilter(device, xE),
3764                             GetEventFilter(device, xE), grab);
3765         }
3767         if (grabinfo->sync.state == FROZEN_NO_EVENT)
3768         {
3769             if (!grabinfo->sync.event)
3770                 grabinfo->sync.event = calloc(1, sizeof(DeviceEvent));
3771             *grabinfo->sync.event = event->device_event;
3772             grabinfo->sync.state = FROZEN_WITH_EVENT;
3773         }
3775         free(xE);
3776         return grab;
3777     }
3778     return NULL;
3779 #undef CORE_MATCH
3780 #undef XI_MATCH
3781 #undef XI2_MATCH
3784 /**
3785  * CheckDeviceGrabs handles both keyboard and pointer events that may cause
3786  * a passive grab to be activated.
3787  *
3788  * If the event is a keyboard event, the ancestors of the focus window are
3789  * traced down and tried to see if they have any passive grabs to be
3790  * activated.  If the focus window itself is reached and it's descendants
3791  * contain the pointer, the ancestors of the window that the pointer is in
3792  * are then traced down starting at the focus window, otherwise no grabs are
3793  * activated.
3794  * If the event is a pointer event, the ancestors of the window that the
3795  * pointer is in are traced down starting at the root until CheckPassiveGrabs
3796  * causes a passive grab to activate or all the windows are
3797  * tried. PRH
3798  *
3799  * If a grab is activated, the event has been sent to the client already!
3800  *
3801  * The event we pass in must always be an XI event. From this, we then emulate
3802  * the core event and then check for grabs.
3803  *
3804  * @param device The device that caused the event.
3805  * @param xE The event to handle (Device{Button|Key}Press).
3806  * @param count Number of events in list.
3807  * @return TRUE if a grab has been activated or false otherwise.
3808 */
3810 Bool
3811 CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor)
3813     int i;
3814     WindowPtr pWin = NULL;
3815     FocusClassPtr focus = IsPointerEvent((InternalEvent*)event) ? NULL : device->focus;
3816     BOOL sendCore = (IsMaster(device) && device->coreEvents);
3817     Bool ret = FALSE;
3819     if (event->type != ET_ButtonPress &&
3820         event->type != ET_KeyPress)
3821         return FALSE;
3823     if (event->type == ET_ButtonPress
3824         && (device->button->buttonsDown != 1))
3825         return FALSE;
3827     if (device->deviceGrab.grab)
3828         return FALSE;
3830     i = 0;
3831     if (ancestor)
3832     {
3833         while (i < device->spriteInfo->sprite->spriteTraceGood)
3834             if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor)
3835                 break;
3836         if (i == device->spriteInfo->sprite->spriteTraceGood)
3837             goto out;
3838     }
3840     if (focus)
3841     {
3842         for (; i < focus->traceGood; i++)
3843         {
3844             pWin = focus->trace[i];
3845             if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event,
3846                                           sendCore, TRUE))
3847             {
3848                 ret = TRUE;
3849                 goto out;
3850             }
3851         }
3853         if ((focus->win == NoneWin) ||
3854             (i >= device->spriteInfo->sprite->spriteTraceGood) ||
3855             (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i-1]))
3856             goto out;
3857     }
3859     for (; i < device->spriteInfo->sprite->spriteTraceGood; i++)
3860     {
3861         pWin = device->spriteInfo->sprite->spriteTrace[i];
3862         if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event,
3863                                       sendCore, TRUE))
3864         {
3865             ret = TRUE;
3866             goto out;
3867         }
3868     }
3870 out:
3871     if (ret == TRUE && event->type == ET_KeyPress)
3872         device->deviceGrab.activatingKey = event->detail.key;
3873     return ret;
3876 /**
3877  * Called for keyboard events to deliver event to whatever client owns the
3878  * focus.
3879  *
3880  * The event is delivered to the keyboard's focus window, the root window or
3881  * to the window owning the input focus.
3882  *
3883  * @param keybd The keyboard originating the event.
3884  * @param event The event, not yet in wire format.
3885  * @param window Window underneath the sprite.
3886  */
3887 void
3888 DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
3890     DeviceIntPtr ptr;
3891     WindowPtr focus = keybd->focus->win;
3892     BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents);
3893     xEvent *core = NULL, *xE = NULL, *xi2 = NULL;
3894     int count, rc;
3895     int deliveries = 0;
3897     if (focus == FollowKeyboardWin)
3898         focus = inputInfo.keyboard->focus->win;
3899     if (!focus)
3900         return;
3901     if (focus == PointerRootWin)
3902     {
3903         DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd);
3904         return;
3905     }
3906     if ((focus == window) || IsParent(focus, window))
3907     {
3908         if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd))
3909             return;
3910     }
3912     /* just deliver it to the focus window */
3913     ptr = GetPairedDevice(keybd);
3916     rc = EventToXI2(event, &xi2);
3917     if (rc == Success)
3918     {
3919         /* XXX: XACE */
3920         int filter = GetEventFilter(keybd, xi2);
3921         FixUpEventFromWindow(ptr->spriteInfo->sprite, xi2, focus, None, FALSE);
3922         deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1,
3923                                            filter, NullGrab);
3924         if (deliveries > 0)
3925             goto unwind;
3926     } else if (rc != BadMatch)
3927         ErrorF("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n",
3928                keybd->name, event->any.type, rc);
3930     rc = EventToXI(event, &xE, &count);
3931     if (rc == Success &&
3932         XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success)
3933     {
3934         FixUpEventFromWindow(ptr->spriteInfo->sprite, xE, focus, None, FALSE);
3935         deliveries = DeliverEventsToWindow(keybd, focus, xE, count,
3936                 GetEventFilter(keybd, xE),
3937                 NullGrab);
3939         if (deliveries > 0)
3940             goto unwind;
3941     } else if (rc != BadMatch)
3942         ErrorF("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n",
3943                keybd->name, event->any.type, rc);
3945     if (sendCore)
3946     {
3947         rc = EventToCore(event, &core, &count);
3948         if (rc == Success) {
3949             if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, core, count) == Success) {
3950                 FixUpEventFromWindow(keybd->spriteInfo->sprite, core, focus,
3951                                      None, FALSE);
3952                 deliveries = DeliverEventsToWindow(keybd, focus, core, count,
3953                                                    GetEventFilter(keybd, core),
3954                                                    NullGrab);
3955             }
3956         } else if (rc != BadMatch)
3957             ErrorF("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n",
3958                     keybd->name, event->any.type, rc);
3959     }
3961 unwind:
3962     free(core);
3963     free(xE);
3964     free(xi2);
3965     return;
3968 /**
3969  * Deliver an event from a device that is currently grabbed. Uses
3970  * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the
3971  * grab. If not, TryClientEvents() is used.
3972  *
3973  * @param deactivateGrab True if the device's grab should be deactivated.
3974  *
3975  * @return The number of events delivered.
3976  */
3977 int
3978 DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
3979                     Bool deactivateGrab)
3981     GrabPtr grab;
3982     GrabInfoPtr grabinfo;
3983     int deliveries = 0;
3984     DeviceIntPtr dev;
3985     SpritePtr pSprite = thisDev->spriteInfo->sprite;
3986     BOOL sendCore = FALSE;
3987     int rc, count = 0;
3988     xEvent *xi = NULL;
3989     xEvent *xi2 = NULL;
3990     xEvent *core = NULL;
3992     grabinfo = &thisDev->deviceGrab;
3993     grab = grabinfo->grab;
3995     if (grab->ownerEvents)
3996     {
3997         WindowPtr focus;
3999         /* Hack: Some pointer device have a focus class. So we need to check
4000          * for the type of event, to see if we really want to deliver it to
4001          * the focus window. For pointer events, the answer is no.
4002          */
4003         if (IsPointerEvent(event))
4004             focus = PointerRootWin;
4005         else if (thisDev->focus)
4006         {
4007             focus = thisDev->focus->win;
4008             if (focus == FollowKeyboardWin)
4009                 focus = inputInfo.keyboard->focus->win;
4010         }
4011         else
4012             focus = PointerRootWin;
4013         if (focus == PointerRootWin)
4014             deliveries = DeliverDeviceEvents(pSprite->win, event, grab,
4015                                              NullWindow, thisDev);
4016         else if (focus && (focus == pSprite->win ||
4017                     IsParent(focus, pSprite->win)))
4018             deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus,
4019                                              thisDev);
4020         else if (focus)
4021             deliveries = DeliverDeviceEvents(focus, event, grab, focus,
4022                                              thisDev);
4023     }
4024     if (!deliveries)
4025     {
4026         Mask mask;
4028         /* XXX: In theory, we could pass the internal events through to
4029          * everything and only convert just before hitting the wire. We can't
4030          * do that yet, so DGE is the last stop for internal events. From here
4031          * onwards, we deal with core/XI events.
4032          */
4034         mask = grab->eventMask;
4036         sendCore = (IsMaster(thisDev) && thisDev->coreEvents);
4037         /* try core event */
4038         if (sendCore && grab->grabtype == GRABTYPE_CORE)
4039         {
4040             rc = EventToCore(event, &core, &count);
4041             if (rc == Success)
4042             {
4043                 FixUpEventFromWindow(pSprite, core, grab->window, None, TRUE);
4044                 if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
4045                             grab->window, core, count) ||
4046                         XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
4047                             grab->window, core, count))
4048                     deliveries = 1; /* don't send, but pretend we did */
4049                 else if (!IsInterferingGrab(rClient(grab), thisDev, core))
4050                 {
4051                     deliveries = TryClientEvents(rClient(grab), thisDev,
4052                             core, count, mask,
4053                             GetEventFilter(thisDev, core),
4054                             grab);
4055                 }
4056             } else if (rc != BadMatch)
4057                 ErrorF("[dix] DeliverGrabbedEvent. Core conversion failed.\n");
4058         }
4060         if (!deliveries)
4061         {
4062             rc = EventToXI2(event, &xi2);
4063             if (rc == Success)
4064             {
4065                 int evtype = xi2_get_type(xi2);
4066                 mask = grab->xi2mask[XIAllDevices][evtype/8] |
4067                     grab->xi2mask[XIAllMasterDevices][evtype/8] |
4068                     grab->xi2mask[thisDev->id][evtype/8];
4069                 /* try XI2 event */
4070                 FixUpEventFromWindow(pSprite, xi2, grab->window, None, TRUE);
4071                 /* XXX: XACE */
4072                 deliveries = TryClientEvents(rClient(grab), thisDev, xi2, 1, mask,
4073                         GetEventFilter(thisDev, xi2), grab);
4074             } else if (rc != BadMatch)
4075                 ErrorF("[dix] %s: XI2 conversion failed in DGE (%d, %d). Skipping delivery.\n",
4076                         thisDev->name, event->any.type, rc);
4077         }
4079         if (!deliveries)
4080         {
4081             rc = EventToXI(event, &xi, &count);
4082             if (rc == Success)
4083             {
4084                 /* try XI event */
4085                 if (grabinfo->fromPassiveGrab  &&
4086                         grabinfo->implicitGrab)
4087                     mask = grab->deviceMask;
4088                 else
4089                     mask = grab->eventMask;
4091                 FixUpEventFromWindow(pSprite, xi, grab->window, None, TRUE);
4093                 if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
4094                             grab->window, xi, count) ||
4095                         XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
4096                             grab->window, xi, count))
4097                     deliveries = 1; /* don't send, but pretend we did */
4098                 else
4099                 {
4100                     deliveries =
4101                         TryClientEvents(rClient(grab), thisDev,
4102                                 xi, count,
4103                                 mask,
4104                                 GetEventFilter(thisDev, xi),
4105                                 grab);
4106                 }
4107             } else if (rc != BadMatch)
4108                 ErrorF("[dix] %s: XI conversion failed in DGE (%d, %d). Skipping delivery.\n",
4109                         thisDev->name, event->any.type, rc);
4110         }
4112         if (deliveries && (event->any.type == ET_Motion))
4113             thisDev->valuator->motionHintWindow = grab->window;
4114     }
4115     if (deliveries && !deactivateGrab && event->any.type != ET_Motion)
4116     {
4117         switch (grabinfo->sync.state)
4118         {
4119         case FREEZE_BOTH_NEXT_EVENT:
4120             dev = GetPairedDevice(thisDev);
4121             if (dev)
4122             {
4123                 FreezeThaw(dev, TRUE);
4124                 if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) &&
4125                     (CLIENT_BITS(grab->resource) ==
4126                      CLIENT_BITS(dev->deviceGrab.grab->resource)))
4127                     dev->deviceGrab.sync.state = FROZEN_NO_EVENT;
4128                 else
4129                     dev->deviceGrab.sync.other = grab;
4130             }
4131             /* fall through */
4132         case FREEZE_NEXT_EVENT:
4133             grabinfo->sync.state = FROZEN_WITH_EVENT;
4134             FreezeThaw(thisDev, TRUE);
4135             if (!grabinfo->sync.event)
4136                 grabinfo->sync.event = calloc(1, sizeof(InternalEvent));
4137             *grabinfo->sync.event = event->device_event;
4138             break;
4139         }
4140     }
4142     free(core);
4143     free(xi);
4144     free(xi2);
4146     return deliveries;
4149 /* This function is used to set the key pressed or key released state -
4150    this is only used when the pressing of keys does not cause
4151    the device's processInputProc to be called, as in for example Mouse Keys.
4152 */
4153 void
4154 FixKeyState (DeviceEvent *event, DeviceIntPtr keybd)
4156     int key = event->detail.key;
4158     if (event->type == ET_KeyPress) {
4159         DebugF("FixKeyState: Key %d %s\n",key,
4160                ((event->type == ET_KeyPress) ? "down" : "up"));
4161     }
4163     if (event->type == ET_KeyPress)
4164         set_key_down(keybd, key, KEY_PROCESSED);
4165     else if (event->type == ET_KeyRelease)
4166         set_key_up(keybd, key, KEY_PROCESSED);
4167     else
4168         FatalError("Impossible keyboard event");
4171 #define AtMostOneClient \
4172         (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
4173 #define ManagerMask \
4174         (SubstructureRedirectMask | ResizeRedirectMask)
4176 /**
4177  * Recalculate which events may be deliverable for the given window.
4178  * Recalculated mask is used for quicker determination which events may be
4179  * delivered to a window.
4180  *
4181  * The otherEventMasks on a WindowOptional is the combination of all event
4182  * masks set by all clients on the window.
4183  * deliverableEventMask is the combination of the eventMask and the
4184  * otherEventMask plus the events that may be propagated to the parent.
4185  *
4186  * Traverses to siblings and parents of the window.
4187  */
4188 void
4189 RecalculateDeliverableEvents(WindowPtr pWin)
4191     OtherClients *others;
4192     WindowPtr pChild;
4194     pChild = pWin;
4195     while (1)
4196     {
4197         if (pChild->optional)
4198         {
4199             pChild->optional->otherEventMasks = 0;
4200             for (others = wOtherClients(pChild); others; others = others->next)
4201             {
4202                 pChild->optional->otherEventMasks |= others->mask;
4203             }
4204         }
4205         pChild->deliverableEvents = pChild->eventMask|
4206                                     wOtherEventMasks(pChild);
4207         if (pChild->parent)
4208             pChild->deliverableEvents |=
4209                 (pChild->parent->deliverableEvents &
4210                  ~wDontPropagateMask(pChild) & PropagateMask);
4211         if (pChild->firstChild)
4212         {
4213             pChild = pChild->firstChild;
4214             continue;
4215         }
4216         while (!pChild->nextSib && (pChild != pWin))
4217             pChild = pChild->parent;
4218         if (pChild == pWin)
4219             break;
4220         pChild = pChild->nextSib;
4221     }
4224 /**
4225  *
4226  *  \param value must conform to DeleteType
4227  */
4228 int
4229 OtherClientGone(pointer value, XID id)
4231     OtherClientsPtr other, prev;
4232     WindowPtr pWin = (WindowPtr)value;
4234     prev = 0;
4235     for (other = wOtherClients(pWin); other; other = other->next)
4236     {
4237         if (other->resource == id)
4238         {
4239             if (prev)
4240                 prev->next = other->next;
4241             else
4242             {
4243                 if (!(pWin->optional->otherClients = other->next))
4244                     CheckWindowOptionalNeed (pWin);
4245             }
4246             free(other);
4247             RecalculateDeliverableEvents(pWin);
4248             return Success;
4249         }
4250         prev = other;
4251     }
4252     FatalError("client not on event list");
4253     /*NOTREACHED*/
4254     return -1; /* make compiler happy */
4257 int
4258 EventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
4260     Mask check;
4261     OtherClients * others;
4262     DeviceIntPtr dev;
4263     int rc;
4265     if (mask & ~AllEventMasks)
4266     {
4267         client->errorValue = mask;
4268         return BadValue;
4269     }
4270     check = (mask & ManagerMask);
4271     if (check) {
4272         rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id,
4273                       RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess);
4274         if (rc != Success)
4275             return rc;
4276     }
4277     check = (mask & AtMostOneClient);
4278     if (check & (pWin->eventMask|wOtherEventMasks(pWin)))
4279     {                                  /* It is illegal for two different
4280                                           clients to select on any of the
4281                                           events for AtMostOneClient. However,
4282                                           it is OK, for some client to
4283                                           continue selecting on one of those
4284                                           events.  */
4285         if ((wClient(pWin) != client) && (check & pWin->eventMask))
4286             return BadAccess;
4287         for (others = wOtherClients (pWin); others; others = others->next)
4288         {
4289             if (!SameClient(others, client) && (check & others->mask))
4290                 return BadAccess;
4291         }
4292     }
4293     if (wClient (pWin) == client)
4294     {
4295         check = pWin->eventMask;
4296         pWin->eventMask = mask;
4297     }
4298     else
4299     {
4300         for (others = wOtherClients (pWin); others; others = others->next)
4301         {
4302             if (SameClient(others, client))
4303             {
4304                 check = others->mask;
4305                 if (mask == 0)
4306                 {
4307                     FreeResource(others->resource, RT_NONE);
4308                     return Success;
4309                 }
4310                 else
4311                     others->mask = mask;
4312                 goto maskSet;
4313             }
4314         }
4315         check = 0;
4316         if (!pWin->optional && !MakeWindowOptional (pWin))
4317             return BadAlloc;
4318         others = malloc(sizeof(OtherClients));
4319         if (!others)
4320             return BadAlloc;
4321         others->mask = mask;
4322         others->resource = FakeClientID(client->index);
4323         others->next = pWin->optional->otherClients;
4324         pWin->optional->otherClients = others;
4325         if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin))
4326             return BadAlloc;
4327     }
4328 maskSet:
4329     if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask))
4330     {
4331         for (dev = inputInfo.devices; dev; dev = dev->next)
4332         {
4333             if (dev->valuator && dev->valuator->motionHintWindow == pWin)
4334                 dev->valuator->motionHintWindow = NullWindow;
4335         }
4336     }
4337     RecalculateDeliverableEvents(pWin);
4338     return Success;
4341 int
4342 EventSuppressForWindow(WindowPtr pWin, ClientPtr client,
4343                        Mask mask, Bool *checkOptional)
4345     int i, free;
4347     if (mask & ~PropagateMask)
4348     {
4349         client->errorValue = mask;
4350         return BadValue;
4351     }
4352     if (pWin->dontPropagate)
4353         DontPropagateRefCnts[pWin->dontPropagate]--;
4354     if (!mask)
4355         i = 0;
4356     else
4357     {
4358         for (i = DNPMCOUNT, free = 0; --i > 0; )
4359         {
4360             if (!DontPropagateRefCnts[i])
4361                 free = i;
4362             else if (mask == DontPropagateMasks[i])
4363                 break;
4364         }
4365         if (!i && free)
4366         {
4367             i = free;
4368             DontPropagateMasks[i] = mask;
4369         }
4370     }
4371     if (i || !mask)
4372     {
4373         pWin->dontPropagate = i;
4374         if (i)
4375             DontPropagateRefCnts[i]++;
4376         if (pWin->optional)
4377         {
4378             pWin->optional->dontPropagateMask = mask;
4379             *checkOptional = TRUE;
4380         }
4381     }
4382     else
4383     {
4384         if (!pWin->optional && !MakeWindowOptional (pWin))
4385         {
4386             if (pWin->dontPropagate)
4387                 DontPropagateRefCnts[pWin->dontPropagate]++;
4388             return BadAlloc;
4389         }
4390         pWin->dontPropagate = 0;
4391         pWin->optional->dontPropagateMask = mask;
4392     }
4393     RecalculateDeliverableEvents(pWin);
4394     return Success;
4397 /**
4398  * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
4399  * Uses the paired keyboard to get some additional information.
4400  */
4401 void
4402 CoreEnterLeaveEvent(
4403     DeviceIntPtr mouse,
4404     int type,
4405     int mode,
4406     int detail,
4407     WindowPtr pWin,
4408     Window child)
4410     xEvent              event;
4411     WindowPtr           focus;
4412     DeviceIntPtr        keybd;
4413     GrabPtr             grab = mouse->deviceGrab.grab;
4414     Mask                mask;
4416     keybd = GetPairedDevice(mouse);
4418     if ((pWin == mouse->valuator->motionHintWindow) &&
4419         (detail != NotifyInferior))
4420         mouse->valuator->motionHintWindow = NullWindow;
4421     if (grab)
4422     {
4423         mask = (pWin == grab->window) ? grab->eventMask : 0;
4424         if (grab->ownerEvents)
4425             mask |= EventMaskForClient(pWin, rClient(grab));
4426     }
4427     else
4428     {
4429         mask = pWin->eventMask | wOtherEventMasks(pWin);
4430     }
4432     memset(&event, 0, sizeof(xEvent));
4433     event.u.u.type = type;
4434     event.u.u.detail = detail;
4435     event.u.enterLeave.time = currentTime.milliseconds;
4436     event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x;
4437     event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y;
4438     /* Counts on the same initial structure of crossing & button events! */
4439     FixUpEventFromWindow(mouse->spriteInfo->sprite, &event, pWin, None, FALSE);
4440     /* Enter/Leave events always set child */
4441     event.u.enterLeave.child = child;
4442     event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
4443         ELFlagSameScreen : 0;
4444     event.u.enterLeave.state = mouse->button ? (mouse->button->state & 0x1f00) : 0;
4445     if (keybd)
4446         event.u.enterLeave.state |=
4447                 XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
4448     event.u.enterLeave.mode = mode;
4449     focus = (keybd) ? keybd->focus->win : None;
4450     if ((focus != NoneWin) &&
4451             ((pWin == focus) || (focus == PointerRootWin) ||
4452              IsParent(focus, pWin)))
4453         event.u.enterLeave.flags |= ELFlagFocus;
4455     if ((mask & GetEventFilter(mouse, &event)))
4456     {
4457         if (grab)
4458             TryClientEvents(rClient(grab), mouse, &event, 1, mask,
4459                             GetEventFilter(mouse, &event), grab);
4460         else
4461             DeliverEventsToWindow(mouse, pWin, &event, 1,
4462                                   GetEventFilter(mouse, &event),
4463                                   NullGrab);
4464     }
4466     if ((type == EnterNotify) && (mask & KeymapStateMask))
4467     {
4468         xKeymapEvent ke;
4469         ClientPtr client = grab ? rClient(grab) : wClient(pWin);
4470         if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess))
4471             memset((char *)&ke.map[0], 0, 31);
4472         else
4473             memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31);
4475         ke.type = KeymapNotify;
4476         if (grab)
4477             TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1,
4478                             mask, KeymapStateMask, grab);
4479         else
4480             DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1,
4481                                   KeymapStateMask, NullGrab);
4482     }
4485 void
4486 DeviceEnterLeaveEvent(
4487     DeviceIntPtr mouse,
4488     int sourceid,
4489     int type,
4490     int mode,
4491     int detail,
4492     WindowPtr pWin,
4493     Window child)
4495     GrabPtr             grab = mouse->deviceGrab.grab;
4496     xXIEnterEvent       *event;
4497     int                 filter;
4498     int                 btlen, len, i;
4499     DeviceIntPtr        kbd;
4501     if ((mode == XINotifyPassiveGrab && type == XI_Leave) ||
4502         (mode == XINotifyPassiveUngrab && type == XI_Enter))
4503         return;
4505     btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
4506     btlen = bytes_to_int32(btlen);
4507     len = sizeof(xXIEnterEvent) + btlen * 4;
4509     event = calloc(1, len);
4510     event->type         = GenericEvent;
4511     event->extension    = IReqCode;
4512     event->evtype       = type;
4513     event->length       = (len - sizeof(xEvent))/4;
4514     event->buttons_len  = btlen;
4515     event->detail       = detail;
4516     event->time         = currentTime.milliseconds;
4517     event->deviceid     = mouse->id;
4518     event->sourceid     = sourceid;
4519     event->mode         = mode;
4520     event->root_x       = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
4521     event->root_y       = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
4523     for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
4524         if (BitIsOn(mouse->button->down, i))
4525             SetBit(&event[1], i);
4527     kbd = GetMaster(mouse, MASTER_KEYBOARD);
4528     if (kbd && kbd->key)
4529     {
4530         event->mods.base_mods = kbd->key->xkbInfo->state.base_mods;
4531         event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods;
4532         event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods;
4534         event->group.base_group = kbd->key->xkbInfo->state.base_group;
4535         event->group.latched_group = kbd->key->xkbInfo->state.latched_group;
4536         event->group.locked_group = kbd->key->xkbInfo->state.locked_group;
4537     }
4539     FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent*)event, pWin,
4540                          None, FALSE);
4542     filter = GetEventFilter(mouse, (xEvent*)event);
4544     if (grab)
4545     {
4546         Mask mask;
4547         mask = grab->xi2mask[XIAllDevices][type/8] |
4548                grab->xi2mask[XIAllMasterDevices][type/8] |
4549                grab->xi2mask[mouse->id][type/8];
4550         TryClientEvents(rClient(grab), mouse, (xEvent*)event, 1, mask,
4551                         filter, grab);
4552     } else {
4553         if (!GetWindowXI2Mask(mouse, pWin, (xEvent*)event))
4554             goto out;
4555         DeliverEventsToWindow(mouse, pWin, (xEvent*)event, 1, filter,
4556                               NullGrab);
4557     }
4559 out:
4560     free(event);
4563 void
4564 CoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
4566     xEvent event;
4568     memset(&event, 0, sizeof(xEvent));
4569     event.u.focus.mode = mode;
4570     event.u.u.type = type;
4571     event.u.u.detail = detail;
4572     event.u.focus.window = pWin->drawable.id;
4574     DeliverEventsToWindow(dev, pWin, &event, 1,
4575                           GetEventFilter(dev, &event), NullGrab);
4576     if ((type == FocusIn) &&
4577             ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
4578     {
4579         xKeymapEvent ke;
4580         ClientPtr client = wClient(pWin);
4581         if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess))
4582             memset((char *)&ke.map[0], 0, 31);
4583         else
4584             memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
4586         ke.type = KeymapNotify;
4587         DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1,
4588                 KeymapStateMask, NullGrab);
4589     }
4592 /**
4593  * Set the input focus to the given window. Subsequent keyboard events will be
4594  * delivered to the given window.
4595  *
4596  * Usually called from ProcSetInputFocus as result of a client request. If so,
4597  * the device is the inputInfo.keyboard.
4598  * If called from ProcXSetInputFocus as result of a client xinput request, the
4599  * device is set to the device specified by the client.
4600  *
4601  * @param client Client that requested input focus change.
4602  * @param dev Focus device.
4603  * @param focusID The window to obtain the focus. Can be PointerRoot or None.
4604  * @param revertTo Specifies where the focus reverts to when window becomes
4605  * unviewable.
4606  * @param ctime Specifies the time.
4607  * @param followOK True if pointer is allowed to follow the keyboard.
4608  */
4609 int
4610 SetInputFocus(
4611     ClientPtr client,
4612     DeviceIntPtr dev,
4613     Window focusID,
4614     CARD8 revertTo,
4615     Time ctime,
4616     Bool followOK)
4618     FocusClassPtr focus;
4619     WindowPtr focusWin;
4620     int mode, rc;
4621     TimeStamp time;
4622     DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */
4625     UpdateCurrentTime();
4626     if ((revertTo != RevertToParent) &&
4627         (revertTo != RevertToPointerRoot) &&
4628         (revertTo != RevertToNone) &&
4629         ((revertTo != RevertToFollowKeyboard) || !followOK))
4630     {
4631         client->errorValue = revertTo;
4632         return BadValue;
4633     }
4634     time = ClientTimeToServerTime(ctime);
4636     if (IsKeyboardDevice(dev))
4637         keybd = dev;
4638     else
4639         keybd = GetPairedDevice(dev);
4641     if ((focusID == None) || (focusID == PointerRoot))
4642         focusWin = (WindowPtr)(long)focusID;
4643     else if ((focusID == FollowKeyboard) && followOK)
4644     {
4645         focusWin = keybd->focus->win;
4646     }
4647     else {
4648         rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess);
4649         if (rc != Success)
4650             return rc;
4651         /* It is a match error to try to set the input focus to an
4652         unviewable window. */
4653         if(!focusWin->realized)
4654             return BadMatch;
4655     }
4656     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess);
4657     if (rc != Success)
4658         return Success;
4660     focus = dev->focus;
4661     if ((CompareTimeStamps(time, currentTime) == LATER) ||
4662         (CompareTimeStamps(time, focus->time) == EARLIER))
4663         return Success;
4664     mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal;
4665     if (focus->win == FollowKeyboardWin)
4666     {
4667         if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin))
4668             DoFocusEvents(dev, keybd->focus->win, focusWin, mode);
4669     } else
4670     {
4671         if (!ActivateFocusInGrab(dev, focus->win, focusWin))
4672             DoFocusEvents(dev, focus->win, focusWin, mode);
4673     }
4674     focus->time = time;
4675     focus->revert = revertTo;
4676     if (focusID == FollowKeyboard)
4677         focus->win = FollowKeyboardWin;
4678     else
4679         focus->win = focusWin;
4680     if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
4681         focus->traceGood = 0;
4682     else
4683     {
4684         int depth = 0;
4685         WindowPtr pWin;
4687         for (pWin = focusWin; pWin; pWin = pWin->parent) depth++;
4688         if (depth > focus->traceSize)
4689         {
4690             focus->traceSize = depth+1;
4691             focus->trace = realloc(focus->trace,
4692                                     focus->traceSize * sizeof(WindowPtr));
4693         }
4694         focus->traceGood = depth;
4695         for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
4696             focus->trace[depth] = pWin;
4697     }
4698     return Success;
4701 /**
4702  * Server-side protocol handling for SetInputFocus request.
4703  *
4704  * Sets the input focus for the virtual core keyboard.
4705  */
4706 int
4707 ProcSetInputFocus(ClientPtr client)
4709     DeviceIntPtr kbd = PickKeyboard(client);
4710     REQUEST(xSetInputFocusReq);
4712     REQUEST_SIZE_MATCH(xSetInputFocusReq);
4714     return SetInputFocus(client, kbd, stuff->focus,
4715                          stuff->revertTo, stuff->time, FALSE);
4718 /**
4719  * Server-side protocol handling for GetInputFocus request.
4720  *
4721  * Sends the current input focus for the client's keyboard back to the
4722  * client.
4723  */
4724 int
4725 ProcGetInputFocus(ClientPtr client)
4727     DeviceIntPtr kbd = PickKeyboard(client);
4728     xGetInputFocusReply rep;
4729     FocusClassPtr focus = kbd->focus;
4730     int rc;
4731     /* REQUEST(xReq); */
4732     REQUEST_SIZE_MATCH(xReq);
4734     rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess);
4735     if (rc != Success)
4736         return rc;
4738     memset(&rep, 0, sizeof(xGetInputFocusReply));
4739     rep.type = X_Reply;
4740     rep.length = 0;
4741     rep.sequenceNumber = client->sequence;
4742     if (focus->win == NoneWin)
4743         rep.focus = None;
4744     else if (focus->win == PointerRootWin)
4745         rep.focus = PointerRoot;
4746     else rep.focus = focus->win->drawable.id;
4747     rep.revertTo = focus->revert;
4748     WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
4749     return Success;
4752 /**
4753  * Server-side protocol handling for GrabPointer request.
4754  *
4755  * Sets an active grab on the client's ClientPointer and returns success
4756  * status to client.
4757  */
4758 int
4759 ProcGrabPointer(ClientPtr client)
4761     xGrabPointerReply rep;
4762     DeviceIntPtr device = PickPointer(client);
4763     GrabPtr grab;
4764     GrabMask mask;
4765     WindowPtr confineTo;
4766     CursorPtr oldCursor;
4767     REQUEST(xGrabPointerReq);
4768     TimeStamp time;
4769     int rc;
4771     REQUEST_SIZE_MATCH(xGrabPointerReq);
4772     UpdateCurrentTime();
4774     if (stuff->eventMask & ~PointerGrabMask)
4775     {
4776         client->errorValue = stuff->eventMask;
4777         return BadValue;
4778     }
4780     if (stuff->confineTo == None)
4781         confineTo = NullWindow;
4782     else
4783     {
4784         rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
4785                              DixSetAttrAccess);
4786         if (rc != Success)
4787             return rc;
4788     }
4790     memset(&rep, 0, sizeof(xGrabPointerReply));
4791     oldCursor = NullCursor;
4792     grab = device->deviceGrab.grab;
4794     if (grab)
4795     {
4796         if (grab->confineTo && !confineTo)
4797             ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE,
4798                                   FALSE);
4799         oldCursor = grab->cursor;
4800     }
4802     mask.core = stuff->eventMask;
4804     rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode,
4805                     stuff->grabWindow, stuff->ownerEvents, stuff->time,
4806                     &mask, GRABTYPE_CORE, stuff->cursor,
4807                     stuff->confineTo, &rep.status);
4808     if (rc != Success)
4809         return rc;
4811     if (oldCursor && rep.status == GrabSuccess)
4812         FreeCursor (oldCursor, (Cursor)0);
4814     time = ClientTimeToServerTime(stuff->time);
4815     rep.type = X_Reply;
4816     rep.sequenceNumber = client->sequence;
4817     rep.length = 0;
4818     WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
4819     return Success;
4822 /**
4823  * Server-side protocol handling for ChangeActivePointerGrab request.
4824  *
4825  * Changes properties of the grab hold by the client. If the client does not
4826  * hold an active grab on the device, nothing happens.
4827  */
4828 int
4829 ProcChangeActivePointerGrab(ClientPtr client)
4831     DeviceIntPtr device;
4832     GrabPtr      grab;
4833     CursorPtr newCursor, oldCursor;
4834     REQUEST(xChangeActivePointerGrabReq);
4835     TimeStamp time;
4837     REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
4838     if (stuff->eventMask & ~PointerGrabMask)
4839     {
4840         client->errorValue = stuff->eventMask;
4841         return BadValue;
4842     }
4843     if (stuff->cursor == None)
4844         newCursor = NullCursor;
4845     else
4846     {
4847         int rc = dixLookupResourceByType((pointer *)&newCursor, stuff->cursor,
4848                                          RT_CURSOR, client, DixUseAccess);
4849         if (rc != Success)
4850         {
4851             client->errorValue = stuff->cursor;
4852             return rc;
4853         }
4854     }
4856     device = PickPointer(client);
4857     grab = device->deviceGrab.grab;
4859     if (!grab)
4860         return Success;
4861     if (!SameClient(grab, client))
4862         return Success;
4863     time = ClientTimeToServerTime(stuff->time);
4864     if ((CompareTimeStamps(time, currentTime) == LATER) ||
4865              (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
4866         return Success;
4867     oldCursor = grab->cursor;
4868     grab->cursor = newCursor;
4869     if (newCursor)
4870         newCursor->refcnt++;
4871     PostNewCursor(device);
4872     if (oldCursor)
4873         FreeCursor(oldCursor, (Cursor)0);
4874     grab->eventMask = stuff->eventMask;
4875     return Success;
4878 /**
4879  * Server-side protocol handling for UngrabPointer request.
4880  *
4881  * Deletes a pointer grab on a device the client has grabbed.
4882  */
4883 int
4884 ProcUngrabPointer(ClientPtr client)
4886     DeviceIntPtr device = PickPointer(client);
4887     GrabPtr grab;
4888     TimeStamp time;
4889     REQUEST(xResourceReq);
4891     REQUEST_SIZE_MATCH(xResourceReq);
4892     UpdateCurrentTime();
4893     grab = device->deviceGrab.grab;
4895     time = ClientTimeToServerTime(stuff->id);
4896     if ((CompareTimeStamps(time, currentTime) != LATER) &&
4897             (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
4898             (grab) && SameClient(grab, client))
4899         (*device->deviceGrab.DeactivateGrab)(device);
4900     return Success;
4903 /**
4904  * Sets a grab on the given device.
4905  *
4906  * Called from ProcGrabKeyboard to work on the client's keyboard.
4907  * Called from ProcXGrabDevice to work on the device specified by the client.
4908  *
4909  * The parameters this_mode and other_mode represent the keyboard_mode and
4910  * pointer_mode parameters of XGrabKeyboard().
4911  * See man page for details on all the parameters
4912  *
4913  * @param client Client that owns the grab.
4914  * @param dev The device to grab.
4915  * @param this_mode GrabModeSync or GrabModeAsync
4916  * @param other_mode GrabModeSync or GrabModeAsync
4917  * @param status Return code to be returned to the caller.
4918  *
4919  * @returns Success or BadValue.
4920  */
4921 int
4922 GrabDevice(ClientPtr client, DeviceIntPtr dev,
4923            unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow,
4924            unsigned ownerEvents, Time ctime, GrabMask *mask,
4925            int grabtype, Cursor curs, Window confineToWin, CARD8 *status)
4927     WindowPtr pWin, confineTo;
4928     GrabPtr grab;
4929     TimeStamp time;
4930     Mask access_mode = DixGrabAccess;
4931     int rc;
4932     GrabInfoPtr grabInfo = &dev->deviceGrab;
4933     CursorPtr cursor;
4935     UpdateCurrentTime();
4936     if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync))
4937     {
4938         client->errorValue = keyboard_mode;
4939         return BadValue;
4940     }
4941     if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync))
4942     {
4943         client->errorValue = pointer_mode;
4944         return BadValue;
4945     }
4946     if ((ownerEvents != xFalse) && (ownerEvents != xTrue))
4947     {
4948         client->errorValue = ownerEvents;
4949         return BadValue;
4950     }
4952     rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
4953     if (rc != Success)
4954         return rc;
4956     if (confineToWin == None)
4957         confineTo = NullWindow;
4958     else
4959     {
4960         rc = dixLookupWindow(&confineTo, confineToWin, client,
4961                              DixSetAttrAccess);
4962         if (rc != Success)
4963             return rc;
4964     }
4966     if (curs == None)
4967         cursor = NullCursor;
4968     else
4969     {
4970         rc = dixLookupResourceByType((pointer *)&cursor, curs, RT_CURSOR,
4971                                client, DixUseAccess);
4972         if (rc != Success)
4973         {
4974             client->errorValue = curs;
4975             return rc;
4976         }
4977         access_mode |= DixForceAccess;
4978     }
4980     if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync)
4981         access_mode |= DixFreezeAccess;
4982     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
4983     if (rc != Success)
4984         return rc;
4986     time = ClientTimeToServerTime(ctime);
4987     grab = grabInfo->grab;
4988     if (grab && grab->grabtype != grabtype)
4989         *status = AlreadyGrabbed;
4990     if (grab && !SameClient(grab, client))
4991         *status = AlreadyGrabbed;
4992     else if ((!pWin->realized) ||
4993              (confineTo &&
4994                 !(confineTo->realized
4995                     && BorderSizeNotEmpty(dev, confineTo))))
4996         *status = GrabNotViewable;
4997     else if ((CompareTimeStamps(time, currentTime) == LATER) ||
4998              (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER))
4999         *status = GrabInvalidTime;
5000     else if (grabInfo->sync.frozen &&
5001              grabInfo->sync.other && !SameClient(grabInfo->sync.other, client))
5002         *status = GrabFrozen;
5003     else
5004     {
5005         GrabRec tempGrab;
5007         /* Otherwise segfaults happen on grabbed MPX devices */
5008         memset(&tempGrab, 0, sizeof(GrabRec));
5010         tempGrab.next = NULL;
5011         tempGrab.window = pWin;
5012         tempGrab.resource = client->clientAsMask;
5013         tempGrab.ownerEvents = ownerEvents;
5014         tempGrab.keyboardMode = keyboard_mode;
5015         tempGrab.pointerMode = pointer_mode;
5016         if (grabtype == GRABTYPE_CORE)
5017             tempGrab.eventMask = mask->core;
5018         else if (grabtype == GRABTYPE_XI)
5019             tempGrab.eventMask = mask->xi;
5020         else
5021             memcpy(tempGrab.xi2mask, mask->xi2mask, sizeof(tempGrab.xi2mask));
5022         tempGrab.device = dev;
5023         tempGrab.cursor = cursor;
5024         tempGrab.confineTo = confineTo;
5025         tempGrab.grabtype = grabtype;
5026         (*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE);
5027         *status = GrabSuccess;
5028     }
5029     return Success;
5032 /**
5033  * Server-side protocol handling for GrabKeyboard request.
5034  *
5035  * Grabs the client's keyboard and returns success status to client.
5036  */
5037 int
5038 ProcGrabKeyboard(ClientPtr client)
5040     xGrabKeyboardReply rep;
5041     REQUEST(xGrabKeyboardReq);
5042     int result;
5043     DeviceIntPtr keyboard = PickKeyboard(client);
5044     GrabMask mask;
5046     REQUEST_SIZE_MATCH(xGrabKeyboardReq);
5048     memset(&rep, 0, sizeof(xGrabKeyboardReply));
5049     mask.core = KeyPressMask | KeyReleaseMask;
5051     result = GrabDevice(client, keyboard, stuff->pointerMode,
5052             stuff->keyboardMode, stuff->grabWindow, stuff->ownerEvents,
5053             stuff->time, &mask, GRABTYPE_CORE, None, None,
5054             &rep.status);
5056     if (result != Success)
5057         return result;
5058     rep.type = X_Reply;
5059     rep.sequenceNumber = client->sequence;
5060     rep.length = 0;
5061     WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
5062     return Success;
5065 /**
5066  * Server-side protocol handling for UngrabKeyboard request.
5067  *
5068  * Deletes a possible grab on the client's keyboard.
5069  */
5070 int
5071 ProcUngrabKeyboard(ClientPtr client)
5073     DeviceIntPtr device = PickKeyboard(client);
5074     GrabPtr grab;
5075     TimeStamp time;
5076     REQUEST(xResourceReq);
5078     REQUEST_SIZE_MATCH(xResourceReq);
5079     UpdateCurrentTime();
5081     grab = device->deviceGrab.grab;
5083     time = ClientTimeToServerTime(stuff->id);
5084     if ((CompareTimeStamps(time, currentTime) != LATER) &&
5085         (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
5086         (grab) && SameClient(grab, client) && grab->grabtype == GRABTYPE_CORE)
5087         (*device->deviceGrab.DeactivateGrab)(device);
5088     return Success;
5091 /**
5092  * Server-side protocol handling for QueryPointer request.
5093  *
5094  * Returns the current state and position of the client's ClientPointer to the
5095  * client.
5096  */
5097 int
5098 ProcQueryPointer(ClientPtr client)
5100     xQueryPointerReply rep;
5101     WindowPtr pWin, t;
5102     DeviceIntPtr mouse = PickPointer(client);
5103     DeviceIntPtr keyboard;
5104     SpritePtr pSprite;
5105     int rc;
5106     REQUEST(xResourceReq);
5107     REQUEST_SIZE_MATCH(xResourceReq);
5109     rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
5110     if (rc != Success)
5111         return rc;
5112     rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
5113     if (rc != Success && rc != BadAccess)
5114         return rc;
5116     keyboard = GetPairedDevice(mouse);
5118     pSprite = mouse->spriteInfo->sprite;
5119     if (mouse->valuator->motionHintWindow)
5120         MaybeStopHint(mouse, client);
5121     memset(&rep, 0, sizeof(xQueryPointerReply));
5122     rep.type = X_Reply;
5123     rep.sequenceNumber = client->sequence;
5124     rep.mask = mouse->button ? (mouse->button->state) : 0;
5125     rep.mask |= XkbStateFieldFromRec(&keyboard->key->xkbInfo->state);
5126     rep.length = 0;
5127     rep.root = (GetCurrentRootWindow(mouse))->drawable.id;
5128     rep.rootX = pSprite->hot.x;
5129     rep.rootY = pSprite->hot.y;
5130     rep.child = None;
5131     if (pSprite->hot.pScreen == pWin->drawable.pScreen)
5132     {
5133         rep.sameScreen = xTrue;
5134         rep.winX = pSprite->hot.x - pWin->drawable.x;
5135         rep.winY = pSprite->hot.y - pWin->drawable.y;
5136         for (t = pSprite->win; t; t = t->parent)
5137             if (t->parent == pWin)
5138             {
5139                 rep.child = t->drawable.id;
5140                 break;
5141             }
5142     }
5143     else
5144     {
5145         rep.sameScreen = xFalse;
5146         rep.winX = 0;
5147         rep.winY = 0;
5148     }
5150 #ifdef PANORAMIX
5151     if(!noPanoramiXExtension) {
5152         rep.rootX += screenInfo.screens[0]->x;
5153         rep.rootY += screenInfo.screens[0]->y;
5154         if(stuff->id == rep.root) {
5155             rep.winX += screenInfo.screens[0]->x;
5156             rep.winY += screenInfo.screens[0]->y;
5157         }
5158     }
5159 #endif
5161     if (rc == BadAccess) {
5162         rep.mask = 0;
5163         rep.child = None;
5164         rep.rootX = 0;
5165         rep.rootY = 0;
5166         rep.winX = 0;
5167         rep.winY = 0;
5168     }
5170     WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
5172     return Success;
5175 /**
5176  * Initializes the device list and the DIX sprite to sane values. Allocates
5177  * trace memory used for quick window traversal.
5178  */
5179 void
5180 InitEvents(void)
5182     int i;
5184     inputInfo.numDevices = 0;
5185     inputInfo.devices = (DeviceIntPtr)NULL;
5186     inputInfo.off_devices = (DeviceIntPtr)NULL;
5187     inputInfo.keyboard = (DeviceIntPtr)NULL;
5188     inputInfo.pointer = (DeviceIntPtr)NULL;
5189     for (i = 0; i < MAXDEVICES; i++)
5190     {
5191         memcpy(&filters[i], default_filter, sizeof(default_filter));
5192     }
5194     syncEvents.replayDev = (DeviceIntPtr)NULL;
5195     syncEvents.replayWin = NullWindow;
5196     while (syncEvents.pending)
5197     {
5198         QdEventPtr next = syncEvents.pending->next;
5199         free(syncEvents.pending);
5200         syncEvents.pending = next;
5201     }
5202     syncEvents.pendtail = &syncEvents.pending;
5203     syncEvents.playingEvents = FALSE;
5204     syncEvents.time.months = 0;
5205     syncEvents.time.milliseconds = 0;   /* hardly matters */
5206     currentTime.months = 0;
5207     currentTime.milliseconds = GetTimeInMillis();
5208     lastDeviceEventTime = currentTime;
5209     for (i = 0; i < DNPMCOUNT; i++)
5210     {
5211         DontPropagateMasks[i] = 0;
5212         DontPropagateRefCnts[i] = 0;
5213     }
5215     InputEventList = InitEventList(GetMaximumEventsNum());
5216     if (!InputEventList)
5217         FatalError("[dix] Failed to allocate input event list.\n");
5220 void
5221 CloseDownEvents(void)
5223     FreeEventList(InputEventList, GetMaximumEventsNum());
5224     InputEventList = NULL;
5227 #define SEND_EVENT_BIT 0x80
5229 /**
5230  * Server-side protocol handling for SendEvent request.
5231  *
5232  * Locates the window to send the event to and forwards the event.
5233  */
5234 int
5235 ProcSendEvent(ClientPtr client)
5237     WindowPtr pWin;
5238     WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
5239     DeviceIntPtr dev = PickPointer(client);
5240     DeviceIntPtr keybd = GetPairedDevice(dev);
5241     SpritePtr pSprite = dev->spriteInfo->sprite;
5242     REQUEST(xSendEventReq);
5244     REQUEST_SIZE_MATCH(xSendEventReq);
5246     /* libXext and other extension libraries may set the bit indicating
5247      * that this event came from a SendEvent request so remove it
5248      * since otherwise the event type may fail the range checks
5249      * and cause an invalid BadValue error to be returned.
5250      *
5251      * This is safe to do since we later add the SendEvent bit (0x80)
5252      * back in once we send the event to the client */
5254     stuff->event.u.u.type &= ~(SEND_EVENT_BIT);
5256     /* The client's event type must be a core event type or one defined by an
5257         extension. */
5259     if ( ! ((stuff->event.u.u.type > X_Reply &&
5260              stuff->event.u.u.type < LASTEvent) ||
5261             (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
5262              stuff->event.u.u.type < (unsigned)lastEvent)))
5263     {
5264         client->errorValue = stuff->event.u.u.type;
5265         return BadValue;
5266     }
5267     if (stuff->event.u.u.type == ClientMessage &&
5268         stuff->event.u.u.detail != 8 &&
5269         stuff->event.u.u.detail != 16 &&
5270         stuff->event.u.u.detail != 32)
5271     {
5272         client->errorValue = stuff->event.u.u.detail;
5273         return BadValue;
5274     }
5275     if (stuff->eventMask & ~AllEventMasks)
5276     {
5277         client->errorValue = stuff->eventMask;
5278         return BadValue;
5279     }
5281     if (stuff->destination == PointerWindow)
5282         pWin = pSprite->win;
5283     else if (stuff->destination == InputFocus)
5284     {
5285         WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin;
5287         if (inputFocus == NoneWin)
5288             return Success;
5290         /* If the input focus is PointerRootWin, send the event to where
5291         the pointer is if possible, then perhaps propogate up to root. */
5292         if (inputFocus == PointerRootWin)
5293             inputFocus = GetCurrentRootWindow(dev);
5295         if (IsParent(inputFocus, pSprite->win))
5296         {
5297             effectiveFocus = inputFocus;
5298             pWin = pSprite->win;
5299         }
5300         else
5301             effectiveFocus = pWin = inputFocus;
5302     }
5303     else
5304         dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess);
5306     if (!pWin)
5307         return BadWindow;
5308     if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue))
5309     {
5310         client->errorValue = stuff->propagate;
5311         return BadValue;
5312     }
5313     stuff->event.u.u.type |= SEND_EVENT_BIT;
5314     if (stuff->propagate)
5315     {
5316         for (;pWin; pWin = pWin->parent)
5317         {
5318             if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin,
5319                          &stuff->event, 1))
5320                 return Success;
5321             if (DeliverEventsToWindow(dev, pWin,
5322                         &stuff->event, 1, stuff->eventMask, NullGrab))
5323                 return Success;
5324             if (pWin == effectiveFocus)
5325                 return Success;
5326             stuff->eventMask &= ~wDontPropagateMask(pWin);
5327             if (!stuff->eventMask)
5328                 break;
5329         }
5330     }
5331     else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1))
5332         DeliverEventsToWindow(dev, pWin, &stuff->event,
5333                                     1, stuff->eventMask, NullGrab);
5334     return Success;
5337 /**
5338  * Server-side protocol handling for UngrabKey request.
5339  *
5340  * Deletes a passive grab for the given key. Works on the
5341  * client's keyboard.
5342  */
5343 int
5344 ProcUngrabKey(ClientPtr client)
5346     REQUEST(xUngrabKeyReq);
5347     WindowPtr pWin;
5348     GrabRec tempGrab;
5349     DeviceIntPtr keybd = PickKeyboard(client);
5350     int rc;
5352     REQUEST_SIZE_MATCH(xUngrabKeyReq);
5353     rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess);
5354     if (rc != Success)
5355         return rc;
5357     if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
5358          (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
5359         && (stuff->key != AnyKey))
5360     {
5361         client->errorValue = stuff->key;
5362         return BadValue;
5363     }
5364     if ((stuff->modifiers != AnyModifier) &&
5365         (stuff->modifiers & ~AllModifiersMask))
5366     {
5367         client->errorValue = stuff->modifiers;
5368         return BadValue;
5369     }
5370     tempGrab.resource = client->clientAsMask;
5371     tempGrab.device = keybd;
5372     tempGrab.window = pWin;
5373     tempGrab.modifiersDetail.exact = stuff->modifiers;
5374     tempGrab.modifiersDetail.pMask = NULL;
5375     tempGrab.modifierDevice = keybd;
5376     tempGrab.type = KeyPress;
5377     tempGrab.grabtype = GRABTYPE_CORE;
5378     tempGrab.detail.exact = stuff->key;
5379     tempGrab.detail.pMask = NULL;
5380     tempGrab.next = NULL;
5382     if (!DeletePassiveGrabFromList(&tempGrab))
5383         return BadAlloc;
5384     return Success;
5387 /**
5388  * Server-side protocol handling for GrabKey request.
5389  *
5390  * Creates a grab for the client's keyboard and adds it to the list of passive
5391  * grabs.
5392  */
5393 int
5394 ProcGrabKey(ClientPtr client)
5396     WindowPtr pWin;
5397     REQUEST(xGrabKeyReq);
5398     GrabPtr grab;
5399     DeviceIntPtr keybd = PickKeyboard(client);
5400     int rc;
5401     GrabParameters param;
5402     GrabMask mask;
5404     REQUEST_SIZE_MATCH(xGrabKeyReq);
5406     memset(&param, 0, sizeof(param));
5407     param.grabtype = GRABTYPE_CORE;
5408     param.ownerEvents = stuff->ownerEvents;
5409     param.this_device_mode = stuff->keyboardMode;
5410     param.other_devices_mode = stuff->pointerMode;
5411     param.modifiers = stuff->modifiers;
5413     rc = CheckGrabValues(client, &param);
5414     if (rc != Success)
5415         return rc;
5417     if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
5418          (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
5419         && (stuff->key != AnyKey))
5420     {
5421         client->errorValue = stuff->key;
5422         return BadValue;
5423     }
5424     rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
5425     if (rc != Success)
5426         return rc;
5429     mask.core = (KeyPressMask | KeyReleaseMask);
5431     grab = CreateGrab(client->index, keybd, keybd, pWin, GRABTYPE_CORE, &mask,
5432                       &param, KeyPress, stuff->key, NullWindow, NullCursor);
5433     if (!grab)
5434         return BadAlloc;
5435     return AddPassiveGrabToList(client, grab);
5439 /**
5440  * Server-side protocol handling for GrabButton request.
5441  *
5442  * Creates a grab for the client's ClientPointer and adds it as a passive grab
5443  * to the list.
5444  */
5445 int
5446 ProcGrabButton(ClientPtr client)
5448     WindowPtr pWin, confineTo;
5449     REQUEST(xGrabButtonReq);
5450     CursorPtr cursor;
5451     GrabPtr grab;
5452     DeviceIntPtr ptr, modifierDevice;
5453     Mask access_mode = DixGrabAccess;
5454     GrabMask mask;
5455     GrabParameters param;
5456     int rc;
5458     REQUEST_SIZE_MATCH(xGrabButtonReq);
5459     if ((stuff->pointerMode != GrabModeSync) &&
5460         (stuff->pointerMode != GrabModeAsync))
5461     {
5462         client->errorValue = stuff->pointerMode;
5463         return BadValue;
5464     }
5465     if ((stuff->keyboardMode != GrabModeSync) &&
5466         (stuff->keyboardMode != GrabModeAsync))
5467     {
5468         client->errorValue = stuff->keyboardMode;
5469         return BadValue;
5470     }
5471     if ((stuff->modifiers != AnyModifier) &&
5472         (stuff->modifiers & ~AllModifiersMask))
5473     {
5474         client->errorValue = stuff->modifiers;
5475         return BadValue;
5476     }
5477     if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
5478     {
5479         client->errorValue = stuff->ownerEvents;
5480         return BadValue;
5481     }
5482     if (stuff->eventMask & ~PointerGrabMask)
5483     {
5484         client->errorValue = stuff->eventMask;
5485         return BadValue;
5486     }
5487     rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
5488     if (rc != Success)
5489         return rc;
5490     if (stuff->confineTo == None)
5491        confineTo = NullWindow;
5492     else {
5493         rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
5494                              DixSetAttrAccess);
5495         if (rc != Success)
5496             return rc;
5497     }
5498     if (stuff->cursor == None)
5499         cursor = NullCursor;
5500     else
5501     {
5502         rc = dixLookupResourceByType((pointer *)&cursor, stuff->cursor, RT_CURSOR,
5503                                client, DixUseAccess);
5504         if (rc != Success)
5505         {
5506             client->errorValue = stuff->cursor;
5507             return rc;
5508         }
5509         access_mode |= DixForceAccess;
5510     }
5512     ptr = PickPointer(client);
5513     modifierDevice = GetPairedDevice(ptr);
5514     if (stuff->pointerMode == GrabModeSync ||
5515         stuff->keyboardMode == GrabModeSync)
5516         access_mode |= DixFreezeAccess;
5517     rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode);
5518     if (rc != Success)
5519         return rc;
5521     memset(&param, 0, sizeof(param));
5522     param.grabtype = GRABTYPE_CORE;
5523     param.ownerEvents = stuff->ownerEvents;
5524     param.this_device_mode = stuff->keyboardMode;
5525     param.other_devices_mode = stuff->pointerMode;
5526     param.modifiers = stuff->modifiers;
5528     mask.core = stuff->eventMask;
5530     grab = CreateGrab(client->index, ptr, modifierDevice, pWin,
5531                       GRABTYPE_CORE, &mask, &param, ButtonPress,
5532                       stuff->button, confineTo, cursor);
5533     if (!grab)
5534         return BadAlloc;
5535     return AddPassiveGrabToList(client, grab);
5538 /**
5539  * Server-side protocol handling for UngrabButton request.
5540  *
5541  * Deletes a passive grab on the client's ClientPointer from the list.
5542  */
5543 int
5544 ProcUngrabButton(ClientPtr client)
5546     REQUEST(xUngrabButtonReq);
5547     WindowPtr pWin;
5548     GrabRec tempGrab;
5549     int rc;
5550     DeviceIntPtr ptr;
5552     REQUEST_SIZE_MATCH(xUngrabButtonReq);
5553     if ((stuff->modifiers != AnyModifier) &&
5554         (stuff->modifiers & ~AllModifiersMask))
5555     {
5556         client->errorValue = stuff->modifiers;
5557         return BadValue;
5558     }
5559     rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
5560     if (rc != Success)
5561         return rc;
5563     ptr = PickPointer(client);
5565     tempGrab.resource = client->clientAsMask;
5566     tempGrab.device = ptr;
5567     tempGrab.window = pWin;
5568     tempGrab.modifiersDetail.exact = stuff->modifiers;
5569     tempGrab.modifiersDetail.pMask = NULL;
5570     tempGrab.modifierDevice = GetPairedDevice(ptr);
5571     tempGrab.type = ButtonPress;
5572     tempGrab.detail.exact = stuff->button;
5573     tempGrab.grabtype = GRABTYPE_CORE;
5574     tempGrab.detail.pMask = NULL;
5575     tempGrab.next = NULL;
5577     if (!DeletePassiveGrabFromList(&tempGrab))
5578         return BadAlloc;
5579     return Success;
5582 /**
5583  * Deactivate any grab that may be on the window, remove the focus.
5584  * Delete any XInput extension events from the window too. Does not change the
5585  * window mask. Use just before the window is deleted.
5586  *
5587  * If freeResources is set, passive grabs on the window are deleted.
5588  *
5589  * @param pWin The window to delete events from.
5590  * @param freeResources True if resources associated with the window should be
5591  * deleted.
5592  */
5593 void
5594 DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
5596     WindowPtr           parent;
5597     DeviceIntPtr        mouse = inputInfo.pointer;
5598     DeviceIntPtr        keybd = inputInfo.keyboard;
5599     FocusClassPtr       focus;
5600     OtherClientsPtr     oc;
5601     GrabPtr             passive;
5602     GrabPtr             grab;
5605     /* Deactivate any grabs performed on this window, before making any
5606         input focus changes. */
5607     grab = mouse->deviceGrab.grab;
5608     if (grab &&
5609         ((grab->window == pWin) || (grab->confineTo == pWin)))
5610         (*mouse->deviceGrab.DeactivateGrab)(mouse);
5613     /* Deactivating a keyboard grab should cause focus events. */
5614     grab = keybd->deviceGrab.grab;
5615     if (grab && (grab->window == pWin))
5616         (*keybd->deviceGrab.DeactivateGrab)(keybd);
5618     /* And now the real devices */
5619     for (mouse = inputInfo.devices; mouse; mouse = mouse->next)
5620     {
5621         grab = mouse->deviceGrab.grab;
5622         if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
5623             (*mouse->deviceGrab.DeactivateGrab)(mouse);
5624     }
5627     for (keybd = inputInfo.devices; keybd; keybd = keybd->next)
5628     {
5629         if (IsKeyboardDevice(keybd))
5630         {
5631             focus = keybd->focus;
5633             /* If the focus window is a root window (ie. has no parent) then don't
5634                delete the focus from it. */
5636             if ((pWin == focus->win) && (pWin->parent != NullWindow))
5637             {
5638                 int focusEventMode = NotifyNormal;
5640                 /* If a grab is in progress, then alter the mode of focus events. */
5642                 if (keybd->deviceGrab.grab)
5643                     focusEventMode = NotifyWhileGrabbed;
5645                 switch (focus->revert)
5646                 {
5647                     case RevertToNone:
5648                         DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
5649                         focus->win = NoneWin;
5650                         focus->traceGood = 0;
5651                         break;
5652                     case RevertToParent:
5653                         parent = pWin;
5654                         do
5655                         {
5656                             parent = parent->parent;
5657                             focus->traceGood--;
5658                         } while (!parent->realized
5659                                 /* This would be a good protocol change -- windows being reparented
5660                                    during SaveSet processing would cause the focus to revert to the
5661                                    nearest enclosing window which will survive the death of the exiting
5662                                    client, instead of ending up reverting to a dying window and thence
5663                                    to None
5664                                  */
5665 #ifdef NOTDEF
5666                                  || wClient(parent)->clientGone
5667 #endif
5668                                 );
5669                         if (!ActivateFocusInGrab(keybd, pWin, parent))
5670                             DoFocusEvents(keybd, pWin, parent, focusEventMode);
5671                         focus->win = parent;
5672                         focus->revert = RevertToNone;
5673                         break;
5674                     case RevertToPointerRoot:
5675                         if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin))
5676                             DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode);
5677                         focus->win = PointerRootWin;
5678                         focus->traceGood = 0;
5679                         break;
5680                 }
5681             }
5682         }
5684         if (IsPointerDevice(keybd))
5685         {
5686             if (keybd->valuator->motionHintWindow == pWin)
5687                 keybd->valuator->motionHintWindow = NullWindow;
5688         }
5689     }
5691     if (freeResources)
5692     {
5693         if (pWin->dontPropagate)
5694             DontPropagateRefCnts[pWin->dontPropagate]--;
5695         while ( (oc = wOtherClients(pWin)) )
5696             FreeResource(oc->resource, RT_NONE);
5697         while ( (passive = wPassiveGrabs(pWin)) )
5698             FreeResource(passive->resource, RT_NONE);
5699      }
5701     DeleteWindowFromAnyExtEvents(pWin, freeResources);
5704 /**
5705  * Call this whenever some window at or below pWin has changed geometry. If
5706  * there is a grab on the window, the cursor will be re-confined into the
5707  * window.
5708  */
5709 void
5710 CheckCursorConfinement(WindowPtr pWin)
5712     GrabPtr grab;
5713     WindowPtr confineTo;
5714     DeviceIntPtr pDev;
5716 #ifdef PANORAMIX
5717     if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return;
5718 #endif
5720     for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
5721     {
5722         if (DevHasCursor(pDev))
5723         {
5724             grab = pDev->deviceGrab.grab;
5725             if (grab && (confineTo = grab->confineTo))
5726             {
5727                 if (!BorderSizeNotEmpty(pDev, confineTo))
5728                     (*pDev->deviceGrab.DeactivateGrab)(pDev);
5729                 else if ((pWin == confineTo) || IsParent(pWin, confineTo))
5730                     ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
5731             }
5732         }
5733     }
5736 Mask
5737 EventMaskForClient(WindowPtr pWin, ClientPtr client)
5739     OtherClientsPtr     other;
5741     if (wClient (pWin) == client)
5742         return pWin->eventMask;
5743     for (other = wOtherClients(pWin); other; other = other->next)
5744     {
5745         if (SameClient(other, client))
5746             return other->mask;
5747     }
5748     return 0;
5751 /**
5752  * Server-side protocol handling for RecolorCursor request.
5753  */
5754 int
5755 ProcRecolorCursor(ClientPtr client)
5757     CursorPtr pCursor;
5758     int         rc, nscr;
5759     ScreenPtr   pscr;
5760     Bool        displayed;
5761     SpritePtr   pSprite = PickPointer(client)->spriteInfo->sprite;
5762     REQUEST(xRecolorCursorReq);
5764     REQUEST_SIZE_MATCH(xRecolorCursorReq);
5765     rc = dixLookupResourceByType((pointer *)&pCursor, stuff->cursor, RT_CURSOR,
5766                            client, DixWriteAccess);
5767     if (rc != Success)
5768     {
5769         client->errorValue = stuff->cursor;
5770         return rc;
5771     }
5773     pCursor->foreRed = stuff->foreRed;
5774     pCursor->foreGreen = stuff->foreGreen;
5775     pCursor->foreBlue = stuff->foreBlue;
5777     pCursor->backRed = stuff->backRed;
5778     pCursor->backGreen = stuff->backGreen;
5779     pCursor->backBlue = stuff->backBlue;
5781     for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
5782     {
5783         pscr = screenInfo.screens[nscr];
5784 #ifdef PANORAMIX
5785         if(!noPanoramiXExtension)
5786             displayed = (pscr == pSprite->screen);
5787         else
5788 #endif
5789             displayed = (pscr == pSprite->hotPhys.pScreen);
5790         ( *pscr->RecolorCursor)(PickPointer(client), pscr, pCursor,
5791                                 (pCursor == pSprite->current) && displayed);
5792     }
5793     return Success;
5796 /**
5797  * Write the given events to a client, swapping the byte order if necessary.
5798  * To swap the byte ordering, a callback is called that has to be set up for
5799  * the given event type.
5800  *
5801  * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
5802  * can be more than one. Usually it's just one event.
5803  *
5804  * Do not modify the event structure passed in. See comment below.
5805  *
5806  * @param pClient Client to send events to.
5807  * @param count Number of events.
5808  * @param events The event list.
5809  */
5810 void
5811 WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
5813 #ifdef PANORAMIX
5814     xEvent    eventCopy;
5815 #endif
5816     xEvent    *eventTo, *eventFrom;
5817     int       i,
5818               eventlength = sizeof(xEvent);
5820     if (!pClient || pClient == serverClient || pClient->clientGone)
5821         return;
5823     for (i = 0; i < count; i++)
5824         if ((events[i].u.u.type & 0x7f) != KeymapNotify)
5825             events[i].u.u.sequenceNumber = pClient->sequence;
5827     /* Let XKB rewrite the state, as it depends on client preferences. */
5828     XkbFilterEvents(pClient, count, events);
5830 #ifdef PANORAMIX
5831     if(!noPanoramiXExtension &&
5832        (screenInfo.screens[0]->x || screenInfo.screens[0]->y))
5833     {
5834         switch(events->u.u.type) {
5835         case MotionNotify:
5836         case ButtonPress:
5837         case ButtonRelease:
5838         case KeyPress:
5839         case KeyRelease:
5840         case EnterNotify:
5841         case LeaveNotify:
5842         /*
5843            When multiple clients want the same event DeliverEventsToWindow
5844            passes the same event structure multiple times so we can't
5845            modify the one passed to us
5846         */
5847             count = 1;  /* should always be 1 */
5848             memcpy(&eventCopy, events, sizeof(xEvent));
5849             eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x;
5850             eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y;
5851             if(eventCopy.u.keyButtonPointer.event ==
5852                eventCopy.u.keyButtonPointer.root)
5853             {
5854                 eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x;
5855                 eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y;
5856             }
5857             events = &eventCopy;
5858             break;
5859         default: break;
5860         }
5861     }
5862 #endif
5864     if (EventCallback)
5865     {
5866         EventInfoRec eventinfo;
5867         eventinfo.client = pClient;
5868         eventinfo.events = events;
5869         eventinfo.count = count;
5870         CallCallbacks(&EventCallback, (pointer)&eventinfo);
5871     }
5872 #ifdef XSERVER_DTRACE
5873     if (XSERVER_SEND_EVENT_ENABLED()) {
5874         for (i = 0; i < count; i++)
5875         {
5876             XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]);
5877         }
5878     }
5879 #endif
5880     /* Just a safety check to make sure we only have one GenericEvent, it just
5881      * makes things easier for me right now. (whot) */
5882     for (i = 1; i < count; i++)
5883     {
5884         if (events[i].u.u.type == GenericEvent)
5885         {
5886             ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n");
5887             return;
5888         }
5889     }
5891     if (events->u.u.type == GenericEvent)
5892     {
5893         eventlength += ((xGenericEvent*)events)->length * 4;
5894     }
5896     if(pClient->swapped)
5897     {
5898         if (eventlength > swapEventLen)
5899         {
5900             swapEventLen = eventlength;
5901             swapEvent = realloc(swapEvent, swapEventLen);
5902             if (!swapEvent)
5903             {
5904                 FatalError("WriteEventsToClient: Out of memory.\n");
5905                 return;
5906             }
5907         }
5909         for(i = 0; i < count; i++)
5910         {
5911             eventFrom = &events[i];
5912             eventTo = swapEvent;
5914             /* Remember to strip off the leading bit of type in case
5915                this event was sent with "SendEvent." */
5916             (*EventSwapVector[eventFrom->u.u.type & 0177])
5917                 (eventFrom, eventTo);
5919             WriteToClient(pClient, eventlength, (char *)eventTo);
5920         }
5921     }
5922     else
5923     {
5924         /* only one GenericEvent, remember? that means either count is 1 and
5925          * eventlength is arbitrary or eventlength is 32 and count doesn't
5926          * matter. And we're all set. Woohoo. */
5927         WriteToClient(pClient, count * eventlength, (char *) events);
5928     }
5931 /*
5932  * Set the client pointer for the given client.
5933  *
5934  * A client can have exactly one ClientPointer. Each time a
5935  * request/reply/event is processed and the choice of devices is ambiguous
5936  * (e.g. QueryPointer request), the server will pick the ClientPointer (see
5937  * PickPointer()).
5938  * If a keyboard is needed, the first keyboard paired with the CP is used.
5939  */
5940 int
5941 SetClientPointer(ClientPtr client, DeviceIntPtr device)
5943     int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess);
5944     if (rc != Success)
5945         return rc;
5947     if (!IsMaster(device))
5948     {
5949         ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n");
5950         return BadDevice;
5951     } else if (!device->spriteInfo->spriteOwner)
5952     {
5953         ErrorF("[dix] Device %d does not have a sprite. "
5954                 "Cannot be ClientPointer\n", device->id);
5955         return BadDevice;
5956     }
5957     client->clientPtr = device;
5958     return Success;
5961 /* PickPointer will pick an appropriate pointer for the given client.
5962  *
5963  * An "appropriate device" is (in order of priority):
5964  *  1) A device the given client has a core grab on.
5965  *  2) A device set as ClientPointer for the given client.
5966  *  3) The first master device.
5967  */
5968 DeviceIntPtr
5969 PickPointer(ClientPtr client)
5971     DeviceIntPtr it = inputInfo.devices;
5973     /* First, check if the client currently has a grab on a device. Even
5974      * keyboards count. */
5975     for(it = inputInfo.devices; it; it = it->next)
5976     {
5977         GrabPtr grab = it->deviceGrab.grab;
5978         if (grab && grab->grabtype == GRABTYPE_CORE && SameClient(grab, client))
5979         {
5980             it = GetMaster(it, MASTER_POINTER);
5981             return it; /* Always return a core grabbed device */
5982         }
5983     }
5985     if (!client->clientPtr)
5986     {
5987         it = inputInfo.devices;
5988         while (it)
5989         {
5990             if (IsMaster(it) && it->spriteInfo->spriteOwner)
5991             {
5992                 client->clientPtr = it;
5993                 break;
5994             }
5995             it = it->next;
5996         }
5997     }
5998     return client->clientPtr;
6001 /* PickKeyboard will pick an appropriate keyboard for the given client by
6002  * searching the list of devices for the keyboard device that is paired with
6003  * the client's pointer.
6004  */
6005 DeviceIntPtr
6006 PickKeyboard(ClientPtr client)
6008     DeviceIntPtr ptr = PickPointer(client);
6009     DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD);
6011     if (!kbd)
6012     {
6013         ErrorF("[dix] ClientPointer not paired with a keyboard. This "
6014                 "is a bug.\n");
6015     }
6017     return kbd;
6020 /* A client that has one or more core grabs does not get core events from
6021  * devices it does not have a grab on. Legacy applications behave bad
6022  * otherwise because they are not used to it and the events interfere.
6023  * Only applies for core events.
6024  *
6025  * Return true if a core event from the device would interfere and should not
6026  * be delivered.
6027  */
6028 Bool
6029 IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event)
6031     DeviceIntPtr it = inputInfo.devices;
6033     switch(event->u.u.type)
6034     {
6035         case KeyPress:
6036         case KeyRelease:
6037         case ButtonPress:
6038         case ButtonRelease:
6039         case MotionNotify:
6040         case EnterNotify:
6041         case LeaveNotify:
6042             break;
6043         default:
6044             return FALSE;
6045     }
6047     if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
6048         return FALSE;
6050     while(it)
6051     {
6052         if (it != dev)
6053         {
6054             if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client)
6055                         && !it->deviceGrab.fromPassiveGrab)
6056             {
6057                 if ((IsPointerDevice(it) && IsPointerDevice(dev)) ||
6058                         (IsKeyboardDevice(it) && IsKeyboardDevice(dev)))
6059                     return TRUE;
6060             }
6061         }
6062         it = it->next;
6063     }
6065     return FALSE;