105b261ecSmrg/************************************************************
205b261ecSmrg
305b261ecSmrgCopyright 1987, 1998  The Open Group
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthe above copyright notice appear in all copies and that both that
805b261ecSmrgcopyright notice and this permission notice appear in supporting
905b261ecSmrgdocumentation.
1005b261ecSmrg
1105b261ecSmrgThe above copyright notice and this permission notice shall be included in
1205b261ecSmrgall copies or substantial portions of the Software.
1305b261ecSmrg
1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2005b261ecSmrg
2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be
2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings
2305b261ecSmrgin this Software without prior written authorization from The Open Group.
2405b261ecSmrg
2505b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
2605b261ecSmrg
2705b261ecSmrg                        All Rights Reserved
2805b261ecSmrg
294642e01fSmrgPermission to use, copy, modify, and distribute this software and its
304642e01fSmrgdocumentation for any purpose and without fee is hereby granted,
3105b261ecSmrgprovided that the above copyright notice appear in all copies and that
324642e01fSmrgboth that copyright notice and this permission notice appear in
3305b261ecSmrgsupporting documentation, and that the name of Digital not be
3405b261ecSmrgused in advertising or publicity pertaining to distribution of the
354642e01fSmrgsoftware without specific, written prior permission.
3605b261ecSmrg
3705b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
3805b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
3905b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
4005b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
4205b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4305b261ecSmrgSOFTWARE.
4405b261ecSmrg
4505b261ecSmrg********************************************************/
4605b261ecSmrg
4705b261ecSmrg/* The panoramix components contained the following notice */
4805b261ecSmrg/*****************************************************************
4905b261ecSmrg
5005b261ecSmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
5105b261ecSmrg
5205b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a copy
5305b261ecSmrgof this software and associated documentation files (the "Software"), to deal
5405b261ecSmrgin the Software without restriction, including without limitation the rights
5505b261ecSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5605b261ecSmrgcopies of the Software.
5705b261ecSmrg
5805b261ecSmrgThe above copyright notice and this permission notice shall be included in
5905b261ecSmrgall copies or substantial portions of the Software.
6005b261ecSmrg
6105b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6205b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6305b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
6405b261ecSmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
6505b261ecSmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
6605b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
6705b261ecSmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6805b261ecSmrg
6905b261ecSmrgExcept as contained in this notice, the name of Digital Equipment Corporation
7005b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use or other
7105b261ecSmrgdealings in this Software without prior written authorization from Digital
7205b261ecSmrgEquipment Corporation.
7305b261ecSmrg
7405b261ecSmrg******************************************************************/
7505b261ecSmrg
766747b715Smrg/*
779ace9065Smrg * Copyright (c) 2003-2005, Oracle and/or its affiliates. All rights reserved.
786747b715Smrg *
796747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a
806747b715Smrg * copy of this software and associated documentation files (the "Software"),
816747b715Smrg * to deal in the Software without restriction, including without limitation
826747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
836747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the
846747b715Smrg * Software is furnished to do so, subject to the following conditions:
856747b715Smrg *
866747b715Smrg * The above copyright notice and this permission notice (including the next
876747b715Smrg * paragraph) shall be included in all copies or substantial portions of the
886747b715Smrg * Software.
896747b715Smrg *
906747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
916747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
926747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
936747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
946747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
956747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
966747b715Smrg * DEALINGS IN THE SOFTWARE.
976747b715Smrg */
9805b261ecSmrg
996747b715Smrg/** @file events.c
10005b261ecSmrg * This file handles event delivery and a big part of the server-side protocol
10105b261ecSmrg * handling (the parts for input devices).
10205b261ecSmrg */
10305b261ecSmrg
10405b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
10505b261ecSmrg#include <dix-config.h>
10605b261ecSmrg#endif
10705b261ecSmrg
10805b261ecSmrg#include <X11/X.h>
10905b261ecSmrg#include "misc.h"
11005b261ecSmrg#include "resource.h"
11105b261ecSmrg#include <X11/Xproto.h>
11205b261ecSmrg#include "windowstr.h"
11305b261ecSmrg#include "inputstr.h"
11435c4bbdfSmrg#include "inpututils.h"
11505b261ecSmrg#include "scrnintstr.h"
11605b261ecSmrg#include "cursorstr.h"
11705b261ecSmrg
11805b261ecSmrg#include "dixstruct.h"
11905b261ecSmrg#ifdef PANORAMIX
12005b261ecSmrg#include "panoramiX.h"
12105b261ecSmrg#include "panoramiXsrv.h"
12205b261ecSmrg#endif
12305b261ecSmrg#include "globals.h"
12405b261ecSmrg
12505b261ecSmrg#include <X11/extensions/XKBproto.h>
1266747b715Smrg#include "xkbsrv.h"
12705b261ecSmrg#include "xace.h"
12835c4bbdfSmrg#include "probes.h"
12905b261ecSmrg
13005b261ecSmrg#include <X11/extensions/XIproto.h>
1316747b715Smrg#include <X11/extensions/XI2proto.h>
1324642e01fSmrg#include <X11/extensions/XI.h>
1336747b715Smrg#include <X11/extensions/XI2.h>
13405b261ecSmrg#include "exglobals.h"
13505b261ecSmrg#include "exevents.h"
13605b261ecSmrg#include "extnsionst.h"
13705b261ecSmrg
13805b261ecSmrg#include "dixevents.h"
13905b261ecSmrg#include "dixgrabs.h"
14005b261ecSmrg#include "dispatch.h"
1414642e01fSmrg
1424642e01fSmrg#include <X11/extensions/ge.h>
1434642e01fSmrg#include "geext.h"
1444642e01fSmrg#include "geint.h"
1454642e01fSmrg
1466747b715Smrg#include "eventstr.h"
1474642e01fSmrg#include "enterleave.h"
1486747b715Smrg#include "eventconvert.h"
14935c4bbdfSmrg#include "mi.h"
1504642e01fSmrg
1516747b715Smrg/* Extension events type numbering starts at EXTENSION_EVENT_BASE.  */
15235c4bbdfSmrg#define NoSuchEvent 0x80000000  /* so doesn't match NoEventMask */
15305b261ecSmrg#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
15405b261ecSmrg#define AllButtonsMask ( \
15505b261ecSmrg	Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
15605b261ecSmrg#define MotionMask ( \
15705b261ecSmrg	PointerMotionMask | Button1MotionMask | \
15805b261ecSmrg	Button2MotionMask | Button3MotionMask | Button4MotionMask | \
15905b261ecSmrg	Button5MotionMask | ButtonMotionMask )
16005b261ecSmrg#define PropagateMask ( \
16105b261ecSmrg	KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
16205b261ecSmrg	MotionMask )
16305b261ecSmrg#define PointerGrabMask ( \
16405b261ecSmrg	ButtonPressMask | ButtonReleaseMask | \
16505b261ecSmrg	EnterWindowMask | LeaveWindowMask | \
16605b261ecSmrg	PointerMotionHintMask | KeymapStateMask | \
16705b261ecSmrg	MotionMask )
16805b261ecSmrg#define AllModifiersMask ( \
16905b261ecSmrg	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
17005b261ecSmrg	Mod3Mask | Mod4Mask | Mod5Mask )
1716747b715Smrg#define LastEventMask OwnerGrabButtonMask
1726747b715Smrg#define AllEventMasks (LastEventMask|(LastEventMask-1))
1736747b715Smrg
17435c4bbdfSmrg/* @return the core event type or 0 if the event is not a core event */
17535c4bbdfSmrgstatic inline int
17635c4bbdfSmrgcore_get_type(const xEvent *event)
17735c4bbdfSmrg{
17835c4bbdfSmrg    int type = event->u.u.type;
17935c4bbdfSmrg
18035c4bbdfSmrg    return ((type & EXTENSION_EVENT_BASE) || type == GenericEvent) ? 0 : type;
18135c4bbdfSmrg}
18235c4bbdfSmrg
18335c4bbdfSmrg/* @return the XI2 event type or 0 if the event is not a XI2 event */
18435c4bbdfSmrgstatic inline int
18535c4bbdfSmrgxi2_get_type(const xEvent *event)
18635c4bbdfSmrg{
18735c4bbdfSmrg    const xGenericEvent *e = (const xGenericEvent *) event;
1886747b715Smrg
18935c4bbdfSmrg    return (e->type != GenericEvent ||
19035c4bbdfSmrg            e->extension != IReqCode) ? 0 : e->evtype;
19135c4bbdfSmrg}
1924642e01fSmrg
1934642e01fSmrg/**
1944642e01fSmrg * Used to indicate a implicit passive grab created by a ButtonPress event.
1954642e01fSmrg * See DeliverEventsToWindow().
1964642e01fSmrg */
1974642e01fSmrg#define ImplicitGrabMask (1 << 7)
19805b261ecSmrg
19905b261ecSmrg#define WID(w) ((w) ? ((w)->drawable.id) : 0)
20005b261ecSmrg
20105b261ecSmrg#define XE_KBPTR (xE->u.keyButtonPointer)
20205b261ecSmrg
2036747b715SmrgCallbackListPtr EventCallback;
2046747b715SmrgCallbackListPtr DeviceEventCallback;
20505b261ecSmrg
20605b261ecSmrg#define DNPMCOUNT 8
20705b261ecSmrg
20805b261ecSmrgMask DontPropagateMasks[DNPMCOUNT];
20905b261ecSmrgstatic int DontPropagateRefCnts[DNPMCOUNT];
21005b261ecSmrg
21135c4bbdfSmrgstatic void CheckVirtualMotion(DeviceIntPtr pDev, QdEventPtr qe,
21235c4bbdfSmrg                               WindowPtr pWin);
21335c4bbdfSmrgstatic void CheckPhysLimits(DeviceIntPtr pDev, CursorPtr cursor,
21435c4bbdfSmrg                            Bool generateEvents, Bool confineToScreen,
2156747b715Smrg                            ScreenPtr pScreen);
21635c4bbdfSmrgstatic Bool IsWrongPointerBarrierClient(ClientPtr client,
21735c4bbdfSmrg                                        DeviceIntPtr dev,
21835c4bbdfSmrg                                        xEvent *event);
2196747b715Smrg
2206747b715Smrg/** Key repeat hack. Do not use but in TryClientEvents */
2216747b715Smrgextern BOOL EventIsKeyRepeat(xEvent *event);
2224642e01fSmrg
22305b261ecSmrg/**
2244642e01fSmrg * Main input device struct.
2254642e01fSmrg *     inputInfo.pointer
22605b261ecSmrg *     is the core pointer. Referred to as "virtual core pointer", "VCP",
2276747b715Smrg *     "core pointer" or inputInfo.pointer. The VCP is the first master
2284642e01fSmrg *     pointer device and cannot be deleted.
2294642e01fSmrg *
23005b261ecSmrg *     inputInfo.keyboard
23105b261ecSmrg *     is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
23205b261ecSmrg *     See inputInfo.pointer.
2334642e01fSmrg *
23405b261ecSmrg *     inputInfo.devices
2354642e01fSmrg *     linked list containing all devices including VCP and VCK.
23605b261ecSmrg *
23705b261ecSmrg *     inputInfo.off_devices
23805b261ecSmrg *     Devices that have not been initialized and are thus turned off.
23905b261ecSmrg *
24005b261ecSmrg *     inputInfo.numDevices
24105b261ecSmrg *     Total number of devices.
2426747b715Smrg *
2436747b715Smrg *     inputInfo.all_devices
2446747b715Smrg *     Virtual device used for XIAllDevices passive grabs. This device is
2456747b715Smrg *     not part of the inputInfo.devices list and mostly unset except for
2466747b715Smrg *     the deviceid. It exists because passivegrabs need a valid device
2476747b715Smrg *     reference.
2486747b715Smrg *
2496747b715Smrg *     inputInfo.all_master_devices
2506747b715Smrg *     Virtual device used for XIAllMasterDevices passive grabs. This device
2516747b715Smrg *     is not part of the inputInfo.devices list and mostly unset except for
2526747b715Smrg *     the deviceid. It exists because passivegrabs need a valid device
2536747b715Smrg *     reference.
25405b261ecSmrg */
2556747b715SmrgInputInfo inputInfo;
2566747b715Smrg
2576747b715SmrgEventSyncInfoRec syncEvents;
25805b261ecSmrg
25935c4bbdfSmrgstatic struct DeviceEventTime {
26035c4bbdfSmrg    Bool reset;
26135c4bbdfSmrg    TimeStamp time;
26235c4bbdfSmrg} lastDeviceEventTime[MAXDEVICES];
26335c4bbdfSmrg
2644642e01fSmrg/**
2656747b715Smrg * The root window the given device is currently on.
2664642e01fSmrg */
2679ace9065Smrg#define RootWindow(sprite) sprite->spriteTrace[0]
2684642e01fSmrg
26935c4bbdfSmrgstatic xEvent *swapEvent = NULL;
2704642e01fSmrgstatic int swapEventLen = 0;
2714642e01fSmrg
2726747b715Smrgvoid
2736747b715SmrgNotImplemented(xEvent *from, xEvent *to)
2746747b715Smrg{
2756747b715Smrg    FatalError("Not implemented");
2766747b715Smrg}
2776747b715Smrg
2784642e01fSmrg/**
2794642e01fSmrg * Convert the given event type from an XI event to a core event.
2806747b715Smrg * @param[in] The XI 1.x event type.
2814642e01fSmrg * @return The matching core event type or 0 if there is none.
28205b261ecSmrg */
2836747b715Smrgint
2844642e01fSmrgXItoCoreType(int xitype)
2854642e01fSmrg{
2864642e01fSmrg    int coretype = 0;
28735c4bbdfSmrg
2884642e01fSmrg    if (xitype == DeviceMotionNotify)
2894642e01fSmrg        coretype = MotionNotify;
2904642e01fSmrg    else if (xitype == DeviceButtonPress)
2914642e01fSmrg        coretype = ButtonPress;
2924642e01fSmrg    else if (xitype == DeviceButtonRelease)
2934642e01fSmrg        coretype = ButtonRelease;
2944642e01fSmrg    else if (xitype == DeviceKeyPress)
2954642e01fSmrg        coretype = KeyPress;
2964642e01fSmrg    else if (xitype == DeviceKeyRelease)
2974642e01fSmrg        coretype = KeyRelease;
2984642e01fSmrg
2994642e01fSmrg    return coretype;
3004642e01fSmrg}
30105b261ecSmrg
30205b261ecSmrg/**
3036747b715Smrg * @return true if the device owns a cursor, false if device shares a cursor
3046747b715Smrg * sprite with another device.
30505b261ecSmrg */
3066747b715SmrgBool
3074642e01fSmrgDevHasCursor(DeviceIntPtr pDev)
3084642e01fSmrg{
3094642e01fSmrg    return pDev->spriteInfo->spriteOwner;
3104642e01fSmrg}
31105b261ecSmrg
3124642e01fSmrg/*
3136747b715Smrg * @return true if a device is a pointer, check is the same as used by XI to
3144642e01fSmrg * fill the 'use' field.
3154642e01fSmrg */
3166747b715SmrgBool
3174642e01fSmrgIsPointerDevice(DeviceIntPtr dev)
3184642e01fSmrg{
3196747b715Smrg    return (dev->type == MASTER_POINTER) ||
32035c4bbdfSmrg        (dev->valuator && dev->button) || (dev->valuator && !dev->key);
3214642e01fSmrg}
32205b261ecSmrg
3234642e01fSmrg/*
3246747b715Smrg * @return true if a device is a keyboard, check is the same as used by XI to
3254642e01fSmrg * fill the 'use' field.
3264642e01fSmrg *
3274642e01fSmrg * Some pointer devices have keys as well (e.g. multimedia keys). Try to not
3284642e01fSmrg * count them as keyboard devices.
3294642e01fSmrg */
3306747b715SmrgBool
3314642e01fSmrgIsKeyboardDevice(DeviceIntPtr dev)
3324642e01fSmrg{
3336747b715Smrg    return (dev->type == MASTER_KEYBOARD) ||
33435c4bbdfSmrg        ((dev->key && dev->kbdfeed) && !IsPointerDevice(dev));
3356747b715Smrg}
3366747b715Smrg
3376747b715SmrgBool
3386747b715SmrgIsMaster(DeviceIntPtr dev)
3396747b715Smrg{
3406747b715Smrg    return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
3414642e01fSmrg}
34205b261ecSmrg
34335c4bbdfSmrgBool
34435c4bbdfSmrgIsFloating(DeviceIntPtr dev)
34535c4bbdfSmrg{
34635c4bbdfSmrg    return !IsMaster(dev) && GetMaster(dev, MASTER_KEYBOARD) == NULL;
34735c4bbdfSmrg}
34835c4bbdfSmrg
34905b261ecSmrg/**
35005b261ecSmrg * Max event opcode.
35105b261ecSmrg */
35205b261ecSmrgextern int lastEvent;
35305b261ecSmrg
3546747b715Smrg#define CantBeFiltered NoEventMask
3554642e01fSmrg/**
3566747b715Smrg * Event masks for each event type.
3576747b715Smrg *
35835c4bbdfSmrg * One set of filters for each device, initialized by memcpy of
35935c4bbdfSmrg * default_filter in InitEvents.
3606747b715Smrg *
3616747b715Smrg * Filters are used whether a given event may be delivered to a client,
3626747b715Smrg * usually in the form of if (window-event-mask & filter); then deliver event.
3636747b715Smrg *
3646747b715Smrg * One notable filter is for PointerMotion/DevicePointerMotion events. Each
3656747b715Smrg * time a button is pressed, the filter is modified to also contain the
3666747b715Smrg * matching ButtonXMotion mask.
3674642e01fSmrg */
36835c4bbdfSmrgMask event_filters[MAXDEVICES][MAXEVENTS];
36935c4bbdfSmrg
37035c4bbdfSmrgstatic const Mask default_filter[MAXEVENTS] = {
37135c4bbdfSmrg    NoSuchEvent,                /* 0 */
37235c4bbdfSmrg    NoSuchEvent,                /* 1 */
37335c4bbdfSmrg    KeyPressMask,               /* KeyPress */
37435c4bbdfSmrg    KeyReleaseMask,             /* KeyRelease */
37535c4bbdfSmrg    ButtonPressMask,            /* ButtonPress */
37635c4bbdfSmrg    ButtonReleaseMask,          /* ButtonRelease */
37735c4bbdfSmrg    PointerMotionMask,          /* MotionNotify (initial state) */
37835c4bbdfSmrg    EnterWindowMask,            /* EnterNotify */
37935c4bbdfSmrg    LeaveWindowMask,            /* LeaveNotify */
38035c4bbdfSmrg    FocusChangeMask,            /* FocusIn */
38135c4bbdfSmrg    FocusChangeMask,            /* FocusOut */
38235c4bbdfSmrg    KeymapStateMask,            /* KeymapNotify */
38335c4bbdfSmrg    ExposureMask,               /* Expose */
38435c4bbdfSmrg    CantBeFiltered,             /* GraphicsExpose */
38535c4bbdfSmrg    CantBeFiltered,             /* NoExpose */
38635c4bbdfSmrg    VisibilityChangeMask,       /* VisibilityNotify */
38735c4bbdfSmrg    SubstructureNotifyMask,     /* CreateNotify */
38835c4bbdfSmrg    StructureAndSubMask,        /* DestroyNotify */
38935c4bbdfSmrg    StructureAndSubMask,        /* UnmapNotify */
39035c4bbdfSmrg    StructureAndSubMask,        /* MapNotify */
39135c4bbdfSmrg    SubstructureRedirectMask,   /* MapRequest */
39235c4bbdfSmrg    StructureAndSubMask,        /* ReparentNotify */
39335c4bbdfSmrg    StructureAndSubMask,        /* ConfigureNotify */
39435c4bbdfSmrg    SubstructureRedirectMask,   /* ConfigureRequest */
39535c4bbdfSmrg    StructureAndSubMask,        /* GravityNotify */
39635c4bbdfSmrg    ResizeRedirectMask,         /* ResizeRequest */
39735c4bbdfSmrg    StructureAndSubMask,        /* CirculateNotify */
39835c4bbdfSmrg    SubstructureRedirectMask,   /* CirculateRequest */
39935c4bbdfSmrg    PropertyChangeMask,         /* PropertyNotify */
40035c4bbdfSmrg    CantBeFiltered,             /* SelectionClear */
40135c4bbdfSmrg    CantBeFiltered,             /* SelectionRequest */
40235c4bbdfSmrg    CantBeFiltered,             /* SelectionNotify */
40335c4bbdfSmrg    ColormapChangeMask,         /* ColormapNotify */
40435c4bbdfSmrg    CantBeFiltered,             /* ClientMessage */
40535c4bbdfSmrg    CantBeFiltered              /* MappingNotify */
40635c4bbdfSmrg};
4074642e01fSmrg
4086747b715Smrg/**
4096747b715Smrg * For the given event, return the matching event filter. This filter may then
4106747b715Smrg * be AND'ed with the selected event mask.
4116747b715Smrg *
4126747b715Smrg * For XI2 events, the returned filter is simply the byte containing the event
4136747b715Smrg * mask we're interested in. E.g. for a mask of (1 << 13), this would be
4146747b715Smrg * byte[1].
4156747b715Smrg *
4166747b715Smrg * @param[in] dev The device the event belongs to, may be NULL.
4176747b715Smrg * @param[in] event The event to get the filter for. Only the type of the
4186747b715Smrg *                  event matters, or the extension + evtype for GenericEvents.
4196747b715Smrg * @return The filter mask for the given event.
4206747b715Smrg *
4216747b715Smrg * @see GetEventMask
4226747b715Smrg */
4236747b715SmrgMask
4246747b715SmrgGetEventFilter(DeviceIntPtr dev, xEvent *event)
4256747b715Smrg{
42635c4bbdfSmrg    int evtype = 0;
42735c4bbdfSmrg
4286747b715Smrg    if (event->u.u.type != GenericEvent)
42935c4bbdfSmrg        return event_get_filter_from_type(dev, event->u.u.type);
43035c4bbdfSmrg    else if ((evtype = xi2_get_type(event)))
43135c4bbdfSmrg        return event_get_filter_from_xi2type(evtype);
4329ace9065Smrg    ErrorF("[dix] Unknown event type %d. No filter\n", event->u.u.type);
4336747b715Smrg    return 0;
4346747b715Smrg}
4354642e01fSmrg
4364642e01fSmrg/**
43735c4bbdfSmrg * Return the single byte of the device's XI2 mask that contains the mask
43835c4bbdfSmrg * for the event_type.
4394642e01fSmrg */
44035c4bbdfSmrgint
44135c4bbdfSmrgGetXI2MaskByte(XI2Mask *mask, DeviceIntPtr dev, int event_type)
44235c4bbdfSmrg{
44335c4bbdfSmrg    /* we just return the matching filter because that's the only use
44435c4bbdfSmrg     * for this mask anyway.
44535c4bbdfSmrg     */
44635c4bbdfSmrg    if (xi2mask_isset(mask, dev, event_type))
44735c4bbdfSmrg        return event_get_filter_from_xi2type(event_type);
44835c4bbdfSmrg    else
44935c4bbdfSmrg        return 0;
45035c4bbdfSmrg}
45135c4bbdfSmrg
45235c4bbdfSmrg/**
45335c4bbdfSmrg * @return TRUE if the mask is set for this event from this device on the
45435c4bbdfSmrg * window, or FALSE otherwise.
45535c4bbdfSmrg */
45635c4bbdfSmrgBool
45735c4bbdfSmrgWindowXI2MaskIsset(DeviceIntPtr dev, WindowPtr win, xEvent *ev)
4586747b715Smrg{
4596747b715Smrg    OtherInputMasks *inputMasks = wOtherInputMasks(win);
4606747b715Smrg    int evtype;
4616747b715Smrg
46235c4bbdfSmrg    if (!inputMasks || xi2_get_type(ev) == 0)
4636747b715Smrg        return 0;
4646747b715Smrg
46535c4bbdfSmrg    evtype = ((xGenericEvent *) ev)->evtype;
4666747b715Smrg
46735c4bbdfSmrg    return xi2mask_isset(inputMasks->xi2mask, dev, evtype);
4686747b715Smrg}
4696747b715Smrg
47090bea6a0Smrg/**
47190bea6a0Smrg * When processing events we operate on InternalEvent pointers. They may actually refer to a
47290bea6a0Smrg * an instance of DeviceEvent, GestureEvent or any other event that comprises the InternalEvent
47390bea6a0Smrg * union. This works well in practice because we always look into event type before doing anything,
47490bea6a0Smrg * except in the case of copying the event. Any copying of InternalEvent should use this function
47590bea6a0Smrg * instead of doing *dst_event = *src_event whenever it's not clear whether source event actually
47690bea6a0Smrg * points to full InternalEvent instance.
47790bea6a0Smrg */
47890bea6a0Smrgvoid
47990bea6a0SmrgCopyPartialInternalEvent(InternalEvent* dst_event, const InternalEvent* src_event)
48090bea6a0Smrg{
48190bea6a0Smrg    memcpy(dst_event, src_event, src_event->any.length);
48290bea6a0Smrg}
48390bea6a0Smrg
4849ace9065SmrgMask
48535c4bbdfSmrgGetEventMask(DeviceIntPtr dev, xEvent *event, InputClients * other)
4866747b715Smrg{
48735c4bbdfSmrg    int evtype;
48835c4bbdfSmrg
4896747b715Smrg    /* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */
49035c4bbdfSmrg    if ((evtype = xi2_get_type(event))) {
49135c4bbdfSmrg        return GetXI2MaskByte(other->xi2mask, dev, evtype);
49235c4bbdfSmrg    }
49335c4bbdfSmrg    else if (core_get_type(event) != 0)
4946747b715Smrg        return other->mask[XIAllDevices];
4956747b715Smrg    else
4966747b715Smrg        return other->mask[dev->id];
4976747b715Smrg}
4986747b715Smrg
49935c4bbdfSmrgstatic CARD8 criticalEvents[32] = {
50035c4bbdfSmrg    0x7c, 0x30, 0x40            /* key, button, expose, and configure events */
50105b261ecSmrg};
50205b261ecSmrg
5036747b715Smrgstatic void
50435c4bbdfSmrgSyntheticMotion(DeviceIntPtr dev, int x, int y)
50535c4bbdfSmrg{
5066747b715Smrg    int screenno = 0;
5076747b715Smrg
5086747b715Smrg#ifdef PANORAMIX
5096747b715Smrg    if (!noPanoramiXExtension)
5106747b715Smrg        screenno = dev->spriteInfo->sprite->screen->myNum;
5116747b715Smrg#endif
5126747b715Smrg    PostSyntheticMotion(dev, x, y, screenno,
51335c4bbdfSmrg                        (syncEvents.playingEvents) ? syncEvents.time.
51435c4bbdfSmrg                        milliseconds : currentTime.milliseconds);
5156747b715Smrg
5166747b715Smrg}
5176747b715Smrg
51805b261ecSmrg#ifdef PANORAMIX
5194642e01fSmrgstatic void PostNewCursor(DeviceIntPtr pDev);
52005b261ecSmrg
5216747b715Smrgstatic Bool
52235c4bbdfSmrgXineramaSetCursorPosition(DeviceIntPtr pDev, int x, int y, Bool generateEvent)
5236747b715Smrg{
52405b261ecSmrg    ScreenPtr pScreen;
52505b261ecSmrg    int i;
5264642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
52705b261ecSmrg
52805b261ecSmrg    /* x,y are in Screen 0 coordinates.  We need to decide what Screen
5294642e01fSmrg       to send the message too and what the coordinates relative to
53005b261ecSmrg       that screen are. */
53105b261ecSmrg
5324642e01fSmrg    pScreen = pSprite->screen;
5336747b715Smrg    x += screenInfo.screens[0]->x;
5346747b715Smrg    y += screenInfo.screens[0]->y;
53505b261ecSmrg
53635c4bbdfSmrg    if (!point_on_screen(pScreen, x, y)) {
53735c4bbdfSmrg        FOR_NSCREENS(i) {
53835c4bbdfSmrg            if (i == pScreen->myNum)
53935c4bbdfSmrg                continue;
54035c4bbdfSmrg            if (point_on_screen(screenInfo.screens[i], x, y)) {
54135c4bbdfSmrg                pScreen = screenInfo.screens[i];
54235c4bbdfSmrg                break;
54335c4bbdfSmrg            }
54435c4bbdfSmrg        }
54505b261ecSmrg    }
54605b261ecSmrg
5474642e01fSmrg    pSprite->screen = pScreen;
5486747b715Smrg    pSprite->hotPhys.x = x - screenInfo.screens[0]->x;
5496747b715Smrg    pSprite->hotPhys.y = y - screenInfo.screens[0]->y;
5506747b715Smrg    x -= pScreen->x;
5516747b715Smrg    y -= pScreen->y;
55205b261ecSmrg
55335c4bbdfSmrg    return (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent);
55405b261ecSmrg}
55505b261ecSmrg
55605b261ecSmrgstatic void
5574642e01fSmrgXineramaConstrainCursor(DeviceIntPtr pDev)
55805b261ecSmrg{
5594642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
5604642e01fSmrg    ScreenPtr pScreen;
5614642e01fSmrg    BoxRec newBox;
5624642e01fSmrg
5634642e01fSmrg    pScreen = pSprite->screen;
5644642e01fSmrg    newBox = pSprite->physLimits;
56505b261ecSmrg
56605b261ecSmrg    /* Translate the constraining box to the screen
56705b261ecSmrg       the sprite is actually on */
5686747b715Smrg    newBox.x1 += screenInfo.screens[0]->x - pScreen->x;
5696747b715Smrg    newBox.x2 += screenInfo.screens[0]->x - pScreen->x;
5706747b715Smrg    newBox.y1 += screenInfo.screens[0]->y - pScreen->y;
5716747b715Smrg    newBox.y2 += screenInfo.screens[0]->y - pScreen->y;
57205b261ecSmrg
57335c4bbdfSmrg    (*pScreen->ConstrainCursor) (pDev, pScreen, &newBox);
57405b261ecSmrg}
57505b261ecSmrg
57605b261ecSmrgstatic Bool
5774642e01fSmrgXineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
57805b261ecSmrg{
5794642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
5804642e01fSmrg
58135c4bbdfSmrg    if (pWin == screenInfo.screens[0]->root) {
58235c4bbdfSmrg        int i;
58335c4bbdfSmrg
58435c4bbdfSmrg        FOR_NSCREENS(i)
58535c4bbdfSmrg            pSprite->windows[i] = screenInfo.screens[i]->root;
58635c4bbdfSmrg    }
58735c4bbdfSmrg    else {
58835c4bbdfSmrg        PanoramiXRes *win;
58935c4bbdfSmrg        int rc, i;
59035c4bbdfSmrg
59135c4bbdfSmrg        rc = dixLookupResourceByType((void **) &win, pWin->drawable.id,
59235c4bbdfSmrg                                     XRT_WINDOW, serverClient, DixReadAccess);
59335c4bbdfSmrg        if (rc != Success)
59435c4bbdfSmrg            return FALSE;
59535c4bbdfSmrg
59635c4bbdfSmrg        FOR_NSCREENS(i) {
59735c4bbdfSmrg            rc = dixLookupWindow(pSprite->windows + i, win->info[i].id,
59835c4bbdfSmrg                                 serverClient, DixReadAccess);
59935c4bbdfSmrg            if (rc != Success)  /* window is being unmapped */
60035c4bbdfSmrg                return FALSE;
60135c4bbdfSmrg        }
60205b261ecSmrg    }
60305b261ecSmrg    return TRUE;
60405b261ecSmrg}
60505b261ecSmrg
60605b261ecSmrgstatic void
6074642e01fSmrgXineramaConfineCursorToWindow(DeviceIntPtr pDev,
60835c4bbdfSmrg                              WindowPtr pWin, Bool generateEvents)
60905b261ecSmrg{
6104642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
61105b261ecSmrg
6126747b715Smrg    int x, y, off_x, off_y, i;
61305b261ecSmrg
6144e185dc0Smrg    assert(!noPanoramiXExtension);
6154e185dc0Smrg
61635c4bbdfSmrg    if (!XineramaSetWindowPntrs(pDev, pWin))
6176747b715Smrg        return;
6184642e01fSmrg
6196747b715Smrg    i = PanoramiXNumScreens - 1;
62005b261ecSmrg
62135c4bbdfSmrg    RegionCopy(&pSprite->Reg1, &pSprite->windows[i]->borderSize);
6226747b715Smrg    off_x = screenInfo.screens[i]->x;
6236747b715Smrg    off_y = screenInfo.screens[i]->y;
62405b261ecSmrg
62535c4bbdfSmrg    while (i--) {
6266747b715Smrg        x = off_x - screenInfo.screens[i]->x;
6276747b715Smrg        y = off_y - screenInfo.screens[i]->y;
62805b261ecSmrg
62935c4bbdfSmrg        if (x || y)
6306747b715Smrg            RegionTranslate(&pSprite->Reg1, x, y);
63105b261ecSmrg
6326747b715Smrg        RegionUnion(&pSprite->Reg1, &pSprite->Reg1,
63335c4bbdfSmrg                    &pSprite->windows[i]->borderSize);
6344642e01fSmrg
6356747b715Smrg        off_x = screenInfo.screens[i]->x;
6366747b715Smrg        off_y = screenInfo.screens[i]->y;
63705b261ecSmrg    }
63805b261ecSmrg
6396747b715Smrg    pSprite->hotLimits = *RegionExtents(&pSprite->Reg1);
64005b261ecSmrg
64135c4bbdfSmrg    if (RegionNumRects(&pSprite->Reg1) > 1)
6426747b715Smrg        pSprite->hotShape = &pSprite->Reg1;
6436747b715Smrg    else
6446747b715Smrg        pSprite->hotShape = NullRegion;
6454642e01fSmrg
6466747b715Smrg    pSprite->confined = FALSE;
64735c4bbdfSmrg    pSprite->confineWin =
64835c4bbdfSmrg        (pWin == screenInfo.screens[0]->root) ? NullWindow : pWin;
64905b261ecSmrg
6506747b715Smrg    CheckPhysLimits(pDev, pSprite->current, generateEvents, FALSE, NULL);
6516747b715Smrg}
65205b261ecSmrg
65335c4bbdfSmrg#endif                          /* PANORAMIX */
65405b261ecSmrg
6556747b715Smrg/**
6566747b715Smrg * Modifies the filter for the given protocol event type to the given masks.
6576747b715Smrg *
6586747b715Smrg * There's only two callers: UpdateDeviceState() and XI's SetMaskForExtEvent().
6596747b715Smrg * The latter initialises masks for the matching XI events, it's a once-off
6606747b715Smrg * setting.
6616747b715Smrg * UDS however changes the mask for MotionNotify and DeviceMotionNotify each
6626747b715Smrg * time a button is pressed to include the matching ButtonXMotion mask in the
6636747b715Smrg * filter.
6646747b715Smrg *
6656747b715Smrg * @param[in] deviceid The device to modify the filter for.
6666747b715Smrg * @param[in] mask The new filter mask.
6676747b715Smrg * @param[in] event Protocol event type.
6686747b715Smrg */
66905b261ecSmrgvoid
6704642e01fSmrgSetMaskForEvent(int deviceid, Mask mask, int event)
67105b261ecSmrg{
67252397711Smrg    if (deviceid < 0 || deviceid >= MAXDEVICES)
6734642e01fSmrg        FatalError("SetMaskForEvent: bogus device id");
67435c4bbdfSmrg    event_filters[deviceid][event] = mask;
67505b261ecSmrg}
67605b261ecSmrg
6776747b715Smrgvoid
67805b261ecSmrgSetCriticalEvent(int event)
67905b261ecSmrg{
68035c4bbdfSmrg    if (event >= MAXEVENTS)
68135c4bbdfSmrg        FatalError("SetCriticalEvent: bogus event number");
68205b261ecSmrg    criticalEvents[event >> 3] |= 1 << (event & 7);
68305b261ecSmrg}
68405b261ecSmrg
6854642e01fSmrgvoid
6864642e01fSmrgConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
68705b261ecSmrg{
68805b261ecSmrg    BoxRec box;
68905b261ecSmrg    int x = *px, y = *py;
69005b261ecSmrg    int incx = 1, incy = 1;
69105b261ecSmrg
6926747b715Smrg    if (RegionContainsPoint(shape, x, y, &box))
69335c4bbdfSmrg        return;
6946747b715Smrg    box = *RegionExtents(shape);
69505b261ecSmrg    /* this is rather crude */
69605b261ecSmrg    do {
69735c4bbdfSmrg        x += incx;
69835c4bbdfSmrg        if (x >= box.x2) {
69935c4bbdfSmrg            incx = -1;
70035c4bbdfSmrg            x = *px - 1;
70135c4bbdfSmrg        }
70235c4bbdfSmrg        else if (x < box.x1) {
70335c4bbdfSmrg            incx = 1;
70435c4bbdfSmrg            x = *px;
70535c4bbdfSmrg            y += incy;
70635c4bbdfSmrg            if (y >= box.y2) {
70735c4bbdfSmrg                incy = -1;
70835c4bbdfSmrg                y = *py - 1;
70935c4bbdfSmrg            }
71035c4bbdfSmrg            else if (y < box.y1)
71135c4bbdfSmrg                return;         /* should never get here! */
71235c4bbdfSmrg        }
7136747b715Smrg    } while (!RegionContainsPoint(shape, x, y, &box));
71405b261ecSmrg    *px = x;
71505b261ecSmrg    *py = y;
71605b261ecSmrg}
71705b261ecSmrg
71805b261ecSmrgstatic void
71935c4bbdfSmrgCheckPhysLimits(DeviceIntPtr pDev, CursorPtr cursor, Bool generateEvents,
72035c4bbdfSmrg                Bool confineToScreen, /* unused if PanoramiX on */
72135c4bbdfSmrg                ScreenPtr pScreen)    /* unused if PanoramiX on */
72205b261ecSmrg{
72305b261ecSmrg    HotSpot new;
7244642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
72505b261ecSmrg
72605b261ecSmrg    if (!cursor)
72735c4bbdfSmrg        return;
7284642e01fSmrg    new = pSprite->hotPhys;
7296747b715Smrg#ifdef PANORAMIX
7306747b715Smrg    if (!noPanoramiXExtension)
7316747b715Smrg        /* I don't care what the DDX has to say about it */
7326747b715Smrg        pSprite->physLimits = pSprite->hotLimits;
73305b261ecSmrg    else
7346747b715Smrg#endif
7356747b715Smrg    {
7366747b715Smrg        if (pScreen)
7376747b715Smrg            new.pScreen = pScreen;
7386747b715Smrg        else
7396747b715Smrg            pScreen = new.pScreen;
7406747b715Smrg        (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits,
74135c4bbdfSmrg                                  &pSprite->physLimits);
7426747b715Smrg        pSprite->confined = confineToScreen;
74335c4bbdfSmrg        (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
7446747b715Smrg    }
7456747b715Smrg
7466747b715Smrg    /* constrain the pointer to those limits */
7474642e01fSmrg    if (new.x < pSprite->physLimits.x1)
74835c4bbdfSmrg        new.x = pSprite->physLimits.x1;
74935c4bbdfSmrg    else if (new.x >= pSprite->physLimits.x2)
75035c4bbdfSmrg        new.x = pSprite->physLimits.x2 - 1;
7514642e01fSmrg    if (new.y < pSprite->physLimits.y1)
75235c4bbdfSmrg        new.y = pSprite->physLimits.y1;
75335c4bbdfSmrg    else if (new.y >= pSprite->physLimits.y2)
75435c4bbdfSmrg        new.y = pSprite->physLimits.y2 - 1;
7554642e01fSmrg    if (pSprite->hotShape)
75635c4bbdfSmrg        ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y);
7576747b715Smrg    if ((
7586747b715Smrg#ifdef PANORAMIX
7596747b715Smrg            noPanoramiXExtension &&
7606747b715Smrg#endif
7616747b715Smrg            (pScreen != pSprite->hotPhys.pScreen)) ||
76235c4bbdfSmrg        (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y)) {
7636747b715Smrg#ifdef PANORAMIX
7646747b715Smrg        if (!noPanoramiXExtension)
76535c4bbdfSmrg            XineramaSetCursorPosition(pDev, new.x, new.y, generateEvents);
7666747b715Smrg        else
7676747b715Smrg#endif
7686747b715Smrg        {
7696747b715Smrg            if (pScreen != pSprite->hotPhys.pScreen)
7706747b715Smrg                pSprite->hotPhys = new;
7716747b715Smrg            (*pScreen->SetCursorPosition)
7726747b715Smrg                (pDev, pScreen, new.x, new.y, generateEvents);
7736747b715Smrg        }
7744642e01fSmrg        if (!generateEvents)
7756747b715Smrg            SyntheticMotion(pDev, new.x, new.y);
77605b261ecSmrg    }
7776747b715Smrg
7786747b715Smrg#ifdef PANORAMIX
7796747b715Smrg    /* Tell DDX what the limits are */
7806747b715Smrg    if (!noPanoramiXExtension)
7816747b715Smrg        XineramaConstrainCursor(pDev);
7826747b715Smrg#endif
78305b261ecSmrg}
78405b261ecSmrg
78505b261ecSmrgstatic void
78635c4bbdfSmrgCheckVirtualMotion(DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin)
78705b261ecSmrg{
7884642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
7896747b715Smrg    RegionPtr reg = NULL;
7906747b715Smrg    DeviceEvent *ev = NULL;
7914642e01fSmrg
79235c4bbdfSmrg    if (qe) {
7936747b715Smrg        ev = &qe->event->device_event;
79435c4bbdfSmrg        switch (ev->type) {
79535c4bbdfSmrg        case ET_Motion:
79635c4bbdfSmrg        case ET_ButtonPress:
79735c4bbdfSmrg        case ET_ButtonRelease:
79835c4bbdfSmrg        case ET_KeyPress:
79935c4bbdfSmrg        case ET_KeyRelease:
80035c4bbdfSmrg        case ET_ProximityIn:
80135c4bbdfSmrg        case ET_ProximityOut:
80235c4bbdfSmrg            pSprite->hot.pScreen = qe->pScreen;
80335c4bbdfSmrg            pSprite->hot.x = ev->root_x;
80435c4bbdfSmrg            pSprite->hot.y = ev->root_y;
80535c4bbdfSmrg            pWin =
80635c4bbdfSmrg                pDev->deviceGrab.grab ? pDev->deviceGrab.grab->
80735c4bbdfSmrg                confineTo : NullWindow;
80835c4bbdfSmrg            break;
80935c4bbdfSmrg        default:
81035c4bbdfSmrg            break;
8116747b715Smrg        }
81205b261ecSmrg    }
81335c4bbdfSmrg    if (pWin) {
81435c4bbdfSmrg        BoxRec lims;
81505b261ecSmrg
8166747b715Smrg#ifdef PANORAMIX
8176747b715Smrg        if (!noPanoramiXExtension) {
8186747b715Smrg            int x, y, off_x, off_y, i;
8196747b715Smrg
82035c4bbdfSmrg            if (!XineramaSetWindowPntrs(pDev, pWin))
8216747b715Smrg                return;
8226747b715Smrg
8236747b715Smrg            i = PanoramiXNumScreens - 1;
8246747b715Smrg
82535c4bbdfSmrg            RegionCopy(&pSprite->Reg2, &pSprite->windows[i]->borderSize);
8266747b715Smrg            off_x = screenInfo.screens[i]->x;
8276747b715Smrg            off_y = screenInfo.screens[i]->y;
8286747b715Smrg
82935c4bbdfSmrg            while (i--) {
8306747b715Smrg                x = off_x - screenInfo.screens[i]->x;
8316747b715Smrg                y = off_y - screenInfo.screens[i]->y;
8326747b715Smrg
83335c4bbdfSmrg                if (x || y)
8346747b715Smrg                    RegionTranslate(&pSprite->Reg2, x, y);
8356747b715Smrg
8366747b715Smrg                RegionUnion(&pSprite->Reg2, &pSprite->Reg2,
83735c4bbdfSmrg                            &pSprite->windows[i]->borderSize);
8386747b715Smrg
8396747b715Smrg                off_x = screenInfo.screens[i]->x;
8406747b715Smrg                off_y = screenInfo.screens[i]->y;
8416747b715Smrg            }
84235c4bbdfSmrg        }
84335c4bbdfSmrg        else
8446747b715Smrg#endif
8456747b715Smrg        {
84635c4bbdfSmrg            if (pSprite->hot.pScreen != pWin->drawable.pScreen) {
8476747b715Smrg                pSprite->hot.pScreen = pWin->drawable.pScreen;
8486747b715Smrg                pSprite->hot.x = pSprite->hot.y = 0;
8496747b715Smrg            }
8506747b715Smrg        }
8516747b715Smrg
85235c4bbdfSmrg        lims = *RegionExtents(&pWin->borderSize);
85335c4bbdfSmrg        if (pSprite->hot.x < lims.x1)
85435c4bbdfSmrg            pSprite->hot.x = lims.x1;
85535c4bbdfSmrg        else if (pSprite->hot.x >= lims.x2)
85635c4bbdfSmrg            pSprite->hot.x = lims.x2 - 1;
85735c4bbdfSmrg        if (pSprite->hot.y < lims.y1)
85835c4bbdfSmrg            pSprite->hot.y = lims.y1;
85935c4bbdfSmrg        else if (pSprite->hot.y >= lims.y2)
86035c4bbdfSmrg            pSprite->hot.y = lims.y2 - 1;
8616747b715Smrg
8626747b715Smrg#ifdef PANORAMIX
86335c4bbdfSmrg        if (!noPanoramiXExtension) {
8646747b715Smrg            if (RegionNumRects(&pSprite->Reg2) > 1)
8656747b715Smrg                reg = &pSprite->Reg2;
8666747b715Smrg
86735c4bbdfSmrg        }
86835c4bbdfSmrg        else
8696747b715Smrg#endif
8706747b715Smrg        {
8716747b715Smrg            if (wBoundingShape(pWin))
8726747b715Smrg                reg = &pWin->borderSize;
8736747b715Smrg        }
8746747b715Smrg
8756747b715Smrg        if (reg)
8766747b715Smrg            ConfineToShape(pDev, reg, &pSprite->hot.x, &pSprite->hot.y);
8776747b715Smrg
87835c4bbdfSmrg        if (qe && ev) {
87935c4bbdfSmrg            qe->pScreen = pSprite->hot.pScreen;
88035c4bbdfSmrg            ev->root_x = pSprite->hot.x;
88135c4bbdfSmrg            ev->root_y = pSprite->hot.y;
88235c4bbdfSmrg        }
88305b261ecSmrg    }
8846747b715Smrg#ifdef PANORAMIX
88535c4bbdfSmrg    if (noPanoramiXExtension)   /* No typo. Only set the root win if disabled */
8866747b715Smrg#endif
8879ace9065Smrg        RootWindow(pDev->spriteInfo->sprite) = pSprite->hot.pScreen->root;
88805b261ecSmrg}
88905b261ecSmrg
89005b261ecSmrgstatic void
89135c4bbdfSmrgConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents,
89235c4bbdfSmrg                      Bool confineToScreen)
89305b261ecSmrg{
8944642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
89505b261ecSmrg
89635c4bbdfSmrg    if (syncEvents.playingEvents) {
89735c4bbdfSmrg        CheckVirtualMotion(pDev, (QdEventPtr) NULL, pWin);
89835c4bbdfSmrg        SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y);
89905b261ecSmrg    }
90035c4bbdfSmrg    else {
9017e31ba66Smrg        ScreenPtr pScreen = pWin->drawable.pScreen;
9027e31ba66Smrg
9036747b715Smrg#ifdef PANORAMIX
90435c4bbdfSmrg        if (!noPanoramiXExtension) {
9056747b715Smrg            XineramaConfineCursorToWindow(pDev, pWin, generateEvents);
9066747b715Smrg            return;
9076747b715Smrg        }
9086747b715Smrg#endif
90935c4bbdfSmrg        pSprite->hotLimits = *RegionExtents(&pWin->borderSize);
91035c4bbdfSmrg        pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize
91135c4bbdfSmrg            : NullRegion;
9124642e01fSmrg        CheckPhysLimits(pDev, pSprite->current, generateEvents,
9136747b715Smrg                        confineToScreen, pWin->drawable.pScreen);
9147e31ba66Smrg
9157e31ba66Smrg        if (*pScreen->CursorConfinedTo)
9167e31ba66Smrg            (*pScreen->CursorConfinedTo) (pDev, pScreen, pWin);
91705b261ecSmrg    }
91805b261ecSmrg}
91905b261ecSmrg
9206747b715SmrgBool
9214642e01fSmrgPointerConfinedToScreen(DeviceIntPtr pDev)
92205b261ecSmrg{
9234642e01fSmrg    return pDev->spriteInfo->sprite->confined;
92405b261ecSmrg}
92505b261ecSmrg
92605b261ecSmrg/**
92705b261ecSmrg * Update the sprite cursor to the given cursor.
92805b261ecSmrg *
92905b261ecSmrg * ChangeToCursor() will display the new cursor and free the old cursor (if
93005b261ecSmrg * applicable). If the provided cursor is already the updated cursor, nothing
93105b261ecSmrg * happens.
93205b261ecSmrg */
93305b261ecSmrgstatic void
9344642e01fSmrgChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
93505b261ecSmrg{
9364642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
9376747b715Smrg    ScreenPtr pScreen;
93805b261ecSmrg
93935c4bbdfSmrg    if (cursor != pSprite->current) {
94035c4bbdfSmrg        if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
94135c4bbdfSmrg            (pSprite->current->bits->yhot != cursor->bits->yhot))
94235c4bbdfSmrg            CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined,
94335c4bbdfSmrg                            (ScreenPtr) NULL);
9446747b715Smrg#ifdef PANORAMIX
9456747b715Smrg        /* XXX: is this really necessary?? (whot) */
9466747b715Smrg        if (!noPanoramiXExtension)
9476747b715Smrg            pScreen = pSprite->screen;
9486747b715Smrg        else
9496747b715Smrg#endif
9506747b715Smrg            pScreen = pSprite->hotPhys.pScreen;
9516747b715Smrg
95235c4bbdfSmrg        (*pScreen->DisplayCursor) (pDev, pScreen, cursor);
95335c4bbdfSmrg        FreeCursor(pSprite->current, (Cursor) 0);
95435c4bbdfSmrg        pSprite->current = RefCursor(cursor);
95505b261ecSmrg    }
95605b261ecSmrg}
95705b261ecSmrg
95805b261ecSmrg/**
9594642e01fSmrg * @returns true if b is a descendent of a
96005b261ecSmrg */
96105b261ecSmrgBool
96205b261ecSmrgIsParent(WindowPtr a, WindowPtr b)
96305b261ecSmrg{
96405b261ecSmrg    for (b = b->parent; b; b = b->parent)
96535c4bbdfSmrg        if (b == a)
96635c4bbdfSmrg            return TRUE;
96705b261ecSmrg    return FALSE;
96805b261ecSmrg}
96905b261ecSmrg
97005b261ecSmrg/**
97105b261ecSmrg * Update the cursor displayed on the screen.
97205b261ecSmrg *
9734642e01fSmrg * Called whenever a cursor may have changed shape or position.
97405b261ecSmrg */
97505b261ecSmrgstatic void
9764642e01fSmrgPostNewCursor(DeviceIntPtr pDev)
97705b261ecSmrg{
97805b261ecSmrg    WindowPtr win;
9794642e01fSmrg    GrabPtr grab = pDev->deviceGrab.grab;
98035c4bbdfSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
98135c4bbdfSmrg    CursorPtr pCursor;
98205b261ecSmrg
98305b261ecSmrg    if (syncEvents.playingEvents)
98435c4bbdfSmrg        return;
98535c4bbdfSmrg    if (grab) {
98635c4bbdfSmrg        if (grab->cursor) {
98735c4bbdfSmrg            ChangeToCursor(pDev, grab->cursor);
98835c4bbdfSmrg            return;
98935c4bbdfSmrg        }
99035c4bbdfSmrg        if (IsParent(grab->window, pSprite->win))
99135c4bbdfSmrg            win = pSprite->win;
99235c4bbdfSmrg        else
99335c4bbdfSmrg            win = grab->window;
99405b261ecSmrg    }
99505b261ecSmrg    else
99635c4bbdfSmrg        win = pSprite->win;
99735c4bbdfSmrg    for (; win; win = win->parent) {
99835c4bbdfSmrg        if (win->optional) {
9994642e01fSmrg            pCursor = WindowGetDeviceCursor(win, pDev);
10004642e01fSmrg            if (!pCursor && win->optional->cursor != NullCursor)
10014642e01fSmrg                pCursor = win->optional->cursor;
100235c4bbdfSmrg            if (pCursor) {
10034642e01fSmrg                ChangeToCursor(pDev, pCursor);
10044642e01fSmrg                return;
10054642e01fSmrg            }
100635c4bbdfSmrg        }
10074642e01fSmrg    }
100805b261ecSmrg}
100905b261ecSmrg
101005b261ecSmrg/**
10114642e01fSmrg * @param dev device which you want to know its current root window
10124642e01fSmrg * @return root window where dev's sprite is located
101305b261ecSmrg */
10146747b715SmrgWindowPtr
10154642e01fSmrgGetCurrentRootWindow(DeviceIntPtr dev)
101605b261ecSmrg{
10179ace9065Smrg    return RootWindow(dev->spriteInfo->sprite);
101805b261ecSmrg}
101905b261ecSmrg
102005b261ecSmrg/**
102105b261ecSmrg * @return window underneath the cursor sprite.
102205b261ecSmrg */
10236747b715SmrgWindowPtr
10244642e01fSmrgGetSpriteWindow(DeviceIntPtr pDev)
102505b261ecSmrg{
10264642e01fSmrg    return pDev->spriteInfo->sprite->win;
102705b261ecSmrg}
102805b261ecSmrg
102905b261ecSmrg/**
103005b261ecSmrg * @return current sprite cursor.
103105b261ecSmrg */
10326747b715SmrgCursorPtr
10334642e01fSmrgGetSpriteCursor(DeviceIntPtr pDev)
103405b261ecSmrg{
10354642e01fSmrg    return pDev->spriteInfo->sprite->current;
103605b261ecSmrg}
103705b261ecSmrg
103805b261ecSmrg/**
103905b261ecSmrg * Set x/y current sprite position in screen coordinates.
104005b261ecSmrg */
10416747b715Smrgvoid
10424642e01fSmrgGetSpritePosition(DeviceIntPtr pDev, int *px, int *py)
104305b261ecSmrg{
10444642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
104535c4bbdfSmrg
10464642e01fSmrg    *px = pSprite->hotPhys.x;
10474642e01fSmrg    *py = pSprite->hotPhys.y;
104805b261ecSmrg}
104905b261ecSmrg
105005b261ecSmrg#ifdef PANORAMIX
10516747b715Smrgint
10524642e01fSmrgXineramaGetCursorScreen(DeviceIntPtr pDev)
105305b261ecSmrg{
105435c4bbdfSmrg    if (!noPanoramiXExtension) {
105535c4bbdfSmrg        return pDev->spriteInfo->sprite->screen->myNum;
105635c4bbdfSmrg    }
105735c4bbdfSmrg    else {
105835c4bbdfSmrg        return 0;
105905b261ecSmrg    }
106005b261ecSmrg}
106135c4bbdfSmrg#endif                          /* PANORAMIX */
106205b261ecSmrg
106335c4bbdfSmrg#define TIMESLOP (5 * 60 * 1000)        /* 5 minutes */
106405b261ecSmrg
106505b261ecSmrgstatic void
106635c4bbdfSmrgMonthChangedOrBadTime(CARD32 *ms)
106705b261ecSmrg{
106805b261ecSmrg    /* If the ddx/OS is careless about not processing timestamped events from
106905b261ecSmrg     * different sources in sorted order, then it's possible for time to go
107005b261ecSmrg     * backwards when it should not.  Here we ensure a decent time.
107105b261ecSmrg     */
107235c4bbdfSmrg    if ((currentTime.milliseconds - *ms) > TIMESLOP)
107335c4bbdfSmrg        currentTime.months++;
107405b261ecSmrg    else
107535c4bbdfSmrg        *ms = currentTime.milliseconds;
107635c4bbdfSmrg}
107735c4bbdfSmrg
107835c4bbdfSmrgvoid
107935c4bbdfSmrgNoticeTime(const DeviceIntPtr dev, TimeStamp time)
108035c4bbdfSmrg{
108135c4bbdfSmrg    currentTime = time;
108235c4bbdfSmrg    lastDeviceEventTime[XIAllDevices].time = currentTime;
108335c4bbdfSmrg    lastDeviceEventTime[dev->id].time = currentTime;
108435c4bbdfSmrg
108535c4bbdfSmrg    LastEventTimeToggleResetFlag(dev->id, TRUE);
108635c4bbdfSmrg    LastEventTimeToggleResetFlag(XIAllDevices, TRUE);
108705b261ecSmrg}
108805b261ecSmrg
10896747b715Smrgstatic void
109035c4bbdfSmrgNoticeTimeMillis(const DeviceIntPtr dev, CARD32 *ms)
10916747b715Smrg{
109235c4bbdfSmrg    TimeStamp time;
109335c4bbdfSmrg    if (*ms < currentTime.milliseconds)
109435c4bbdfSmrg        MonthChangedOrBadTime(ms);
109535c4bbdfSmrg    time.months = currentTime.months;
109635c4bbdfSmrg    time.milliseconds = *ms;
109735c4bbdfSmrg    NoticeTime(dev, time);
10986747b715Smrg}
109905b261ecSmrg
110005b261ecSmrgvoid
110135c4bbdfSmrgNoticeEventTime(InternalEvent *ev, DeviceIntPtr dev)
110205b261ecSmrg{
110305b261ecSmrg    if (!syncEvents.playingEvents)
110435c4bbdfSmrg        NoticeTimeMillis(dev, &ev->any.time);
110535c4bbdfSmrg}
110635c4bbdfSmrg
110735c4bbdfSmrgTimeStamp
110835c4bbdfSmrgLastEventTime(int deviceid)
110935c4bbdfSmrg{
111035c4bbdfSmrg    return lastDeviceEventTime[deviceid].time;
111135c4bbdfSmrg}
111235c4bbdfSmrg
111335c4bbdfSmrgBool
111435c4bbdfSmrgLastEventTimeWasReset(int deviceid)
111535c4bbdfSmrg{
111635c4bbdfSmrg    return lastDeviceEventTime[deviceid].reset;
111735c4bbdfSmrg}
111835c4bbdfSmrg
111935c4bbdfSmrgvoid
112035c4bbdfSmrgLastEventTimeToggleResetFlag(int deviceid, Bool state)
112135c4bbdfSmrg{
112235c4bbdfSmrg    lastDeviceEventTime[deviceid].reset = state;
112335c4bbdfSmrg}
112435c4bbdfSmrg
112535c4bbdfSmrgvoid
112635c4bbdfSmrgLastEventTimeToggleResetAll(Bool state)
112735c4bbdfSmrg{
112835c4bbdfSmrg    DeviceIntPtr dev;
112935c4bbdfSmrg    nt_list_for_each_entry(dev, inputInfo.devices, next) {
113035c4bbdfSmrg        LastEventTimeToggleResetFlag(dev->id, FALSE);
113135c4bbdfSmrg    }
113235c4bbdfSmrg    LastEventTimeToggleResetFlag(XIAllDevices, FALSE);
113335c4bbdfSmrg    LastEventTimeToggleResetFlag(XIAllMasterDevices, FALSE);
113405b261ecSmrg}
113505b261ecSmrg
113605b261ecSmrg/**************************************************************************
113705b261ecSmrg *            The following procedures deal with synchronous events       *
113805b261ecSmrg **************************************************************************/
113905b261ecSmrg
11404642e01fSmrg/**
11414642e01fSmrg * EnqueueEvent is a device's processInputProc if a device is frozen.
11424642e01fSmrg * Instead of delivering the events to the client, the event is tacked onto a
11434642e01fSmrg * linked list for later delivery.
11444642e01fSmrg */
114505b261ecSmrgvoid
11466747b715SmrgEnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
114705b261ecSmrg{
114835c4bbdfSmrg    QdEventPtr tail = NULL;
114935c4bbdfSmrg    QdEventPtr qe;
115035c4bbdfSmrg    SpritePtr pSprite = device->spriteInfo->sprite;
115135c4bbdfSmrg    int eventlen;
11526747b715Smrg    DeviceEvent *event = &ev->device_event;
11534642e01fSmrg
115435c4bbdfSmrg    if (!xorg_list_is_empty(&syncEvents.pending))
115535c4bbdfSmrg        tail = xorg_list_last_entry(&syncEvents.pending, QdEventRec, next);
115635c4bbdfSmrg
115735c4bbdfSmrg    NoticeTimeMillis(device, &ev->any.time);
115805b261ecSmrg
115905b261ecSmrg    /* Fix for key repeating bug. */
11604642e01fSmrg    if (device->key != NULL && device->key->xkbInfo != NULL &&
11616747b715Smrg        event->type == ET_KeyRelease)
116235c4bbdfSmrg        AccessXCancelRepeatKey(device->key->xkbInfo, event->detail.key);
116335c4bbdfSmrg
116435c4bbdfSmrg    if (DeviceEventCallback) {
116535c4bbdfSmrg        DeviceEventInfoRec eventinfo;
116635c4bbdfSmrg
116735c4bbdfSmrg        /*  The RECORD spec says that the root window field of motion events
116835c4bbdfSmrg         *  must be valid.  At this point, it hasn't been filled in yet, so
116935c4bbdfSmrg         *  we do it here.  The long expression below is necessary to get
117035c4bbdfSmrg         *  the current root window; the apparently reasonable alternative
117135c4bbdfSmrg         *  GetCurrentRootWindow()->drawable.id doesn't give you the right
117235c4bbdfSmrg         *  answer on the first motion event after a screen change because
117335c4bbdfSmrg         *  the data that GetCurrentRootWindow relies on hasn't been
117435c4bbdfSmrg         *  updated yet.
117535c4bbdfSmrg         */
117635c4bbdfSmrg        if (ev->any.type == ET_Motion)
117735c4bbdfSmrg            ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
117805b261ecSmrg
117935c4bbdfSmrg        eventinfo.event = ev;
118035c4bbdfSmrg        eventinfo.device = device;
118135c4bbdfSmrg        CallCallbacks(&DeviceEventCallback, (void *) &eventinfo);
118235c4bbdfSmrg    }
118335c4bbdfSmrg
118435c4bbdfSmrg    if (event->type == ET_Motion) {
118505b261ecSmrg#ifdef PANORAMIX
118635c4bbdfSmrg        if (!noPanoramiXExtension) {
118735c4bbdfSmrg            event->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
118835c4bbdfSmrg            event->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
118935c4bbdfSmrg        }
119005b261ecSmrg#endif
119135c4bbdfSmrg        pSprite->hotPhys.x = event->root_x;
119235c4bbdfSmrg        pSprite->hotPhys.y = event->root_y;
119335c4bbdfSmrg        /* do motion compression, but not if from different devices */
119435c4bbdfSmrg        if (tail &&
119535c4bbdfSmrg            (tail->event->any.type == ET_Motion) &&
119605b261ecSmrg            (tail->device == device) &&
119735c4bbdfSmrg            (tail->pScreen == pSprite->hotPhys.pScreen)) {
11986747b715Smrg            DeviceEvent *tailev = &tail->event->device_event;
119935c4bbdfSmrg
120035c4bbdfSmrg            tailev->root_x = pSprite->hotPhys.x;
120135c4bbdfSmrg            tailev->root_y = pSprite->hotPhys.y;
120235c4bbdfSmrg            tailev->time = event->time;
120335c4bbdfSmrg            tail->months = currentTime.months;
120435c4bbdfSmrg            return;
120535c4bbdfSmrg        }
120605b261ecSmrg    }
12074642e01fSmrg
12085a112b11Smrg    eventlen = sizeof(InternalEvent);
12094642e01fSmrg
12106747b715Smrg    qe = malloc(sizeof(QdEventRec) + eventlen);
121105b261ecSmrg    if (!qe)
121235c4bbdfSmrg        return;
121335c4bbdfSmrg    xorg_list_init(&qe->next);
121405b261ecSmrg    qe->device = device;
12154642e01fSmrg    qe->pScreen = pSprite->hotPhys.pScreen;
121605b261ecSmrg    qe->months = currentTime.months;
121735c4bbdfSmrg    qe->event = (InternalEvent *) (qe + 1);
12183138c4c0Smrg    CopyPartialInternalEvent(qe->event, (InternalEvent *)event);
121935c4bbdfSmrg    xorg_list_append(&qe->next, &syncEvents.pending);
122005b261ecSmrg}
122105b261ecSmrg
12224642e01fSmrg/**
12234642e01fSmrg * Run through the list of events queued up in syncEvents.
12244642e01fSmrg * For each event do:
12254642e01fSmrg * If the device for this event is not frozen anymore, take it and process it
12264642e01fSmrg * as usually.
12274642e01fSmrg * After that, check if there's any devices in the list that are not frozen.
12284642e01fSmrg * If there is none, we're done. If there is at least one device that is not
12294642e01fSmrg * frozen, then re-run from the beginning of the event queue.
12304642e01fSmrg */
123135c4bbdfSmrgvoid
123205b261ecSmrgPlayReleasedEvents(void)
123305b261ecSmrg{
123435c4bbdfSmrg    QdEventPtr tmp;
123535c4bbdfSmrg    QdEventPtr qe;
123605b261ecSmrg    DeviceIntPtr dev;
12374642e01fSmrg    DeviceIntPtr pDev;
123805b261ecSmrg
123935c4bbdfSmrg restart:
124035c4bbdfSmrg    xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) {
124135c4bbdfSmrg        if (!qe->device->deviceGrab.sync.frozen) {
124235c4bbdfSmrg            xorg_list_del(&qe->next);
12434642e01fSmrg            pDev = qe->device;
124435c4bbdfSmrg            if (qe->event->any.type == ET_Motion)
124535c4bbdfSmrg                CheckVirtualMotion(pDev, qe, NullWindow);
124635c4bbdfSmrg            syncEvents.time.months = qe->months;
12476747b715Smrg            syncEvents.time.milliseconds = qe->event->any.time;
124805b261ecSmrg#ifdef PANORAMIX
124935c4bbdfSmrg            /* Translate back to the sprite screen since processInputProc
125035c4bbdfSmrg               will translate from sprite screen to screen 0 upon reentry
125135c4bbdfSmrg               to the DIX layer */
125235c4bbdfSmrg            if (!noPanoramiXExtension) {
12536747b715Smrg                DeviceEvent *ev = &qe->event->device_event;
125435c4bbdfSmrg
125535c4bbdfSmrg                switch (ev->type) {
125635c4bbdfSmrg                case ET_Motion:
125735c4bbdfSmrg                case ET_ButtonPress:
125835c4bbdfSmrg                case ET_ButtonRelease:
125935c4bbdfSmrg                case ET_KeyPress:
126035c4bbdfSmrg                case ET_KeyRelease:
126135c4bbdfSmrg                case ET_ProximityIn:
126235c4bbdfSmrg                case ET_ProximityOut:
126335c4bbdfSmrg                case ET_TouchBegin:
126435c4bbdfSmrg                case ET_TouchUpdate:
126535c4bbdfSmrg                case ET_TouchEnd:
126635c4bbdfSmrg                    ev->root_x += screenInfo.screens[0]->x -
126735c4bbdfSmrg                        pDev->spriteInfo->sprite->screen->x;
126835c4bbdfSmrg                    ev->root_y += screenInfo.screens[0]->y -
126935c4bbdfSmrg                        pDev->spriteInfo->sprite->screen->y;
127035c4bbdfSmrg                    break;
127135c4bbdfSmrg                default:
127235c4bbdfSmrg                    break;
12736747b715Smrg                }
12746747b715Smrg
127535c4bbdfSmrg            }
127605b261ecSmrg#endif
127735c4bbdfSmrg            (*qe->device->public.processInputProc) (qe->event, qe->device);
127835c4bbdfSmrg            free(qe);
127935c4bbdfSmrg            for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen;
128035c4bbdfSmrg                 dev = dev->next);
128135c4bbdfSmrg            if (!dev)
128235c4bbdfSmrg                break;
128335c4bbdfSmrg
128435c4bbdfSmrg            /* Playing the event may have unfrozen another device. */
128535c4bbdfSmrg            /* So to play it safe, restart at the head of the queue */
128635c4bbdfSmrg            goto restart;
128735c4bbdfSmrg        }
12884642e01fSmrg    }
128905b261ecSmrg}
129005b261ecSmrg
12914642e01fSmrg/**
12924642e01fSmrg * Freeze or thaw the given devices. The device's processing proc is
12934642e01fSmrg * switched to either the real processing proc (in case of thawing) or an
12944642e01fSmrg * enqueuing processing proc (usually EnqueueEvent()).
12954642e01fSmrg *
12964642e01fSmrg * @param dev The device to freeze/thaw
12974642e01fSmrg * @param frozen True to freeze or false to thaw.
12984642e01fSmrg */
129905b261ecSmrgstatic void
130005b261ecSmrgFreezeThaw(DeviceIntPtr dev, Bool frozen)
130105b261ecSmrg{
13024642e01fSmrg    dev->deviceGrab.sync.frozen = frozen;
130305b261ecSmrg    if (frozen)
130435c4bbdfSmrg        dev->public.processInputProc = dev->public.enqueueInputProc;
130505b261ecSmrg    else
130635c4bbdfSmrg        dev->public.processInputProc = dev->public.realInputProc;
130705b261ecSmrg}
130805b261ecSmrg
13094642e01fSmrg/**
13104642e01fSmrg * Unfreeze devices and replay all events to the respective clients.
13114642e01fSmrg *
13124642e01fSmrg * ComputeFreezes takes the first event in the device's frozen event queue. It
13134642e01fSmrg * runs up the sprite tree (spriteTrace) and searches for the window to replay
13144642e01fSmrg * the events from. If it is found, it checks for passive grabs one down from
13154642e01fSmrg * the window or delivers the events.
13164642e01fSmrg */
13174642e01fSmrgstatic void
131805b261ecSmrgComputeFreezes(void)
131905b261ecSmrg{
132005b261ecSmrg    DeviceIntPtr replayDev = syncEvents.replayDev;
132105b261ecSmrg    GrabPtr grab;
132205b261ecSmrg    DeviceIntPtr dev;
132305b261ecSmrg
132405b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
132535c4bbdfSmrg        FreezeThaw(dev, dev->deviceGrab.sync.other ||
132635c4bbdfSmrg                   (dev->deviceGrab.sync.state >= FROZEN));
132735c4bbdfSmrg    if (syncEvents.playingEvents ||
132835c4bbdfSmrg        (!replayDev && xorg_list_is_empty(&syncEvents.pending)))
132935c4bbdfSmrg        return;
133005b261ecSmrg    syncEvents.playingEvents = TRUE;
133135c4bbdfSmrg    if (replayDev) {
13325a112b11Smrg        InternalEvent *event = replayDev->deviceGrab.sync.event;
13336747b715Smrg
133435c4bbdfSmrg        syncEvents.replayDev = (DeviceIntPtr) NULL;
133505b261ecSmrg
13365a112b11Smrg        if (!CheckDeviceGrabs(replayDev, event,
13375a112b11Smrg                              syncEvents.replayWin)) {
13385a112b11Smrg            if (IsTouchEvent(event)) {
133935c4bbdfSmrg                TouchPointInfoPtr ti =
13405a112b11Smrg                    TouchFindByClientID(replayDev, event->device_event.touchid);
134135c4bbdfSmrg                BUG_WARN(!ti);
134235c4bbdfSmrg
134335c4bbdfSmrg                TouchListenerAcceptReject(replayDev, ti, 0, XIRejectTouch);
134435c4bbdfSmrg            }
13455a112b11Smrg            else if (IsGestureEvent(event)) {
13465a112b11Smrg                GestureInfoPtr gi =
13475a112b11Smrg                    GestureFindActiveByEventType(replayDev, event->any.type);
13485a112b11Smrg                if (gi) {
13495a112b11Smrg                    GestureEmitGestureEndToOwner(replayDev, gi);
13505a112b11Smrg                    GestureEndGesture(gi);
13515a112b11Smrg                }
13525a112b11Smrg                ProcessGestureEvent(event, replayDev);
13535a112b11Smrg            }
13545a112b11Smrg            else {
13555a112b11Smrg                WindowPtr w = XYToWindow(replayDev->spriteInfo->sprite,
13565a112b11Smrg                                         event->device_event.root_x,
13575a112b11Smrg                                         event->device_event.root_y);
13585a112b11Smrg                if (replayDev->focus && !IsPointerEvent(event))
13595a112b11Smrg                    DeliverFocusedEvent(replayDev, event, w);
13605a112b11Smrg                else
13615a112b11Smrg                    DeliverDeviceEvents(w, event, NullGrab,
13625a112b11Smrg                                        NullWindow, replayDev);
13635a112b11Smrg            }
13649ace9065Smrg        }
136505b261ecSmrg    }
136635c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
136735c4bbdfSmrg        if (!dev->deviceGrab.sync.frozen) {
136835c4bbdfSmrg            PlayReleasedEvents();
136935c4bbdfSmrg            break;
137035c4bbdfSmrg        }
137105b261ecSmrg    }
137205b261ecSmrg    syncEvents.playingEvents = FALSE;
137335c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
137435c4bbdfSmrg        if (DevHasCursor(dev)) {
13754642e01fSmrg            /* the following may have been skipped during replay,
137635c4bbdfSmrg               so do it now */
137735c4bbdfSmrg            if ((grab = dev->deviceGrab.grab) && grab->confineTo) {
13784642e01fSmrg                if (grab->confineTo->drawable.pScreen !=
137935c4bbdfSmrg                    dev->spriteInfo->sprite->hotPhys.pScreen)
13804642e01fSmrg                    dev->spriteInfo->sprite->hotPhys.x =
13814642e01fSmrg                        dev->spriteInfo->sprite->hotPhys.y = 0;
13824642e01fSmrg                ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE);
13834642e01fSmrg            }
13844642e01fSmrg            else
13854642e01fSmrg                ConfineCursorToWindow(dev,
138635c4bbdfSmrg                                      dev->spriteInfo->sprite->hotPhys.pScreen->
138735c4bbdfSmrg                                      root, TRUE, FALSE);
13884642e01fSmrg            PostNewCursor(dev);
13894642e01fSmrg        }
139005b261ecSmrg    }
139105b261ecSmrg}
139205b261ecSmrg
139305b261ecSmrg#ifdef RANDR
139405b261ecSmrgvoid
139535c4bbdfSmrgScreenRestructured(ScreenPtr pScreen)
139605b261ecSmrg{
139705b261ecSmrg    GrabPtr grab;
13984642e01fSmrg    DeviceIntPtr pDev;
139905b261ecSmrg
140035c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
140135c4bbdfSmrg        if (!IsFloating(pDev) && !DevHasCursor(pDev))
14024642e01fSmrg            continue;
14034642e01fSmrg
14044642e01fSmrg        /* GrabDevice doesn't have a confineTo field, so we don't need to
14054642e01fSmrg         * worry about it. */
140635c4bbdfSmrg        if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
14074642e01fSmrg            if (grab->confineTo->drawable.pScreen
140835c4bbdfSmrg                != pDev->spriteInfo->sprite->hotPhys.pScreen)
140935c4bbdfSmrg                pDev->spriteInfo->sprite->hotPhys.x =
141035c4bbdfSmrg                    pDev->spriteInfo->sprite->hotPhys.y = 0;
14114642e01fSmrg            ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
14124642e01fSmrg        }
14134642e01fSmrg        else
14144642e01fSmrg            ConfineCursorToWindow(pDev,
141535c4bbdfSmrg                                  pDev->spriteInfo->sprite->hotPhys.pScreen->
141635c4bbdfSmrg                                  root, TRUE, FALSE);
141705b261ecSmrg    }
141805b261ecSmrg}
141905b261ecSmrg#endif
142005b261ecSmrg
14214642e01fSmrgstatic void
142205b261ecSmrgCheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
142305b261ecSmrg{
14244642e01fSmrg    GrabPtr grab = thisDev->deviceGrab.grab;
142505b261ecSmrg    DeviceIntPtr dev;
142605b261ecSmrg
142705b261ecSmrg    if (thisMode == GrabModeSync)
142835c4bbdfSmrg        thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT;
142935c4bbdfSmrg    else {                      /* free both if same client owns both */
143035c4bbdfSmrg        thisDev->deviceGrab.sync.state = THAWED;
143135c4bbdfSmrg        if (thisDev->deviceGrab.sync.other &&
143235c4bbdfSmrg            (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) ==
143335c4bbdfSmrg             CLIENT_BITS(grab->resource)))
143435c4bbdfSmrg            thisDev->deviceGrab.sync.other = NullGrab;
143505b261ecSmrg    }
14364642e01fSmrg
143735c4bbdfSmrg    if (IsMaster(thisDev)) {
14384642e01fSmrg        dev = GetPairedDevice(thisDev);
14394642e01fSmrg        if (otherMode == GrabModeSync)
14404642e01fSmrg            dev->deviceGrab.sync.other = grab;
144135c4bbdfSmrg        else {                  /* free both if same client owns both */
14424642e01fSmrg            if (dev->deviceGrab.sync.other &&
144335c4bbdfSmrg                (CLIENT_BITS(dev->deviceGrab.sync.other->resource) ==
144435c4bbdfSmrg                 CLIENT_BITS(grab->resource)))
14454642e01fSmrg                dev->deviceGrab.sync.other = NullGrab;
14464642e01fSmrg        }
144705b261ecSmrg    }
144805b261ecSmrg    ComputeFreezes();
144905b261ecSmrg}
145005b261ecSmrg
14516747b715Smrg/**
14526747b715Smrg * Save the device's master device id. This needs to be done
14536747b715Smrg * if a client directly grabs a slave device that is attached to a master. For
14546747b715Smrg * the duration of the grab, the device is detached, ungrabbing re-attaches it
14556747b715Smrg * though.
14566747b715Smrg *
14576747b715Smrg * We store the ID of the master device only in case the master disappears
14586747b715Smrg * while the device has a grab.
14596747b715Smrg */
14606747b715Smrgstatic void
14616747b715SmrgDetachFromMaster(DeviceIntPtr dev)
14626747b715Smrg{
146335c4bbdfSmrg    if (IsFloating(dev))
14646747b715Smrg        return;
14656747b715Smrg
146635c4bbdfSmrg    dev->saved_master_id = GetMaster(dev, MASTER_ATTACHED)->id;
14676747b715Smrg
14686747b715Smrg    AttachDevice(NULL, dev, NULL);
14696747b715Smrg}
14706747b715Smrg
14716747b715Smrgstatic void
14726747b715SmrgReattachToOldMaster(DeviceIntPtr dev)
14736747b715Smrg{
14746747b715Smrg    DeviceIntPtr master = NULL;
14756747b715Smrg
14766747b715Smrg    if (IsMaster(dev))
14776747b715Smrg        return;
14786747b715Smrg
14796747b715Smrg    dixLookupDevice(&master, dev->saved_master_id, serverClient, DixUseAccess);
14806747b715Smrg
148135c4bbdfSmrg    if (master) {
14826747b715Smrg        AttachDevice(serverClient, dev, master);
148335c4bbdfSmrg        dev->saved_master_id = 0;
148435c4bbdfSmrg    }
148535c4bbdfSmrg}
148635c4bbdfSmrg
14872f76b07dSmrg/**
14882f76b07dSmrg * Return the current master keyboard or, if we're temporarily detached, the one
14892f76b07dSmrg * we've been attached to previously.
14902f76b07dSmrg */
14912f76b07dSmrgstatic DeviceIntPtr
14922f76b07dSmrgCurrentOrOldMasterKeyboard(DeviceIntPtr dev)
14932f76b07dSmrg{
14942f76b07dSmrg    DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
14952f76b07dSmrg
14962f76b07dSmrg    if (kbd)
14972f76b07dSmrg        return kbd;
14982f76b07dSmrg
14992f76b07dSmrg    if (dev->saved_master_id) {
15002f76b07dSmrg        dixLookupDevice(&kbd, dev->saved_master_id, serverClient, DixUseAccess);
15012f76b07dSmrg        if (!kbd)
15022f76b07dSmrg            return NULL;
15032f76b07dSmrg        /* if dev is a pointer the saved master is a master pointer,
15042f76b07dSmrg         * we want the keybard */
15052f76b07dSmrg        return GetMaster(kbd, MASTER_KEYBOARD);
15062f76b07dSmrg    }
15072f76b07dSmrg
15082f76b07dSmrg    return NULL;
15092f76b07dSmrg}
15102f76b07dSmrg
151135c4bbdfSmrg/**
151235c4bbdfSmrg * Update touch records when an explicit grab is activated. Any touches owned by
151335c4bbdfSmrg * the grabbing client are updated so the listener state reflects the new grab.
151435c4bbdfSmrg */
151535c4bbdfSmrgstatic void
151635c4bbdfSmrgUpdateTouchesForGrab(DeviceIntPtr mouse)
151735c4bbdfSmrg{
151835c4bbdfSmrg    int i;
151935c4bbdfSmrg
152035c4bbdfSmrg    if (!mouse->touch || mouse->deviceGrab.fromPassiveGrab)
152135c4bbdfSmrg        return;
152235c4bbdfSmrg
152335c4bbdfSmrg    for (i = 0; i < mouse->touch->num_touches; i++) {
152435c4bbdfSmrg        TouchPointInfoPtr ti = mouse->touch->touches + i;
152535c4bbdfSmrg        TouchListener *listener = &ti->listeners[0];
152635c4bbdfSmrg        GrabPtr grab = mouse->deviceGrab.grab;
152735c4bbdfSmrg
152835c4bbdfSmrg        if (ti->active &&
152935c4bbdfSmrg            CLIENT_BITS(listener->listener) == grab->resource) {
15305a112b11Smrg            if (grab->grabtype == CORE || grab->grabtype == XI ||
15315a112b11Smrg                !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin)) {
153290bea6a0Smrg                /*  Note that the grab will override any current listeners and if these listeners
153390bea6a0Smrg                    already received touch events then this is the place to send touch end event
153490bea6a0Smrg                    to complete the touch sequence.
15355a112b11Smrg
153690bea6a0Smrg                    Unfortunately GTK3 menu widget implementation relies on not getting touch end
153790bea6a0Smrg                    event, so we can't fix the current behavior.
153890bea6a0Smrg                */
15395a112b11Smrg                listener->type = TOUCH_LISTENER_POINTER_GRAB;
15405a112b11Smrg            } else {
15415a112b11Smrg                listener->type = TOUCH_LISTENER_GRAB;
15425a112b11Smrg            }
15435a112b11Smrg
154435c4bbdfSmrg            listener->listener = grab->resource;
154535c4bbdfSmrg            listener->level = grab->grabtype;
154635c4bbdfSmrg            listener->window = grab->window;
15475a112b11Smrg            listener->state = TOUCH_LISTENER_IS_OWNER;
154835c4bbdfSmrg
154935c4bbdfSmrg            if (listener->grab)
155035c4bbdfSmrg                FreeGrab(listener->grab);
155135c4bbdfSmrg            listener->grab = AllocGrab(grab);
155235c4bbdfSmrg        }
15536747b715Smrg    }
15546747b715Smrg}
15556747b715Smrg
15565a112b11Smrg/**
15575a112b11Smrg * Update gesture records when an explicit grab is activated. Any gestures owned
15585a112b11Smrg * by the grabbing client are updated so the listener state reflects the new
15595a112b11Smrg * grab.
15605a112b11Smrg */
15615a112b11Smrgstatic void
15625a112b11SmrgUpdateGesturesForGrab(DeviceIntPtr mouse)
15635a112b11Smrg{
15645a112b11Smrg    if (!mouse->gesture || mouse->deviceGrab.fromPassiveGrab)
15655a112b11Smrg        return;
15665a112b11Smrg
15675a112b11Smrg    GestureInfoPtr gi = &mouse->gesture->gesture;
15685a112b11Smrg    GestureListener *listener = &gi->listener;
15695a112b11Smrg    GrabPtr grab = mouse->deviceGrab.grab;
15705a112b11Smrg
15715a112b11Smrg    if (gi->active && CLIENT_BITS(listener->listener) == grab->resource) {
15725a112b11Smrg        if (grab->grabtype == CORE || grab->grabtype == XI ||
15735a112b11Smrg            !xi2mask_isset(grab->xi2mask, mouse, GetXI2Type(gi->type))) {
15745a112b11Smrg
15755a112b11Smrg            if (listener->type == GESTURE_LISTENER_REGULAR) {
15765a112b11Smrg                /* if the listener already got any events relating to the gesture, we must send
15775a112b11Smrg                   a gesture end because the grab overrides the previous listener and won't
15785a112b11Smrg                   itself send any gesture events.
15795a112b11Smrg                */
15805a112b11Smrg                GestureEmitGestureEndToOwner(mouse, gi);
15815a112b11Smrg            }
15825a112b11Smrg            listener->type = GESTURE_LISTENER_NONGESTURE_GRAB;
15835a112b11Smrg        } else {
15845a112b11Smrg            listener->type = GESTURE_LISTENER_GRAB;
15855a112b11Smrg        }
15865a112b11Smrg
15875a112b11Smrg        listener->listener = grab->resource;
15885a112b11Smrg        listener->window = grab->window;
15895a112b11Smrg
15905a112b11Smrg        if (listener->grab)
15915a112b11Smrg            FreeGrab(listener->grab);
15925a112b11Smrg        listener->grab = AllocGrab(grab);
15935a112b11Smrg    }
15945a112b11Smrg}
15955a112b11Smrg
159605b261ecSmrg/**
159705b261ecSmrg * Activate a pointer grab on the given device. A pointer grab will cause all
15984642e01fSmrg * core pointer events of this device to be delivered to the grabbing client only.
15994642e01fSmrg * No other device will send core events to the grab client while the grab is
16004642e01fSmrg * on, but core events will be sent to other clients.
16014642e01fSmrg * Can cause the cursor to change if a grab cursor is set.
16024642e01fSmrg *
16034642e01fSmrg * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab
16044642e01fSmrg * is an implicit grab caused by a ButtonPress event.
16054642e01fSmrg *
160605b261ecSmrg * @param mouse The device to grab.
160705b261ecSmrg * @param grab The grab structure, needs to be setup.
160805b261ecSmrg * @param autoGrab True if the grab was caused by a button down event and not
16095a112b11Smrg * explicitly by a client.
161005b261ecSmrg */
161105b261ecSmrgvoid
16124642e01fSmrgActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
161305b261ecSmrg                    TimeStamp time, Bool autoGrab)
161405b261ecSmrg{
16154642e01fSmrg    GrabInfoPtr grabinfo = &mouse->deviceGrab;
161635c4bbdfSmrg    GrabPtr oldgrab = grabinfo->grab;
16174642e01fSmrg    WindowPtr oldWin = (grabinfo->grab) ?
161835c4bbdfSmrg        grabinfo->grab->window : mouse->spriteInfo->sprite->win;
16194642e01fSmrg    Bool isPassive = autoGrab & ~ImplicitGrabMask;
162005b261ecSmrg
16216747b715Smrg    /* slave devices need to float for the duration of the grab. */
162235c4bbdfSmrg    if (grab->grabtype == XI2 &&
16236747b715Smrg        !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse))
16246747b715Smrg        DetachFromMaster(mouse);
16256747b715Smrg
162635c4bbdfSmrg    if (grab->confineTo) {
162735c4bbdfSmrg        if (grab->confineTo->drawable.pScreen
162835c4bbdfSmrg            != mouse->spriteInfo->sprite->hotPhys.pScreen)
162935c4bbdfSmrg            mouse->spriteInfo->sprite->hotPhys.x =
16304642e01fSmrg                mouse->spriteInfo->sprite->hotPhys.y = 0;
163135c4bbdfSmrg        ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE);
163205b261ecSmrg    }
1633806e81e9Smrg    if (! (grabinfo->grab && oldWin == grabinfo->grab->window
1634806e81e9Smrg			  && oldWin == grab->window))
1635806e81e9Smrg        DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab);
163605b261ecSmrg    mouse->valuator->motionHintWindow = NullWindow;
163705b261ecSmrg    if (syncEvents.playingEvents)
16384642e01fSmrg        grabinfo->grabTime = syncEvents.time;
163905b261ecSmrg    else
164035c4bbdfSmrg        grabinfo->grabTime = time;
164135c4bbdfSmrg    grabinfo->grab = AllocGrab(grab);
16424642e01fSmrg    grabinfo->fromPassiveGrab = isPassive;
16434642e01fSmrg    grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
16444642e01fSmrg    PostNewCursor(mouse);
164535c4bbdfSmrg    UpdateTouchesForGrab(mouse);
16465a112b11Smrg    UpdateGesturesForGrab(mouse);
164735c4bbdfSmrg    CheckGrabForSyncs(mouse, (Bool) grab->pointerMode,
164835c4bbdfSmrg                      (Bool) grab->keyboardMode);
164935c4bbdfSmrg    if (oldgrab)
165035c4bbdfSmrg        FreeGrab(oldgrab);
165105b261ecSmrg}
165205b261ecSmrg
165305b261ecSmrg/**
165405b261ecSmrg * Delete grab on given device, update the sprite.
165505b261ecSmrg *
16564642e01fSmrg * Extension devices are set up for ActivateKeyboardGrab().
165705b261ecSmrg */
165805b261ecSmrgvoid
165905b261ecSmrgDeactivatePointerGrab(DeviceIntPtr mouse)
166005b261ecSmrg{
16614642e01fSmrg    GrabPtr grab = mouse->deviceGrab.grab;
166205b261ecSmrg    DeviceIntPtr dev;
166335c4bbdfSmrg    Bool wasPassive = mouse->deviceGrab.fromPassiveGrab;
16646747b715Smrg    Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
16656747b715Smrg                        mouse->deviceGrab.implicitGrab);
166635c4bbdfSmrg    XID grab_resource = grab->resource;
166735c4bbdfSmrg    int i;
166835c4bbdfSmrg
166935c4bbdfSmrg    /* If an explicit grab was deactivated, we must remove it from the head of
167035c4bbdfSmrg     * all the touches' listener lists. */
167135c4bbdfSmrg    for (i = 0; !wasPassive && mouse->touch && i < mouse->touch->num_touches; i++) {
167235c4bbdfSmrg        TouchPointInfoPtr ti = mouse->touch->touches + i;
167335c4bbdfSmrg        if (ti->active && TouchResourceIsOwner(ti, grab_resource)) {
167435c4bbdfSmrg            int mode = XIRejectTouch;
167535c4bbdfSmrg            /* Rejecting will generate a TouchEnd, but we must not
167635c4bbdfSmrg               emulate a ButtonRelease here. So pretend the listener
167735c4bbdfSmrg               already has the end event */
167835c4bbdfSmrg            if (grab->grabtype == CORE || grab->grabtype == XI ||
16795a112b11Smrg                    !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin)) {
168035c4bbdfSmrg                mode = XIAcceptTouch;
168135c4bbdfSmrg                /* NOTE: we set the state here, but
168235c4bbdfSmrg                 * ProcessTouchOwnershipEvent() will still call
168335c4bbdfSmrg                 * TouchEmitTouchEnd for this listener. The other half of
168435c4bbdfSmrg                 * this hack is in DeliverTouchEndEvent */
16855a112b11Smrg                ti->listeners[0].state = TOUCH_LISTENER_HAS_END;
168635c4bbdfSmrg            }
168735c4bbdfSmrg            TouchListenerAcceptReject(mouse, ti, 0, mode);
168835c4bbdfSmrg        }
168935c4bbdfSmrg    }
169035c4bbdfSmrg
169135c4bbdfSmrg    TouchRemovePointerGrab(mouse);
169205b261ecSmrg
169305b261ecSmrg    mouse->valuator->motionHintWindow = NullWindow;
16944642e01fSmrg    mouse->deviceGrab.grab = NullGrab;
16954642e01fSmrg    mouse->deviceGrab.sync.state = NOT_GRABBED;
16964642e01fSmrg    mouse->deviceGrab.fromPassiveGrab = FALSE;
16974642e01fSmrg
169835c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
169935c4bbdfSmrg        if (dev->deviceGrab.sync.other == grab)
170035c4bbdfSmrg            dev->deviceGrab.sync.other = NullGrab;
170105b261ecSmrg    }
17025a112b11Smrg
17035a112b11Smrg    /* in case of explicit gesture grab, send end event to the grab client */
17045a112b11Smrg    if (!wasPassive && mouse->gesture) {
17055a112b11Smrg        GestureInfoPtr gi = &mouse->gesture->gesture;
17065a112b11Smrg        if (gi->active && GestureResourceIsOwner(gi, grab_resource)) {
17075a112b11Smrg            GestureEmitGestureEndToOwner(mouse, gi);
17085a112b11Smrg            GestureEndGesture(gi);
17095a112b11Smrg        }
17105a112b11Smrg    }
17115a112b11Smrg
17126747b715Smrg    DoEnterLeaveEvents(mouse, mouse->id, grab->window,
17134642e01fSmrg                       mouse->spriteInfo->sprite->win, NotifyUngrab);
171405b261ecSmrg    if (grab->confineTo)
171535c4bbdfSmrg        ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE);
17164642e01fSmrg    PostNewCursor(mouse);
17174642e01fSmrg
171835c4bbdfSmrg    if (!wasImplicit && grab->grabtype == XI2)
17196747b715Smrg        ReattachToOldMaster(mouse);
17206747b715Smrg
172105b261ecSmrg    ComputeFreezes();
172235c4bbdfSmrg
172335c4bbdfSmrg    FreeGrab(grab);
172405b261ecSmrg}
172505b261ecSmrg
172605b261ecSmrg/**
17274642e01fSmrg * Activate a keyboard grab on the given device.
172805b261ecSmrg *
172905b261ecSmrg * Extension devices have ActivateKeyboardGrab() set as their grabbing proc.
173005b261ecSmrg */
173105b261ecSmrgvoid
173235c4bbdfSmrgActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time,
173335c4bbdfSmrg                     Bool passive)
173405b261ecSmrg{
17354642e01fSmrg    GrabInfoPtr grabinfo = &keybd->deviceGrab;
173635c4bbdfSmrg    GrabPtr oldgrab = grabinfo->grab;
173705b261ecSmrg    WindowPtr oldWin;
17382f76b07dSmrg    DeviceIntPtr master_keyboard = CurrentOrOldMasterKeyboard(keybd);
17392f76b07dSmrg
17402f76b07dSmrg    if (!master_keyboard)
17412f76b07dSmrg        master_keyboard = inputInfo.keyboard;
174205b261ecSmrg
17436747b715Smrg    /* slave devices need to float for the duration of the grab. */
174435c4bbdfSmrg    if (grab->grabtype == XI2 && keybd->enabled &&
174535c4bbdfSmrg        !(passive & ImplicitGrabMask) && !IsMaster(keybd))
17466747b715Smrg        DetachFromMaster(keybd);
17476747b715Smrg
174835c4bbdfSmrg    if (!keybd->enabled)
174935c4bbdfSmrg        oldWin = NULL;
175035c4bbdfSmrg    else if (grabinfo->grab)
175135c4bbdfSmrg        oldWin = grabinfo->grab->window;
175205b261ecSmrg    else if (keybd->focus)
175335c4bbdfSmrg        oldWin = keybd->focus->win;
175405b261ecSmrg    else
175535c4bbdfSmrg        oldWin = keybd->spriteInfo->sprite->win;
175605b261ecSmrg    if (oldWin == FollowKeyboardWin)
17572f76b07dSmrg        oldWin = master_keyboard->focus->win;
175805b261ecSmrg    if (keybd->valuator)
175935c4bbdfSmrg        keybd->valuator->motionHintWindow = NullWindow;
1760806e81e9Smrg    if (oldWin &&
1761806e81e9Smrg	! (grabinfo->grab && oldWin == grabinfo->grab->window
1762806e81e9Smrg			  && oldWin == grab->window))
176335c4bbdfSmrg        DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
176405b261ecSmrg    if (syncEvents.playingEvents)
176535c4bbdfSmrg        grabinfo->grabTime = syncEvents.time;
176605b261ecSmrg    else
176735c4bbdfSmrg        grabinfo->grabTime = time;
176835c4bbdfSmrg    grabinfo->grab = AllocGrab(grab);
17694642e01fSmrg    grabinfo->fromPassiveGrab = passive;
17706747b715Smrg    grabinfo->implicitGrab = passive & ImplicitGrabMask;
177135c4bbdfSmrg    CheckGrabForSyncs(keybd, (Bool) grab->keyboardMode,
177235c4bbdfSmrg                      (Bool) grab->pointerMode);
177335c4bbdfSmrg    if (oldgrab)
177435c4bbdfSmrg        FreeGrab(oldgrab);
177505b261ecSmrg}
177605b261ecSmrg
177705b261ecSmrg/**
17784642e01fSmrg * Delete keyboard grab for the given device.
177905b261ecSmrg */
178005b261ecSmrgvoid
178105b261ecSmrgDeactivateKeyboardGrab(DeviceIntPtr keybd)
178205b261ecSmrg{
17834642e01fSmrg    GrabPtr grab = keybd->deviceGrab.grab;
178405b261ecSmrg    DeviceIntPtr dev;
178535c4bbdfSmrg    WindowPtr focusWin;
17866747b715Smrg    Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab &&
17876747b715Smrg                        keybd->deviceGrab.implicitGrab);
17882f76b07dSmrg    DeviceIntPtr master_keyboard = CurrentOrOldMasterKeyboard(keybd);
17892f76b07dSmrg
17902f76b07dSmrg    if (!master_keyboard)
17912f76b07dSmrg        master_keyboard = inputInfo.keyboard;
179205b261ecSmrg
179305b261ecSmrg    if (keybd->valuator)
179435c4bbdfSmrg        keybd->valuator->motionHintWindow = NullWindow;
17954642e01fSmrg    keybd->deviceGrab.grab = NullGrab;
17964642e01fSmrg    keybd->deviceGrab.sync.state = NOT_GRABBED;
17974642e01fSmrg    keybd->deviceGrab.fromPassiveGrab = FALSE;
17984642e01fSmrg
179935c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
180035c4bbdfSmrg        if (dev->deviceGrab.sync.other == grab)
180135c4bbdfSmrg            dev->deviceGrab.sync.other = NullGrab;
180205b261ecSmrg    }
180335c4bbdfSmrg
180435c4bbdfSmrg    if (keybd->focus)
180535c4bbdfSmrg        focusWin = keybd->focus->win;
180635c4bbdfSmrg    else if (keybd->spriteInfo->sprite)
180735c4bbdfSmrg        focusWin = keybd->spriteInfo->sprite->win;
180835c4bbdfSmrg    else
180935c4bbdfSmrg        focusWin = NullWindow;
181035c4bbdfSmrg
181135c4bbdfSmrg    if (focusWin == FollowKeyboardWin)
18122f76b07dSmrg        focusWin = master_keyboard->focus->win;
181335c4bbdfSmrg
181405b261ecSmrg    DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
18154642e01fSmrg
181635c4bbdfSmrg    if (!wasImplicit && grab->grabtype == XI2)
18176747b715Smrg        ReattachToOldMaster(keybd);
18186747b715Smrg
181905b261ecSmrg    ComputeFreezes();
182035c4bbdfSmrg
182135c4bbdfSmrg    FreeGrab(grab);
182205b261ecSmrg}
182305b261ecSmrg
182405b261ecSmrgvoid
182535c4bbdfSmrgAllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState)
182605b261ecSmrg{
182705b261ecSmrg    Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
182805b261ecSmrg    TimeStamp grabTime;
182905b261ecSmrg    DeviceIntPtr dev;
183035c4bbdfSmrg    GrabInfoPtr devgrabinfo, grabinfo = &thisDev->deviceGrab;
183105b261ecSmrg
18324642e01fSmrg    thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
183305b261ecSmrg    thisSynced = FALSE;
183405b261ecSmrg    otherGrabbed = FALSE;
18356747b715Smrg    othersFrozen = FALSE;
18364642e01fSmrg    grabTime = grabinfo->grabTime;
183735c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
18384642e01fSmrg        devgrabinfo = &dev->deviceGrab;
18394642e01fSmrg
184035c4bbdfSmrg        if (dev == thisDev)
184135c4bbdfSmrg            continue;
184235c4bbdfSmrg        if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) {
184335c4bbdfSmrg            if (!(thisGrabbed || otherGrabbed) ||
184435c4bbdfSmrg                (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER))
184535c4bbdfSmrg                grabTime = devgrabinfo->grabTime;
184635c4bbdfSmrg            otherGrabbed = TRUE;
184735c4bbdfSmrg            if (grabinfo->sync.other == devgrabinfo->grab)
184835c4bbdfSmrg                thisSynced = TRUE;
184935c4bbdfSmrg            if (devgrabinfo->sync.state >= FROZEN)
185035c4bbdfSmrg                othersFrozen = TRUE;
185135c4bbdfSmrg        }
185205b261ecSmrg    }
18534642e01fSmrg    if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced))
185435c4bbdfSmrg        return;
185505b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
185635c4bbdfSmrg        (CompareTimeStamps(time, grabTime) == EARLIER))
185735c4bbdfSmrg        return;
185835c4bbdfSmrg    switch (newState) {
185935c4bbdfSmrg    case THAWED:               /* Async */
186035c4bbdfSmrg        if (thisGrabbed)
186135c4bbdfSmrg            grabinfo->sync.state = THAWED;
186235c4bbdfSmrg        if (thisSynced)
186335c4bbdfSmrg            grabinfo->sync.other = NullGrab;
186435c4bbdfSmrg        ComputeFreezes();
186535c4bbdfSmrg        break;
186635c4bbdfSmrg    case FREEZE_NEXT_EVENT:    /* Sync */
186735c4bbdfSmrg        if (thisGrabbed) {
186835c4bbdfSmrg            grabinfo->sync.state = FREEZE_NEXT_EVENT;
186935c4bbdfSmrg            if (thisSynced)
187035c4bbdfSmrg                grabinfo->sync.other = NullGrab;
187135c4bbdfSmrg            ComputeFreezes();
187235c4bbdfSmrg        }
187335c4bbdfSmrg        break;
187435c4bbdfSmrg    case THAWED_BOTH:          /* AsyncBoth */
187535c4bbdfSmrg        if (othersFrozen) {
187635c4bbdfSmrg            for (dev = inputInfo.devices; dev; dev = dev->next) {
187735c4bbdfSmrg                devgrabinfo = &dev->deviceGrab;
187835c4bbdfSmrg                if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
187935c4bbdfSmrg                    devgrabinfo->sync.state = THAWED;
188035c4bbdfSmrg                if (devgrabinfo->sync.other &&
188135c4bbdfSmrg                    SameClient(devgrabinfo->sync.other, client))
188235c4bbdfSmrg                    devgrabinfo->sync.other = NullGrab;
188335c4bbdfSmrg            }
188435c4bbdfSmrg            ComputeFreezes();
188535c4bbdfSmrg        }
188635c4bbdfSmrg        break;
188735c4bbdfSmrg    case FREEZE_BOTH_NEXT_EVENT:       /* SyncBoth */
188835c4bbdfSmrg        if (othersFrozen) {
188935c4bbdfSmrg            for (dev = inputInfo.devices; dev; dev = dev->next) {
189035c4bbdfSmrg                devgrabinfo = &dev->deviceGrab;
189135c4bbdfSmrg                if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
189235c4bbdfSmrg                    devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT;
189335c4bbdfSmrg                if (devgrabinfo->sync.other
189435c4bbdfSmrg                    && SameClient(devgrabinfo->sync.other, client))
189535c4bbdfSmrg                    devgrabinfo->sync.other = NullGrab;
189635c4bbdfSmrg            }
189735c4bbdfSmrg            ComputeFreezes();
189835c4bbdfSmrg        }
189935c4bbdfSmrg        break;
190035c4bbdfSmrg    case NOT_GRABBED:          /* Replay */
190135c4bbdfSmrg        if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT) {
190235c4bbdfSmrg            if (thisSynced)
190335c4bbdfSmrg                grabinfo->sync.other = NullGrab;
190435c4bbdfSmrg            syncEvents.replayDev = thisDev;
190535c4bbdfSmrg            syncEvents.replayWin = grabinfo->grab->window;
190635c4bbdfSmrg            (*grabinfo->DeactivateGrab) (thisDev);
190735c4bbdfSmrg            syncEvents.replayDev = (DeviceIntPtr) NULL;
190835c4bbdfSmrg        }
190935c4bbdfSmrg        break;
191035c4bbdfSmrg    case THAW_OTHERS:          /* AsyncOthers */
191135c4bbdfSmrg        if (othersFrozen) {
191235c4bbdfSmrg            for (dev = inputInfo.devices; dev; dev = dev->next) {
191335c4bbdfSmrg                if (dev == thisDev)
191435c4bbdfSmrg                    continue;
191535c4bbdfSmrg                devgrabinfo = &dev->deviceGrab;
191635c4bbdfSmrg                if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
191735c4bbdfSmrg                    devgrabinfo->sync.state = THAWED;
191835c4bbdfSmrg                if (devgrabinfo->sync.other
191935c4bbdfSmrg                    && SameClient(devgrabinfo->sync.other, client))
192035c4bbdfSmrg                    devgrabinfo->sync.other = NullGrab;
192135c4bbdfSmrg            }
192235c4bbdfSmrg            ComputeFreezes();
192335c4bbdfSmrg        }
192435c4bbdfSmrg        break;
192535c4bbdfSmrg    }
192635c4bbdfSmrg
192735c4bbdfSmrg    /* We've unfrozen the grab. If the grab was a touch grab, we're now the
192835c4bbdfSmrg     * owner and expected to accept/reject it. Reject == ReplayPointer which
192935c4bbdfSmrg     * we've handled in ComputeFreezes() (during DeactivateGrab) above,
193035c4bbdfSmrg     * anything else is accept.
193135c4bbdfSmrg     */
193235c4bbdfSmrg    if (newState != NOT_GRABBED /* Replay */ &&
19335a112b11Smrg        IsTouchEvent(grabinfo->sync.event)) {
19345a112b11Smrg        TouchAcceptAndEnd(thisDev, grabinfo->sync.event->device_event.touchid);
193505b261ecSmrg    }
193605b261ecSmrg}
193705b261ecSmrg
193805b261ecSmrg/**
193905b261ecSmrg * Server-side protocol handling for AllowEvents request.
194005b261ecSmrg *
19414642e01fSmrg * Release some events from a frozen device.
194205b261ecSmrg */
194305b261ecSmrgint
194405b261ecSmrgProcAllowEvents(ClientPtr client)
194505b261ecSmrg{
194635c4bbdfSmrg    TimeStamp time;
194735c4bbdfSmrg    DeviceIntPtr mouse = NULL;
194835c4bbdfSmrg    DeviceIntPtr keybd = NULL;
194935c4bbdfSmrg
195005b261ecSmrg    REQUEST(xAllowEventsReq);
195105b261ecSmrg
195205b261ecSmrg    REQUEST_SIZE_MATCH(xAllowEventsReq);
19537e31ba66Smrg    UpdateCurrentTime();
195405b261ecSmrg    time = ClientTimeToServerTime(stuff->time);
19554642e01fSmrg
19564642e01fSmrg    mouse = PickPointer(client);
19574642e01fSmrg    keybd = PickKeyboard(client);
19584642e01fSmrg
195935c4bbdfSmrg    switch (stuff->mode) {
196035c4bbdfSmrg    case ReplayPointer:
196135c4bbdfSmrg        AllowSome(client, time, mouse, NOT_GRABBED);
196235c4bbdfSmrg        break;
196335c4bbdfSmrg    case SyncPointer:
196435c4bbdfSmrg        AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
196535c4bbdfSmrg        break;
196635c4bbdfSmrg    case AsyncPointer:
196735c4bbdfSmrg        AllowSome(client, time, mouse, THAWED);
196835c4bbdfSmrg        break;
196935c4bbdfSmrg    case ReplayKeyboard:
197035c4bbdfSmrg        AllowSome(client, time, keybd, NOT_GRABBED);
197135c4bbdfSmrg        break;
197235c4bbdfSmrg    case SyncKeyboard:
197335c4bbdfSmrg        AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
197435c4bbdfSmrg        break;
197535c4bbdfSmrg    case AsyncKeyboard:
197635c4bbdfSmrg        AllowSome(client, time, keybd, THAWED);
197735c4bbdfSmrg        break;
197835c4bbdfSmrg    case SyncBoth:
197935c4bbdfSmrg        AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
198035c4bbdfSmrg        break;
198135c4bbdfSmrg    case AsyncBoth:
198235c4bbdfSmrg        AllowSome(client, time, keybd, THAWED_BOTH);
198335c4bbdfSmrg        break;
198435c4bbdfSmrg    default:
198535c4bbdfSmrg        client->errorValue = stuff->mode;
198635c4bbdfSmrg        return BadValue;
198705b261ecSmrg    }
198805b261ecSmrg    return Success;
198905b261ecSmrg}
199005b261ecSmrg
199105b261ecSmrg/**
199205b261ecSmrg * Deactivate grabs from any device that has been grabbed by the client.
199305b261ecSmrg */
199405b261ecSmrgvoid
199505b261ecSmrgReleaseActiveGrabs(ClientPtr client)
199605b261ecSmrg{
199705b261ecSmrg    DeviceIntPtr dev;
199835c4bbdfSmrg    Bool done;
199905b261ecSmrg
200005b261ecSmrg    /* XXX CloseDownClient should remove passive grabs before
200105b261ecSmrg     * releasing active grabs.
200205b261ecSmrg     */
200305b261ecSmrg    do {
200435c4bbdfSmrg        done = TRUE;
200535c4bbdfSmrg        for (dev = inputInfo.devices; dev; dev = dev->next) {
200635c4bbdfSmrg            if (dev->deviceGrab.grab &&
200735c4bbdfSmrg                SameClient(dev->deviceGrab.grab, client)) {
200835c4bbdfSmrg                (*dev->deviceGrab.DeactivateGrab) (dev);
200935c4bbdfSmrg                done = FALSE;
201035c4bbdfSmrg            }
201135c4bbdfSmrg        }
201205b261ecSmrg    } while (!done);
201305b261ecSmrg}
201405b261ecSmrg
201505b261ecSmrg/**************************************************************************
201605b261ecSmrg *            The following procedures deal with delivering events        *
201705b261ecSmrg **************************************************************************/
201805b261ecSmrg
201905b261ecSmrg/**
202005b261ecSmrg * Deliver the given events to the given client.
202105b261ecSmrg *
202205b261ecSmrg * More than one event may be delivered at a time. This is the case with
202305b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events.
202405b261ecSmrg *
202505b261ecSmrg * TryClientEvents() is the last station before actually writing the events to
202605b261ecSmrg * the socket. Anything that is not filtered here, will get delivered to the
20274642e01fSmrg * client.
20284642e01fSmrg * An event is only delivered if
202905b261ecSmrg *   - mask and filter match up.
203005b261ecSmrg *   - no other client has a grab on the device that caused the event.
20314642e01fSmrg *
203205b261ecSmrg *
203305b261ecSmrg * @param client The target client to deliver to.
20344642e01fSmrg * @param dev The device the event came from. May be NULL.
203505b261ecSmrg * @param pEvents The events to be delivered.
203605b261ecSmrg * @param count Number of elements in pEvents.
203705b261ecSmrg * @param mask Event mask as set by the window.
203805b261ecSmrg * @param filter Mask based on event type.
20394642e01fSmrg * @param grab Possible grab on the device that caused the event.
204005b261ecSmrg *
204105b261ecSmrg * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
204205b261ecSmrg * client.
204305b261ecSmrg */
20446747b715Smrgint
204535c4bbdfSmrgTryClientEvents(ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
204635c4bbdfSmrg                int count, Mask mask, Mask filter, GrabPtr grab)
204705b261ecSmrg{
204805b261ecSmrg    int type;
204905b261ecSmrg
205005b261ecSmrg#ifdef DEBUG_EVENTS
20516747b715Smrg    ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s",
20526747b715Smrg           pEvents->u.u.type, pEvents->u.u.detail, mask,
20536747b715Smrg           client ? client->index : -1,
20546747b715Smrg           (client && client->clientGone) ? " (gone)" : "");
205505b261ecSmrg#endif
20566747b715Smrg
20576747b715Smrg    if (!client || client == serverClient || client->clientGone) {
205805b261ecSmrg#ifdef DEBUG_EVENTS
20596747b715Smrg        ErrorF(" not delivered to fake/dead client\n");
206005b261ecSmrg#endif
20616747b715Smrg        return 0;
20626747b715Smrg    }
206305b261ecSmrg
206435c4bbdfSmrg    if (filter != CantBeFiltered && !(mask & filter)) {
206535c4bbdfSmrg#ifdef DEBUG_EVENTS
20666747b715Smrg        ErrorF(" filtered\n");
206735c4bbdfSmrg#endif
20686747b715Smrg        return 0;
20696747b715Smrg    }
207005b261ecSmrg
207135c4bbdfSmrg    if (grab && !SameClient(grab, client)) {
207205b261ecSmrg#ifdef DEBUG_EVENTS
20736747b715Smrg        ErrorF(" not delivered due to grab\n");
207405b261ecSmrg#endif
207535c4bbdfSmrg        return -1;              /* don't send, but notify caller */
207605b261ecSmrg    }
20776747b715Smrg
20786747b715Smrg    type = pEvents->u.u.type;
207935c4bbdfSmrg    if (type == MotionNotify) {
208035c4bbdfSmrg        if (mask & PointerMotionHintMask) {
20816747b715Smrg            if (WID(dev->valuator->motionHintWindow) ==
208235c4bbdfSmrg                pEvents->u.keyButtonPointer.event) {
208305b261ecSmrg#ifdef DEBUG_EVENTS
20846747b715Smrg                ErrorF("[dix] \n");
20856747b715Smrg                ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
208605b261ecSmrg#endif
208735c4bbdfSmrg                return 1;       /* don't send, but pretend we did */
20886747b715Smrg            }
20896747b715Smrg            pEvents->u.u.detail = NotifyHint;
20906747b715Smrg        }
209135c4bbdfSmrg        else {
20926747b715Smrg            pEvents->u.u.detail = NotifyNormal;
20936747b715Smrg        }
20946747b715Smrg    }
209535c4bbdfSmrg    else if (type == DeviceMotionNotify) {
209635c4bbdfSmrg        if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer *) pEvents,
20976747b715Smrg                                            mask) != 0)
20986747b715Smrg            return 1;
209935c4bbdfSmrg    }
210035c4bbdfSmrg    else if (type == KeyPress) {
210135c4bbdfSmrg        if (EventIsKeyRepeat(pEvents)) {
210235c4bbdfSmrg            if (!_XkbWantsDetectableAutoRepeat(client)) {
21036747b715Smrg                xEvent release = *pEvents;
210435c4bbdfSmrg
21056747b715Smrg                release.u.u.type = KeyRelease;
21066747b715Smrg                WriteEventsToClient(client, 1, &release);
21076747b715Smrg#ifdef DEBUG_EVENTS
21086747b715Smrg                ErrorF(" (plus fake core release for repeat)");
21096747b715Smrg#endif
211035c4bbdfSmrg            }
211135c4bbdfSmrg            else {
21126747b715Smrg#ifdef DEBUG_EVENTS
21136747b715Smrg                ErrorF(" (detectable autorepeat for core)");
21146747b715Smrg#endif
21156747b715Smrg            }
21166747b715Smrg        }
21176747b715Smrg
211835c4bbdfSmrg    }
211935c4bbdfSmrg    else if (type == DeviceKeyPress) {
212035c4bbdfSmrg        if (EventIsKeyRepeat(pEvents)) {
212135c4bbdfSmrg            if (!_XkbWantsDetectableAutoRepeat(client)) {
212235c4bbdfSmrg                deviceKeyButtonPointer release =
212335c4bbdfSmrg                    *(deviceKeyButtonPointer *) pEvents;
21246747b715Smrg                release.type = DeviceKeyRelease;
21256747b715Smrg#ifdef DEBUG_EVENTS
21266747b715Smrg                ErrorF(" (plus fake xi1 release for repeat)");
21276747b715Smrg#endif
21286747b715Smrg                WriteEventsToClient(client, 1, (xEvent *) &release);
21296747b715Smrg            }
21306747b715Smrg            else {
21316747b715Smrg#ifdef DEBUG_EVENTS
21326747b715Smrg                ErrorF(" (detectable autorepeat for core)");
21336747b715Smrg#endif
21346747b715Smrg            }
21356747b715Smrg        }
21366747b715Smrg    }
21376747b715Smrg
213835c4bbdfSmrg    if (BitIsOn(criticalEvents, type)) {
21396747b715Smrg        if (client->smart_priority < SMART_MAX_PRIORITY)
21406747b715Smrg            client->smart_priority++;
21416747b715Smrg        SetCriticalOutputPending();
214205b261ecSmrg    }
21436747b715Smrg
21446747b715Smrg    WriteEventsToClient(client, count, pEvents);
21456747b715Smrg#ifdef DEBUG_EVENTS
21466747b715Smrg    ErrorF("[dix]  delivered\n");
21476747b715Smrg#endif
21486747b715Smrg    return 1;
214905b261ecSmrg}
215005b261ecSmrg
215135c4bbdfSmrgstatic BOOL
215235c4bbdfSmrgActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win,
215335c4bbdfSmrg                     xEvent *event, Mask deliveryMask)
215435c4bbdfSmrg{
215535c4bbdfSmrg    GrabPtr tempGrab;
215635c4bbdfSmrg    OtherInputMasks *inputMasks;
215735c4bbdfSmrg    CARD8 type = event->u.u.type;
215835c4bbdfSmrg    enum InputLevel grabtype;
215935c4bbdfSmrg
216035c4bbdfSmrg    if (type == ButtonPress)
216135c4bbdfSmrg        grabtype = CORE;
216235c4bbdfSmrg    else if (type == DeviceButtonPress)
216335c4bbdfSmrg        grabtype = XI;
216435c4bbdfSmrg    else if ((type = xi2_get_type(event)) == XI_ButtonPress)
216535c4bbdfSmrg        grabtype = XI2;
216635c4bbdfSmrg    else
216735c4bbdfSmrg        return FALSE;
216835c4bbdfSmrg
216935c4bbdfSmrg    tempGrab = AllocGrab(NULL);
217035c4bbdfSmrg    if (!tempGrab)
217135c4bbdfSmrg        return FALSE;
217235c4bbdfSmrg    tempGrab->next = NULL;
217335c4bbdfSmrg    tempGrab->device = dev;
217435c4bbdfSmrg    tempGrab->resource = client->clientAsMask;
217535c4bbdfSmrg    tempGrab->window = win;
217635c4bbdfSmrg    tempGrab->ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
217735c4bbdfSmrg    tempGrab->eventMask = deliveryMask;
217835c4bbdfSmrg    tempGrab->keyboardMode = GrabModeAsync;
217935c4bbdfSmrg    tempGrab->pointerMode = GrabModeAsync;
218035c4bbdfSmrg    tempGrab->confineTo = NullWindow;
218135c4bbdfSmrg    tempGrab->cursor = NullCursor;
218235c4bbdfSmrg    tempGrab->type = type;
218335c4bbdfSmrg    tempGrab->grabtype = grabtype;
218435c4bbdfSmrg
218535c4bbdfSmrg    /* get the XI and XI2 device mask */
218635c4bbdfSmrg    inputMasks = wOtherInputMasks(win);
218735c4bbdfSmrg    tempGrab->deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id] : 0;
218835c4bbdfSmrg
218935c4bbdfSmrg    if (inputMasks)
219035c4bbdfSmrg        xi2mask_merge(tempGrab->xi2mask, inputMasks->xi2mask);
219135c4bbdfSmrg
219235c4bbdfSmrg    (*dev->deviceGrab.ActivateGrab) (dev, tempGrab,
219335c4bbdfSmrg                                     currentTime, TRUE | ImplicitGrabMask);
219435c4bbdfSmrg    FreeGrab(tempGrab);
219535c4bbdfSmrg    return TRUE;
219635c4bbdfSmrg}
219735c4bbdfSmrg
219835c4bbdfSmrg/**
219935c4bbdfSmrg * Attempt event delivery to the client owning the window.
220035c4bbdfSmrg */
220135c4bbdfSmrgstatic enum EventDeliveryState
220235c4bbdfSmrgDeliverToWindowOwner(DeviceIntPtr dev, WindowPtr win,
220335c4bbdfSmrg                     xEvent *events, int count, Mask filter, GrabPtr grab)
220435c4bbdfSmrg{
220535c4bbdfSmrg    /* if nobody ever wants to see this event, skip some work */
220635c4bbdfSmrg    if (filter != CantBeFiltered &&
220735c4bbdfSmrg        !((wOtherEventMasks(win) | win->eventMask) & filter))
220835c4bbdfSmrg        return EVENT_SKIP;
220935c4bbdfSmrg
221035c4bbdfSmrg    if (IsInterferingGrab(wClient(win), dev, events))
221135c4bbdfSmrg        return EVENT_SKIP;
221235c4bbdfSmrg
221335c4bbdfSmrg    if (!XaceHook(XACE_RECEIVE_ACCESS, wClient(win), win, events, count)) {
221435c4bbdfSmrg        int attempt = TryClientEvents(wClient(win), dev, events,
221535c4bbdfSmrg                                      count, win->eventMask,
221635c4bbdfSmrg                                      filter, grab);
221735c4bbdfSmrg
221835c4bbdfSmrg        if (attempt > 0)
221935c4bbdfSmrg            return EVENT_DELIVERED;
222035c4bbdfSmrg        if (attempt < 0)
222135c4bbdfSmrg            return EVENT_REJECTED;
222235c4bbdfSmrg    }
222335c4bbdfSmrg
222435c4bbdfSmrg    return EVENT_NOT_DELIVERED;
222535c4bbdfSmrg}
222635c4bbdfSmrg
222735c4bbdfSmrg/**
222835c4bbdfSmrg * Get the list of clients that should be tried for event delivery on the
222935c4bbdfSmrg * given window.
223035c4bbdfSmrg *
223135c4bbdfSmrg * @return 1 if the client list should be traversed, zero if the event
223235c4bbdfSmrg * should be skipped.
223335c4bbdfSmrg */
223435c4bbdfSmrgstatic Bool
223535c4bbdfSmrgGetClientsForDelivery(DeviceIntPtr dev, WindowPtr win,
223635c4bbdfSmrg                      xEvent *events, Mask filter, InputClients ** iclients)
223735c4bbdfSmrg{
223835c4bbdfSmrg    int rc = 0;
223935c4bbdfSmrg
224035c4bbdfSmrg    if (core_get_type(events) != 0)
224135c4bbdfSmrg        *iclients = (InputClients *) wOtherClients(win);
224235c4bbdfSmrg    else if (xi2_get_type(events) != 0) {
224335c4bbdfSmrg        OtherInputMasks *inputMasks = wOtherInputMasks(win);
224435c4bbdfSmrg
224535c4bbdfSmrg        /* Has any client selected for the event? */
224635c4bbdfSmrg        if (!WindowXI2MaskIsset(dev, win, events))
224735c4bbdfSmrg            goto out;
224835c4bbdfSmrg        *iclients = inputMasks->inputClients;
224935c4bbdfSmrg    }
225035c4bbdfSmrg    else {
225135c4bbdfSmrg        OtherInputMasks *inputMasks = wOtherInputMasks(win);
225235c4bbdfSmrg
225335c4bbdfSmrg        /* Has any client selected for the event? */
225435c4bbdfSmrg        if (!inputMasks || !(inputMasks->inputEvents[dev->id] & filter))
225535c4bbdfSmrg            goto out;
225635c4bbdfSmrg
225735c4bbdfSmrg        *iclients = inputMasks->inputClients;
225835c4bbdfSmrg    }
225935c4bbdfSmrg
226035c4bbdfSmrg    rc = 1;
226135c4bbdfSmrg out:
226235c4bbdfSmrg    return rc;
226335c4bbdfSmrg}
226435c4bbdfSmrg
226535c4bbdfSmrg/**
226635c4bbdfSmrg * Try delivery on each client in inputclients, provided the event mask
226735c4bbdfSmrg * accepts it and there is no interfering core grab..
226835c4bbdfSmrg */
226935c4bbdfSmrgstatic enum EventDeliveryState
227035c4bbdfSmrgDeliverEventToInputClients(DeviceIntPtr dev, InputClients * inputclients,
227135c4bbdfSmrg                           WindowPtr win, xEvent *events,
227235c4bbdfSmrg                           int count, Mask filter, GrabPtr grab,
227335c4bbdfSmrg                           ClientPtr *client_return, Mask *mask_return)
227435c4bbdfSmrg{
227535c4bbdfSmrg    int attempt;
227635c4bbdfSmrg    enum EventDeliveryState rc = EVENT_NOT_DELIVERED;
227735c4bbdfSmrg    Bool have_device_button_grab_class_client = FALSE;
227835c4bbdfSmrg
227935c4bbdfSmrg    for (; inputclients; inputclients = inputclients->next) {
228035c4bbdfSmrg        Mask mask;
228135c4bbdfSmrg        ClientPtr client = rClient(inputclients);
228235c4bbdfSmrg
228335c4bbdfSmrg        if (IsInterferingGrab(client, dev, events))
228435c4bbdfSmrg            continue;
228535c4bbdfSmrg
228635c4bbdfSmrg        if (IsWrongPointerBarrierClient(client, dev, events))
228735c4bbdfSmrg            continue;
228835c4bbdfSmrg
228935c4bbdfSmrg        mask = GetEventMask(dev, events, inputclients);
229035c4bbdfSmrg
229135c4bbdfSmrg        if (XaceHook(XACE_RECEIVE_ACCESS, client, win, events, count))
229235c4bbdfSmrg            /* do nothing */ ;
229335c4bbdfSmrg        else if ((attempt = TryClientEvents(client, dev,
229435c4bbdfSmrg                                            events, count,
229535c4bbdfSmrg                                            mask, filter, grab))) {
229635c4bbdfSmrg            if (attempt > 0) {
229735c4bbdfSmrg                /*
229835c4bbdfSmrg                 * The order of clients is arbitrary therefore if one
229935c4bbdfSmrg                 * client belongs to DeviceButtonGrabClass make sure to
230035c4bbdfSmrg                 * catch it.
230135c4bbdfSmrg                 */
230235c4bbdfSmrg                if (!have_device_button_grab_class_client) {
230335c4bbdfSmrg                    rc = EVENT_DELIVERED;
230435c4bbdfSmrg                    *client_return = client;
230535c4bbdfSmrg                    *mask_return = mask;
230635c4bbdfSmrg                    /* Success overrides non-success, so if we've been
230735c4bbdfSmrg                     * successful on one client, return that */
230835c4bbdfSmrg                    if (mask & DeviceButtonGrabMask)
230935c4bbdfSmrg                        have_device_button_grab_class_client = TRUE;
231035c4bbdfSmrg                }
231135c4bbdfSmrg            } else if (rc == EVENT_NOT_DELIVERED)
231235c4bbdfSmrg                rc = EVENT_REJECTED;
231335c4bbdfSmrg        }
231435c4bbdfSmrg    }
231535c4bbdfSmrg
231635c4bbdfSmrg    return rc;
231735c4bbdfSmrg}
231835c4bbdfSmrg
231935c4bbdfSmrg/**
232035c4bbdfSmrg * Deliver events to clients registered on the window.
232135c4bbdfSmrg *
232235c4bbdfSmrg * @param client_return On successful delivery, set to the recipient.
232335c4bbdfSmrg * @param mask_return On successful delivery, set to the recipient's event
232435c4bbdfSmrg * mask for this event.
232535c4bbdfSmrg */
232635c4bbdfSmrgstatic enum EventDeliveryState
232735c4bbdfSmrgDeliverEventToWindowMask(DeviceIntPtr dev, WindowPtr win, xEvent *events,
232835c4bbdfSmrg                         int count, Mask filter, GrabPtr grab,
232935c4bbdfSmrg                         ClientPtr *client_return, Mask *mask_return)
233035c4bbdfSmrg{
233135c4bbdfSmrg    InputClients *iclients;
233235c4bbdfSmrg
233335c4bbdfSmrg    if (!GetClientsForDelivery(dev, win, events, filter, &iclients))
233435c4bbdfSmrg        return EVENT_SKIP;
233535c4bbdfSmrg
233635c4bbdfSmrg    return DeliverEventToInputClients(dev, iclients, win, events, count, filter,
233735c4bbdfSmrg                                      grab, client_return, mask_return);
233835c4bbdfSmrg
233935c4bbdfSmrg}
234035c4bbdfSmrg
234105b261ecSmrg/**
234205b261ecSmrg * Deliver events to a window. At this point, we do not yet know if the event
234305b261ecSmrg * actually needs to be delivered. May activate a grab if the event is a
234405b261ecSmrg * button press.
234505b261ecSmrg *
23464642e01fSmrg * Core events are always delivered to the window owner. If the filter is
23474642e01fSmrg * something other than CantBeFiltered, the event is also delivered to other
23484642e01fSmrg * clients with the matching mask on the window.
23494642e01fSmrg *
235005b261ecSmrg * More than one event may be delivered at a time. This is the case with
235105b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events.
23524642e01fSmrg *
235305b261ecSmrg * @param pWin The window that would get the event.
235405b261ecSmrg * @param pEvents The events to be delivered.
235505b261ecSmrg * @param count Number of elements in pEvents.
235605b261ecSmrg * @param filter Mask based on event type.
23574642e01fSmrg * @param grab Possible grab on the device that caused the event.
235805b261ecSmrg *
235935c4bbdfSmrg * @return a positive number if at least one successful delivery has been
236035c4bbdfSmrg * made, 0 if no events were delivered, or a negative number if the event
236135c4bbdfSmrg * has not been delivered _and_ rejected by at least one client.
236205b261ecSmrg */
236305b261ecSmrgint
23644642e01fSmrgDeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
236535c4bbdfSmrg                      *pEvents, int count, Mask filter, GrabPtr grab)
236605b261ecSmrg{
236705b261ecSmrg    int deliveries = 0, nondeliveries = 0;
236805b261ecSmrg    ClientPtr client = NullClient;
236935c4bbdfSmrg    Mask deliveryMask = 0;      /* If a grab occurs due to a button press, then
237035c4bbdfSmrg                                   this mask is the mask of the grab. */
237105b261ecSmrg    int type = pEvents->u.u.type;
237205b261ecSmrg
23736747b715Smrg    /* Deliver to window owner */
237435c4bbdfSmrg    if ((filter == CantBeFiltered) || core_get_type(pEvents) != 0) {
237535c4bbdfSmrg        enum EventDeliveryState rc;
23764642e01fSmrg
237735c4bbdfSmrg        rc = DeliverToWindowOwner(pDev, pWin, pEvents, count, filter, grab);
23784642e01fSmrg
237935c4bbdfSmrg        switch (rc) {
238035c4bbdfSmrg        case EVENT_SKIP:
238135c4bbdfSmrg            return 0;
238235c4bbdfSmrg        case EVENT_REJECTED:
238335c4bbdfSmrg            nondeliveries--;
238435c4bbdfSmrg            break;
238535c4bbdfSmrg        case EVENT_DELIVERED:
238635c4bbdfSmrg            /* We delivered to the owner, with our event mask */
238735c4bbdfSmrg            deliveries++;
238835c4bbdfSmrg            client = wClient(pWin);
238935c4bbdfSmrg            deliveryMask = pWin->eventMask;
239035c4bbdfSmrg            break;
239135c4bbdfSmrg        case EVENT_NOT_DELIVERED:
239235c4bbdfSmrg            break;
239335c4bbdfSmrg        }
239405b261ecSmrg    }
23956747b715Smrg
23966747b715Smrg    /* CantBeFiltered means only window owner gets the event */
239735c4bbdfSmrg    if (filter != CantBeFiltered) {
239835c4bbdfSmrg        enum EventDeliveryState rc;
239935c4bbdfSmrg
240035c4bbdfSmrg        rc = DeliverEventToWindowMask(pDev, pWin, pEvents, count, filter,
240135c4bbdfSmrg                                      grab, &client, &deliveryMask);
24024642e01fSmrg
240335c4bbdfSmrg        switch (rc) {
240435c4bbdfSmrg        case EVENT_SKIP:
240535c4bbdfSmrg            return 0;
240635c4bbdfSmrg        case EVENT_REJECTED:
240735c4bbdfSmrg            nondeliveries--;
240835c4bbdfSmrg            break;
240935c4bbdfSmrg        case EVENT_DELIVERED:
241035c4bbdfSmrg            deliveries++;
241135c4bbdfSmrg            break;
241235c4bbdfSmrg        case EVENT_NOT_DELIVERED:
241335c4bbdfSmrg            break;
24144642e01fSmrg        }
241535c4bbdfSmrg    }
24164642e01fSmrg
241735c4bbdfSmrg    if (deliveries) {
241835c4bbdfSmrg        /*
241935c4bbdfSmrg         * Note that since core events are delivered first, an implicit grab may
242035c4bbdfSmrg         * be activated on a core grab, stopping the XI events.
242135c4bbdfSmrg         */
242235c4bbdfSmrg        if (!grab &&
242335c4bbdfSmrg            ActivateImplicitGrab(pDev, client, pWin, pEvents, deliveryMask))
242435c4bbdfSmrg            /* grab activated */ ;
242535c4bbdfSmrg        else if (type == MotionNotify)
242635c4bbdfSmrg            pDev->valuator->motionHintWindow = pWin;
242735c4bbdfSmrg        else if (type == DeviceMotionNotify || type == DeviceButtonPress)
242835c4bbdfSmrg            CheckDeviceGrabAndHintWindow(pWin, type,
242935c4bbdfSmrg                                         (deviceKeyButtonPointer *) pEvents,
243035c4bbdfSmrg                                         grab, client, deliveryMask);
243135c4bbdfSmrg        return deliveries;
243235c4bbdfSmrg    }
243335c4bbdfSmrg    return nondeliveries;
243435c4bbdfSmrg}
243535c4bbdfSmrg
243635c4bbdfSmrg/**
243735c4bbdfSmrg * Filter out raw events for XI 2.0 and XI 2.1 clients.
243835c4bbdfSmrg *
243935c4bbdfSmrg * If there is a grab on the device, 2.0 clients only get raw events if they
244035c4bbdfSmrg * have the grab. 2.1+ clients get raw events in all cases.
244135c4bbdfSmrg *
244235c4bbdfSmrg * @return TRUE if the event should be discarded, FALSE otherwise.
244335c4bbdfSmrg */
244435c4bbdfSmrgstatic BOOL
244535c4bbdfSmrgFilterRawEvents(const ClientPtr client, const GrabPtr grab, WindowPtr root)
244635c4bbdfSmrg{
244735c4bbdfSmrg    XIClientPtr client_xi_version;
244835c4bbdfSmrg    int cmp;
24496747b715Smrg
245035c4bbdfSmrg    /* device not grabbed -> don't filter */
245135c4bbdfSmrg    if (!grab)
245235c4bbdfSmrg        return FALSE;
24536747b715Smrg
245435c4bbdfSmrg    client_xi_version =
245535c4bbdfSmrg        dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
245635c4bbdfSmrg
245735c4bbdfSmrg    cmp = version_compare(client_xi_version->major_version,
245835c4bbdfSmrg                          client_xi_version->minor_version, 2, 0);
245935c4bbdfSmrg    /* XI 2.0: if device is grabbed, skip
246035c4bbdfSmrg       XI 2.1: if device is grabbed by us, skip, we've already delivered */
246135c4bbdfSmrg    if (cmp == 0)
246235c4bbdfSmrg        return TRUE;
246335c4bbdfSmrg
246435c4bbdfSmrg    return (grab->window != root) ? FALSE : SameClient(grab, client);
246535c4bbdfSmrg}
246635c4bbdfSmrg
246735c4bbdfSmrg/**
246835c4bbdfSmrg * Deliver a raw event to the grab owner (if any) and to all root windows.
246935c4bbdfSmrg *
247035c4bbdfSmrg * Raw event delivery differs between XI 2.0 and XI 2.1.
247135c4bbdfSmrg * XI 2.0: events delivered to the grabbing client (if any) OR to all root
247235c4bbdfSmrg * windows
247335c4bbdfSmrg * XI 2.1: events delivered to all root windows, regardless of grabbing
247435c4bbdfSmrg * state.
247535c4bbdfSmrg */
247635c4bbdfSmrgvoid
247735c4bbdfSmrgDeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
247835c4bbdfSmrg{
247935c4bbdfSmrg    GrabPtr grab = device->deviceGrab.grab;
248035c4bbdfSmrg    xEvent *xi;
248135c4bbdfSmrg    int i, rc;
248235c4bbdfSmrg    int filter;
248335c4bbdfSmrg
248435c4bbdfSmrg    rc = EventToXI2((InternalEvent *) ev, (xEvent **) &xi);
248535c4bbdfSmrg    if (rc != Success) {
248635c4bbdfSmrg        ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n",
248735c4bbdfSmrg               __func__, device->name, rc);
248835c4bbdfSmrg        return;
248905b261ecSmrg    }
24904642e01fSmrg
249135c4bbdfSmrg    if (grab)
249235c4bbdfSmrg        DeliverGrabbedEvent((InternalEvent *) ev, device, FALSE);
249335c4bbdfSmrg
249435c4bbdfSmrg    filter = GetEventFilter(device, xi);
249535c4bbdfSmrg
249635c4bbdfSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
249735c4bbdfSmrg        WindowPtr root;
249835c4bbdfSmrg        InputClients *inputclients;
249935c4bbdfSmrg
250035c4bbdfSmrg        root = screenInfo.screens[i]->root;
250135c4bbdfSmrg        if (!GetClientsForDelivery(device, root, xi, filter, &inputclients))
250235c4bbdfSmrg            continue;
250335c4bbdfSmrg
250435c4bbdfSmrg        for (; inputclients; inputclients = inputclients->next) {
250535c4bbdfSmrg            ClientPtr c;        /* unused */
250635c4bbdfSmrg            Mask m;             /* unused */
250735c4bbdfSmrg            InputClients ic = *inputclients;
25084642e01fSmrg
250935c4bbdfSmrg            /* Because we run through the list manually, copy the actual
251035c4bbdfSmrg             * list, shorten the copy to only have one client and then pass
251135c4bbdfSmrg             * that down to DeliverEventToInputClients. This way we avoid
251235c4bbdfSmrg             * double events on XI 2.1 clients that have a grab on the
251335c4bbdfSmrg             * device.
251435c4bbdfSmrg             */
251535c4bbdfSmrg            ic.next = NULL;
25166747b715Smrg
251735c4bbdfSmrg            if (!FilterRawEvents(rClient(&ic), grab, root))
251835c4bbdfSmrg                DeliverEventToInputClients(device, &ic, root, xi, 1,
251935c4bbdfSmrg                                           filter, NULL, &c, &m);
252035c4bbdfSmrg        }
252105b261ecSmrg    }
252235c4bbdfSmrg
252335c4bbdfSmrg    free(xi);
252405b261ecSmrg}
252505b261ecSmrg
252605b261ecSmrg/* If the event goes to dontClient, don't send it and return 0.  if
252705b261ecSmrg   send works,  return 1 or if send didn't work, return 2.
252805b261ecSmrg   Only works for core events.
252905b261ecSmrg*/
253005b261ecSmrg
253105b261ecSmrg#ifdef PANORAMIX
25324642e01fSmrgstatic int
253335c4bbdfSmrgXineramaTryClientEventsResult(ClientPtr client,
253435c4bbdfSmrg                              GrabPtr grab, Mask mask, Mask filter)
253535c4bbdfSmrg{
253605b261ecSmrg    if ((client) && (client != serverClient) && (!client->clientGone) &&
253735c4bbdfSmrg        ((filter == CantBeFiltered) || (mask & filter))) {
253835c4bbdfSmrg        if (grab && !SameClient(grab, client))
253935c4bbdfSmrg            return -1;
254035c4bbdfSmrg        else
254135c4bbdfSmrg            return 1;
254205b261ecSmrg    }
254305b261ecSmrg    return 0;
254405b261ecSmrg}
254505b261ecSmrg#endif
254605b261ecSmrg
254705b261ecSmrg/**
254805b261ecSmrg * Try to deliver events to the interested parties.
254905b261ecSmrg *
255005b261ecSmrg * @param pWin The window that would get the event.
255105b261ecSmrg * @param pEvents The events to be delivered.
255205b261ecSmrg * @param count Number of elements in pEvents.
255305b261ecSmrg * @param filter Mask based on event type.
255405b261ecSmrg * @param dontClient Don't deliver to the dontClient.
255505b261ecSmrg */
255605b261ecSmrgint
25574642e01fSmrgMaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
255805b261ecSmrg                           int count, Mask filter, ClientPtr dontClient)
255905b261ecSmrg{
256005b261ecSmrg    OtherClients *other;
256105b261ecSmrg
256235c4bbdfSmrg    if (pWin->eventMask & filter) {
256305b261ecSmrg        if (wClient(pWin) == dontClient)
256435c4bbdfSmrg            return 0;
256505b261ecSmrg#ifdef PANORAMIX
256635c4bbdfSmrg        if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
256735c4bbdfSmrg            return XineramaTryClientEventsResult(wClient(pWin), NullGrab,
256835c4bbdfSmrg                                                 pWin->eventMask, filter);
256905b261ecSmrg#endif
257035c4bbdfSmrg        if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
257135c4bbdfSmrg            return 1;           /* don't send, but pretend we did */
257235c4bbdfSmrg        return TryClientEvents(wClient(pWin), NULL, pEvents, count,
257335c4bbdfSmrg                               pWin->eventMask, filter, NullGrab);
257405b261ecSmrg    }
257535c4bbdfSmrg    for (other = wOtherClients(pWin); other; other = other->next) {
257635c4bbdfSmrg        if (other->mask & filter) {
257705b261ecSmrg            if (SameClient(other, dontClient))
257835c4bbdfSmrg                return 0;
257905b261ecSmrg#ifdef PANORAMIX
258035c4bbdfSmrg            if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
258135c4bbdfSmrg                return XineramaTryClientEventsResult(rClient(other), NullGrab,
258235c4bbdfSmrg                                                     other->mask, filter);
258305b261ecSmrg#endif
258435c4bbdfSmrg            if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents,
258535c4bbdfSmrg                         count))
258635c4bbdfSmrg                return 1;       /* don't send, but pretend we did */
258735c4bbdfSmrg            return TryClientEvents(rClient(other), NULL, pEvents, count,
258835c4bbdfSmrg                                   other->mask, filter, NullGrab);
258935c4bbdfSmrg        }
259005b261ecSmrg    }
259105b261ecSmrg    return 2;
259205b261ecSmrg}
259305b261ecSmrg
259435c4bbdfSmrgstatic Window
259535c4bbdfSmrgFindChildForEvent(SpritePtr pSprite, WindowPtr event)
25966747b715Smrg{
259735c4bbdfSmrg    WindowPtr w = DeepestSpriteWin(pSprite);
25986747b715Smrg    Window child = None;
25996747b715Smrg
26006747b715Smrg    /* If the search ends up past the root should the child field be
26016747b715Smrg       set to none or should the value in the argument be passed
26026747b715Smrg       through. It probably doesn't matter since everyone calls
26036747b715Smrg       this function with child == None anyway. */
260435c4bbdfSmrg    while (w) {
26056747b715Smrg        /* If the source window is same as event window, child should be
26066747b715Smrg           none.  Don't bother going all all the way back to the root. */
26076747b715Smrg
260835c4bbdfSmrg        if (w == event) {
26096747b715Smrg            child = None;
26106747b715Smrg            break;
26116747b715Smrg        }
26126747b715Smrg
261335c4bbdfSmrg        if (w->parent == event) {
26146747b715Smrg            child = w->drawable.id;
26156747b715Smrg            break;
26166747b715Smrg        }
26176747b715Smrg        w = w->parent;
26186747b715Smrg    }
26196747b715Smrg    return child;
26206747b715Smrg}
26216747b715Smrg
26225a112b11Smrgstatic void
26235a112b11SmrgFixUpXI2DeviceEventFromWindow(SpritePtr pSprite, int evtype,
26245a112b11Smrg                              xXIDeviceEvent *event, WindowPtr pWin, Window child)
26255a112b11Smrg{
26265a112b11Smrg    event->root = RootWindow(pSprite)->drawable.id;
26275a112b11Smrg    event->event = pWin->drawable.id;
26285a112b11Smrg
26295a112b11Smrg    if (evtype == XI_TouchOwnership) {
26305a112b11Smrg        event->child = child;
26315a112b11Smrg        return;
26325a112b11Smrg    }
26335a112b11Smrg
26345a112b11Smrg    if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
26355a112b11Smrg        event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x);
26365a112b11Smrg        event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y);
26375a112b11Smrg        event->child = child;
26385a112b11Smrg    }
26395a112b11Smrg    else {
26405a112b11Smrg        event->event_x = 0;
26415a112b11Smrg        event->event_y = 0;
26425a112b11Smrg        event->child = None;
26435a112b11Smrg    }
26445a112b11Smrg
26455a112b11Smrg    if (event->evtype == XI_Enter || event->evtype == XI_Leave ||
26465a112b11Smrg        event->evtype == XI_FocusIn || event->evtype == XI_FocusOut)
26475a112b11Smrg        ((xXIEnterEvent *) event)->same_screen =
26485a112b11Smrg            (pSprite->hot.pScreen == pWin->drawable.pScreen);
26495a112b11Smrg}
26505a112b11Smrg
26515a112b11Smrgstatic void
26525a112b11SmrgFixUpXI2PinchEventFromWindow(SpritePtr pSprite, xXIGesturePinchEvent *event,
26535a112b11Smrg                             WindowPtr pWin, Window child)
26545a112b11Smrg{
26555a112b11Smrg    event->root = RootWindow(pSprite)->drawable.id;
26565a112b11Smrg    event->event = pWin->drawable.id;
26575a112b11Smrg
26585a112b11Smrg    if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
26595a112b11Smrg        event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x);
26605a112b11Smrg        event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y);
26615a112b11Smrg        event->child = child;
26625a112b11Smrg    }
26635a112b11Smrg    else {
26645a112b11Smrg        event->event_x = 0;
26655a112b11Smrg        event->event_y = 0;
26665a112b11Smrg        event->child = None;
26675a112b11Smrg    }
26685a112b11Smrg}
26695a112b11Smrg
26705a112b11Smrgstatic void
26715a112b11SmrgFixUpXI2SwipeEventFromWindow(SpritePtr pSprite, xXIGestureSwipeEvent *event,
26725a112b11Smrg                             WindowPtr pWin, Window child)
26735a112b11Smrg{
26745a112b11Smrg    event->root = RootWindow(pSprite)->drawable.id;
26755a112b11Smrg    event->event = pWin->drawable.id;
26765a112b11Smrg
26775a112b11Smrg    if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
26785a112b11Smrg        event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x);
26795a112b11Smrg        event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y);
26805a112b11Smrg        event->child = child;
26815a112b11Smrg    }
26825a112b11Smrg    else {
26835a112b11Smrg        event->event_x = 0;
26845a112b11Smrg        event->event_y = 0;
26855a112b11Smrg        event->child = None;
26865a112b11Smrg    }
26875a112b11Smrg}
26885a112b11Smrg
268905b261ecSmrg/**
269005b261ecSmrg * Adjust event fields to comply with the window properties.
269105b261ecSmrg *
269205b261ecSmrg * @param xE Event to be modified in place
269305b261ecSmrg * @param pWin The window to get the information from.
269405b261ecSmrg * @param child Child window setting for event (if applicable)
269505b261ecSmrg * @param calcChild If True, calculate the child window.
269605b261ecSmrg */
26976747b715Smrgvoid
269835c4bbdfSmrgFixUpEventFromWindow(SpritePtr pSprite,
269935c4bbdfSmrg                     xEvent *xE, WindowPtr pWin, Window child, Bool calcChild)
270005b261ecSmrg{
270135c4bbdfSmrg    int evtype;
270235c4bbdfSmrg
270305b261ecSmrg    if (calcChild)
27049ace9065Smrg        child = FindChildForEvent(pSprite, pWin);
27056747b715Smrg
270635c4bbdfSmrg    if ((evtype = xi2_get_type(xE))) {
270735c4bbdfSmrg        switch (evtype) {
270835c4bbdfSmrg        case XI_RawKeyPress:
270935c4bbdfSmrg        case XI_RawKeyRelease:
271035c4bbdfSmrg        case XI_RawButtonPress:
271135c4bbdfSmrg        case XI_RawButtonRelease:
271235c4bbdfSmrg        case XI_RawMotion:
271335c4bbdfSmrg        case XI_RawTouchBegin:
271435c4bbdfSmrg        case XI_RawTouchUpdate:
271535c4bbdfSmrg        case XI_RawTouchEnd:
271635c4bbdfSmrg        case XI_DeviceChanged:
271735c4bbdfSmrg        case XI_HierarchyChanged:
271835c4bbdfSmrg        case XI_PropertyEvent:
271935c4bbdfSmrg        case XI_BarrierHit:
272035c4bbdfSmrg        case XI_BarrierLeave:
27216747b715Smrg            return;
27225a112b11Smrg        case XI_GesturePinchBegin:
27235a112b11Smrg        case XI_GesturePinchUpdate:
27245a112b11Smrg        case XI_GesturePinchEnd:
27255a112b11Smrg            FixUpXI2PinchEventFromWindow(pSprite,
27265a112b11Smrg                                         (xXIGesturePinchEvent*) xE, pWin, child);
27275a112b11Smrg            break;
27285a112b11Smrg        case XI_GestureSwipeBegin:
27295a112b11Smrg        case XI_GestureSwipeUpdate:
27305a112b11Smrg        case XI_GestureSwipeEnd:
27315a112b11Smrg            FixUpXI2SwipeEventFromWindow(pSprite,
27325a112b11Smrg                                         (xXIGestureSwipeEvent*) xE, pWin, child);
27335a112b11Smrg            break;
273435c4bbdfSmrg        default:
27355a112b11Smrg            FixUpXI2DeviceEventFromWindow(pSprite, evtype,
27365a112b11Smrg                                          (xXIDeviceEvent*) xE, pWin, child);
273735c4bbdfSmrg            break;
273835c4bbdfSmrg        }
273935c4bbdfSmrg    }
274035c4bbdfSmrg    else {
27419ace9065Smrg        XE_KBPTR.root = RootWindow(pSprite)->drawable.id;
27426747b715Smrg        XE_KBPTR.event = pWin->drawable.id;
274335c4bbdfSmrg        if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
27446747b715Smrg            XE_KBPTR.sameScreen = xTrue;
27456747b715Smrg            XE_KBPTR.child = child;
274635c4bbdfSmrg            XE_KBPTR.eventX = XE_KBPTR.rootX - pWin->drawable.x;
274735c4bbdfSmrg            XE_KBPTR.eventY = XE_KBPTR.rootY - pWin->drawable.y;
27486747b715Smrg        }
274935c4bbdfSmrg        else {
27506747b715Smrg            XE_KBPTR.sameScreen = xFalse;
27516747b715Smrg            XE_KBPTR.child = None;
27526747b715Smrg            XE_KBPTR.eventX = 0;
27536747b715Smrg            XE_KBPTR.eventY = 0;
27546747b715Smrg        }
275505b261ecSmrg    }
275605b261ecSmrg}
275705b261ecSmrg
27586747b715Smrg/**
27596747b715Smrg * Check if a given event is deliverable at all on a given window.
27606747b715Smrg *
27616747b715Smrg * This function only checks if any client wants it, not for a specific
27626747b715Smrg * client.
27636747b715Smrg *
27646747b715Smrg * @param[in] dev The device this event is being sent for.
276535c4bbdfSmrg * @param[in] evtype The event type of the event that is to be sent.
27666747b715Smrg * @param[in] win The current event window.
27676747b715Smrg *
276835c4bbdfSmrg * @return Bitmask of ::EVENT_XI2_MASK, ::EVENT_XI1_MASK, ::EVENT_CORE_MASK, and
276935c4bbdfSmrg *         ::EVENT_DONT_PROPAGATE_MASK.
27706747b715Smrg */
27719ace9065Smrgint
277235c4bbdfSmrgEventIsDeliverable(DeviceIntPtr dev, int evtype, WindowPtr win)
27736747b715Smrg{
27746747b715Smrg    int rc = 0;
27756747b715Smrg    int filter = 0;
27766747b715Smrg    int type;
27776747b715Smrg    OtherInputMasks *inputMasks = wOtherInputMasks(win);
277835c4bbdfSmrg
277935c4bbdfSmrg    if ((type = GetXI2Type(evtype)) != 0) {
278035c4bbdfSmrg        if (inputMasks && xi2mask_isset(inputMasks->xi2mask, dev, type))
278135c4bbdfSmrg            rc |= EVENT_XI2_MASK;
278235c4bbdfSmrg    }
278335c4bbdfSmrg
278435c4bbdfSmrg    if ((type = GetXIType(evtype)) != 0) {
278535c4bbdfSmrg        filter = event_get_filter_from_type(dev, type);
278635c4bbdfSmrg
278735c4bbdfSmrg        /* Check for XI mask */
278835c4bbdfSmrg        if (inputMasks &&
278935c4bbdfSmrg            (inputMasks->deliverableEvents[dev->id] & filter) &&
279035c4bbdfSmrg            (inputMasks->inputEvents[dev->id] & filter))
279135c4bbdfSmrg            rc |= EVENT_XI1_MASK;
279235c4bbdfSmrg
279335c4bbdfSmrg        /* Check for XI DontPropagate mask */
279435c4bbdfSmrg        if (inputMasks && (inputMasks->dontPropagateMask[dev->id] & filter))
279535c4bbdfSmrg            rc |= EVENT_DONT_PROPAGATE_MASK;
279635c4bbdfSmrg
279735c4bbdfSmrg    }
279835c4bbdfSmrg
279935c4bbdfSmrg    if ((type = GetCoreType(evtype)) != 0) {
280035c4bbdfSmrg        filter = event_get_filter_from_type(dev, type);
280135c4bbdfSmrg
280235c4bbdfSmrg        /* Check for core mask */
280335c4bbdfSmrg        if ((win->deliverableEvents & filter) &&
280435c4bbdfSmrg            ((wOtherEventMasks(win) | win->eventMask) & filter))
280535c4bbdfSmrg            rc |= EVENT_CORE_MASK;
280635c4bbdfSmrg
280735c4bbdfSmrg        /* Check for core DontPropagate mask */
280835c4bbdfSmrg        if (filter & wDontPropagateMask(win))
280935c4bbdfSmrg            rc |= EVENT_DONT_PROPAGATE_MASK;
281035c4bbdfSmrg    }
28116747b715Smrg
28126747b715Smrg    return rc;
28136747b715Smrg}
28146747b715Smrg
281535c4bbdfSmrgstatic int
281635c4bbdfSmrgDeliverEvent(DeviceIntPtr dev, xEvent *xE, int count,
281735c4bbdfSmrg             WindowPtr win, Window child, GrabPtr grab)
281835c4bbdfSmrg{
281935c4bbdfSmrg    SpritePtr pSprite = dev->spriteInfo->sprite;
282035c4bbdfSmrg    Mask filter;
282135c4bbdfSmrg    int deliveries = 0;
282235c4bbdfSmrg
282335c4bbdfSmrg    if (XaceHook(XACE_SEND_ACCESS, NULL, dev, win, xE, count) == Success) {
282435c4bbdfSmrg        filter = GetEventFilter(dev, xE);
282535c4bbdfSmrg        FixUpEventFromWindow(pSprite, xE, win, child, FALSE);
282635c4bbdfSmrg        deliveries = DeliverEventsToWindow(dev, win, xE, count, filter, grab);
282735c4bbdfSmrg    }
282835c4bbdfSmrg
282935c4bbdfSmrg    return deliveries;
283035c4bbdfSmrg}
283135c4bbdfSmrg
283235c4bbdfSmrgstatic int
283335c4bbdfSmrgDeliverOneEvent(InternalEvent *event, DeviceIntPtr dev, enum InputLevel level,
283435c4bbdfSmrg                WindowPtr win, Window child, GrabPtr grab)
283535c4bbdfSmrg{
283635c4bbdfSmrg    xEvent *xE = NULL;
283735c4bbdfSmrg    int count = 0;
283835c4bbdfSmrg    int deliveries = 0;
283935c4bbdfSmrg    int rc;
284035c4bbdfSmrg
284135c4bbdfSmrg    switch (level) {
284235c4bbdfSmrg    case XI2:
284335c4bbdfSmrg        rc = EventToXI2(event, &xE);
284435c4bbdfSmrg        count = 1;
284535c4bbdfSmrg        break;
284635c4bbdfSmrg    case XI:
284735c4bbdfSmrg        rc = EventToXI(event, &xE, &count);
284835c4bbdfSmrg        break;
284935c4bbdfSmrg    case CORE:
285035c4bbdfSmrg        rc = EventToCore(event, &xE, &count);
285135c4bbdfSmrg        break;
285235c4bbdfSmrg    default:
285335c4bbdfSmrg        rc = BadImplementation;
285435c4bbdfSmrg        break;
285535c4bbdfSmrg    }
285635c4bbdfSmrg
285735c4bbdfSmrg    if (rc == Success) {
285835c4bbdfSmrg        deliveries = DeliverEvent(dev, xE, count, win, child, grab);
285935c4bbdfSmrg        free(xE);
286035c4bbdfSmrg    }
286135c4bbdfSmrg    else
286235c4bbdfSmrg        BUG_WARN_MSG(rc != BadMatch,
286335c4bbdfSmrg                     "%s: conversion to level %d failed with rc %d\n",
286435c4bbdfSmrg                     dev->name, level, rc);
286535c4bbdfSmrg    return deliveries;
286635c4bbdfSmrg}
286735c4bbdfSmrg
28686747b715Smrg/**
28696747b715Smrg * Deliver events caused by input devices.
28706747b715Smrg *
28714642e01fSmrg * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is
28724642e01fSmrg * called directly from the processInputProc.
28734642e01fSmrg * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call
28744642e01fSmrg * DeliverDeviceEvents.
28754642e01fSmrg * For focused events, DeliverFocusedEvent is called first, and _may_ call
28764642e01fSmrg * DeliverDeviceEvents.
287705b261ecSmrg *
287805b261ecSmrg * @param pWin Window to deliver event to.
28796747b715Smrg * @param event The events to deliver, not yet in wire format.
288005b261ecSmrg * @param grab Possible grab on a device.
288105b261ecSmrg * @param stopAt Don't recurse up to the root window.
288205b261ecSmrg * @param dev The device that is responsible for the event.
288305b261ecSmrg *
28844642e01fSmrg * @see DeliverGrabbedEvent
28854642e01fSmrg * @see DeliverFocusedEvent
288605b261ecSmrg */
288705b261ecSmrgint
28886747b715SmrgDeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
28896747b715Smrg                    WindowPtr stopAt, DeviceIntPtr dev)
289005b261ecSmrg{
289105b261ecSmrg    Window child = None;
289205b261ecSmrg    int deliveries = 0;
289335c4bbdfSmrg    int mask;
28944642e01fSmrg
289535c4bbdfSmrg    verify_internal_event(event);
28964642e01fSmrg
289735c4bbdfSmrg    while (pWin) {
289835c4bbdfSmrg        if ((mask = EventIsDeliverable(dev, event->any.type, pWin))) {
28996747b715Smrg            /* XI2 events first */
290035c4bbdfSmrg            if (mask & EVENT_XI2_MASK) {
290135c4bbdfSmrg                deliveries =
290235c4bbdfSmrg                    DeliverOneEvent(event, dev, XI2, pWin, child, grab);
290335c4bbdfSmrg                if (deliveries > 0)
290435c4bbdfSmrg                    break;
29054642e01fSmrg            }
29064642e01fSmrg
29076747b715Smrg            /* XI events */
290835c4bbdfSmrg            if (mask & EVENT_XI1_MASK) {
290935c4bbdfSmrg                deliveries = DeliverOneEvent(event, dev, XI, pWin, child, grab);
291035c4bbdfSmrg                if (deliveries > 0)
291135c4bbdfSmrg                    break;
29126747b715Smrg            }
29134642e01fSmrg
29146747b715Smrg            /* Core event */
291535c4bbdfSmrg            if ((mask & EVENT_CORE_MASK) && IsMaster(dev) && dev->coreEvents) {
291635c4bbdfSmrg                deliveries =
291735c4bbdfSmrg                    DeliverOneEvent(event, dev, CORE, pWin, child, grab);
291835c4bbdfSmrg                if (deliveries > 0)
291935c4bbdfSmrg                    break;
29204642e01fSmrg            }
29214642e01fSmrg
292235c4bbdfSmrg        }
292335c4bbdfSmrg
292435c4bbdfSmrg        if ((deliveries < 0) || (pWin == stopAt) ||
292535c4bbdfSmrg            (mask & EVENT_DONT_PROPAGATE_MASK)) {
292635c4bbdfSmrg            deliveries = 0;
292735c4bbdfSmrg            break;
29284642e01fSmrg        }
29294642e01fSmrg
29304642e01fSmrg        child = pWin->drawable.id;
29314642e01fSmrg        pWin = pWin->parent;
293205b261ecSmrg    }
29334642e01fSmrg
29346747b715Smrg    return deliveries;
293505b261ecSmrg}
293605b261ecSmrg
293705b261ecSmrg/**
29385a112b11Smrg * Deliver event to a window and its immediate parent. Used for most window
293905b261ecSmrg * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
29404642e01fSmrg * propagate up the tree or extension events
294105b261ecSmrg *
294205b261ecSmrg * In case of a ReparentNotify event, the event will be delivered to the
294305b261ecSmrg * otherParent as well.
294405b261ecSmrg *
294505b261ecSmrg * @param pWin Window to deliver events to.
294605b261ecSmrg * @param xE Events to deliver.
294705b261ecSmrg * @param count number of events in xE.
294805b261ecSmrg * @param otherParent Used for ReparentNotify events.
294905b261ecSmrg */
29506747b715Smrgint
295135c4bbdfSmrgDeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent)
295205b261ecSmrg{
29536747b715Smrg    DeviceIntRec dummy;
295435c4bbdfSmrg    int deliveries;
295505b261ecSmrg
295605b261ecSmrg#ifdef PANORAMIX
295735c4bbdfSmrg    if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
295835c4bbdfSmrg        return count;
295905b261ecSmrg#endif
296005b261ecSmrg
296105b261ecSmrg    if (!count)
296235c4bbdfSmrg        return 0;
29636747b715Smrg
29646747b715Smrg    dummy.id = XIAllDevices;
296535c4bbdfSmrg
296635c4bbdfSmrg    switch (xE->u.u.type) {
296735c4bbdfSmrg    case DestroyNotify:
296835c4bbdfSmrg    case UnmapNotify:
296935c4bbdfSmrg    case MapNotify:
297035c4bbdfSmrg    case MapRequest:
297135c4bbdfSmrg    case ReparentNotify:
297235c4bbdfSmrg    case ConfigureNotify:
297335c4bbdfSmrg    case ConfigureRequest:
297435c4bbdfSmrg    case GravityNotify:
297535c4bbdfSmrg    case CirculateNotify:
297635c4bbdfSmrg    case CirculateRequest:
297735c4bbdfSmrg        xE->u.destroyNotify.event = pWin->drawable.id;
297835c4bbdfSmrg        break;
297935c4bbdfSmrg    }
298035c4bbdfSmrg
298135c4bbdfSmrg    switch (xE->u.u.type) {
298235c4bbdfSmrg    case DestroyNotify:
298335c4bbdfSmrg    case UnmapNotify:
298435c4bbdfSmrg    case MapNotify:
298535c4bbdfSmrg    case ReparentNotify:
298635c4bbdfSmrg    case ConfigureNotify:
298735c4bbdfSmrg    case GravityNotify:
298835c4bbdfSmrg    case CirculateNotify:
298935c4bbdfSmrg        break;
299035c4bbdfSmrg    default:
299135c4bbdfSmrg    {
299235c4bbdfSmrg        Mask filter;
299335c4bbdfSmrg
299435c4bbdfSmrg        filter = GetEventFilter(&dummy, xE);
299535c4bbdfSmrg        return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab);
299635c4bbdfSmrg    }
299735c4bbdfSmrg    }
299835c4bbdfSmrg
29996747b715Smrg    deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count,
30006747b715Smrg                                       StructureNotifyMask, NullGrab);
300135c4bbdfSmrg    if (pWin->parent) {
300235c4bbdfSmrg        xE->u.destroyNotify.event = pWin->parent->drawable.id;
300335c4bbdfSmrg        deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count,
300435c4bbdfSmrg                                            SubstructureNotifyMask, NullGrab);
300535c4bbdfSmrg        if (xE->u.u.type == ReparentNotify) {
300635c4bbdfSmrg            xE->u.destroyNotify.event = otherParent->drawable.id;
30076747b715Smrg            deliveries += DeliverEventsToWindow(&dummy,
300835c4bbdfSmrg                                                otherParent, xE, count,
300935c4bbdfSmrg                                                SubstructureNotifyMask,
301035c4bbdfSmrg                                                NullGrab);
301135c4bbdfSmrg        }
301205b261ecSmrg    }
301305b261ecSmrg    return deliveries;
301405b261ecSmrg}
301505b261ecSmrg
301635c4bbdfSmrgBool
301705b261ecSmrgPointInBorderSize(WindowPtr pWin, int x, int y)
301805b261ecSmrg{
301905b261ecSmrg    BoxRec box;
302005b261ecSmrg
302135c4bbdfSmrg    if (RegionContainsPoint(&pWin->borderSize, x, y, &box))
302235c4bbdfSmrg        return TRUE;
302305b261ecSmrg
302405b261ecSmrg#ifdef PANORAMIX
302535c4bbdfSmrg    if (!noPanoramiXExtension &&
302635c4bbdfSmrg        XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
302735c4bbdfSmrg        SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
302835c4bbdfSmrg        int i;
302935c4bbdfSmrg
303035c4bbdfSmrg        FOR_NSCREENS_FORWARD_SKIP(i) {
303135c4bbdfSmrg            if (RegionContainsPoint(&pSprite->windows[i]->borderSize,
303235c4bbdfSmrg                                    x + screenInfo.screens[0]->x -
303335c4bbdfSmrg                                    screenInfo.screens[i]->x,
303435c4bbdfSmrg                                    y + screenInfo.screens[0]->y -
303535c4bbdfSmrg                                    screenInfo.screens[i]->y, &box))
303635c4bbdfSmrg                return TRUE;
303735c4bbdfSmrg        }
303805b261ecSmrg    }
303905b261ecSmrg#endif
304005b261ecSmrg    return FALSE;
304105b261ecSmrg}
304205b261ecSmrg
304305b261ecSmrg/**
304405b261ecSmrg * Traversed from the root window to the window at the position x/y. While
304505b261ecSmrg * traversing, it sets up the traversal history in the spriteTrace array.
304605b261ecSmrg * After completing, the spriteTrace history is set in the following way:
304705b261ecSmrg *   spriteTrace[0] ... root window
304805b261ecSmrg *   spriteTrace[1] ... top level window that encloses x/y
304905b261ecSmrg *       ...
305005b261ecSmrg *   spriteTrace[spriteTraceGood - 1] ... window at x/y
305105b261ecSmrg *
305205b261ecSmrg * @returns the window at the given coordinates.
305305b261ecSmrg */
30549ace9065SmrgWindowPtr
30559ace9065SmrgXYToWindow(SpritePtr pSprite, int x, int y)
305605b261ecSmrg{
305735c4bbdfSmrg    ScreenPtr pScreen = RootWindow(pSprite)->drawable.pScreen;
305805b261ecSmrg
305935c4bbdfSmrg    return (*pScreen->XYToWindow)(pScreen, pSprite, x, y);
306005b261ecSmrg}
306105b261ecSmrg
30626747b715Smrg/**
30636747b715Smrg * Ungrab a currently FocusIn grabbed device and grab the device on the
30646747b715Smrg * given window. If the win given is the NoneWin, the device is ungrabbed if
30656747b715Smrg * applicable and FALSE is returned.
30666747b715Smrg *
30676747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise.
30686747b715Smrg */
30696747b715SmrgBOOL
30706747b715SmrgActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
30716747b715Smrg{
30726747b715Smrg    BOOL rc = FALSE;
30735a112b11Smrg    InternalEvent event;
30746747b715Smrg
307535c4bbdfSmrg    if (dev->deviceGrab.grab) {
30769ace9065Smrg        if (!dev->deviceGrab.fromPassiveGrab ||
30777e31ba66Smrg            dev->deviceGrab.grab->type != XI_FocusIn ||
30789ace9065Smrg            dev->deviceGrab.grab->window == win ||
30796747b715Smrg            IsParent(dev->deviceGrab.grab->window, win))
30806747b715Smrg            return FALSE;
30816747b715Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
308235c4bbdfSmrg        (*dev->deviceGrab.DeactivateGrab) (dev);
30836747b715Smrg    }
30846747b715Smrg
30856747b715Smrg    if (win == NoneWin || win == PointerRootWin)
30866747b715Smrg        return FALSE;
30876747b715Smrg
30885a112b11Smrg    event = (InternalEvent) {
30895a112b11Smrg        .device_event.header = ET_Internal,
30905a112b11Smrg        .device_event.type = ET_FocusIn,
30915a112b11Smrg        .device_event.length = sizeof(DeviceEvent),
30925a112b11Smrg        .device_event.time = GetTimeInMillis(),
30935a112b11Smrg        .device_event.deviceid = dev->id,
30945a112b11Smrg        .device_event.sourceid = dev->id,
30955a112b11Smrg        .device_event.detail.button = 0
309635c4bbdfSmrg    };
30975a112b11Smrg    rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE,
309835c4bbdfSmrg                                    TRUE) != NULL);
30996747b715Smrg    if (rc)
31007e31ba66Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
31016747b715Smrg    return rc;
31026747b715Smrg}
31036747b715Smrg
31046747b715Smrg/**
31056747b715Smrg * Ungrab a currently Enter grabbed device and grab the device for the given
31066747b715Smrg * window.
31076747b715Smrg *
31086747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise.
31096747b715Smrg */
31106747b715Smrgstatic BOOL
31116747b715SmrgActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
31126747b715Smrg{
31136747b715Smrg    BOOL rc = FALSE;
31145a112b11Smrg    InternalEvent event;
31156747b715Smrg
311635c4bbdfSmrg    if (dev->deviceGrab.grab) {
31179ace9065Smrg        if (!dev->deviceGrab.fromPassiveGrab ||
31189ace9065Smrg            dev->deviceGrab.grab->type != XI_Enter ||
31199ace9065Smrg            dev->deviceGrab.grab->window == win ||
31206747b715Smrg            IsParent(dev->deviceGrab.grab->window, win))
31216747b715Smrg            return FALSE;
31226747b715Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
312335c4bbdfSmrg        (*dev->deviceGrab.DeactivateGrab) (dev);
312435c4bbdfSmrg    }
312535c4bbdfSmrg
31265a112b11Smrg    event = (InternalEvent) {
31275a112b11Smrg        .device_event.header = ET_Internal,
31285a112b11Smrg        .device_event.type = ET_Enter,
31295a112b11Smrg        .device_event.length = sizeof(DeviceEvent),
31305a112b11Smrg        .device_event.time = GetTimeInMillis(),
31315a112b11Smrg        .device_event.deviceid = dev->id,
31325a112b11Smrg        .device_event.sourceid = dev->id,
31335a112b11Smrg        .device_event.detail.button = 0
313435c4bbdfSmrg    };
31355a112b11Smrg    rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE,
313635c4bbdfSmrg                                    TRUE) != NULL);
31376747b715Smrg    if (rc)
31386747b715Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
31396747b715Smrg    return rc;
31406747b715Smrg}
31416747b715Smrg
314205b261ecSmrg/**
314305b261ecSmrg * Update the sprite coordinates based on the event. Update the cursor
314405b261ecSmrg * position, then update the event with the new coordinates that may have been
314505b261ecSmrg * changed. If the window underneath the sprite has changed, change to new
314605b261ecSmrg * cursor and send enter/leave events.
31474642e01fSmrg *
31484642e01fSmrg * CheckMotion() will not do anything and return FALSE if the event is not a
31494642e01fSmrg * pointer event.
31504642e01fSmrg *
31514642e01fSmrg * @return TRUE if the sprite has moved or FALSE otherwise.
315205b261ecSmrg */
31534642e01fSmrgBool
31546747b715SmrgCheckMotion(DeviceEvent *ev, DeviceIntPtr pDev)
315505b261ecSmrg{
31566747b715Smrg    WindowPtr prevSpriteWin, newSpriteWin;
31574642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
31584642e01fSmrg
315935c4bbdfSmrg    verify_internal_event((InternalEvent *) ev);
316005b261ecSmrg
31616747b715Smrg    prevSpriteWin = pSprite->win;
316205b261ecSmrg
316335c4bbdfSmrg    if (ev && !syncEvents.playingEvents) {
31644642e01fSmrg        /* GetPointerEvents() guarantees that pointer events have the correct
31654642e01fSmrg           rootX/Y set already. */
316635c4bbdfSmrg        switch (ev->type) {
316735c4bbdfSmrg        case ET_ButtonPress:
316835c4bbdfSmrg        case ET_ButtonRelease:
316935c4bbdfSmrg        case ET_Motion:
317035c4bbdfSmrg        case ET_TouchBegin:
317135c4bbdfSmrg        case ET_TouchUpdate:
317235c4bbdfSmrg        case ET_TouchEnd:
317335c4bbdfSmrg            break;
317435c4bbdfSmrg        default:
317535c4bbdfSmrg            /* all other events return FALSE */
317635c4bbdfSmrg            return FALSE;
31774642e01fSmrg        }
31784642e01fSmrg
31796747b715Smrg#ifdef PANORAMIX
318035c4bbdfSmrg        if (!noPanoramiXExtension) {
31816747b715Smrg            /* Motion events entering DIX get translated to Screen 0
31826747b715Smrg               coordinates.  Replayed events have already been
31836747b715Smrg               translated since they've entered DIX before */
31846747b715Smrg            ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
31856747b715Smrg            ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
318635c4bbdfSmrg        }
318735c4bbdfSmrg        else
31886747b715Smrg#endif
31896747b715Smrg        {
319035c4bbdfSmrg            if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen) {
31916747b715Smrg                pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
31929ace9065Smrg                RootWindow(pDev->spriteInfo->sprite) =
31939ace9065Smrg                    pSprite->hot.pScreen->root;
31946747b715Smrg            }
31954642e01fSmrg        }
31966747b715Smrg
31976747b715Smrg        pSprite->hot.x = ev->root_x;
31986747b715Smrg        pSprite->hot.y = ev->root_y;
31994642e01fSmrg        if (pSprite->hot.x < pSprite->physLimits.x1)
32004642e01fSmrg            pSprite->hot.x = pSprite->physLimits.x1;
32014642e01fSmrg        else if (pSprite->hot.x >= pSprite->physLimits.x2)
32024642e01fSmrg            pSprite->hot.x = pSprite->physLimits.x2 - 1;
32034642e01fSmrg        if (pSprite->hot.y < pSprite->physLimits.y1)
32044642e01fSmrg            pSprite->hot.y = pSprite->physLimits.y1;
32054642e01fSmrg        else if (pSprite->hot.y >= pSprite->physLimits.y2)
32064642e01fSmrg            pSprite->hot.y = pSprite->physLimits.y2 - 1;
320735c4bbdfSmrg        if (pSprite->hotShape)
320835c4bbdfSmrg            ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x,
320935c4bbdfSmrg                           &pSprite->hot.y);
321035c4bbdfSmrg        pSprite->hotPhys = pSprite->hot;
32114642e01fSmrg
321235c4bbdfSmrg        if ((pSprite->hotPhys.x != ev->root_x) ||
321335c4bbdfSmrg            (pSprite->hotPhys.y != ev->root_y)) {
32146747b715Smrg#ifdef PANORAMIX
321535c4bbdfSmrg            if (!noPanoramiXExtension) {
321635c4bbdfSmrg                XineramaSetCursorPosition(pDev, pSprite->hotPhys.x,
321735c4bbdfSmrg                                          pSprite->hotPhys.y, FALSE);
321835c4bbdfSmrg            }
321935c4bbdfSmrg            else
32206747b715Smrg#endif
32216747b715Smrg            {
322235c4bbdfSmrg                (*pSprite->hotPhys.pScreen->SetCursorPosition) (pDev,
322335c4bbdfSmrg                                                                pSprite->
322435c4bbdfSmrg                                                                hotPhys.pScreen,
322535c4bbdfSmrg                                                                pSprite->
322635c4bbdfSmrg                                                                hotPhys.x,
322735c4bbdfSmrg                                                                pSprite->
322835c4bbdfSmrg                                                                hotPhys.y,
322935c4bbdfSmrg                                                                FALSE);
32306747b715Smrg            }
323135c4bbdfSmrg        }
32324642e01fSmrg
323335c4bbdfSmrg        ev->root_x = pSprite->hot.x;
323435c4bbdfSmrg        ev->root_y = pSprite->hot.y;
323505b261ecSmrg    }
323605b261ecSmrg
32379ace9065Smrg    newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y);
32386747b715Smrg
323935c4bbdfSmrg    if (newSpriteWin != prevSpriteWin) {
32406747b715Smrg        int sourceid;
324135c4bbdfSmrg
32426747b715Smrg        if (!ev) {
32436747b715Smrg            UpdateCurrentTimeIf();
324435c4bbdfSmrg            sourceid = pDev->id;        /* when from WindowsRestructured */
324535c4bbdfSmrg        }
324635c4bbdfSmrg        else
32476747b715Smrg            sourceid = ev->sourceid;
32486747b715Smrg
324935c4bbdfSmrg        if (prevSpriteWin != NullWindow) {
32506747b715Smrg            if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin))
32516747b715Smrg                DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin,
32526747b715Smrg                                   newSpriteWin, NotifyNormal);
32534642e01fSmrg        }
32546747b715Smrg        /* set pSprite->win after ActivateEnterGrab, otherwise
32556747b715Smrg           sprite window == grab_window and no enter/leave events are
32566747b715Smrg           sent. */
32576747b715Smrg        pSprite->win = newSpriteWin;
32586747b715Smrg        PostNewCursor(pDev);
325905b261ecSmrg        return FALSE;
326005b261ecSmrg    }
326105b261ecSmrg    return TRUE;
326205b261ecSmrg}
326305b261ecSmrg
326405b261ecSmrg/**
326505b261ecSmrg * Windows have restructured, we need to update the sprite position and the
326605b261ecSmrg * sprite's cursor.
326705b261ecSmrg */
32684642e01fSmrgvoid
326905b261ecSmrgWindowsRestructured(void)
327005b261ecSmrg{
32714642e01fSmrg    DeviceIntPtr pDev = inputInfo.devices;
327235c4bbdfSmrg
327335c4bbdfSmrg    while (pDev) {
327435c4bbdfSmrg        if (IsMaster(pDev) || IsFloating(pDev))
3275b1d344b3Smrg            CheckMotion(NULL, pDev);
32764642e01fSmrg        pDev = pDev->next;
32774642e01fSmrg    }
327805b261ecSmrg}
327905b261ecSmrg
328005b261ecSmrg#ifdef PANORAMIX
328105b261ecSmrg/* This was added to support reconfiguration under Xdmx.  The problem is
32826747b715Smrg * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin
328305b261ecSmrg * other than 0,0, the information in the private sprite structure must
328405b261ecSmrg * be updated accordingly, or XYToWindow (and other routines) will not
328505b261ecSmrg * compute correctly. */
328635c4bbdfSmrgvoid
328735c4bbdfSmrgReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
328805b261ecSmrg{
328935c4bbdfSmrg    GrabPtr grab;
32904642e01fSmrg    DeviceIntPtr pDev;
32914642e01fSmrg    SpritePtr pSprite;
329205b261ecSmrg
329335c4bbdfSmrg    if (noPanoramiXExtension)
329435c4bbdfSmrg        return;
329505b261ecSmrg
32964642e01fSmrg    pDev = inputInfo.devices;
329735c4bbdfSmrg    while (pDev) {
329835c4bbdfSmrg        if (DevHasCursor(pDev)) {
32994642e01fSmrg            pSprite = pDev->spriteInfo->sprite;
330035c4bbdfSmrg            pSprite->hot.x -= xoff;
330135c4bbdfSmrg            pSprite->hot.y -= yoff;
33024642e01fSmrg
330335c4bbdfSmrg            pSprite->hotPhys.x -= xoff;
330435c4bbdfSmrg            pSprite->hotPhys.y -= yoff;
33054642e01fSmrg
33064642e01fSmrg            pSprite->hotLimits.x1 -= xoff;
33074642e01fSmrg            pSprite->hotLimits.y1 -= yoff;
33084642e01fSmrg            pSprite->hotLimits.x2 -= xoff;
33094642e01fSmrg            pSprite->hotLimits.y2 -= yoff;
33104642e01fSmrg
33116747b715Smrg            if (RegionNotEmpty(&pSprite->Reg1))
33126747b715Smrg                RegionTranslate(&pSprite->Reg1, xoff, yoff);
33136747b715Smrg            if (RegionNotEmpty(&pSprite->Reg2))
33146747b715Smrg                RegionTranslate(&pSprite->Reg2, xoff, yoff);
33154642e01fSmrg
33164642e01fSmrg            /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
33174642e01fSmrg            if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
33184642e01fSmrg                if (grab->confineTo->drawable.pScreen
331935c4bbdfSmrg                    != pSprite->hotPhys.pScreen)
33204642e01fSmrg                    pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
33214642e01fSmrg                ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
332235c4bbdfSmrg            }
332335c4bbdfSmrg            else
332435c4bbdfSmrg                ConfineCursorToWindow(pDev,
332535c4bbdfSmrg                                      pSprite->hotPhys.pScreen->root,
332635c4bbdfSmrg                                      TRUE, FALSE);
33274642e01fSmrg
33284642e01fSmrg        }
33294642e01fSmrg        pDev = pDev->next;
33304642e01fSmrg    }
33314642e01fSmrg}
33324642e01fSmrg#endif
33334642e01fSmrg
33344642e01fSmrg/**
33354642e01fSmrg * Initialize a sprite for the given device and set it to some sane values. If
33364642e01fSmrg * the device already has a sprite alloc'd, don't realloc but just reset to
33374642e01fSmrg * default values.
33384642e01fSmrg * If a window is supplied, the sprite will be initialized with the window's
33394642e01fSmrg * cursor and positioned in the center of the window's screen. The root window
33404642e01fSmrg * is a good choice to pass in here.
33414642e01fSmrg *
33424642e01fSmrg * It's a good idea to call it only for pointer devices, unless you have a
33434642e01fSmrg * really talented keyboard.
33444642e01fSmrg *
33454642e01fSmrg * @param pDev The device to initialize.
33464642e01fSmrg * @param pWin The window where to generate the sprite in.
33474642e01fSmrg *
33484642e01fSmrg */
33494642e01fSmrgvoid
33504642e01fSmrgInitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
33514642e01fSmrg{
33524642e01fSmrg    SpritePtr pSprite;
33534642e01fSmrg    ScreenPtr pScreen;
33546747b715Smrg    CursorPtr pCursor;
33554642e01fSmrg
335635c4bbdfSmrg    if (!pDev->spriteInfo->sprite) {
33574642e01fSmrg        DeviceIntPtr it;
33584642e01fSmrg
335935c4bbdfSmrg        pDev->spriteInfo->sprite = (SpritePtr) calloc(1, sizeof(SpriteRec));
33604642e01fSmrg        if (!pDev->spriteInfo->sprite)
33614642e01fSmrg            FatalError("InitializeSprite: failed to allocate sprite struct");
33624642e01fSmrg
33634642e01fSmrg        /* We may have paired another device with this device before our
33644642e01fSmrg         * device had a actual sprite. We need to check for this and reset the
33654642e01fSmrg         * sprite field for all paired devices.
33664642e01fSmrg         *
33674642e01fSmrg         * The VCK is always paired with the VCP before the VCP has a sprite.
33684642e01fSmrg         */
336935c4bbdfSmrg        for (it = inputInfo.devices; it; it = it->next) {
33704642e01fSmrg            if (it->spriteInfo->paired == pDev)
33714642e01fSmrg                it->spriteInfo->sprite = pDev->spriteInfo->sprite;
33724642e01fSmrg        }
33734642e01fSmrg        if (inputInfo.keyboard->spriteInfo->paired == pDev)
33744642e01fSmrg            inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite;
33754642e01fSmrg    }
33764642e01fSmrg
33774642e01fSmrg    pSprite = pDev->spriteInfo->sprite;
33784642e01fSmrg    pDev->spriteInfo->spriteOwner = TRUE;
337905b261ecSmrg
338035c4bbdfSmrg    pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr) NULL;
33814642e01fSmrg    pSprite->hot.pScreen = pScreen;
33824642e01fSmrg    pSprite->hotPhys.pScreen = pScreen;
338335c4bbdfSmrg    if (pScreen) {
33844642e01fSmrg        pSprite->hotPhys.x = pScreen->width / 2;
33854642e01fSmrg        pSprite->hotPhys.y = pScreen->height / 2;
33864642e01fSmrg        pSprite->hotLimits.x2 = pScreen->width;
33874642e01fSmrg        pSprite->hotLimits.y2 = pScreen->height;
33884642e01fSmrg    }
33894642e01fSmrg
33904642e01fSmrg    pSprite->hot = pSprite->hotPhys;
33914642e01fSmrg    pSprite->win = pWin;
33924642e01fSmrg
339335c4bbdfSmrg    if (pWin) {
339435c4bbdfSmrg        pCursor = wCursor(pWin);
339535c4bbdfSmrg        pSprite->spriteTrace = (WindowPtr *) calloc(1, 32 * sizeof(WindowPtr));
339635c4bbdfSmrg        if (!pSprite->spriteTrace)
339735c4bbdfSmrg            FatalError("Failed to allocate spriteTrace");
339835c4bbdfSmrg        pSprite->spriteTraceSize = 32;
33994642e01fSmrg
340035c4bbdfSmrg        RootWindow(pDev->spriteInfo->sprite) = pWin;
340135c4bbdfSmrg        pSprite->spriteTraceGood = 1;
34024642e01fSmrg
340335c4bbdfSmrg        pSprite->pEnqueueScreen = pScreen;
340435c4bbdfSmrg        pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
34054642e01fSmrg
340635c4bbdfSmrg    }
340735c4bbdfSmrg    else {
34086747b715Smrg        pCursor = NullCursor;
340935c4bbdfSmrg        pSprite->spriteTrace = NULL;
341035c4bbdfSmrg        pSprite->spriteTraceSize = 0;
341135c4bbdfSmrg        pSprite->spriteTraceGood = 0;
341235c4bbdfSmrg        pSprite->pEnqueueScreen = screenInfo.screens[0];
341335c4bbdfSmrg        pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
341435c4bbdfSmrg    }
341535c4bbdfSmrg    pCursor = RefCursor(pCursor);
34166747b715Smrg    if (pSprite->current)
341735c4bbdfSmrg        FreeCursor(pSprite->current, None);
34186747b715Smrg    pSprite->current = pCursor;
34194642e01fSmrg
342035c4bbdfSmrg    if (pScreen) {
342135c4bbdfSmrg        (*pScreen->RealizeCursor) (pDev, pScreen, pSprite->current);
342235c4bbdfSmrg        (*pScreen->CursorLimits) (pDev, pScreen, pSprite->current,
342335c4bbdfSmrg                                  &pSprite->hotLimits, &pSprite->physLimits);
34244642e01fSmrg        pSprite->confined = FALSE;
34254642e01fSmrg
342635c4bbdfSmrg        (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
34274642e01fSmrg        (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
342835c4bbdfSmrg                                       pSprite->hot.y, FALSE);
34294642e01fSmrg        (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
34304642e01fSmrg    }
343105b261ecSmrg#ifdef PANORAMIX
343235c4bbdfSmrg    if (!noPanoramiXExtension) {
34336747b715Smrg        pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
34346747b715Smrg        pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
343535c4bbdfSmrg        pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
34366747b715Smrg        pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
34374642e01fSmrg        pSprite->physLimits = pSprite->hotLimits;
34384642e01fSmrg        pSprite->confineWin = NullWindow;
34394642e01fSmrg        pSprite->hotShape = NullRegion;
34404642e01fSmrg        pSprite->screen = pScreen;
34414642e01fSmrg        /* gotta UNINIT these someplace */
34426747b715Smrg        RegionNull(&pSprite->Reg1);
34436747b715Smrg        RegionNull(&pSprite->Reg2);
34444642e01fSmrg    }
344505b261ecSmrg#endif
34464642e01fSmrg}
34474642e01fSmrg
344835c4bbdfSmrgvoid FreeSprite(DeviceIntPtr dev)
344935c4bbdfSmrg{
345035c4bbdfSmrg    if (DevHasCursor(dev) && dev->spriteInfo->sprite) {
345135c4bbdfSmrg        if (dev->spriteInfo->sprite->current)
345235c4bbdfSmrg            FreeCursor(dev->spriteInfo->sprite->current, None);
345335c4bbdfSmrg        free(dev->spriteInfo->sprite->spriteTrace);
345435c4bbdfSmrg        free(dev->spriteInfo->sprite);
345535c4bbdfSmrg    }
345635c4bbdfSmrg    dev->spriteInfo->sprite = NULL;
345735c4bbdfSmrg}
345835c4bbdfSmrg
345935c4bbdfSmrg
34604642e01fSmrg/**
34614642e01fSmrg * Update the mouse sprite info when the server switches from a pScreen to another.
34624642e01fSmrg * Otherwise, the pScreen of the mouse sprite is never updated when we switch
34634642e01fSmrg * from a pScreen to another. Never updating the pScreen of the mouse sprite
34644642e01fSmrg * implies that windows that are in pScreen whose pScreen->myNum >0 will never
34654642e01fSmrg * get pointer events. This is  because in CheckMotion(), sprite.hotPhys.pScreen
34664642e01fSmrg * always points to the first pScreen it has been set by
34674642e01fSmrg * DefineInitialRootWindow().
34684642e01fSmrg *
34694642e01fSmrg * Calling this function is useful for use cases where the server
34704642e01fSmrg * has more than one pScreen.
34714642e01fSmrg * This function is similar to DefineInitialRootWindow() but it does not
34724642e01fSmrg * reset the mouse pointer position.
34734642e01fSmrg * @param win must be the new pScreen we are switching to.
34744642e01fSmrg */
34754642e01fSmrgvoid
34764642e01fSmrgUpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
34774642e01fSmrg{
34784642e01fSmrg    SpritePtr pSprite = NULL;
34794642e01fSmrg    WindowPtr win = NULL;
34806747b715Smrg    CursorPtr pCursor;
348135c4bbdfSmrg
34824642e01fSmrg    if (!pScreen)
348335c4bbdfSmrg        return;
34844642e01fSmrg
34854642e01fSmrg    if (!pDev->spriteInfo->sprite)
34864642e01fSmrg        return;
34874642e01fSmrg
34884642e01fSmrg    pSprite = pDev->spriteInfo->sprite;
34894642e01fSmrg
34906747b715Smrg    win = pScreen->root;
34914642e01fSmrg
34924642e01fSmrg    pSprite->hotPhys.pScreen = pScreen;
34934642e01fSmrg    pSprite->hot = pSprite->hotPhys;
34944642e01fSmrg    pSprite->hotLimits.x2 = pScreen->width;
34954642e01fSmrg    pSprite->hotLimits.y2 = pScreen->height;
34964642e01fSmrg    pSprite->win = win;
349735c4bbdfSmrg    pCursor = RefCursor(wCursor(win));
34986747b715Smrg    if (pSprite->current)
349935c4bbdfSmrg        FreeCursor(pSprite->current, 0);
35006747b715Smrg    pSprite->current = pCursor;
35014642e01fSmrg    pSprite->spriteTraceGood = 1;
35024642e01fSmrg    pSprite->spriteTrace[0] = win;
35034642e01fSmrg    (*pScreen->CursorLimits) (pDev,
35044642e01fSmrg                              pScreen,
35054642e01fSmrg                              pSprite->current,
350635c4bbdfSmrg                              &pSprite->hotLimits, &pSprite->physLimits);
35074642e01fSmrg    pSprite->confined = FALSE;
35084642e01fSmrg    (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
35094642e01fSmrg    (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
35104642e01fSmrg
35114642e01fSmrg#ifdef PANORAMIX
351235c4bbdfSmrg    if (!noPanoramiXExtension) {
35136747b715Smrg        pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
35146747b715Smrg        pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
351535c4bbdfSmrg        pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
35166747b715Smrg        pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
35174642e01fSmrg        pSprite->physLimits = pSprite->hotLimits;
35184642e01fSmrg        pSprite->screen = pScreen;
351905b261ecSmrg    }
352005b261ecSmrg#endif
352105b261ecSmrg}
352205b261ecSmrg
352305b261ecSmrg/*
352405b261ecSmrg * This does not take any shortcuts, and even ignores its argument, since
352505b261ecSmrg * it does not happen very often, and one has to walk up the tree since
352605b261ecSmrg * this might be a newly instantiated cursor for an intermediate window
352705b261ecSmrg * between the one the pointer is in and the one that the last cursor was
352805b261ecSmrg * instantiated from.
352905b261ecSmrg */
353005b261ecSmrgvoid
353105b261ecSmrgWindowHasNewCursor(WindowPtr pWin)
353205b261ecSmrg{
35334642e01fSmrg    DeviceIntPtr pDev;
35344642e01fSmrg
353535c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
35364642e01fSmrg        if (DevHasCursor(pDev))
35374642e01fSmrg            PostNewCursor(pDev);
353805b261ecSmrg}
353905b261ecSmrg
35406747b715Smrgvoid
35414642e01fSmrgNewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
354205b261ecSmrg{
354335c4bbdfSmrg    DeviceIntPtr ptr;
354435c4bbdfSmrg    SpritePtr pSprite;
354535c4bbdfSmrg
354635c4bbdfSmrg    ptr =
354735c4bbdfSmrg        IsFloating(pDev) ? pDev :
354835c4bbdfSmrg        GetXTestDevice(GetMaster(pDev, MASTER_POINTER));
354935c4bbdfSmrg    pSprite = ptr->spriteInfo->sprite;
35504642e01fSmrg
35514642e01fSmrg    pSprite->hotPhys.x = x;
35524642e01fSmrg    pSprite->hotPhys.y = y;
355305b261ecSmrg#ifdef PANORAMIX
355435c4bbdfSmrg    if (!noPanoramiXExtension) {
355535c4bbdfSmrg        pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x;
355635c4bbdfSmrg        pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y;
355735c4bbdfSmrg        if (newScreen != pSprite->screen) {
355835c4bbdfSmrg            pSprite->screen = newScreen;
355935c4bbdfSmrg            /* Make sure we tell the DDX to update its copy of the screen */
356035c4bbdfSmrg            if (pSprite->confineWin)
356135c4bbdfSmrg                XineramaConfineCursorToWindow(ptr, pSprite->confineWin, TRUE);
356235c4bbdfSmrg            else
356335c4bbdfSmrg                XineramaConfineCursorToWindow(ptr, screenInfo.screens[0]->root,
356435c4bbdfSmrg                                              TRUE);
356535c4bbdfSmrg            /* if the pointer wasn't confined, the DDX won't get
356635c4bbdfSmrg               told of the pointer warp so we reposition it here */
356735c4bbdfSmrg            if (!syncEvents.playingEvents)
356835c4bbdfSmrg                (*pSprite->screen->SetCursorPosition) (ptr,
356935c4bbdfSmrg                                                       pSprite->screen,
357035c4bbdfSmrg                                                       pSprite->hotPhys.x +
357135c4bbdfSmrg                                                       screenInfo.screens[0]->
357235c4bbdfSmrg                                                       x - pSprite->screen->x,
357335c4bbdfSmrg                                                       pSprite->hotPhys.y +
357435c4bbdfSmrg                                                       screenInfo.screens[0]->
357535c4bbdfSmrg                                                       y - pSprite->screen->y,
357635c4bbdfSmrg                                                       FALSE);
357735c4bbdfSmrg        }
357835c4bbdfSmrg    }
357935c4bbdfSmrg    else
358005b261ecSmrg#endif
35814642e01fSmrg    if (newScreen != pSprite->hotPhys.pScreen)
358235c4bbdfSmrg        ConfineCursorToWindow(ptr, newScreen->root, TRUE, FALSE);
358305b261ecSmrg}
358405b261ecSmrg
358505b261ecSmrg#ifdef PANORAMIX
358605b261ecSmrg
358705b261ecSmrgstatic Bool
358835c4bbdfSmrgXineramaPointInWindowIsVisible(WindowPtr pWin, int x, int y)
358905b261ecSmrg{
359005b261ecSmrg    BoxRec box;
359105b261ecSmrg    int i, xoff, yoff;
359205b261ecSmrg
359335c4bbdfSmrg    if (!pWin->realized)
359435c4bbdfSmrg        return FALSE;
359505b261ecSmrg
35966747b715Smrg    if (RegionContainsPoint(&pWin->borderClip, x, y, &box))
359705b261ecSmrg        return TRUE;
359805b261ecSmrg
359935c4bbdfSmrg    if (!XineramaSetWindowPntrs(inputInfo.pointer, pWin))
360035c4bbdfSmrg         return FALSE;
36014642e01fSmrg
36026747b715Smrg    xoff = x + screenInfo.screens[0]->x;
36036747b715Smrg    yoff = y + screenInfo.screens[0]->y;
360405b261ecSmrg
360535c4bbdfSmrg    FOR_NSCREENS_FORWARD_SKIP(i) {
360635c4bbdfSmrg        pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
360735c4bbdfSmrg
360835c4bbdfSmrg        x = xoff - screenInfo.screens[i]->x;
360935c4bbdfSmrg        y = yoff - screenInfo.screens[i]->y;
361005b261ecSmrg
361135c4bbdfSmrg        if (RegionContainsPoint(&pWin->borderClip, x, y, &box)
361235c4bbdfSmrg            && (!wInputShape(pWin) ||
361335c4bbdfSmrg                RegionContainsPoint(wInputShape(pWin),
361435c4bbdfSmrg                                    x - pWin->drawable.x,
361535c4bbdfSmrg                                    y - pWin->drawable.y, &box)))
361605b261ecSmrg            return TRUE;
361705b261ecSmrg
361805b261ecSmrg    }
361905b261ecSmrg
362005b261ecSmrg    return FALSE;
362105b261ecSmrg}
362205b261ecSmrg
362305b261ecSmrgstatic int
362405b261ecSmrgXineramaWarpPointer(ClientPtr client)
362505b261ecSmrg{
362635c4bbdfSmrg    WindowPtr dest = NULL;
362735c4bbdfSmrg    int x, y, rc;
362835c4bbdfSmrg    SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
362905b261ecSmrg
363005b261ecSmrg    REQUEST(xWarpPointerReq);
363105b261ecSmrg
363205b261ecSmrg    if (stuff->dstWid != None) {
363335c4bbdfSmrg        rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
363435c4bbdfSmrg        if (rc != Success)
363535c4bbdfSmrg            return rc;
363605b261ecSmrg    }
36374642e01fSmrg    x = pSprite->hotPhys.x;
36384642e01fSmrg    y = pSprite->hotPhys.y;
363905b261ecSmrg
364035c4bbdfSmrg    if (stuff->srcWid != None) {
364135c4bbdfSmrg        int winX, winY;
364235c4bbdfSmrg        XID winID = stuff->srcWid;
364305b261ecSmrg        WindowPtr source;
36444642e01fSmrg
364535c4bbdfSmrg        rc = dixLookupWindow(&source, winID, client, DixReadAccess);
364635c4bbdfSmrg        if (rc != Success)
364735c4bbdfSmrg            return rc;
364835c4bbdfSmrg
364935c4bbdfSmrg        winX = source->drawable.x;
365035c4bbdfSmrg        winY = source->drawable.y;
365135c4bbdfSmrg        if (source == screenInfo.screens[0]->root) {
365235c4bbdfSmrg            winX -= screenInfo.screens[0]->x;
365335c4bbdfSmrg            winY -= screenInfo.screens[0]->y;
365435c4bbdfSmrg        }
365535c4bbdfSmrg        if (x < winX + stuff->srcX ||
365635c4bbdfSmrg            y < winY + stuff->srcY ||
365735c4bbdfSmrg            (stuff->srcWidth != 0 &&
365835c4bbdfSmrg             winX + stuff->srcX + (int) stuff->srcWidth < x) ||
365935c4bbdfSmrg            (stuff->srcHeight != 0 &&
366035c4bbdfSmrg             winY + stuff->srcY + (int) stuff->srcHeight < y) ||
366135c4bbdfSmrg            !XineramaPointInWindowIsVisible(source, x, y))
366235c4bbdfSmrg            return Success;
366305b261ecSmrg    }
366405b261ecSmrg    if (dest) {
366535c4bbdfSmrg        x = dest->drawable.x;
366635c4bbdfSmrg        y = dest->drawable.y;
366735c4bbdfSmrg        if (dest == screenInfo.screens[0]->root) {
366835c4bbdfSmrg            x -= screenInfo.screens[0]->x;
366935c4bbdfSmrg            y -= screenInfo.screens[0]->y;
367035c4bbdfSmrg        }
36714642e01fSmrg    }
367205b261ecSmrg
367305b261ecSmrg    x += stuff->dstX;
367405b261ecSmrg    y += stuff->dstY;
367505b261ecSmrg
36764642e01fSmrg    if (x < pSprite->physLimits.x1)
367735c4bbdfSmrg        x = pSprite->physLimits.x1;
36784642e01fSmrg    else if (x >= pSprite->physLimits.x2)
367935c4bbdfSmrg        x = pSprite->physLimits.x2 - 1;
36804642e01fSmrg    if (y < pSprite->physLimits.y1)
368135c4bbdfSmrg        y = pSprite->physLimits.y1;
36824642e01fSmrg    else if (y >= pSprite->physLimits.y2)
368335c4bbdfSmrg        y = pSprite->physLimits.y2 - 1;
36844642e01fSmrg    if (pSprite->hotShape)
368535c4bbdfSmrg        ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
368605b261ecSmrg
36874642e01fSmrg    XineramaSetCursorPosition(PickPointer(client), x, y, TRUE);
368805b261ecSmrg
368905b261ecSmrg    return Success;
369005b261ecSmrg}
369105b261ecSmrg
369205b261ecSmrg#endif
369305b261ecSmrg
369405b261ecSmrg/**
369505b261ecSmrg * Server-side protocol handling for WarpPointer request.
369605b261ecSmrg * Warps the cursor position to the coordinates given in the request.
369705b261ecSmrg */
369805b261ecSmrgint
369905b261ecSmrgProcWarpPointer(ClientPtr client)
370005b261ecSmrg{
370135c4bbdfSmrg    WindowPtr dest = NULL;
370235c4bbdfSmrg    int x, y, rc;
370335c4bbdfSmrg    ScreenPtr newScreen;
37046747b715Smrg    DeviceIntPtr dev, tmp;
370535c4bbdfSmrg    SpritePtr pSprite;
370605b261ecSmrg
370705b261ecSmrg    REQUEST(xWarpPointerReq);
370805b261ecSmrg    REQUEST_SIZE_MATCH(xWarpPointerReq);
370905b261ecSmrg
37106747b715Smrg    dev = PickPointer(client);
37116747b715Smrg
37126747b715Smrg    for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
371335c4bbdfSmrg        if (GetMaster(tmp, MASTER_ATTACHED) == dev) {
371435c4bbdfSmrg            rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
371535c4bbdfSmrg            if (rc != Success)
371635c4bbdfSmrg                return rc;
371735c4bbdfSmrg        }
37184642e01fSmrg    }
37194642e01fSmrg
372035c4bbdfSmrg    if (dev->lastSlave)
372135c4bbdfSmrg        dev = dev->lastSlave;
37224642e01fSmrg    pSprite = dev->spriteInfo->sprite;
37234642e01fSmrg
372405b261ecSmrg#ifdef PANORAMIX
372535c4bbdfSmrg    if (!noPanoramiXExtension)
372635c4bbdfSmrg        return XineramaWarpPointer(client);
372705b261ecSmrg#endif
372805b261ecSmrg
372905b261ecSmrg    if (stuff->dstWid != None) {
373035c4bbdfSmrg        rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess);
373135c4bbdfSmrg        if (rc != Success)
373235c4bbdfSmrg            return rc;
373305b261ecSmrg    }
37344642e01fSmrg    x = pSprite->hotPhys.x;
37354642e01fSmrg    y = pSprite->hotPhys.y;
373605b261ecSmrg
373735c4bbdfSmrg    if (stuff->srcWid != None) {
373835c4bbdfSmrg        int winX, winY;
373935c4bbdfSmrg        XID winID = stuff->srcWid;
374005b261ecSmrg        WindowPtr source;
37414642e01fSmrg
374235c4bbdfSmrg        rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess);
374335c4bbdfSmrg        if (rc != Success)
374435c4bbdfSmrg            return rc;
374535c4bbdfSmrg
374635c4bbdfSmrg        winX = source->drawable.x;
374735c4bbdfSmrg        winY = source->drawable.y;
374835c4bbdfSmrg        if (source->drawable.pScreen != pSprite->hotPhys.pScreen ||
374935c4bbdfSmrg            x < winX + stuff->srcX ||
375035c4bbdfSmrg            y < winY + stuff->srcY ||
375135c4bbdfSmrg            (stuff->srcWidth != 0 &&
375235c4bbdfSmrg             winX + stuff->srcX + (int) stuff->srcWidth < x) ||
375335c4bbdfSmrg            (stuff->srcHeight != 0 &&
375435c4bbdfSmrg             winY + stuff->srcY + (int) stuff->srcHeight < y) ||
37557e31ba66Smrg            (source->parent && !PointInWindowIsVisible(source, x, y)))
375635c4bbdfSmrg            return Success;
375735c4bbdfSmrg    }
375835c4bbdfSmrg    if (dest) {
375935c4bbdfSmrg        x = dest->drawable.x;
376035c4bbdfSmrg        y = dest->drawable.y;
376135c4bbdfSmrg        newScreen = dest->drawable.pScreen;
376235c4bbdfSmrg    }
376335c4bbdfSmrg    else
376435c4bbdfSmrg        newScreen = pSprite->hotPhys.pScreen;
376505b261ecSmrg
376605b261ecSmrg    x += stuff->dstX;
376705b261ecSmrg    y += stuff->dstY;
376805b261ecSmrg
376905b261ecSmrg    if (x < 0)
377035c4bbdfSmrg        x = 0;
377105b261ecSmrg    else if (x >= newScreen->width)
377235c4bbdfSmrg        x = newScreen->width - 1;
377305b261ecSmrg    if (y < 0)
377435c4bbdfSmrg        y = 0;
377505b261ecSmrg    else if (y >= newScreen->height)
377635c4bbdfSmrg        y = newScreen->height - 1;
377735c4bbdfSmrg
377835c4bbdfSmrg    if (newScreen == pSprite->hotPhys.pScreen) {
377935c4bbdfSmrg        if (x < pSprite->physLimits.x1)
378035c4bbdfSmrg            x = pSprite->physLimits.x1;
378135c4bbdfSmrg        else if (x >= pSprite->physLimits.x2)
378235c4bbdfSmrg            x = pSprite->physLimits.x2 - 1;
378335c4bbdfSmrg        if (y < pSprite->physLimits.y1)
378435c4bbdfSmrg            y = pSprite->physLimits.y1;
378535c4bbdfSmrg        else if (y >= pSprite->physLimits.y2)
378635c4bbdfSmrg            y = pSprite->physLimits.y2 - 1;
378735c4bbdfSmrg        if (pSprite->hotShape)
378835c4bbdfSmrg            ConfineToShape(dev, pSprite->hotShape, &x, &y);
378935c4bbdfSmrg        (*newScreen->SetCursorPosition) (dev, newScreen, x, y, TRUE);
379035c4bbdfSmrg    }
379135c4bbdfSmrg    else if (!PointerConfinedToScreen(dev)) {
379235c4bbdfSmrg        NewCurrentScreen(dev, newScreen, x, y);
379305b261ecSmrg    }
37947e31ba66Smrg    if (*newScreen->CursorWarpedTo)
37957e31ba66Smrg        (*newScreen->CursorWarpedTo) (dev, newScreen, client,
37967e31ba66Smrg                                      dest, pSprite, x, y);
379705b261ecSmrg    return Success;
379805b261ecSmrg}
379905b261ecSmrg
38004642e01fSmrgstatic Bool
38014642e01fSmrgBorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
380205b261ecSmrg{
380335c4bbdfSmrg    if (RegionNotEmpty(&pWin->borderSize))
380435c4bbdfSmrg        return TRUE;
380505b261ecSmrg
380605b261ecSmrg#ifdef PANORAMIX
380735c4bbdfSmrg    if (!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) {
380835c4bbdfSmrg        int i;
380935c4bbdfSmrg
381035c4bbdfSmrg        FOR_NSCREENS_FORWARD_SKIP(i) {
381135c4bbdfSmrg            if (RegionNotEmpty
381235c4bbdfSmrg                (&pDev->spriteInfo->sprite->windows[i]->borderSize))
381335c4bbdfSmrg                return TRUE;
381435c4bbdfSmrg        }
381535c4bbdfSmrg    }
381605b261ecSmrg#endif
381735c4bbdfSmrg    return FALSE;
381805b261ecSmrg}
381905b261ecSmrg
38204642e01fSmrg/**
382135c4bbdfSmrg * Activate the given passive grab. If the grab is activated successfully, the
382235c4bbdfSmrg * event has been delivered to the client.
38234642e01fSmrg *
382435c4bbdfSmrg * @param device The device of the event to check.
382535c4bbdfSmrg * @param grab The grab to check.
38266747b715Smrg * @param event The current device event.
382735c4bbdfSmrg * @param real_event The original event, in case of touch emulation. The
382835c4bbdfSmrg * real event is the one stored in the sync queue.
382935c4bbdfSmrg *
383035c4bbdfSmrg * @return Whether the grab has been activated.
383105b261ecSmrg */
383235c4bbdfSmrgBool
383335c4bbdfSmrgActivatePassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event,
383435c4bbdfSmrg                    InternalEvent *real_event)
383505b261ecSmrg{
38369ace9065Smrg    SpritePtr pSprite = device->spriteInfo->sprite;
383735c4bbdfSmrg    xEvent *xE = NULL;
383835c4bbdfSmrg    int count;
383935c4bbdfSmrg    int rc;
38406747b715Smrg
384135c4bbdfSmrg    /* The only consumers of corestate are Xi 1.x and core events, which
384235c4bbdfSmrg     * are guaranteed to come from DeviceEvents. */
384335c4bbdfSmrg    if (grab->grabtype == XI || grab->grabtype == CORE) {
384435c4bbdfSmrg        DeviceIntPtr gdev;
384505b261ecSmrg
384635c4bbdfSmrg        event->device_event.corestate &= 0x1f00;
384735c4bbdfSmrg
384835c4bbdfSmrg        if (grab->grabtype == CORE)
384935c4bbdfSmrg            gdev = GetMaster(device, KEYBOARD_OR_FLOAT);
385035c4bbdfSmrg        else
385135c4bbdfSmrg            gdev = grab->modifierDevice;
385235c4bbdfSmrg
385335c4bbdfSmrg        if (gdev && gdev->key && gdev->key->xkbInfo)
385435c4bbdfSmrg            event->device_event.corestate |=
385535c4bbdfSmrg                gdev->key->xkbInfo->state.grab_mods & (~0x1f00);
385635c4bbdfSmrg    }
385735c4bbdfSmrg
385835c4bbdfSmrg    if (grab->grabtype == CORE) {
385935c4bbdfSmrg        rc = EventToCore(event, &xE, &count);
386035c4bbdfSmrg        if (rc != Success) {
386135c4bbdfSmrg            BUG_WARN_MSG(rc != BadMatch, "[dix] %s: core conversion failed"
386235c4bbdfSmrg                         "(%d, %d).\n", device->name, event->any.type, rc);
386335c4bbdfSmrg            return FALSE;
38644642e01fSmrg        }
386535c4bbdfSmrg    }
386635c4bbdfSmrg    else if (grab->grabtype == XI2) {
386735c4bbdfSmrg        rc = EventToXI2(event, &xE);
386835c4bbdfSmrg        if (rc != Success) {
386935c4bbdfSmrg            if (rc != BadMatch)
387035c4bbdfSmrg                BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI2 conversion failed"
387135c4bbdfSmrg                             "(%d, %d).\n", device->name, event->any.type, rc);
387235c4bbdfSmrg            return FALSE;
387335c4bbdfSmrg        }
387435c4bbdfSmrg        count = 1;
387535c4bbdfSmrg    }
387635c4bbdfSmrg    else {
387735c4bbdfSmrg        rc = EventToXI(event, &xE, &count);
387835c4bbdfSmrg        if (rc != Success) {
387935c4bbdfSmrg            if (rc != BadMatch)
388035c4bbdfSmrg                BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI conversion failed"
388135c4bbdfSmrg                             "(%d, %d).\n", device->name, event->any.type, rc);
388235c4bbdfSmrg            return FALSE;
388335c4bbdfSmrg        }
388435c4bbdfSmrg    }
38856747b715Smrg
38865a112b11Smrg    ActivateGrabNoDelivery(device, grab, event, real_event);
38876747b715Smrg
388835c4bbdfSmrg    if (xE) {
388935c4bbdfSmrg        FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
38906747b715Smrg
389135c4bbdfSmrg        /* XXX: XACE? */
389235c4bbdfSmrg        TryClientEvents(rClient(grab), device, xE, count,
389335c4bbdfSmrg                        GetEventFilter(device, xE),
389435c4bbdfSmrg                        GetEventFilter(device, xE), grab);
389535c4bbdfSmrg    }
38966747b715Smrg
389735c4bbdfSmrg    free(xE);
389835c4bbdfSmrg    return TRUE;
389935c4bbdfSmrg}
390035c4bbdfSmrg
39015a112b11Smrg/**
39025a112b11Smrg * Activates a grab without event delivery.
39035a112b11Smrg *
39045a112b11Smrg * @param device The device of the event to check.
39055a112b11Smrg * @param grab The grab to check.
39065a112b11Smrg * @param event The current device event.
39075a112b11Smrg * @param real_event The original event, in case of touch emulation. The
39085a112b11Smrg * real event is the one stored in the sync queue.
39095a112b11Smrg */
39105a112b11Smrgvoid ActivateGrabNoDelivery(DeviceIntPtr dev, GrabPtr grab,
39115a112b11Smrg                            InternalEvent *event, InternalEvent *real_event)
39125a112b11Smrg{
39135a112b11Smrg    GrabInfoPtr grabinfo = &dev->deviceGrab;
39145a112b11Smrg    (*grabinfo->ActivateGrab) (dev, grab,
39155a112b11Smrg                               ClientTimeToServerTime(event->any.time), TRUE);
39165a112b11Smrg
39175a112b11Smrg    if (grabinfo->sync.state == FROZEN_NO_EVENT)
39185a112b11Smrg        grabinfo->sync.state = FROZEN_WITH_EVENT;
391990bea6a0Smrg    CopyPartialInternalEvent(grabinfo->sync.event, real_event);
39205a112b11Smrg}
39215a112b11Smrg
392235c4bbdfSmrgstatic BOOL
392335c4bbdfSmrgCoreGrabInterferes(DeviceIntPtr device, GrabPtr grab)
392435c4bbdfSmrg{
392535c4bbdfSmrg    DeviceIntPtr other;
392635c4bbdfSmrg    BOOL interfering = FALSE;
392735c4bbdfSmrg
392835c4bbdfSmrg    for (other = inputInfo.devices; other; other = other->next) {
392935c4bbdfSmrg        GrabPtr othergrab = other->deviceGrab.grab;
393035c4bbdfSmrg
393135c4bbdfSmrg        if (othergrab && othergrab->grabtype == CORE &&
393235c4bbdfSmrg            SameClient(grab, rClient(othergrab)) &&
393335c4bbdfSmrg            ((IsPointerDevice(grab->device) &&
393435c4bbdfSmrg              IsPointerDevice(othergrab->device)) ||
393535c4bbdfSmrg             (IsKeyboardDevice(grab->device) &&
393635c4bbdfSmrg              IsKeyboardDevice(othergrab->device)))) {
393735c4bbdfSmrg            interfering = TRUE;
393835c4bbdfSmrg            break;
39396747b715Smrg        }
394035c4bbdfSmrg    }
39416747b715Smrg
394235c4bbdfSmrg    return interfering;
394335c4bbdfSmrg}
39444642e01fSmrg
394535c4bbdfSmrgenum MatchFlags {
394635c4bbdfSmrg    NO_MATCH = 0x0,
394735c4bbdfSmrg    CORE_MATCH = 0x1,
394835c4bbdfSmrg    XI_MATCH = 0x2,
394935c4bbdfSmrg    XI2_MATCH = 0x4,
395035c4bbdfSmrg};
39516747b715Smrg
395235c4bbdfSmrg/**
395335c4bbdfSmrg * Match the grab against the temporary grab on the given input level.
395435c4bbdfSmrg * Modifies the temporary grab pointer.
395535c4bbdfSmrg *
395635c4bbdfSmrg * @param grab The grab to match against
395735c4bbdfSmrg * @param tmp The temporary grab to use for matching
395835c4bbdfSmrg * @param level The input level we want to match on
395935c4bbdfSmrg * @param event_type Wire protocol event type
396035c4bbdfSmrg *
396135c4bbdfSmrg * @return The respective matched flag or 0 for no match
396235c4bbdfSmrg */
396335c4bbdfSmrgstatic enum MatchFlags
396435c4bbdfSmrgMatchForType(const GrabPtr grab, GrabPtr tmp, enum InputLevel level,
396535c4bbdfSmrg             int event_type)
396635c4bbdfSmrg{
396735c4bbdfSmrg    enum MatchFlags match;
396835c4bbdfSmrg    BOOL ignore_device = FALSE;
396935c4bbdfSmrg    int grabtype;
397035c4bbdfSmrg    int evtype;
39714642e01fSmrg
397235c4bbdfSmrg    switch (level) {
397335c4bbdfSmrg    case XI2:
397435c4bbdfSmrg        grabtype = XI2;
397535c4bbdfSmrg        evtype = GetXI2Type(event_type);
397635c4bbdfSmrg        BUG_WARN(!evtype);
397735c4bbdfSmrg        match = XI2_MATCH;
397835c4bbdfSmrg        break;
397935c4bbdfSmrg    case XI:
398035c4bbdfSmrg        grabtype = XI;
398135c4bbdfSmrg        evtype = GetXIType(event_type);
398235c4bbdfSmrg        match = XI_MATCH;
398335c4bbdfSmrg        break;
398435c4bbdfSmrg    case CORE:
398535c4bbdfSmrg        grabtype = CORE;
398635c4bbdfSmrg        evtype = GetCoreType(event_type);
398735c4bbdfSmrg        match = CORE_MATCH;
398835c4bbdfSmrg        ignore_device = TRUE;
398935c4bbdfSmrg        break;
399035c4bbdfSmrg    default:
399135c4bbdfSmrg        return NO_MATCH;
399235c4bbdfSmrg    }
399335c4bbdfSmrg
399435c4bbdfSmrg    tmp->grabtype = grabtype;
399535c4bbdfSmrg    tmp->type = evtype;
399635c4bbdfSmrg
399735c4bbdfSmrg    if (tmp->type && GrabMatchesSecond(tmp, grab, ignore_device))
399835c4bbdfSmrg        return match;
399935c4bbdfSmrg
400035c4bbdfSmrg    return NO_MATCH;
400135c4bbdfSmrg}
40024642e01fSmrg
400335c4bbdfSmrg/**
400435c4bbdfSmrg * Check an individual grab against an event to determine if a passive grab
400535c4bbdfSmrg * should be activated.
400635c4bbdfSmrg *
400735c4bbdfSmrg * @param device The device of the event to check.
400835c4bbdfSmrg * @param grab The grab to check.
400935c4bbdfSmrg * @param event The current device event.
401035c4bbdfSmrg * @param checkCore Check for core grabs too.
401135c4bbdfSmrg * @param tempGrab A pre-allocated temporary grab record for matching. This
401235c4bbdfSmrg *        must have the window and device values filled in.
401335c4bbdfSmrg *
401435c4bbdfSmrg * @return Whether the grab matches the event.
401535c4bbdfSmrg */
401635c4bbdfSmrgstatic Bool
401735c4bbdfSmrgCheckPassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event,
401835c4bbdfSmrg                 Bool checkCore, GrabPtr tempGrab)
401935c4bbdfSmrg{
402035c4bbdfSmrg    DeviceIntPtr gdev;
402135c4bbdfSmrg    XkbSrvInfoPtr xkbi = NULL;
402235c4bbdfSmrg    enum MatchFlags match = 0;
402335c4bbdfSmrg    int emulated_type = 0;
40246747b715Smrg
402535c4bbdfSmrg    gdev = grab->modifierDevice;
402635c4bbdfSmrg    if (grab->grabtype == CORE) {
402735c4bbdfSmrg        gdev = GetMaster(device, KEYBOARD_OR_FLOAT);
402835c4bbdfSmrg    }
402935c4bbdfSmrg    else if (grab->grabtype == XI2) {
403035c4bbdfSmrg        /* if the device is an attached slave device, gdev must be the
403135c4bbdfSmrg         * attached master keyboard. Since the slave may have been
403235c4bbdfSmrg         * reattached after the grab, the modifier device may not be the
403335c4bbdfSmrg         * same. */
403435c4bbdfSmrg        if (!IsMaster(grab->device) && !IsFloating(device))
403535c4bbdfSmrg            gdev = GetMaster(device, MASTER_KEYBOARD);
403635c4bbdfSmrg    }
40374642e01fSmrg
403835c4bbdfSmrg    if (gdev && gdev->key)
403935c4bbdfSmrg        xkbi = gdev->key->xkbInfo;
404035c4bbdfSmrg    tempGrab->modifierDevice = grab->modifierDevice;
404135c4bbdfSmrg    tempGrab->modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
404205b261ecSmrg
404335c4bbdfSmrg    /* Check for XI2 and XI grabs first */
404435c4bbdfSmrg    match = MatchForType(grab, tempGrab, XI2, event->any.type);
404505b261ecSmrg
404635c4bbdfSmrg    if (!match && IsTouchEvent(event) &&
404735c4bbdfSmrg        (event->device_event.flags & TOUCH_POINTER_EMULATED)) {
404835c4bbdfSmrg        emulated_type = TouchGetPointerEventType(event);
404935c4bbdfSmrg        match = MatchForType(grab, tempGrab, XI2, emulated_type);
405035c4bbdfSmrg    }
405135c4bbdfSmrg
405235c4bbdfSmrg    if (!match)
405335c4bbdfSmrg        match = MatchForType(grab, tempGrab, XI, event->any.type);
405435c4bbdfSmrg
405535c4bbdfSmrg    if (!match && emulated_type)
405635c4bbdfSmrg        match = MatchForType(grab, tempGrab, XI, emulated_type);
405735c4bbdfSmrg
405835c4bbdfSmrg    if (!match && checkCore) {
405935c4bbdfSmrg        match = MatchForType(grab, tempGrab, CORE, event->any.type);
406035c4bbdfSmrg        if (!match && emulated_type)
406135c4bbdfSmrg            match = MatchForType(grab, tempGrab, CORE, emulated_type);
406235c4bbdfSmrg    }
406335c4bbdfSmrg
406435c4bbdfSmrg    if (!match || (grab->confineTo &&
406535c4bbdfSmrg                   (!grab->confineTo->realized ||
406635c4bbdfSmrg                    !BorderSizeNotEmpty(device, grab->confineTo))))
406735c4bbdfSmrg        return FALSE;
406835c4bbdfSmrg
406935c4bbdfSmrg    /* In some cases a passive core grab may exist, but the client
407035c4bbdfSmrg     * already has a core grab on some other device. In this case we
407135c4bbdfSmrg     * must not get the grab, otherwise we may never ungrab the
407235c4bbdfSmrg     * device.
407335c4bbdfSmrg     */
407435c4bbdfSmrg
407535c4bbdfSmrg    if (grab->grabtype == CORE) {
407635c4bbdfSmrg        /* A passive grab may have been created for a different device
407735c4bbdfSmrg           than it is assigned to at this point in time.
407835c4bbdfSmrg           Update the grab's device and modifier device to reflect the
407935c4bbdfSmrg           current state.
408035c4bbdfSmrg           Since XGrabDeviceButton requires to specify the
408135c4bbdfSmrg           modifierDevice explicitly, we don't override this choice.
408235c4bbdfSmrg         */
408335c4bbdfSmrg        if (grab->type < GenericEvent) {
408435c4bbdfSmrg            grab->device = device;
408535c4bbdfSmrg            grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD);
408635c4bbdfSmrg        }
408735c4bbdfSmrg
408835c4bbdfSmrg        if (CoreGrabInterferes(device, grab))
408935c4bbdfSmrg            return FALSE;
409035c4bbdfSmrg    }
409135c4bbdfSmrg
409235c4bbdfSmrg    return TRUE;
409335c4bbdfSmrg}
409435c4bbdfSmrg
409535c4bbdfSmrg/**
409635c4bbdfSmrg * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
409735c4bbdfSmrg * passive grab set on the window to be activated.
409835c4bbdfSmrg * If activate is true and a passive grab is found, it will be activated,
409935c4bbdfSmrg * and the event will be delivered to the client.
410035c4bbdfSmrg *
410135c4bbdfSmrg * @param pWin The window that may be subject to a passive grab.
410235c4bbdfSmrg * @param device Device that caused the event.
410335c4bbdfSmrg * @param event The current device event.
410435c4bbdfSmrg * @param checkCore Check for core grabs too.
410535c4bbdfSmrg * @param activate If a grab is found, activate it and deliver the event.
410635c4bbdfSmrg */
410735c4bbdfSmrg
410835c4bbdfSmrgGrabPtr
410935c4bbdfSmrgCheckPassiveGrabsOnWindow(WindowPtr pWin,
411035c4bbdfSmrg                          DeviceIntPtr device,
411135c4bbdfSmrg                          InternalEvent *event, BOOL checkCore, BOOL activate)
411235c4bbdfSmrg{
411335c4bbdfSmrg    GrabPtr grab = wPassiveGrabs(pWin);
411435c4bbdfSmrg    GrabPtr tempGrab;
411535c4bbdfSmrg
411635c4bbdfSmrg    if (!grab)
411735c4bbdfSmrg        return NULL;
411835c4bbdfSmrg
411935c4bbdfSmrg    tempGrab = AllocGrab(NULL);
412035c4bbdfSmrg    if (tempGrab == NULL)
412135c4bbdfSmrg        return NULL;
412235c4bbdfSmrg
412335c4bbdfSmrg    /* Fill out the grab details, but leave the type for later before
412435c4bbdfSmrg     * comparing */
412535c4bbdfSmrg    switch (event->any.type) {
412635c4bbdfSmrg    case ET_KeyPress:
412735c4bbdfSmrg    case ET_KeyRelease:
412835c4bbdfSmrg        tempGrab->detail.exact = event->device_event.detail.key;
412935c4bbdfSmrg        break;
413035c4bbdfSmrg    case ET_ButtonPress:
413135c4bbdfSmrg    case ET_ButtonRelease:
413235c4bbdfSmrg    case ET_TouchBegin:
413335c4bbdfSmrg    case ET_TouchEnd:
413435c4bbdfSmrg        tempGrab->detail.exact = event->device_event.detail.button;
413535c4bbdfSmrg        break;
413635c4bbdfSmrg    default:
413735c4bbdfSmrg        tempGrab->detail.exact = 0;
413835c4bbdfSmrg        break;
413935c4bbdfSmrg    }
414035c4bbdfSmrg    tempGrab->window = pWin;
414135c4bbdfSmrg    tempGrab->device = device;
414235c4bbdfSmrg    tempGrab->detail.pMask = NULL;
414335c4bbdfSmrg    tempGrab->modifiersDetail.pMask = NULL;
414435c4bbdfSmrg    tempGrab->next = NULL;
414535c4bbdfSmrg
414635c4bbdfSmrg    for (; grab; grab = grab->next) {
414735c4bbdfSmrg        if (!CheckPassiveGrab(device, grab, event, checkCore, tempGrab))
414835c4bbdfSmrg            continue;
414935c4bbdfSmrg
415035c4bbdfSmrg        if (activate && !ActivatePassiveGrab(device, grab, event, event))
415135c4bbdfSmrg            continue;
41526747b715Smrg
415335c4bbdfSmrg        break;
415405b261ecSmrg    }
415535c4bbdfSmrg
415635c4bbdfSmrg    FreeGrab(tempGrab);
415735c4bbdfSmrg    return grab;
415805b261ecSmrg}
415905b261ecSmrg
416005b261ecSmrg/**
416105b261ecSmrg * CheckDeviceGrabs handles both keyboard and pointer events that may cause
41624642e01fSmrg * a passive grab to be activated.
416305b261ecSmrg *
416405b261ecSmrg * If the event is a keyboard event, the ancestors of the focus window are
416505b261ecSmrg * traced down and tried to see if they have any passive grabs to be
41665a112b11Smrg * activated.  If the focus window itself is reached and its descendants
416705b261ecSmrg * contain the pointer, the ancestors of the window that the pointer is in
416805b261ecSmrg * are then traced down starting at the focus window, otherwise no grabs are
41694642e01fSmrg * activated.
417005b261ecSmrg * If the event is a pointer event, the ancestors of the window that the
417105b261ecSmrg * pointer is in are traced down starting at the root until CheckPassiveGrabs
417205b261ecSmrg * causes a passive grab to activate or all the windows are
417305b261ecSmrg * tried. PRH
417405b261ecSmrg *
417505b261ecSmrg * If a grab is activated, the event has been sent to the client already!
417605b261ecSmrg *
41774642e01fSmrg * The event we pass in must always be an XI event. From this, we then emulate
41784642e01fSmrg * the core event and then check for grabs.
41794642e01fSmrg *
418005b261ecSmrg * @param device The device that caused the event.
41814642e01fSmrg * @param xE The event to handle (Device{Button|Key}Press).
418205b261ecSmrg * @param count Number of events in list.
418305b261ecSmrg * @return TRUE if a grab has been activated or false otherwise.
418405b261ecSmrg*/
418505b261ecSmrg
418605b261ecSmrgBool
41875a112b11SmrgCheckDeviceGrabs(DeviceIntPtr device, InternalEvent *ievent, WindowPtr ancestor)
418805b261ecSmrg{
418905b261ecSmrg    int i;
419005b261ecSmrg    WindowPtr pWin = NULL;
419135c4bbdfSmrg    FocusClassPtr focus =
41925a112b11Smrg        IsPointerEvent(ievent) ? NULL : device->focus;
41936747b715Smrg    BOOL sendCore = (IsMaster(device) && device->coreEvents);
419435c4bbdfSmrg    Bool ret = FALSE;
41955a112b11Smrg    DeviceEvent *event = &ievent->device_event;
419605b261ecSmrg
419735c4bbdfSmrg    if (event->type != ET_ButtonPress && event->type != ET_KeyPress)
41984642e01fSmrg        return FALSE;
41994642e01fSmrg
420035c4bbdfSmrg    if (event->type == ET_ButtonPress && (device->button->buttonsDown != 1))
420135c4bbdfSmrg        return FALSE;
42024642e01fSmrg
42039ace9065Smrg    if (device->deviceGrab.grab)
42049ace9065Smrg        return FALSE;
42059ace9065Smrg
42069ace9065Smrg    i = 0;
420735c4bbdfSmrg    if (ancestor) {
42089ace9065Smrg        while (i < device->spriteInfo->sprite->spriteTraceGood)
42099ace9065Smrg            if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor)
42109ace9065Smrg                break;
42119ace9065Smrg        if (i == device->spriteInfo->sprite->spriteTraceGood)
421235c4bbdfSmrg            goto out;
42139ace9065Smrg    }
421405b261ecSmrg
421535c4bbdfSmrg    if (focus) {
421635c4bbdfSmrg        for (; i < focus->traceGood; i++) {
421735c4bbdfSmrg            pWin = focus->trace[i];
42185a112b11Smrg            if (CheckPassiveGrabsOnWindow(pWin, device, ievent,
421935c4bbdfSmrg                                          sendCore, TRUE)) {
422035c4bbdfSmrg                ret = TRUE;
422135c4bbdfSmrg                goto out;
422235c4bbdfSmrg            }
422335c4bbdfSmrg        }
42244642e01fSmrg
422535c4bbdfSmrg        if ((focus->win == NoneWin) ||
422635c4bbdfSmrg            (i >= device->spriteInfo->sprite->spriteTraceGood) ||
422735c4bbdfSmrg            (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i - 1]))
422835c4bbdfSmrg            goto out;
422905b261ecSmrg    }
423005b261ecSmrg
423135c4bbdfSmrg    for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) {
423235c4bbdfSmrg        pWin = device->spriteInfo->sprite->spriteTrace[i];
42335a112b11Smrg        if (CheckPassiveGrabsOnWindow(pWin, device, ievent,
423435c4bbdfSmrg                                      sendCore, TRUE)) {
423535c4bbdfSmrg            ret = TRUE;
423635c4bbdfSmrg            goto out;
423735c4bbdfSmrg        }
423805b261ecSmrg    }
423905b261ecSmrg
424035c4bbdfSmrg out:
424135c4bbdfSmrg    if (ret == TRUE && event->type == ET_KeyPress)
424235c4bbdfSmrg        device->deviceGrab.activatingKey = event->detail.key;
424335c4bbdfSmrg    return ret;
424405b261ecSmrg}
424505b261ecSmrg
424605b261ecSmrg/**
424705b261ecSmrg * Called for keyboard events to deliver event to whatever client owns the
42486747b715Smrg * focus.
42496747b715Smrg *
42506747b715Smrg * The event is delivered to the keyboard's focus window, the root window or
42516747b715Smrg * to the window owning the input focus.
425205b261ecSmrg *
425305b261ecSmrg * @param keybd The keyboard originating the event.
42546747b715Smrg * @param event The event, not yet in wire format.
425505b261ecSmrg * @param window Window underneath the sprite.
425605b261ecSmrg */
425705b261ecSmrgvoid
42586747b715SmrgDeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
425905b261ecSmrg{
42606747b715Smrg    DeviceIntPtr ptr;
426105b261ecSmrg    WindowPtr focus = keybd->focus->win;
42626747b715Smrg    BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents);
426335c4bbdfSmrg    xEvent *core = NULL, *xE = NULL, *xi2 = NULL;
42646747b715Smrg    int count, rc;
42654642e01fSmrg    int deliveries = 0;
426605b261ecSmrg
426705b261ecSmrg    if (focus == FollowKeyboardWin)
426835c4bbdfSmrg        focus = inputInfo.keyboard->focus->win;
426905b261ecSmrg    if (!focus)
427035c4bbdfSmrg        return;
427135c4bbdfSmrg    if (focus == PointerRootWin) {
427235c4bbdfSmrg        DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd);
427335c4bbdfSmrg        return;
427405b261ecSmrg    }
427535c4bbdfSmrg    if ((focus == window) || IsParent(focus, window)) {
427635c4bbdfSmrg        if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd))
427735c4bbdfSmrg            return;
427805b261ecSmrg    }
42794642e01fSmrg
428005b261ecSmrg    /* just deliver it to the focus window */
428135c4bbdfSmrg    ptr = GetMaster(keybd, POINTER_OR_FLOAT);
42826747b715Smrg
42836747b715Smrg    rc = EventToXI2(event, &xi2);
428435c4bbdfSmrg    if (rc == Success) {
42856747b715Smrg        /* XXX: XACE */
42866747b715Smrg        int filter = GetEventFilter(keybd, xi2);
428735c4bbdfSmrg
42889ace9065Smrg        FixUpEventFromWindow(ptr->spriteInfo->sprite, xi2, focus, None, FALSE);
42896747b715Smrg        deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1,
42906747b715Smrg                                           filter, NullGrab);
42916747b715Smrg        if (deliveries > 0)
42926747b715Smrg            goto unwind;
429335c4bbdfSmrg    }
429435c4bbdfSmrg    else if (rc != BadMatch)
429535c4bbdfSmrg        ErrorF
429635c4bbdfSmrg            ("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n",
429735c4bbdfSmrg             keybd->name, event->any.type, rc);
42986747b715Smrg
42996747b715Smrg    rc = EventToXI(event, &xE, &count);
43006747b715Smrg    if (rc == Success &&
430135c4bbdfSmrg        XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success) {
43029ace9065Smrg        FixUpEventFromWindow(ptr->spriteInfo->sprite, xE, focus, None, FALSE);
43036747b715Smrg        deliveries = DeliverEventsToWindow(keybd, focus, xE, count,
430435c4bbdfSmrg                                           GetEventFilter(keybd, xE), NullGrab);
43056747b715Smrg
43066747b715Smrg        if (deliveries > 0)
43076747b715Smrg            goto unwind;
430835c4bbdfSmrg    }
430935c4bbdfSmrg    else if (rc != BadMatch)
431035c4bbdfSmrg        ErrorF
431135c4bbdfSmrg            ("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n",
431235c4bbdfSmrg             keybd->name, event->any.type, rc);
43134642e01fSmrg
431435c4bbdfSmrg    if (sendCore) {
431535c4bbdfSmrg        rc = EventToCore(event, &core, &count);
43166747b715Smrg        if (rc == Success) {
431735c4bbdfSmrg            if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, core, count) ==
431835c4bbdfSmrg                Success) {
431935c4bbdfSmrg                FixUpEventFromWindow(keybd->spriteInfo->sprite, core, focus,
43209ace9065Smrg                                     None, FALSE);
432135c4bbdfSmrg                deliveries =
432235c4bbdfSmrg                    DeliverEventsToWindow(keybd, focus, core, count,
432335c4bbdfSmrg                                          GetEventFilter(keybd, core),
432435c4bbdfSmrg                                          NullGrab);
43256747b715Smrg            }
432635c4bbdfSmrg        }
432735c4bbdfSmrg        else if (rc != BadMatch)
432835c4bbdfSmrg            ErrorF
432935c4bbdfSmrg                ("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n",
433035c4bbdfSmrg                 keybd->name, event->any.type, rc);
43314642e01fSmrg    }
43326747b715Smrg
433335c4bbdfSmrg unwind:
433435c4bbdfSmrg    free(core);
43356747b715Smrg    free(xE);
43366747b715Smrg    free(xi2);
43376747b715Smrg    return;
433805b261ecSmrg}
433905b261ecSmrg
434035c4bbdfSmrgint
434135c4bbdfSmrgDeliverOneGrabbedEvent(InternalEvent *event, DeviceIntPtr dev,
434235c4bbdfSmrg                       enum InputLevel level)
434335c4bbdfSmrg{
434435c4bbdfSmrg    SpritePtr pSprite = dev->spriteInfo->sprite;
434535c4bbdfSmrg    int rc;
434635c4bbdfSmrg    xEvent *xE = NULL;
434735c4bbdfSmrg    int count = 0;
434835c4bbdfSmrg    int deliveries = 0;
434935c4bbdfSmrg    Mask mask;
435035c4bbdfSmrg    GrabInfoPtr grabinfo = &dev->deviceGrab;
435135c4bbdfSmrg    GrabPtr grab = grabinfo->grab;
435235c4bbdfSmrg    Mask filter;
435335c4bbdfSmrg
435435c4bbdfSmrg    if (grab->grabtype != level)
435535c4bbdfSmrg        return 0;
435635c4bbdfSmrg
435735c4bbdfSmrg    switch (level) {
435835c4bbdfSmrg    case XI2:
435935c4bbdfSmrg        rc = EventToXI2(event, &xE);
436035c4bbdfSmrg        count = 1;
436135c4bbdfSmrg        if (rc == Success) {
436235c4bbdfSmrg            int evtype = xi2_get_type(xE);
436335c4bbdfSmrg
436435c4bbdfSmrg            mask = GetXI2MaskByte(grab->xi2mask, dev, evtype);
436535c4bbdfSmrg            filter = GetEventFilter(dev, xE);
436635c4bbdfSmrg        }
436735c4bbdfSmrg        break;
436835c4bbdfSmrg    case XI:
436935c4bbdfSmrg        if (grabinfo->fromPassiveGrab && grabinfo->implicitGrab)
437035c4bbdfSmrg            mask = grab->deviceMask;
437135c4bbdfSmrg        else
437235c4bbdfSmrg            mask = grab->eventMask;
437335c4bbdfSmrg        rc = EventToXI(event, &xE, &count);
437435c4bbdfSmrg        if (rc == Success)
437535c4bbdfSmrg            filter = GetEventFilter(dev, xE);
437635c4bbdfSmrg        break;
437735c4bbdfSmrg    case CORE:
437835c4bbdfSmrg        rc = EventToCore(event, &xE, &count);
437935c4bbdfSmrg        mask = grab->eventMask;
438035c4bbdfSmrg        if (rc == Success)
438135c4bbdfSmrg            filter = GetEventFilter(dev, xE);
438235c4bbdfSmrg        break;
438335c4bbdfSmrg    default:
438435c4bbdfSmrg        BUG_WARN_MSG(1, "Invalid input level %d\n", level);
438535c4bbdfSmrg        return 0;
438635c4bbdfSmrg    }
438735c4bbdfSmrg
438835c4bbdfSmrg    if (rc == Success) {
438935c4bbdfSmrg        FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
439035c4bbdfSmrg        if (XaceHook(XACE_SEND_ACCESS, 0, dev,
439135c4bbdfSmrg                     grab->window, xE, count) ||
439235c4bbdfSmrg            XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
439335c4bbdfSmrg                     grab->window, xE, count))
439435c4bbdfSmrg            deliveries = 1;     /* don't send, but pretend we did */
439535c4bbdfSmrg        else if (level != CORE || !IsInterferingGrab(rClient(grab), dev, xE)) {
439635c4bbdfSmrg            deliveries = TryClientEvents(rClient(grab), dev,
439735c4bbdfSmrg                                         xE, count, mask, filter, grab);
439835c4bbdfSmrg        }
439935c4bbdfSmrg    }
440035c4bbdfSmrg    else
440135c4bbdfSmrg        BUG_WARN_MSG(rc != BadMatch,
440235c4bbdfSmrg                     "%s: conversion to mode %d failed on %d with %d\n",
440335c4bbdfSmrg                     dev->name, level, event->any.type, rc);
440435c4bbdfSmrg
440535c4bbdfSmrg    free(xE);
440635c4bbdfSmrg    return deliveries;
440735c4bbdfSmrg}
440835c4bbdfSmrg
440905b261ecSmrg/**
441005b261ecSmrg * Deliver an event from a device that is currently grabbed. Uses
441105b261ecSmrg * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the
441205b261ecSmrg * grab. If not, TryClientEvents() is used.
441305b261ecSmrg *
441405b261ecSmrg * @param deactivateGrab True if the device's grab should be deactivated.
441535c4bbdfSmrg *
441635c4bbdfSmrg * @return The number of events delivered.
441705b261ecSmrg */
441835c4bbdfSmrgint
44196747b715SmrgDeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
44206747b715Smrg                    Bool deactivateGrab)
442105b261ecSmrg{
44224642e01fSmrg    GrabPtr grab;
44234642e01fSmrg    GrabInfoPtr grabinfo;
442405b261ecSmrg    int deliveries = 0;
44254642e01fSmrg    SpritePtr pSprite = thisDev->spriteInfo->sprite;
44264642e01fSmrg    BOOL sendCore = FALSE;
44274642e01fSmrg
44284642e01fSmrg    grabinfo = &thisDev->deviceGrab;
44294642e01fSmrg    grab = grabinfo->grab;
443005b261ecSmrg
443135c4bbdfSmrg    if (grab->ownerEvents) {
443235c4bbdfSmrg        WindowPtr focus;
443305b261ecSmrg
44344642e01fSmrg        /* Hack: Some pointer device have a focus class. So we need to check
44354642e01fSmrg         * for the type of event, to see if we really want to deliver it to
44364642e01fSmrg         * the focus window. For pointer events, the answer is no.
44374642e01fSmrg         */
44386747b715Smrg        if (IsPointerEvent(event))
44394642e01fSmrg            focus = PointerRootWin;
444035c4bbdfSmrg        else if (thisDev->focus) {
444135c4bbdfSmrg            focus = thisDev->focus->win;
444235c4bbdfSmrg            if (focus == FollowKeyboardWin)
444335c4bbdfSmrg                focus = inputInfo.keyboard->focus->win;
444435c4bbdfSmrg        }
444535c4bbdfSmrg        else
444635c4bbdfSmrg            focus = PointerRootWin;
444735c4bbdfSmrg        if (focus == PointerRootWin)
444835c4bbdfSmrg            deliveries = DeliverDeviceEvents(pSprite->win, event, grab,
44496747b715Smrg                                             NullWindow, thisDev);
445035c4bbdfSmrg        else if (focus && (focus == pSprite->win ||
445135c4bbdfSmrg                           IsParent(focus, pSprite->win)))
445235c4bbdfSmrg            deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus,
445335c4bbdfSmrg                                             thisDev);
445435c4bbdfSmrg        else if (focus)
445535c4bbdfSmrg            deliveries = DeliverDeviceEvents(focus, event, grab, focus,
445635c4bbdfSmrg                                             thisDev);
445735c4bbdfSmrg    }
445835c4bbdfSmrg    if (!deliveries) {
44596747b715Smrg        sendCore = (IsMaster(thisDev) && thisDev->coreEvents);
44606747b715Smrg        /* try core event */
446135c4bbdfSmrg        if ((sendCore && grab->grabtype == CORE) || grab->grabtype != CORE)
446235c4bbdfSmrg            deliveries = DeliverOneGrabbedEvent(event, thisDev, grab->grabtype);
44636747b715Smrg
44646747b715Smrg        if (deliveries && (event->any.type == ET_Motion))
44654642e01fSmrg            thisDev->valuator->motionHintWindow = grab->window;
446605b261ecSmrg    }
446735c4bbdfSmrg    if (deliveries && !deactivateGrab &&
446835c4bbdfSmrg        (event->any.type == ET_KeyPress ||
446935c4bbdfSmrg         event->any.type == ET_KeyRelease ||
447035c4bbdfSmrg         event->any.type == ET_ButtonPress ||
447135c4bbdfSmrg         event->any.type == ET_ButtonRelease)) {
44725a112b11Smrg        FreezeThisEventIfNeededForSyncGrab(thisDev, event);
447305b261ecSmrg    }
447405b261ecSmrg
447535c4bbdfSmrg    return deliveries;
44766747b715Smrg}
447705b261ecSmrg
44785a112b11Smrgvoid
44795a112b11SmrgFreezeThisEventIfNeededForSyncGrab(DeviceIntPtr thisDev, InternalEvent *event)
44805a112b11Smrg{
44815a112b11Smrg    GrabInfoPtr grabinfo = &thisDev->deviceGrab;
44825a112b11Smrg    GrabPtr grab = grabinfo->grab;
44835a112b11Smrg    DeviceIntPtr dev;
44845a112b11Smrg
44855a112b11Smrg    switch (grabinfo->sync.state) {
44865a112b11Smrg    case FREEZE_BOTH_NEXT_EVENT:
44875a112b11Smrg        dev = GetPairedDevice(thisDev);
44885a112b11Smrg        if (dev) {
44895a112b11Smrg            FreezeThaw(dev, TRUE);
44905a112b11Smrg            if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) &&
44915a112b11Smrg                (CLIENT_BITS(grab->resource) ==
44925a112b11Smrg                 CLIENT_BITS(dev->deviceGrab.grab->resource)))
44935a112b11Smrg                dev->deviceGrab.sync.state = FROZEN_NO_EVENT;
44945a112b11Smrg            else
44955a112b11Smrg                dev->deviceGrab.sync.other = grab;
44965a112b11Smrg        }
44975a112b11Smrg        /* fall through */
44985a112b11Smrg    case FREEZE_NEXT_EVENT:
44995a112b11Smrg        grabinfo->sync.state = FROZEN_WITH_EVENT;
45005a112b11Smrg        FreezeThaw(thisDev, TRUE);
450190bea6a0Smrg        CopyPartialInternalEvent(grabinfo->sync.event, event);
45025a112b11Smrg        break;
45035a112b11Smrg    }
45045a112b11Smrg}
45055a112b11Smrg
45066747b715Smrg/* This function is used to set the key pressed or key released state -
45076747b715Smrg   this is only used when the pressing of keys does not cause
45086747b715Smrg   the device's processInputProc to be called, as in for example Mouse Keys.
45096747b715Smrg*/
45106747b715Smrgvoid
451135c4bbdfSmrgFixKeyState(DeviceEvent *event, DeviceIntPtr keybd)
45126747b715Smrg{
45136747b715Smrg    int key = event->detail.key;
45146747b715Smrg
45156747b715Smrg    if (event->type == ET_KeyPress) {
451635c4bbdfSmrg        DebugF("FixKeyState: Key %d %s\n", key,
45176747b715Smrg               ((event->type == ET_KeyPress) ? "down" : "up"));
451805b261ecSmrg    }
45194642e01fSmrg
45206747b715Smrg    if (event->type == ET_KeyPress)
45216747b715Smrg        set_key_down(keybd, key, KEY_PROCESSED);
45226747b715Smrg    else if (event->type == ET_KeyRelease)
45236747b715Smrg        set_key_up(keybd, key, KEY_PROCESSED);
452405b261ecSmrg    else
45256747b715Smrg        FatalError("Impossible keyboard event");
452605b261ecSmrg}
452705b261ecSmrg
452805b261ecSmrg#define AtMostOneClient \
452905b261ecSmrg	(SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
45304642e01fSmrg#define ManagerMask \
45314642e01fSmrg	(SubstructureRedirectMask | ResizeRedirectMask)
453205b261ecSmrg
453305b261ecSmrg/**
453405b261ecSmrg * Recalculate which events may be deliverable for the given window.
453505b261ecSmrg * Recalculated mask is used for quicker determination which events may be
453605b261ecSmrg * delivered to a window.
453705b261ecSmrg *
453805b261ecSmrg * The otherEventMasks on a WindowOptional is the combination of all event
453905b261ecSmrg * masks set by all clients on the window.
454005b261ecSmrg * deliverableEventMask is the combination of the eventMask and the
45416747b715Smrg * otherEventMask plus the events that may be propagated to the parent.
454205b261ecSmrg *
454305b261ecSmrg * Traverses to siblings and parents of the window.
454405b261ecSmrg */
454505b261ecSmrgvoid
45466747b715SmrgRecalculateDeliverableEvents(WindowPtr pWin)
454705b261ecSmrg{
454805b261ecSmrg    OtherClients *others;
454905b261ecSmrg    WindowPtr pChild;
455005b261ecSmrg
455105b261ecSmrg    pChild = pWin;
455235c4bbdfSmrg    while (1) {
455335c4bbdfSmrg        if (pChild->optional) {
455435c4bbdfSmrg            pChild->optional->otherEventMasks = 0;
455535c4bbdfSmrg            for (others = wOtherClients(pChild); others; others = others->next) {
455635c4bbdfSmrg                pChild->optional->otherEventMasks |= others->mask;
455735c4bbdfSmrg            }
455835c4bbdfSmrg        }
455935c4bbdfSmrg        pChild->deliverableEvents = pChild->eventMask |
456035c4bbdfSmrg            wOtherEventMasks(pChild);
456135c4bbdfSmrg        if (pChild->parent)
456235c4bbdfSmrg            pChild->deliverableEvents |=
456335c4bbdfSmrg                (pChild->parent->deliverableEvents &
456435c4bbdfSmrg                 ~wDontPropagateMask(pChild) & PropagateMask);
456535c4bbdfSmrg        if (pChild->firstChild) {
456635c4bbdfSmrg            pChild = pChild->firstChild;
456735c4bbdfSmrg            continue;
456835c4bbdfSmrg        }
456935c4bbdfSmrg        while (!pChild->nextSib && (pChild != pWin))
457035c4bbdfSmrg            pChild = pChild->parent;
457135c4bbdfSmrg        if (pChild == pWin)
457235c4bbdfSmrg            break;
457335c4bbdfSmrg        pChild = pChild->nextSib;
457405b261ecSmrg    }
457505b261ecSmrg}
457605b261ecSmrg
457705b261ecSmrg/**
457805b261ecSmrg *
457905b261ecSmrg *  \param value must conform to DeleteType
458005b261ecSmrg */
458105b261ecSmrgint
458235c4bbdfSmrgOtherClientGone(void *value, XID id)
458305b261ecSmrg{
458405b261ecSmrg    OtherClientsPtr other, prev;
458535c4bbdfSmrg    WindowPtr pWin = (WindowPtr) value;
458605b261ecSmrg
458705b261ecSmrg    prev = 0;
458835c4bbdfSmrg    for (other = wOtherClients(pWin); other; other = other->next) {
458935c4bbdfSmrg        if (other->resource == id) {
459035c4bbdfSmrg            if (prev)
459135c4bbdfSmrg                prev->next = other->next;
459235c4bbdfSmrg            else {
459335c4bbdfSmrg                if (!(pWin->optional->otherClients = other->next))
459435c4bbdfSmrg                    CheckWindowOptionalNeed(pWin);
459535c4bbdfSmrg            }
459635c4bbdfSmrg            free(other);
459735c4bbdfSmrg            RecalculateDeliverableEvents(pWin);
459835c4bbdfSmrg            return Success;
459935c4bbdfSmrg        }
460035c4bbdfSmrg        prev = other;
460105b261ecSmrg    }
460205b261ecSmrg    FatalError("client not on event list");
460305b261ecSmrg}
460405b261ecSmrg
460505b261ecSmrgint
460605b261ecSmrgEventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
460705b261ecSmrg{
460805b261ecSmrg    Mask check;
460935c4bbdfSmrg    OtherClients *others;
46104642e01fSmrg    DeviceIntPtr dev;
46114642e01fSmrg    int rc;
461205b261ecSmrg
461335c4bbdfSmrg    if (mask & ~AllEventMasks) {
461435c4bbdfSmrg        client->errorValue = mask;
461535c4bbdfSmrg        return BadValue;
461605b261ecSmrg    }
46174642e01fSmrg    check = (mask & ManagerMask);
46184642e01fSmrg    if (check) {
461935c4bbdfSmrg        rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id,
462035c4bbdfSmrg                      RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess);
462135c4bbdfSmrg        if (rc != Success)
462235c4bbdfSmrg            return rc;
46234642e01fSmrg    }
462405b261ecSmrg    check = (mask & AtMostOneClient);
462535c4bbdfSmrg    if (check & (pWin->eventMask | wOtherEventMasks(pWin))) {
462635c4bbdfSmrg        /* It is illegal for two different clients to select on any of the
462735c4bbdfSmrg           events for AtMostOneClient. However, it is OK, for some client to
462835c4bbdfSmrg           continue selecting on one of those events.  */
462935c4bbdfSmrg        if ((wClient(pWin) != client) && (check & pWin->eventMask))
463035c4bbdfSmrg            return BadAccess;
463135c4bbdfSmrg        for (others = wOtherClients(pWin); others; others = others->next) {
463235c4bbdfSmrg            if (!SameClient(others, client) && (check & others->mask))
463335c4bbdfSmrg                return BadAccess;
463435c4bbdfSmrg        }
463505b261ecSmrg    }
463635c4bbdfSmrg    if (wClient(pWin) == client) {
463735c4bbdfSmrg        check = pWin->eventMask;
463835c4bbdfSmrg        pWin->eventMask = mask;
463935c4bbdfSmrg    }
464035c4bbdfSmrg    else {
464135c4bbdfSmrg        for (others = wOtherClients(pWin); others; others = others->next) {
464235c4bbdfSmrg            if (SameClient(others, client)) {
464335c4bbdfSmrg                check = others->mask;
464435c4bbdfSmrg                if (mask == 0) {
464535c4bbdfSmrg                    FreeResource(others->resource, RT_NONE);
464635c4bbdfSmrg                    return Success;
464735c4bbdfSmrg                }
464835c4bbdfSmrg                else
464935c4bbdfSmrg                    others->mask = mask;
465035c4bbdfSmrg                goto maskSet;
465135c4bbdfSmrg            }
465235c4bbdfSmrg        }
465335c4bbdfSmrg        check = 0;
465435c4bbdfSmrg        if (!pWin->optional && !MakeWindowOptional(pWin))
465535c4bbdfSmrg            return BadAlloc;
465635c4bbdfSmrg        others = malloc(sizeof(OtherClients));
465735c4bbdfSmrg        if (!others)
465835c4bbdfSmrg            return BadAlloc;
465935c4bbdfSmrg        others->mask = mask;
466035c4bbdfSmrg        others->resource = FakeClientID(client->index);
466135c4bbdfSmrg        others->next = pWin->optional->otherClients;
466235c4bbdfSmrg        pWin->optional->otherClients = others;
466335c4bbdfSmrg        if (!AddResource(others->resource, RT_OTHERCLIENT, (void *) pWin))
466435c4bbdfSmrg            return BadAlloc;
466535c4bbdfSmrg    }
466635c4bbdfSmrg maskSet:
466735c4bbdfSmrg    if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask)) {
466835c4bbdfSmrg        for (dev = inputInfo.devices; dev; dev = dev->next) {
46694642e01fSmrg            if (dev->valuator && dev->valuator->motionHintWindow == pWin)
46704642e01fSmrg                dev->valuator->motionHintWindow = NullWindow;
46714642e01fSmrg        }
46724642e01fSmrg    }
467305b261ecSmrg    RecalculateDeliverableEvents(pWin);
467405b261ecSmrg    return Success;
467505b261ecSmrg}
467605b261ecSmrg
467705b261ecSmrgint
46784642e01fSmrgEventSuppressForWindow(WindowPtr pWin, ClientPtr client,
467905b261ecSmrg                       Mask mask, Bool *checkOptional)
468005b261ecSmrg{
468135c4bbdfSmrg    int i, freed;
468205b261ecSmrg
468335c4bbdfSmrg    if (mask & ~PropagateMask) {
468435c4bbdfSmrg        client->errorValue = mask;
468535c4bbdfSmrg        return BadValue;
468605b261ecSmrg    }
468705b261ecSmrg    if (pWin->dontPropagate)
468835c4bbdfSmrg        DontPropagateRefCnts[pWin->dontPropagate]--;
468905b261ecSmrg    if (!mask)
469035c4bbdfSmrg        i = 0;
469135c4bbdfSmrg    else {
469235c4bbdfSmrg        for (i = DNPMCOUNT, freed = 0; --i > 0;) {
469335c4bbdfSmrg            if (!DontPropagateRefCnts[i])
469435c4bbdfSmrg                freed = i;
469535c4bbdfSmrg            else if (mask == DontPropagateMasks[i])
469635c4bbdfSmrg                break;
469735c4bbdfSmrg        }
469835c4bbdfSmrg        if (!i && freed) {
469935c4bbdfSmrg            i = freed;
470035c4bbdfSmrg            DontPropagateMasks[i] = mask;
470135c4bbdfSmrg        }
470205b261ecSmrg    }
470335c4bbdfSmrg    if (i || !mask) {
470435c4bbdfSmrg        pWin->dontPropagate = i;
470535c4bbdfSmrg        if (i)
470635c4bbdfSmrg            DontPropagateRefCnts[i]++;
470735c4bbdfSmrg        if (pWin->optional) {
470835c4bbdfSmrg            pWin->optional->dontPropagateMask = mask;
470935c4bbdfSmrg            *checkOptional = TRUE;
471035c4bbdfSmrg        }
471135c4bbdfSmrg    }
471235c4bbdfSmrg    else {
471335c4bbdfSmrg        if (!pWin->optional && !MakeWindowOptional(pWin)) {
471435c4bbdfSmrg            if (pWin->dontPropagate)
471535c4bbdfSmrg                DontPropagateRefCnts[pWin->dontPropagate]++;
471635c4bbdfSmrg            return BadAlloc;
471735c4bbdfSmrg        }
471835c4bbdfSmrg        pWin->dontPropagate = 0;
471905b261ecSmrg        pWin->optional->dontPropagateMask = mask;
472005b261ecSmrg    }
472105b261ecSmrg    RecalculateDeliverableEvents(pWin);
472205b261ecSmrg    return Success;
472305b261ecSmrg}
472405b261ecSmrg
472505b261ecSmrg/**
47264642e01fSmrg * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
47274642e01fSmrg * Uses the paired keyboard to get some additional information.
472805b261ecSmrg */
47294642e01fSmrgvoid
473035c4bbdfSmrgCoreEnterLeaveEvent(DeviceIntPtr mouse,
473135c4bbdfSmrg                    int type,
473235c4bbdfSmrg                    int mode, int detail, WindowPtr pWin, Window child)
473335c4bbdfSmrg{
473435c4bbdfSmrg    xEvent event = {
473535c4bbdfSmrg        .u.u.type = type,
473635c4bbdfSmrg        .u.u.detail = detail
473735c4bbdfSmrg    };
473835c4bbdfSmrg    WindowPtr focus;
473935c4bbdfSmrg    DeviceIntPtr keybd;
474035c4bbdfSmrg    GrabPtr grab = mouse->deviceGrab.grab;
474135c4bbdfSmrg    Mask mask;
474235c4bbdfSmrg
474335c4bbdfSmrg    keybd = GetMaster(mouse, KEYBOARD_OR_FLOAT);
47444642e01fSmrg
474505b261ecSmrg    if ((pWin == mouse->valuator->motionHintWindow) &&
474635c4bbdfSmrg        (detail != NotifyInferior))
474735c4bbdfSmrg        mouse->valuator->motionHintWindow = NullWindow;
474835c4bbdfSmrg    if (grab) {
474935c4bbdfSmrg        mask = (pWin == grab->window) ? grab->eventMask : 0;
475035c4bbdfSmrg        if (grab->ownerEvents)
475135c4bbdfSmrg            mask |= EventMaskForClient(pWin, rClient(grab));
475205b261ecSmrg    }
475335c4bbdfSmrg    else {
475435c4bbdfSmrg        mask = pWin->eventMask | wOtherEventMasks(pWin);
475505b261ecSmrg    }
47564642e01fSmrg
47574642e01fSmrg    event.u.enterLeave.time = currentTime.milliseconds;
47584642e01fSmrg    event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x;
47594642e01fSmrg    event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y;
47604642e01fSmrg    /* Counts on the same initial structure of crossing & button events! */
47619ace9065Smrg    FixUpEventFromWindow(mouse->spriteInfo->sprite, &event, pWin, None, FALSE);
47624642e01fSmrg    /* Enter/Leave events always set child */
47634642e01fSmrg    event.u.enterLeave.child = child;
47644642e01fSmrg    event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
47654642e01fSmrg        ELFlagSameScreen : 0;
476635c4bbdfSmrg    event.u.enterLeave.state =
476735c4bbdfSmrg        mouse->button ? (mouse->button->state & 0x1f00) : 0;
47686747b715Smrg    if (keybd)
47696747b715Smrg        event.u.enterLeave.state |=
477035c4bbdfSmrg            XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
47714642e01fSmrg    event.u.enterLeave.mode = mode;
47724642e01fSmrg    focus = (keybd) ? keybd->focus->win : None;
47734642e01fSmrg    if ((focus != NoneWin) &&
477435c4bbdfSmrg        ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin)))
47754642e01fSmrg        event.u.enterLeave.flags |= ELFlagFocus;
477605b261ecSmrg
477735c4bbdfSmrg    if ((mask & GetEventFilter(mouse, &event))) {
47784642e01fSmrg        if (grab)
47794642e01fSmrg            TryClientEvents(rClient(grab), mouse, &event, 1, mask,
47806747b715Smrg                            GetEventFilter(mouse, &event), grab);
47814642e01fSmrg        else
47824642e01fSmrg            DeliverEventsToWindow(mouse, pWin, &event, 1,
478335c4bbdfSmrg                                  GetEventFilter(mouse, &event), NullGrab);
478405b261ecSmrg    }
478505b261ecSmrg
478635c4bbdfSmrg    if ((type == EnterNotify) && (mask & KeymapStateMask)) {
478735c4bbdfSmrg        xKeymapEvent ke = {
478835c4bbdfSmrg            .type = KeymapNotify
478935c4bbdfSmrg        };
47906747b715Smrg        ClientPtr client = grab ? rClient(grab) : wClient(pWin);
479135c4bbdfSmrg        int rc;
479235c4bbdfSmrg
479335c4bbdfSmrg        rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess);
479435c4bbdfSmrg        if (rc == Success)
479535c4bbdfSmrg            memcpy((char *) &ke.map[0], (char *) &keybd->key->down[1], 31);
47964642e01fSmrg
47974642e01fSmrg        if (grab)
479835c4bbdfSmrg            TryClientEvents(rClient(grab), keybd, (xEvent *) &ke, 1,
47994642e01fSmrg                            mask, KeymapStateMask, grab);
48004642e01fSmrg        else
480135c4bbdfSmrg            DeliverEventsToWindow(mouse, pWin, (xEvent *) &ke, 1,
48026747b715Smrg                                  KeymapStateMask, NullGrab);
48036747b715Smrg    }
48046747b715Smrg}
48056747b715Smrg
48066747b715Smrgvoid
480735c4bbdfSmrgDeviceEnterLeaveEvent(DeviceIntPtr mouse,
480835c4bbdfSmrg                      int sourceid,
480935c4bbdfSmrg                      int type,
481035c4bbdfSmrg                      int mode, int detail, WindowPtr pWin, Window child)
481135c4bbdfSmrg{
481235c4bbdfSmrg    GrabPtr grab = mouse->deviceGrab.grab;
481335c4bbdfSmrg    xXIEnterEvent *event;
481435c4bbdfSmrg    WindowPtr focus;
481535c4bbdfSmrg    int filter;
481635c4bbdfSmrg    int btlen, len, i;
481735c4bbdfSmrg    DeviceIntPtr kbd;
48186747b715Smrg
48196747b715Smrg    if ((mode == XINotifyPassiveGrab && type == XI_Leave) ||
48206747b715Smrg        (mode == XINotifyPassiveUngrab && type == XI_Enter))
48216747b715Smrg        return;
48226747b715Smrg
48236747b715Smrg    btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
48246747b715Smrg    btlen = bytes_to_int32(btlen);
48256747b715Smrg    len = sizeof(xXIEnterEvent) + btlen * 4;
48266747b715Smrg
48276747b715Smrg    event = calloc(1, len);
482835c4bbdfSmrg    event->type = GenericEvent;
482935c4bbdfSmrg    event->extension = IReqCode;
483035c4bbdfSmrg    event->evtype = type;
483135c4bbdfSmrg    event->length = (len - sizeof(xEvent)) / 4;
483235c4bbdfSmrg    event->buttons_len = btlen;
483335c4bbdfSmrg    event->detail = detail;
483435c4bbdfSmrg    event->time = currentTime.milliseconds;
483535c4bbdfSmrg    event->deviceid = mouse->id;
483635c4bbdfSmrg    event->sourceid = sourceid;
483735c4bbdfSmrg    event->mode = mode;
483835c4bbdfSmrg    event->root_x = double_to_fp1616(mouse->spriteInfo->sprite->hot.x);
483935c4bbdfSmrg    event->root_y = double_to_fp1616(mouse->spriteInfo->sprite->hot.y);
48406747b715Smrg
48416747b715Smrg    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
48426747b715Smrg        if (BitIsOn(mouse->button->down, i))
48436747b715Smrg            SetBit(&event[1], i);
48446747b715Smrg
484535c4bbdfSmrg    kbd = GetMaster(mouse, MASTER_KEYBOARD);
484635c4bbdfSmrg    if (kbd && kbd->key) {
48476747b715Smrg        event->mods.base_mods = kbd->key->xkbInfo->state.base_mods;
48486747b715Smrg        event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods;
48496747b715Smrg        event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods;
48506747b715Smrg
48516747b715Smrg        event->group.base_group = kbd->key->xkbInfo->state.base_group;
48526747b715Smrg        event->group.latched_group = kbd->key->xkbInfo->state.latched_group;
48536747b715Smrg        event->group.locked_group = kbd->key->xkbInfo->state.locked_group;
485405b261ecSmrg    }
48556747b715Smrg
485635c4bbdfSmrg    focus = (kbd) ? kbd->focus->win : None;
485735c4bbdfSmrg    if ((focus != NoneWin) &&
485835c4bbdfSmrg        ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin)))
485935c4bbdfSmrg        event->focus = TRUE;
486035c4bbdfSmrg
486135c4bbdfSmrg    FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent *) event, pWin,
48629ace9065Smrg                         None, FALSE);
48636747b715Smrg
486435c4bbdfSmrg    filter = GetEventFilter(mouse, (xEvent *) event);
48656747b715Smrg
486635c4bbdfSmrg    if (grab && grab->grabtype == XI2) {
48676747b715Smrg        Mask mask;
486835c4bbdfSmrg
486935c4bbdfSmrg        mask = xi2mask_isset(grab->xi2mask, mouse, type);
487035c4bbdfSmrg        TryClientEvents(rClient(grab), mouse, (xEvent *) event, 1, mask, 1,
487135c4bbdfSmrg                        grab);
487235c4bbdfSmrg    }
487335c4bbdfSmrg    else {
487435c4bbdfSmrg        if (!WindowXI2MaskIsset(mouse, pWin, (xEvent *) event))
48756747b715Smrg            goto out;
487635c4bbdfSmrg        DeliverEventsToWindow(mouse, pWin, (xEvent *) event, 1, filter,
48776747b715Smrg                              NullGrab);
48786747b715Smrg    }
48796747b715Smrg
488035c4bbdfSmrg out:
48816747b715Smrg    free(event);
488205b261ecSmrg}
488305b261ecSmrg
48844642e01fSmrgvoid
48854642e01fSmrgCoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
488605b261ecSmrg{
488735c4bbdfSmrg    xEvent event = {
488835c4bbdfSmrg        .u.u.type = type,
488935c4bbdfSmrg        .u.u.detail = detail
489035c4bbdfSmrg    };
489105b261ecSmrg    event.u.focus.mode = mode;
489205b261ecSmrg    event.u.focus.window = pWin->drawable.id;
48936747b715Smrg
48946747b715Smrg    DeliverEventsToWindow(dev, pWin, &event, 1,
48956747b715Smrg                          GetEventFilter(dev, &event), NullGrab);
489605b261ecSmrg    if ((type == FocusIn) &&
489735c4bbdfSmrg        ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) {
489835c4bbdfSmrg        xKeymapEvent ke = {
489935c4bbdfSmrg            .type = KeymapNotify
490035c4bbdfSmrg        };
49016747b715Smrg        ClientPtr client = wClient(pWin);
490235c4bbdfSmrg        int rc;
490305b261ecSmrg
490435c4bbdfSmrg        rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess);
490535c4bbdfSmrg        if (rc == Success)
490635c4bbdfSmrg            memcpy((char *) &ke.map[0], (char *) &dev->key->down[1], 31);
490735c4bbdfSmrg
490835c4bbdfSmrg        DeliverEventsToWindow(dev, pWin, (xEvent *) &ke, 1,
490935c4bbdfSmrg                              KeymapStateMask, NullGrab);
491005b261ecSmrg    }
491105b261ecSmrg}
491205b261ecSmrg
491305b261ecSmrg/**
491405b261ecSmrg * Set the input focus to the given window. Subsequent keyboard events will be
491505b261ecSmrg * delivered to the given window.
49164642e01fSmrg *
491705b261ecSmrg * Usually called from ProcSetInputFocus as result of a client request. If so,
491805b261ecSmrg * the device is the inputInfo.keyboard.
491905b261ecSmrg * If called from ProcXSetInputFocus as result of a client xinput request, the
492005b261ecSmrg * device is set to the device specified by the client.
492105b261ecSmrg *
492205b261ecSmrg * @param client Client that requested input focus change.
49234642e01fSmrg * @param dev Focus device.
492405b261ecSmrg * @param focusID The window to obtain the focus. Can be PointerRoot or None.
492505b261ecSmrg * @param revertTo Specifies where the focus reverts to when window becomes
492605b261ecSmrg * unviewable.
492705b261ecSmrg * @param ctime Specifies the time.
492805b261ecSmrg * @param followOK True if pointer is allowed to follow the keyboard.
492905b261ecSmrg */
493005b261ecSmrgint
493135c4bbdfSmrgSetInputFocus(ClientPtr client,
493235c4bbdfSmrg              DeviceIntPtr dev,
493335c4bbdfSmrg              Window focusID, CARD8 revertTo, Time ctime, Bool followOK)
493405b261ecSmrg{
493505b261ecSmrg    FocusClassPtr focus;
493605b261ecSmrg    WindowPtr focusWin;
493705b261ecSmrg    int mode, rc;
493805b261ecSmrg    TimeStamp time;
493935c4bbdfSmrg    DeviceIntPtr keybd;         /* used for FollowKeyboard or FollowKeyboardWin */
494005b261ecSmrg
494105b261ecSmrg    UpdateCurrentTime();
494205b261ecSmrg    if ((revertTo != RevertToParent) &&
494335c4bbdfSmrg        (revertTo != RevertToPointerRoot) &&
494435c4bbdfSmrg        (revertTo != RevertToNone) &&
494535c4bbdfSmrg        ((revertTo != RevertToFollowKeyboard) || !followOK)) {
494635c4bbdfSmrg        client->errorValue = revertTo;
494735c4bbdfSmrg        return BadValue;
494805b261ecSmrg    }
494905b261ecSmrg    time = ClientTimeToServerTime(ctime);
49504642e01fSmrg
495135c4bbdfSmrg    keybd = GetMaster(dev, KEYBOARD_OR_FLOAT);
49524642e01fSmrg
495305b261ecSmrg    if ((focusID == None) || (focusID == PointerRoot))
495435c4bbdfSmrg        focusWin = (WindowPtr) (long) focusID;
495535c4bbdfSmrg    else if ((focusID == FollowKeyboard) && followOK) {
495635c4bbdfSmrg        focusWin = keybd->focus->win;
49574642e01fSmrg    }
495805b261ecSmrg    else {
495935c4bbdfSmrg        rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess);
496035c4bbdfSmrg        if (rc != Success)
496135c4bbdfSmrg            return rc;
496235c4bbdfSmrg        /* It is a match error to try to set the input focus to an
496335c4bbdfSmrg           unviewable window. */
496435c4bbdfSmrg        if (!focusWin->realized)
496535c4bbdfSmrg            return BadMatch;
496605b261ecSmrg    }
49674642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess);
49684642e01fSmrg    if (rc != Success)
496935c4bbdfSmrg        return Success;
49704642e01fSmrg
497105b261ecSmrg    focus = dev->focus;
497205b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
497335c4bbdfSmrg        (CompareTimeStamps(time, focus->time) == EARLIER))
497435c4bbdfSmrg        return Success;
49754642e01fSmrg    mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal;
497635c4bbdfSmrg    if (focus->win == FollowKeyboardWin) {
49776747b715Smrg        if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin))
49786747b715Smrg            DoFocusEvents(dev, keybd->focus->win, focusWin, mode);
497935c4bbdfSmrg    }
498035c4bbdfSmrg    else {
49816747b715Smrg        if (!ActivateFocusInGrab(dev, focus->win, focusWin))
49826747b715Smrg            DoFocusEvents(dev, focus->win, focusWin, mode);
49836747b715Smrg    }
498405b261ecSmrg    focus->time = time;
498505b261ecSmrg    focus->revert = revertTo;
498605b261ecSmrg    if (focusID == FollowKeyboard)
498735c4bbdfSmrg        focus->win = FollowKeyboardWin;
498805b261ecSmrg    else
498935c4bbdfSmrg        focus->win = focusWin;
499005b261ecSmrg    if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
499135c4bbdfSmrg        focus->traceGood = 0;
499235c4bbdfSmrg    else {
499305b261ecSmrg        int depth = 0;
499435c4bbdfSmrg        WindowPtr pWin;
499535c4bbdfSmrg
499635c4bbdfSmrg        for (pWin = focusWin; pWin; pWin = pWin->parent)
499735c4bbdfSmrg            depth++;
499835c4bbdfSmrg        if (depth > focus->traceSize) {
499935c4bbdfSmrg            focus->traceSize = depth + 1;
500035c4bbdfSmrg            focus->trace = reallocarray(focus->trace, focus->traceSize,
500135c4bbdfSmrg                                        sizeof(WindowPtr));
500235c4bbdfSmrg        }
500335c4bbdfSmrg        focus->traceGood = depth;
50044642e01fSmrg        for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
500535c4bbdfSmrg            focus->trace[depth] = pWin;
500605b261ecSmrg    }
500705b261ecSmrg    return Success;
500805b261ecSmrg}
500905b261ecSmrg
501005b261ecSmrg/**
501105b261ecSmrg * Server-side protocol handling for SetInputFocus request.
501205b261ecSmrg *
501305b261ecSmrg * Sets the input focus for the virtual core keyboard.
501405b261ecSmrg */
501505b261ecSmrgint
50166747b715SmrgProcSetInputFocus(ClientPtr client)
501705b261ecSmrg{
50184642e01fSmrg    DeviceIntPtr kbd = PickKeyboard(client);
501935c4bbdfSmrg
502005b261ecSmrg    REQUEST(xSetInputFocusReq);
502105b261ecSmrg
502205b261ecSmrg    REQUEST_SIZE_MATCH(xSetInputFocusReq);
502305b261ecSmrg
50244642e01fSmrg    return SetInputFocus(client, kbd, stuff->focus,
502535c4bbdfSmrg                         stuff->revertTo, stuff->time, FALSE);
502605b261ecSmrg}
502705b261ecSmrg
502805b261ecSmrg/**
502905b261ecSmrg * Server-side protocol handling for GetInputFocus request.
50304642e01fSmrg *
50314642e01fSmrg * Sends the current input focus for the client's keyboard back to the
503205b261ecSmrg * client.
503305b261ecSmrg */
503405b261ecSmrgint
503505b261ecSmrgProcGetInputFocus(ClientPtr client)
503605b261ecSmrg{
50374642e01fSmrg    DeviceIntPtr kbd = PickKeyboard(client);
503805b261ecSmrg    xGetInputFocusReply rep;
50394642e01fSmrg    FocusClassPtr focus = kbd->focus;
50404642e01fSmrg    int rc;
504135c4bbdfSmrg
504205b261ecSmrg    /* REQUEST(xReq); */
504305b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
50444642e01fSmrg
50454642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess);
50464642e01fSmrg    if (rc != Success)
504735c4bbdfSmrg        return rc;
504835c4bbdfSmrg
504935c4bbdfSmrg    rep = (xGetInputFocusReply) {
505035c4bbdfSmrg        .type = X_Reply,
505135c4bbdfSmrg        .length = 0,
505235c4bbdfSmrg        .sequenceNumber = client->sequence,
505335c4bbdfSmrg        .revertTo = focus->revert
505435c4bbdfSmrg    };
50554642e01fSmrg
505605b261ecSmrg    if (focus->win == NoneWin)
505735c4bbdfSmrg        rep.focus = None;
505805b261ecSmrg    else if (focus->win == PointerRootWin)
505935c4bbdfSmrg        rep.focus = PointerRoot;
506035c4bbdfSmrg    else
506135c4bbdfSmrg        rep.focus = focus->win->drawable.id;
506235c4bbdfSmrg
506305b261ecSmrg    WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
506405b261ecSmrg    return Success;
506505b261ecSmrg}
506605b261ecSmrg
506705b261ecSmrg/**
50684642e01fSmrg * Server-side protocol handling for GrabPointer request.
506905b261ecSmrg *
50704642e01fSmrg * Sets an active grab on the client's ClientPointer and returns success
50714642e01fSmrg * status to client.
507205b261ecSmrg */
507305b261ecSmrgint
507405b261ecSmrgProcGrabPointer(ClientPtr client)
507505b261ecSmrg{
507605b261ecSmrg    xGrabPointerReply rep;
50774642e01fSmrg    DeviceIntPtr device = PickPointer(client);
507805b261ecSmrg    GrabPtr grab;
50796747b715Smrg    GrabMask mask;
50806747b715Smrg    WindowPtr confineTo;
508135c4bbdfSmrg    BYTE status;
508235c4bbdfSmrg
508305b261ecSmrg    REQUEST(xGrabPointerReq);
508405b261ecSmrg    int rc;
508505b261ecSmrg
508605b261ecSmrg    REQUEST_SIZE_MATCH(xGrabPointerReq);
508705b261ecSmrg    UpdateCurrentTime();
50886747b715Smrg
508935c4bbdfSmrg    if (stuff->eventMask & ~PointerGrabMask) {
509035c4bbdfSmrg        client->errorValue = stuff->eventMask;
509105b261ecSmrg        return BadValue;
509205b261ecSmrg    }
50936747b715Smrg
509405b261ecSmrg    if (stuff->confineTo == None)
509535c4bbdfSmrg        confineTo = NullWindow;
509635c4bbdfSmrg    else {
509735c4bbdfSmrg        rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
509835c4bbdfSmrg                             DixSetAttrAccess);
509935c4bbdfSmrg        if (rc != Success)
510035c4bbdfSmrg            return rc;
510105b261ecSmrg    }
51026747b715Smrg
51036747b715Smrg    grab = device->deviceGrab.grab;
51046747b715Smrg
510535c4bbdfSmrg    if (grab && grab->confineTo && !confineTo)
510635c4bbdfSmrg        ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE, FALSE);
51076747b715Smrg
51086747b715Smrg    mask.core = stuff->eventMask;
51096747b715Smrg
51106747b715Smrg    rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode,
51116747b715Smrg                    stuff->grabWindow, stuff->ownerEvents, stuff->time,
511235c4bbdfSmrg                    &mask, CORE, stuff->cursor, stuff->confineTo, &status);
51134642e01fSmrg    if (rc != Success)
51146747b715Smrg        return rc;
51156747b715Smrg
511635c4bbdfSmrg    rep = (xGrabPointerReply) {
511735c4bbdfSmrg        .type = X_Reply,
511835c4bbdfSmrg        .status = status,
511935c4bbdfSmrg        .sequenceNumber = client->sequence,
512035c4bbdfSmrg        .length = 0
512135c4bbdfSmrg    };
512205b261ecSmrg    WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
512305b261ecSmrg    return Success;
512405b261ecSmrg}
512505b261ecSmrg
512605b261ecSmrg/**
512705b261ecSmrg * Server-side protocol handling for ChangeActivePointerGrab request.
512805b261ecSmrg *
512905b261ecSmrg * Changes properties of the grab hold by the client. If the client does not
51304642e01fSmrg * hold an active grab on the device, nothing happens.
513105b261ecSmrg */
513205b261ecSmrgint
513305b261ecSmrgProcChangeActivePointerGrab(ClientPtr client)
513405b261ecSmrg{
51354642e01fSmrg    DeviceIntPtr device;
513635c4bbdfSmrg    GrabPtr grab;
513705b261ecSmrg    CursorPtr newCursor, oldCursor;
513835c4bbdfSmrg
513905b261ecSmrg    REQUEST(xChangeActivePointerGrabReq);
514005b261ecSmrg    TimeStamp time;
514105b261ecSmrg
514205b261ecSmrg    REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
514335c4bbdfSmrg    if (stuff->eventMask & ~PointerGrabMask) {
514435c4bbdfSmrg        client->errorValue = stuff->eventMask;
514505b261ecSmrg        return BadValue;
514605b261ecSmrg    }
514705b261ecSmrg    if (stuff->cursor == None)
514835c4bbdfSmrg        newCursor = NullCursor;
514935c4bbdfSmrg    else {
515035c4bbdfSmrg        int rc = dixLookupResourceByType((void **) &newCursor, stuff->cursor,
515135c4bbdfSmrg                                         RT_CURSOR, client, DixUseAccess);
515235c4bbdfSmrg
515335c4bbdfSmrg        if (rc != Success) {
515435c4bbdfSmrg            client->errorValue = stuff->cursor;
515535c4bbdfSmrg            return rc;
515635c4bbdfSmrg        }
515705b261ecSmrg    }
51584642e01fSmrg
51594642e01fSmrg    device = PickPointer(client);
51604642e01fSmrg    grab = device->deviceGrab.grab;
51614642e01fSmrg
516205b261ecSmrg    if (!grab)
516335c4bbdfSmrg        return Success;
516405b261ecSmrg    if (!SameClient(grab, client))
516535c4bbdfSmrg        return Success;
51667e31ba66Smrg    UpdateCurrentTime();
516705b261ecSmrg    time = ClientTimeToServerTime(stuff->time);
516805b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
516935c4bbdfSmrg        (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
517035c4bbdfSmrg        return Success;
517105b261ecSmrg    oldCursor = grab->cursor;
517235c4bbdfSmrg    grab->cursor = RefCursor(newCursor);
51734642e01fSmrg    PostNewCursor(device);
517405b261ecSmrg    if (oldCursor)
517535c4bbdfSmrg        FreeCursor(oldCursor, (Cursor) 0);
517605b261ecSmrg    grab->eventMask = stuff->eventMask;
517705b261ecSmrg    return Success;
517805b261ecSmrg}
517905b261ecSmrg
518005b261ecSmrg/**
518105b261ecSmrg * Server-side protocol handling for UngrabPointer request.
518205b261ecSmrg *
51834642e01fSmrg * Deletes a pointer grab on a device the client has grabbed.
518405b261ecSmrg */
518505b261ecSmrgint
518605b261ecSmrgProcUngrabPointer(ClientPtr client)
518705b261ecSmrg{
51884642e01fSmrg    DeviceIntPtr device = PickPointer(client);
518905b261ecSmrg    GrabPtr grab;
519005b261ecSmrg    TimeStamp time;
519135c4bbdfSmrg
519205b261ecSmrg    REQUEST(xResourceReq);
519305b261ecSmrg
519405b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
519505b261ecSmrg    UpdateCurrentTime();
51964642e01fSmrg    grab = device->deviceGrab.grab;
51974642e01fSmrg
519805b261ecSmrg    time = ClientTimeToServerTime(stuff->id);
519905b261ecSmrg    if ((CompareTimeStamps(time, currentTime) != LATER) &&
520035c4bbdfSmrg        (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
520135c4bbdfSmrg        (grab) && SameClient(grab, client))
520235c4bbdfSmrg        (*device->deviceGrab.DeactivateGrab) (device);
520305b261ecSmrg    return Success;
520405b261ecSmrg}
520505b261ecSmrg
520605b261ecSmrg/**
520705b261ecSmrg * Sets a grab on the given device.
52084642e01fSmrg *
52094642e01fSmrg * Called from ProcGrabKeyboard to work on the client's keyboard.
521005b261ecSmrg * Called from ProcXGrabDevice to work on the device specified by the client.
52114642e01fSmrg *
521205b261ecSmrg * The parameters this_mode and other_mode represent the keyboard_mode and
52134642e01fSmrg * pointer_mode parameters of XGrabKeyboard().
521405b261ecSmrg * See man page for details on all the parameters
52154642e01fSmrg *
521605b261ecSmrg * @param client Client that owns the grab.
52174642e01fSmrg * @param dev The device to grab.
521805b261ecSmrg * @param this_mode GrabModeSync or GrabModeAsync
521905b261ecSmrg * @param other_mode GrabModeSync or GrabModeAsync
522005b261ecSmrg * @param status Return code to be returned to the caller.
52214642e01fSmrg *
522235c4bbdfSmrg * @returns Success or BadValue or BadAlloc.
522305b261ecSmrg */
522405b261ecSmrgint
52254642e01fSmrgGrabDevice(ClientPtr client, DeviceIntPtr dev,
52266747b715Smrg           unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow,
52276747b715Smrg           unsigned ownerEvents, Time ctime, GrabMask *mask,
52286747b715Smrg           int grabtype, Cursor curs, Window confineToWin, CARD8 *status)
522905b261ecSmrg{
52306747b715Smrg    WindowPtr pWin, confineTo;
523105b261ecSmrg    GrabPtr grab;
523205b261ecSmrg    TimeStamp time;
52334642e01fSmrg    Mask access_mode = DixGrabAccess;
523405b261ecSmrg    int rc;
52354642e01fSmrg    GrabInfoPtr grabInfo = &dev->deviceGrab;
52366747b715Smrg    CursorPtr cursor;
523705b261ecSmrg
523805b261ecSmrg    UpdateCurrentTime();
523935c4bbdfSmrg    if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync)) {
524035c4bbdfSmrg        client->errorValue = keyboard_mode;
524105b261ecSmrg        return BadValue;
524205b261ecSmrg    }
524335c4bbdfSmrg    if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync)) {
524435c4bbdfSmrg        client->errorValue = pointer_mode;
524505b261ecSmrg        return BadValue;
524605b261ecSmrg    }
524735c4bbdfSmrg    if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) {
524835c4bbdfSmrg        client->errorValue = ownerEvents;
524905b261ecSmrg        return BadValue;
525005b261ecSmrg    }
52514642e01fSmrg
52524642e01fSmrg    rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
525305b261ecSmrg    if (rc != Success)
525435c4bbdfSmrg        return rc;
52556747b715Smrg
52566747b715Smrg    if (confineToWin == None)
525735c4bbdfSmrg        confineTo = NullWindow;
525835c4bbdfSmrg    else {
525935c4bbdfSmrg        rc = dixLookupWindow(&confineTo, confineToWin, client,
526035c4bbdfSmrg                             DixSetAttrAccess);
526135c4bbdfSmrg        if (rc != Success)
526235c4bbdfSmrg            return rc;
52636747b715Smrg    }
52646747b715Smrg
52656747b715Smrg    if (curs == None)
526635c4bbdfSmrg        cursor = NullCursor;
526735c4bbdfSmrg    else {
526835c4bbdfSmrg        rc = dixLookupResourceByType((void **) &cursor, curs, RT_CURSOR,
526935c4bbdfSmrg                                     client, DixUseAccess);
527035c4bbdfSmrg        if (rc != Success) {
527135c4bbdfSmrg            client->errorValue = curs;
527235c4bbdfSmrg            return rc;
527335c4bbdfSmrg        }
527435c4bbdfSmrg        access_mode |= DixForceAccess;
52756747b715Smrg    }
52766747b715Smrg
52776747b715Smrg    if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync)
527835c4bbdfSmrg        access_mode |= DixFreezeAccess;
52794642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
52804642e01fSmrg    if (rc != Success)
528135c4bbdfSmrg        return rc;
52824642e01fSmrg
528305b261ecSmrg    time = ClientTimeToServerTime(ctime);
52844642e01fSmrg    grab = grabInfo->grab;
52856747b715Smrg    if (grab && grab->grabtype != grabtype)
52866747b715Smrg        *status = AlreadyGrabbed;
528735c4bbdfSmrg    else if (grab && !SameClient(grab, client))
528835c4bbdfSmrg        *status = AlreadyGrabbed;
52896747b715Smrg    else if ((!pWin->realized) ||
52906747b715Smrg             (confineTo &&
529135c4bbdfSmrg              !(confineTo->realized && BorderSizeNotEmpty(dev, confineTo))))
529235c4bbdfSmrg        *status = GrabNotViewable;
529305b261ecSmrg    else if ((CompareTimeStamps(time, currentTime) == LATER) ||
529435c4bbdfSmrg             (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER))
529535c4bbdfSmrg        *status = GrabInvalidTime;
52964642e01fSmrg    else if (grabInfo->sync.frozen &&
529735c4bbdfSmrg             grabInfo->sync.other && !SameClient(grabInfo->sync.other, client))
529835c4bbdfSmrg        *status = GrabFrozen;
529935c4bbdfSmrg    else {
530035c4bbdfSmrg        GrabPtr tempGrab;
530135c4bbdfSmrg
530235c4bbdfSmrg        tempGrab = AllocGrab(NULL);
530335c4bbdfSmrg        if (tempGrab == NULL)
530435c4bbdfSmrg            return BadAlloc;
530535c4bbdfSmrg
530635c4bbdfSmrg        tempGrab->next = NULL;
530735c4bbdfSmrg        tempGrab->window = pWin;
530835c4bbdfSmrg        tempGrab->resource = client->clientAsMask;
530935c4bbdfSmrg        tempGrab->ownerEvents = ownerEvents;
531035c4bbdfSmrg        tempGrab->keyboardMode = keyboard_mode;
531135c4bbdfSmrg        tempGrab->pointerMode = pointer_mode;
531235c4bbdfSmrg        if (grabtype == CORE)
531335c4bbdfSmrg            tempGrab->eventMask = mask->core;
531435c4bbdfSmrg        else if (grabtype == XI)
531535c4bbdfSmrg            tempGrab->eventMask = mask->xi;
531635c4bbdfSmrg        else
531735c4bbdfSmrg            xi2mask_merge(tempGrab->xi2mask, mask->xi2mask);
531835c4bbdfSmrg        tempGrab->device = dev;
531935c4bbdfSmrg        tempGrab->cursor = RefCursor(cursor);
532035c4bbdfSmrg        tempGrab->confineTo = confineTo;
532135c4bbdfSmrg        tempGrab->grabtype = grabtype;
532235c4bbdfSmrg        (*grabInfo->ActivateGrab) (dev, tempGrab, time, FALSE);
532335c4bbdfSmrg        *status = GrabSuccess;
532435c4bbdfSmrg
532535c4bbdfSmrg        FreeGrab(tempGrab);
532605b261ecSmrg    }
532705b261ecSmrg    return Success;
532805b261ecSmrg}
532905b261ecSmrg
533005b261ecSmrg/**
533105b261ecSmrg * Server-side protocol handling for GrabKeyboard request.
533205b261ecSmrg *
53334642e01fSmrg * Grabs the client's keyboard and returns success status to client.
533405b261ecSmrg */
533505b261ecSmrgint
533605b261ecSmrgProcGrabKeyboard(ClientPtr client)
533705b261ecSmrg{
533805b261ecSmrg    xGrabKeyboardReply rep;
533935c4bbdfSmrg    BYTE status;
534035c4bbdfSmrg
534105b261ecSmrg    REQUEST(xGrabKeyboardReq);
534205b261ecSmrg    int result;
53434642e01fSmrg    DeviceIntPtr keyboard = PickKeyboard(client);
53446747b715Smrg    GrabMask mask;
534505b261ecSmrg
534605b261ecSmrg    REQUEST_SIZE_MATCH(xGrabKeyboardReq);
53477e31ba66Smrg    UpdateCurrentTime();
534805b261ecSmrg
53496747b715Smrg    mask.core = KeyPressMask | KeyReleaseMask;
53506747b715Smrg
53516747b715Smrg    result = GrabDevice(client, keyboard, stuff->pointerMode,
535235c4bbdfSmrg                        stuff->keyboardMode, stuff->grabWindow,
535335c4bbdfSmrg                        stuff->ownerEvents, stuff->time, &mask, CORE, None,
535435c4bbdfSmrg                        None, &status);
535505b261ecSmrg
535605b261ecSmrg    if (result != Success)
535735c4bbdfSmrg        return result;
535835c4bbdfSmrg
535935c4bbdfSmrg    rep = (xGrabKeyboardReply) {
536035c4bbdfSmrg        .type = X_Reply,
536135c4bbdfSmrg        .status = status,
536235c4bbdfSmrg        .sequenceNumber = client->sequence,
536335c4bbdfSmrg        .length = 0
536435c4bbdfSmrg    };
536505b261ecSmrg    WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
536605b261ecSmrg    return Success;
536705b261ecSmrg}
536805b261ecSmrg
536905b261ecSmrg/**
537005b261ecSmrg * Server-side protocol handling for UngrabKeyboard request.
537105b261ecSmrg *
53724642e01fSmrg * Deletes a possible grab on the client's keyboard.
537305b261ecSmrg */
537405b261ecSmrgint
537505b261ecSmrgProcUngrabKeyboard(ClientPtr client)
537605b261ecSmrg{
53774642e01fSmrg    DeviceIntPtr device = PickKeyboard(client);
537805b261ecSmrg    GrabPtr grab;
537905b261ecSmrg    TimeStamp time;
538035c4bbdfSmrg
538105b261ecSmrg    REQUEST(xResourceReq);
538205b261ecSmrg
538305b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
538405b261ecSmrg    UpdateCurrentTime();
53854642e01fSmrg
53864642e01fSmrg    grab = device->deviceGrab.grab;
53874642e01fSmrg
538805b261ecSmrg    time = ClientTimeToServerTime(stuff->id);
538905b261ecSmrg    if ((CompareTimeStamps(time, currentTime) != LATER) &&
539035c4bbdfSmrg        (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
539135c4bbdfSmrg        (grab) && SameClient(grab, client) && grab->grabtype == CORE)
539235c4bbdfSmrg        (*device->deviceGrab.DeactivateGrab) (device);
539305b261ecSmrg    return Success;
539405b261ecSmrg}
539505b261ecSmrg
539605b261ecSmrg/**
539705b261ecSmrg * Server-side protocol handling for QueryPointer request.
539805b261ecSmrg *
53994642e01fSmrg * Returns the current state and position of the client's ClientPointer to the
54004642e01fSmrg * client.
540105b261ecSmrg */
540205b261ecSmrgint
540305b261ecSmrgProcQueryPointer(ClientPtr client)
540405b261ecSmrg{
540505b261ecSmrg    xQueryPointerReply rep;
540605b261ecSmrg    WindowPtr pWin, t;
54074642e01fSmrg    DeviceIntPtr mouse = PickPointer(client);
54086747b715Smrg    DeviceIntPtr keyboard;
54094642e01fSmrg    SpritePtr pSprite;
541005b261ecSmrg    int rc;
541135c4bbdfSmrg
54124642e01fSmrg    REQUEST(xResourceReq);
541305b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
54144642e01fSmrg
54154642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
54164642e01fSmrg    if (rc != Success)
541735c4bbdfSmrg        return rc;
54184642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
54196747b715Smrg    if (rc != Success && rc != BadAccess)
542035c4bbdfSmrg        return rc;
54214642e01fSmrg
542235c4bbdfSmrg    keyboard = GetMaster(mouse, MASTER_KEYBOARD);
54236747b715Smrg
54244642e01fSmrg    pSprite = mouse->spriteInfo->sprite;
542505b261ecSmrg    if (mouse->valuator->motionHintWindow)
542635c4bbdfSmrg        MaybeStopHint(mouse, client);
542735c4bbdfSmrg    rep = (xQueryPointerReply) {
542835c4bbdfSmrg        .type = X_Reply,
542935c4bbdfSmrg        .sequenceNumber = client->sequence,
543035c4bbdfSmrg        .length = 0,
543135c4bbdfSmrg        .mask = event_get_corestate(mouse, keyboard),
543235c4bbdfSmrg        .root = (GetCurrentRootWindow(mouse))->drawable.id,
543335c4bbdfSmrg        .rootX = pSprite->hot.x,
543435c4bbdfSmrg        .rootY = pSprite->hot.y,
543535c4bbdfSmrg        .child = None
543635c4bbdfSmrg    };
543735c4bbdfSmrg    if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
543835c4bbdfSmrg        rep.sameScreen = xTrue;
543935c4bbdfSmrg        rep.winX = pSprite->hot.x - pWin->drawable.x;
544035c4bbdfSmrg        rep.winY = pSprite->hot.y - pWin->drawable.y;
544135c4bbdfSmrg        for (t = pSprite->win; t; t = t->parent)
544235c4bbdfSmrg            if (t->parent == pWin) {
544335c4bbdfSmrg                rep.child = t->drawable.id;
544435c4bbdfSmrg                break;
544535c4bbdfSmrg            }
544605b261ecSmrg    }
544735c4bbdfSmrg    else {
544835c4bbdfSmrg        rep.sameScreen = xFalse;
544935c4bbdfSmrg        rep.winX = 0;
545035c4bbdfSmrg        rep.winY = 0;
545105b261ecSmrg    }
545205b261ecSmrg
545305b261ecSmrg#ifdef PANORAMIX
545435c4bbdfSmrg    if (!noPanoramiXExtension) {
545535c4bbdfSmrg        rep.rootX += screenInfo.screens[0]->x;
545635c4bbdfSmrg        rep.rootY += screenInfo.screens[0]->y;
545735c4bbdfSmrg        if (stuff->id == rep.root) {
545835c4bbdfSmrg            rep.winX += screenInfo.screens[0]->x;
545935c4bbdfSmrg            rep.winY += screenInfo.screens[0]->y;
546035c4bbdfSmrg        }
546105b261ecSmrg    }
546205b261ecSmrg#endif
546305b261ecSmrg
54646747b715Smrg    if (rc == BadAccess) {
546535c4bbdfSmrg        rep.mask = 0;
546635c4bbdfSmrg        rep.child = None;
546735c4bbdfSmrg        rep.rootX = 0;
546835c4bbdfSmrg        rep.rootY = 0;
546935c4bbdfSmrg        rep.winX = 0;
547035c4bbdfSmrg        rep.winY = 0;
54716747b715Smrg    }
54726747b715Smrg
547305b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
547405b261ecSmrg
54756747b715Smrg    return Success;
547605b261ecSmrg}
547705b261ecSmrg
547805b261ecSmrg/**
547905b261ecSmrg * Initializes the device list and the DIX sprite to sane values. Allocates
548005b261ecSmrg * trace memory used for quick window traversal.
548105b261ecSmrg */
548205b261ecSmrgvoid
548305b261ecSmrgInitEvents(void)
548405b261ecSmrg{
548505b261ecSmrg    int i;
548635c4bbdfSmrg    QdEventPtr qe, tmp;
548705b261ecSmrg
548805b261ecSmrg    inputInfo.numDevices = 0;
548935c4bbdfSmrg    inputInfo.devices = (DeviceIntPtr) NULL;
549035c4bbdfSmrg    inputInfo.off_devices = (DeviceIntPtr) NULL;
549135c4bbdfSmrg    inputInfo.keyboard = (DeviceIntPtr) NULL;
549235c4bbdfSmrg    inputInfo.pointer = (DeviceIntPtr) NULL;
549335c4bbdfSmrg
549435c4bbdfSmrg    for (i = 0; i < MAXDEVICES; i++) {
549535c4bbdfSmrg        DeviceIntRec dummy;
549635c4bbdfSmrg        memcpy(&event_filters[i], default_filter, sizeof(default_filter));
549735c4bbdfSmrg
549835c4bbdfSmrg        dummy.id = i;
549935c4bbdfSmrg        NoticeTime(&dummy, currentTime);
550035c4bbdfSmrg        LastEventTimeToggleResetFlag(i, FALSE);
550105b261ecSmrg    }
55024642e01fSmrg
550335c4bbdfSmrg    syncEvents.replayDev = (DeviceIntPtr) NULL;
550405b261ecSmrg    syncEvents.replayWin = NullWindow;
550535c4bbdfSmrg    if (syncEvents.pending.next)
550635c4bbdfSmrg        xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next)
550735c4bbdfSmrg            free(qe);
550835c4bbdfSmrg    xorg_list_init(&syncEvents.pending);
550905b261ecSmrg    syncEvents.playingEvents = FALSE;
551005b261ecSmrg    syncEvents.time.months = 0;
551135c4bbdfSmrg    syncEvents.time.milliseconds = 0;   /* hardly matters */
551205b261ecSmrg    currentTime.months = 0;
551305b261ecSmrg    currentTime.milliseconds = GetTimeInMillis();
551435c4bbdfSmrg    for (i = 0; i < DNPMCOUNT; i++) {
551535c4bbdfSmrg        DontPropagateMasks[i] = 0;
551635c4bbdfSmrg        DontPropagateRefCnts[i] = 0;
551705b261ecSmrg    }
55184642e01fSmrg
551935c4bbdfSmrg    InputEventList = InitEventList(GetMaximumEventsNum());
55204642e01fSmrg    if (!InputEventList)
55214642e01fSmrg        FatalError("[dix] Failed to allocate input event list.\n");
552205b261ecSmrg}
552305b261ecSmrg
552405b261ecSmrgvoid
552505b261ecSmrgCloseDownEvents(void)
552605b261ecSmrg{
552735c4bbdfSmrg    FreeEventList(InputEventList, GetMaximumEventsNum());
55286747b715Smrg    InputEventList = NULL;
552905b261ecSmrg}
553005b261ecSmrg
5531475c125cSmrg#define SEND_EVENT_BIT 0x80
5532475c125cSmrg
553305b261ecSmrg/**
553405b261ecSmrg * Server-side protocol handling for SendEvent request.
553505b261ecSmrg *
55364642e01fSmrg * Locates the window to send the event to and forwards the event.
553705b261ecSmrg */
553805b261ecSmrgint
553905b261ecSmrgProcSendEvent(ClientPtr client)
554005b261ecSmrg{
554105b261ecSmrg    WindowPtr pWin;
554235c4bbdfSmrg    WindowPtr effectiveFocus = NullWindow;      /* only set if dest==InputFocus */
55436747b715Smrg    DeviceIntPtr dev = PickPointer(client);
554435c4bbdfSmrg    DeviceIntPtr keybd = GetMaster(dev, MASTER_KEYBOARD);
55456747b715Smrg    SpritePtr pSprite = dev->spriteInfo->sprite;
554635c4bbdfSmrg
554705b261ecSmrg    REQUEST(xSendEventReq);
554805b261ecSmrg
554905b261ecSmrg    REQUEST_SIZE_MATCH(xSendEventReq);
555005b261ecSmrg
5551475c125cSmrg    /* libXext and other extension libraries may set the bit indicating
5552475c125cSmrg     * that this event came from a SendEvent request so remove it
5553475c125cSmrg     * since otherwise the event type may fail the range checks
5554475c125cSmrg     * and cause an invalid BadValue error to be returned.
5555475c125cSmrg     *
5556475c125cSmrg     * This is safe to do since we later add the SendEvent bit (0x80)
5557475c125cSmrg     * back in once we send the event to the client */
5558475c125cSmrg
5559475c125cSmrg    stuff->event.u.u.type &= ~(SEND_EVENT_BIT);
5560475c125cSmrg
556105b261ecSmrg    /* The client's event type must be a core event type or one defined by an
556235c4bbdfSmrg       extension. */
556305b261ecSmrg
556435c4bbdfSmrg    if (!((stuff->event.u.u.type > X_Reply &&
556535c4bbdfSmrg           stuff->event.u.u.type < LASTEvent) ||
556635c4bbdfSmrg          (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
556735c4bbdfSmrg           stuff->event.u.u.type < (unsigned) lastEvent))) {
556835c4bbdfSmrg        client->errorValue = stuff->event.u.u.type;
556935c4bbdfSmrg        return BadValue;
557005b261ecSmrg    }
55710679523aSmrg    /* Generic events can have variable size, but SendEvent request holds
55720679523aSmrg       exactly 32B of event data. */
55730679523aSmrg    if (stuff->event.u.u.type == GenericEvent) {
55740679523aSmrg        client->errorValue = stuff->event.u.u.type;
55750679523aSmrg        return BadValue;
55760679523aSmrg    }
557705b261ecSmrg    if (stuff->event.u.u.type == ClientMessage &&
557835c4bbdfSmrg        stuff->event.u.u.detail != 8 &&
557935c4bbdfSmrg        stuff->event.u.u.detail != 16 && stuff->event.u.u.detail != 32) {
558035c4bbdfSmrg        client->errorValue = stuff->event.u.u.detail;
558135c4bbdfSmrg        return BadValue;
558205b261ecSmrg    }
558335c4bbdfSmrg    if (stuff->eventMask & ~AllEventMasks) {
558435c4bbdfSmrg        client->errorValue = stuff->eventMask;
558535c4bbdfSmrg        return BadValue;
558605b261ecSmrg    }
558705b261ecSmrg
558805b261ecSmrg    if (stuff->destination == PointerWindow)
558935c4bbdfSmrg        pWin = pSprite->win;
559035c4bbdfSmrg    else if (stuff->destination == InputFocus) {
559135c4bbdfSmrg        WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin;
559205b261ecSmrg
559335c4bbdfSmrg        if (inputFocus == NoneWin)
559435c4bbdfSmrg            return Success;
559505b261ecSmrg
559635c4bbdfSmrg        /* If the input focus is PointerRootWin, send the event to where
55975a112b11Smrg           the pointer is if possible, then perhaps propagate up to root. */
559835c4bbdfSmrg        if (inputFocus == PointerRootWin)
559935c4bbdfSmrg            inputFocus = GetCurrentRootWindow(dev);
560005b261ecSmrg
560135c4bbdfSmrg        if (IsParent(inputFocus, pSprite->win)) {
560235c4bbdfSmrg            effectiveFocus = inputFocus;
560335c4bbdfSmrg            pWin = pSprite->win;
560435c4bbdfSmrg        }
560535c4bbdfSmrg        else
560635c4bbdfSmrg            effectiveFocus = pWin = inputFocus;
560705b261ecSmrg    }
560805b261ecSmrg    else
560935c4bbdfSmrg        dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess);
561005b261ecSmrg
561105b261ecSmrg    if (!pWin)
561235c4bbdfSmrg        return BadWindow;
561335c4bbdfSmrg    if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) {
561435c4bbdfSmrg        client->errorValue = stuff->propagate;
561535c4bbdfSmrg        return BadValue;
561605b261ecSmrg    }
5617475c125cSmrg    stuff->event.u.u.type |= SEND_EVENT_BIT;
561835c4bbdfSmrg    if (stuff->propagate) {
561935c4bbdfSmrg        for (; pWin; pWin = pWin->parent) {
562035c4bbdfSmrg            if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin,
562135c4bbdfSmrg                         &stuff->event, 1))
562235c4bbdfSmrg                return Success;
56236747b715Smrg            if (DeliverEventsToWindow(dev, pWin,
562435c4bbdfSmrg                                      &stuff->event, 1, stuff->eventMask,
562535c4bbdfSmrg                                      NullGrab))
562635c4bbdfSmrg                return Success;
562735c4bbdfSmrg            if (pWin == effectiveFocus)
562835c4bbdfSmrg                return Success;
562935c4bbdfSmrg            stuff->eventMask &= ~wDontPropagateMask(pWin);
563035c4bbdfSmrg            if (!stuff->eventMask)
563135c4bbdfSmrg                break;
563235c4bbdfSmrg        }
563305b261ecSmrg    }
56344642e01fSmrg    else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1))
56356747b715Smrg        DeliverEventsToWindow(dev, pWin, &stuff->event,
563635c4bbdfSmrg                              1, stuff->eventMask, NullGrab);
563705b261ecSmrg    return Success;
563805b261ecSmrg}
563905b261ecSmrg
564005b261ecSmrg/**
564105b261ecSmrg * Server-side protocol handling for UngrabKey request.
564205b261ecSmrg *
56434642e01fSmrg * Deletes a passive grab for the given key. Works on the
56444642e01fSmrg * client's keyboard.
564505b261ecSmrg */
564605b261ecSmrgint
564705b261ecSmrgProcUngrabKey(ClientPtr client)
564805b261ecSmrg{
564905b261ecSmrg    REQUEST(xUngrabKeyReq);
565005b261ecSmrg    WindowPtr pWin;
565135c4bbdfSmrg    GrabPtr tempGrab;
56524642e01fSmrg    DeviceIntPtr keybd = PickKeyboard(client);
565305b261ecSmrg    int rc;
565405b261ecSmrg
565505b261ecSmrg    REQUEST_SIZE_MATCH(xUngrabKeyReq);
56566747b715Smrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess);
565705b261ecSmrg    if (rc != Success)
565835c4bbdfSmrg        return rc;
565905b261ecSmrg
56606747b715Smrg    if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
566135c4bbdfSmrg         (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
566235c4bbdfSmrg        && (stuff->key != AnyKey)) {
566335c4bbdfSmrg        client->errorValue = stuff->key;
566405b261ecSmrg        return BadValue;
566505b261ecSmrg    }
566605b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
566735c4bbdfSmrg        (stuff->modifiers & ~AllModifiersMask)) {
566835c4bbdfSmrg        client->errorValue = stuff->modifiers;
566935c4bbdfSmrg        return BadValue;
567035c4bbdfSmrg    }
567135c4bbdfSmrg    tempGrab = AllocGrab(NULL);
567235c4bbdfSmrg    if (!tempGrab)
567335c4bbdfSmrg        return BadAlloc;
567435c4bbdfSmrg    tempGrab->resource = client->clientAsMask;
567535c4bbdfSmrg    tempGrab->device = keybd;
567635c4bbdfSmrg    tempGrab->window = pWin;
567735c4bbdfSmrg    tempGrab->modifiersDetail.exact = stuff->modifiers;
567835c4bbdfSmrg    tempGrab->modifiersDetail.pMask = NULL;
567935c4bbdfSmrg    tempGrab->modifierDevice = keybd;
568035c4bbdfSmrg    tempGrab->type = KeyPress;
568135c4bbdfSmrg    tempGrab->grabtype = CORE;
568235c4bbdfSmrg    tempGrab->detail.exact = stuff->key;
568335c4bbdfSmrg    tempGrab->detail.pMask = NULL;
568435c4bbdfSmrg    tempGrab->next = NULL;
568535c4bbdfSmrg
568635c4bbdfSmrg    if (!DeletePassiveGrabFromList(tempGrab))
568735c4bbdfSmrg        rc = BadAlloc;
568835c4bbdfSmrg
568935c4bbdfSmrg    FreeGrab(tempGrab);
569035c4bbdfSmrg
569135c4bbdfSmrg    return rc;
569205b261ecSmrg}
569305b261ecSmrg
569405b261ecSmrg/**
569505b261ecSmrg * Server-side protocol handling for GrabKey request.
569605b261ecSmrg *
56974642e01fSmrg * Creates a grab for the client's keyboard and adds it to the list of passive
56984642e01fSmrg * grabs.
569905b261ecSmrg */
570005b261ecSmrgint
570105b261ecSmrgProcGrabKey(ClientPtr client)
570205b261ecSmrg{
570305b261ecSmrg    WindowPtr pWin;
570435c4bbdfSmrg
570505b261ecSmrg    REQUEST(xGrabKeyReq);
570605b261ecSmrg    GrabPtr grab;
57074642e01fSmrg    DeviceIntPtr keybd = PickKeyboard(client);
570805b261ecSmrg    int rc;
57096747b715Smrg    GrabParameters param;
57106747b715Smrg    GrabMask mask;
571105b261ecSmrg
571205b261ecSmrg    REQUEST_SIZE_MATCH(xGrabKeyReq);
57136747b715Smrg
571435c4bbdfSmrg    param = (GrabParameters) {
571535c4bbdfSmrg        .grabtype = CORE,
571635c4bbdfSmrg        .ownerEvents = stuff->ownerEvents,
571735c4bbdfSmrg        .this_device_mode = stuff->keyboardMode,
571835c4bbdfSmrg        .other_devices_mode = stuff->pointerMode,
571935c4bbdfSmrg        .modifiers = stuff->modifiers
572035c4bbdfSmrg    };
57216747b715Smrg
57226747b715Smrg    rc = CheckGrabValues(client, &param);
57236747b715Smrg    if (rc != Success)
57246747b715Smrg        return rc;
57256747b715Smrg
57266747b715Smrg    if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
572735c4bbdfSmrg         (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
572835c4bbdfSmrg        && (stuff->key != AnyKey)) {
572935c4bbdfSmrg        client->errorValue = stuff->key;
573005b261ecSmrg        return BadValue;
573105b261ecSmrg    }
57324642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
573305b261ecSmrg    if (rc != Success)
573435c4bbdfSmrg        return rc;
57356747b715Smrg
57366747b715Smrg    mask.core = (KeyPressMask | KeyReleaseMask);
57376747b715Smrg
573835c4bbdfSmrg    grab = CreateGrab(client->index, keybd, keybd, pWin, CORE, &mask,
57396747b715Smrg                      &param, KeyPress, stuff->key, NullWindow, NullCursor);
574005b261ecSmrg    if (!grab)
574135c4bbdfSmrg        return BadAlloc;
57424642e01fSmrg    return AddPassiveGrabToList(client, grab);
574305b261ecSmrg}
574405b261ecSmrg
574505b261ecSmrg/**
574605b261ecSmrg * Server-side protocol handling for GrabButton request.
574705b261ecSmrg *
57484642e01fSmrg * Creates a grab for the client's ClientPointer and adds it as a passive grab
57494642e01fSmrg * to the list.
575005b261ecSmrg */
575105b261ecSmrgint
575205b261ecSmrgProcGrabButton(ClientPtr client)
575305b261ecSmrg{
575405b261ecSmrg    WindowPtr pWin, confineTo;
575535c4bbdfSmrg
575605b261ecSmrg    REQUEST(xGrabButtonReq);
575705b261ecSmrg    CursorPtr cursor;
575805b261ecSmrg    GrabPtr grab;
57594642e01fSmrg    DeviceIntPtr ptr, modifierDevice;
57604642e01fSmrg    Mask access_mode = DixGrabAccess;
57616747b715Smrg    GrabMask mask;
57626747b715Smrg    GrabParameters param;
576305b261ecSmrg    int rc;
576405b261ecSmrg
576505b261ecSmrg    REQUEST_SIZE_MATCH(xGrabButtonReq);
57667e31ba66Smrg    UpdateCurrentTime();
576705b261ecSmrg    if ((stuff->pointerMode != GrabModeSync) &&
576835c4bbdfSmrg        (stuff->pointerMode != GrabModeAsync)) {
576935c4bbdfSmrg        client->errorValue = stuff->pointerMode;
577005b261ecSmrg        return BadValue;
577105b261ecSmrg    }
577205b261ecSmrg    if ((stuff->keyboardMode != GrabModeSync) &&
577335c4bbdfSmrg        (stuff->keyboardMode != GrabModeAsync)) {
577435c4bbdfSmrg        client->errorValue = stuff->keyboardMode;
577505b261ecSmrg        return BadValue;
577605b261ecSmrg    }
577705b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
577835c4bbdfSmrg        (stuff->modifiers & ~AllModifiersMask)) {
577935c4bbdfSmrg        client->errorValue = stuff->modifiers;
578035c4bbdfSmrg        return BadValue;
578105b261ecSmrg    }
578235c4bbdfSmrg    if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) {
578335c4bbdfSmrg        client->errorValue = stuff->ownerEvents;
578435c4bbdfSmrg        return BadValue;
578505b261ecSmrg    }
578635c4bbdfSmrg    if (stuff->eventMask & ~PointerGrabMask) {
578735c4bbdfSmrg        client->errorValue = stuff->eventMask;
578805b261ecSmrg        return BadValue;
578905b261ecSmrg    }
57904642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
579105b261ecSmrg    if (rc != Success)
579235c4bbdfSmrg        return rc;
579305b261ecSmrg    if (stuff->confineTo == None)
579435c4bbdfSmrg        confineTo = NullWindow;
579505b261ecSmrg    else {
579635c4bbdfSmrg        rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
579735c4bbdfSmrg                             DixSetAttrAccess);
579835c4bbdfSmrg        if (rc != Success)
579935c4bbdfSmrg            return rc;
580005b261ecSmrg    }
580105b261ecSmrg    if (stuff->cursor == None)
580235c4bbdfSmrg        cursor = NullCursor;
580335c4bbdfSmrg    else {
580435c4bbdfSmrg        rc = dixLookupResourceByType((void **) &cursor, stuff->cursor,
580535c4bbdfSmrg                                     RT_CURSOR, client, DixUseAccess);
580635c4bbdfSmrg        if (rc != Success) {
580735c4bbdfSmrg            client->errorValue = stuff->cursor;
580835c4bbdfSmrg            return rc;
580935c4bbdfSmrg        }
581035c4bbdfSmrg        access_mode |= DixForceAccess;
581105b261ecSmrg    }
581205b261ecSmrg
58134642e01fSmrg    ptr = PickPointer(client);
581435c4bbdfSmrg    modifierDevice = GetMaster(ptr, MASTER_KEYBOARD);
58154642e01fSmrg    if (stuff->pointerMode == GrabModeSync ||
581635c4bbdfSmrg        stuff->keyboardMode == GrabModeSync)
581735c4bbdfSmrg        access_mode |= DixFreezeAccess;
58184642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode);
58194642e01fSmrg    if (rc != Success)
582035c4bbdfSmrg        return rc;
582105b261ecSmrg
582235c4bbdfSmrg    param = (GrabParameters) {
582335c4bbdfSmrg        .grabtype = CORE,
582435c4bbdfSmrg        .ownerEvents = stuff->ownerEvents,
582535c4bbdfSmrg        .this_device_mode = stuff->keyboardMode,
582635c4bbdfSmrg        .other_devices_mode = stuff->pointerMode,
582735c4bbdfSmrg        .modifiers = stuff->modifiers
582835c4bbdfSmrg    };
58296747b715Smrg
58306747b715Smrg    mask.core = stuff->eventMask;
58316747b715Smrg
58326747b715Smrg    grab = CreateGrab(client->index, ptr, modifierDevice, pWin,
583335c4bbdfSmrg                      CORE, &mask, &param, ButtonPress,
58346747b715Smrg                      stuff->button, confineTo, cursor);
583505b261ecSmrg    if (!grab)
583635c4bbdfSmrg        return BadAlloc;
58374642e01fSmrg    return AddPassiveGrabToList(client, grab);
583805b261ecSmrg}
583905b261ecSmrg
584005b261ecSmrg/**
584105b261ecSmrg * Server-side protocol handling for UngrabButton request.
584205b261ecSmrg *
58434642e01fSmrg * Deletes a passive grab on the client's ClientPointer from the list.
584405b261ecSmrg */
584505b261ecSmrgint
584605b261ecSmrgProcUngrabButton(ClientPtr client)
584705b261ecSmrg{
584805b261ecSmrg    REQUEST(xUngrabButtonReq);
584905b261ecSmrg    WindowPtr pWin;
585035c4bbdfSmrg    GrabPtr tempGrab;
585105b261ecSmrg    int rc;
58526747b715Smrg    DeviceIntPtr ptr;
585305b261ecSmrg
585405b261ecSmrg    REQUEST_SIZE_MATCH(xUngrabButtonReq);
58557e31ba66Smrg    UpdateCurrentTime();
585605b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
585735c4bbdfSmrg        (stuff->modifiers & ~AllModifiersMask)) {
585835c4bbdfSmrg        client->errorValue = stuff->modifiers;
585935c4bbdfSmrg        return BadValue;
586005b261ecSmrg    }
586105b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
586205b261ecSmrg    if (rc != Success)
586335c4bbdfSmrg        return rc;
58646747b715Smrg
58656747b715Smrg    ptr = PickPointer(client);
58666747b715Smrg
586735c4bbdfSmrg    tempGrab = AllocGrab(NULL);
586835c4bbdfSmrg    if (!tempGrab)
586935c4bbdfSmrg        return BadAlloc;
587035c4bbdfSmrg    tempGrab->resource = client->clientAsMask;
587135c4bbdfSmrg    tempGrab->device = ptr;
587235c4bbdfSmrg    tempGrab->window = pWin;
587335c4bbdfSmrg    tempGrab->modifiersDetail.exact = stuff->modifiers;
587435c4bbdfSmrg    tempGrab->modifiersDetail.pMask = NULL;
587535c4bbdfSmrg    tempGrab->modifierDevice = GetMaster(ptr, MASTER_KEYBOARD);
587635c4bbdfSmrg    tempGrab->type = ButtonPress;
587735c4bbdfSmrg    tempGrab->detail.exact = stuff->button;
587835c4bbdfSmrg    tempGrab->grabtype = CORE;
587935c4bbdfSmrg    tempGrab->detail.pMask = NULL;
588035c4bbdfSmrg    tempGrab->next = NULL;
588135c4bbdfSmrg
588235c4bbdfSmrg    if (!DeletePassiveGrabFromList(tempGrab))
588335c4bbdfSmrg        rc = BadAlloc;
588435c4bbdfSmrg
588535c4bbdfSmrg    FreeGrab(tempGrab);
588635c4bbdfSmrg    return rc;
588705b261ecSmrg}
588805b261ecSmrg
588905b261ecSmrg/**
589005b261ecSmrg * Deactivate any grab that may be on the window, remove the focus.
589105b261ecSmrg * Delete any XInput extension events from the window too. Does not change the
589205b261ecSmrg * window mask. Use just before the window is deleted.
589305b261ecSmrg *
589405b261ecSmrg * If freeResources is set, passive grabs on the window are deleted.
589505b261ecSmrg *
589605b261ecSmrg * @param pWin The window to delete events from.
589705b261ecSmrg * @param freeResources True if resources associated with the window should be
589805b261ecSmrg * deleted.
589905b261ecSmrg */
590005b261ecSmrgvoid
590105b261ecSmrgDeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
590205b261ecSmrg{
590335c4bbdfSmrg    WindowPtr parent;
590435c4bbdfSmrg    DeviceIntPtr mouse = inputInfo.pointer;
590535c4bbdfSmrg    DeviceIntPtr keybd = inputInfo.keyboard;
590635c4bbdfSmrg    FocusClassPtr focus;
590735c4bbdfSmrg    OtherClientsPtr oc;
590835c4bbdfSmrg    GrabPtr passive;
590935c4bbdfSmrg    GrabPtr grab;
591005b261ecSmrg
591105b261ecSmrg    /* Deactivate any grabs performed on this window, before making any
591235c4bbdfSmrg       input focus changes. */
59134642e01fSmrg    grab = mouse->deviceGrab.grab;
591435c4bbdfSmrg    if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
591535c4bbdfSmrg        (*mouse->deviceGrab.DeactivateGrab) (mouse);
591605b261ecSmrg
591705b261ecSmrg    /* Deactivating a keyboard grab should cause focus events. */
59184642e01fSmrg    grab = keybd->deviceGrab.grab;
59194642e01fSmrg    if (grab && (grab->window == pWin))
592035c4bbdfSmrg        (*keybd->deviceGrab.DeactivateGrab) (keybd);
592105b261ecSmrg
59224642e01fSmrg    /* And now the real devices */
592335c4bbdfSmrg    for (mouse = inputInfo.devices; mouse; mouse = mouse->next) {
59244642e01fSmrg        grab = mouse->deviceGrab.grab;
59254642e01fSmrg        if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
592635c4bbdfSmrg            (*mouse->deviceGrab.DeactivateGrab) (mouse);
59274642e01fSmrg    }
592805b261ecSmrg
592935c4bbdfSmrg    for (keybd = inputInfo.devices; keybd; keybd = keybd->next) {
593035c4bbdfSmrg        if (IsKeyboardDevice(keybd)) {
59314642e01fSmrg            focus = keybd->focus;
59324642e01fSmrg
593335c4bbdfSmrg            /* If the focus window is a root window (ie. has no parent)
593435c4bbdfSmrg               then don't delete the focus from it. */
59354642e01fSmrg
593635c4bbdfSmrg            if ((pWin == focus->win) && (pWin->parent != NullWindow)) {
59374642e01fSmrg                int focusEventMode = NotifyNormal;
59384642e01fSmrg
59394642e01fSmrg                /* If a grab is in progress, then alter the mode of focus events. */
59404642e01fSmrg
59414642e01fSmrg                if (keybd->deviceGrab.grab)
59424642e01fSmrg                    focusEventMode = NotifyWhileGrabbed;
59434642e01fSmrg
594435c4bbdfSmrg                switch (focus->revert) {
594535c4bbdfSmrg                case RevertToNone:
594635c4bbdfSmrg                    DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
594735c4bbdfSmrg                    focus->win = NoneWin;
594835c4bbdfSmrg                    focus->traceGood = 0;
594935c4bbdfSmrg                    break;
595035c4bbdfSmrg                case RevertToParent:
595135c4bbdfSmrg                    parent = pWin;
595235c4bbdfSmrg                    do {
595335c4bbdfSmrg                        parent = parent->parent;
595435c4bbdfSmrg                        focus->traceGood--;
595535c4bbdfSmrg                    } while (!parent->realized
595635c4bbdfSmrg                    /* This would be a good protocol change -- windows being
595735c4bbdfSmrg                       reparented during SaveSet processing would cause the
595835c4bbdfSmrg                       focus to revert to the nearest enclosing window which
595935c4bbdfSmrg                       will survive the death of the exiting client, instead
596035c4bbdfSmrg                       of ending up reverting to a dying window and thence
596135c4bbdfSmrg                       to None */
596205b261ecSmrg#ifdef NOTDEF
596335c4bbdfSmrg                             || wClient(parent)->clientGone
596405b261ecSmrg#endif
596535c4bbdfSmrg                        );
596635c4bbdfSmrg                    if (!ActivateFocusInGrab(keybd, pWin, parent))
596735c4bbdfSmrg                        DoFocusEvents(keybd, pWin, parent, focusEventMode);
596835c4bbdfSmrg                    focus->win = parent;
596935c4bbdfSmrg                    focus->revert = RevertToNone;
597035c4bbdfSmrg                    break;
597135c4bbdfSmrg                case RevertToPointerRoot:
597235c4bbdfSmrg                    if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin))
597335c4bbdfSmrg                        DoFocusEvents(keybd, pWin, PointerRootWin,
597435c4bbdfSmrg                                      focusEventMode);
597535c4bbdfSmrg                    focus->win = PointerRootWin;
597635c4bbdfSmrg                    focus->traceGood = 0;
597735c4bbdfSmrg                    break;
59784642e01fSmrg                }
59794642e01fSmrg            }
59804642e01fSmrg        }
598105b261ecSmrg
598235c4bbdfSmrg        if (IsPointerDevice(keybd)) {
59834642e01fSmrg            if (keybd->valuator->motionHintWindow == pWin)
59844642e01fSmrg                keybd->valuator->motionHintWindow = NullWindow;
59854642e01fSmrg        }
59864642e01fSmrg    }
598705b261ecSmrg
598835c4bbdfSmrg    if (freeResources) {
598935c4bbdfSmrg        if (pWin->dontPropagate)
599035c4bbdfSmrg            DontPropagateRefCnts[pWin->dontPropagate]--;
599135c4bbdfSmrg        while ((oc = wOtherClients(pWin)))
599235c4bbdfSmrg            FreeResource(oc->resource, RT_NONE);
599335c4bbdfSmrg        while ((passive = wPassiveGrabs(pWin)))
599435c4bbdfSmrg            FreeResource(passive->resource, RT_NONE);
599535c4bbdfSmrg    }
59964642e01fSmrg
599705b261ecSmrg    DeleteWindowFromAnyExtEvents(pWin, freeResources);
599805b261ecSmrg}
599905b261ecSmrg
600005b261ecSmrg/**
600105b261ecSmrg * Call this whenever some window at or below pWin has changed geometry. If
600205b261ecSmrg * there is a grab on the window, the cursor will be re-confined into the
600305b261ecSmrg * window.
600405b261ecSmrg */
60056747b715Smrgvoid
600605b261ecSmrgCheckCursorConfinement(WindowPtr pWin)
600705b261ecSmrg{
60084642e01fSmrg    GrabPtr grab;
600905b261ecSmrg    WindowPtr confineTo;
60104642e01fSmrg    DeviceIntPtr pDev;
601105b261ecSmrg
601205b261ecSmrg#ifdef PANORAMIX
601335c4bbdfSmrg    if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
601435c4bbdfSmrg        return;
601505b261ecSmrg#endif
601605b261ecSmrg
601735c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
601835c4bbdfSmrg        if (DevHasCursor(pDev)) {
60194642e01fSmrg            grab = pDev->deviceGrab.grab;
602035c4bbdfSmrg            if (grab && (confineTo = grab->confineTo)) {
60214642e01fSmrg                if (!BorderSizeNotEmpty(pDev, confineTo))
602235c4bbdfSmrg                    (*pDev->deviceGrab.DeactivateGrab) (pDev);
60234642e01fSmrg                else if ((pWin == confineTo) || IsParent(pWin, confineTo))
60244642e01fSmrg                    ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
60254642e01fSmrg            }
60264642e01fSmrg        }
602705b261ecSmrg    }
602805b261ecSmrg}
602905b261ecSmrg
603005b261ecSmrgMask
603105b261ecSmrgEventMaskForClient(WindowPtr pWin, ClientPtr client)
603205b261ecSmrg{
603335c4bbdfSmrg    OtherClientsPtr other;
603405b261ecSmrg
603535c4bbdfSmrg    if (wClient(pWin) == client)
603635c4bbdfSmrg        return pWin->eventMask;
603735c4bbdfSmrg    for (other = wOtherClients(pWin); other; other = other->next) {
603835c4bbdfSmrg        if (SameClient(other, client))
603935c4bbdfSmrg            return other->mask;
604005b261ecSmrg    }
604105b261ecSmrg    return 0;
604205b261ecSmrg}
604305b261ecSmrg
604405b261ecSmrg/**
604505b261ecSmrg * Server-side protocol handling for RecolorCursor request.
604605b261ecSmrg */
604705b261ecSmrgint
604805b261ecSmrgProcRecolorCursor(ClientPtr client)
604905b261ecSmrg{
605005b261ecSmrg    CursorPtr pCursor;
605135c4bbdfSmrg    int rc, nscr;
605235c4bbdfSmrg    ScreenPtr pscr;
605335c4bbdfSmrg    Bool displayed;
605435c4bbdfSmrg    SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
605535c4bbdfSmrg
605605b261ecSmrg    REQUEST(xRecolorCursorReq);
605705b261ecSmrg
605805b261ecSmrg    REQUEST_SIZE_MATCH(xRecolorCursorReq);
605935c4bbdfSmrg    rc = dixLookupResourceByType((void **) &pCursor, stuff->cursor, RT_CURSOR,
606035c4bbdfSmrg                                 client, DixWriteAccess);
606135c4bbdfSmrg    if (rc != Success) {
606235c4bbdfSmrg        client->errorValue = stuff->cursor;
606335c4bbdfSmrg        return rc;
606405b261ecSmrg    }
606505b261ecSmrg
606605b261ecSmrg    pCursor->foreRed = stuff->foreRed;
606705b261ecSmrg    pCursor->foreGreen = stuff->foreGreen;
606805b261ecSmrg    pCursor->foreBlue = stuff->foreBlue;
606905b261ecSmrg
607005b261ecSmrg    pCursor->backRed = stuff->backRed;
607105b261ecSmrg    pCursor->backGreen = stuff->backGreen;
607205b261ecSmrg    pCursor->backBlue = stuff->backBlue;
607305b261ecSmrg
607435c4bbdfSmrg    for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
607535c4bbdfSmrg        pscr = screenInfo.screens[nscr];
607605b261ecSmrg#ifdef PANORAMIX
607735c4bbdfSmrg        if (!noPanoramiXExtension)
607835c4bbdfSmrg            displayed = (pscr == pSprite->screen);
607935c4bbdfSmrg        else
608005b261ecSmrg#endif
608135c4bbdfSmrg            displayed = (pscr == pSprite->hotPhys.pScreen);
608235c4bbdfSmrg        (*pscr->RecolorCursor) (PickPointer(client), pscr, pCursor,
608335c4bbdfSmrg                                (pCursor == pSprite->current) && displayed);
608405b261ecSmrg    }
60856747b715Smrg    return Success;
608605b261ecSmrg}
608705b261ecSmrg
608805b261ecSmrg/**
608905b261ecSmrg * Write the given events to a client, swapping the byte order if necessary.
609005b261ecSmrg * To swap the byte ordering, a callback is called that has to be set up for
609105b261ecSmrg * the given event type.
609205b261ecSmrg *
609305b261ecSmrg * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
60944642e01fSmrg * can be more than one. Usually it's just one event.
609505b261ecSmrg *
609605b261ecSmrg * Do not modify the event structure passed in. See comment below.
60974642e01fSmrg *
609805b261ecSmrg * @param pClient Client to send events to.
609905b261ecSmrg * @param count Number of events.
610005b261ecSmrg * @param events The event list.
610105b261ecSmrg */
61026747b715Smrgvoid
610305b261ecSmrgWriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
610405b261ecSmrg{
610505b261ecSmrg#ifdef PANORAMIX
610635c4bbdfSmrg    xEvent eventCopy;
610705b261ecSmrg#endif
610835c4bbdfSmrg    xEvent *eventTo, *eventFrom;
610935c4bbdfSmrg    int i, eventlength = sizeof(xEvent);
611005b261ecSmrg
61116747b715Smrg    if (!pClient || pClient == serverClient || pClient->clientGone)
611235c4bbdfSmrg        return;
61136747b715Smrg
61146747b715Smrg    for (i = 0; i < count; i++)
611535c4bbdfSmrg        if ((events[i].u.u.type & 0x7f) != KeymapNotify)
611635c4bbdfSmrg            events[i].u.u.sequenceNumber = pClient->sequence;
61176747b715Smrg
61186747b715Smrg    /* Let XKB rewrite the state, as it depends on client preferences. */
61196747b715Smrg    XkbFilterEvents(pClient, count, events);
612005b261ecSmrg
612105b261ecSmrg#ifdef PANORAMIX
612235c4bbdfSmrg    if (!noPanoramiXExtension &&
612335c4bbdfSmrg        (screenInfo.screens[0]->x || screenInfo.screens[0]->y)) {
612435c4bbdfSmrg        switch (events->u.u.type) {
612535c4bbdfSmrg        case MotionNotify:
612635c4bbdfSmrg        case ButtonPress:
612735c4bbdfSmrg        case ButtonRelease:
612835c4bbdfSmrg        case KeyPress:
612935c4bbdfSmrg        case KeyRelease:
613035c4bbdfSmrg        case EnterNotify:
613135c4bbdfSmrg        case LeaveNotify:
613235c4bbdfSmrg            /*
613335c4bbdfSmrg               When multiple clients want the same event DeliverEventsToWindow
613435c4bbdfSmrg               passes the same event structure multiple times so we can't
613535c4bbdfSmrg               modify the one passed to us
613635c4bbdfSmrg             */
613735c4bbdfSmrg            count = 1;          /* should always be 1 */
613835c4bbdfSmrg            memcpy(&eventCopy, events, sizeof(xEvent));
613935c4bbdfSmrg            eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x;
614035c4bbdfSmrg            eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y;
614135c4bbdfSmrg            if (eventCopy.u.keyButtonPointer.event ==
614235c4bbdfSmrg                eventCopy.u.keyButtonPointer.root) {
614335c4bbdfSmrg                eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x;
614435c4bbdfSmrg                eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y;
614535c4bbdfSmrg            }
614635c4bbdfSmrg            events = &eventCopy;
614735c4bbdfSmrg            break;
614835c4bbdfSmrg        default:
614935c4bbdfSmrg            break;
615035c4bbdfSmrg        }
615105b261ecSmrg    }
615205b261ecSmrg#endif
615305b261ecSmrg
615435c4bbdfSmrg    if (EventCallback) {
615535c4bbdfSmrg        EventInfoRec eventinfo;
615635c4bbdfSmrg
615735c4bbdfSmrg        eventinfo.client = pClient;
615835c4bbdfSmrg        eventinfo.events = events;
615935c4bbdfSmrg        eventinfo.count = count;
616035c4bbdfSmrg        CallCallbacks(&EventCallback, (void *) &eventinfo);
616105b261ecSmrg    }
616205b261ecSmrg#ifdef XSERVER_DTRACE
616305b261ecSmrg    if (XSERVER_SEND_EVENT_ENABLED()) {
616435c4bbdfSmrg        for (i = 0; i < count; i++) {
616535c4bbdfSmrg            XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]);
616635c4bbdfSmrg        }
616705b261ecSmrg    }
61684642e01fSmrg#endif
61694642e01fSmrg    /* Just a safety check to make sure we only have one GenericEvent, it just
61704642e01fSmrg     * makes things easier for me right now. (whot) */
617135c4bbdfSmrg    for (i = 1; i < count; i++) {
617235c4bbdfSmrg        if (events[i].u.u.type == GenericEvent) {
61734642e01fSmrg            ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n");
61744642e01fSmrg            return;
61754642e01fSmrg        }
61764642e01fSmrg    }
61774642e01fSmrg
617835c4bbdfSmrg    if (events->u.u.type == GenericEvent) {
617935c4bbdfSmrg        eventlength += ((xGenericEvent *) events)->length * 4;
61804642e01fSmrg    }
61814642e01fSmrg
618235c4bbdfSmrg    if (pClient->swapped) {
618335c4bbdfSmrg        if (eventlength > swapEventLen) {
61844642e01fSmrg            swapEventLen = eventlength;
61856747b715Smrg            swapEvent = realloc(swapEvent, swapEventLen);
618635c4bbdfSmrg            if (!swapEvent) {
61874642e01fSmrg                FatalError("WriteEventsToClient: Out of memory.\n");
61884642e01fSmrg                return;
61894642e01fSmrg            }
61904642e01fSmrg        }
61914642e01fSmrg
619235c4bbdfSmrg        for (i = 0; i < count; i++) {
619335c4bbdfSmrg            eventFrom = &events[i];
61944642e01fSmrg            eventTo = swapEvent;
61954642e01fSmrg
619635c4bbdfSmrg            /* Remember to strip off the leading bit of type in case
619735c4bbdfSmrg               this event was sent with "SendEvent." */
619835c4bbdfSmrg            (*EventSwapVector[eventFrom->u.u.type & 0177])
619935c4bbdfSmrg                (eventFrom, eventTo);
62004642e01fSmrg
620135c4bbdfSmrg            WriteToClient(pClient, eventlength, eventTo);
620235c4bbdfSmrg        }
620305b261ecSmrg    }
620435c4bbdfSmrg    else {
62054642e01fSmrg        /* only one GenericEvent, remember? that means either count is 1 and
62064642e01fSmrg         * eventlength is arbitrary or eventlength is 32 and count doesn't
62074642e01fSmrg         * matter. And we're all set. Woohoo. */
620835c4bbdfSmrg        WriteToClient(pClient, count * eventlength, events);
620905b261ecSmrg    }
621005b261ecSmrg}
62114642e01fSmrg
62124642e01fSmrg/*
62136747b715Smrg * Set the client pointer for the given client.
62144642e01fSmrg *
62154642e01fSmrg * A client can have exactly one ClientPointer. Each time a
62164642e01fSmrg * request/reply/event is processed and the choice of devices is ambiguous
62174642e01fSmrg * (e.g. QueryPointer request), the server will pick the ClientPointer (see
62184642e01fSmrg * PickPointer()).
62194642e01fSmrg * If a keyboard is needed, the first keyboard paired with the CP is used.
62204642e01fSmrg */
62216747b715Smrgint
62226747b715SmrgSetClientPointer(ClientPtr client, DeviceIntPtr device)
62234642e01fSmrg{
62246747b715Smrg    int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess);
622535c4bbdfSmrg
62266747b715Smrg    if (rc != Success)
622735c4bbdfSmrg        return rc;
62286747b715Smrg
622935c4bbdfSmrg    if (!IsMaster(device)) {
62304642e01fSmrg        ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n");
62316747b715Smrg        return BadDevice;
623235c4bbdfSmrg    }
623335c4bbdfSmrg    else if (!device->spriteInfo->spriteOwner) {
62344642e01fSmrg        ErrorF("[dix] Device %d does not have a sprite. "
623535c4bbdfSmrg               "Cannot be ClientPointer\n", device->id);
62366747b715Smrg        return BadDevice;
62374642e01fSmrg    }
62384642e01fSmrg    client->clientPtr = device;
62396747b715Smrg    return Success;
62404642e01fSmrg}
62414642e01fSmrg
62424642e01fSmrg/* PickPointer will pick an appropriate pointer for the given client.
62434642e01fSmrg *
62444642e01fSmrg * An "appropriate device" is (in order of priority):
62454642e01fSmrg *  1) A device the given client has a core grab on.
62464642e01fSmrg *  2) A device set as ClientPointer for the given client.
62474642e01fSmrg *  3) The first master device.
62484642e01fSmrg */
62496747b715SmrgDeviceIntPtr
62504642e01fSmrgPickPointer(ClientPtr client)
62514642e01fSmrg{
62524642e01fSmrg    DeviceIntPtr it = inputInfo.devices;
62534642e01fSmrg
62544642e01fSmrg    /* First, check if the client currently has a grab on a device. Even
62554642e01fSmrg     * keyboards count. */
625635c4bbdfSmrg    for (it = inputInfo.devices; it; it = it->next) {
62574642e01fSmrg        GrabPtr grab = it->deviceGrab.grab;
625835c4bbdfSmrg
625935c4bbdfSmrg        if (grab && grab->grabtype == CORE && SameClient(grab, client)) {
62606747b715Smrg            it = GetMaster(it, MASTER_POINTER);
626135c4bbdfSmrg            return it;          /* Always return a core grabbed device */
62624642e01fSmrg        }
62634642e01fSmrg    }
62644642e01fSmrg
626535c4bbdfSmrg    if (!client->clientPtr) {
626635c4bbdfSmrg        it = inputInfo.devices;
626735c4bbdfSmrg        while (it) {
626835c4bbdfSmrg            if (IsMaster(it) && it->spriteInfo->spriteOwner) {
62694642e01fSmrg                client->clientPtr = it;
62704642e01fSmrg                break;
62714642e01fSmrg            }
62724642e01fSmrg            it = it->next;
62734642e01fSmrg        }
62744642e01fSmrg    }
62754642e01fSmrg    return client->clientPtr;
62764642e01fSmrg}
62774642e01fSmrg
62784642e01fSmrg/* PickKeyboard will pick an appropriate keyboard for the given client by
62794642e01fSmrg * searching the list of devices for the keyboard device that is paired with
62804642e01fSmrg * the client's pointer.
62814642e01fSmrg */
62826747b715SmrgDeviceIntPtr
62834642e01fSmrgPickKeyboard(ClientPtr client)
62844642e01fSmrg{
62854642e01fSmrg    DeviceIntPtr ptr = PickPointer(client);
62866747b715Smrg    DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD);
62874642e01fSmrg
628835c4bbdfSmrg    if (!kbd) {
62894642e01fSmrg        ErrorF("[dix] ClientPointer not paired with a keyboard. This "
629035c4bbdfSmrg               "is a bug.\n");
62914642e01fSmrg    }
62924642e01fSmrg
62934642e01fSmrg    return kbd;
62944642e01fSmrg}
62954642e01fSmrg
62964642e01fSmrg/* A client that has one or more core grabs does not get core events from
62974642e01fSmrg * devices it does not have a grab on. Legacy applications behave bad
62984642e01fSmrg * otherwise because they are not used to it and the events interfere.
62994642e01fSmrg * Only applies for core events.
63004642e01fSmrg *
63014642e01fSmrg * Return true if a core event from the device would interfere and should not
63024642e01fSmrg * be delivered.
63034642e01fSmrg */
63044642e01fSmrgBool
630535c4bbdfSmrgIsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent *event)
63064642e01fSmrg{
63074642e01fSmrg    DeviceIntPtr it = inputInfo.devices;
63084642e01fSmrg
630935c4bbdfSmrg    switch (event->u.u.type) {
631035c4bbdfSmrg    case KeyPress:
631135c4bbdfSmrg    case KeyRelease:
631235c4bbdfSmrg    case ButtonPress:
631335c4bbdfSmrg    case ButtonRelease:
631435c4bbdfSmrg    case MotionNotify:
631535c4bbdfSmrg    case EnterNotify:
631635c4bbdfSmrg    case LeaveNotify:
631735c4bbdfSmrg        break;
631835c4bbdfSmrg    default:
631935c4bbdfSmrg        return FALSE;
63204642e01fSmrg    }
63214642e01fSmrg
63226747b715Smrg    if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
63236747b715Smrg        return FALSE;
63246747b715Smrg
632535c4bbdfSmrg    while (it) {
632635c4bbdfSmrg        if (it != dev) {
63274642e01fSmrg            if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client)
632835c4bbdfSmrg                && !it->deviceGrab.fromPassiveGrab) {
63294642e01fSmrg                if ((IsPointerDevice(it) && IsPointerDevice(dev)) ||
633035c4bbdfSmrg                    (IsKeyboardDevice(it) && IsKeyboardDevice(dev)))
63314642e01fSmrg                    return TRUE;
63324642e01fSmrg            }
63334642e01fSmrg        }
63344642e01fSmrg        it = it->next;
63354642e01fSmrg    }
63364642e01fSmrg
63374642e01fSmrg    return FALSE;
63384642e01fSmrg}
63394642e01fSmrg
634035c4bbdfSmrg/* PointerBarrier events are only delivered to the client that created that
634135c4bbdfSmrg * barrier */
634235c4bbdfSmrgstatic Bool
634335c4bbdfSmrgIsWrongPointerBarrierClient(ClientPtr client, DeviceIntPtr dev, xEvent *event)
634435c4bbdfSmrg{
634535c4bbdfSmrg    xXIBarrierEvent *ev = (xXIBarrierEvent*)event;
634635c4bbdfSmrg
634735c4bbdfSmrg    if (ev->type != GenericEvent || ev->extension != IReqCode)
634835c4bbdfSmrg        return FALSE;
634935c4bbdfSmrg
635035c4bbdfSmrg    if (ev->evtype != XI_BarrierHit && ev->evtype != XI_BarrierLeave)
635135c4bbdfSmrg        return FALSE;
635235c4bbdfSmrg
635335c4bbdfSmrg    return client->index != CLIENT_ID(ev->barrier);
635435c4bbdfSmrg}
6355