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