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