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