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