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