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