events.c revision 806e81e9
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
4709ace9065SmrgMask
47135c4bbdfSmrgGetEventMask(DeviceIntPtr dev, xEvent *event, InputClients * other)
4726747b715Smrg{
47335c4bbdfSmrg    int evtype;
47435c4bbdfSmrg
4756747b715Smrg    /* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */
47635c4bbdfSmrg    if ((evtype = xi2_get_type(event))) {
47735c4bbdfSmrg        return GetXI2MaskByte(other->xi2mask, dev, evtype);
47835c4bbdfSmrg    }
47935c4bbdfSmrg    else if (core_get_type(event) != 0)
4806747b715Smrg        return other->mask[XIAllDevices];
4816747b715Smrg    else
4826747b715Smrg        return other->mask[dev->id];
4836747b715Smrg}
4846747b715Smrg
48535c4bbdfSmrgstatic CARD8 criticalEvents[32] = {
48635c4bbdfSmrg    0x7c, 0x30, 0x40            /* key, button, expose, and configure events */
48705b261ecSmrg};
48805b261ecSmrg
4896747b715Smrgstatic void
49035c4bbdfSmrgSyntheticMotion(DeviceIntPtr dev, int x, int y)
49135c4bbdfSmrg{
4926747b715Smrg    int screenno = 0;
4936747b715Smrg
4946747b715Smrg#ifdef PANORAMIX
4956747b715Smrg    if (!noPanoramiXExtension)
4966747b715Smrg        screenno = dev->spriteInfo->sprite->screen->myNum;
4976747b715Smrg#endif
4986747b715Smrg    PostSyntheticMotion(dev, x, y, screenno,
49935c4bbdfSmrg                        (syncEvents.playingEvents) ? syncEvents.time.
50035c4bbdfSmrg                        milliseconds : currentTime.milliseconds);
5016747b715Smrg
5026747b715Smrg}
5036747b715Smrg
50405b261ecSmrg#ifdef PANORAMIX
5054642e01fSmrgstatic void PostNewCursor(DeviceIntPtr pDev);
50605b261ecSmrg
5076747b715Smrgstatic Bool
50835c4bbdfSmrgXineramaSetCursorPosition(DeviceIntPtr pDev, int x, int y, Bool generateEvent)
5096747b715Smrg{
51005b261ecSmrg    ScreenPtr pScreen;
51105b261ecSmrg    int i;
5124642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
51305b261ecSmrg
51405b261ecSmrg    /* x,y are in Screen 0 coordinates.  We need to decide what Screen
5154642e01fSmrg       to send the message too and what the coordinates relative to
51605b261ecSmrg       that screen are. */
51705b261ecSmrg
5184642e01fSmrg    pScreen = pSprite->screen;
5196747b715Smrg    x += screenInfo.screens[0]->x;
5206747b715Smrg    y += screenInfo.screens[0]->y;
52105b261ecSmrg
52235c4bbdfSmrg    if (!point_on_screen(pScreen, x, y)) {
52335c4bbdfSmrg        FOR_NSCREENS(i) {
52435c4bbdfSmrg            if (i == pScreen->myNum)
52535c4bbdfSmrg                continue;
52635c4bbdfSmrg            if (point_on_screen(screenInfo.screens[i], x, y)) {
52735c4bbdfSmrg                pScreen = screenInfo.screens[i];
52835c4bbdfSmrg                break;
52935c4bbdfSmrg            }
53035c4bbdfSmrg        }
53105b261ecSmrg    }
53205b261ecSmrg
5334642e01fSmrg    pSprite->screen = pScreen;
5346747b715Smrg    pSprite->hotPhys.x = x - screenInfo.screens[0]->x;
5356747b715Smrg    pSprite->hotPhys.y = y - screenInfo.screens[0]->y;
5366747b715Smrg    x -= pScreen->x;
5376747b715Smrg    y -= pScreen->y;
53805b261ecSmrg
53935c4bbdfSmrg    return (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent);
54005b261ecSmrg}
54105b261ecSmrg
54205b261ecSmrgstatic void
5434642e01fSmrgXineramaConstrainCursor(DeviceIntPtr pDev)
54405b261ecSmrg{
5454642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
5464642e01fSmrg    ScreenPtr pScreen;
5474642e01fSmrg    BoxRec newBox;
5484642e01fSmrg
5494642e01fSmrg    pScreen = pSprite->screen;
5504642e01fSmrg    newBox = pSprite->physLimits;
55105b261ecSmrg
55205b261ecSmrg    /* Translate the constraining box to the screen
55305b261ecSmrg       the sprite is actually on */
5546747b715Smrg    newBox.x1 += screenInfo.screens[0]->x - pScreen->x;
5556747b715Smrg    newBox.x2 += screenInfo.screens[0]->x - pScreen->x;
5566747b715Smrg    newBox.y1 += screenInfo.screens[0]->y - pScreen->y;
5576747b715Smrg    newBox.y2 += screenInfo.screens[0]->y - pScreen->y;
55805b261ecSmrg
55935c4bbdfSmrg    (*pScreen->ConstrainCursor) (pDev, pScreen, &newBox);
56005b261ecSmrg}
56105b261ecSmrg
56205b261ecSmrgstatic Bool
5634642e01fSmrgXineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
56405b261ecSmrg{
5654642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
5664642e01fSmrg
56735c4bbdfSmrg    if (pWin == screenInfo.screens[0]->root) {
56835c4bbdfSmrg        int i;
56935c4bbdfSmrg
57035c4bbdfSmrg        FOR_NSCREENS(i)
57135c4bbdfSmrg            pSprite->windows[i] = screenInfo.screens[i]->root;
57235c4bbdfSmrg    }
57335c4bbdfSmrg    else {
57435c4bbdfSmrg        PanoramiXRes *win;
57535c4bbdfSmrg        int rc, i;
57635c4bbdfSmrg
57735c4bbdfSmrg        rc = dixLookupResourceByType((void **) &win, pWin->drawable.id,
57835c4bbdfSmrg                                     XRT_WINDOW, serverClient, DixReadAccess);
57935c4bbdfSmrg        if (rc != Success)
58035c4bbdfSmrg            return FALSE;
58135c4bbdfSmrg
58235c4bbdfSmrg        FOR_NSCREENS(i) {
58335c4bbdfSmrg            rc = dixLookupWindow(pSprite->windows + i, win->info[i].id,
58435c4bbdfSmrg                                 serverClient, DixReadAccess);
58535c4bbdfSmrg            if (rc != Success)  /* window is being unmapped */
58635c4bbdfSmrg                return FALSE;
58735c4bbdfSmrg        }
58805b261ecSmrg    }
58905b261ecSmrg    return TRUE;
59005b261ecSmrg}
59105b261ecSmrg
59205b261ecSmrgstatic void
5934642e01fSmrgXineramaConfineCursorToWindow(DeviceIntPtr pDev,
59435c4bbdfSmrg                              WindowPtr pWin, Bool generateEvents)
59505b261ecSmrg{
5964642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
59705b261ecSmrg
5986747b715Smrg    int x, y, off_x, off_y, i;
59905b261ecSmrg
6004e185dc0Smrg    assert(!noPanoramiXExtension);
6014e185dc0Smrg
60235c4bbdfSmrg    if (!XineramaSetWindowPntrs(pDev, pWin))
6036747b715Smrg        return;
6044642e01fSmrg
6056747b715Smrg    i = PanoramiXNumScreens - 1;
60605b261ecSmrg
60735c4bbdfSmrg    RegionCopy(&pSprite->Reg1, &pSprite->windows[i]->borderSize);
6086747b715Smrg    off_x = screenInfo.screens[i]->x;
6096747b715Smrg    off_y = screenInfo.screens[i]->y;
61005b261ecSmrg
61135c4bbdfSmrg    while (i--) {
6126747b715Smrg        x = off_x - screenInfo.screens[i]->x;
6136747b715Smrg        y = off_y - screenInfo.screens[i]->y;
61405b261ecSmrg
61535c4bbdfSmrg        if (x || y)
6166747b715Smrg            RegionTranslate(&pSprite->Reg1, x, y);
61705b261ecSmrg
6186747b715Smrg        RegionUnion(&pSprite->Reg1, &pSprite->Reg1,
61935c4bbdfSmrg                    &pSprite->windows[i]->borderSize);
6204642e01fSmrg
6216747b715Smrg        off_x = screenInfo.screens[i]->x;
6226747b715Smrg        off_y = screenInfo.screens[i]->y;
62305b261ecSmrg    }
62405b261ecSmrg
6256747b715Smrg    pSprite->hotLimits = *RegionExtents(&pSprite->Reg1);
62605b261ecSmrg
62735c4bbdfSmrg    if (RegionNumRects(&pSprite->Reg1) > 1)
6286747b715Smrg        pSprite->hotShape = &pSprite->Reg1;
6296747b715Smrg    else
6306747b715Smrg        pSprite->hotShape = NullRegion;
6314642e01fSmrg
6326747b715Smrg    pSprite->confined = FALSE;
63335c4bbdfSmrg    pSprite->confineWin =
63435c4bbdfSmrg        (pWin == screenInfo.screens[0]->root) ? NullWindow : pWin;
63505b261ecSmrg
6366747b715Smrg    CheckPhysLimits(pDev, pSprite->current, generateEvents, FALSE, NULL);
6376747b715Smrg}
63805b261ecSmrg
63935c4bbdfSmrg#endif                          /* PANORAMIX */
64005b261ecSmrg
6416747b715Smrg/**
6426747b715Smrg * Modifies the filter for the given protocol event type to the given masks.
6436747b715Smrg *
6446747b715Smrg * There's only two callers: UpdateDeviceState() and XI's SetMaskForExtEvent().
6456747b715Smrg * The latter initialises masks for the matching XI events, it's a once-off
6466747b715Smrg * setting.
6476747b715Smrg * UDS however changes the mask for MotionNotify and DeviceMotionNotify each
6486747b715Smrg * time a button is pressed to include the matching ButtonXMotion mask in the
6496747b715Smrg * filter.
6506747b715Smrg *
6516747b715Smrg * @param[in] deviceid The device to modify the filter for.
6526747b715Smrg * @param[in] mask The new filter mask.
6536747b715Smrg * @param[in] event Protocol event type.
6546747b715Smrg */
65505b261ecSmrgvoid
6564642e01fSmrgSetMaskForEvent(int deviceid, Mask mask, int event)
65705b261ecSmrg{
65852397711Smrg    if (deviceid < 0 || deviceid >= MAXDEVICES)
6594642e01fSmrg        FatalError("SetMaskForEvent: bogus device id");
66035c4bbdfSmrg    event_filters[deviceid][event] = mask;
66105b261ecSmrg}
66205b261ecSmrg
6636747b715Smrgvoid
66405b261ecSmrgSetCriticalEvent(int event)
66505b261ecSmrg{
66635c4bbdfSmrg    if (event >= MAXEVENTS)
66735c4bbdfSmrg        FatalError("SetCriticalEvent: bogus event number");
66805b261ecSmrg    criticalEvents[event >> 3] |= 1 << (event & 7);
66905b261ecSmrg}
67005b261ecSmrg
6714642e01fSmrgvoid
6724642e01fSmrgConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
67305b261ecSmrg{
67405b261ecSmrg    BoxRec box;
67505b261ecSmrg    int x = *px, y = *py;
67605b261ecSmrg    int incx = 1, incy = 1;
67705b261ecSmrg
6786747b715Smrg    if (RegionContainsPoint(shape, x, y, &box))
67935c4bbdfSmrg        return;
6806747b715Smrg    box = *RegionExtents(shape);
68105b261ecSmrg    /* this is rather crude */
68205b261ecSmrg    do {
68335c4bbdfSmrg        x += incx;
68435c4bbdfSmrg        if (x >= box.x2) {
68535c4bbdfSmrg            incx = -1;
68635c4bbdfSmrg            x = *px - 1;
68735c4bbdfSmrg        }
68835c4bbdfSmrg        else if (x < box.x1) {
68935c4bbdfSmrg            incx = 1;
69035c4bbdfSmrg            x = *px;
69135c4bbdfSmrg            y += incy;
69235c4bbdfSmrg            if (y >= box.y2) {
69335c4bbdfSmrg                incy = -1;
69435c4bbdfSmrg                y = *py - 1;
69535c4bbdfSmrg            }
69635c4bbdfSmrg            else if (y < box.y1)
69735c4bbdfSmrg                return;         /* should never get here! */
69835c4bbdfSmrg        }
6996747b715Smrg    } while (!RegionContainsPoint(shape, x, y, &box));
70005b261ecSmrg    *px = x;
70105b261ecSmrg    *py = y;
70205b261ecSmrg}
70305b261ecSmrg
70405b261ecSmrgstatic void
70535c4bbdfSmrgCheckPhysLimits(DeviceIntPtr pDev, CursorPtr cursor, Bool generateEvents,
70635c4bbdfSmrg                Bool confineToScreen, /* unused if PanoramiX on */
70735c4bbdfSmrg                ScreenPtr pScreen)    /* unused if PanoramiX on */
70805b261ecSmrg{
70905b261ecSmrg    HotSpot new;
7104642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
71105b261ecSmrg
71205b261ecSmrg    if (!cursor)
71335c4bbdfSmrg        return;
7144642e01fSmrg    new = pSprite->hotPhys;
7156747b715Smrg#ifdef PANORAMIX
7166747b715Smrg    if (!noPanoramiXExtension)
7176747b715Smrg        /* I don't care what the DDX has to say about it */
7186747b715Smrg        pSprite->physLimits = pSprite->hotLimits;
71905b261ecSmrg    else
7206747b715Smrg#endif
7216747b715Smrg    {
7226747b715Smrg        if (pScreen)
7236747b715Smrg            new.pScreen = pScreen;
7246747b715Smrg        else
7256747b715Smrg            pScreen = new.pScreen;
7266747b715Smrg        (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits,
72735c4bbdfSmrg                                  &pSprite->physLimits);
7286747b715Smrg        pSprite->confined = confineToScreen;
72935c4bbdfSmrg        (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
7306747b715Smrg    }
7316747b715Smrg
7326747b715Smrg    /* constrain the pointer to those limits */
7334642e01fSmrg    if (new.x < pSprite->physLimits.x1)
73435c4bbdfSmrg        new.x = pSprite->physLimits.x1;
73535c4bbdfSmrg    else if (new.x >= pSprite->physLimits.x2)
73635c4bbdfSmrg        new.x = pSprite->physLimits.x2 - 1;
7374642e01fSmrg    if (new.y < pSprite->physLimits.y1)
73835c4bbdfSmrg        new.y = pSprite->physLimits.y1;
73935c4bbdfSmrg    else if (new.y >= pSprite->physLimits.y2)
74035c4bbdfSmrg        new.y = pSprite->physLimits.y2 - 1;
7414642e01fSmrg    if (pSprite->hotShape)
74235c4bbdfSmrg        ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y);
7436747b715Smrg    if ((
7446747b715Smrg#ifdef PANORAMIX
7456747b715Smrg            noPanoramiXExtension &&
7466747b715Smrg#endif
7476747b715Smrg            (pScreen != pSprite->hotPhys.pScreen)) ||
74835c4bbdfSmrg        (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y)) {
7496747b715Smrg#ifdef PANORAMIX
7506747b715Smrg        if (!noPanoramiXExtension)
75135c4bbdfSmrg            XineramaSetCursorPosition(pDev, new.x, new.y, generateEvents);
7526747b715Smrg        else
7536747b715Smrg#endif
7546747b715Smrg        {
7556747b715Smrg            if (pScreen != pSprite->hotPhys.pScreen)
7566747b715Smrg                pSprite->hotPhys = new;
7576747b715Smrg            (*pScreen->SetCursorPosition)
7586747b715Smrg                (pDev, pScreen, new.x, new.y, generateEvents);
7596747b715Smrg        }
7604642e01fSmrg        if (!generateEvents)
7616747b715Smrg            SyntheticMotion(pDev, new.x, new.y);
76205b261ecSmrg    }
7636747b715Smrg
7646747b715Smrg#ifdef PANORAMIX
7656747b715Smrg    /* Tell DDX what the limits are */
7666747b715Smrg    if (!noPanoramiXExtension)
7676747b715Smrg        XineramaConstrainCursor(pDev);
7686747b715Smrg#endif
76905b261ecSmrg}
77005b261ecSmrg
77105b261ecSmrgstatic void
77235c4bbdfSmrgCheckVirtualMotion(DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin)
77305b261ecSmrg{
7744642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
7756747b715Smrg    RegionPtr reg = NULL;
7766747b715Smrg    DeviceEvent *ev = NULL;
7774642e01fSmrg
77835c4bbdfSmrg    if (qe) {
7796747b715Smrg        ev = &qe->event->device_event;
78035c4bbdfSmrg        switch (ev->type) {
78135c4bbdfSmrg        case ET_Motion:
78235c4bbdfSmrg        case ET_ButtonPress:
78335c4bbdfSmrg        case ET_ButtonRelease:
78435c4bbdfSmrg        case ET_KeyPress:
78535c4bbdfSmrg        case ET_KeyRelease:
78635c4bbdfSmrg        case ET_ProximityIn:
78735c4bbdfSmrg        case ET_ProximityOut:
78835c4bbdfSmrg            pSprite->hot.pScreen = qe->pScreen;
78935c4bbdfSmrg            pSprite->hot.x = ev->root_x;
79035c4bbdfSmrg            pSprite->hot.y = ev->root_y;
79135c4bbdfSmrg            pWin =
79235c4bbdfSmrg                pDev->deviceGrab.grab ? pDev->deviceGrab.grab->
79335c4bbdfSmrg                confineTo : NullWindow;
79435c4bbdfSmrg            break;
79535c4bbdfSmrg        default:
79635c4bbdfSmrg            break;
7976747b715Smrg        }
79805b261ecSmrg    }
79935c4bbdfSmrg    if (pWin) {
80035c4bbdfSmrg        BoxRec lims;
80105b261ecSmrg
8026747b715Smrg#ifdef PANORAMIX
8036747b715Smrg        if (!noPanoramiXExtension) {
8046747b715Smrg            int x, y, off_x, off_y, i;
8056747b715Smrg
80635c4bbdfSmrg            if (!XineramaSetWindowPntrs(pDev, pWin))
8076747b715Smrg                return;
8086747b715Smrg
8096747b715Smrg            i = PanoramiXNumScreens - 1;
8106747b715Smrg
81135c4bbdfSmrg            RegionCopy(&pSprite->Reg2, &pSprite->windows[i]->borderSize);
8126747b715Smrg            off_x = screenInfo.screens[i]->x;
8136747b715Smrg            off_y = screenInfo.screens[i]->y;
8146747b715Smrg
81535c4bbdfSmrg            while (i--) {
8166747b715Smrg                x = off_x - screenInfo.screens[i]->x;
8176747b715Smrg                y = off_y - screenInfo.screens[i]->y;
8186747b715Smrg
81935c4bbdfSmrg                if (x || y)
8206747b715Smrg                    RegionTranslate(&pSprite->Reg2, x, y);
8216747b715Smrg
8226747b715Smrg                RegionUnion(&pSprite->Reg2, &pSprite->Reg2,
82335c4bbdfSmrg                            &pSprite->windows[i]->borderSize);
8246747b715Smrg
8256747b715Smrg                off_x = screenInfo.screens[i]->x;
8266747b715Smrg                off_y = screenInfo.screens[i]->y;
8276747b715Smrg            }
82835c4bbdfSmrg        }
82935c4bbdfSmrg        else
8306747b715Smrg#endif
8316747b715Smrg        {
83235c4bbdfSmrg            if (pSprite->hot.pScreen != pWin->drawable.pScreen) {
8336747b715Smrg                pSprite->hot.pScreen = pWin->drawable.pScreen;
8346747b715Smrg                pSprite->hot.x = pSprite->hot.y = 0;
8356747b715Smrg            }
8366747b715Smrg        }
8376747b715Smrg
83835c4bbdfSmrg        lims = *RegionExtents(&pWin->borderSize);
83935c4bbdfSmrg        if (pSprite->hot.x < lims.x1)
84035c4bbdfSmrg            pSprite->hot.x = lims.x1;
84135c4bbdfSmrg        else if (pSprite->hot.x >= lims.x2)
84235c4bbdfSmrg            pSprite->hot.x = lims.x2 - 1;
84335c4bbdfSmrg        if (pSprite->hot.y < lims.y1)
84435c4bbdfSmrg            pSprite->hot.y = lims.y1;
84535c4bbdfSmrg        else if (pSprite->hot.y >= lims.y2)
84635c4bbdfSmrg            pSprite->hot.y = lims.y2 - 1;
8476747b715Smrg
8486747b715Smrg#ifdef PANORAMIX
84935c4bbdfSmrg        if (!noPanoramiXExtension) {
8506747b715Smrg            if (RegionNumRects(&pSprite->Reg2) > 1)
8516747b715Smrg                reg = &pSprite->Reg2;
8526747b715Smrg
85335c4bbdfSmrg        }
85435c4bbdfSmrg        else
8556747b715Smrg#endif
8566747b715Smrg        {
8576747b715Smrg            if (wBoundingShape(pWin))
8586747b715Smrg                reg = &pWin->borderSize;
8596747b715Smrg        }
8606747b715Smrg
8616747b715Smrg        if (reg)
8626747b715Smrg            ConfineToShape(pDev, reg, &pSprite->hot.x, &pSprite->hot.y);
8636747b715Smrg
86435c4bbdfSmrg        if (qe && ev) {
86535c4bbdfSmrg            qe->pScreen = pSprite->hot.pScreen;
86635c4bbdfSmrg            ev->root_x = pSprite->hot.x;
86735c4bbdfSmrg            ev->root_y = pSprite->hot.y;
86835c4bbdfSmrg        }
86905b261ecSmrg    }
8706747b715Smrg#ifdef PANORAMIX
87135c4bbdfSmrg    if (noPanoramiXExtension)   /* No typo. Only set the root win if disabled */
8726747b715Smrg#endif
8739ace9065Smrg        RootWindow(pDev->spriteInfo->sprite) = pSprite->hot.pScreen->root;
87405b261ecSmrg}
87505b261ecSmrg
87605b261ecSmrgstatic void
87735c4bbdfSmrgConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents,
87835c4bbdfSmrg                      Bool confineToScreen)
87905b261ecSmrg{
8804642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
88105b261ecSmrg
88235c4bbdfSmrg    if (syncEvents.playingEvents) {
88335c4bbdfSmrg        CheckVirtualMotion(pDev, (QdEventPtr) NULL, pWin);
88435c4bbdfSmrg        SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y);
88505b261ecSmrg    }
88635c4bbdfSmrg    else {
8877e31ba66Smrg        ScreenPtr pScreen = pWin->drawable.pScreen;
8887e31ba66Smrg
8896747b715Smrg#ifdef PANORAMIX
89035c4bbdfSmrg        if (!noPanoramiXExtension) {
8916747b715Smrg            XineramaConfineCursorToWindow(pDev, pWin, generateEvents);
8926747b715Smrg            return;
8936747b715Smrg        }
8946747b715Smrg#endif
89535c4bbdfSmrg        pSprite->hotLimits = *RegionExtents(&pWin->borderSize);
89635c4bbdfSmrg        pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize
89735c4bbdfSmrg            : NullRegion;
8984642e01fSmrg        CheckPhysLimits(pDev, pSprite->current, generateEvents,
8996747b715Smrg                        confineToScreen, pWin->drawable.pScreen);
9007e31ba66Smrg
9017e31ba66Smrg        if (*pScreen->CursorConfinedTo)
9027e31ba66Smrg            (*pScreen->CursorConfinedTo) (pDev, pScreen, pWin);
90305b261ecSmrg    }
90405b261ecSmrg}
90505b261ecSmrg
9066747b715SmrgBool
9074642e01fSmrgPointerConfinedToScreen(DeviceIntPtr pDev)
90805b261ecSmrg{
9094642e01fSmrg    return pDev->spriteInfo->sprite->confined;
91005b261ecSmrg}
91105b261ecSmrg
91205b261ecSmrg/**
91305b261ecSmrg * Update the sprite cursor to the given cursor.
91405b261ecSmrg *
91505b261ecSmrg * ChangeToCursor() will display the new cursor and free the old cursor (if
91605b261ecSmrg * applicable). If the provided cursor is already the updated cursor, nothing
91705b261ecSmrg * happens.
91805b261ecSmrg */
91905b261ecSmrgstatic void
9204642e01fSmrgChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
92105b261ecSmrg{
9224642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
9236747b715Smrg    ScreenPtr pScreen;
92405b261ecSmrg
92535c4bbdfSmrg    if (cursor != pSprite->current) {
92635c4bbdfSmrg        if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
92735c4bbdfSmrg            (pSprite->current->bits->yhot != cursor->bits->yhot))
92835c4bbdfSmrg            CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined,
92935c4bbdfSmrg                            (ScreenPtr) NULL);
9306747b715Smrg#ifdef PANORAMIX
9316747b715Smrg        /* XXX: is this really necessary?? (whot) */
9326747b715Smrg        if (!noPanoramiXExtension)
9336747b715Smrg            pScreen = pSprite->screen;
9346747b715Smrg        else
9356747b715Smrg#endif
9366747b715Smrg            pScreen = pSprite->hotPhys.pScreen;
9376747b715Smrg
93835c4bbdfSmrg        (*pScreen->DisplayCursor) (pDev, pScreen, cursor);
93935c4bbdfSmrg        FreeCursor(pSprite->current, (Cursor) 0);
94035c4bbdfSmrg        pSprite->current = RefCursor(cursor);
94105b261ecSmrg    }
94205b261ecSmrg}
94305b261ecSmrg
94405b261ecSmrg/**
9454642e01fSmrg * @returns true if b is a descendent of a
94605b261ecSmrg */
94705b261ecSmrgBool
94805b261ecSmrgIsParent(WindowPtr a, WindowPtr b)
94905b261ecSmrg{
95005b261ecSmrg    for (b = b->parent; b; b = b->parent)
95135c4bbdfSmrg        if (b == a)
95235c4bbdfSmrg            return TRUE;
95305b261ecSmrg    return FALSE;
95405b261ecSmrg}
95505b261ecSmrg
95605b261ecSmrg/**
95705b261ecSmrg * Update the cursor displayed on the screen.
95805b261ecSmrg *
9594642e01fSmrg * Called whenever a cursor may have changed shape or position.
96005b261ecSmrg */
96105b261ecSmrgstatic void
9624642e01fSmrgPostNewCursor(DeviceIntPtr pDev)
96305b261ecSmrg{
96405b261ecSmrg    WindowPtr win;
9654642e01fSmrg    GrabPtr grab = pDev->deviceGrab.grab;
96635c4bbdfSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
96735c4bbdfSmrg    CursorPtr pCursor;
96805b261ecSmrg
96905b261ecSmrg    if (syncEvents.playingEvents)
97035c4bbdfSmrg        return;
97135c4bbdfSmrg    if (grab) {
97235c4bbdfSmrg        if (grab->cursor) {
97335c4bbdfSmrg            ChangeToCursor(pDev, grab->cursor);
97435c4bbdfSmrg            return;
97535c4bbdfSmrg        }
97635c4bbdfSmrg        if (IsParent(grab->window, pSprite->win))
97735c4bbdfSmrg            win = pSprite->win;
97835c4bbdfSmrg        else
97935c4bbdfSmrg            win = grab->window;
98005b261ecSmrg    }
98105b261ecSmrg    else
98235c4bbdfSmrg        win = pSprite->win;
98335c4bbdfSmrg    for (; win; win = win->parent) {
98435c4bbdfSmrg        if (win->optional) {
9854642e01fSmrg            pCursor = WindowGetDeviceCursor(win, pDev);
9864642e01fSmrg            if (!pCursor && win->optional->cursor != NullCursor)
9874642e01fSmrg                pCursor = win->optional->cursor;
98835c4bbdfSmrg            if (pCursor) {
9894642e01fSmrg                ChangeToCursor(pDev, pCursor);
9904642e01fSmrg                return;
9914642e01fSmrg            }
99235c4bbdfSmrg        }
9934642e01fSmrg    }
99405b261ecSmrg}
99505b261ecSmrg
99605b261ecSmrg/**
9974642e01fSmrg * @param dev device which you want to know its current root window
9984642e01fSmrg * @return root window where dev's sprite is located
99905b261ecSmrg */
10006747b715SmrgWindowPtr
10014642e01fSmrgGetCurrentRootWindow(DeviceIntPtr dev)
100205b261ecSmrg{
10039ace9065Smrg    return RootWindow(dev->spriteInfo->sprite);
100405b261ecSmrg}
100505b261ecSmrg
100605b261ecSmrg/**
100705b261ecSmrg * @return window underneath the cursor sprite.
100805b261ecSmrg */
10096747b715SmrgWindowPtr
10104642e01fSmrgGetSpriteWindow(DeviceIntPtr pDev)
101105b261ecSmrg{
10124642e01fSmrg    return pDev->spriteInfo->sprite->win;
101305b261ecSmrg}
101405b261ecSmrg
101505b261ecSmrg/**
101605b261ecSmrg * @return current sprite cursor.
101705b261ecSmrg */
10186747b715SmrgCursorPtr
10194642e01fSmrgGetSpriteCursor(DeviceIntPtr pDev)
102005b261ecSmrg{
10214642e01fSmrg    return pDev->spriteInfo->sprite->current;
102205b261ecSmrg}
102305b261ecSmrg
102405b261ecSmrg/**
102505b261ecSmrg * Set x/y current sprite position in screen coordinates.
102605b261ecSmrg */
10276747b715Smrgvoid
10284642e01fSmrgGetSpritePosition(DeviceIntPtr pDev, int *px, int *py)
102905b261ecSmrg{
10304642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
103135c4bbdfSmrg
10324642e01fSmrg    *px = pSprite->hotPhys.x;
10334642e01fSmrg    *py = pSprite->hotPhys.y;
103405b261ecSmrg}
103505b261ecSmrg
103605b261ecSmrg#ifdef PANORAMIX
10376747b715Smrgint
10384642e01fSmrgXineramaGetCursorScreen(DeviceIntPtr pDev)
103905b261ecSmrg{
104035c4bbdfSmrg    if (!noPanoramiXExtension) {
104135c4bbdfSmrg        return pDev->spriteInfo->sprite->screen->myNum;
104235c4bbdfSmrg    }
104335c4bbdfSmrg    else {
104435c4bbdfSmrg        return 0;
104505b261ecSmrg    }
104605b261ecSmrg}
104735c4bbdfSmrg#endif                          /* PANORAMIX */
104805b261ecSmrg
104935c4bbdfSmrg#define TIMESLOP (5 * 60 * 1000)        /* 5 minutes */
105005b261ecSmrg
105105b261ecSmrgstatic void
105235c4bbdfSmrgMonthChangedOrBadTime(CARD32 *ms)
105305b261ecSmrg{
105405b261ecSmrg    /* If the ddx/OS is careless about not processing timestamped events from
105505b261ecSmrg     * different sources in sorted order, then it's possible for time to go
105605b261ecSmrg     * backwards when it should not.  Here we ensure a decent time.
105705b261ecSmrg     */
105835c4bbdfSmrg    if ((currentTime.milliseconds - *ms) > TIMESLOP)
105935c4bbdfSmrg        currentTime.months++;
106005b261ecSmrg    else
106135c4bbdfSmrg        *ms = currentTime.milliseconds;
106235c4bbdfSmrg}
106335c4bbdfSmrg
106435c4bbdfSmrgvoid
106535c4bbdfSmrgNoticeTime(const DeviceIntPtr dev, TimeStamp time)
106635c4bbdfSmrg{
106735c4bbdfSmrg    currentTime = time;
106835c4bbdfSmrg    lastDeviceEventTime[XIAllDevices].time = currentTime;
106935c4bbdfSmrg    lastDeviceEventTime[dev->id].time = currentTime;
107035c4bbdfSmrg
107135c4bbdfSmrg    LastEventTimeToggleResetFlag(dev->id, TRUE);
107235c4bbdfSmrg    LastEventTimeToggleResetFlag(XIAllDevices, TRUE);
107305b261ecSmrg}
107405b261ecSmrg
10756747b715Smrgstatic void
107635c4bbdfSmrgNoticeTimeMillis(const DeviceIntPtr dev, CARD32 *ms)
10776747b715Smrg{
107835c4bbdfSmrg    TimeStamp time;
107935c4bbdfSmrg    if (*ms < currentTime.milliseconds)
108035c4bbdfSmrg        MonthChangedOrBadTime(ms);
108135c4bbdfSmrg    time.months = currentTime.months;
108235c4bbdfSmrg    time.milliseconds = *ms;
108335c4bbdfSmrg    NoticeTime(dev, time);
10846747b715Smrg}
108505b261ecSmrg
108605b261ecSmrgvoid
108735c4bbdfSmrgNoticeEventTime(InternalEvent *ev, DeviceIntPtr dev)
108805b261ecSmrg{
108905b261ecSmrg    if (!syncEvents.playingEvents)
109035c4bbdfSmrg        NoticeTimeMillis(dev, &ev->any.time);
109135c4bbdfSmrg}
109235c4bbdfSmrg
109335c4bbdfSmrgTimeStamp
109435c4bbdfSmrgLastEventTime(int deviceid)
109535c4bbdfSmrg{
109635c4bbdfSmrg    return lastDeviceEventTime[deviceid].time;
109735c4bbdfSmrg}
109835c4bbdfSmrg
109935c4bbdfSmrgBool
110035c4bbdfSmrgLastEventTimeWasReset(int deviceid)
110135c4bbdfSmrg{
110235c4bbdfSmrg    return lastDeviceEventTime[deviceid].reset;
110335c4bbdfSmrg}
110435c4bbdfSmrg
110535c4bbdfSmrgvoid
110635c4bbdfSmrgLastEventTimeToggleResetFlag(int deviceid, Bool state)
110735c4bbdfSmrg{
110835c4bbdfSmrg    lastDeviceEventTime[deviceid].reset = state;
110935c4bbdfSmrg}
111035c4bbdfSmrg
111135c4bbdfSmrgvoid
111235c4bbdfSmrgLastEventTimeToggleResetAll(Bool state)
111335c4bbdfSmrg{
111435c4bbdfSmrg    DeviceIntPtr dev;
111535c4bbdfSmrg    nt_list_for_each_entry(dev, inputInfo.devices, next) {
111635c4bbdfSmrg        LastEventTimeToggleResetFlag(dev->id, FALSE);
111735c4bbdfSmrg    }
111835c4bbdfSmrg    LastEventTimeToggleResetFlag(XIAllDevices, FALSE);
111935c4bbdfSmrg    LastEventTimeToggleResetFlag(XIAllMasterDevices, FALSE);
112005b261ecSmrg}
112105b261ecSmrg
112205b261ecSmrg/**************************************************************************
112305b261ecSmrg *            The following procedures deal with synchronous events       *
112405b261ecSmrg **************************************************************************/
112505b261ecSmrg
11264642e01fSmrg/**
11274642e01fSmrg * EnqueueEvent is a device's processInputProc if a device is frozen.
11284642e01fSmrg * Instead of delivering the events to the client, the event is tacked onto a
11294642e01fSmrg * linked list for later delivery.
11304642e01fSmrg */
113105b261ecSmrgvoid
11326747b715SmrgEnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
113305b261ecSmrg{
113435c4bbdfSmrg    QdEventPtr tail = NULL;
113535c4bbdfSmrg    QdEventPtr qe;
113635c4bbdfSmrg    SpritePtr pSprite = device->spriteInfo->sprite;
113735c4bbdfSmrg    int eventlen;
11386747b715Smrg    DeviceEvent *event = &ev->device_event;
11394642e01fSmrg
114035c4bbdfSmrg    if (!xorg_list_is_empty(&syncEvents.pending))
114135c4bbdfSmrg        tail = xorg_list_last_entry(&syncEvents.pending, QdEventRec, next);
114235c4bbdfSmrg
114335c4bbdfSmrg    NoticeTimeMillis(device, &ev->any.time);
114405b261ecSmrg
114505b261ecSmrg    /* Fix for key repeating bug. */
11464642e01fSmrg    if (device->key != NULL && device->key->xkbInfo != NULL &&
11476747b715Smrg        event->type == ET_KeyRelease)
114835c4bbdfSmrg        AccessXCancelRepeatKey(device->key->xkbInfo, event->detail.key);
114935c4bbdfSmrg
115035c4bbdfSmrg    if (DeviceEventCallback) {
115135c4bbdfSmrg        DeviceEventInfoRec eventinfo;
115235c4bbdfSmrg
115335c4bbdfSmrg        /*  The RECORD spec says that the root window field of motion events
115435c4bbdfSmrg         *  must be valid.  At this point, it hasn't been filled in yet, so
115535c4bbdfSmrg         *  we do it here.  The long expression below is necessary to get
115635c4bbdfSmrg         *  the current root window; the apparently reasonable alternative
115735c4bbdfSmrg         *  GetCurrentRootWindow()->drawable.id doesn't give you the right
115835c4bbdfSmrg         *  answer on the first motion event after a screen change because
115935c4bbdfSmrg         *  the data that GetCurrentRootWindow relies on hasn't been
116035c4bbdfSmrg         *  updated yet.
116135c4bbdfSmrg         */
116235c4bbdfSmrg        if (ev->any.type == ET_Motion)
116335c4bbdfSmrg            ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
116405b261ecSmrg
116535c4bbdfSmrg        eventinfo.event = ev;
116635c4bbdfSmrg        eventinfo.device = device;
116735c4bbdfSmrg        CallCallbacks(&DeviceEventCallback, (void *) &eventinfo);
116835c4bbdfSmrg    }
116935c4bbdfSmrg
117035c4bbdfSmrg    if (event->type == ET_Motion) {
117105b261ecSmrg#ifdef PANORAMIX
117235c4bbdfSmrg        if (!noPanoramiXExtension) {
117335c4bbdfSmrg            event->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
117435c4bbdfSmrg            event->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
117535c4bbdfSmrg        }
117605b261ecSmrg#endif
117735c4bbdfSmrg        pSprite->hotPhys.x = event->root_x;
117835c4bbdfSmrg        pSprite->hotPhys.y = event->root_y;
117935c4bbdfSmrg        /* do motion compression, but not if from different devices */
118035c4bbdfSmrg        if (tail &&
118135c4bbdfSmrg            (tail->event->any.type == ET_Motion) &&
118205b261ecSmrg            (tail->device == device) &&
118335c4bbdfSmrg            (tail->pScreen == pSprite->hotPhys.pScreen)) {
11846747b715Smrg            DeviceEvent *tailev = &tail->event->device_event;
118535c4bbdfSmrg
118635c4bbdfSmrg            tailev->root_x = pSprite->hotPhys.x;
118735c4bbdfSmrg            tailev->root_y = pSprite->hotPhys.y;
118835c4bbdfSmrg            tailev->time = event->time;
118935c4bbdfSmrg            tail->months = currentTime.months;
119035c4bbdfSmrg            return;
119135c4bbdfSmrg        }
119205b261ecSmrg    }
11934642e01fSmrg
11946747b715Smrg    eventlen = event->length;
11954642e01fSmrg
11966747b715Smrg    qe = malloc(sizeof(QdEventRec) + eventlen);
119705b261ecSmrg    if (!qe)
119835c4bbdfSmrg        return;
119935c4bbdfSmrg    xorg_list_init(&qe->next);
120005b261ecSmrg    qe->device = device;
12014642e01fSmrg    qe->pScreen = pSprite->hotPhys.pScreen;
120205b261ecSmrg    qe->months = currentTime.months;
120335c4bbdfSmrg    qe->event = (InternalEvent *) (qe + 1);
12046747b715Smrg    memcpy(qe->event, event, eventlen);
120535c4bbdfSmrg    xorg_list_append(&qe->next, &syncEvents.pending);
120605b261ecSmrg}
120705b261ecSmrg
12084642e01fSmrg/**
12094642e01fSmrg * Run through the list of events queued up in syncEvents.
12104642e01fSmrg * For each event do:
12114642e01fSmrg * If the device for this event is not frozen anymore, take it and process it
12124642e01fSmrg * as usually.
12134642e01fSmrg * After that, check if there's any devices in the list that are not frozen.
12144642e01fSmrg * If there is none, we're done. If there is at least one device that is not
12154642e01fSmrg * frozen, then re-run from the beginning of the event queue.
12164642e01fSmrg */
121735c4bbdfSmrgvoid
121805b261ecSmrgPlayReleasedEvents(void)
121905b261ecSmrg{
122035c4bbdfSmrg    QdEventPtr tmp;
122135c4bbdfSmrg    QdEventPtr qe;
122205b261ecSmrg    DeviceIntPtr dev;
12234642e01fSmrg    DeviceIntPtr pDev;
122405b261ecSmrg
122535c4bbdfSmrg restart:
122635c4bbdfSmrg    xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) {
122735c4bbdfSmrg        if (!qe->device->deviceGrab.sync.frozen) {
122835c4bbdfSmrg            xorg_list_del(&qe->next);
12294642e01fSmrg            pDev = qe->device;
123035c4bbdfSmrg            if (qe->event->any.type == ET_Motion)
123135c4bbdfSmrg                CheckVirtualMotion(pDev, qe, NullWindow);
123235c4bbdfSmrg            syncEvents.time.months = qe->months;
12336747b715Smrg            syncEvents.time.milliseconds = qe->event->any.time;
123405b261ecSmrg#ifdef PANORAMIX
123535c4bbdfSmrg            /* Translate back to the sprite screen since processInputProc
123635c4bbdfSmrg               will translate from sprite screen to screen 0 upon reentry
123735c4bbdfSmrg               to the DIX layer */
123835c4bbdfSmrg            if (!noPanoramiXExtension) {
12396747b715Smrg                DeviceEvent *ev = &qe->event->device_event;
124035c4bbdfSmrg
124135c4bbdfSmrg                switch (ev->type) {
124235c4bbdfSmrg                case ET_Motion:
124335c4bbdfSmrg                case ET_ButtonPress:
124435c4bbdfSmrg                case ET_ButtonRelease:
124535c4bbdfSmrg                case ET_KeyPress:
124635c4bbdfSmrg                case ET_KeyRelease:
124735c4bbdfSmrg                case ET_ProximityIn:
124835c4bbdfSmrg                case ET_ProximityOut:
124935c4bbdfSmrg                case ET_TouchBegin:
125035c4bbdfSmrg                case ET_TouchUpdate:
125135c4bbdfSmrg                case ET_TouchEnd:
125235c4bbdfSmrg                    ev->root_x += screenInfo.screens[0]->x -
125335c4bbdfSmrg                        pDev->spriteInfo->sprite->screen->x;
125435c4bbdfSmrg                    ev->root_y += screenInfo.screens[0]->y -
125535c4bbdfSmrg                        pDev->spriteInfo->sprite->screen->y;
125635c4bbdfSmrg                    break;
125735c4bbdfSmrg                default:
125835c4bbdfSmrg                    break;
12596747b715Smrg                }
12606747b715Smrg
126135c4bbdfSmrg            }
126205b261ecSmrg#endif
126335c4bbdfSmrg            (*qe->device->public.processInputProc) (qe->event, qe->device);
126435c4bbdfSmrg            free(qe);
126535c4bbdfSmrg            for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen;
126635c4bbdfSmrg                 dev = dev->next);
126735c4bbdfSmrg            if (!dev)
126835c4bbdfSmrg                break;
126935c4bbdfSmrg
127035c4bbdfSmrg            /* Playing the event may have unfrozen another device. */
127135c4bbdfSmrg            /* So to play it safe, restart at the head of the queue */
127235c4bbdfSmrg            goto restart;
127335c4bbdfSmrg        }
12744642e01fSmrg    }
127505b261ecSmrg}
127605b261ecSmrg
12774642e01fSmrg/**
12784642e01fSmrg * Freeze or thaw the given devices. The device's processing proc is
12794642e01fSmrg * switched to either the real processing proc (in case of thawing) or an
12804642e01fSmrg * enqueuing processing proc (usually EnqueueEvent()).
12814642e01fSmrg *
12824642e01fSmrg * @param dev The device to freeze/thaw
12834642e01fSmrg * @param frozen True to freeze or false to thaw.
12844642e01fSmrg */
128505b261ecSmrgstatic void
128605b261ecSmrgFreezeThaw(DeviceIntPtr dev, Bool frozen)
128705b261ecSmrg{
12884642e01fSmrg    dev->deviceGrab.sync.frozen = frozen;
128905b261ecSmrg    if (frozen)
129035c4bbdfSmrg        dev->public.processInputProc = dev->public.enqueueInputProc;
129105b261ecSmrg    else
129235c4bbdfSmrg        dev->public.processInputProc = dev->public.realInputProc;
129305b261ecSmrg}
129405b261ecSmrg
12954642e01fSmrg/**
12964642e01fSmrg * Unfreeze devices and replay all events to the respective clients.
12974642e01fSmrg *
12984642e01fSmrg * ComputeFreezes takes the first event in the device's frozen event queue. It
12994642e01fSmrg * runs up the sprite tree (spriteTrace) and searches for the window to replay
13004642e01fSmrg * the events from. If it is found, it checks for passive grabs one down from
13014642e01fSmrg * the window or delivers the events.
13024642e01fSmrg */
13034642e01fSmrgstatic void
130405b261ecSmrgComputeFreezes(void)
130505b261ecSmrg{
130605b261ecSmrg    DeviceIntPtr replayDev = syncEvents.replayDev;
130705b261ecSmrg    WindowPtr w;
130805b261ecSmrg    GrabPtr grab;
130905b261ecSmrg    DeviceIntPtr dev;
131005b261ecSmrg
131105b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
131235c4bbdfSmrg        FreezeThaw(dev, dev->deviceGrab.sync.other ||
131335c4bbdfSmrg                   (dev->deviceGrab.sync.state >= FROZEN));
131435c4bbdfSmrg    if (syncEvents.playingEvents ||
131535c4bbdfSmrg        (!replayDev && xorg_list_is_empty(&syncEvents.pending)))
131635c4bbdfSmrg        return;
131705b261ecSmrg    syncEvents.playingEvents = TRUE;
131835c4bbdfSmrg    if (replayDev) {
131935c4bbdfSmrg        DeviceEvent *event = replayDev->deviceGrab.sync.event;
13206747b715Smrg
132135c4bbdfSmrg        syncEvents.replayDev = (DeviceIntPtr) NULL;
132205b261ecSmrg
13239ace9065Smrg        w = XYToWindow(replayDev->spriteInfo->sprite,
13249ace9065Smrg                       event->root_x, event->root_y);
132535c4bbdfSmrg        if (!CheckDeviceGrabs(replayDev, event, syncEvents.replayWin)) {
132635c4bbdfSmrg            if (IsTouchEvent((InternalEvent *) event)) {
132735c4bbdfSmrg                TouchPointInfoPtr ti =
132835c4bbdfSmrg                    TouchFindByClientID(replayDev, event->touchid);
132935c4bbdfSmrg                BUG_WARN(!ti);
133035c4bbdfSmrg
133135c4bbdfSmrg                TouchListenerAcceptReject(replayDev, ti, 0, XIRejectTouch);
133235c4bbdfSmrg            }
133335c4bbdfSmrg            else if (replayDev->focus &&
133435c4bbdfSmrg                     !IsPointerEvent((InternalEvent *) event))
133535c4bbdfSmrg                DeliverFocusedEvent(replayDev, (InternalEvent *) event, w);
13369ace9065Smrg            else
133735c4bbdfSmrg                DeliverDeviceEvents(w, (InternalEvent *) event, NullGrab,
13389ace9065Smrg                                    NullWindow, replayDev);
13399ace9065Smrg        }
134005b261ecSmrg    }
134135c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
134235c4bbdfSmrg        if (!dev->deviceGrab.sync.frozen) {
134335c4bbdfSmrg            PlayReleasedEvents();
134435c4bbdfSmrg            break;
134535c4bbdfSmrg        }
134605b261ecSmrg    }
134705b261ecSmrg    syncEvents.playingEvents = FALSE;
134835c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
134935c4bbdfSmrg        if (DevHasCursor(dev)) {
13504642e01fSmrg            /* the following may have been skipped during replay,
135135c4bbdfSmrg               so do it now */
135235c4bbdfSmrg            if ((grab = dev->deviceGrab.grab) && grab->confineTo) {
13534642e01fSmrg                if (grab->confineTo->drawable.pScreen !=
135435c4bbdfSmrg                    dev->spriteInfo->sprite->hotPhys.pScreen)
13554642e01fSmrg                    dev->spriteInfo->sprite->hotPhys.x =
13564642e01fSmrg                        dev->spriteInfo->sprite->hotPhys.y = 0;
13574642e01fSmrg                ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE);
13584642e01fSmrg            }
13594642e01fSmrg            else
13604642e01fSmrg                ConfineCursorToWindow(dev,
136135c4bbdfSmrg                                      dev->spriteInfo->sprite->hotPhys.pScreen->
136235c4bbdfSmrg                                      root, TRUE, FALSE);
13634642e01fSmrg            PostNewCursor(dev);
13644642e01fSmrg        }
136505b261ecSmrg    }
136605b261ecSmrg}
136705b261ecSmrg
136805b261ecSmrg#ifdef RANDR
136905b261ecSmrgvoid
137035c4bbdfSmrgScreenRestructured(ScreenPtr pScreen)
137105b261ecSmrg{
137205b261ecSmrg    GrabPtr grab;
13734642e01fSmrg    DeviceIntPtr pDev;
137405b261ecSmrg
137535c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
137635c4bbdfSmrg        if (!IsFloating(pDev) && !DevHasCursor(pDev))
13774642e01fSmrg            continue;
13784642e01fSmrg
13794642e01fSmrg        /* GrabDevice doesn't have a confineTo field, so we don't need to
13804642e01fSmrg         * worry about it. */
138135c4bbdfSmrg        if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
13824642e01fSmrg            if (grab->confineTo->drawable.pScreen
138335c4bbdfSmrg                != pDev->spriteInfo->sprite->hotPhys.pScreen)
138435c4bbdfSmrg                pDev->spriteInfo->sprite->hotPhys.x =
138535c4bbdfSmrg                    pDev->spriteInfo->sprite->hotPhys.y = 0;
13864642e01fSmrg            ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
13874642e01fSmrg        }
13884642e01fSmrg        else
13894642e01fSmrg            ConfineCursorToWindow(pDev,
139035c4bbdfSmrg                                  pDev->spriteInfo->sprite->hotPhys.pScreen->
139135c4bbdfSmrg                                  root, TRUE, FALSE);
139205b261ecSmrg    }
139305b261ecSmrg}
139405b261ecSmrg#endif
139505b261ecSmrg
13964642e01fSmrgstatic void
139705b261ecSmrgCheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
139805b261ecSmrg{
13994642e01fSmrg    GrabPtr grab = thisDev->deviceGrab.grab;
140005b261ecSmrg    DeviceIntPtr dev;
140105b261ecSmrg
140205b261ecSmrg    if (thisMode == GrabModeSync)
140335c4bbdfSmrg        thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT;
140435c4bbdfSmrg    else {                      /* free both if same client owns both */
140535c4bbdfSmrg        thisDev->deviceGrab.sync.state = THAWED;
140635c4bbdfSmrg        if (thisDev->deviceGrab.sync.other &&
140735c4bbdfSmrg            (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) ==
140835c4bbdfSmrg             CLIENT_BITS(grab->resource)))
140935c4bbdfSmrg            thisDev->deviceGrab.sync.other = NullGrab;
141005b261ecSmrg    }
14114642e01fSmrg
141235c4bbdfSmrg    if (IsMaster(thisDev)) {
14134642e01fSmrg        dev = GetPairedDevice(thisDev);
14144642e01fSmrg        if (otherMode == GrabModeSync)
14154642e01fSmrg            dev->deviceGrab.sync.other = grab;
141635c4bbdfSmrg        else {                  /* free both if same client owns both */
14174642e01fSmrg            if (dev->deviceGrab.sync.other &&
141835c4bbdfSmrg                (CLIENT_BITS(dev->deviceGrab.sync.other->resource) ==
141935c4bbdfSmrg                 CLIENT_BITS(grab->resource)))
14204642e01fSmrg                dev->deviceGrab.sync.other = NullGrab;
14214642e01fSmrg        }
142205b261ecSmrg    }
142305b261ecSmrg    ComputeFreezes();
142405b261ecSmrg}
142505b261ecSmrg
14266747b715Smrg/**
14276747b715Smrg * Save the device's master device id. This needs to be done
14286747b715Smrg * if a client directly grabs a slave device that is attached to a master. For
14296747b715Smrg * the duration of the grab, the device is detached, ungrabbing re-attaches it
14306747b715Smrg * though.
14316747b715Smrg *
14326747b715Smrg * We store the ID of the master device only in case the master disappears
14336747b715Smrg * while the device has a grab.
14346747b715Smrg */
14356747b715Smrgstatic void
14366747b715SmrgDetachFromMaster(DeviceIntPtr dev)
14376747b715Smrg{
143835c4bbdfSmrg    if (IsFloating(dev))
14396747b715Smrg        return;
14406747b715Smrg
144135c4bbdfSmrg    dev->saved_master_id = GetMaster(dev, MASTER_ATTACHED)->id;
14426747b715Smrg
14436747b715Smrg    AttachDevice(NULL, dev, NULL);
14446747b715Smrg}
14456747b715Smrg
14466747b715Smrgstatic void
14476747b715SmrgReattachToOldMaster(DeviceIntPtr dev)
14486747b715Smrg{
14496747b715Smrg    DeviceIntPtr master = NULL;
14506747b715Smrg
14516747b715Smrg    if (IsMaster(dev))
14526747b715Smrg        return;
14536747b715Smrg
14546747b715Smrg    dixLookupDevice(&master, dev->saved_master_id, serverClient, DixUseAccess);
14556747b715Smrg
145635c4bbdfSmrg    if (master) {
14576747b715Smrg        AttachDevice(serverClient, dev, master);
145835c4bbdfSmrg        dev->saved_master_id = 0;
145935c4bbdfSmrg    }
146035c4bbdfSmrg}
146135c4bbdfSmrg
146235c4bbdfSmrg/**
146335c4bbdfSmrg * Update touch records when an explicit grab is activated. Any touches owned by
146435c4bbdfSmrg * the grabbing client are updated so the listener state reflects the new grab.
146535c4bbdfSmrg */
146635c4bbdfSmrgstatic void
146735c4bbdfSmrgUpdateTouchesForGrab(DeviceIntPtr mouse)
146835c4bbdfSmrg{
146935c4bbdfSmrg    int i;
147035c4bbdfSmrg
147135c4bbdfSmrg    if (!mouse->touch || mouse->deviceGrab.fromPassiveGrab)
147235c4bbdfSmrg        return;
147335c4bbdfSmrg
147435c4bbdfSmrg    for (i = 0; i < mouse->touch->num_touches; i++) {
147535c4bbdfSmrg        TouchPointInfoPtr ti = mouse->touch->touches + i;
147635c4bbdfSmrg        TouchListener *listener = &ti->listeners[0];
147735c4bbdfSmrg        GrabPtr grab = mouse->deviceGrab.grab;
147835c4bbdfSmrg
147935c4bbdfSmrg        if (ti->active &&
148035c4bbdfSmrg            CLIENT_BITS(listener->listener) == grab->resource) {
148135c4bbdfSmrg            listener->listener = grab->resource;
148235c4bbdfSmrg            listener->level = grab->grabtype;
148335c4bbdfSmrg            listener->state = LISTENER_IS_OWNER;
148435c4bbdfSmrg            listener->window = grab->window;
148535c4bbdfSmrg
148635c4bbdfSmrg            if (grab->grabtype == CORE || grab->grabtype == XI ||
148735c4bbdfSmrg                !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin))
148835c4bbdfSmrg                listener->type = LISTENER_POINTER_GRAB;
148935c4bbdfSmrg            else
149035c4bbdfSmrg                listener->type = LISTENER_GRAB;
149135c4bbdfSmrg            if (listener->grab)
149235c4bbdfSmrg                FreeGrab(listener->grab);
149335c4bbdfSmrg            listener->grab = AllocGrab(grab);
149435c4bbdfSmrg        }
14956747b715Smrg    }
14966747b715Smrg}
14976747b715Smrg
149805b261ecSmrg/**
149905b261ecSmrg * Activate a pointer grab on the given device. A pointer grab will cause all
15004642e01fSmrg * core pointer events of this device to be delivered to the grabbing client only.
15014642e01fSmrg * No other device will send core events to the grab client while the grab is
15024642e01fSmrg * on, but core events will be sent to other clients.
15034642e01fSmrg * Can cause the cursor to change if a grab cursor is set.
15044642e01fSmrg *
15054642e01fSmrg * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab
15064642e01fSmrg * is an implicit grab caused by a ButtonPress event.
15074642e01fSmrg *
150805b261ecSmrg * @param mouse The device to grab.
150905b261ecSmrg * @param grab The grab structure, needs to be setup.
151005b261ecSmrg * @param autoGrab True if the grab was caused by a button down event and not
15114642e01fSmrg * explicitely by a client.
151205b261ecSmrg */
151305b261ecSmrgvoid
15144642e01fSmrgActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
151505b261ecSmrg                    TimeStamp time, Bool autoGrab)
151605b261ecSmrg{
15174642e01fSmrg    GrabInfoPtr grabinfo = &mouse->deviceGrab;
151835c4bbdfSmrg    GrabPtr oldgrab = grabinfo->grab;
15194642e01fSmrg    WindowPtr oldWin = (grabinfo->grab) ?
152035c4bbdfSmrg        grabinfo->grab->window : mouse->spriteInfo->sprite->win;
15214642e01fSmrg    Bool isPassive = autoGrab & ~ImplicitGrabMask;
152205b261ecSmrg
15236747b715Smrg    /* slave devices need to float for the duration of the grab. */
152435c4bbdfSmrg    if (grab->grabtype == XI2 &&
15256747b715Smrg        !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse))
15266747b715Smrg        DetachFromMaster(mouse);
15276747b715Smrg
152835c4bbdfSmrg    if (grab->confineTo) {
152935c4bbdfSmrg        if (grab->confineTo->drawable.pScreen
153035c4bbdfSmrg            != mouse->spriteInfo->sprite->hotPhys.pScreen)
153135c4bbdfSmrg            mouse->spriteInfo->sprite->hotPhys.x =
15324642e01fSmrg                mouse->spriteInfo->sprite->hotPhys.y = 0;
153335c4bbdfSmrg        ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE);
153405b261ecSmrg    }
1535806e81e9Smrg    if (! (grabinfo->grab && oldWin == grabinfo->grab->window
1536806e81e9Smrg			  && oldWin == grab->window))
1537806e81e9Smrg        DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab);
153805b261ecSmrg    mouse->valuator->motionHintWindow = NullWindow;
153905b261ecSmrg    if (syncEvents.playingEvents)
15404642e01fSmrg        grabinfo->grabTime = syncEvents.time;
154105b261ecSmrg    else
154235c4bbdfSmrg        grabinfo->grabTime = time;
154335c4bbdfSmrg    grabinfo->grab = AllocGrab(grab);
15444642e01fSmrg    grabinfo->fromPassiveGrab = isPassive;
15454642e01fSmrg    grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
15464642e01fSmrg    PostNewCursor(mouse);
154735c4bbdfSmrg    UpdateTouchesForGrab(mouse);
154835c4bbdfSmrg    CheckGrabForSyncs(mouse, (Bool) grab->pointerMode,
154935c4bbdfSmrg                      (Bool) grab->keyboardMode);
155035c4bbdfSmrg    if (oldgrab)
155135c4bbdfSmrg        FreeGrab(oldgrab);
155205b261ecSmrg}
155305b261ecSmrg
155405b261ecSmrg/**
155505b261ecSmrg * Delete grab on given device, update the sprite.
155605b261ecSmrg *
15574642e01fSmrg * Extension devices are set up for ActivateKeyboardGrab().
155805b261ecSmrg */
155905b261ecSmrgvoid
156005b261ecSmrgDeactivatePointerGrab(DeviceIntPtr mouse)
156105b261ecSmrg{
15624642e01fSmrg    GrabPtr grab = mouse->deviceGrab.grab;
156305b261ecSmrg    DeviceIntPtr dev;
156435c4bbdfSmrg    Bool wasPassive = mouse->deviceGrab.fromPassiveGrab;
15656747b715Smrg    Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
15666747b715Smrg                        mouse->deviceGrab.implicitGrab);
156735c4bbdfSmrg    XID grab_resource = grab->resource;
156835c4bbdfSmrg    int i;
156935c4bbdfSmrg
157035c4bbdfSmrg    /* If an explicit grab was deactivated, we must remove it from the head of
157135c4bbdfSmrg     * all the touches' listener lists. */
157235c4bbdfSmrg    for (i = 0; !wasPassive && mouse->touch && i < mouse->touch->num_touches; i++) {
157335c4bbdfSmrg        TouchPointInfoPtr ti = mouse->touch->touches + i;
157435c4bbdfSmrg        if (ti->active && TouchResourceIsOwner(ti, grab_resource)) {
157535c4bbdfSmrg            int mode = XIRejectTouch;
157635c4bbdfSmrg            /* Rejecting will generate a TouchEnd, but we must not
157735c4bbdfSmrg               emulate a ButtonRelease here. So pretend the listener
157835c4bbdfSmrg               already has the end event */
157935c4bbdfSmrg            if (grab->grabtype == CORE || grab->grabtype == XI ||
158035c4bbdfSmrg                    !xi2mask_isset(mouse->deviceGrab.grab->xi2mask, mouse, XI_TouchBegin)) {
158135c4bbdfSmrg                mode = XIAcceptTouch;
158235c4bbdfSmrg                /* NOTE: we set the state here, but
158335c4bbdfSmrg                 * ProcessTouchOwnershipEvent() will still call
158435c4bbdfSmrg                 * TouchEmitTouchEnd for this listener. The other half of
158535c4bbdfSmrg                 * this hack is in DeliverTouchEndEvent */
158635c4bbdfSmrg                ti->listeners[0].state = LISTENER_HAS_END;
158735c4bbdfSmrg            }
158835c4bbdfSmrg            TouchListenerAcceptReject(mouse, ti, 0, mode);
158935c4bbdfSmrg        }
159035c4bbdfSmrg    }
159135c4bbdfSmrg
159235c4bbdfSmrg    TouchRemovePointerGrab(mouse);
159305b261ecSmrg
159405b261ecSmrg    mouse->valuator->motionHintWindow = NullWindow;
15954642e01fSmrg    mouse->deviceGrab.grab = NullGrab;
15964642e01fSmrg    mouse->deviceGrab.sync.state = NOT_GRABBED;
15974642e01fSmrg    mouse->deviceGrab.fromPassiveGrab = FALSE;
15984642e01fSmrg
159935c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
160035c4bbdfSmrg        if (dev->deviceGrab.sync.other == grab)
160135c4bbdfSmrg            dev->deviceGrab.sync.other = NullGrab;
160205b261ecSmrg    }
16036747b715Smrg    DoEnterLeaveEvents(mouse, mouse->id, grab->window,
16044642e01fSmrg                       mouse->spriteInfo->sprite->win, NotifyUngrab);
160505b261ecSmrg    if (grab->confineTo)
160635c4bbdfSmrg        ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE);
16074642e01fSmrg    PostNewCursor(mouse);
16084642e01fSmrg
160935c4bbdfSmrg    if (!wasImplicit && grab->grabtype == XI2)
16106747b715Smrg        ReattachToOldMaster(mouse);
16116747b715Smrg
161205b261ecSmrg    ComputeFreezes();
161335c4bbdfSmrg
161435c4bbdfSmrg    FreeGrab(grab);
161505b261ecSmrg}
161605b261ecSmrg
161705b261ecSmrg/**
16184642e01fSmrg * Activate a keyboard grab on the given device.
161905b261ecSmrg *
162005b261ecSmrg * Extension devices have ActivateKeyboardGrab() set as their grabbing proc.
162105b261ecSmrg */
162205b261ecSmrgvoid
162335c4bbdfSmrgActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time,
162435c4bbdfSmrg                     Bool passive)
162505b261ecSmrg{
16264642e01fSmrg    GrabInfoPtr grabinfo = &keybd->deviceGrab;
162735c4bbdfSmrg    GrabPtr oldgrab = grabinfo->grab;
162805b261ecSmrg    WindowPtr oldWin;
162905b261ecSmrg
16306747b715Smrg    /* slave devices need to float for the duration of the grab. */
163135c4bbdfSmrg    if (grab->grabtype == XI2 && keybd->enabled &&
163235c4bbdfSmrg        !(passive & ImplicitGrabMask) && !IsMaster(keybd))
16336747b715Smrg        DetachFromMaster(keybd);
16346747b715Smrg
163535c4bbdfSmrg    if (!keybd->enabled)
163635c4bbdfSmrg        oldWin = NULL;
163735c4bbdfSmrg    else if (grabinfo->grab)
163835c4bbdfSmrg        oldWin = grabinfo->grab->window;
163905b261ecSmrg    else if (keybd->focus)
164035c4bbdfSmrg        oldWin = keybd->focus->win;
164105b261ecSmrg    else
164235c4bbdfSmrg        oldWin = keybd->spriteInfo->sprite->win;
164305b261ecSmrg    if (oldWin == FollowKeyboardWin)
164435c4bbdfSmrg        oldWin = keybd->focus->win;
164505b261ecSmrg    if (keybd->valuator)
164635c4bbdfSmrg        keybd->valuator->motionHintWindow = NullWindow;
1647806e81e9Smrg    if (oldWin &&
1648806e81e9Smrg	! (grabinfo->grab && oldWin == grabinfo->grab->window
1649806e81e9Smrg			  && oldWin == grab->window))
165035c4bbdfSmrg        DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
165105b261ecSmrg    if (syncEvents.playingEvents)
165235c4bbdfSmrg        grabinfo->grabTime = syncEvents.time;
165305b261ecSmrg    else
165435c4bbdfSmrg        grabinfo->grabTime = time;
165535c4bbdfSmrg    grabinfo->grab = AllocGrab(grab);
16564642e01fSmrg    grabinfo->fromPassiveGrab = passive;
16576747b715Smrg    grabinfo->implicitGrab = passive & ImplicitGrabMask;
165835c4bbdfSmrg    CheckGrabForSyncs(keybd, (Bool) grab->keyboardMode,
165935c4bbdfSmrg                      (Bool) grab->pointerMode);
166035c4bbdfSmrg    if (oldgrab)
166135c4bbdfSmrg        FreeGrab(oldgrab);
166205b261ecSmrg}
166305b261ecSmrg
166405b261ecSmrg/**
16654642e01fSmrg * Delete keyboard grab for the given device.
166605b261ecSmrg */
166705b261ecSmrgvoid
166805b261ecSmrgDeactivateKeyboardGrab(DeviceIntPtr keybd)
166905b261ecSmrg{
16704642e01fSmrg    GrabPtr grab = keybd->deviceGrab.grab;
167105b261ecSmrg    DeviceIntPtr dev;
167235c4bbdfSmrg    WindowPtr focusWin;
16736747b715Smrg    Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab &&
16746747b715Smrg                        keybd->deviceGrab.implicitGrab);
167505b261ecSmrg
167605b261ecSmrg    if (keybd->valuator)
167735c4bbdfSmrg        keybd->valuator->motionHintWindow = NullWindow;
16784642e01fSmrg    keybd->deviceGrab.grab = NullGrab;
16794642e01fSmrg    keybd->deviceGrab.sync.state = NOT_GRABBED;
16804642e01fSmrg    keybd->deviceGrab.fromPassiveGrab = FALSE;
16814642e01fSmrg
168235c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
168335c4bbdfSmrg        if (dev->deviceGrab.sync.other == grab)
168435c4bbdfSmrg            dev->deviceGrab.sync.other = NullGrab;
168505b261ecSmrg    }
168635c4bbdfSmrg
168735c4bbdfSmrg    if (keybd->focus)
168835c4bbdfSmrg        focusWin = keybd->focus->win;
168935c4bbdfSmrg    else if (keybd->spriteInfo->sprite)
169035c4bbdfSmrg        focusWin = keybd->spriteInfo->sprite->win;
169135c4bbdfSmrg    else
169235c4bbdfSmrg        focusWin = NullWindow;
169335c4bbdfSmrg
169435c4bbdfSmrg    if (focusWin == FollowKeyboardWin)
169535c4bbdfSmrg        focusWin = inputInfo.keyboard->focus->win;
169635c4bbdfSmrg
169705b261ecSmrg    DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
16984642e01fSmrg
169935c4bbdfSmrg    if (!wasImplicit && grab->grabtype == XI2)
17006747b715Smrg        ReattachToOldMaster(keybd);
17016747b715Smrg
170205b261ecSmrg    ComputeFreezes();
170335c4bbdfSmrg
170435c4bbdfSmrg    FreeGrab(grab);
170505b261ecSmrg}
170605b261ecSmrg
170705b261ecSmrgvoid
170835c4bbdfSmrgAllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState)
170905b261ecSmrg{
171005b261ecSmrg    Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
171105b261ecSmrg    TimeStamp grabTime;
171205b261ecSmrg    DeviceIntPtr dev;
171335c4bbdfSmrg    GrabInfoPtr devgrabinfo, grabinfo = &thisDev->deviceGrab;
171405b261ecSmrg
17154642e01fSmrg    thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
171605b261ecSmrg    thisSynced = FALSE;
171705b261ecSmrg    otherGrabbed = FALSE;
17186747b715Smrg    othersFrozen = FALSE;
17194642e01fSmrg    grabTime = grabinfo->grabTime;
172035c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
17214642e01fSmrg        devgrabinfo = &dev->deviceGrab;
17224642e01fSmrg
172335c4bbdfSmrg        if (dev == thisDev)
172435c4bbdfSmrg            continue;
172535c4bbdfSmrg        if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) {
172635c4bbdfSmrg            if (!(thisGrabbed || otherGrabbed) ||
172735c4bbdfSmrg                (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER))
172835c4bbdfSmrg                grabTime = devgrabinfo->grabTime;
172935c4bbdfSmrg            otherGrabbed = TRUE;
173035c4bbdfSmrg            if (grabinfo->sync.other == devgrabinfo->grab)
173135c4bbdfSmrg                thisSynced = TRUE;
173235c4bbdfSmrg            if (devgrabinfo->sync.state >= FROZEN)
173335c4bbdfSmrg                othersFrozen = TRUE;
173435c4bbdfSmrg        }
173505b261ecSmrg    }
17364642e01fSmrg    if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced))
173735c4bbdfSmrg        return;
173805b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
173935c4bbdfSmrg        (CompareTimeStamps(time, grabTime) == EARLIER))
174035c4bbdfSmrg        return;
174135c4bbdfSmrg    switch (newState) {
174235c4bbdfSmrg    case THAWED:               /* Async */
174335c4bbdfSmrg        if (thisGrabbed)
174435c4bbdfSmrg            grabinfo->sync.state = THAWED;
174535c4bbdfSmrg        if (thisSynced)
174635c4bbdfSmrg            grabinfo->sync.other = NullGrab;
174735c4bbdfSmrg        ComputeFreezes();
174835c4bbdfSmrg        break;
174935c4bbdfSmrg    case FREEZE_NEXT_EVENT:    /* Sync */
175035c4bbdfSmrg        if (thisGrabbed) {
175135c4bbdfSmrg            grabinfo->sync.state = FREEZE_NEXT_EVENT;
175235c4bbdfSmrg            if (thisSynced)
175335c4bbdfSmrg                grabinfo->sync.other = NullGrab;
175435c4bbdfSmrg            ComputeFreezes();
175535c4bbdfSmrg        }
175635c4bbdfSmrg        break;
175735c4bbdfSmrg    case THAWED_BOTH:          /* AsyncBoth */
175835c4bbdfSmrg        if (othersFrozen) {
175935c4bbdfSmrg            for (dev = inputInfo.devices; dev; dev = dev->next) {
176035c4bbdfSmrg                devgrabinfo = &dev->deviceGrab;
176135c4bbdfSmrg                if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
176235c4bbdfSmrg                    devgrabinfo->sync.state = THAWED;
176335c4bbdfSmrg                if (devgrabinfo->sync.other &&
176435c4bbdfSmrg                    SameClient(devgrabinfo->sync.other, client))
176535c4bbdfSmrg                    devgrabinfo->sync.other = NullGrab;
176635c4bbdfSmrg            }
176735c4bbdfSmrg            ComputeFreezes();
176835c4bbdfSmrg        }
176935c4bbdfSmrg        break;
177035c4bbdfSmrg    case FREEZE_BOTH_NEXT_EVENT:       /* SyncBoth */
177135c4bbdfSmrg        if (othersFrozen) {
177235c4bbdfSmrg            for (dev = inputInfo.devices; dev; dev = dev->next) {
177335c4bbdfSmrg                devgrabinfo = &dev->deviceGrab;
177435c4bbdfSmrg                if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
177535c4bbdfSmrg                    devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT;
177635c4bbdfSmrg                if (devgrabinfo->sync.other
177735c4bbdfSmrg                    && SameClient(devgrabinfo->sync.other, client))
177835c4bbdfSmrg                    devgrabinfo->sync.other = NullGrab;
177935c4bbdfSmrg            }
178035c4bbdfSmrg            ComputeFreezes();
178135c4bbdfSmrg        }
178235c4bbdfSmrg        break;
178335c4bbdfSmrg    case NOT_GRABBED:          /* Replay */
178435c4bbdfSmrg        if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT) {
178535c4bbdfSmrg            if (thisSynced)
178635c4bbdfSmrg                grabinfo->sync.other = NullGrab;
178735c4bbdfSmrg            syncEvents.replayDev = thisDev;
178835c4bbdfSmrg            syncEvents.replayWin = grabinfo->grab->window;
178935c4bbdfSmrg            (*grabinfo->DeactivateGrab) (thisDev);
179035c4bbdfSmrg            syncEvents.replayDev = (DeviceIntPtr) NULL;
179135c4bbdfSmrg        }
179235c4bbdfSmrg        break;
179335c4bbdfSmrg    case THAW_OTHERS:          /* AsyncOthers */
179435c4bbdfSmrg        if (othersFrozen) {
179535c4bbdfSmrg            for (dev = inputInfo.devices; dev; dev = dev->next) {
179635c4bbdfSmrg                if (dev == thisDev)
179735c4bbdfSmrg                    continue;
179835c4bbdfSmrg                devgrabinfo = &dev->deviceGrab;
179935c4bbdfSmrg                if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
180035c4bbdfSmrg                    devgrabinfo->sync.state = THAWED;
180135c4bbdfSmrg                if (devgrabinfo->sync.other
180235c4bbdfSmrg                    && SameClient(devgrabinfo->sync.other, client))
180335c4bbdfSmrg                    devgrabinfo->sync.other = NullGrab;
180435c4bbdfSmrg            }
180535c4bbdfSmrg            ComputeFreezes();
180635c4bbdfSmrg        }
180735c4bbdfSmrg        break;
180835c4bbdfSmrg    }
180935c4bbdfSmrg
181035c4bbdfSmrg    /* We've unfrozen the grab. If the grab was a touch grab, we're now the
181135c4bbdfSmrg     * owner and expected to accept/reject it. Reject == ReplayPointer which
181235c4bbdfSmrg     * we've handled in ComputeFreezes() (during DeactivateGrab) above,
181335c4bbdfSmrg     * anything else is accept.
181435c4bbdfSmrg     */
181535c4bbdfSmrg    if (newState != NOT_GRABBED /* Replay */ &&
181635c4bbdfSmrg        IsTouchEvent((InternalEvent*)grabinfo->sync.event)) {
181735c4bbdfSmrg        TouchAcceptAndEnd(thisDev, grabinfo->sync.event->touchid);
181805b261ecSmrg    }
181905b261ecSmrg}
182005b261ecSmrg
182105b261ecSmrg/**
182205b261ecSmrg * Server-side protocol handling for AllowEvents request.
182305b261ecSmrg *
18244642e01fSmrg * Release some events from a frozen device.
182505b261ecSmrg */
182605b261ecSmrgint
182705b261ecSmrgProcAllowEvents(ClientPtr client)
182805b261ecSmrg{
182935c4bbdfSmrg    TimeStamp time;
183035c4bbdfSmrg    DeviceIntPtr mouse = NULL;
183135c4bbdfSmrg    DeviceIntPtr keybd = NULL;
183235c4bbdfSmrg
183305b261ecSmrg    REQUEST(xAllowEventsReq);
183405b261ecSmrg
183505b261ecSmrg    REQUEST_SIZE_MATCH(xAllowEventsReq);
18367e31ba66Smrg    UpdateCurrentTime();
183705b261ecSmrg    time = ClientTimeToServerTime(stuff->time);
18384642e01fSmrg
18394642e01fSmrg    mouse = PickPointer(client);
18404642e01fSmrg    keybd = PickKeyboard(client);
18414642e01fSmrg
184235c4bbdfSmrg    switch (stuff->mode) {
184335c4bbdfSmrg    case ReplayPointer:
184435c4bbdfSmrg        AllowSome(client, time, mouse, NOT_GRABBED);
184535c4bbdfSmrg        break;
184635c4bbdfSmrg    case SyncPointer:
184735c4bbdfSmrg        AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
184835c4bbdfSmrg        break;
184935c4bbdfSmrg    case AsyncPointer:
185035c4bbdfSmrg        AllowSome(client, time, mouse, THAWED);
185135c4bbdfSmrg        break;
185235c4bbdfSmrg    case ReplayKeyboard:
185335c4bbdfSmrg        AllowSome(client, time, keybd, NOT_GRABBED);
185435c4bbdfSmrg        break;
185535c4bbdfSmrg    case SyncKeyboard:
185635c4bbdfSmrg        AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
185735c4bbdfSmrg        break;
185835c4bbdfSmrg    case AsyncKeyboard:
185935c4bbdfSmrg        AllowSome(client, time, keybd, THAWED);
186035c4bbdfSmrg        break;
186135c4bbdfSmrg    case SyncBoth:
186235c4bbdfSmrg        AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
186335c4bbdfSmrg        break;
186435c4bbdfSmrg    case AsyncBoth:
186535c4bbdfSmrg        AllowSome(client, time, keybd, THAWED_BOTH);
186635c4bbdfSmrg        break;
186735c4bbdfSmrg    default:
186835c4bbdfSmrg        client->errorValue = stuff->mode;
186935c4bbdfSmrg        return BadValue;
187005b261ecSmrg    }
187105b261ecSmrg    return Success;
187205b261ecSmrg}
187305b261ecSmrg
187405b261ecSmrg/**
187505b261ecSmrg * Deactivate grabs from any device that has been grabbed by the client.
187605b261ecSmrg */
187705b261ecSmrgvoid
187805b261ecSmrgReleaseActiveGrabs(ClientPtr client)
187905b261ecSmrg{
188005b261ecSmrg    DeviceIntPtr dev;
188135c4bbdfSmrg    Bool done;
188205b261ecSmrg
188305b261ecSmrg    /* XXX CloseDownClient should remove passive grabs before
188405b261ecSmrg     * releasing active grabs.
188505b261ecSmrg     */
188605b261ecSmrg    do {
188735c4bbdfSmrg        done = TRUE;
188835c4bbdfSmrg        for (dev = inputInfo.devices; dev; dev = dev->next) {
188935c4bbdfSmrg            if (dev->deviceGrab.grab &&
189035c4bbdfSmrg                SameClient(dev->deviceGrab.grab, client)) {
189135c4bbdfSmrg                (*dev->deviceGrab.DeactivateGrab) (dev);
189235c4bbdfSmrg                done = FALSE;
189335c4bbdfSmrg            }
189435c4bbdfSmrg        }
189505b261ecSmrg    } while (!done);
189605b261ecSmrg}
189705b261ecSmrg
189805b261ecSmrg/**************************************************************************
189905b261ecSmrg *            The following procedures deal with delivering events        *
190005b261ecSmrg **************************************************************************/
190105b261ecSmrg
190205b261ecSmrg/**
190305b261ecSmrg * Deliver the given events to the given client.
190405b261ecSmrg *
190505b261ecSmrg * More than one event may be delivered at a time. This is the case with
190605b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events.
190705b261ecSmrg *
190805b261ecSmrg * TryClientEvents() is the last station before actually writing the events to
190905b261ecSmrg * the socket. Anything that is not filtered here, will get delivered to the
19104642e01fSmrg * client.
19114642e01fSmrg * An event is only delivered if
191205b261ecSmrg *   - mask and filter match up.
191305b261ecSmrg *   - no other client has a grab on the device that caused the event.
19144642e01fSmrg *
191505b261ecSmrg *
191605b261ecSmrg * @param client The target client to deliver to.
19174642e01fSmrg * @param dev The device the event came from. May be NULL.
191805b261ecSmrg * @param pEvents The events to be delivered.
191905b261ecSmrg * @param count Number of elements in pEvents.
192005b261ecSmrg * @param mask Event mask as set by the window.
192105b261ecSmrg * @param filter Mask based on event type.
19224642e01fSmrg * @param grab Possible grab on the device that caused the event.
192305b261ecSmrg *
192405b261ecSmrg * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
192505b261ecSmrg * client.
192605b261ecSmrg */
19276747b715Smrgint
192835c4bbdfSmrgTryClientEvents(ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
192935c4bbdfSmrg                int count, Mask mask, Mask filter, GrabPtr grab)
193005b261ecSmrg{
193105b261ecSmrg    int type;
193205b261ecSmrg
193305b261ecSmrg#ifdef DEBUG_EVENTS
19346747b715Smrg    ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s",
19356747b715Smrg           pEvents->u.u.type, pEvents->u.u.detail, mask,
19366747b715Smrg           client ? client->index : -1,
19376747b715Smrg           (client && client->clientGone) ? " (gone)" : "");
193805b261ecSmrg#endif
19396747b715Smrg
19406747b715Smrg    if (!client || client == serverClient || client->clientGone) {
194105b261ecSmrg#ifdef DEBUG_EVENTS
19426747b715Smrg        ErrorF(" not delivered to fake/dead client\n");
194305b261ecSmrg#endif
19446747b715Smrg        return 0;
19456747b715Smrg    }
194605b261ecSmrg
194735c4bbdfSmrg    if (filter != CantBeFiltered && !(mask & filter)) {
194835c4bbdfSmrg#ifdef DEBUG_EVENTS
19496747b715Smrg        ErrorF(" filtered\n");
195035c4bbdfSmrg#endif
19516747b715Smrg        return 0;
19526747b715Smrg    }
195305b261ecSmrg
195435c4bbdfSmrg    if (grab && !SameClient(grab, client)) {
195505b261ecSmrg#ifdef DEBUG_EVENTS
19566747b715Smrg        ErrorF(" not delivered due to grab\n");
195705b261ecSmrg#endif
195835c4bbdfSmrg        return -1;              /* don't send, but notify caller */
195905b261ecSmrg    }
19606747b715Smrg
19616747b715Smrg    type = pEvents->u.u.type;
196235c4bbdfSmrg    if (type == MotionNotify) {
196335c4bbdfSmrg        if (mask & PointerMotionHintMask) {
19646747b715Smrg            if (WID(dev->valuator->motionHintWindow) ==
196535c4bbdfSmrg                pEvents->u.keyButtonPointer.event) {
196605b261ecSmrg#ifdef DEBUG_EVENTS
19676747b715Smrg                ErrorF("[dix] \n");
19686747b715Smrg                ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
196905b261ecSmrg#endif
197035c4bbdfSmrg                return 1;       /* don't send, but pretend we did */
19716747b715Smrg            }
19726747b715Smrg            pEvents->u.u.detail = NotifyHint;
19736747b715Smrg        }
197435c4bbdfSmrg        else {
19756747b715Smrg            pEvents->u.u.detail = NotifyNormal;
19766747b715Smrg        }
19776747b715Smrg    }
197835c4bbdfSmrg    else if (type == DeviceMotionNotify) {
197935c4bbdfSmrg        if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer *) pEvents,
19806747b715Smrg                                            mask) != 0)
19816747b715Smrg            return 1;
198235c4bbdfSmrg    }
198335c4bbdfSmrg    else if (type == KeyPress) {
198435c4bbdfSmrg        if (EventIsKeyRepeat(pEvents)) {
198535c4bbdfSmrg            if (!_XkbWantsDetectableAutoRepeat(client)) {
19866747b715Smrg                xEvent release = *pEvents;
198735c4bbdfSmrg
19886747b715Smrg                release.u.u.type = KeyRelease;
19896747b715Smrg                WriteEventsToClient(client, 1, &release);
19906747b715Smrg#ifdef DEBUG_EVENTS
19916747b715Smrg                ErrorF(" (plus fake core release for repeat)");
19926747b715Smrg#endif
199335c4bbdfSmrg            }
199435c4bbdfSmrg            else {
19956747b715Smrg#ifdef DEBUG_EVENTS
19966747b715Smrg                ErrorF(" (detectable autorepeat for core)");
19976747b715Smrg#endif
19986747b715Smrg            }
19996747b715Smrg        }
20006747b715Smrg
200135c4bbdfSmrg    }
200235c4bbdfSmrg    else if (type == DeviceKeyPress) {
200335c4bbdfSmrg        if (EventIsKeyRepeat(pEvents)) {
200435c4bbdfSmrg            if (!_XkbWantsDetectableAutoRepeat(client)) {
200535c4bbdfSmrg                deviceKeyButtonPointer release =
200635c4bbdfSmrg                    *(deviceKeyButtonPointer *) pEvents;
20076747b715Smrg                release.type = DeviceKeyRelease;
20086747b715Smrg#ifdef DEBUG_EVENTS
20096747b715Smrg                ErrorF(" (plus fake xi1 release for repeat)");
20106747b715Smrg#endif
20116747b715Smrg                WriteEventsToClient(client, 1, (xEvent *) &release);
20126747b715Smrg            }
20136747b715Smrg            else {
20146747b715Smrg#ifdef DEBUG_EVENTS
20156747b715Smrg                ErrorF(" (detectable autorepeat for core)");
20166747b715Smrg#endif
20176747b715Smrg            }
20186747b715Smrg        }
20196747b715Smrg    }
20206747b715Smrg
202135c4bbdfSmrg    if (BitIsOn(criticalEvents, type)) {
20226747b715Smrg        if (client->smart_priority < SMART_MAX_PRIORITY)
20236747b715Smrg            client->smart_priority++;
20246747b715Smrg        SetCriticalOutputPending();
202505b261ecSmrg    }
20266747b715Smrg
20276747b715Smrg    WriteEventsToClient(client, count, pEvents);
20286747b715Smrg#ifdef DEBUG_EVENTS
20296747b715Smrg    ErrorF("[dix]  delivered\n");
20306747b715Smrg#endif
20316747b715Smrg    return 1;
203205b261ecSmrg}
203305b261ecSmrg
203435c4bbdfSmrgstatic BOOL
203535c4bbdfSmrgActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win,
203635c4bbdfSmrg                     xEvent *event, Mask deliveryMask)
203735c4bbdfSmrg{
203835c4bbdfSmrg    GrabPtr tempGrab;
203935c4bbdfSmrg    OtherInputMasks *inputMasks;
204035c4bbdfSmrg    CARD8 type = event->u.u.type;
204135c4bbdfSmrg    enum InputLevel grabtype;
204235c4bbdfSmrg
204335c4bbdfSmrg    if (type == ButtonPress)
204435c4bbdfSmrg        grabtype = CORE;
204535c4bbdfSmrg    else if (type == DeviceButtonPress)
204635c4bbdfSmrg        grabtype = XI;
204735c4bbdfSmrg    else if ((type = xi2_get_type(event)) == XI_ButtonPress)
204835c4bbdfSmrg        grabtype = XI2;
204935c4bbdfSmrg    else
205035c4bbdfSmrg        return FALSE;
205135c4bbdfSmrg
205235c4bbdfSmrg    tempGrab = AllocGrab(NULL);
205335c4bbdfSmrg    if (!tempGrab)
205435c4bbdfSmrg        return FALSE;
205535c4bbdfSmrg    tempGrab->next = NULL;
205635c4bbdfSmrg    tempGrab->device = dev;
205735c4bbdfSmrg    tempGrab->resource = client->clientAsMask;
205835c4bbdfSmrg    tempGrab->window = win;
205935c4bbdfSmrg    tempGrab->ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
206035c4bbdfSmrg    tempGrab->eventMask = deliveryMask;
206135c4bbdfSmrg    tempGrab->keyboardMode = GrabModeAsync;
206235c4bbdfSmrg    tempGrab->pointerMode = GrabModeAsync;
206335c4bbdfSmrg    tempGrab->confineTo = NullWindow;
206435c4bbdfSmrg    tempGrab->cursor = NullCursor;
206535c4bbdfSmrg    tempGrab->type = type;
206635c4bbdfSmrg    tempGrab->grabtype = grabtype;
206735c4bbdfSmrg
206835c4bbdfSmrg    /* get the XI and XI2 device mask */
206935c4bbdfSmrg    inputMasks = wOtherInputMasks(win);
207035c4bbdfSmrg    tempGrab->deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id] : 0;
207135c4bbdfSmrg
207235c4bbdfSmrg    if (inputMasks)
207335c4bbdfSmrg        xi2mask_merge(tempGrab->xi2mask, inputMasks->xi2mask);
207435c4bbdfSmrg
207535c4bbdfSmrg    (*dev->deviceGrab.ActivateGrab) (dev, tempGrab,
207635c4bbdfSmrg                                     currentTime, TRUE | ImplicitGrabMask);
207735c4bbdfSmrg    FreeGrab(tempGrab);
207835c4bbdfSmrg    return TRUE;
207935c4bbdfSmrg}
208035c4bbdfSmrg
208135c4bbdfSmrg/**
208235c4bbdfSmrg * Attempt event delivery to the client owning the window.
208335c4bbdfSmrg */
208435c4bbdfSmrgstatic enum EventDeliveryState
208535c4bbdfSmrgDeliverToWindowOwner(DeviceIntPtr dev, WindowPtr win,
208635c4bbdfSmrg                     xEvent *events, int count, Mask filter, GrabPtr grab)
208735c4bbdfSmrg{
208835c4bbdfSmrg    /* if nobody ever wants to see this event, skip some work */
208935c4bbdfSmrg    if (filter != CantBeFiltered &&
209035c4bbdfSmrg        !((wOtherEventMasks(win) | win->eventMask) & filter))
209135c4bbdfSmrg        return EVENT_SKIP;
209235c4bbdfSmrg
209335c4bbdfSmrg    if (IsInterferingGrab(wClient(win), dev, events))
209435c4bbdfSmrg        return EVENT_SKIP;
209535c4bbdfSmrg
209635c4bbdfSmrg    if (!XaceHook(XACE_RECEIVE_ACCESS, wClient(win), win, events, count)) {
209735c4bbdfSmrg        int attempt = TryClientEvents(wClient(win), dev, events,
209835c4bbdfSmrg                                      count, win->eventMask,
209935c4bbdfSmrg                                      filter, grab);
210035c4bbdfSmrg
210135c4bbdfSmrg        if (attempt > 0)
210235c4bbdfSmrg            return EVENT_DELIVERED;
210335c4bbdfSmrg        if (attempt < 0)
210435c4bbdfSmrg            return EVENT_REJECTED;
210535c4bbdfSmrg    }
210635c4bbdfSmrg
210735c4bbdfSmrg    return EVENT_NOT_DELIVERED;
210835c4bbdfSmrg}
210935c4bbdfSmrg
211035c4bbdfSmrg/**
211135c4bbdfSmrg * Get the list of clients that should be tried for event delivery on the
211235c4bbdfSmrg * given window.
211335c4bbdfSmrg *
211435c4bbdfSmrg * @return 1 if the client list should be traversed, zero if the event
211535c4bbdfSmrg * should be skipped.
211635c4bbdfSmrg */
211735c4bbdfSmrgstatic Bool
211835c4bbdfSmrgGetClientsForDelivery(DeviceIntPtr dev, WindowPtr win,
211935c4bbdfSmrg                      xEvent *events, Mask filter, InputClients ** iclients)
212035c4bbdfSmrg{
212135c4bbdfSmrg    int rc = 0;
212235c4bbdfSmrg
212335c4bbdfSmrg    if (core_get_type(events) != 0)
212435c4bbdfSmrg        *iclients = (InputClients *) wOtherClients(win);
212535c4bbdfSmrg    else if (xi2_get_type(events) != 0) {
212635c4bbdfSmrg        OtherInputMasks *inputMasks = wOtherInputMasks(win);
212735c4bbdfSmrg
212835c4bbdfSmrg        /* Has any client selected for the event? */
212935c4bbdfSmrg        if (!WindowXI2MaskIsset(dev, win, events))
213035c4bbdfSmrg            goto out;
213135c4bbdfSmrg        *iclients = inputMasks->inputClients;
213235c4bbdfSmrg    }
213335c4bbdfSmrg    else {
213435c4bbdfSmrg        OtherInputMasks *inputMasks = wOtherInputMasks(win);
213535c4bbdfSmrg
213635c4bbdfSmrg        /* Has any client selected for the event? */
213735c4bbdfSmrg        if (!inputMasks || !(inputMasks->inputEvents[dev->id] & filter))
213835c4bbdfSmrg            goto out;
213935c4bbdfSmrg
214035c4bbdfSmrg        *iclients = inputMasks->inputClients;
214135c4bbdfSmrg    }
214235c4bbdfSmrg
214335c4bbdfSmrg    rc = 1;
214435c4bbdfSmrg out:
214535c4bbdfSmrg    return rc;
214635c4bbdfSmrg}
214735c4bbdfSmrg
214835c4bbdfSmrg/**
214935c4bbdfSmrg * Try delivery on each client in inputclients, provided the event mask
215035c4bbdfSmrg * accepts it and there is no interfering core grab..
215135c4bbdfSmrg */
215235c4bbdfSmrgstatic enum EventDeliveryState
215335c4bbdfSmrgDeliverEventToInputClients(DeviceIntPtr dev, InputClients * inputclients,
215435c4bbdfSmrg                           WindowPtr win, xEvent *events,
215535c4bbdfSmrg                           int count, Mask filter, GrabPtr grab,
215635c4bbdfSmrg                           ClientPtr *client_return, Mask *mask_return)
215735c4bbdfSmrg{
215835c4bbdfSmrg    int attempt;
215935c4bbdfSmrg    enum EventDeliveryState rc = EVENT_NOT_DELIVERED;
216035c4bbdfSmrg    Bool have_device_button_grab_class_client = FALSE;
216135c4bbdfSmrg
216235c4bbdfSmrg    for (; inputclients; inputclients = inputclients->next) {
216335c4bbdfSmrg        Mask mask;
216435c4bbdfSmrg        ClientPtr client = rClient(inputclients);
216535c4bbdfSmrg
216635c4bbdfSmrg        if (IsInterferingGrab(client, dev, events))
216735c4bbdfSmrg            continue;
216835c4bbdfSmrg
216935c4bbdfSmrg        if (IsWrongPointerBarrierClient(client, dev, events))
217035c4bbdfSmrg            continue;
217135c4bbdfSmrg
217235c4bbdfSmrg        mask = GetEventMask(dev, events, inputclients);
217335c4bbdfSmrg
217435c4bbdfSmrg        if (XaceHook(XACE_RECEIVE_ACCESS, client, win, events, count))
217535c4bbdfSmrg            /* do nothing */ ;
217635c4bbdfSmrg        else if ((attempt = TryClientEvents(client, dev,
217735c4bbdfSmrg                                            events, count,
217835c4bbdfSmrg                                            mask, filter, grab))) {
217935c4bbdfSmrg            if (attempt > 0) {
218035c4bbdfSmrg                /*
218135c4bbdfSmrg                 * The order of clients is arbitrary therefore if one
218235c4bbdfSmrg                 * client belongs to DeviceButtonGrabClass make sure to
218335c4bbdfSmrg                 * catch it.
218435c4bbdfSmrg                 */
218535c4bbdfSmrg                if (!have_device_button_grab_class_client) {
218635c4bbdfSmrg                    rc = EVENT_DELIVERED;
218735c4bbdfSmrg                    *client_return = client;
218835c4bbdfSmrg                    *mask_return = mask;
218935c4bbdfSmrg                    /* Success overrides non-success, so if we've been
219035c4bbdfSmrg                     * successful on one client, return that */
219135c4bbdfSmrg                    if (mask & DeviceButtonGrabMask)
219235c4bbdfSmrg                        have_device_button_grab_class_client = TRUE;
219335c4bbdfSmrg                }
219435c4bbdfSmrg            } else if (rc == EVENT_NOT_DELIVERED)
219535c4bbdfSmrg                rc = EVENT_REJECTED;
219635c4bbdfSmrg        }
219735c4bbdfSmrg    }
219835c4bbdfSmrg
219935c4bbdfSmrg    return rc;
220035c4bbdfSmrg}
220135c4bbdfSmrg
220235c4bbdfSmrg/**
220335c4bbdfSmrg * Deliver events to clients registered on the window.
220435c4bbdfSmrg *
220535c4bbdfSmrg * @param client_return On successful delivery, set to the recipient.
220635c4bbdfSmrg * @param mask_return On successful delivery, set to the recipient's event
220735c4bbdfSmrg * mask for this event.
220835c4bbdfSmrg */
220935c4bbdfSmrgstatic enum EventDeliveryState
221035c4bbdfSmrgDeliverEventToWindowMask(DeviceIntPtr dev, WindowPtr win, xEvent *events,
221135c4bbdfSmrg                         int count, Mask filter, GrabPtr grab,
221235c4bbdfSmrg                         ClientPtr *client_return, Mask *mask_return)
221335c4bbdfSmrg{
221435c4bbdfSmrg    InputClients *iclients;
221535c4bbdfSmrg
221635c4bbdfSmrg    if (!GetClientsForDelivery(dev, win, events, filter, &iclients))
221735c4bbdfSmrg        return EVENT_SKIP;
221835c4bbdfSmrg
221935c4bbdfSmrg    return DeliverEventToInputClients(dev, iclients, win, events, count, filter,
222035c4bbdfSmrg                                      grab, client_return, mask_return);
222135c4bbdfSmrg
222235c4bbdfSmrg}
222335c4bbdfSmrg
222405b261ecSmrg/**
222505b261ecSmrg * Deliver events to a window. At this point, we do not yet know if the event
222605b261ecSmrg * actually needs to be delivered. May activate a grab if the event is a
222705b261ecSmrg * button press.
222805b261ecSmrg *
22294642e01fSmrg * Core events are always delivered to the window owner. If the filter is
22304642e01fSmrg * something other than CantBeFiltered, the event is also delivered to other
22314642e01fSmrg * clients with the matching mask on the window.
22324642e01fSmrg *
223305b261ecSmrg * More than one event may be delivered at a time. This is the case with
223405b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events.
22354642e01fSmrg *
223605b261ecSmrg * @param pWin The window that would get the event.
223705b261ecSmrg * @param pEvents The events to be delivered.
223805b261ecSmrg * @param count Number of elements in pEvents.
223905b261ecSmrg * @param filter Mask based on event type.
22404642e01fSmrg * @param grab Possible grab on the device that caused the event.
224105b261ecSmrg *
224235c4bbdfSmrg * @return a positive number if at least one successful delivery has been
224335c4bbdfSmrg * made, 0 if no events were delivered, or a negative number if the event
224435c4bbdfSmrg * has not been delivered _and_ rejected by at least one client.
224505b261ecSmrg */
224605b261ecSmrgint
22474642e01fSmrgDeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
224835c4bbdfSmrg                      *pEvents, int count, Mask filter, GrabPtr grab)
224905b261ecSmrg{
225005b261ecSmrg    int deliveries = 0, nondeliveries = 0;
225105b261ecSmrg    ClientPtr client = NullClient;
225235c4bbdfSmrg    Mask deliveryMask = 0;      /* If a grab occurs due to a button press, then
225335c4bbdfSmrg                                   this mask is the mask of the grab. */
225405b261ecSmrg    int type = pEvents->u.u.type;
225505b261ecSmrg
22566747b715Smrg    /* Deliver to window owner */
225735c4bbdfSmrg    if ((filter == CantBeFiltered) || core_get_type(pEvents) != 0) {
225835c4bbdfSmrg        enum EventDeliveryState rc;
22594642e01fSmrg
226035c4bbdfSmrg        rc = DeliverToWindowOwner(pDev, pWin, pEvents, count, filter, grab);
22614642e01fSmrg
226235c4bbdfSmrg        switch (rc) {
226335c4bbdfSmrg        case EVENT_SKIP:
226435c4bbdfSmrg            return 0;
226535c4bbdfSmrg        case EVENT_REJECTED:
226635c4bbdfSmrg            nondeliveries--;
226735c4bbdfSmrg            break;
226835c4bbdfSmrg        case EVENT_DELIVERED:
226935c4bbdfSmrg            /* We delivered to the owner, with our event mask */
227035c4bbdfSmrg            deliveries++;
227135c4bbdfSmrg            client = wClient(pWin);
227235c4bbdfSmrg            deliveryMask = pWin->eventMask;
227335c4bbdfSmrg            break;
227435c4bbdfSmrg        case EVENT_NOT_DELIVERED:
227535c4bbdfSmrg            break;
227635c4bbdfSmrg        }
227705b261ecSmrg    }
22786747b715Smrg
22796747b715Smrg    /* CantBeFiltered means only window owner gets the event */
228035c4bbdfSmrg    if (filter != CantBeFiltered) {
228135c4bbdfSmrg        enum EventDeliveryState rc;
228235c4bbdfSmrg
228335c4bbdfSmrg        rc = DeliverEventToWindowMask(pDev, pWin, pEvents, count, filter,
228435c4bbdfSmrg                                      grab, &client, &deliveryMask);
22854642e01fSmrg
228635c4bbdfSmrg        switch (rc) {
228735c4bbdfSmrg        case EVENT_SKIP:
228835c4bbdfSmrg            return 0;
228935c4bbdfSmrg        case EVENT_REJECTED:
229035c4bbdfSmrg            nondeliveries--;
229135c4bbdfSmrg            break;
229235c4bbdfSmrg        case EVENT_DELIVERED:
229335c4bbdfSmrg            deliveries++;
229435c4bbdfSmrg            break;
229535c4bbdfSmrg        case EVENT_NOT_DELIVERED:
229635c4bbdfSmrg            break;
22974642e01fSmrg        }
229835c4bbdfSmrg    }
22994642e01fSmrg
230035c4bbdfSmrg    if (deliveries) {
230135c4bbdfSmrg        /*
230235c4bbdfSmrg         * Note that since core events are delivered first, an implicit grab may
230335c4bbdfSmrg         * be activated on a core grab, stopping the XI events.
230435c4bbdfSmrg         */
230535c4bbdfSmrg        if (!grab &&
230635c4bbdfSmrg            ActivateImplicitGrab(pDev, client, pWin, pEvents, deliveryMask))
230735c4bbdfSmrg            /* grab activated */ ;
230835c4bbdfSmrg        else if (type == MotionNotify)
230935c4bbdfSmrg            pDev->valuator->motionHintWindow = pWin;
231035c4bbdfSmrg        else if (type == DeviceMotionNotify || type == DeviceButtonPress)
231135c4bbdfSmrg            CheckDeviceGrabAndHintWindow(pWin, type,
231235c4bbdfSmrg                                         (deviceKeyButtonPointer *) pEvents,
231335c4bbdfSmrg                                         grab, client, deliveryMask);
231435c4bbdfSmrg        return deliveries;
231535c4bbdfSmrg    }
231635c4bbdfSmrg    return nondeliveries;
231735c4bbdfSmrg}
231835c4bbdfSmrg
231935c4bbdfSmrg/**
232035c4bbdfSmrg * Filter out raw events for XI 2.0 and XI 2.1 clients.
232135c4bbdfSmrg *
232235c4bbdfSmrg * If there is a grab on the device, 2.0 clients only get raw events if they
232335c4bbdfSmrg * have the grab. 2.1+ clients get raw events in all cases.
232435c4bbdfSmrg *
232535c4bbdfSmrg * @return TRUE if the event should be discarded, FALSE otherwise.
232635c4bbdfSmrg */
232735c4bbdfSmrgstatic BOOL
232835c4bbdfSmrgFilterRawEvents(const ClientPtr client, const GrabPtr grab, WindowPtr root)
232935c4bbdfSmrg{
233035c4bbdfSmrg    XIClientPtr client_xi_version;
233135c4bbdfSmrg    int cmp;
23326747b715Smrg
233335c4bbdfSmrg    /* device not grabbed -> don't filter */
233435c4bbdfSmrg    if (!grab)
233535c4bbdfSmrg        return FALSE;
23366747b715Smrg
233735c4bbdfSmrg    client_xi_version =
233835c4bbdfSmrg        dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
233935c4bbdfSmrg
234035c4bbdfSmrg    cmp = version_compare(client_xi_version->major_version,
234135c4bbdfSmrg                          client_xi_version->minor_version, 2, 0);
234235c4bbdfSmrg    /* XI 2.0: if device is grabbed, skip
234335c4bbdfSmrg       XI 2.1: if device is grabbed by us, skip, we've already delivered */
234435c4bbdfSmrg    if (cmp == 0)
234535c4bbdfSmrg        return TRUE;
234635c4bbdfSmrg
234735c4bbdfSmrg    return (grab->window != root) ? FALSE : SameClient(grab, client);
234835c4bbdfSmrg}
234935c4bbdfSmrg
235035c4bbdfSmrg/**
235135c4bbdfSmrg * Deliver a raw event to the grab owner (if any) and to all root windows.
235235c4bbdfSmrg *
235335c4bbdfSmrg * Raw event delivery differs between XI 2.0 and XI 2.1.
235435c4bbdfSmrg * XI 2.0: events delivered to the grabbing client (if any) OR to all root
235535c4bbdfSmrg * windows
235635c4bbdfSmrg * XI 2.1: events delivered to all root windows, regardless of grabbing
235735c4bbdfSmrg * state.
235835c4bbdfSmrg */
235935c4bbdfSmrgvoid
236035c4bbdfSmrgDeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
236135c4bbdfSmrg{
236235c4bbdfSmrg    GrabPtr grab = device->deviceGrab.grab;
236335c4bbdfSmrg    xEvent *xi;
236435c4bbdfSmrg    int i, rc;
236535c4bbdfSmrg    int filter;
236635c4bbdfSmrg
236735c4bbdfSmrg    rc = EventToXI2((InternalEvent *) ev, (xEvent **) &xi);
236835c4bbdfSmrg    if (rc != Success) {
236935c4bbdfSmrg        ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n",
237035c4bbdfSmrg               __func__, device->name, rc);
237135c4bbdfSmrg        return;
237205b261ecSmrg    }
23734642e01fSmrg
237435c4bbdfSmrg    if (grab)
237535c4bbdfSmrg        DeliverGrabbedEvent((InternalEvent *) ev, device, FALSE);
237635c4bbdfSmrg
237735c4bbdfSmrg    filter = GetEventFilter(device, xi);
237835c4bbdfSmrg
237935c4bbdfSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
238035c4bbdfSmrg        WindowPtr root;
238135c4bbdfSmrg        InputClients *inputclients;
238235c4bbdfSmrg
238335c4bbdfSmrg        root = screenInfo.screens[i]->root;
238435c4bbdfSmrg        if (!GetClientsForDelivery(device, root, xi, filter, &inputclients))
238535c4bbdfSmrg            continue;
238635c4bbdfSmrg
238735c4bbdfSmrg        for (; inputclients; inputclients = inputclients->next) {
238835c4bbdfSmrg            ClientPtr c;        /* unused */
238935c4bbdfSmrg            Mask m;             /* unused */
239035c4bbdfSmrg            InputClients ic = *inputclients;
23914642e01fSmrg
239235c4bbdfSmrg            /* Because we run through the list manually, copy the actual
239335c4bbdfSmrg             * list, shorten the copy to only have one client and then pass
239435c4bbdfSmrg             * that down to DeliverEventToInputClients. This way we avoid
239535c4bbdfSmrg             * double events on XI 2.1 clients that have a grab on the
239635c4bbdfSmrg             * device.
239735c4bbdfSmrg             */
239835c4bbdfSmrg            ic.next = NULL;
23996747b715Smrg
240035c4bbdfSmrg            if (!FilterRawEvents(rClient(&ic), grab, root))
240135c4bbdfSmrg                DeliverEventToInputClients(device, &ic, root, xi, 1,
240235c4bbdfSmrg                                           filter, NULL, &c, &m);
240335c4bbdfSmrg        }
240405b261ecSmrg    }
240535c4bbdfSmrg
240635c4bbdfSmrg    free(xi);
240705b261ecSmrg}
240805b261ecSmrg
240905b261ecSmrg/* If the event goes to dontClient, don't send it and return 0.  if
241005b261ecSmrg   send works,  return 1 or if send didn't work, return 2.
241105b261ecSmrg   Only works for core events.
241205b261ecSmrg*/
241305b261ecSmrg
241405b261ecSmrg#ifdef PANORAMIX
24154642e01fSmrgstatic int
241635c4bbdfSmrgXineramaTryClientEventsResult(ClientPtr client,
241735c4bbdfSmrg                              GrabPtr grab, Mask mask, Mask filter)
241835c4bbdfSmrg{
241905b261ecSmrg    if ((client) && (client != serverClient) && (!client->clientGone) &&
242035c4bbdfSmrg        ((filter == CantBeFiltered) || (mask & filter))) {
242135c4bbdfSmrg        if (grab && !SameClient(grab, client))
242235c4bbdfSmrg            return -1;
242335c4bbdfSmrg        else
242435c4bbdfSmrg            return 1;
242505b261ecSmrg    }
242605b261ecSmrg    return 0;
242705b261ecSmrg}
242805b261ecSmrg#endif
242905b261ecSmrg
243005b261ecSmrg/**
243105b261ecSmrg * Try to deliver events to the interested parties.
243205b261ecSmrg *
243305b261ecSmrg * @param pWin The window that would get the event.
243405b261ecSmrg * @param pEvents The events to be delivered.
243505b261ecSmrg * @param count Number of elements in pEvents.
243605b261ecSmrg * @param filter Mask based on event type.
243705b261ecSmrg * @param dontClient Don't deliver to the dontClient.
243805b261ecSmrg */
243905b261ecSmrgint
24404642e01fSmrgMaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
244105b261ecSmrg                           int count, Mask filter, ClientPtr dontClient)
244205b261ecSmrg{
244305b261ecSmrg    OtherClients *other;
244405b261ecSmrg
244535c4bbdfSmrg    if (pWin->eventMask & filter) {
244605b261ecSmrg        if (wClient(pWin) == dontClient)
244735c4bbdfSmrg            return 0;
244805b261ecSmrg#ifdef PANORAMIX
244935c4bbdfSmrg        if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
245035c4bbdfSmrg            return XineramaTryClientEventsResult(wClient(pWin), NullGrab,
245135c4bbdfSmrg                                                 pWin->eventMask, filter);
245205b261ecSmrg#endif
245335c4bbdfSmrg        if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
245435c4bbdfSmrg            return 1;           /* don't send, but pretend we did */
245535c4bbdfSmrg        return TryClientEvents(wClient(pWin), NULL, pEvents, count,
245635c4bbdfSmrg                               pWin->eventMask, filter, NullGrab);
245705b261ecSmrg    }
245835c4bbdfSmrg    for (other = wOtherClients(pWin); other; other = other->next) {
245935c4bbdfSmrg        if (other->mask & filter) {
246005b261ecSmrg            if (SameClient(other, dontClient))
246135c4bbdfSmrg                return 0;
246205b261ecSmrg#ifdef PANORAMIX
246335c4bbdfSmrg            if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
246435c4bbdfSmrg                return XineramaTryClientEventsResult(rClient(other), NullGrab,
246535c4bbdfSmrg                                                     other->mask, filter);
246605b261ecSmrg#endif
246735c4bbdfSmrg            if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents,
246835c4bbdfSmrg                         count))
246935c4bbdfSmrg                return 1;       /* don't send, but pretend we did */
247035c4bbdfSmrg            return TryClientEvents(rClient(other), NULL, pEvents, count,
247135c4bbdfSmrg                                   other->mask, filter, NullGrab);
247235c4bbdfSmrg        }
247305b261ecSmrg    }
247405b261ecSmrg    return 2;
247505b261ecSmrg}
247605b261ecSmrg
247735c4bbdfSmrgstatic Window
247835c4bbdfSmrgFindChildForEvent(SpritePtr pSprite, WindowPtr event)
24796747b715Smrg{
248035c4bbdfSmrg    WindowPtr w = DeepestSpriteWin(pSprite);
24816747b715Smrg    Window child = None;
24826747b715Smrg
24836747b715Smrg    /* If the search ends up past the root should the child field be
24846747b715Smrg       set to none or should the value in the argument be passed
24856747b715Smrg       through. It probably doesn't matter since everyone calls
24866747b715Smrg       this function with child == None anyway. */
248735c4bbdfSmrg    while (w) {
24886747b715Smrg        /* If the source window is same as event window, child should be
24896747b715Smrg           none.  Don't bother going all all the way back to the root. */
24906747b715Smrg
249135c4bbdfSmrg        if (w == event) {
24926747b715Smrg            child = None;
24936747b715Smrg            break;
24946747b715Smrg        }
24956747b715Smrg
249635c4bbdfSmrg        if (w->parent == event) {
24976747b715Smrg            child = w->drawable.id;
24986747b715Smrg            break;
24996747b715Smrg        }
25006747b715Smrg        w = w->parent;
25016747b715Smrg    }
25026747b715Smrg    return child;
25036747b715Smrg}
25046747b715Smrg
250505b261ecSmrg/**
250605b261ecSmrg * Adjust event fields to comply with the window properties.
250705b261ecSmrg *
250805b261ecSmrg * @param xE Event to be modified in place
250905b261ecSmrg * @param pWin The window to get the information from.
251005b261ecSmrg * @param child Child window setting for event (if applicable)
251105b261ecSmrg * @param calcChild If True, calculate the child window.
251205b261ecSmrg */
25136747b715Smrgvoid
251435c4bbdfSmrgFixUpEventFromWindow(SpritePtr pSprite,
251535c4bbdfSmrg                     xEvent *xE, WindowPtr pWin, Window child, Bool calcChild)
251605b261ecSmrg{
251735c4bbdfSmrg    int evtype;
251835c4bbdfSmrg
251905b261ecSmrg    if (calcChild)
25209ace9065Smrg        child = FindChildForEvent(pSprite, pWin);
25216747b715Smrg
252235c4bbdfSmrg    if ((evtype = xi2_get_type(xE))) {
252335c4bbdfSmrg        xXIDeviceEvent *event = (xXIDeviceEvent *) xE;
252435c4bbdfSmrg
252535c4bbdfSmrg        switch (evtype) {
252635c4bbdfSmrg        case XI_RawKeyPress:
252735c4bbdfSmrg        case XI_RawKeyRelease:
252835c4bbdfSmrg        case XI_RawButtonPress:
252935c4bbdfSmrg        case XI_RawButtonRelease:
253035c4bbdfSmrg        case XI_RawMotion:
253135c4bbdfSmrg        case XI_RawTouchBegin:
253235c4bbdfSmrg        case XI_RawTouchUpdate:
253335c4bbdfSmrg        case XI_RawTouchEnd:
253435c4bbdfSmrg        case XI_DeviceChanged:
253535c4bbdfSmrg        case XI_HierarchyChanged:
253635c4bbdfSmrg        case XI_PropertyEvent:
253735c4bbdfSmrg        case XI_BarrierHit:
253835c4bbdfSmrg        case XI_BarrierLeave:
25396747b715Smrg            return;
254035c4bbdfSmrg        default:
254135c4bbdfSmrg            break;
254235c4bbdfSmrg        }
254305b261ecSmrg
25449ace9065Smrg        event->root = RootWindow(pSprite)->drawable.id;
25456747b715Smrg        event->event = pWin->drawable.id;
254635c4bbdfSmrg
254735c4bbdfSmrg        if (evtype == XI_TouchOwnership) {
25486747b715Smrg            event->child = child;
254935c4bbdfSmrg            return;
255035c4bbdfSmrg        }
255135c4bbdfSmrg
255235c4bbdfSmrg        if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
255335c4bbdfSmrg            event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x);
255435c4bbdfSmrg            event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y);
255535c4bbdfSmrg            event->child = child;
255635c4bbdfSmrg        }
255735c4bbdfSmrg        else {
25586747b715Smrg            event->event_x = 0;
25596747b715Smrg            event->event_y = 0;
25606747b715Smrg            event->child = None;
25616747b715Smrg        }
256205b261ecSmrg
25636747b715Smrg        if (event->evtype == XI_Enter || event->evtype == XI_Leave ||
25646747b715Smrg            event->evtype == XI_FocusIn || event->evtype == XI_FocusOut)
256535c4bbdfSmrg            ((xXIEnterEvent *) event)->same_screen =
25666747b715Smrg                (pSprite->hot.pScreen == pWin->drawable.pScreen);
25674642e01fSmrg
256835c4bbdfSmrg    }
256935c4bbdfSmrg    else {
25709ace9065Smrg        XE_KBPTR.root = RootWindow(pSprite)->drawable.id;
25716747b715Smrg        XE_KBPTR.event = pWin->drawable.id;
257235c4bbdfSmrg        if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
25736747b715Smrg            XE_KBPTR.sameScreen = xTrue;
25746747b715Smrg            XE_KBPTR.child = child;
257535c4bbdfSmrg            XE_KBPTR.eventX = XE_KBPTR.rootX - pWin->drawable.x;
257635c4bbdfSmrg            XE_KBPTR.eventY = XE_KBPTR.rootY - pWin->drawable.y;
25776747b715Smrg        }
257835c4bbdfSmrg        else {
25796747b715Smrg            XE_KBPTR.sameScreen = xFalse;
25806747b715Smrg            XE_KBPTR.child = None;
25816747b715Smrg            XE_KBPTR.eventX = 0;
25826747b715Smrg            XE_KBPTR.eventY = 0;
25836747b715Smrg        }
258405b261ecSmrg    }
258505b261ecSmrg}
258605b261ecSmrg
25876747b715Smrg/**
25886747b715Smrg * Check if a given event is deliverable at all on a given window.
25896747b715Smrg *
25906747b715Smrg * This function only checks if any client wants it, not for a specific
25916747b715Smrg * client.
25926747b715Smrg *
25936747b715Smrg * @param[in] dev The device this event is being sent for.
259435c4bbdfSmrg * @param[in] evtype The event type of the event that is to be sent.
25956747b715Smrg * @param[in] win The current event window.
25966747b715Smrg *
259735c4bbdfSmrg * @return Bitmask of ::EVENT_XI2_MASK, ::EVENT_XI1_MASK, ::EVENT_CORE_MASK, and
259835c4bbdfSmrg *         ::EVENT_DONT_PROPAGATE_MASK.
25996747b715Smrg */
26009ace9065Smrgint
260135c4bbdfSmrgEventIsDeliverable(DeviceIntPtr dev, int evtype, WindowPtr win)
26026747b715Smrg{
26036747b715Smrg    int rc = 0;
26046747b715Smrg    int filter = 0;
26056747b715Smrg    int type;
26066747b715Smrg    OtherInputMasks *inputMasks = wOtherInputMasks(win);
260735c4bbdfSmrg
260835c4bbdfSmrg    if ((type = GetXI2Type(evtype)) != 0) {
260935c4bbdfSmrg        if (inputMasks && xi2mask_isset(inputMasks->xi2mask, dev, type))
261035c4bbdfSmrg            rc |= EVENT_XI2_MASK;
261135c4bbdfSmrg    }
261235c4bbdfSmrg
261335c4bbdfSmrg    if ((type = GetXIType(evtype)) != 0) {
261435c4bbdfSmrg        filter = event_get_filter_from_type(dev, type);
261535c4bbdfSmrg
261635c4bbdfSmrg        /* Check for XI mask */
261735c4bbdfSmrg        if (inputMasks &&
261835c4bbdfSmrg            (inputMasks->deliverableEvents[dev->id] & filter) &&
261935c4bbdfSmrg            (inputMasks->inputEvents[dev->id] & filter))
262035c4bbdfSmrg            rc |= EVENT_XI1_MASK;
262135c4bbdfSmrg
262235c4bbdfSmrg        /* Check for XI DontPropagate mask */
262335c4bbdfSmrg        if (inputMasks && (inputMasks->dontPropagateMask[dev->id] & filter))
262435c4bbdfSmrg            rc |= EVENT_DONT_PROPAGATE_MASK;
262535c4bbdfSmrg
262635c4bbdfSmrg    }
262735c4bbdfSmrg
262835c4bbdfSmrg    if ((type = GetCoreType(evtype)) != 0) {
262935c4bbdfSmrg        filter = event_get_filter_from_type(dev, type);
263035c4bbdfSmrg
263135c4bbdfSmrg        /* Check for core mask */
263235c4bbdfSmrg        if ((win->deliverableEvents & filter) &&
263335c4bbdfSmrg            ((wOtherEventMasks(win) | win->eventMask) & filter))
263435c4bbdfSmrg            rc |= EVENT_CORE_MASK;
263535c4bbdfSmrg
263635c4bbdfSmrg        /* Check for core DontPropagate mask */
263735c4bbdfSmrg        if (filter & wDontPropagateMask(win))
263835c4bbdfSmrg            rc |= EVENT_DONT_PROPAGATE_MASK;
263935c4bbdfSmrg    }
26406747b715Smrg
26416747b715Smrg    return rc;
26426747b715Smrg}
26436747b715Smrg
264435c4bbdfSmrgstatic int
264535c4bbdfSmrgDeliverEvent(DeviceIntPtr dev, xEvent *xE, int count,
264635c4bbdfSmrg             WindowPtr win, Window child, GrabPtr grab)
264735c4bbdfSmrg{
264835c4bbdfSmrg    SpritePtr pSprite = dev->spriteInfo->sprite;
264935c4bbdfSmrg    Mask filter;
265035c4bbdfSmrg    int deliveries = 0;
265135c4bbdfSmrg
265235c4bbdfSmrg    if (XaceHook(XACE_SEND_ACCESS, NULL, dev, win, xE, count) == Success) {
265335c4bbdfSmrg        filter = GetEventFilter(dev, xE);
265435c4bbdfSmrg        FixUpEventFromWindow(pSprite, xE, win, child, FALSE);
265535c4bbdfSmrg        deliveries = DeliverEventsToWindow(dev, win, xE, count, filter, grab);
265635c4bbdfSmrg    }
265735c4bbdfSmrg
265835c4bbdfSmrg    return deliveries;
265935c4bbdfSmrg}
266035c4bbdfSmrg
266135c4bbdfSmrgstatic int
266235c4bbdfSmrgDeliverOneEvent(InternalEvent *event, DeviceIntPtr dev, enum InputLevel level,
266335c4bbdfSmrg                WindowPtr win, Window child, GrabPtr grab)
266435c4bbdfSmrg{
266535c4bbdfSmrg    xEvent *xE = NULL;
266635c4bbdfSmrg    int count = 0;
266735c4bbdfSmrg    int deliveries = 0;
266835c4bbdfSmrg    int rc;
266935c4bbdfSmrg
267035c4bbdfSmrg    switch (level) {
267135c4bbdfSmrg    case XI2:
267235c4bbdfSmrg        rc = EventToXI2(event, &xE);
267335c4bbdfSmrg        count = 1;
267435c4bbdfSmrg        break;
267535c4bbdfSmrg    case XI:
267635c4bbdfSmrg        rc = EventToXI(event, &xE, &count);
267735c4bbdfSmrg        break;
267835c4bbdfSmrg    case CORE:
267935c4bbdfSmrg        rc = EventToCore(event, &xE, &count);
268035c4bbdfSmrg        break;
268135c4bbdfSmrg    default:
268235c4bbdfSmrg        rc = BadImplementation;
268335c4bbdfSmrg        break;
268435c4bbdfSmrg    }
268535c4bbdfSmrg
268635c4bbdfSmrg    if (rc == Success) {
268735c4bbdfSmrg        deliveries = DeliverEvent(dev, xE, count, win, child, grab);
268835c4bbdfSmrg        free(xE);
268935c4bbdfSmrg    }
269035c4bbdfSmrg    else
269135c4bbdfSmrg        BUG_WARN_MSG(rc != BadMatch,
269235c4bbdfSmrg                     "%s: conversion to level %d failed with rc %d\n",
269335c4bbdfSmrg                     dev->name, level, rc);
269435c4bbdfSmrg    return deliveries;
269535c4bbdfSmrg}
269635c4bbdfSmrg
26976747b715Smrg/**
26986747b715Smrg * Deliver events caused by input devices.
26996747b715Smrg *
27004642e01fSmrg * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is
27014642e01fSmrg * called directly from the processInputProc.
27024642e01fSmrg * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call
27034642e01fSmrg * DeliverDeviceEvents.
27044642e01fSmrg * For focused events, DeliverFocusedEvent is called first, and _may_ call
27054642e01fSmrg * DeliverDeviceEvents.
270605b261ecSmrg *
270705b261ecSmrg * @param pWin Window to deliver event to.
27086747b715Smrg * @param event The events to deliver, not yet in wire format.
270905b261ecSmrg * @param grab Possible grab on a device.
271005b261ecSmrg * @param stopAt Don't recurse up to the root window.
271105b261ecSmrg * @param dev The device that is responsible for the event.
271205b261ecSmrg *
27134642e01fSmrg * @see DeliverGrabbedEvent
27144642e01fSmrg * @see DeliverFocusedEvent
271505b261ecSmrg */
271605b261ecSmrgint
27176747b715SmrgDeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
27186747b715Smrg                    WindowPtr stopAt, DeviceIntPtr dev)
271905b261ecSmrg{
272005b261ecSmrg    Window child = None;
272105b261ecSmrg    int deliveries = 0;
272235c4bbdfSmrg    int mask;
27234642e01fSmrg
272435c4bbdfSmrg    verify_internal_event(event);
27254642e01fSmrg
272635c4bbdfSmrg    while (pWin) {
272735c4bbdfSmrg        if ((mask = EventIsDeliverable(dev, event->any.type, pWin))) {
27286747b715Smrg            /* XI2 events first */
272935c4bbdfSmrg            if (mask & EVENT_XI2_MASK) {
273035c4bbdfSmrg                deliveries =
273135c4bbdfSmrg                    DeliverOneEvent(event, dev, XI2, pWin, child, grab);
273235c4bbdfSmrg                if (deliveries > 0)
273335c4bbdfSmrg                    break;
27344642e01fSmrg            }
27354642e01fSmrg
27366747b715Smrg            /* XI events */
273735c4bbdfSmrg            if (mask & EVENT_XI1_MASK) {
273835c4bbdfSmrg                deliveries = DeliverOneEvent(event, dev, XI, pWin, child, grab);
273935c4bbdfSmrg                if (deliveries > 0)
274035c4bbdfSmrg                    break;
27416747b715Smrg            }
27424642e01fSmrg
27436747b715Smrg            /* Core event */
274435c4bbdfSmrg            if ((mask & EVENT_CORE_MASK) && IsMaster(dev) && dev->coreEvents) {
274535c4bbdfSmrg                deliveries =
274635c4bbdfSmrg                    DeliverOneEvent(event, dev, CORE, pWin, child, grab);
274735c4bbdfSmrg                if (deliveries > 0)
274835c4bbdfSmrg                    break;
27494642e01fSmrg            }
27504642e01fSmrg
275135c4bbdfSmrg        }
275235c4bbdfSmrg
275335c4bbdfSmrg        if ((deliveries < 0) || (pWin == stopAt) ||
275435c4bbdfSmrg            (mask & EVENT_DONT_PROPAGATE_MASK)) {
275535c4bbdfSmrg            deliveries = 0;
275635c4bbdfSmrg            break;
27574642e01fSmrg        }
27584642e01fSmrg
27594642e01fSmrg        child = pWin->drawable.id;
27604642e01fSmrg        pWin = pWin->parent;
276105b261ecSmrg    }
27624642e01fSmrg
27636747b715Smrg    return deliveries;
276405b261ecSmrg}
276505b261ecSmrg
276605b261ecSmrg/**
276705b261ecSmrg * Deliver event to a window and it's immediate parent. Used for most window
276805b261ecSmrg * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
27694642e01fSmrg * propagate up the tree or extension events
277005b261ecSmrg *
277105b261ecSmrg * In case of a ReparentNotify event, the event will be delivered to the
277205b261ecSmrg * otherParent as well.
277305b261ecSmrg *
277405b261ecSmrg * @param pWin Window to deliver events to.
277505b261ecSmrg * @param xE Events to deliver.
277605b261ecSmrg * @param count number of events in xE.
277705b261ecSmrg * @param otherParent Used for ReparentNotify events.
277805b261ecSmrg */
27796747b715Smrgint
278035c4bbdfSmrgDeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent)
278105b261ecSmrg{
27826747b715Smrg    DeviceIntRec dummy;
278335c4bbdfSmrg    int deliveries;
278405b261ecSmrg
278505b261ecSmrg#ifdef PANORAMIX
278635c4bbdfSmrg    if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
278735c4bbdfSmrg        return count;
278805b261ecSmrg#endif
278905b261ecSmrg
279005b261ecSmrg    if (!count)
279135c4bbdfSmrg        return 0;
27926747b715Smrg
27936747b715Smrg    dummy.id = XIAllDevices;
279435c4bbdfSmrg
279535c4bbdfSmrg    switch (xE->u.u.type) {
279635c4bbdfSmrg    case DestroyNotify:
279735c4bbdfSmrg    case UnmapNotify:
279835c4bbdfSmrg    case MapNotify:
279935c4bbdfSmrg    case MapRequest:
280035c4bbdfSmrg    case ReparentNotify:
280135c4bbdfSmrg    case ConfigureNotify:
280235c4bbdfSmrg    case ConfigureRequest:
280335c4bbdfSmrg    case GravityNotify:
280435c4bbdfSmrg    case CirculateNotify:
280535c4bbdfSmrg    case CirculateRequest:
280635c4bbdfSmrg        xE->u.destroyNotify.event = pWin->drawable.id;
280735c4bbdfSmrg        break;
280835c4bbdfSmrg    }
280935c4bbdfSmrg
281035c4bbdfSmrg    switch (xE->u.u.type) {
281135c4bbdfSmrg    case DestroyNotify:
281235c4bbdfSmrg    case UnmapNotify:
281335c4bbdfSmrg    case MapNotify:
281435c4bbdfSmrg    case ReparentNotify:
281535c4bbdfSmrg    case ConfigureNotify:
281635c4bbdfSmrg    case GravityNotify:
281735c4bbdfSmrg    case CirculateNotify:
281835c4bbdfSmrg        break;
281935c4bbdfSmrg    default:
282035c4bbdfSmrg    {
282135c4bbdfSmrg        Mask filter;
282235c4bbdfSmrg
282335c4bbdfSmrg        filter = GetEventFilter(&dummy, xE);
282435c4bbdfSmrg        return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab);
282535c4bbdfSmrg    }
282635c4bbdfSmrg    }
282735c4bbdfSmrg
28286747b715Smrg    deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count,
28296747b715Smrg                                       StructureNotifyMask, NullGrab);
283035c4bbdfSmrg    if (pWin->parent) {
283135c4bbdfSmrg        xE->u.destroyNotify.event = pWin->parent->drawable.id;
283235c4bbdfSmrg        deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count,
283335c4bbdfSmrg                                            SubstructureNotifyMask, NullGrab);
283435c4bbdfSmrg        if (xE->u.u.type == ReparentNotify) {
283535c4bbdfSmrg            xE->u.destroyNotify.event = otherParent->drawable.id;
28366747b715Smrg            deliveries += DeliverEventsToWindow(&dummy,
283735c4bbdfSmrg                                                otherParent, xE, count,
283835c4bbdfSmrg                                                SubstructureNotifyMask,
283935c4bbdfSmrg                                                NullGrab);
284035c4bbdfSmrg        }
284105b261ecSmrg    }
284205b261ecSmrg    return deliveries;
284305b261ecSmrg}
284405b261ecSmrg
284535c4bbdfSmrgBool
284605b261ecSmrgPointInBorderSize(WindowPtr pWin, int x, int y)
284705b261ecSmrg{
284805b261ecSmrg    BoxRec box;
284905b261ecSmrg
285035c4bbdfSmrg    if (RegionContainsPoint(&pWin->borderSize, x, y, &box))
285135c4bbdfSmrg        return TRUE;
285205b261ecSmrg
285305b261ecSmrg#ifdef PANORAMIX
285435c4bbdfSmrg    if (!noPanoramiXExtension &&
285535c4bbdfSmrg        XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
285635c4bbdfSmrg        SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
285735c4bbdfSmrg        int i;
285835c4bbdfSmrg
285935c4bbdfSmrg        FOR_NSCREENS_FORWARD_SKIP(i) {
286035c4bbdfSmrg            if (RegionContainsPoint(&pSprite->windows[i]->borderSize,
286135c4bbdfSmrg                                    x + screenInfo.screens[0]->x -
286235c4bbdfSmrg                                    screenInfo.screens[i]->x,
286335c4bbdfSmrg                                    y + screenInfo.screens[0]->y -
286435c4bbdfSmrg                                    screenInfo.screens[i]->y, &box))
286535c4bbdfSmrg                return TRUE;
286635c4bbdfSmrg        }
286705b261ecSmrg    }
286805b261ecSmrg#endif
286905b261ecSmrg    return FALSE;
287005b261ecSmrg}
287105b261ecSmrg
287205b261ecSmrg/**
287305b261ecSmrg * Traversed from the root window to the window at the position x/y. While
287405b261ecSmrg * traversing, it sets up the traversal history in the spriteTrace array.
287505b261ecSmrg * After completing, the spriteTrace history is set in the following way:
287605b261ecSmrg *   spriteTrace[0] ... root window
287705b261ecSmrg *   spriteTrace[1] ... top level window that encloses x/y
287805b261ecSmrg *       ...
287905b261ecSmrg *   spriteTrace[spriteTraceGood - 1] ... window at x/y
288005b261ecSmrg *
288105b261ecSmrg * @returns the window at the given coordinates.
288205b261ecSmrg */
28839ace9065SmrgWindowPtr
28849ace9065SmrgXYToWindow(SpritePtr pSprite, int x, int y)
288505b261ecSmrg{
288635c4bbdfSmrg    ScreenPtr pScreen = RootWindow(pSprite)->drawable.pScreen;
288705b261ecSmrg
288835c4bbdfSmrg    return (*pScreen->XYToWindow)(pScreen, pSprite, x, y);
288905b261ecSmrg}
289005b261ecSmrg
28916747b715Smrg/**
28926747b715Smrg * Ungrab a currently FocusIn grabbed device and grab the device on the
28936747b715Smrg * given window. If the win given is the NoneWin, the device is ungrabbed if
28946747b715Smrg * applicable and FALSE is returned.
28956747b715Smrg *
28966747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise.
28976747b715Smrg */
28986747b715SmrgBOOL
28996747b715SmrgActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
29006747b715Smrg{
29016747b715Smrg    BOOL rc = FALSE;
29026747b715Smrg    DeviceEvent event;
29036747b715Smrg
290435c4bbdfSmrg    if (dev->deviceGrab.grab) {
29059ace9065Smrg        if (!dev->deviceGrab.fromPassiveGrab ||
29067e31ba66Smrg            dev->deviceGrab.grab->type != XI_FocusIn ||
29079ace9065Smrg            dev->deviceGrab.grab->window == win ||
29086747b715Smrg            IsParent(dev->deviceGrab.grab->window, win))
29096747b715Smrg            return FALSE;
29106747b715Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
291135c4bbdfSmrg        (*dev->deviceGrab.DeactivateGrab) (dev);
29126747b715Smrg    }
29136747b715Smrg
29146747b715Smrg    if (win == NoneWin || win == PointerRootWin)
29156747b715Smrg        return FALSE;
29166747b715Smrg
291735c4bbdfSmrg    event = (DeviceEvent) {
291835c4bbdfSmrg        .header = ET_Internal,
291935c4bbdfSmrg        .type = ET_FocusIn,
292035c4bbdfSmrg        .length = sizeof(DeviceEvent),
292135c4bbdfSmrg        .time = GetTimeInMillis(),
292235c4bbdfSmrg        .deviceid = dev->id,
292335c4bbdfSmrg        .sourceid = dev->id,
292435c4bbdfSmrg        .detail.button = 0
292535c4bbdfSmrg    };
292635c4bbdfSmrg    rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE,
292735c4bbdfSmrg                                    TRUE) != NULL);
29286747b715Smrg    if (rc)
29297e31ba66Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
29306747b715Smrg    return rc;
29316747b715Smrg}
29326747b715Smrg
29336747b715Smrg/**
29346747b715Smrg * Ungrab a currently Enter grabbed device and grab the device for the given
29356747b715Smrg * window.
29366747b715Smrg *
29376747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise.
29386747b715Smrg */
29396747b715Smrgstatic BOOL
29406747b715SmrgActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
29416747b715Smrg{
29426747b715Smrg    BOOL rc = FALSE;
29436747b715Smrg    DeviceEvent event;
29446747b715Smrg
294535c4bbdfSmrg    if (dev->deviceGrab.grab) {
29469ace9065Smrg        if (!dev->deviceGrab.fromPassiveGrab ||
29479ace9065Smrg            dev->deviceGrab.grab->type != XI_Enter ||
29489ace9065Smrg            dev->deviceGrab.grab->window == win ||
29496747b715Smrg            IsParent(dev->deviceGrab.grab->window, win))
29506747b715Smrg            return FALSE;
29516747b715Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
295235c4bbdfSmrg        (*dev->deviceGrab.DeactivateGrab) (dev);
295335c4bbdfSmrg    }
295435c4bbdfSmrg
295535c4bbdfSmrg    event = (DeviceEvent) {
295635c4bbdfSmrg        .header = ET_Internal,
295735c4bbdfSmrg        .type = ET_Enter,
295835c4bbdfSmrg        .length = sizeof(DeviceEvent),
295935c4bbdfSmrg        .time = GetTimeInMillis(),
296035c4bbdfSmrg        .deviceid = dev->id,
296135c4bbdfSmrg        .sourceid = dev->id,
296235c4bbdfSmrg        .detail.button = 0
296335c4bbdfSmrg    };
296435c4bbdfSmrg    rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE,
296535c4bbdfSmrg                                    TRUE) != NULL);
29666747b715Smrg    if (rc)
29676747b715Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
29686747b715Smrg    return rc;
29696747b715Smrg}
29706747b715Smrg
297105b261ecSmrg/**
297205b261ecSmrg * Update the sprite coordinates based on the event. Update the cursor
297305b261ecSmrg * position, then update the event with the new coordinates that may have been
297405b261ecSmrg * changed. If the window underneath the sprite has changed, change to new
297505b261ecSmrg * cursor and send enter/leave events.
29764642e01fSmrg *
29774642e01fSmrg * CheckMotion() will not do anything and return FALSE if the event is not a
29784642e01fSmrg * pointer event.
29794642e01fSmrg *
29804642e01fSmrg * @return TRUE if the sprite has moved or FALSE otherwise.
298105b261ecSmrg */
29824642e01fSmrgBool
29836747b715SmrgCheckMotion(DeviceEvent *ev, DeviceIntPtr pDev)
298405b261ecSmrg{
29856747b715Smrg    WindowPtr prevSpriteWin, newSpriteWin;
29864642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
29874642e01fSmrg
298835c4bbdfSmrg    verify_internal_event((InternalEvent *) ev);
298905b261ecSmrg
29906747b715Smrg    prevSpriteWin = pSprite->win;
299105b261ecSmrg
299235c4bbdfSmrg    if (ev && !syncEvents.playingEvents) {
29934642e01fSmrg        /* GetPointerEvents() guarantees that pointer events have the correct
29944642e01fSmrg           rootX/Y set already. */
299535c4bbdfSmrg        switch (ev->type) {
299635c4bbdfSmrg        case ET_ButtonPress:
299735c4bbdfSmrg        case ET_ButtonRelease:
299835c4bbdfSmrg        case ET_Motion:
299935c4bbdfSmrg        case ET_TouchBegin:
300035c4bbdfSmrg        case ET_TouchUpdate:
300135c4bbdfSmrg        case ET_TouchEnd:
300235c4bbdfSmrg            break;
300335c4bbdfSmrg        default:
300435c4bbdfSmrg            /* all other events return FALSE */
300535c4bbdfSmrg            return FALSE;
30064642e01fSmrg        }
30074642e01fSmrg
30086747b715Smrg#ifdef PANORAMIX
300935c4bbdfSmrg        if (!noPanoramiXExtension) {
30106747b715Smrg            /* Motion events entering DIX get translated to Screen 0
30116747b715Smrg               coordinates.  Replayed events have already been
30126747b715Smrg               translated since they've entered DIX before */
30136747b715Smrg            ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
30146747b715Smrg            ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
301535c4bbdfSmrg        }
301635c4bbdfSmrg        else
30176747b715Smrg#endif
30186747b715Smrg        {
301935c4bbdfSmrg            if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen) {
30206747b715Smrg                pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
30219ace9065Smrg                RootWindow(pDev->spriteInfo->sprite) =
30229ace9065Smrg                    pSprite->hot.pScreen->root;
30236747b715Smrg            }
30244642e01fSmrg        }
30256747b715Smrg
30266747b715Smrg        pSprite->hot.x = ev->root_x;
30276747b715Smrg        pSprite->hot.y = ev->root_y;
30284642e01fSmrg        if (pSprite->hot.x < pSprite->physLimits.x1)
30294642e01fSmrg            pSprite->hot.x = pSprite->physLimits.x1;
30304642e01fSmrg        else if (pSprite->hot.x >= pSprite->physLimits.x2)
30314642e01fSmrg            pSprite->hot.x = pSprite->physLimits.x2 - 1;
30324642e01fSmrg        if (pSprite->hot.y < pSprite->physLimits.y1)
30334642e01fSmrg            pSprite->hot.y = pSprite->physLimits.y1;
30344642e01fSmrg        else if (pSprite->hot.y >= pSprite->physLimits.y2)
30354642e01fSmrg            pSprite->hot.y = pSprite->physLimits.y2 - 1;
303635c4bbdfSmrg        if (pSprite->hotShape)
303735c4bbdfSmrg            ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x,
303835c4bbdfSmrg                           &pSprite->hot.y);
303935c4bbdfSmrg        pSprite->hotPhys = pSprite->hot;
30404642e01fSmrg
304135c4bbdfSmrg        if ((pSprite->hotPhys.x != ev->root_x) ||
304235c4bbdfSmrg            (pSprite->hotPhys.y != ev->root_y)) {
30436747b715Smrg#ifdef PANORAMIX
304435c4bbdfSmrg            if (!noPanoramiXExtension) {
304535c4bbdfSmrg                XineramaSetCursorPosition(pDev, pSprite->hotPhys.x,
304635c4bbdfSmrg                                          pSprite->hotPhys.y, FALSE);
304735c4bbdfSmrg            }
304835c4bbdfSmrg            else
30496747b715Smrg#endif
30506747b715Smrg            {
305135c4bbdfSmrg                (*pSprite->hotPhys.pScreen->SetCursorPosition) (pDev,
305235c4bbdfSmrg                                                                pSprite->
305335c4bbdfSmrg                                                                hotPhys.pScreen,
305435c4bbdfSmrg                                                                pSprite->
305535c4bbdfSmrg                                                                hotPhys.x,
305635c4bbdfSmrg                                                                pSprite->
305735c4bbdfSmrg                                                                hotPhys.y,
305835c4bbdfSmrg                                                                FALSE);
30596747b715Smrg            }
306035c4bbdfSmrg        }
30614642e01fSmrg
306235c4bbdfSmrg        ev->root_x = pSprite->hot.x;
306335c4bbdfSmrg        ev->root_y = pSprite->hot.y;
306405b261ecSmrg    }
306505b261ecSmrg
30669ace9065Smrg    newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y);
30676747b715Smrg
306835c4bbdfSmrg    if (newSpriteWin != prevSpriteWin) {
30696747b715Smrg        int sourceid;
307035c4bbdfSmrg
30716747b715Smrg        if (!ev) {
30726747b715Smrg            UpdateCurrentTimeIf();
307335c4bbdfSmrg            sourceid = pDev->id;        /* when from WindowsRestructured */
307435c4bbdfSmrg        }
307535c4bbdfSmrg        else
30766747b715Smrg            sourceid = ev->sourceid;
30776747b715Smrg
307835c4bbdfSmrg        if (prevSpriteWin != NullWindow) {
30796747b715Smrg            if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin))
30806747b715Smrg                DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin,
30816747b715Smrg                                   newSpriteWin, NotifyNormal);
30824642e01fSmrg        }
30836747b715Smrg        /* set pSprite->win after ActivateEnterGrab, otherwise
30846747b715Smrg           sprite window == grab_window and no enter/leave events are
30856747b715Smrg           sent. */
30866747b715Smrg        pSprite->win = newSpriteWin;
30876747b715Smrg        PostNewCursor(pDev);
308805b261ecSmrg        return FALSE;
308905b261ecSmrg    }
309005b261ecSmrg    return TRUE;
309105b261ecSmrg}
309205b261ecSmrg
309305b261ecSmrg/**
309405b261ecSmrg * Windows have restructured, we need to update the sprite position and the
309505b261ecSmrg * sprite's cursor.
309605b261ecSmrg */
30974642e01fSmrgvoid
309805b261ecSmrgWindowsRestructured(void)
309905b261ecSmrg{
31004642e01fSmrg    DeviceIntPtr pDev = inputInfo.devices;
310135c4bbdfSmrg
310235c4bbdfSmrg    while (pDev) {
310335c4bbdfSmrg        if (IsMaster(pDev) || IsFloating(pDev))
3104b1d344b3Smrg            CheckMotion(NULL, pDev);
31054642e01fSmrg        pDev = pDev->next;
31064642e01fSmrg    }
310705b261ecSmrg}
310805b261ecSmrg
310905b261ecSmrg#ifdef PANORAMIX
311005b261ecSmrg/* This was added to support reconfiguration under Xdmx.  The problem is
31116747b715Smrg * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin
311205b261ecSmrg * other than 0,0, the information in the private sprite structure must
311305b261ecSmrg * be updated accordingly, or XYToWindow (and other routines) will not
311405b261ecSmrg * compute correctly. */
311535c4bbdfSmrgvoid
311635c4bbdfSmrgReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
311705b261ecSmrg{
311835c4bbdfSmrg    GrabPtr grab;
31194642e01fSmrg    DeviceIntPtr pDev;
31204642e01fSmrg    SpritePtr pSprite;
312105b261ecSmrg
312235c4bbdfSmrg    if (noPanoramiXExtension)
312335c4bbdfSmrg        return;
312405b261ecSmrg
31254642e01fSmrg    pDev = inputInfo.devices;
312635c4bbdfSmrg    while (pDev) {
312735c4bbdfSmrg        if (DevHasCursor(pDev)) {
31284642e01fSmrg            pSprite = pDev->spriteInfo->sprite;
312935c4bbdfSmrg            pSprite->hot.x -= xoff;
313035c4bbdfSmrg            pSprite->hot.y -= yoff;
31314642e01fSmrg
313235c4bbdfSmrg            pSprite->hotPhys.x -= xoff;
313335c4bbdfSmrg            pSprite->hotPhys.y -= yoff;
31344642e01fSmrg
31354642e01fSmrg            pSprite->hotLimits.x1 -= xoff;
31364642e01fSmrg            pSprite->hotLimits.y1 -= yoff;
31374642e01fSmrg            pSprite->hotLimits.x2 -= xoff;
31384642e01fSmrg            pSprite->hotLimits.y2 -= yoff;
31394642e01fSmrg
31406747b715Smrg            if (RegionNotEmpty(&pSprite->Reg1))
31416747b715Smrg                RegionTranslate(&pSprite->Reg1, xoff, yoff);
31426747b715Smrg            if (RegionNotEmpty(&pSprite->Reg2))
31436747b715Smrg                RegionTranslate(&pSprite->Reg2, xoff, yoff);
31444642e01fSmrg
31454642e01fSmrg            /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
31464642e01fSmrg            if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
31474642e01fSmrg                if (grab->confineTo->drawable.pScreen
314835c4bbdfSmrg                    != pSprite->hotPhys.pScreen)
31494642e01fSmrg                    pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
31504642e01fSmrg                ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
315135c4bbdfSmrg            }
315235c4bbdfSmrg            else
315335c4bbdfSmrg                ConfineCursorToWindow(pDev,
315435c4bbdfSmrg                                      pSprite->hotPhys.pScreen->root,
315535c4bbdfSmrg                                      TRUE, FALSE);
31564642e01fSmrg
31574642e01fSmrg        }
31584642e01fSmrg        pDev = pDev->next;
31594642e01fSmrg    }
31604642e01fSmrg}
31614642e01fSmrg#endif
31624642e01fSmrg
31634642e01fSmrg/**
31644642e01fSmrg * Initialize a sprite for the given device and set it to some sane values. If
31654642e01fSmrg * the device already has a sprite alloc'd, don't realloc but just reset to
31664642e01fSmrg * default values.
31674642e01fSmrg * If a window is supplied, the sprite will be initialized with the window's
31684642e01fSmrg * cursor and positioned in the center of the window's screen. The root window
31694642e01fSmrg * is a good choice to pass in here.
31704642e01fSmrg *
31714642e01fSmrg * It's a good idea to call it only for pointer devices, unless you have a
31724642e01fSmrg * really talented keyboard.
31734642e01fSmrg *
31744642e01fSmrg * @param pDev The device to initialize.
31754642e01fSmrg * @param pWin The window where to generate the sprite in.
31764642e01fSmrg *
31774642e01fSmrg */
31784642e01fSmrgvoid
31794642e01fSmrgInitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
31804642e01fSmrg{
31814642e01fSmrg    SpritePtr pSprite;
31824642e01fSmrg    ScreenPtr pScreen;
31836747b715Smrg    CursorPtr pCursor;
31844642e01fSmrg
318535c4bbdfSmrg    if (!pDev->spriteInfo->sprite) {
31864642e01fSmrg        DeviceIntPtr it;
31874642e01fSmrg
318835c4bbdfSmrg        pDev->spriteInfo->sprite = (SpritePtr) calloc(1, sizeof(SpriteRec));
31894642e01fSmrg        if (!pDev->spriteInfo->sprite)
31904642e01fSmrg            FatalError("InitializeSprite: failed to allocate sprite struct");
31914642e01fSmrg
31924642e01fSmrg        /* We may have paired another device with this device before our
31934642e01fSmrg         * device had a actual sprite. We need to check for this and reset the
31944642e01fSmrg         * sprite field for all paired devices.
31954642e01fSmrg         *
31964642e01fSmrg         * The VCK is always paired with the VCP before the VCP has a sprite.
31974642e01fSmrg         */
319835c4bbdfSmrg        for (it = inputInfo.devices; it; it = it->next) {
31994642e01fSmrg            if (it->spriteInfo->paired == pDev)
32004642e01fSmrg                it->spriteInfo->sprite = pDev->spriteInfo->sprite;
32014642e01fSmrg        }
32024642e01fSmrg        if (inputInfo.keyboard->spriteInfo->paired == pDev)
32034642e01fSmrg            inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite;
32044642e01fSmrg    }
32054642e01fSmrg
32064642e01fSmrg    pSprite = pDev->spriteInfo->sprite;
32074642e01fSmrg    pDev->spriteInfo->spriteOwner = TRUE;
320805b261ecSmrg
320935c4bbdfSmrg    pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr) NULL;
32104642e01fSmrg    pSprite->hot.pScreen = pScreen;
32114642e01fSmrg    pSprite->hotPhys.pScreen = pScreen;
321235c4bbdfSmrg    if (pScreen) {
32134642e01fSmrg        pSprite->hotPhys.x = pScreen->width / 2;
32144642e01fSmrg        pSprite->hotPhys.y = pScreen->height / 2;
32154642e01fSmrg        pSprite->hotLimits.x2 = pScreen->width;
32164642e01fSmrg        pSprite->hotLimits.y2 = pScreen->height;
32174642e01fSmrg    }
32184642e01fSmrg
32194642e01fSmrg    pSprite->hot = pSprite->hotPhys;
32204642e01fSmrg    pSprite->win = pWin;
32214642e01fSmrg
322235c4bbdfSmrg    if (pWin) {
322335c4bbdfSmrg        pCursor = wCursor(pWin);
322435c4bbdfSmrg        pSprite->spriteTrace = (WindowPtr *) calloc(1, 32 * sizeof(WindowPtr));
322535c4bbdfSmrg        if (!pSprite->spriteTrace)
322635c4bbdfSmrg            FatalError("Failed to allocate spriteTrace");
322735c4bbdfSmrg        pSprite->spriteTraceSize = 32;
32284642e01fSmrg
322935c4bbdfSmrg        RootWindow(pDev->spriteInfo->sprite) = pWin;
323035c4bbdfSmrg        pSprite->spriteTraceGood = 1;
32314642e01fSmrg
323235c4bbdfSmrg        pSprite->pEnqueueScreen = pScreen;
323335c4bbdfSmrg        pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
32344642e01fSmrg
323535c4bbdfSmrg    }
323635c4bbdfSmrg    else {
32376747b715Smrg        pCursor = NullCursor;
323835c4bbdfSmrg        pSprite->spriteTrace = NULL;
323935c4bbdfSmrg        pSprite->spriteTraceSize = 0;
324035c4bbdfSmrg        pSprite->spriteTraceGood = 0;
324135c4bbdfSmrg        pSprite->pEnqueueScreen = screenInfo.screens[0];
324235c4bbdfSmrg        pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
324335c4bbdfSmrg    }
324435c4bbdfSmrg    pCursor = RefCursor(pCursor);
32456747b715Smrg    if (pSprite->current)
324635c4bbdfSmrg        FreeCursor(pSprite->current, None);
32476747b715Smrg    pSprite->current = pCursor;
32484642e01fSmrg
324935c4bbdfSmrg    if (pScreen) {
325035c4bbdfSmrg        (*pScreen->RealizeCursor) (pDev, pScreen, pSprite->current);
325135c4bbdfSmrg        (*pScreen->CursorLimits) (pDev, pScreen, pSprite->current,
325235c4bbdfSmrg                                  &pSprite->hotLimits, &pSprite->physLimits);
32534642e01fSmrg        pSprite->confined = FALSE;
32544642e01fSmrg
325535c4bbdfSmrg        (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
32564642e01fSmrg        (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
325735c4bbdfSmrg                                       pSprite->hot.y, FALSE);
32584642e01fSmrg        (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
32594642e01fSmrg    }
326005b261ecSmrg#ifdef PANORAMIX
326135c4bbdfSmrg    if (!noPanoramiXExtension) {
32626747b715Smrg        pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
32636747b715Smrg        pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
326435c4bbdfSmrg        pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
32656747b715Smrg        pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
32664642e01fSmrg        pSprite->physLimits = pSprite->hotLimits;
32674642e01fSmrg        pSprite->confineWin = NullWindow;
32684642e01fSmrg        pSprite->hotShape = NullRegion;
32694642e01fSmrg        pSprite->screen = pScreen;
32704642e01fSmrg        /* gotta UNINIT these someplace */
32716747b715Smrg        RegionNull(&pSprite->Reg1);
32726747b715Smrg        RegionNull(&pSprite->Reg2);
32734642e01fSmrg    }
327405b261ecSmrg#endif
32754642e01fSmrg}
32764642e01fSmrg
327735c4bbdfSmrgvoid FreeSprite(DeviceIntPtr dev)
327835c4bbdfSmrg{
327935c4bbdfSmrg    if (DevHasCursor(dev) && dev->spriteInfo->sprite) {
328035c4bbdfSmrg        if (dev->spriteInfo->sprite->current)
328135c4bbdfSmrg            FreeCursor(dev->spriteInfo->sprite->current, None);
328235c4bbdfSmrg        free(dev->spriteInfo->sprite->spriteTrace);
328335c4bbdfSmrg        free(dev->spriteInfo->sprite);
328435c4bbdfSmrg    }
328535c4bbdfSmrg    dev->spriteInfo->sprite = NULL;
328635c4bbdfSmrg}
328735c4bbdfSmrg
328835c4bbdfSmrg
32894642e01fSmrg/**
32904642e01fSmrg * Update the mouse sprite info when the server switches from a pScreen to another.
32914642e01fSmrg * Otherwise, the pScreen of the mouse sprite is never updated when we switch
32924642e01fSmrg * from a pScreen to another. Never updating the pScreen of the mouse sprite
32934642e01fSmrg * implies that windows that are in pScreen whose pScreen->myNum >0 will never
32944642e01fSmrg * get pointer events. This is  because in CheckMotion(), sprite.hotPhys.pScreen
32954642e01fSmrg * always points to the first pScreen it has been set by
32964642e01fSmrg * DefineInitialRootWindow().
32974642e01fSmrg *
32984642e01fSmrg * Calling this function is useful for use cases where the server
32994642e01fSmrg * has more than one pScreen.
33004642e01fSmrg * This function is similar to DefineInitialRootWindow() but it does not
33014642e01fSmrg * reset the mouse pointer position.
33024642e01fSmrg * @param win must be the new pScreen we are switching to.
33034642e01fSmrg */
33044642e01fSmrgvoid
33054642e01fSmrgUpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
33064642e01fSmrg{
33074642e01fSmrg    SpritePtr pSprite = NULL;
33084642e01fSmrg    WindowPtr win = NULL;
33096747b715Smrg    CursorPtr pCursor;
331035c4bbdfSmrg
33114642e01fSmrg    if (!pScreen)
331235c4bbdfSmrg        return;
33134642e01fSmrg
33144642e01fSmrg    if (!pDev->spriteInfo->sprite)
33154642e01fSmrg        return;
33164642e01fSmrg
33174642e01fSmrg    pSprite = pDev->spriteInfo->sprite;
33184642e01fSmrg
33196747b715Smrg    win = pScreen->root;
33204642e01fSmrg
33214642e01fSmrg    pSprite->hotPhys.pScreen = pScreen;
33224642e01fSmrg    pSprite->hot = pSprite->hotPhys;
33234642e01fSmrg    pSprite->hotLimits.x2 = pScreen->width;
33244642e01fSmrg    pSprite->hotLimits.y2 = pScreen->height;
33254642e01fSmrg    pSprite->win = win;
332635c4bbdfSmrg    pCursor = RefCursor(wCursor(win));
33276747b715Smrg    if (pSprite->current)
332835c4bbdfSmrg        FreeCursor(pSprite->current, 0);
33296747b715Smrg    pSprite->current = pCursor;
33304642e01fSmrg    pSprite->spriteTraceGood = 1;
33314642e01fSmrg    pSprite->spriteTrace[0] = win;
33324642e01fSmrg    (*pScreen->CursorLimits) (pDev,
33334642e01fSmrg                              pScreen,
33344642e01fSmrg                              pSprite->current,
333535c4bbdfSmrg                              &pSprite->hotLimits, &pSprite->physLimits);
33364642e01fSmrg    pSprite->confined = FALSE;
33374642e01fSmrg    (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
33384642e01fSmrg    (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
33394642e01fSmrg
33404642e01fSmrg#ifdef PANORAMIX
334135c4bbdfSmrg    if (!noPanoramiXExtension) {
33426747b715Smrg        pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
33436747b715Smrg        pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
334435c4bbdfSmrg        pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
33456747b715Smrg        pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
33464642e01fSmrg        pSprite->physLimits = pSprite->hotLimits;
33474642e01fSmrg        pSprite->screen = pScreen;
334805b261ecSmrg    }
334905b261ecSmrg#endif
335005b261ecSmrg}
335105b261ecSmrg
335205b261ecSmrg/*
335305b261ecSmrg * This does not take any shortcuts, and even ignores its argument, since
335405b261ecSmrg * it does not happen very often, and one has to walk up the tree since
335505b261ecSmrg * this might be a newly instantiated cursor for an intermediate window
335605b261ecSmrg * between the one the pointer is in and the one that the last cursor was
335705b261ecSmrg * instantiated from.
335805b261ecSmrg */
335905b261ecSmrgvoid
336005b261ecSmrgWindowHasNewCursor(WindowPtr pWin)
336105b261ecSmrg{
33624642e01fSmrg    DeviceIntPtr pDev;
33634642e01fSmrg
336435c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
33654642e01fSmrg        if (DevHasCursor(pDev))
33664642e01fSmrg            PostNewCursor(pDev);
336705b261ecSmrg}
336805b261ecSmrg
33696747b715Smrgvoid
33704642e01fSmrgNewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
337105b261ecSmrg{
337235c4bbdfSmrg    DeviceIntPtr ptr;
337335c4bbdfSmrg    SpritePtr pSprite;
337435c4bbdfSmrg
337535c4bbdfSmrg    ptr =
337635c4bbdfSmrg        IsFloating(pDev) ? pDev :
337735c4bbdfSmrg        GetXTestDevice(GetMaster(pDev, MASTER_POINTER));
337835c4bbdfSmrg    pSprite = ptr->spriteInfo->sprite;
33794642e01fSmrg
33804642e01fSmrg    pSprite->hotPhys.x = x;
33814642e01fSmrg    pSprite->hotPhys.y = y;
338205b261ecSmrg#ifdef PANORAMIX
338335c4bbdfSmrg    if (!noPanoramiXExtension) {
338435c4bbdfSmrg        pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x;
338535c4bbdfSmrg        pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y;
338635c4bbdfSmrg        if (newScreen != pSprite->screen) {
338735c4bbdfSmrg            pSprite->screen = newScreen;
338835c4bbdfSmrg            /* Make sure we tell the DDX to update its copy of the screen */
338935c4bbdfSmrg            if (pSprite->confineWin)
339035c4bbdfSmrg                XineramaConfineCursorToWindow(ptr, pSprite->confineWin, TRUE);
339135c4bbdfSmrg            else
339235c4bbdfSmrg                XineramaConfineCursorToWindow(ptr, screenInfo.screens[0]->root,
339335c4bbdfSmrg                                              TRUE);
339435c4bbdfSmrg            /* if the pointer wasn't confined, the DDX won't get
339535c4bbdfSmrg               told of the pointer warp so we reposition it here */
339635c4bbdfSmrg            if (!syncEvents.playingEvents)
339735c4bbdfSmrg                (*pSprite->screen->SetCursorPosition) (ptr,
339835c4bbdfSmrg                                                       pSprite->screen,
339935c4bbdfSmrg                                                       pSprite->hotPhys.x +
340035c4bbdfSmrg                                                       screenInfo.screens[0]->
340135c4bbdfSmrg                                                       x - pSprite->screen->x,
340235c4bbdfSmrg                                                       pSprite->hotPhys.y +
340335c4bbdfSmrg                                                       screenInfo.screens[0]->
340435c4bbdfSmrg                                                       y - pSprite->screen->y,
340535c4bbdfSmrg                                                       FALSE);
340635c4bbdfSmrg        }
340735c4bbdfSmrg    }
340835c4bbdfSmrg    else
340905b261ecSmrg#endif
34104642e01fSmrg    if (newScreen != pSprite->hotPhys.pScreen)
341135c4bbdfSmrg        ConfineCursorToWindow(ptr, newScreen->root, TRUE, FALSE);
341205b261ecSmrg}
341305b261ecSmrg
341405b261ecSmrg#ifdef PANORAMIX
341505b261ecSmrg
341605b261ecSmrgstatic Bool
341735c4bbdfSmrgXineramaPointInWindowIsVisible(WindowPtr pWin, int x, int y)
341805b261ecSmrg{
341905b261ecSmrg    BoxRec box;
342005b261ecSmrg    int i, xoff, yoff;
342105b261ecSmrg
342235c4bbdfSmrg    if (!pWin->realized)
342335c4bbdfSmrg        return FALSE;
342405b261ecSmrg
34256747b715Smrg    if (RegionContainsPoint(&pWin->borderClip, x, y, &box))
342605b261ecSmrg        return TRUE;
342705b261ecSmrg
342835c4bbdfSmrg    if (!XineramaSetWindowPntrs(inputInfo.pointer, pWin))
342935c4bbdfSmrg         return FALSE;
34304642e01fSmrg
34316747b715Smrg    xoff = x + screenInfo.screens[0]->x;
34326747b715Smrg    yoff = y + screenInfo.screens[0]->y;
343305b261ecSmrg
343435c4bbdfSmrg    FOR_NSCREENS_FORWARD_SKIP(i) {
343535c4bbdfSmrg        pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
343635c4bbdfSmrg
343735c4bbdfSmrg        x = xoff - screenInfo.screens[i]->x;
343835c4bbdfSmrg        y = yoff - screenInfo.screens[i]->y;
343905b261ecSmrg
344035c4bbdfSmrg        if (RegionContainsPoint(&pWin->borderClip, x, y, &box)
344135c4bbdfSmrg            && (!wInputShape(pWin) ||
344235c4bbdfSmrg                RegionContainsPoint(wInputShape(pWin),
344335c4bbdfSmrg                                    x - pWin->drawable.x,
344435c4bbdfSmrg                                    y - pWin->drawable.y, &box)))
344505b261ecSmrg            return TRUE;
344605b261ecSmrg
344705b261ecSmrg    }
344805b261ecSmrg
344905b261ecSmrg    return FALSE;
345005b261ecSmrg}
345105b261ecSmrg
345205b261ecSmrgstatic int
345305b261ecSmrgXineramaWarpPointer(ClientPtr client)
345405b261ecSmrg{
345535c4bbdfSmrg    WindowPtr dest = NULL;
345635c4bbdfSmrg    int x, y, rc;
345735c4bbdfSmrg    SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
345805b261ecSmrg
345905b261ecSmrg    REQUEST(xWarpPointerReq);
346005b261ecSmrg
346105b261ecSmrg    if (stuff->dstWid != None) {
346235c4bbdfSmrg        rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
346335c4bbdfSmrg        if (rc != Success)
346435c4bbdfSmrg            return rc;
346505b261ecSmrg    }
34664642e01fSmrg    x = pSprite->hotPhys.x;
34674642e01fSmrg    y = pSprite->hotPhys.y;
346805b261ecSmrg
346935c4bbdfSmrg    if (stuff->srcWid != None) {
347035c4bbdfSmrg        int winX, winY;
347135c4bbdfSmrg        XID winID = stuff->srcWid;
347205b261ecSmrg        WindowPtr source;
34734642e01fSmrg
347435c4bbdfSmrg        rc = dixLookupWindow(&source, winID, client, DixReadAccess);
347535c4bbdfSmrg        if (rc != Success)
347635c4bbdfSmrg            return rc;
347735c4bbdfSmrg
347835c4bbdfSmrg        winX = source->drawable.x;
347935c4bbdfSmrg        winY = source->drawable.y;
348035c4bbdfSmrg        if (source == screenInfo.screens[0]->root) {
348135c4bbdfSmrg            winX -= screenInfo.screens[0]->x;
348235c4bbdfSmrg            winY -= screenInfo.screens[0]->y;
348335c4bbdfSmrg        }
348435c4bbdfSmrg        if (x < winX + stuff->srcX ||
348535c4bbdfSmrg            y < winY + stuff->srcY ||
348635c4bbdfSmrg            (stuff->srcWidth != 0 &&
348735c4bbdfSmrg             winX + stuff->srcX + (int) stuff->srcWidth < x) ||
348835c4bbdfSmrg            (stuff->srcHeight != 0 &&
348935c4bbdfSmrg             winY + stuff->srcY + (int) stuff->srcHeight < y) ||
349035c4bbdfSmrg            !XineramaPointInWindowIsVisible(source, x, y))
349135c4bbdfSmrg            return Success;
349205b261ecSmrg    }
349305b261ecSmrg    if (dest) {
349435c4bbdfSmrg        x = dest->drawable.x;
349535c4bbdfSmrg        y = dest->drawable.y;
349635c4bbdfSmrg        if (dest == screenInfo.screens[0]->root) {
349735c4bbdfSmrg            x -= screenInfo.screens[0]->x;
349835c4bbdfSmrg            y -= screenInfo.screens[0]->y;
349935c4bbdfSmrg        }
35004642e01fSmrg    }
350105b261ecSmrg
350205b261ecSmrg    x += stuff->dstX;
350305b261ecSmrg    y += stuff->dstY;
350405b261ecSmrg
35054642e01fSmrg    if (x < pSprite->physLimits.x1)
350635c4bbdfSmrg        x = pSprite->physLimits.x1;
35074642e01fSmrg    else if (x >= pSprite->physLimits.x2)
350835c4bbdfSmrg        x = pSprite->physLimits.x2 - 1;
35094642e01fSmrg    if (y < pSprite->physLimits.y1)
351035c4bbdfSmrg        y = pSprite->physLimits.y1;
35114642e01fSmrg    else if (y >= pSprite->physLimits.y2)
351235c4bbdfSmrg        y = pSprite->physLimits.y2 - 1;
35134642e01fSmrg    if (pSprite->hotShape)
351435c4bbdfSmrg        ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
351505b261ecSmrg
35164642e01fSmrg    XineramaSetCursorPosition(PickPointer(client), x, y, TRUE);
351705b261ecSmrg
351805b261ecSmrg    return Success;
351905b261ecSmrg}
352005b261ecSmrg
352105b261ecSmrg#endif
352205b261ecSmrg
352305b261ecSmrg/**
352405b261ecSmrg * Server-side protocol handling for WarpPointer request.
352505b261ecSmrg * Warps the cursor position to the coordinates given in the request.
352605b261ecSmrg */
352705b261ecSmrgint
352805b261ecSmrgProcWarpPointer(ClientPtr client)
352905b261ecSmrg{
353035c4bbdfSmrg    WindowPtr dest = NULL;
353135c4bbdfSmrg    int x, y, rc;
353235c4bbdfSmrg    ScreenPtr newScreen;
35336747b715Smrg    DeviceIntPtr dev, tmp;
353435c4bbdfSmrg    SpritePtr pSprite;
353505b261ecSmrg
353605b261ecSmrg    REQUEST(xWarpPointerReq);
353705b261ecSmrg    REQUEST_SIZE_MATCH(xWarpPointerReq);
353805b261ecSmrg
35396747b715Smrg    dev = PickPointer(client);
35406747b715Smrg
35416747b715Smrg    for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
354235c4bbdfSmrg        if (GetMaster(tmp, MASTER_ATTACHED) == dev) {
354335c4bbdfSmrg            rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
354435c4bbdfSmrg            if (rc != Success)
354535c4bbdfSmrg                return rc;
354635c4bbdfSmrg        }
35474642e01fSmrg    }
35484642e01fSmrg
354935c4bbdfSmrg    if (dev->lastSlave)
355035c4bbdfSmrg        dev = dev->lastSlave;
35514642e01fSmrg    pSprite = dev->spriteInfo->sprite;
35524642e01fSmrg
355305b261ecSmrg#ifdef PANORAMIX
355435c4bbdfSmrg    if (!noPanoramiXExtension)
355535c4bbdfSmrg        return XineramaWarpPointer(client);
355605b261ecSmrg#endif
355705b261ecSmrg
355805b261ecSmrg    if (stuff->dstWid != None) {
355935c4bbdfSmrg        rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess);
356035c4bbdfSmrg        if (rc != Success)
356135c4bbdfSmrg            return rc;
356205b261ecSmrg    }
35634642e01fSmrg    x = pSprite->hotPhys.x;
35644642e01fSmrg    y = pSprite->hotPhys.y;
356505b261ecSmrg
356635c4bbdfSmrg    if (stuff->srcWid != None) {
356735c4bbdfSmrg        int winX, winY;
356835c4bbdfSmrg        XID winID = stuff->srcWid;
356905b261ecSmrg        WindowPtr source;
35704642e01fSmrg
357135c4bbdfSmrg        rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess);
357235c4bbdfSmrg        if (rc != Success)
357335c4bbdfSmrg            return rc;
357435c4bbdfSmrg
357535c4bbdfSmrg        winX = source->drawable.x;
357635c4bbdfSmrg        winY = source->drawable.y;
357735c4bbdfSmrg        if (source->drawable.pScreen != pSprite->hotPhys.pScreen ||
357835c4bbdfSmrg            x < winX + stuff->srcX ||
357935c4bbdfSmrg            y < winY + stuff->srcY ||
358035c4bbdfSmrg            (stuff->srcWidth != 0 &&
358135c4bbdfSmrg             winX + stuff->srcX + (int) stuff->srcWidth < x) ||
358235c4bbdfSmrg            (stuff->srcHeight != 0 &&
358335c4bbdfSmrg             winY + stuff->srcY + (int) stuff->srcHeight < y) ||
35847e31ba66Smrg            (source->parent && !PointInWindowIsVisible(source, x, y)))
358535c4bbdfSmrg            return Success;
358635c4bbdfSmrg    }
358735c4bbdfSmrg    if (dest) {
358835c4bbdfSmrg        x = dest->drawable.x;
358935c4bbdfSmrg        y = dest->drawable.y;
359035c4bbdfSmrg        newScreen = dest->drawable.pScreen;
359135c4bbdfSmrg    }
359235c4bbdfSmrg    else
359335c4bbdfSmrg        newScreen = pSprite->hotPhys.pScreen;
359405b261ecSmrg
359505b261ecSmrg    x += stuff->dstX;
359605b261ecSmrg    y += stuff->dstY;
359705b261ecSmrg
359805b261ecSmrg    if (x < 0)
359935c4bbdfSmrg        x = 0;
360005b261ecSmrg    else if (x >= newScreen->width)
360135c4bbdfSmrg        x = newScreen->width - 1;
360205b261ecSmrg    if (y < 0)
360335c4bbdfSmrg        y = 0;
360405b261ecSmrg    else if (y >= newScreen->height)
360535c4bbdfSmrg        y = newScreen->height - 1;
360635c4bbdfSmrg
360735c4bbdfSmrg    if (newScreen == pSprite->hotPhys.pScreen) {
360835c4bbdfSmrg        if (x < pSprite->physLimits.x1)
360935c4bbdfSmrg            x = pSprite->physLimits.x1;
361035c4bbdfSmrg        else if (x >= pSprite->physLimits.x2)
361135c4bbdfSmrg            x = pSprite->physLimits.x2 - 1;
361235c4bbdfSmrg        if (y < pSprite->physLimits.y1)
361335c4bbdfSmrg            y = pSprite->physLimits.y1;
361435c4bbdfSmrg        else if (y >= pSprite->physLimits.y2)
361535c4bbdfSmrg            y = pSprite->physLimits.y2 - 1;
361635c4bbdfSmrg        if (pSprite->hotShape)
361735c4bbdfSmrg            ConfineToShape(dev, pSprite->hotShape, &x, &y);
361835c4bbdfSmrg        (*newScreen->SetCursorPosition) (dev, newScreen, x, y, TRUE);
361935c4bbdfSmrg    }
362035c4bbdfSmrg    else if (!PointerConfinedToScreen(dev)) {
362135c4bbdfSmrg        NewCurrentScreen(dev, newScreen, x, y);
362205b261ecSmrg    }
36237e31ba66Smrg    if (*newScreen->CursorWarpedTo)
36247e31ba66Smrg        (*newScreen->CursorWarpedTo) (dev, newScreen, client,
36257e31ba66Smrg                                      dest, pSprite, x, y);
362605b261ecSmrg    return Success;
362705b261ecSmrg}
362805b261ecSmrg
36294642e01fSmrgstatic Bool
36304642e01fSmrgBorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
363105b261ecSmrg{
363235c4bbdfSmrg    if (RegionNotEmpty(&pWin->borderSize))
363335c4bbdfSmrg        return TRUE;
363405b261ecSmrg
363505b261ecSmrg#ifdef PANORAMIX
363635c4bbdfSmrg    if (!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) {
363735c4bbdfSmrg        int i;
363835c4bbdfSmrg
363935c4bbdfSmrg        FOR_NSCREENS_FORWARD_SKIP(i) {
364035c4bbdfSmrg            if (RegionNotEmpty
364135c4bbdfSmrg                (&pDev->spriteInfo->sprite->windows[i]->borderSize))
364235c4bbdfSmrg                return TRUE;
364335c4bbdfSmrg        }
364435c4bbdfSmrg    }
364505b261ecSmrg#endif
364635c4bbdfSmrg    return FALSE;
364705b261ecSmrg}
364805b261ecSmrg
36494642e01fSmrg/**
365035c4bbdfSmrg * Activate the given passive grab. If the grab is activated successfully, the
365135c4bbdfSmrg * event has been delivered to the client.
36524642e01fSmrg *
365335c4bbdfSmrg * @param device The device of the event to check.
365435c4bbdfSmrg * @param grab The grab to check.
36556747b715Smrg * @param event The current device event.
365635c4bbdfSmrg * @param real_event The original event, in case of touch emulation. The
365735c4bbdfSmrg * real event is the one stored in the sync queue.
365835c4bbdfSmrg *
365935c4bbdfSmrg * @return Whether the grab has been activated.
366005b261ecSmrg */
366135c4bbdfSmrgBool
366235c4bbdfSmrgActivatePassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event,
366335c4bbdfSmrg                    InternalEvent *real_event)
366405b261ecSmrg{
36659ace9065Smrg    SpritePtr pSprite = device->spriteInfo->sprite;
366635c4bbdfSmrg    GrabInfoPtr grabinfo = &device->deviceGrab;
366735c4bbdfSmrg    xEvent *xE = NULL;
366835c4bbdfSmrg    int count;
366935c4bbdfSmrg    int rc;
36706747b715Smrg
367135c4bbdfSmrg    /* The only consumers of corestate are Xi 1.x and core events, which
367235c4bbdfSmrg     * are guaranteed to come from DeviceEvents. */
367335c4bbdfSmrg    if (grab->grabtype == XI || grab->grabtype == CORE) {
367435c4bbdfSmrg        DeviceIntPtr gdev;
367505b261ecSmrg
367635c4bbdfSmrg        event->device_event.corestate &= 0x1f00;
367735c4bbdfSmrg
367835c4bbdfSmrg        if (grab->grabtype == CORE)
367935c4bbdfSmrg            gdev = GetMaster(device, KEYBOARD_OR_FLOAT);
368035c4bbdfSmrg        else
368135c4bbdfSmrg            gdev = grab->modifierDevice;
368235c4bbdfSmrg
368335c4bbdfSmrg        if (gdev && gdev->key && gdev->key->xkbInfo)
368435c4bbdfSmrg            event->device_event.corestate |=
368535c4bbdfSmrg                gdev->key->xkbInfo->state.grab_mods & (~0x1f00);
368635c4bbdfSmrg    }
368735c4bbdfSmrg
368835c4bbdfSmrg    if (grab->grabtype == CORE) {
368935c4bbdfSmrg        rc = EventToCore(event, &xE, &count);
369035c4bbdfSmrg        if (rc != Success) {
369135c4bbdfSmrg            BUG_WARN_MSG(rc != BadMatch, "[dix] %s: core conversion failed"
369235c4bbdfSmrg                         "(%d, %d).\n", device->name, event->any.type, rc);
369335c4bbdfSmrg            return FALSE;
36944642e01fSmrg        }
369535c4bbdfSmrg    }
369635c4bbdfSmrg    else if (grab->grabtype == XI2) {
369735c4bbdfSmrg        rc = EventToXI2(event, &xE);
369835c4bbdfSmrg        if (rc != Success) {
369935c4bbdfSmrg            if (rc != BadMatch)
370035c4bbdfSmrg                BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI2 conversion failed"
370135c4bbdfSmrg                             "(%d, %d).\n", device->name, event->any.type, rc);
370235c4bbdfSmrg            return FALSE;
370335c4bbdfSmrg        }
370435c4bbdfSmrg        count = 1;
370535c4bbdfSmrg    }
370635c4bbdfSmrg    else {
370735c4bbdfSmrg        rc = EventToXI(event, &xE, &count);
370835c4bbdfSmrg        if (rc != Success) {
370935c4bbdfSmrg            if (rc != BadMatch)
371035c4bbdfSmrg                BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI conversion failed"
371135c4bbdfSmrg                             "(%d, %d).\n", device->name, event->any.type, rc);
371235c4bbdfSmrg            return FALSE;
371335c4bbdfSmrg        }
371435c4bbdfSmrg    }
37156747b715Smrg
371635c4bbdfSmrg    (*grabinfo->ActivateGrab) (device, grab,
371735c4bbdfSmrg                               ClientTimeToServerTime(event->any.time), TRUE);
37186747b715Smrg
371935c4bbdfSmrg    if (xE) {
372035c4bbdfSmrg        FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
37216747b715Smrg
372235c4bbdfSmrg        /* XXX: XACE? */
372335c4bbdfSmrg        TryClientEvents(rClient(grab), device, xE, count,
372435c4bbdfSmrg                        GetEventFilter(device, xE),
372535c4bbdfSmrg                        GetEventFilter(device, xE), grab);
372635c4bbdfSmrg    }
37276747b715Smrg
372835c4bbdfSmrg    if (grabinfo->sync.state == FROZEN_NO_EVENT)
372935c4bbdfSmrg        grabinfo->sync.state = FROZEN_WITH_EVENT;
373035c4bbdfSmrg    *grabinfo->sync.event = real_event->device_event;
37316747b715Smrg
373235c4bbdfSmrg    free(xE);
373335c4bbdfSmrg    return TRUE;
373435c4bbdfSmrg}
373535c4bbdfSmrg
373635c4bbdfSmrgstatic BOOL
373735c4bbdfSmrgCoreGrabInterferes(DeviceIntPtr device, GrabPtr grab)
373835c4bbdfSmrg{
373935c4bbdfSmrg    DeviceIntPtr other;
374035c4bbdfSmrg    BOOL interfering = FALSE;
374135c4bbdfSmrg
374235c4bbdfSmrg    for (other = inputInfo.devices; other; other = other->next) {
374335c4bbdfSmrg        GrabPtr othergrab = other->deviceGrab.grab;
374435c4bbdfSmrg
374535c4bbdfSmrg        if (othergrab && othergrab->grabtype == CORE &&
374635c4bbdfSmrg            SameClient(grab, rClient(othergrab)) &&
374735c4bbdfSmrg            ((IsPointerDevice(grab->device) &&
374835c4bbdfSmrg              IsPointerDevice(othergrab->device)) ||
374935c4bbdfSmrg             (IsKeyboardDevice(grab->device) &&
375035c4bbdfSmrg              IsKeyboardDevice(othergrab->device)))) {
375135c4bbdfSmrg            interfering = TRUE;
375235c4bbdfSmrg            break;
37536747b715Smrg        }
375435c4bbdfSmrg    }
37556747b715Smrg
375635c4bbdfSmrg    return interfering;
375735c4bbdfSmrg}
37584642e01fSmrg
375935c4bbdfSmrgenum MatchFlags {
376035c4bbdfSmrg    NO_MATCH = 0x0,
376135c4bbdfSmrg    CORE_MATCH = 0x1,
376235c4bbdfSmrg    XI_MATCH = 0x2,
376335c4bbdfSmrg    XI2_MATCH = 0x4,
376435c4bbdfSmrg};
37656747b715Smrg
376635c4bbdfSmrg/**
376735c4bbdfSmrg * Match the grab against the temporary grab on the given input level.
376835c4bbdfSmrg * Modifies the temporary grab pointer.
376935c4bbdfSmrg *
377035c4bbdfSmrg * @param grab The grab to match against
377135c4bbdfSmrg * @param tmp The temporary grab to use for matching
377235c4bbdfSmrg * @param level The input level we want to match on
377335c4bbdfSmrg * @param event_type Wire protocol event type
377435c4bbdfSmrg *
377535c4bbdfSmrg * @return The respective matched flag or 0 for no match
377635c4bbdfSmrg */
377735c4bbdfSmrgstatic enum MatchFlags
377835c4bbdfSmrgMatchForType(const GrabPtr grab, GrabPtr tmp, enum InputLevel level,
377935c4bbdfSmrg             int event_type)
378035c4bbdfSmrg{
378135c4bbdfSmrg    enum MatchFlags match;
378235c4bbdfSmrg    BOOL ignore_device = FALSE;
378335c4bbdfSmrg    int grabtype;
378435c4bbdfSmrg    int evtype;
37854642e01fSmrg
378635c4bbdfSmrg    switch (level) {
378735c4bbdfSmrg    case XI2:
378835c4bbdfSmrg        grabtype = XI2;
378935c4bbdfSmrg        evtype = GetXI2Type(event_type);
379035c4bbdfSmrg        BUG_WARN(!evtype);
379135c4bbdfSmrg        match = XI2_MATCH;
379235c4bbdfSmrg        break;
379335c4bbdfSmrg    case XI:
379435c4bbdfSmrg        grabtype = XI;
379535c4bbdfSmrg        evtype = GetXIType(event_type);
379635c4bbdfSmrg        match = XI_MATCH;
379735c4bbdfSmrg        break;
379835c4bbdfSmrg    case CORE:
379935c4bbdfSmrg        grabtype = CORE;
380035c4bbdfSmrg        evtype = GetCoreType(event_type);
380135c4bbdfSmrg        match = CORE_MATCH;
380235c4bbdfSmrg        ignore_device = TRUE;
380335c4bbdfSmrg        break;
380435c4bbdfSmrg    default:
380535c4bbdfSmrg        return NO_MATCH;
380635c4bbdfSmrg    }
380735c4bbdfSmrg
380835c4bbdfSmrg    tmp->grabtype = grabtype;
380935c4bbdfSmrg    tmp->type = evtype;
381035c4bbdfSmrg
381135c4bbdfSmrg    if (tmp->type && GrabMatchesSecond(tmp, grab, ignore_device))
381235c4bbdfSmrg        return match;
381335c4bbdfSmrg
381435c4bbdfSmrg    return NO_MATCH;
381535c4bbdfSmrg}
38164642e01fSmrg
381735c4bbdfSmrg/**
381835c4bbdfSmrg * Check an individual grab against an event to determine if a passive grab
381935c4bbdfSmrg * should be activated.
382035c4bbdfSmrg *
382135c4bbdfSmrg * @param device The device of the event to check.
382235c4bbdfSmrg * @param grab The grab to check.
382335c4bbdfSmrg * @param event The current device event.
382435c4bbdfSmrg * @param checkCore Check for core grabs too.
382535c4bbdfSmrg * @param tempGrab A pre-allocated temporary grab record for matching. This
382635c4bbdfSmrg *        must have the window and device values filled in.
382735c4bbdfSmrg *
382835c4bbdfSmrg * @return Whether the grab matches the event.
382935c4bbdfSmrg */
383035c4bbdfSmrgstatic Bool
383135c4bbdfSmrgCheckPassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event,
383235c4bbdfSmrg                 Bool checkCore, GrabPtr tempGrab)
383335c4bbdfSmrg{
383435c4bbdfSmrg    DeviceIntPtr gdev;
383535c4bbdfSmrg    XkbSrvInfoPtr xkbi = NULL;
383635c4bbdfSmrg    enum MatchFlags match = 0;
383735c4bbdfSmrg    int emulated_type = 0;
38386747b715Smrg
383935c4bbdfSmrg    gdev = grab->modifierDevice;
384035c4bbdfSmrg    if (grab->grabtype == CORE) {
384135c4bbdfSmrg        gdev = GetMaster(device, KEYBOARD_OR_FLOAT);
384235c4bbdfSmrg    }
384335c4bbdfSmrg    else if (grab->grabtype == XI2) {
384435c4bbdfSmrg        /* if the device is an attached slave device, gdev must be the
384535c4bbdfSmrg         * attached master keyboard. Since the slave may have been
384635c4bbdfSmrg         * reattached after the grab, the modifier device may not be the
384735c4bbdfSmrg         * same. */
384835c4bbdfSmrg        if (!IsMaster(grab->device) && !IsFloating(device))
384935c4bbdfSmrg            gdev = GetMaster(device, MASTER_KEYBOARD);
385035c4bbdfSmrg    }
38514642e01fSmrg
385235c4bbdfSmrg    if (gdev && gdev->key)
385335c4bbdfSmrg        xkbi = gdev->key->xkbInfo;
385435c4bbdfSmrg    tempGrab->modifierDevice = grab->modifierDevice;
385535c4bbdfSmrg    tempGrab->modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
385605b261ecSmrg
385735c4bbdfSmrg    /* Check for XI2 and XI grabs first */
385835c4bbdfSmrg    match = MatchForType(grab, tempGrab, XI2, event->any.type);
385905b261ecSmrg
386035c4bbdfSmrg    if (!match && IsTouchEvent(event) &&
386135c4bbdfSmrg        (event->device_event.flags & TOUCH_POINTER_EMULATED)) {
386235c4bbdfSmrg        emulated_type = TouchGetPointerEventType(event);
386335c4bbdfSmrg        match = MatchForType(grab, tempGrab, XI2, emulated_type);
386435c4bbdfSmrg    }
386535c4bbdfSmrg
386635c4bbdfSmrg    if (!match)
386735c4bbdfSmrg        match = MatchForType(grab, tempGrab, XI, event->any.type);
386835c4bbdfSmrg
386935c4bbdfSmrg    if (!match && emulated_type)
387035c4bbdfSmrg        match = MatchForType(grab, tempGrab, XI, emulated_type);
387135c4bbdfSmrg
387235c4bbdfSmrg    if (!match && checkCore) {
387335c4bbdfSmrg        match = MatchForType(grab, tempGrab, CORE, event->any.type);
387435c4bbdfSmrg        if (!match && emulated_type)
387535c4bbdfSmrg            match = MatchForType(grab, tempGrab, CORE, emulated_type);
387635c4bbdfSmrg    }
387735c4bbdfSmrg
387835c4bbdfSmrg    if (!match || (grab->confineTo &&
387935c4bbdfSmrg                   (!grab->confineTo->realized ||
388035c4bbdfSmrg                    !BorderSizeNotEmpty(device, grab->confineTo))))
388135c4bbdfSmrg        return FALSE;
388235c4bbdfSmrg
388335c4bbdfSmrg    /* In some cases a passive core grab may exist, but the client
388435c4bbdfSmrg     * already has a core grab on some other device. In this case we
388535c4bbdfSmrg     * must not get the grab, otherwise we may never ungrab the
388635c4bbdfSmrg     * device.
388735c4bbdfSmrg     */
388835c4bbdfSmrg
388935c4bbdfSmrg    if (grab->grabtype == CORE) {
389035c4bbdfSmrg        /* A passive grab may have been created for a different device
389135c4bbdfSmrg           than it is assigned to at this point in time.
389235c4bbdfSmrg           Update the grab's device and modifier device to reflect the
389335c4bbdfSmrg           current state.
389435c4bbdfSmrg           Since XGrabDeviceButton requires to specify the
389535c4bbdfSmrg           modifierDevice explicitly, we don't override this choice.
389635c4bbdfSmrg         */
389735c4bbdfSmrg        if (grab->type < GenericEvent) {
389835c4bbdfSmrg            grab->device = device;
389935c4bbdfSmrg            grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD);
390035c4bbdfSmrg        }
390135c4bbdfSmrg
390235c4bbdfSmrg        if (CoreGrabInterferes(device, grab))
390335c4bbdfSmrg            return FALSE;
390435c4bbdfSmrg    }
390535c4bbdfSmrg
390635c4bbdfSmrg    return TRUE;
390735c4bbdfSmrg}
390835c4bbdfSmrg
390935c4bbdfSmrg/**
391035c4bbdfSmrg * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
391135c4bbdfSmrg * passive grab set on the window to be activated.
391235c4bbdfSmrg * If activate is true and a passive grab is found, it will be activated,
391335c4bbdfSmrg * and the event will be delivered to the client.
391435c4bbdfSmrg *
391535c4bbdfSmrg * @param pWin The window that may be subject to a passive grab.
391635c4bbdfSmrg * @param device Device that caused the event.
391735c4bbdfSmrg * @param event The current device event.
391835c4bbdfSmrg * @param checkCore Check for core grabs too.
391935c4bbdfSmrg * @param activate If a grab is found, activate it and deliver the event.
392035c4bbdfSmrg */
392135c4bbdfSmrg
392235c4bbdfSmrgGrabPtr
392335c4bbdfSmrgCheckPassiveGrabsOnWindow(WindowPtr pWin,
392435c4bbdfSmrg                          DeviceIntPtr device,
392535c4bbdfSmrg                          InternalEvent *event, BOOL checkCore, BOOL activate)
392635c4bbdfSmrg{
392735c4bbdfSmrg    GrabPtr grab = wPassiveGrabs(pWin);
392835c4bbdfSmrg    GrabPtr tempGrab;
392935c4bbdfSmrg
393035c4bbdfSmrg    if (!grab)
393135c4bbdfSmrg        return NULL;
393235c4bbdfSmrg
393335c4bbdfSmrg    tempGrab = AllocGrab(NULL);
393435c4bbdfSmrg    if (tempGrab == NULL)
393535c4bbdfSmrg        return NULL;
393635c4bbdfSmrg
393735c4bbdfSmrg    /* Fill out the grab details, but leave the type for later before
393835c4bbdfSmrg     * comparing */
393935c4bbdfSmrg    switch (event->any.type) {
394035c4bbdfSmrg    case ET_KeyPress:
394135c4bbdfSmrg    case ET_KeyRelease:
394235c4bbdfSmrg        tempGrab->detail.exact = event->device_event.detail.key;
394335c4bbdfSmrg        break;
394435c4bbdfSmrg    case ET_ButtonPress:
394535c4bbdfSmrg    case ET_ButtonRelease:
394635c4bbdfSmrg    case ET_TouchBegin:
394735c4bbdfSmrg    case ET_TouchEnd:
394835c4bbdfSmrg        tempGrab->detail.exact = event->device_event.detail.button;
394935c4bbdfSmrg        break;
395035c4bbdfSmrg    default:
395135c4bbdfSmrg        tempGrab->detail.exact = 0;
395235c4bbdfSmrg        break;
395335c4bbdfSmrg    }
395435c4bbdfSmrg    tempGrab->window = pWin;
395535c4bbdfSmrg    tempGrab->device = device;
395635c4bbdfSmrg    tempGrab->detail.pMask = NULL;
395735c4bbdfSmrg    tempGrab->modifiersDetail.pMask = NULL;
395835c4bbdfSmrg    tempGrab->next = NULL;
395935c4bbdfSmrg
396035c4bbdfSmrg    for (; grab; grab = grab->next) {
396135c4bbdfSmrg        if (!CheckPassiveGrab(device, grab, event, checkCore, tempGrab))
396235c4bbdfSmrg            continue;
396335c4bbdfSmrg
396435c4bbdfSmrg        if (activate && !ActivatePassiveGrab(device, grab, event, event))
396535c4bbdfSmrg            continue;
39666747b715Smrg
396735c4bbdfSmrg        break;
396805b261ecSmrg    }
396935c4bbdfSmrg
397035c4bbdfSmrg    FreeGrab(tempGrab);
397135c4bbdfSmrg    return grab;
397205b261ecSmrg}
397305b261ecSmrg
397405b261ecSmrg/**
397505b261ecSmrg * CheckDeviceGrabs handles both keyboard and pointer events that may cause
39764642e01fSmrg * a passive grab to be activated.
397705b261ecSmrg *
397805b261ecSmrg * If the event is a keyboard event, the ancestors of the focus window are
397905b261ecSmrg * traced down and tried to see if they have any passive grabs to be
398005b261ecSmrg * activated.  If the focus window itself is reached and it's descendants
398105b261ecSmrg * contain the pointer, the ancestors of the window that the pointer is in
398205b261ecSmrg * are then traced down starting at the focus window, otherwise no grabs are
39834642e01fSmrg * activated.
398405b261ecSmrg * If the event is a pointer event, the ancestors of the window that the
398505b261ecSmrg * pointer is in are traced down starting at the root until CheckPassiveGrabs
398605b261ecSmrg * causes a passive grab to activate or all the windows are
398705b261ecSmrg * tried. PRH
398805b261ecSmrg *
398905b261ecSmrg * If a grab is activated, the event has been sent to the client already!
399005b261ecSmrg *
39914642e01fSmrg * The event we pass in must always be an XI event. From this, we then emulate
39924642e01fSmrg * the core event and then check for grabs.
39934642e01fSmrg *
399405b261ecSmrg * @param device The device that caused the event.
39954642e01fSmrg * @param xE The event to handle (Device{Button|Key}Press).
399605b261ecSmrg * @param count Number of events in list.
399705b261ecSmrg * @return TRUE if a grab has been activated or false otherwise.
399805b261ecSmrg*/
399905b261ecSmrg
400005b261ecSmrgBool
40019ace9065SmrgCheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor)
400205b261ecSmrg{
400305b261ecSmrg    int i;
400405b261ecSmrg    WindowPtr pWin = NULL;
400535c4bbdfSmrg    FocusClassPtr focus =
400635c4bbdfSmrg        IsPointerEvent((InternalEvent *) event) ? NULL : device->focus;
40076747b715Smrg    BOOL sendCore = (IsMaster(device) && device->coreEvents);
400835c4bbdfSmrg    Bool ret = FALSE;
400905b261ecSmrg
401035c4bbdfSmrg    if (event->type != ET_ButtonPress && event->type != ET_KeyPress)
40114642e01fSmrg        return FALSE;
40124642e01fSmrg
401335c4bbdfSmrg    if (event->type == ET_ButtonPress && (device->button->buttonsDown != 1))
401435c4bbdfSmrg        return FALSE;
40154642e01fSmrg
40169ace9065Smrg    if (device->deviceGrab.grab)
40179ace9065Smrg        return FALSE;
40189ace9065Smrg
40199ace9065Smrg    i = 0;
402035c4bbdfSmrg    if (ancestor) {
40219ace9065Smrg        while (i < device->spriteInfo->sprite->spriteTraceGood)
40229ace9065Smrg            if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor)
40239ace9065Smrg                break;
40249ace9065Smrg        if (i == device->spriteInfo->sprite->spriteTraceGood)
402535c4bbdfSmrg            goto out;
40269ace9065Smrg    }
402705b261ecSmrg
402835c4bbdfSmrg    if (focus) {
402935c4bbdfSmrg        for (; i < focus->traceGood; i++) {
403035c4bbdfSmrg            pWin = focus->trace[i];
403135c4bbdfSmrg            if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event,
403235c4bbdfSmrg                                          sendCore, TRUE)) {
403335c4bbdfSmrg                ret = TRUE;
403435c4bbdfSmrg                goto out;
403535c4bbdfSmrg            }
403635c4bbdfSmrg        }
40374642e01fSmrg
403835c4bbdfSmrg        if ((focus->win == NoneWin) ||
403935c4bbdfSmrg            (i >= device->spriteInfo->sprite->spriteTraceGood) ||
404035c4bbdfSmrg            (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i - 1]))
404135c4bbdfSmrg            goto out;
404205b261ecSmrg    }
404305b261ecSmrg
404435c4bbdfSmrg    for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) {
404535c4bbdfSmrg        pWin = device->spriteInfo->sprite->spriteTrace[i];
404635c4bbdfSmrg        if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event,
404735c4bbdfSmrg                                      sendCore, TRUE)) {
404835c4bbdfSmrg            ret = TRUE;
404935c4bbdfSmrg            goto out;
405035c4bbdfSmrg        }
405105b261ecSmrg    }
405205b261ecSmrg
405335c4bbdfSmrg out:
405435c4bbdfSmrg    if (ret == TRUE && event->type == ET_KeyPress)
405535c4bbdfSmrg        device->deviceGrab.activatingKey = event->detail.key;
405635c4bbdfSmrg    return ret;
405705b261ecSmrg}
405805b261ecSmrg
405905b261ecSmrg/**
406005b261ecSmrg * Called for keyboard events to deliver event to whatever client owns the
40616747b715Smrg * focus.
40626747b715Smrg *
40636747b715Smrg * The event is delivered to the keyboard's focus window, the root window or
40646747b715Smrg * to the window owning the input focus.
406505b261ecSmrg *
406605b261ecSmrg * @param keybd The keyboard originating the event.
40676747b715Smrg * @param event The event, not yet in wire format.
406805b261ecSmrg * @param window Window underneath the sprite.
406905b261ecSmrg */
407005b261ecSmrgvoid
40716747b715SmrgDeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
407205b261ecSmrg{
40736747b715Smrg    DeviceIntPtr ptr;
407405b261ecSmrg    WindowPtr focus = keybd->focus->win;
40756747b715Smrg    BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents);
407635c4bbdfSmrg    xEvent *core = NULL, *xE = NULL, *xi2 = NULL;
40776747b715Smrg    int count, rc;
40784642e01fSmrg    int deliveries = 0;
407905b261ecSmrg
408005b261ecSmrg    if (focus == FollowKeyboardWin)
408135c4bbdfSmrg        focus = inputInfo.keyboard->focus->win;
408205b261ecSmrg    if (!focus)
408335c4bbdfSmrg        return;
408435c4bbdfSmrg    if (focus == PointerRootWin) {
408535c4bbdfSmrg        DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd);
408635c4bbdfSmrg        return;
408705b261ecSmrg    }
408835c4bbdfSmrg    if ((focus == window) || IsParent(focus, window)) {
408935c4bbdfSmrg        if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd))
409035c4bbdfSmrg            return;
409105b261ecSmrg    }
40924642e01fSmrg
409305b261ecSmrg    /* just deliver it to the focus window */
409435c4bbdfSmrg    ptr = GetMaster(keybd, POINTER_OR_FLOAT);
40956747b715Smrg
40966747b715Smrg    rc = EventToXI2(event, &xi2);
409735c4bbdfSmrg    if (rc == Success) {
40986747b715Smrg        /* XXX: XACE */
40996747b715Smrg        int filter = GetEventFilter(keybd, xi2);
410035c4bbdfSmrg
41019ace9065Smrg        FixUpEventFromWindow(ptr->spriteInfo->sprite, xi2, focus, None, FALSE);
41026747b715Smrg        deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1,
41036747b715Smrg                                           filter, NullGrab);
41046747b715Smrg        if (deliveries > 0)
41056747b715Smrg            goto unwind;
410635c4bbdfSmrg    }
410735c4bbdfSmrg    else if (rc != BadMatch)
410835c4bbdfSmrg        ErrorF
410935c4bbdfSmrg            ("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n",
411035c4bbdfSmrg             keybd->name, event->any.type, rc);
41116747b715Smrg
41126747b715Smrg    rc = EventToXI(event, &xE, &count);
41136747b715Smrg    if (rc == Success &&
411435c4bbdfSmrg        XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success) {
41159ace9065Smrg        FixUpEventFromWindow(ptr->spriteInfo->sprite, xE, focus, None, FALSE);
41166747b715Smrg        deliveries = DeliverEventsToWindow(keybd, focus, xE, count,
411735c4bbdfSmrg                                           GetEventFilter(keybd, xE), NullGrab);
41186747b715Smrg
41196747b715Smrg        if (deliveries > 0)
41206747b715Smrg            goto unwind;
412135c4bbdfSmrg    }
412235c4bbdfSmrg    else if (rc != BadMatch)
412335c4bbdfSmrg        ErrorF
412435c4bbdfSmrg            ("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n",
412535c4bbdfSmrg             keybd->name, event->any.type, rc);
41264642e01fSmrg
412735c4bbdfSmrg    if (sendCore) {
412835c4bbdfSmrg        rc = EventToCore(event, &core, &count);
41296747b715Smrg        if (rc == Success) {
413035c4bbdfSmrg            if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, core, count) ==
413135c4bbdfSmrg                Success) {
413235c4bbdfSmrg                FixUpEventFromWindow(keybd->spriteInfo->sprite, core, focus,
41339ace9065Smrg                                     None, FALSE);
413435c4bbdfSmrg                deliveries =
413535c4bbdfSmrg                    DeliverEventsToWindow(keybd, focus, core, count,
413635c4bbdfSmrg                                          GetEventFilter(keybd, core),
413735c4bbdfSmrg                                          NullGrab);
41386747b715Smrg            }
413935c4bbdfSmrg        }
414035c4bbdfSmrg        else if (rc != BadMatch)
414135c4bbdfSmrg            ErrorF
414235c4bbdfSmrg                ("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n",
414335c4bbdfSmrg                 keybd->name, event->any.type, rc);
41444642e01fSmrg    }
41456747b715Smrg
414635c4bbdfSmrg unwind:
414735c4bbdfSmrg    free(core);
41486747b715Smrg    free(xE);
41496747b715Smrg    free(xi2);
41506747b715Smrg    return;
415105b261ecSmrg}
415205b261ecSmrg
415335c4bbdfSmrgint
415435c4bbdfSmrgDeliverOneGrabbedEvent(InternalEvent *event, DeviceIntPtr dev,
415535c4bbdfSmrg                       enum InputLevel level)
415635c4bbdfSmrg{
415735c4bbdfSmrg    SpritePtr pSprite = dev->spriteInfo->sprite;
415835c4bbdfSmrg    int rc;
415935c4bbdfSmrg    xEvent *xE = NULL;
416035c4bbdfSmrg    int count = 0;
416135c4bbdfSmrg    int deliveries = 0;
416235c4bbdfSmrg    Mask mask;
416335c4bbdfSmrg    GrabInfoPtr grabinfo = &dev->deviceGrab;
416435c4bbdfSmrg    GrabPtr grab = grabinfo->grab;
416535c4bbdfSmrg    Mask filter;
416635c4bbdfSmrg
416735c4bbdfSmrg    if (grab->grabtype != level)
416835c4bbdfSmrg        return 0;
416935c4bbdfSmrg
417035c4bbdfSmrg    switch (level) {
417135c4bbdfSmrg    case XI2:
417235c4bbdfSmrg        rc = EventToXI2(event, &xE);
417335c4bbdfSmrg        count = 1;
417435c4bbdfSmrg        if (rc == Success) {
417535c4bbdfSmrg            int evtype = xi2_get_type(xE);
417635c4bbdfSmrg
417735c4bbdfSmrg            mask = GetXI2MaskByte(grab->xi2mask, dev, evtype);
417835c4bbdfSmrg            filter = GetEventFilter(dev, xE);
417935c4bbdfSmrg        }
418035c4bbdfSmrg        break;
418135c4bbdfSmrg    case XI:
418235c4bbdfSmrg        if (grabinfo->fromPassiveGrab && grabinfo->implicitGrab)
418335c4bbdfSmrg            mask = grab->deviceMask;
418435c4bbdfSmrg        else
418535c4bbdfSmrg            mask = grab->eventMask;
418635c4bbdfSmrg        rc = EventToXI(event, &xE, &count);
418735c4bbdfSmrg        if (rc == Success)
418835c4bbdfSmrg            filter = GetEventFilter(dev, xE);
418935c4bbdfSmrg        break;
419035c4bbdfSmrg    case CORE:
419135c4bbdfSmrg        rc = EventToCore(event, &xE, &count);
419235c4bbdfSmrg        mask = grab->eventMask;
419335c4bbdfSmrg        if (rc == Success)
419435c4bbdfSmrg            filter = GetEventFilter(dev, xE);
419535c4bbdfSmrg        break;
419635c4bbdfSmrg    default:
419735c4bbdfSmrg        BUG_WARN_MSG(1, "Invalid input level %d\n", level);
419835c4bbdfSmrg        return 0;
419935c4bbdfSmrg    }
420035c4bbdfSmrg
420135c4bbdfSmrg    if (rc == Success) {
420235c4bbdfSmrg        FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
420335c4bbdfSmrg        if (XaceHook(XACE_SEND_ACCESS, 0, dev,
420435c4bbdfSmrg                     grab->window, xE, count) ||
420535c4bbdfSmrg            XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
420635c4bbdfSmrg                     grab->window, xE, count))
420735c4bbdfSmrg            deliveries = 1;     /* don't send, but pretend we did */
420835c4bbdfSmrg        else if (level != CORE || !IsInterferingGrab(rClient(grab), dev, xE)) {
420935c4bbdfSmrg            deliveries = TryClientEvents(rClient(grab), dev,
421035c4bbdfSmrg                                         xE, count, mask, filter, grab);
421135c4bbdfSmrg        }
421235c4bbdfSmrg    }
421335c4bbdfSmrg    else
421435c4bbdfSmrg        BUG_WARN_MSG(rc != BadMatch,
421535c4bbdfSmrg                     "%s: conversion to mode %d failed on %d with %d\n",
421635c4bbdfSmrg                     dev->name, level, event->any.type, rc);
421735c4bbdfSmrg
421835c4bbdfSmrg    free(xE);
421935c4bbdfSmrg    return deliveries;
422035c4bbdfSmrg}
422135c4bbdfSmrg
422205b261ecSmrg/**
422305b261ecSmrg * Deliver an event from a device that is currently grabbed. Uses
422405b261ecSmrg * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the
422505b261ecSmrg * grab. If not, TryClientEvents() is used.
422605b261ecSmrg *
422705b261ecSmrg * @param deactivateGrab True if the device's grab should be deactivated.
422835c4bbdfSmrg *
422935c4bbdfSmrg * @return The number of events delivered.
423005b261ecSmrg */
423135c4bbdfSmrgint
42326747b715SmrgDeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
42336747b715Smrg                    Bool deactivateGrab)
423405b261ecSmrg{
42354642e01fSmrg    GrabPtr grab;
42364642e01fSmrg    GrabInfoPtr grabinfo;
423705b261ecSmrg    int deliveries = 0;
423805b261ecSmrg    DeviceIntPtr dev;
42394642e01fSmrg    SpritePtr pSprite = thisDev->spriteInfo->sprite;
42404642e01fSmrg    BOOL sendCore = FALSE;
42414642e01fSmrg
42424642e01fSmrg    grabinfo = &thisDev->deviceGrab;
42434642e01fSmrg    grab = grabinfo->grab;
424405b261ecSmrg
424535c4bbdfSmrg    if (grab->ownerEvents) {
424635c4bbdfSmrg        WindowPtr focus;
424705b261ecSmrg
42484642e01fSmrg        /* Hack: Some pointer device have a focus class. So we need to check
42494642e01fSmrg         * for the type of event, to see if we really want to deliver it to
42504642e01fSmrg         * the focus window. For pointer events, the answer is no.
42514642e01fSmrg         */
42526747b715Smrg        if (IsPointerEvent(event))
42534642e01fSmrg            focus = PointerRootWin;
425435c4bbdfSmrg        else if (thisDev->focus) {
425535c4bbdfSmrg            focus = thisDev->focus->win;
425635c4bbdfSmrg            if (focus == FollowKeyboardWin)
425735c4bbdfSmrg                focus = inputInfo.keyboard->focus->win;
425835c4bbdfSmrg        }
425935c4bbdfSmrg        else
426035c4bbdfSmrg            focus = PointerRootWin;
426135c4bbdfSmrg        if (focus == PointerRootWin)
426235c4bbdfSmrg            deliveries = DeliverDeviceEvents(pSprite->win, event, grab,
42636747b715Smrg                                             NullWindow, thisDev);
426435c4bbdfSmrg        else if (focus && (focus == pSprite->win ||
426535c4bbdfSmrg                           IsParent(focus, pSprite->win)))
426635c4bbdfSmrg            deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus,
426735c4bbdfSmrg                                             thisDev);
426835c4bbdfSmrg        else if (focus)
426935c4bbdfSmrg            deliveries = DeliverDeviceEvents(focus, event, grab, focus,
427035c4bbdfSmrg                                             thisDev);
427135c4bbdfSmrg    }
427235c4bbdfSmrg    if (!deliveries) {
42736747b715Smrg        sendCore = (IsMaster(thisDev) && thisDev->coreEvents);
42746747b715Smrg        /* try core event */
427535c4bbdfSmrg        if ((sendCore && grab->grabtype == CORE) || grab->grabtype != CORE)
427635c4bbdfSmrg            deliveries = DeliverOneGrabbedEvent(event, thisDev, grab->grabtype);
42776747b715Smrg
42786747b715Smrg        if (deliveries && (event->any.type == ET_Motion))
42794642e01fSmrg            thisDev->valuator->motionHintWindow = grab->window;
428005b261ecSmrg    }
428135c4bbdfSmrg    if (deliveries && !deactivateGrab &&
428235c4bbdfSmrg        (event->any.type == ET_KeyPress ||
428335c4bbdfSmrg         event->any.type == ET_KeyRelease ||
428435c4bbdfSmrg         event->any.type == ET_ButtonPress ||
428535c4bbdfSmrg         event->any.type == ET_ButtonRelease)) {
428635c4bbdfSmrg        switch (grabinfo->sync.state) {
428735c4bbdfSmrg        case FREEZE_BOTH_NEXT_EVENT:
428835c4bbdfSmrg            dev = GetPairedDevice(thisDev);
428935c4bbdfSmrg            if (dev) {
429035c4bbdfSmrg                FreezeThaw(dev, TRUE);
429135c4bbdfSmrg                if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) &&
429235c4bbdfSmrg                    (CLIENT_BITS(grab->resource) ==
429335c4bbdfSmrg                     CLIENT_BITS(dev->deviceGrab.grab->resource)))
429435c4bbdfSmrg                    dev->deviceGrab.sync.state = FROZEN_NO_EVENT;
429535c4bbdfSmrg                else
42966747b715Smrg                    dev->deviceGrab.sync.other = grab;
429735c4bbdfSmrg            }
429835c4bbdfSmrg            /* fall through */
429935c4bbdfSmrg        case FREEZE_NEXT_EVENT:
430035c4bbdfSmrg            grabinfo->sync.state = FROZEN_WITH_EVENT;
430135c4bbdfSmrg            FreezeThaw(thisDev, TRUE);
430235c4bbdfSmrg            *grabinfo->sync.event = event->device_event;
430335c4bbdfSmrg            break;
430435c4bbdfSmrg        }
430505b261ecSmrg    }
430605b261ecSmrg
430735c4bbdfSmrg    return deliveries;
43086747b715Smrg}
430905b261ecSmrg
43106747b715Smrg/* This function is used to set the key pressed or key released state -
43116747b715Smrg   this is only used when the pressing of keys does not cause
43126747b715Smrg   the device's processInputProc to be called, as in for example Mouse Keys.
43136747b715Smrg*/
43146747b715Smrgvoid
431535c4bbdfSmrgFixKeyState(DeviceEvent *event, DeviceIntPtr keybd)
43166747b715Smrg{
43176747b715Smrg    int key = event->detail.key;
43186747b715Smrg
43196747b715Smrg    if (event->type == ET_KeyPress) {
432035c4bbdfSmrg        DebugF("FixKeyState: Key %d %s\n", key,
43216747b715Smrg               ((event->type == ET_KeyPress) ? "down" : "up"));
432205b261ecSmrg    }
43234642e01fSmrg
43246747b715Smrg    if (event->type == ET_KeyPress)
43256747b715Smrg        set_key_down(keybd, key, KEY_PROCESSED);
43266747b715Smrg    else if (event->type == ET_KeyRelease)
43276747b715Smrg        set_key_up(keybd, key, KEY_PROCESSED);
432805b261ecSmrg    else
43296747b715Smrg        FatalError("Impossible keyboard event");
433005b261ecSmrg}
433105b261ecSmrg
433205b261ecSmrg#define AtMostOneClient \
433305b261ecSmrg	(SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
43344642e01fSmrg#define ManagerMask \
43354642e01fSmrg	(SubstructureRedirectMask | ResizeRedirectMask)
433605b261ecSmrg
433705b261ecSmrg/**
433805b261ecSmrg * Recalculate which events may be deliverable for the given window.
433905b261ecSmrg * Recalculated mask is used for quicker determination which events may be
434005b261ecSmrg * delivered to a window.
434105b261ecSmrg *
434205b261ecSmrg * The otherEventMasks on a WindowOptional is the combination of all event
434305b261ecSmrg * masks set by all clients on the window.
434405b261ecSmrg * deliverableEventMask is the combination of the eventMask and the
43456747b715Smrg * otherEventMask plus the events that may be propagated to the parent.
434605b261ecSmrg *
434705b261ecSmrg * Traverses to siblings and parents of the window.
434805b261ecSmrg */
434905b261ecSmrgvoid
43506747b715SmrgRecalculateDeliverableEvents(WindowPtr pWin)
435105b261ecSmrg{
435205b261ecSmrg    OtherClients *others;
435305b261ecSmrg    WindowPtr pChild;
435405b261ecSmrg
435505b261ecSmrg    pChild = pWin;
435635c4bbdfSmrg    while (1) {
435735c4bbdfSmrg        if (pChild->optional) {
435835c4bbdfSmrg            pChild->optional->otherEventMasks = 0;
435935c4bbdfSmrg            for (others = wOtherClients(pChild); others; others = others->next) {
436035c4bbdfSmrg                pChild->optional->otherEventMasks |= others->mask;
436135c4bbdfSmrg            }
436235c4bbdfSmrg        }
436335c4bbdfSmrg        pChild->deliverableEvents = pChild->eventMask |
436435c4bbdfSmrg            wOtherEventMasks(pChild);
436535c4bbdfSmrg        if (pChild->parent)
436635c4bbdfSmrg            pChild->deliverableEvents |=
436735c4bbdfSmrg                (pChild->parent->deliverableEvents &
436835c4bbdfSmrg                 ~wDontPropagateMask(pChild) & PropagateMask);
436935c4bbdfSmrg        if (pChild->firstChild) {
437035c4bbdfSmrg            pChild = pChild->firstChild;
437135c4bbdfSmrg            continue;
437235c4bbdfSmrg        }
437335c4bbdfSmrg        while (!pChild->nextSib && (pChild != pWin))
437435c4bbdfSmrg            pChild = pChild->parent;
437535c4bbdfSmrg        if (pChild == pWin)
437635c4bbdfSmrg            break;
437735c4bbdfSmrg        pChild = pChild->nextSib;
437805b261ecSmrg    }
437905b261ecSmrg}
438005b261ecSmrg
438105b261ecSmrg/**
438205b261ecSmrg *
438305b261ecSmrg *  \param value must conform to DeleteType
438405b261ecSmrg */
438505b261ecSmrgint
438635c4bbdfSmrgOtherClientGone(void *value, XID id)
438705b261ecSmrg{
438805b261ecSmrg    OtherClientsPtr other, prev;
438935c4bbdfSmrg    WindowPtr pWin = (WindowPtr) value;
439005b261ecSmrg
439105b261ecSmrg    prev = 0;
439235c4bbdfSmrg    for (other = wOtherClients(pWin); other; other = other->next) {
439335c4bbdfSmrg        if (other->resource == id) {
439435c4bbdfSmrg            if (prev)
439535c4bbdfSmrg                prev->next = other->next;
439635c4bbdfSmrg            else {
439735c4bbdfSmrg                if (!(pWin->optional->otherClients = other->next))
439835c4bbdfSmrg                    CheckWindowOptionalNeed(pWin);
439935c4bbdfSmrg            }
440035c4bbdfSmrg            free(other);
440135c4bbdfSmrg            RecalculateDeliverableEvents(pWin);
440235c4bbdfSmrg            return Success;
440335c4bbdfSmrg        }
440435c4bbdfSmrg        prev = other;
440505b261ecSmrg    }
440605b261ecSmrg    FatalError("client not on event list");
440705b261ecSmrg}
440805b261ecSmrg
440905b261ecSmrgint
441005b261ecSmrgEventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
441105b261ecSmrg{
441205b261ecSmrg    Mask check;
441335c4bbdfSmrg    OtherClients *others;
44144642e01fSmrg    DeviceIntPtr dev;
44154642e01fSmrg    int rc;
441605b261ecSmrg
441735c4bbdfSmrg    if (mask & ~AllEventMasks) {
441835c4bbdfSmrg        client->errorValue = mask;
441935c4bbdfSmrg        return BadValue;
442005b261ecSmrg    }
44214642e01fSmrg    check = (mask & ManagerMask);
44224642e01fSmrg    if (check) {
442335c4bbdfSmrg        rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id,
442435c4bbdfSmrg                      RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess);
442535c4bbdfSmrg        if (rc != Success)
442635c4bbdfSmrg            return rc;
44274642e01fSmrg    }
442805b261ecSmrg    check = (mask & AtMostOneClient);
442935c4bbdfSmrg    if (check & (pWin->eventMask | wOtherEventMasks(pWin))) {
443035c4bbdfSmrg        /* It is illegal for two different clients to select on any of the
443135c4bbdfSmrg           events for AtMostOneClient. However, it is OK, for some client to
443235c4bbdfSmrg           continue selecting on one of those events.  */
443335c4bbdfSmrg        if ((wClient(pWin) != client) && (check & pWin->eventMask))
443435c4bbdfSmrg            return BadAccess;
443535c4bbdfSmrg        for (others = wOtherClients(pWin); others; others = others->next) {
443635c4bbdfSmrg            if (!SameClient(others, client) && (check & others->mask))
443735c4bbdfSmrg                return BadAccess;
443835c4bbdfSmrg        }
443905b261ecSmrg    }
444035c4bbdfSmrg    if (wClient(pWin) == client) {
444135c4bbdfSmrg        check = pWin->eventMask;
444235c4bbdfSmrg        pWin->eventMask = mask;
444335c4bbdfSmrg    }
444435c4bbdfSmrg    else {
444535c4bbdfSmrg        for (others = wOtherClients(pWin); others; others = others->next) {
444635c4bbdfSmrg            if (SameClient(others, client)) {
444735c4bbdfSmrg                check = others->mask;
444835c4bbdfSmrg                if (mask == 0) {
444935c4bbdfSmrg                    FreeResource(others->resource, RT_NONE);
445035c4bbdfSmrg                    return Success;
445135c4bbdfSmrg                }
445235c4bbdfSmrg                else
445335c4bbdfSmrg                    others->mask = mask;
445435c4bbdfSmrg                goto maskSet;
445535c4bbdfSmrg            }
445635c4bbdfSmrg        }
445735c4bbdfSmrg        check = 0;
445835c4bbdfSmrg        if (!pWin->optional && !MakeWindowOptional(pWin))
445935c4bbdfSmrg            return BadAlloc;
446035c4bbdfSmrg        others = malloc(sizeof(OtherClients));
446135c4bbdfSmrg        if (!others)
446235c4bbdfSmrg            return BadAlloc;
446335c4bbdfSmrg        others->mask = mask;
446435c4bbdfSmrg        others->resource = FakeClientID(client->index);
446535c4bbdfSmrg        others->next = pWin->optional->otherClients;
446635c4bbdfSmrg        pWin->optional->otherClients = others;
446735c4bbdfSmrg        if (!AddResource(others->resource, RT_OTHERCLIENT, (void *) pWin))
446835c4bbdfSmrg            return BadAlloc;
446935c4bbdfSmrg    }
447035c4bbdfSmrg maskSet:
447135c4bbdfSmrg    if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask)) {
447235c4bbdfSmrg        for (dev = inputInfo.devices; dev; dev = dev->next) {
44734642e01fSmrg            if (dev->valuator && dev->valuator->motionHintWindow == pWin)
44744642e01fSmrg                dev->valuator->motionHintWindow = NullWindow;
44754642e01fSmrg        }
44764642e01fSmrg    }
447705b261ecSmrg    RecalculateDeliverableEvents(pWin);
447805b261ecSmrg    return Success;
447905b261ecSmrg}
448005b261ecSmrg
448105b261ecSmrgint
44824642e01fSmrgEventSuppressForWindow(WindowPtr pWin, ClientPtr client,
448305b261ecSmrg                       Mask mask, Bool *checkOptional)
448405b261ecSmrg{
448535c4bbdfSmrg    int i, freed;
448605b261ecSmrg
448735c4bbdfSmrg    if (mask & ~PropagateMask) {
448835c4bbdfSmrg        client->errorValue = mask;
448935c4bbdfSmrg        return BadValue;
449005b261ecSmrg    }
449105b261ecSmrg    if (pWin->dontPropagate)
449235c4bbdfSmrg        DontPropagateRefCnts[pWin->dontPropagate]--;
449305b261ecSmrg    if (!mask)
449435c4bbdfSmrg        i = 0;
449535c4bbdfSmrg    else {
449635c4bbdfSmrg        for (i = DNPMCOUNT, freed = 0; --i > 0;) {
449735c4bbdfSmrg            if (!DontPropagateRefCnts[i])
449835c4bbdfSmrg                freed = i;
449935c4bbdfSmrg            else if (mask == DontPropagateMasks[i])
450035c4bbdfSmrg                break;
450135c4bbdfSmrg        }
450235c4bbdfSmrg        if (!i && freed) {
450335c4bbdfSmrg            i = freed;
450435c4bbdfSmrg            DontPropagateMasks[i] = mask;
450535c4bbdfSmrg        }
450605b261ecSmrg    }
450735c4bbdfSmrg    if (i || !mask) {
450835c4bbdfSmrg        pWin->dontPropagate = i;
450935c4bbdfSmrg        if (i)
451035c4bbdfSmrg            DontPropagateRefCnts[i]++;
451135c4bbdfSmrg        if (pWin->optional) {
451235c4bbdfSmrg            pWin->optional->dontPropagateMask = mask;
451335c4bbdfSmrg            *checkOptional = TRUE;
451435c4bbdfSmrg        }
451535c4bbdfSmrg    }
451635c4bbdfSmrg    else {
451735c4bbdfSmrg        if (!pWin->optional && !MakeWindowOptional(pWin)) {
451835c4bbdfSmrg            if (pWin->dontPropagate)
451935c4bbdfSmrg                DontPropagateRefCnts[pWin->dontPropagate]++;
452035c4bbdfSmrg            return BadAlloc;
452135c4bbdfSmrg        }
452235c4bbdfSmrg        pWin->dontPropagate = 0;
452305b261ecSmrg        pWin->optional->dontPropagateMask = mask;
452405b261ecSmrg    }
452505b261ecSmrg    RecalculateDeliverableEvents(pWin);
452605b261ecSmrg    return Success;
452705b261ecSmrg}
452805b261ecSmrg
452905b261ecSmrg/**
45304642e01fSmrg * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
45314642e01fSmrg * Uses the paired keyboard to get some additional information.
453205b261ecSmrg */
45334642e01fSmrgvoid
453435c4bbdfSmrgCoreEnterLeaveEvent(DeviceIntPtr mouse,
453535c4bbdfSmrg                    int type,
453635c4bbdfSmrg                    int mode, int detail, WindowPtr pWin, Window child)
453735c4bbdfSmrg{
453835c4bbdfSmrg    xEvent event = {
453935c4bbdfSmrg        .u.u.type = type,
454035c4bbdfSmrg        .u.u.detail = detail
454135c4bbdfSmrg    };
454235c4bbdfSmrg    WindowPtr focus;
454335c4bbdfSmrg    DeviceIntPtr keybd;
454435c4bbdfSmrg    GrabPtr grab = mouse->deviceGrab.grab;
454535c4bbdfSmrg    Mask mask;
454635c4bbdfSmrg
454735c4bbdfSmrg    keybd = GetMaster(mouse, KEYBOARD_OR_FLOAT);
45484642e01fSmrg
454905b261ecSmrg    if ((pWin == mouse->valuator->motionHintWindow) &&
455035c4bbdfSmrg        (detail != NotifyInferior))
455135c4bbdfSmrg        mouse->valuator->motionHintWindow = NullWindow;
455235c4bbdfSmrg    if (grab) {
455335c4bbdfSmrg        mask = (pWin == grab->window) ? grab->eventMask : 0;
455435c4bbdfSmrg        if (grab->ownerEvents)
455535c4bbdfSmrg            mask |= EventMaskForClient(pWin, rClient(grab));
455605b261ecSmrg    }
455735c4bbdfSmrg    else {
455835c4bbdfSmrg        mask = pWin->eventMask | wOtherEventMasks(pWin);
455905b261ecSmrg    }
45604642e01fSmrg
45614642e01fSmrg    event.u.enterLeave.time = currentTime.milliseconds;
45624642e01fSmrg    event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x;
45634642e01fSmrg    event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y;
45644642e01fSmrg    /* Counts on the same initial structure of crossing & button events! */
45659ace9065Smrg    FixUpEventFromWindow(mouse->spriteInfo->sprite, &event, pWin, None, FALSE);
45664642e01fSmrg    /* Enter/Leave events always set child */
45674642e01fSmrg    event.u.enterLeave.child = child;
45684642e01fSmrg    event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
45694642e01fSmrg        ELFlagSameScreen : 0;
457035c4bbdfSmrg    event.u.enterLeave.state =
457135c4bbdfSmrg        mouse->button ? (mouse->button->state & 0x1f00) : 0;
45726747b715Smrg    if (keybd)
45736747b715Smrg        event.u.enterLeave.state |=
457435c4bbdfSmrg            XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
45754642e01fSmrg    event.u.enterLeave.mode = mode;
45764642e01fSmrg    focus = (keybd) ? keybd->focus->win : None;
45774642e01fSmrg    if ((focus != NoneWin) &&
457835c4bbdfSmrg        ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin)))
45794642e01fSmrg        event.u.enterLeave.flags |= ELFlagFocus;
458005b261ecSmrg
458135c4bbdfSmrg    if ((mask & GetEventFilter(mouse, &event))) {
45824642e01fSmrg        if (grab)
45834642e01fSmrg            TryClientEvents(rClient(grab), mouse, &event, 1, mask,
45846747b715Smrg                            GetEventFilter(mouse, &event), grab);
45854642e01fSmrg        else
45864642e01fSmrg            DeliverEventsToWindow(mouse, pWin, &event, 1,
458735c4bbdfSmrg                                  GetEventFilter(mouse, &event), NullGrab);
458805b261ecSmrg    }
458905b261ecSmrg
459035c4bbdfSmrg    if ((type == EnterNotify) && (mask & KeymapStateMask)) {
459135c4bbdfSmrg        xKeymapEvent ke = {
459235c4bbdfSmrg            .type = KeymapNotify
459335c4bbdfSmrg        };
45946747b715Smrg        ClientPtr client = grab ? rClient(grab) : wClient(pWin);
459535c4bbdfSmrg        int rc;
459635c4bbdfSmrg
459735c4bbdfSmrg        rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess);
459835c4bbdfSmrg        if (rc == Success)
459935c4bbdfSmrg            memcpy((char *) &ke.map[0], (char *) &keybd->key->down[1], 31);
46004642e01fSmrg
46014642e01fSmrg        if (grab)
460235c4bbdfSmrg            TryClientEvents(rClient(grab), keybd, (xEvent *) &ke, 1,
46034642e01fSmrg                            mask, KeymapStateMask, grab);
46044642e01fSmrg        else
460535c4bbdfSmrg            DeliverEventsToWindow(mouse, pWin, (xEvent *) &ke, 1,
46066747b715Smrg                                  KeymapStateMask, NullGrab);
46076747b715Smrg    }
46086747b715Smrg}
46096747b715Smrg
46106747b715Smrgvoid
461135c4bbdfSmrgDeviceEnterLeaveEvent(DeviceIntPtr mouse,
461235c4bbdfSmrg                      int sourceid,
461335c4bbdfSmrg                      int type,
461435c4bbdfSmrg                      int mode, int detail, WindowPtr pWin, Window child)
461535c4bbdfSmrg{
461635c4bbdfSmrg    GrabPtr grab = mouse->deviceGrab.grab;
461735c4bbdfSmrg    xXIEnterEvent *event;
461835c4bbdfSmrg    WindowPtr focus;
461935c4bbdfSmrg    int filter;
462035c4bbdfSmrg    int btlen, len, i;
462135c4bbdfSmrg    DeviceIntPtr kbd;
46226747b715Smrg
46236747b715Smrg    if ((mode == XINotifyPassiveGrab && type == XI_Leave) ||
46246747b715Smrg        (mode == XINotifyPassiveUngrab && type == XI_Enter))
46256747b715Smrg        return;
46266747b715Smrg
46276747b715Smrg    btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
46286747b715Smrg    btlen = bytes_to_int32(btlen);
46296747b715Smrg    len = sizeof(xXIEnterEvent) + btlen * 4;
46306747b715Smrg
46316747b715Smrg    event = calloc(1, len);
463235c4bbdfSmrg    event->type = GenericEvent;
463335c4bbdfSmrg    event->extension = IReqCode;
463435c4bbdfSmrg    event->evtype = type;
463535c4bbdfSmrg    event->length = (len - sizeof(xEvent)) / 4;
463635c4bbdfSmrg    event->buttons_len = btlen;
463735c4bbdfSmrg    event->detail = detail;
463835c4bbdfSmrg    event->time = currentTime.milliseconds;
463935c4bbdfSmrg    event->deviceid = mouse->id;
464035c4bbdfSmrg    event->sourceid = sourceid;
464135c4bbdfSmrg    event->mode = mode;
464235c4bbdfSmrg    event->root_x = double_to_fp1616(mouse->spriteInfo->sprite->hot.x);
464335c4bbdfSmrg    event->root_y = double_to_fp1616(mouse->spriteInfo->sprite->hot.y);
46446747b715Smrg
46456747b715Smrg    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
46466747b715Smrg        if (BitIsOn(mouse->button->down, i))
46476747b715Smrg            SetBit(&event[1], i);
46486747b715Smrg
464935c4bbdfSmrg    kbd = GetMaster(mouse, MASTER_KEYBOARD);
465035c4bbdfSmrg    if (kbd && kbd->key) {
46516747b715Smrg        event->mods.base_mods = kbd->key->xkbInfo->state.base_mods;
46526747b715Smrg        event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods;
46536747b715Smrg        event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods;
46546747b715Smrg
46556747b715Smrg        event->group.base_group = kbd->key->xkbInfo->state.base_group;
46566747b715Smrg        event->group.latched_group = kbd->key->xkbInfo->state.latched_group;
46576747b715Smrg        event->group.locked_group = kbd->key->xkbInfo->state.locked_group;
465805b261ecSmrg    }
46596747b715Smrg
466035c4bbdfSmrg    focus = (kbd) ? kbd->focus->win : None;
466135c4bbdfSmrg    if ((focus != NoneWin) &&
466235c4bbdfSmrg        ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin)))
466335c4bbdfSmrg        event->focus = TRUE;
466435c4bbdfSmrg
466535c4bbdfSmrg    FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent *) event, pWin,
46669ace9065Smrg                         None, FALSE);
46676747b715Smrg
466835c4bbdfSmrg    filter = GetEventFilter(mouse, (xEvent *) event);
46696747b715Smrg
467035c4bbdfSmrg    if (grab && grab->grabtype == XI2) {
46716747b715Smrg        Mask mask;
467235c4bbdfSmrg
467335c4bbdfSmrg        mask = xi2mask_isset(grab->xi2mask, mouse, type);
467435c4bbdfSmrg        TryClientEvents(rClient(grab), mouse, (xEvent *) event, 1, mask, 1,
467535c4bbdfSmrg                        grab);
467635c4bbdfSmrg    }
467735c4bbdfSmrg    else {
467835c4bbdfSmrg        if (!WindowXI2MaskIsset(mouse, pWin, (xEvent *) event))
46796747b715Smrg            goto out;
468035c4bbdfSmrg        DeliverEventsToWindow(mouse, pWin, (xEvent *) event, 1, filter,
46816747b715Smrg                              NullGrab);
46826747b715Smrg    }
46836747b715Smrg
468435c4bbdfSmrg out:
46856747b715Smrg    free(event);
468605b261ecSmrg}
468705b261ecSmrg
46884642e01fSmrgvoid
46894642e01fSmrgCoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
469005b261ecSmrg{
469135c4bbdfSmrg    xEvent event = {
469235c4bbdfSmrg        .u.u.type = type,
469335c4bbdfSmrg        .u.u.detail = detail
469435c4bbdfSmrg    };
469505b261ecSmrg    event.u.focus.mode = mode;
469605b261ecSmrg    event.u.focus.window = pWin->drawable.id;
46976747b715Smrg
46986747b715Smrg    DeliverEventsToWindow(dev, pWin, &event, 1,
46996747b715Smrg                          GetEventFilter(dev, &event), NullGrab);
470005b261ecSmrg    if ((type == FocusIn) &&
470135c4bbdfSmrg        ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) {
470235c4bbdfSmrg        xKeymapEvent ke = {
470335c4bbdfSmrg            .type = KeymapNotify
470435c4bbdfSmrg        };
47056747b715Smrg        ClientPtr client = wClient(pWin);
470635c4bbdfSmrg        int rc;
470705b261ecSmrg
470835c4bbdfSmrg        rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess);
470935c4bbdfSmrg        if (rc == Success)
471035c4bbdfSmrg            memcpy((char *) &ke.map[0], (char *) &dev->key->down[1], 31);
471135c4bbdfSmrg
471235c4bbdfSmrg        DeliverEventsToWindow(dev, pWin, (xEvent *) &ke, 1,
471335c4bbdfSmrg                              KeymapStateMask, NullGrab);
471405b261ecSmrg    }
471505b261ecSmrg}
471605b261ecSmrg
471705b261ecSmrg/**
471805b261ecSmrg * Set the input focus to the given window. Subsequent keyboard events will be
471905b261ecSmrg * delivered to the given window.
47204642e01fSmrg *
472105b261ecSmrg * Usually called from ProcSetInputFocus as result of a client request. If so,
472205b261ecSmrg * the device is the inputInfo.keyboard.
472305b261ecSmrg * If called from ProcXSetInputFocus as result of a client xinput request, the
472405b261ecSmrg * device is set to the device specified by the client.
472505b261ecSmrg *
472605b261ecSmrg * @param client Client that requested input focus change.
47274642e01fSmrg * @param dev Focus device.
472805b261ecSmrg * @param focusID The window to obtain the focus. Can be PointerRoot or None.
472905b261ecSmrg * @param revertTo Specifies where the focus reverts to when window becomes
473005b261ecSmrg * unviewable.
473105b261ecSmrg * @param ctime Specifies the time.
473205b261ecSmrg * @param followOK True if pointer is allowed to follow the keyboard.
473305b261ecSmrg */
473405b261ecSmrgint
473535c4bbdfSmrgSetInputFocus(ClientPtr client,
473635c4bbdfSmrg              DeviceIntPtr dev,
473735c4bbdfSmrg              Window focusID, CARD8 revertTo, Time ctime, Bool followOK)
473805b261ecSmrg{
473905b261ecSmrg    FocusClassPtr focus;
474005b261ecSmrg    WindowPtr focusWin;
474105b261ecSmrg    int mode, rc;
474205b261ecSmrg    TimeStamp time;
474335c4bbdfSmrg    DeviceIntPtr keybd;         /* used for FollowKeyboard or FollowKeyboardWin */
474405b261ecSmrg
474505b261ecSmrg    UpdateCurrentTime();
474605b261ecSmrg    if ((revertTo != RevertToParent) &&
474735c4bbdfSmrg        (revertTo != RevertToPointerRoot) &&
474835c4bbdfSmrg        (revertTo != RevertToNone) &&
474935c4bbdfSmrg        ((revertTo != RevertToFollowKeyboard) || !followOK)) {
475035c4bbdfSmrg        client->errorValue = revertTo;
475135c4bbdfSmrg        return BadValue;
475205b261ecSmrg    }
475305b261ecSmrg    time = ClientTimeToServerTime(ctime);
47544642e01fSmrg
475535c4bbdfSmrg    keybd = GetMaster(dev, KEYBOARD_OR_FLOAT);
47564642e01fSmrg
475705b261ecSmrg    if ((focusID == None) || (focusID == PointerRoot))
475835c4bbdfSmrg        focusWin = (WindowPtr) (long) focusID;
475935c4bbdfSmrg    else if ((focusID == FollowKeyboard) && followOK) {
476035c4bbdfSmrg        focusWin = keybd->focus->win;
47614642e01fSmrg    }
476205b261ecSmrg    else {
476335c4bbdfSmrg        rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess);
476435c4bbdfSmrg        if (rc != Success)
476535c4bbdfSmrg            return rc;
476635c4bbdfSmrg        /* It is a match error to try to set the input focus to an
476735c4bbdfSmrg           unviewable window. */
476835c4bbdfSmrg        if (!focusWin->realized)
476935c4bbdfSmrg            return BadMatch;
477005b261ecSmrg    }
47714642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess);
47724642e01fSmrg    if (rc != Success)
477335c4bbdfSmrg        return Success;
47744642e01fSmrg
477505b261ecSmrg    focus = dev->focus;
477605b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
477735c4bbdfSmrg        (CompareTimeStamps(time, focus->time) == EARLIER))
477835c4bbdfSmrg        return Success;
47794642e01fSmrg    mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal;
478035c4bbdfSmrg    if (focus->win == FollowKeyboardWin) {
47816747b715Smrg        if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin))
47826747b715Smrg            DoFocusEvents(dev, keybd->focus->win, focusWin, mode);
478335c4bbdfSmrg    }
478435c4bbdfSmrg    else {
47856747b715Smrg        if (!ActivateFocusInGrab(dev, focus->win, focusWin))
47866747b715Smrg            DoFocusEvents(dev, focus->win, focusWin, mode);
47876747b715Smrg    }
478805b261ecSmrg    focus->time = time;
478905b261ecSmrg    focus->revert = revertTo;
479005b261ecSmrg    if (focusID == FollowKeyboard)
479135c4bbdfSmrg        focus->win = FollowKeyboardWin;
479205b261ecSmrg    else
479335c4bbdfSmrg        focus->win = focusWin;
479405b261ecSmrg    if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
479535c4bbdfSmrg        focus->traceGood = 0;
479635c4bbdfSmrg    else {
479705b261ecSmrg        int depth = 0;
479835c4bbdfSmrg        WindowPtr pWin;
479935c4bbdfSmrg
480035c4bbdfSmrg        for (pWin = focusWin; pWin; pWin = pWin->parent)
480135c4bbdfSmrg            depth++;
480235c4bbdfSmrg        if (depth > focus->traceSize) {
480335c4bbdfSmrg            focus->traceSize = depth + 1;
480435c4bbdfSmrg            focus->trace = reallocarray(focus->trace, focus->traceSize,
480535c4bbdfSmrg                                        sizeof(WindowPtr));
480635c4bbdfSmrg        }
480735c4bbdfSmrg        focus->traceGood = depth;
48084642e01fSmrg        for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
480935c4bbdfSmrg            focus->trace[depth] = pWin;
481005b261ecSmrg    }
481105b261ecSmrg    return Success;
481205b261ecSmrg}
481305b261ecSmrg
481405b261ecSmrg/**
481505b261ecSmrg * Server-side protocol handling for SetInputFocus request.
481605b261ecSmrg *
481705b261ecSmrg * Sets the input focus for the virtual core keyboard.
481805b261ecSmrg */
481905b261ecSmrgint
48206747b715SmrgProcSetInputFocus(ClientPtr client)
482105b261ecSmrg{
48224642e01fSmrg    DeviceIntPtr kbd = PickKeyboard(client);
482335c4bbdfSmrg
482405b261ecSmrg    REQUEST(xSetInputFocusReq);
482505b261ecSmrg
482605b261ecSmrg    REQUEST_SIZE_MATCH(xSetInputFocusReq);
482705b261ecSmrg
48284642e01fSmrg    return SetInputFocus(client, kbd, stuff->focus,
482935c4bbdfSmrg                         stuff->revertTo, stuff->time, FALSE);
483005b261ecSmrg}
483105b261ecSmrg
483205b261ecSmrg/**
483305b261ecSmrg * Server-side protocol handling for GetInputFocus request.
48344642e01fSmrg *
48354642e01fSmrg * Sends the current input focus for the client's keyboard back to the
483605b261ecSmrg * client.
483705b261ecSmrg */
483805b261ecSmrgint
483905b261ecSmrgProcGetInputFocus(ClientPtr client)
484005b261ecSmrg{
48414642e01fSmrg    DeviceIntPtr kbd = PickKeyboard(client);
484205b261ecSmrg    xGetInputFocusReply rep;
48434642e01fSmrg    FocusClassPtr focus = kbd->focus;
48444642e01fSmrg    int rc;
484535c4bbdfSmrg
484605b261ecSmrg    /* REQUEST(xReq); */
484705b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
48484642e01fSmrg
48494642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess);
48504642e01fSmrg    if (rc != Success)
485135c4bbdfSmrg        return rc;
485235c4bbdfSmrg
485335c4bbdfSmrg    rep = (xGetInputFocusReply) {
485435c4bbdfSmrg        .type = X_Reply,
485535c4bbdfSmrg        .length = 0,
485635c4bbdfSmrg        .sequenceNumber = client->sequence,
485735c4bbdfSmrg        .revertTo = focus->revert
485835c4bbdfSmrg    };
48594642e01fSmrg
486005b261ecSmrg    if (focus->win == NoneWin)
486135c4bbdfSmrg        rep.focus = None;
486205b261ecSmrg    else if (focus->win == PointerRootWin)
486335c4bbdfSmrg        rep.focus = PointerRoot;
486435c4bbdfSmrg    else
486535c4bbdfSmrg        rep.focus = focus->win->drawable.id;
486635c4bbdfSmrg
486705b261ecSmrg    WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
486805b261ecSmrg    return Success;
486905b261ecSmrg}
487005b261ecSmrg
487105b261ecSmrg/**
48724642e01fSmrg * Server-side protocol handling for GrabPointer request.
487305b261ecSmrg *
48744642e01fSmrg * Sets an active grab on the client's ClientPointer and returns success
48754642e01fSmrg * status to client.
487605b261ecSmrg */
487705b261ecSmrgint
487805b261ecSmrgProcGrabPointer(ClientPtr client)
487905b261ecSmrg{
488005b261ecSmrg    xGrabPointerReply rep;
48814642e01fSmrg    DeviceIntPtr device = PickPointer(client);
488205b261ecSmrg    GrabPtr grab;
48836747b715Smrg    GrabMask mask;
48846747b715Smrg    WindowPtr confineTo;
488535c4bbdfSmrg    BYTE status;
488635c4bbdfSmrg
488705b261ecSmrg    REQUEST(xGrabPointerReq);
488805b261ecSmrg    int rc;
488905b261ecSmrg
489005b261ecSmrg    REQUEST_SIZE_MATCH(xGrabPointerReq);
489105b261ecSmrg    UpdateCurrentTime();
48926747b715Smrg
489335c4bbdfSmrg    if (stuff->eventMask & ~PointerGrabMask) {
489435c4bbdfSmrg        client->errorValue = stuff->eventMask;
489505b261ecSmrg        return BadValue;
489605b261ecSmrg    }
48976747b715Smrg
489805b261ecSmrg    if (stuff->confineTo == None)
489935c4bbdfSmrg        confineTo = NullWindow;
490035c4bbdfSmrg    else {
490135c4bbdfSmrg        rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
490235c4bbdfSmrg                             DixSetAttrAccess);
490335c4bbdfSmrg        if (rc != Success)
490435c4bbdfSmrg            return rc;
490505b261ecSmrg    }
49066747b715Smrg
49076747b715Smrg    grab = device->deviceGrab.grab;
49086747b715Smrg
490935c4bbdfSmrg    if (grab && grab->confineTo && !confineTo)
491035c4bbdfSmrg        ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE, FALSE);
49116747b715Smrg
49126747b715Smrg    mask.core = stuff->eventMask;
49136747b715Smrg
49146747b715Smrg    rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode,
49156747b715Smrg                    stuff->grabWindow, stuff->ownerEvents, stuff->time,
491635c4bbdfSmrg                    &mask, CORE, stuff->cursor, stuff->confineTo, &status);
49174642e01fSmrg    if (rc != Success)
49186747b715Smrg        return rc;
49196747b715Smrg
492035c4bbdfSmrg    rep = (xGrabPointerReply) {
492135c4bbdfSmrg        .type = X_Reply,
492235c4bbdfSmrg        .status = status,
492335c4bbdfSmrg        .sequenceNumber = client->sequence,
492435c4bbdfSmrg        .length = 0
492535c4bbdfSmrg    };
492605b261ecSmrg    WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
492705b261ecSmrg    return Success;
492805b261ecSmrg}
492905b261ecSmrg
493005b261ecSmrg/**
493105b261ecSmrg * Server-side protocol handling for ChangeActivePointerGrab request.
493205b261ecSmrg *
493305b261ecSmrg * Changes properties of the grab hold by the client. If the client does not
49344642e01fSmrg * hold an active grab on the device, nothing happens.
493505b261ecSmrg */
493605b261ecSmrgint
493705b261ecSmrgProcChangeActivePointerGrab(ClientPtr client)
493805b261ecSmrg{
49394642e01fSmrg    DeviceIntPtr device;
494035c4bbdfSmrg    GrabPtr grab;
494105b261ecSmrg    CursorPtr newCursor, oldCursor;
494235c4bbdfSmrg
494305b261ecSmrg    REQUEST(xChangeActivePointerGrabReq);
494405b261ecSmrg    TimeStamp time;
494505b261ecSmrg
494605b261ecSmrg    REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
494735c4bbdfSmrg    if (stuff->eventMask & ~PointerGrabMask) {
494835c4bbdfSmrg        client->errorValue = stuff->eventMask;
494905b261ecSmrg        return BadValue;
495005b261ecSmrg    }
495105b261ecSmrg    if (stuff->cursor == None)
495235c4bbdfSmrg        newCursor = NullCursor;
495335c4bbdfSmrg    else {
495435c4bbdfSmrg        int rc = dixLookupResourceByType((void **) &newCursor, stuff->cursor,
495535c4bbdfSmrg                                         RT_CURSOR, client, DixUseAccess);
495635c4bbdfSmrg
495735c4bbdfSmrg        if (rc != Success) {
495835c4bbdfSmrg            client->errorValue = stuff->cursor;
495935c4bbdfSmrg            return rc;
496035c4bbdfSmrg        }
496105b261ecSmrg    }
49624642e01fSmrg
49634642e01fSmrg    device = PickPointer(client);
49644642e01fSmrg    grab = device->deviceGrab.grab;
49654642e01fSmrg
496605b261ecSmrg    if (!grab)
496735c4bbdfSmrg        return Success;
496805b261ecSmrg    if (!SameClient(grab, client))
496935c4bbdfSmrg        return Success;
49707e31ba66Smrg    UpdateCurrentTime();
497105b261ecSmrg    time = ClientTimeToServerTime(stuff->time);
497205b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
497335c4bbdfSmrg        (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
497435c4bbdfSmrg        return Success;
497505b261ecSmrg    oldCursor = grab->cursor;
497635c4bbdfSmrg    grab->cursor = RefCursor(newCursor);
49774642e01fSmrg    PostNewCursor(device);
497805b261ecSmrg    if (oldCursor)
497935c4bbdfSmrg        FreeCursor(oldCursor, (Cursor) 0);
498005b261ecSmrg    grab->eventMask = stuff->eventMask;
498105b261ecSmrg    return Success;
498205b261ecSmrg}
498305b261ecSmrg
498405b261ecSmrg/**
498505b261ecSmrg * Server-side protocol handling for UngrabPointer request.
498605b261ecSmrg *
49874642e01fSmrg * Deletes a pointer grab on a device the client has grabbed.
498805b261ecSmrg */
498905b261ecSmrgint
499005b261ecSmrgProcUngrabPointer(ClientPtr client)
499105b261ecSmrg{
49924642e01fSmrg    DeviceIntPtr device = PickPointer(client);
499305b261ecSmrg    GrabPtr grab;
499405b261ecSmrg    TimeStamp time;
499535c4bbdfSmrg
499605b261ecSmrg    REQUEST(xResourceReq);
499705b261ecSmrg
499805b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
499905b261ecSmrg    UpdateCurrentTime();
50004642e01fSmrg    grab = device->deviceGrab.grab;
50014642e01fSmrg
500205b261ecSmrg    time = ClientTimeToServerTime(stuff->id);
500305b261ecSmrg    if ((CompareTimeStamps(time, currentTime) != LATER) &&
500435c4bbdfSmrg        (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
500535c4bbdfSmrg        (grab) && SameClient(grab, client))
500635c4bbdfSmrg        (*device->deviceGrab.DeactivateGrab) (device);
500705b261ecSmrg    return Success;
500805b261ecSmrg}
500905b261ecSmrg
501005b261ecSmrg/**
501105b261ecSmrg * Sets a grab on the given device.
50124642e01fSmrg *
50134642e01fSmrg * Called from ProcGrabKeyboard to work on the client's keyboard.
501405b261ecSmrg * Called from ProcXGrabDevice to work on the device specified by the client.
50154642e01fSmrg *
501605b261ecSmrg * The parameters this_mode and other_mode represent the keyboard_mode and
50174642e01fSmrg * pointer_mode parameters of XGrabKeyboard().
501805b261ecSmrg * See man page for details on all the parameters
50194642e01fSmrg *
502005b261ecSmrg * @param client Client that owns the grab.
50214642e01fSmrg * @param dev The device to grab.
502205b261ecSmrg * @param this_mode GrabModeSync or GrabModeAsync
502305b261ecSmrg * @param other_mode GrabModeSync or GrabModeAsync
502405b261ecSmrg * @param status Return code to be returned to the caller.
50254642e01fSmrg *
502635c4bbdfSmrg * @returns Success or BadValue or BadAlloc.
502705b261ecSmrg */
502805b261ecSmrgint
50294642e01fSmrgGrabDevice(ClientPtr client, DeviceIntPtr dev,
50306747b715Smrg           unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow,
50316747b715Smrg           unsigned ownerEvents, Time ctime, GrabMask *mask,
50326747b715Smrg           int grabtype, Cursor curs, Window confineToWin, CARD8 *status)
503305b261ecSmrg{
50346747b715Smrg    WindowPtr pWin, confineTo;
503505b261ecSmrg    GrabPtr grab;
503605b261ecSmrg    TimeStamp time;
50374642e01fSmrg    Mask access_mode = DixGrabAccess;
503805b261ecSmrg    int rc;
50394642e01fSmrg    GrabInfoPtr grabInfo = &dev->deviceGrab;
50406747b715Smrg    CursorPtr cursor;
504105b261ecSmrg
504205b261ecSmrg    UpdateCurrentTime();
504335c4bbdfSmrg    if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync)) {
504435c4bbdfSmrg        client->errorValue = keyboard_mode;
504505b261ecSmrg        return BadValue;
504605b261ecSmrg    }
504735c4bbdfSmrg    if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync)) {
504835c4bbdfSmrg        client->errorValue = pointer_mode;
504905b261ecSmrg        return BadValue;
505005b261ecSmrg    }
505135c4bbdfSmrg    if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) {
505235c4bbdfSmrg        client->errorValue = ownerEvents;
505305b261ecSmrg        return BadValue;
505405b261ecSmrg    }
50554642e01fSmrg
50564642e01fSmrg    rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
505705b261ecSmrg    if (rc != Success)
505835c4bbdfSmrg        return rc;
50596747b715Smrg
50606747b715Smrg    if (confineToWin == None)
506135c4bbdfSmrg        confineTo = NullWindow;
506235c4bbdfSmrg    else {
506335c4bbdfSmrg        rc = dixLookupWindow(&confineTo, confineToWin, client,
506435c4bbdfSmrg                             DixSetAttrAccess);
506535c4bbdfSmrg        if (rc != Success)
506635c4bbdfSmrg            return rc;
50676747b715Smrg    }
50686747b715Smrg
50696747b715Smrg    if (curs == None)
507035c4bbdfSmrg        cursor = NullCursor;
507135c4bbdfSmrg    else {
507235c4bbdfSmrg        rc = dixLookupResourceByType((void **) &cursor, curs, RT_CURSOR,
507335c4bbdfSmrg                                     client, DixUseAccess);
507435c4bbdfSmrg        if (rc != Success) {
507535c4bbdfSmrg            client->errorValue = curs;
507635c4bbdfSmrg            return rc;
507735c4bbdfSmrg        }
507835c4bbdfSmrg        access_mode |= DixForceAccess;
50796747b715Smrg    }
50806747b715Smrg
50816747b715Smrg    if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync)
508235c4bbdfSmrg        access_mode |= DixFreezeAccess;
50834642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
50844642e01fSmrg    if (rc != Success)
508535c4bbdfSmrg        return rc;
50864642e01fSmrg
508705b261ecSmrg    time = ClientTimeToServerTime(ctime);
50884642e01fSmrg    grab = grabInfo->grab;
50896747b715Smrg    if (grab && grab->grabtype != grabtype)
50906747b715Smrg        *status = AlreadyGrabbed;
509135c4bbdfSmrg    else if (grab && !SameClient(grab, client))
509235c4bbdfSmrg        *status = AlreadyGrabbed;
50936747b715Smrg    else if ((!pWin->realized) ||
50946747b715Smrg             (confineTo &&
509535c4bbdfSmrg              !(confineTo->realized && BorderSizeNotEmpty(dev, confineTo))))
509635c4bbdfSmrg        *status = GrabNotViewable;
509705b261ecSmrg    else if ((CompareTimeStamps(time, currentTime) == LATER) ||
509835c4bbdfSmrg             (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER))
509935c4bbdfSmrg        *status = GrabInvalidTime;
51004642e01fSmrg    else if (grabInfo->sync.frozen &&
510135c4bbdfSmrg             grabInfo->sync.other && !SameClient(grabInfo->sync.other, client))
510235c4bbdfSmrg        *status = GrabFrozen;
510335c4bbdfSmrg    else {
510435c4bbdfSmrg        GrabPtr tempGrab;
510535c4bbdfSmrg
510635c4bbdfSmrg        tempGrab = AllocGrab(NULL);
510735c4bbdfSmrg        if (tempGrab == NULL)
510835c4bbdfSmrg            return BadAlloc;
510935c4bbdfSmrg
511035c4bbdfSmrg        tempGrab->next = NULL;
511135c4bbdfSmrg        tempGrab->window = pWin;
511235c4bbdfSmrg        tempGrab->resource = client->clientAsMask;
511335c4bbdfSmrg        tempGrab->ownerEvents = ownerEvents;
511435c4bbdfSmrg        tempGrab->keyboardMode = keyboard_mode;
511535c4bbdfSmrg        tempGrab->pointerMode = pointer_mode;
511635c4bbdfSmrg        if (grabtype == CORE)
511735c4bbdfSmrg            tempGrab->eventMask = mask->core;
511835c4bbdfSmrg        else if (grabtype == XI)
511935c4bbdfSmrg            tempGrab->eventMask = mask->xi;
512035c4bbdfSmrg        else
512135c4bbdfSmrg            xi2mask_merge(tempGrab->xi2mask, mask->xi2mask);
512235c4bbdfSmrg        tempGrab->device = dev;
512335c4bbdfSmrg        tempGrab->cursor = RefCursor(cursor);
512435c4bbdfSmrg        tempGrab->confineTo = confineTo;
512535c4bbdfSmrg        tempGrab->grabtype = grabtype;
512635c4bbdfSmrg        (*grabInfo->ActivateGrab) (dev, tempGrab, time, FALSE);
512735c4bbdfSmrg        *status = GrabSuccess;
512835c4bbdfSmrg
512935c4bbdfSmrg        FreeGrab(tempGrab);
513005b261ecSmrg    }
513105b261ecSmrg    return Success;
513205b261ecSmrg}
513305b261ecSmrg
513405b261ecSmrg/**
513505b261ecSmrg * Server-side protocol handling for GrabKeyboard request.
513605b261ecSmrg *
51374642e01fSmrg * Grabs the client's keyboard and returns success status to client.
513805b261ecSmrg */
513905b261ecSmrgint
514005b261ecSmrgProcGrabKeyboard(ClientPtr client)
514105b261ecSmrg{
514205b261ecSmrg    xGrabKeyboardReply rep;
514335c4bbdfSmrg    BYTE status;
514435c4bbdfSmrg
514505b261ecSmrg    REQUEST(xGrabKeyboardReq);
514605b261ecSmrg    int result;
51474642e01fSmrg    DeviceIntPtr keyboard = PickKeyboard(client);
51486747b715Smrg    GrabMask mask;
514905b261ecSmrg
515005b261ecSmrg    REQUEST_SIZE_MATCH(xGrabKeyboardReq);
51517e31ba66Smrg    UpdateCurrentTime();
515205b261ecSmrg
51536747b715Smrg    mask.core = KeyPressMask | KeyReleaseMask;
51546747b715Smrg
51556747b715Smrg    result = GrabDevice(client, keyboard, stuff->pointerMode,
515635c4bbdfSmrg                        stuff->keyboardMode, stuff->grabWindow,
515735c4bbdfSmrg                        stuff->ownerEvents, stuff->time, &mask, CORE, None,
515835c4bbdfSmrg                        None, &status);
515905b261ecSmrg
516005b261ecSmrg    if (result != Success)
516135c4bbdfSmrg        return result;
516235c4bbdfSmrg
516335c4bbdfSmrg    rep = (xGrabKeyboardReply) {
516435c4bbdfSmrg        .type = X_Reply,
516535c4bbdfSmrg        .status = status,
516635c4bbdfSmrg        .sequenceNumber = client->sequence,
516735c4bbdfSmrg        .length = 0
516835c4bbdfSmrg    };
516905b261ecSmrg    WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
517005b261ecSmrg    return Success;
517105b261ecSmrg}
517205b261ecSmrg
517305b261ecSmrg/**
517405b261ecSmrg * Server-side protocol handling for UngrabKeyboard request.
517505b261ecSmrg *
51764642e01fSmrg * Deletes a possible grab on the client's keyboard.
517705b261ecSmrg */
517805b261ecSmrgint
517905b261ecSmrgProcUngrabKeyboard(ClientPtr client)
518005b261ecSmrg{
51814642e01fSmrg    DeviceIntPtr device = PickKeyboard(client);
518205b261ecSmrg    GrabPtr grab;
518305b261ecSmrg    TimeStamp time;
518435c4bbdfSmrg
518505b261ecSmrg    REQUEST(xResourceReq);
518605b261ecSmrg
518705b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
518805b261ecSmrg    UpdateCurrentTime();
51894642e01fSmrg
51904642e01fSmrg    grab = device->deviceGrab.grab;
51914642e01fSmrg
519205b261ecSmrg    time = ClientTimeToServerTime(stuff->id);
519305b261ecSmrg    if ((CompareTimeStamps(time, currentTime) != LATER) &&
519435c4bbdfSmrg        (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
519535c4bbdfSmrg        (grab) && SameClient(grab, client) && grab->grabtype == CORE)
519635c4bbdfSmrg        (*device->deviceGrab.DeactivateGrab) (device);
519705b261ecSmrg    return Success;
519805b261ecSmrg}
519905b261ecSmrg
520005b261ecSmrg/**
520105b261ecSmrg * Server-side protocol handling for QueryPointer request.
520205b261ecSmrg *
52034642e01fSmrg * Returns the current state and position of the client's ClientPointer to the
52044642e01fSmrg * client.
520505b261ecSmrg */
520605b261ecSmrgint
520705b261ecSmrgProcQueryPointer(ClientPtr client)
520805b261ecSmrg{
520905b261ecSmrg    xQueryPointerReply rep;
521005b261ecSmrg    WindowPtr pWin, t;
52114642e01fSmrg    DeviceIntPtr mouse = PickPointer(client);
52126747b715Smrg    DeviceIntPtr keyboard;
52134642e01fSmrg    SpritePtr pSprite;
521405b261ecSmrg    int rc;
521535c4bbdfSmrg
52164642e01fSmrg    REQUEST(xResourceReq);
521705b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
52184642e01fSmrg
52194642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
52204642e01fSmrg    if (rc != Success)
522135c4bbdfSmrg        return rc;
52224642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
52236747b715Smrg    if (rc != Success && rc != BadAccess)
522435c4bbdfSmrg        return rc;
52254642e01fSmrg
522635c4bbdfSmrg    keyboard = GetMaster(mouse, MASTER_KEYBOARD);
52276747b715Smrg
52284642e01fSmrg    pSprite = mouse->spriteInfo->sprite;
522905b261ecSmrg    if (mouse->valuator->motionHintWindow)
523035c4bbdfSmrg        MaybeStopHint(mouse, client);
523135c4bbdfSmrg    rep = (xQueryPointerReply) {
523235c4bbdfSmrg        .type = X_Reply,
523335c4bbdfSmrg        .sequenceNumber = client->sequence,
523435c4bbdfSmrg        .length = 0,
523535c4bbdfSmrg        .mask = event_get_corestate(mouse, keyboard),
523635c4bbdfSmrg        .root = (GetCurrentRootWindow(mouse))->drawable.id,
523735c4bbdfSmrg        .rootX = pSprite->hot.x,
523835c4bbdfSmrg        .rootY = pSprite->hot.y,
523935c4bbdfSmrg        .child = None
524035c4bbdfSmrg    };
524135c4bbdfSmrg    if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
524235c4bbdfSmrg        rep.sameScreen = xTrue;
524335c4bbdfSmrg        rep.winX = pSprite->hot.x - pWin->drawable.x;
524435c4bbdfSmrg        rep.winY = pSprite->hot.y - pWin->drawable.y;
524535c4bbdfSmrg        for (t = pSprite->win; t; t = t->parent)
524635c4bbdfSmrg            if (t->parent == pWin) {
524735c4bbdfSmrg                rep.child = t->drawable.id;
524835c4bbdfSmrg                break;
524935c4bbdfSmrg            }
525005b261ecSmrg    }
525135c4bbdfSmrg    else {
525235c4bbdfSmrg        rep.sameScreen = xFalse;
525335c4bbdfSmrg        rep.winX = 0;
525435c4bbdfSmrg        rep.winY = 0;
525505b261ecSmrg    }
525605b261ecSmrg
525705b261ecSmrg#ifdef PANORAMIX
525835c4bbdfSmrg    if (!noPanoramiXExtension) {
525935c4bbdfSmrg        rep.rootX += screenInfo.screens[0]->x;
526035c4bbdfSmrg        rep.rootY += screenInfo.screens[0]->y;
526135c4bbdfSmrg        if (stuff->id == rep.root) {
526235c4bbdfSmrg            rep.winX += screenInfo.screens[0]->x;
526335c4bbdfSmrg            rep.winY += screenInfo.screens[0]->y;
526435c4bbdfSmrg        }
526505b261ecSmrg    }
526605b261ecSmrg#endif
526705b261ecSmrg
52686747b715Smrg    if (rc == BadAccess) {
526935c4bbdfSmrg        rep.mask = 0;
527035c4bbdfSmrg        rep.child = None;
527135c4bbdfSmrg        rep.rootX = 0;
527235c4bbdfSmrg        rep.rootY = 0;
527335c4bbdfSmrg        rep.winX = 0;
527435c4bbdfSmrg        rep.winY = 0;
52756747b715Smrg    }
52766747b715Smrg
527705b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
527805b261ecSmrg
52796747b715Smrg    return Success;
528005b261ecSmrg}
528105b261ecSmrg
528205b261ecSmrg/**
528305b261ecSmrg * Initializes the device list and the DIX sprite to sane values. Allocates
528405b261ecSmrg * trace memory used for quick window traversal.
528505b261ecSmrg */
528605b261ecSmrgvoid
528705b261ecSmrgInitEvents(void)
528805b261ecSmrg{
528905b261ecSmrg    int i;
529035c4bbdfSmrg    QdEventPtr qe, tmp;
529105b261ecSmrg
529205b261ecSmrg    inputInfo.numDevices = 0;
529335c4bbdfSmrg    inputInfo.devices = (DeviceIntPtr) NULL;
529435c4bbdfSmrg    inputInfo.off_devices = (DeviceIntPtr) NULL;
529535c4bbdfSmrg    inputInfo.keyboard = (DeviceIntPtr) NULL;
529635c4bbdfSmrg    inputInfo.pointer = (DeviceIntPtr) NULL;
529735c4bbdfSmrg
529835c4bbdfSmrg    for (i = 0; i < MAXDEVICES; i++) {
529935c4bbdfSmrg        DeviceIntRec dummy;
530035c4bbdfSmrg        memcpy(&event_filters[i], default_filter, sizeof(default_filter));
530135c4bbdfSmrg
530235c4bbdfSmrg        dummy.id = i;
530335c4bbdfSmrg        NoticeTime(&dummy, currentTime);
530435c4bbdfSmrg        LastEventTimeToggleResetFlag(i, FALSE);
530505b261ecSmrg    }
53064642e01fSmrg
530735c4bbdfSmrg    syncEvents.replayDev = (DeviceIntPtr) NULL;
530805b261ecSmrg    syncEvents.replayWin = NullWindow;
530935c4bbdfSmrg    if (syncEvents.pending.next)
531035c4bbdfSmrg        xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next)
531135c4bbdfSmrg            free(qe);
531235c4bbdfSmrg    xorg_list_init(&syncEvents.pending);
531305b261ecSmrg    syncEvents.playingEvents = FALSE;
531405b261ecSmrg    syncEvents.time.months = 0;
531535c4bbdfSmrg    syncEvents.time.milliseconds = 0;   /* hardly matters */
531605b261ecSmrg    currentTime.months = 0;
531705b261ecSmrg    currentTime.milliseconds = GetTimeInMillis();
531835c4bbdfSmrg    for (i = 0; i < DNPMCOUNT; i++) {
531935c4bbdfSmrg        DontPropagateMasks[i] = 0;
532035c4bbdfSmrg        DontPropagateRefCnts[i] = 0;
532105b261ecSmrg    }
53224642e01fSmrg
532335c4bbdfSmrg    InputEventList = InitEventList(GetMaximumEventsNum());
53244642e01fSmrg    if (!InputEventList)
53254642e01fSmrg        FatalError("[dix] Failed to allocate input event list.\n");
532605b261ecSmrg}
532705b261ecSmrg
532805b261ecSmrgvoid
532905b261ecSmrgCloseDownEvents(void)
533005b261ecSmrg{
533135c4bbdfSmrg    FreeEventList(InputEventList, GetMaximumEventsNum());
53326747b715Smrg    InputEventList = NULL;
533305b261ecSmrg}
533405b261ecSmrg
5335475c125cSmrg#define SEND_EVENT_BIT 0x80
5336475c125cSmrg
533705b261ecSmrg/**
533805b261ecSmrg * Server-side protocol handling for SendEvent request.
533905b261ecSmrg *
53404642e01fSmrg * Locates the window to send the event to and forwards the event.
534105b261ecSmrg */
534205b261ecSmrgint
534305b261ecSmrgProcSendEvent(ClientPtr client)
534405b261ecSmrg{
534505b261ecSmrg    WindowPtr pWin;
534635c4bbdfSmrg    WindowPtr effectiveFocus = NullWindow;      /* only set if dest==InputFocus */
53476747b715Smrg    DeviceIntPtr dev = PickPointer(client);
534835c4bbdfSmrg    DeviceIntPtr keybd = GetMaster(dev, MASTER_KEYBOARD);
53496747b715Smrg    SpritePtr pSprite = dev->spriteInfo->sprite;
535035c4bbdfSmrg
535105b261ecSmrg    REQUEST(xSendEventReq);
535205b261ecSmrg
535305b261ecSmrg    REQUEST_SIZE_MATCH(xSendEventReq);
535405b261ecSmrg
5355475c125cSmrg    /* libXext and other extension libraries may set the bit indicating
5356475c125cSmrg     * that this event came from a SendEvent request so remove it
5357475c125cSmrg     * since otherwise the event type may fail the range checks
5358475c125cSmrg     * and cause an invalid BadValue error to be returned.
5359475c125cSmrg     *
5360475c125cSmrg     * This is safe to do since we later add the SendEvent bit (0x80)
5361475c125cSmrg     * back in once we send the event to the client */
5362475c125cSmrg
5363475c125cSmrg    stuff->event.u.u.type &= ~(SEND_EVENT_BIT);
5364475c125cSmrg
536505b261ecSmrg    /* The client's event type must be a core event type or one defined by an
536635c4bbdfSmrg       extension. */
536705b261ecSmrg
536835c4bbdfSmrg    if (!((stuff->event.u.u.type > X_Reply &&
536935c4bbdfSmrg           stuff->event.u.u.type < LASTEvent) ||
537035c4bbdfSmrg          (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
537135c4bbdfSmrg           stuff->event.u.u.type < (unsigned) lastEvent))) {
537235c4bbdfSmrg        client->errorValue = stuff->event.u.u.type;
537335c4bbdfSmrg        return BadValue;
537405b261ecSmrg    }
53750679523aSmrg    /* Generic events can have variable size, but SendEvent request holds
53760679523aSmrg       exactly 32B of event data. */
53770679523aSmrg    if (stuff->event.u.u.type == GenericEvent) {
53780679523aSmrg        client->errorValue = stuff->event.u.u.type;
53790679523aSmrg        return BadValue;
53800679523aSmrg    }
538105b261ecSmrg    if (stuff->event.u.u.type == ClientMessage &&
538235c4bbdfSmrg        stuff->event.u.u.detail != 8 &&
538335c4bbdfSmrg        stuff->event.u.u.detail != 16 && stuff->event.u.u.detail != 32) {
538435c4bbdfSmrg        client->errorValue = stuff->event.u.u.detail;
538535c4bbdfSmrg        return BadValue;
538605b261ecSmrg    }
538735c4bbdfSmrg    if (stuff->eventMask & ~AllEventMasks) {
538835c4bbdfSmrg        client->errorValue = stuff->eventMask;
538935c4bbdfSmrg        return BadValue;
539005b261ecSmrg    }
539105b261ecSmrg
539205b261ecSmrg    if (stuff->destination == PointerWindow)
539335c4bbdfSmrg        pWin = pSprite->win;
539435c4bbdfSmrg    else if (stuff->destination == InputFocus) {
539535c4bbdfSmrg        WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin;
539605b261ecSmrg
539735c4bbdfSmrg        if (inputFocus == NoneWin)
539835c4bbdfSmrg            return Success;
539905b261ecSmrg
540035c4bbdfSmrg        /* If the input focus is PointerRootWin, send the event to where
540135c4bbdfSmrg           the pointer is if possible, then perhaps propogate up to root. */
540235c4bbdfSmrg        if (inputFocus == PointerRootWin)
540335c4bbdfSmrg            inputFocus = GetCurrentRootWindow(dev);
540405b261ecSmrg
540535c4bbdfSmrg        if (IsParent(inputFocus, pSprite->win)) {
540635c4bbdfSmrg            effectiveFocus = inputFocus;
540735c4bbdfSmrg            pWin = pSprite->win;
540835c4bbdfSmrg        }
540935c4bbdfSmrg        else
541035c4bbdfSmrg            effectiveFocus = pWin = inputFocus;
541105b261ecSmrg    }
541205b261ecSmrg    else
541335c4bbdfSmrg        dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess);
541405b261ecSmrg
541505b261ecSmrg    if (!pWin)
541635c4bbdfSmrg        return BadWindow;
541735c4bbdfSmrg    if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) {
541835c4bbdfSmrg        client->errorValue = stuff->propagate;
541935c4bbdfSmrg        return BadValue;
542005b261ecSmrg    }
5421475c125cSmrg    stuff->event.u.u.type |= SEND_EVENT_BIT;
542235c4bbdfSmrg    if (stuff->propagate) {
542335c4bbdfSmrg        for (; pWin; pWin = pWin->parent) {
542435c4bbdfSmrg            if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin,
542535c4bbdfSmrg                         &stuff->event, 1))
542635c4bbdfSmrg                return Success;
54276747b715Smrg            if (DeliverEventsToWindow(dev, pWin,
542835c4bbdfSmrg                                      &stuff->event, 1, stuff->eventMask,
542935c4bbdfSmrg                                      NullGrab))
543035c4bbdfSmrg                return Success;
543135c4bbdfSmrg            if (pWin == effectiveFocus)
543235c4bbdfSmrg                return Success;
543335c4bbdfSmrg            stuff->eventMask &= ~wDontPropagateMask(pWin);
543435c4bbdfSmrg            if (!stuff->eventMask)
543535c4bbdfSmrg                break;
543635c4bbdfSmrg        }
543705b261ecSmrg    }
54384642e01fSmrg    else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1))
54396747b715Smrg        DeliverEventsToWindow(dev, pWin, &stuff->event,
544035c4bbdfSmrg                              1, stuff->eventMask, NullGrab);
544105b261ecSmrg    return Success;
544205b261ecSmrg}
544305b261ecSmrg
544405b261ecSmrg/**
544505b261ecSmrg * Server-side protocol handling for UngrabKey request.
544605b261ecSmrg *
54474642e01fSmrg * Deletes a passive grab for the given key. Works on the
54484642e01fSmrg * client's keyboard.
544905b261ecSmrg */
545005b261ecSmrgint
545105b261ecSmrgProcUngrabKey(ClientPtr client)
545205b261ecSmrg{
545305b261ecSmrg    REQUEST(xUngrabKeyReq);
545405b261ecSmrg    WindowPtr pWin;
545535c4bbdfSmrg    GrabPtr tempGrab;
54564642e01fSmrg    DeviceIntPtr keybd = PickKeyboard(client);
545705b261ecSmrg    int rc;
545805b261ecSmrg
545905b261ecSmrg    REQUEST_SIZE_MATCH(xUngrabKeyReq);
54606747b715Smrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess);
546105b261ecSmrg    if (rc != Success)
546235c4bbdfSmrg        return rc;
546305b261ecSmrg
54646747b715Smrg    if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
546535c4bbdfSmrg         (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
546635c4bbdfSmrg        && (stuff->key != AnyKey)) {
546735c4bbdfSmrg        client->errorValue = stuff->key;
546805b261ecSmrg        return BadValue;
546905b261ecSmrg    }
547005b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
547135c4bbdfSmrg        (stuff->modifiers & ~AllModifiersMask)) {
547235c4bbdfSmrg        client->errorValue = stuff->modifiers;
547335c4bbdfSmrg        return BadValue;
547435c4bbdfSmrg    }
547535c4bbdfSmrg    tempGrab = AllocGrab(NULL);
547635c4bbdfSmrg    if (!tempGrab)
547735c4bbdfSmrg        return BadAlloc;
547835c4bbdfSmrg    tempGrab->resource = client->clientAsMask;
547935c4bbdfSmrg    tempGrab->device = keybd;
548035c4bbdfSmrg    tempGrab->window = pWin;
548135c4bbdfSmrg    tempGrab->modifiersDetail.exact = stuff->modifiers;
548235c4bbdfSmrg    tempGrab->modifiersDetail.pMask = NULL;
548335c4bbdfSmrg    tempGrab->modifierDevice = keybd;
548435c4bbdfSmrg    tempGrab->type = KeyPress;
548535c4bbdfSmrg    tempGrab->grabtype = CORE;
548635c4bbdfSmrg    tempGrab->detail.exact = stuff->key;
548735c4bbdfSmrg    tempGrab->detail.pMask = NULL;
548835c4bbdfSmrg    tempGrab->next = NULL;
548935c4bbdfSmrg
549035c4bbdfSmrg    if (!DeletePassiveGrabFromList(tempGrab))
549135c4bbdfSmrg        rc = BadAlloc;
549235c4bbdfSmrg
549335c4bbdfSmrg    FreeGrab(tempGrab);
549435c4bbdfSmrg
549535c4bbdfSmrg    return rc;
549605b261ecSmrg}
549705b261ecSmrg
549805b261ecSmrg/**
549905b261ecSmrg * Server-side protocol handling for GrabKey request.
550005b261ecSmrg *
55014642e01fSmrg * Creates a grab for the client's keyboard and adds it to the list of passive
55024642e01fSmrg * grabs.
550305b261ecSmrg */
550405b261ecSmrgint
550505b261ecSmrgProcGrabKey(ClientPtr client)
550605b261ecSmrg{
550705b261ecSmrg    WindowPtr pWin;
550835c4bbdfSmrg
550905b261ecSmrg    REQUEST(xGrabKeyReq);
551005b261ecSmrg    GrabPtr grab;
55114642e01fSmrg    DeviceIntPtr keybd = PickKeyboard(client);
551205b261ecSmrg    int rc;
55136747b715Smrg    GrabParameters param;
55146747b715Smrg    GrabMask mask;
551505b261ecSmrg
551605b261ecSmrg    REQUEST_SIZE_MATCH(xGrabKeyReq);
55176747b715Smrg
551835c4bbdfSmrg    param = (GrabParameters) {
551935c4bbdfSmrg        .grabtype = CORE,
552035c4bbdfSmrg        .ownerEvents = stuff->ownerEvents,
552135c4bbdfSmrg        .this_device_mode = stuff->keyboardMode,
552235c4bbdfSmrg        .other_devices_mode = stuff->pointerMode,
552335c4bbdfSmrg        .modifiers = stuff->modifiers
552435c4bbdfSmrg    };
55256747b715Smrg
55266747b715Smrg    rc = CheckGrabValues(client, &param);
55276747b715Smrg    if (rc != Success)
55286747b715Smrg        return rc;
55296747b715Smrg
55306747b715Smrg    if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
553135c4bbdfSmrg         (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
553235c4bbdfSmrg        && (stuff->key != AnyKey)) {
553335c4bbdfSmrg        client->errorValue = stuff->key;
553405b261ecSmrg        return BadValue;
553505b261ecSmrg    }
55364642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
553705b261ecSmrg    if (rc != Success)
553835c4bbdfSmrg        return rc;
55396747b715Smrg
55406747b715Smrg    mask.core = (KeyPressMask | KeyReleaseMask);
55416747b715Smrg
554235c4bbdfSmrg    grab = CreateGrab(client->index, keybd, keybd, pWin, CORE, &mask,
55436747b715Smrg                      &param, KeyPress, stuff->key, NullWindow, NullCursor);
554405b261ecSmrg    if (!grab)
554535c4bbdfSmrg        return BadAlloc;
55464642e01fSmrg    return AddPassiveGrabToList(client, grab);
554705b261ecSmrg}
554805b261ecSmrg
554905b261ecSmrg/**
555005b261ecSmrg * Server-side protocol handling for GrabButton request.
555105b261ecSmrg *
55524642e01fSmrg * Creates a grab for the client's ClientPointer and adds it as a passive grab
55534642e01fSmrg * to the list.
555405b261ecSmrg */
555505b261ecSmrgint
555605b261ecSmrgProcGrabButton(ClientPtr client)
555705b261ecSmrg{
555805b261ecSmrg    WindowPtr pWin, confineTo;
555935c4bbdfSmrg
556005b261ecSmrg    REQUEST(xGrabButtonReq);
556105b261ecSmrg    CursorPtr cursor;
556205b261ecSmrg    GrabPtr grab;
55634642e01fSmrg    DeviceIntPtr ptr, modifierDevice;
55644642e01fSmrg    Mask access_mode = DixGrabAccess;
55656747b715Smrg    GrabMask mask;
55666747b715Smrg    GrabParameters param;
556705b261ecSmrg    int rc;
556805b261ecSmrg
556905b261ecSmrg    REQUEST_SIZE_MATCH(xGrabButtonReq);
55707e31ba66Smrg    UpdateCurrentTime();
557105b261ecSmrg    if ((stuff->pointerMode != GrabModeSync) &&
557235c4bbdfSmrg        (stuff->pointerMode != GrabModeAsync)) {
557335c4bbdfSmrg        client->errorValue = stuff->pointerMode;
557405b261ecSmrg        return BadValue;
557505b261ecSmrg    }
557605b261ecSmrg    if ((stuff->keyboardMode != GrabModeSync) &&
557735c4bbdfSmrg        (stuff->keyboardMode != GrabModeAsync)) {
557835c4bbdfSmrg        client->errorValue = stuff->keyboardMode;
557905b261ecSmrg        return BadValue;
558005b261ecSmrg    }
558105b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
558235c4bbdfSmrg        (stuff->modifiers & ~AllModifiersMask)) {
558335c4bbdfSmrg        client->errorValue = stuff->modifiers;
558435c4bbdfSmrg        return BadValue;
558505b261ecSmrg    }
558635c4bbdfSmrg    if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) {
558735c4bbdfSmrg        client->errorValue = stuff->ownerEvents;
558835c4bbdfSmrg        return BadValue;
558905b261ecSmrg    }
559035c4bbdfSmrg    if (stuff->eventMask & ~PointerGrabMask) {
559135c4bbdfSmrg        client->errorValue = stuff->eventMask;
559205b261ecSmrg        return BadValue;
559305b261ecSmrg    }
55944642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
559505b261ecSmrg    if (rc != Success)
559635c4bbdfSmrg        return rc;
559705b261ecSmrg    if (stuff->confineTo == None)
559835c4bbdfSmrg        confineTo = NullWindow;
559905b261ecSmrg    else {
560035c4bbdfSmrg        rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
560135c4bbdfSmrg                             DixSetAttrAccess);
560235c4bbdfSmrg        if (rc != Success)
560335c4bbdfSmrg            return rc;
560405b261ecSmrg    }
560505b261ecSmrg    if (stuff->cursor == None)
560635c4bbdfSmrg        cursor = NullCursor;
560735c4bbdfSmrg    else {
560835c4bbdfSmrg        rc = dixLookupResourceByType((void **) &cursor, stuff->cursor,
560935c4bbdfSmrg                                     RT_CURSOR, client, DixUseAccess);
561035c4bbdfSmrg        if (rc != Success) {
561135c4bbdfSmrg            client->errorValue = stuff->cursor;
561235c4bbdfSmrg            return rc;
561335c4bbdfSmrg        }
561435c4bbdfSmrg        access_mode |= DixForceAccess;
561505b261ecSmrg    }
561605b261ecSmrg
56174642e01fSmrg    ptr = PickPointer(client);
561835c4bbdfSmrg    modifierDevice = GetMaster(ptr, MASTER_KEYBOARD);
56194642e01fSmrg    if (stuff->pointerMode == GrabModeSync ||
562035c4bbdfSmrg        stuff->keyboardMode == GrabModeSync)
562135c4bbdfSmrg        access_mode |= DixFreezeAccess;
56224642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode);
56234642e01fSmrg    if (rc != Success)
562435c4bbdfSmrg        return rc;
562505b261ecSmrg
562635c4bbdfSmrg    param = (GrabParameters) {
562735c4bbdfSmrg        .grabtype = CORE,
562835c4bbdfSmrg        .ownerEvents = stuff->ownerEvents,
562935c4bbdfSmrg        .this_device_mode = stuff->keyboardMode,
563035c4bbdfSmrg        .other_devices_mode = stuff->pointerMode,
563135c4bbdfSmrg        .modifiers = stuff->modifiers
563235c4bbdfSmrg    };
56336747b715Smrg
56346747b715Smrg    mask.core = stuff->eventMask;
56356747b715Smrg
56366747b715Smrg    grab = CreateGrab(client->index, ptr, modifierDevice, pWin,
563735c4bbdfSmrg                      CORE, &mask, &param, ButtonPress,
56386747b715Smrg                      stuff->button, confineTo, cursor);
563905b261ecSmrg    if (!grab)
564035c4bbdfSmrg        return BadAlloc;
56414642e01fSmrg    return AddPassiveGrabToList(client, grab);
564205b261ecSmrg}
564305b261ecSmrg
564405b261ecSmrg/**
564505b261ecSmrg * Server-side protocol handling for UngrabButton request.
564605b261ecSmrg *
56474642e01fSmrg * Deletes a passive grab on the client's ClientPointer from the list.
564805b261ecSmrg */
564905b261ecSmrgint
565005b261ecSmrgProcUngrabButton(ClientPtr client)
565105b261ecSmrg{
565205b261ecSmrg    REQUEST(xUngrabButtonReq);
565305b261ecSmrg    WindowPtr pWin;
565435c4bbdfSmrg    GrabPtr tempGrab;
565505b261ecSmrg    int rc;
56566747b715Smrg    DeviceIntPtr ptr;
565705b261ecSmrg
565805b261ecSmrg    REQUEST_SIZE_MATCH(xUngrabButtonReq);
56597e31ba66Smrg    UpdateCurrentTime();
566005b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
566135c4bbdfSmrg        (stuff->modifiers & ~AllModifiersMask)) {
566235c4bbdfSmrg        client->errorValue = stuff->modifiers;
566335c4bbdfSmrg        return BadValue;
566405b261ecSmrg    }
566505b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
566605b261ecSmrg    if (rc != Success)
566735c4bbdfSmrg        return rc;
56686747b715Smrg
56696747b715Smrg    ptr = PickPointer(client);
56706747b715Smrg
567135c4bbdfSmrg    tempGrab = AllocGrab(NULL);
567235c4bbdfSmrg    if (!tempGrab)
567335c4bbdfSmrg        return BadAlloc;
567435c4bbdfSmrg    tempGrab->resource = client->clientAsMask;
567535c4bbdfSmrg    tempGrab->device = ptr;
567635c4bbdfSmrg    tempGrab->window = pWin;
567735c4bbdfSmrg    tempGrab->modifiersDetail.exact = stuff->modifiers;
567835c4bbdfSmrg    tempGrab->modifiersDetail.pMask = NULL;
567935c4bbdfSmrg    tempGrab->modifierDevice = GetMaster(ptr, MASTER_KEYBOARD);
568035c4bbdfSmrg    tempGrab->type = ButtonPress;
568135c4bbdfSmrg    tempGrab->detail.exact = stuff->button;
568235c4bbdfSmrg    tempGrab->grabtype = CORE;
568335c4bbdfSmrg    tempGrab->detail.pMask = NULL;
568435c4bbdfSmrg    tempGrab->next = NULL;
568535c4bbdfSmrg
568635c4bbdfSmrg    if (!DeletePassiveGrabFromList(tempGrab))
568735c4bbdfSmrg        rc = BadAlloc;
568835c4bbdfSmrg
568935c4bbdfSmrg    FreeGrab(tempGrab);
569035c4bbdfSmrg    return rc;
569105b261ecSmrg}
569205b261ecSmrg
569305b261ecSmrg/**
569405b261ecSmrg * Deactivate any grab that may be on the window, remove the focus.
569505b261ecSmrg * Delete any XInput extension events from the window too. Does not change the
569605b261ecSmrg * window mask. Use just before the window is deleted.
569705b261ecSmrg *
569805b261ecSmrg * If freeResources is set, passive grabs on the window are deleted.
569905b261ecSmrg *
570005b261ecSmrg * @param pWin The window to delete events from.
570105b261ecSmrg * @param freeResources True if resources associated with the window should be
570205b261ecSmrg * deleted.
570305b261ecSmrg */
570405b261ecSmrgvoid
570505b261ecSmrgDeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
570605b261ecSmrg{
570735c4bbdfSmrg    WindowPtr parent;
570835c4bbdfSmrg    DeviceIntPtr mouse = inputInfo.pointer;
570935c4bbdfSmrg    DeviceIntPtr keybd = inputInfo.keyboard;
571035c4bbdfSmrg    FocusClassPtr focus;
571135c4bbdfSmrg    OtherClientsPtr oc;
571235c4bbdfSmrg    GrabPtr passive;
571335c4bbdfSmrg    GrabPtr grab;
571405b261ecSmrg
571505b261ecSmrg    /* Deactivate any grabs performed on this window, before making any
571635c4bbdfSmrg       input focus changes. */
57174642e01fSmrg    grab = mouse->deviceGrab.grab;
571835c4bbdfSmrg    if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
571935c4bbdfSmrg        (*mouse->deviceGrab.DeactivateGrab) (mouse);
572005b261ecSmrg
572105b261ecSmrg    /* Deactivating a keyboard grab should cause focus events. */
57224642e01fSmrg    grab = keybd->deviceGrab.grab;
57234642e01fSmrg    if (grab && (grab->window == pWin))
572435c4bbdfSmrg        (*keybd->deviceGrab.DeactivateGrab) (keybd);
572505b261ecSmrg
57264642e01fSmrg    /* And now the real devices */
572735c4bbdfSmrg    for (mouse = inputInfo.devices; mouse; mouse = mouse->next) {
57284642e01fSmrg        grab = mouse->deviceGrab.grab;
57294642e01fSmrg        if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
573035c4bbdfSmrg            (*mouse->deviceGrab.DeactivateGrab) (mouse);
57314642e01fSmrg    }
573205b261ecSmrg
573335c4bbdfSmrg    for (keybd = inputInfo.devices; keybd; keybd = keybd->next) {
573435c4bbdfSmrg        if (IsKeyboardDevice(keybd)) {
57354642e01fSmrg            focus = keybd->focus;
57364642e01fSmrg
573735c4bbdfSmrg            /* If the focus window is a root window (ie. has no parent)
573835c4bbdfSmrg               then don't delete the focus from it. */
57394642e01fSmrg
574035c4bbdfSmrg            if ((pWin == focus->win) && (pWin->parent != NullWindow)) {
57414642e01fSmrg                int focusEventMode = NotifyNormal;
57424642e01fSmrg
57434642e01fSmrg                /* If a grab is in progress, then alter the mode of focus events. */
57444642e01fSmrg
57454642e01fSmrg                if (keybd->deviceGrab.grab)
57464642e01fSmrg                    focusEventMode = NotifyWhileGrabbed;
57474642e01fSmrg
574835c4bbdfSmrg                switch (focus->revert) {
574935c4bbdfSmrg                case RevertToNone:
575035c4bbdfSmrg                    DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
575135c4bbdfSmrg                    focus->win = NoneWin;
575235c4bbdfSmrg                    focus->traceGood = 0;
575335c4bbdfSmrg                    break;
575435c4bbdfSmrg                case RevertToParent:
575535c4bbdfSmrg                    parent = pWin;
575635c4bbdfSmrg                    do {
575735c4bbdfSmrg                        parent = parent->parent;
575835c4bbdfSmrg                        focus->traceGood--;
575935c4bbdfSmrg                    } while (!parent->realized
576035c4bbdfSmrg                    /* This would be a good protocol change -- windows being
576135c4bbdfSmrg                       reparented during SaveSet processing would cause the
576235c4bbdfSmrg                       focus to revert to the nearest enclosing window which
576335c4bbdfSmrg                       will survive the death of the exiting client, instead
576435c4bbdfSmrg                       of ending up reverting to a dying window and thence
576535c4bbdfSmrg                       to None */
576605b261ecSmrg#ifdef NOTDEF
576735c4bbdfSmrg                             || wClient(parent)->clientGone
576805b261ecSmrg#endif
576935c4bbdfSmrg                        );
577035c4bbdfSmrg                    if (!ActivateFocusInGrab(keybd, pWin, parent))
577135c4bbdfSmrg                        DoFocusEvents(keybd, pWin, parent, focusEventMode);
577235c4bbdfSmrg                    focus->win = parent;
577335c4bbdfSmrg                    focus->revert = RevertToNone;
577435c4bbdfSmrg                    break;
577535c4bbdfSmrg                case RevertToPointerRoot:
577635c4bbdfSmrg                    if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin))
577735c4bbdfSmrg                        DoFocusEvents(keybd, pWin, PointerRootWin,
577835c4bbdfSmrg                                      focusEventMode);
577935c4bbdfSmrg                    focus->win = PointerRootWin;
578035c4bbdfSmrg                    focus->traceGood = 0;
578135c4bbdfSmrg                    break;
57824642e01fSmrg                }
57834642e01fSmrg            }
57844642e01fSmrg        }
578505b261ecSmrg
578635c4bbdfSmrg        if (IsPointerDevice(keybd)) {
57874642e01fSmrg            if (keybd->valuator->motionHintWindow == pWin)
57884642e01fSmrg                keybd->valuator->motionHintWindow = NullWindow;
57894642e01fSmrg        }
57904642e01fSmrg    }
579105b261ecSmrg
579235c4bbdfSmrg    if (freeResources) {
579335c4bbdfSmrg        if (pWin->dontPropagate)
579435c4bbdfSmrg            DontPropagateRefCnts[pWin->dontPropagate]--;
579535c4bbdfSmrg        while ((oc = wOtherClients(pWin)))
579635c4bbdfSmrg            FreeResource(oc->resource, RT_NONE);
579735c4bbdfSmrg        while ((passive = wPassiveGrabs(pWin)))
579835c4bbdfSmrg            FreeResource(passive->resource, RT_NONE);
579935c4bbdfSmrg    }
58004642e01fSmrg
580105b261ecSmrg    DeleteWindowFromAnyExtEvents(pWin, freeResources);
580205b261ecSmrg}
580305b261ecSmrg
580405b261ecSmrg/**
580505b261ecSmrg * Call this whenever some window at or below pWin has changed geometry. If
580605b261ecSmrg * there is a grab on the window, the cursor will be re-confined into the
580705b261ecSmrg * window.
580805b261ecSmrg */
58096747b715Smrgvoid
581005b261ecSmrgCheckCursorConfinement(WindowPtr pWin)
581105b261ecSmrg{
58124642e01fSmrg    GrabPtr grab;
581305b261ecSmrg    WindowPtr confineTo;
58144642e01fSmrg    DeviceIntPtr pDev;
581505b261ecSmrg
581605b261ecSmrg#ifdef PANORAMIX
581735c4bbdfSmrg    if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
581835c4bbdfSmrg        return;
581905b261ecSmrg#endif
582005b261ecSmrg
582135c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
582235c4bbdfSmrg        if (DevHasCursor(pDev)) {
58234642e01fSmrg            grab = pDev->deviceGrab.grab;
582435c4bbdfSmrg            if (grab && (confineTo = grab->confineTo)) {
58254642e01fSmrg                if (!BorderSizeNotEmpty(pDev, confineTo))
582635c4bbdfSmrg                    (*pDev->deviceGrab.DeactivateGrab) (pDev);
58274642e01fSmrg                else if ((pWin == confineTo) || IsParent(pWin, confineTo))
58284642e01fSmrg                    ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
58294642e01fSmrg            }
58304642e01fSmrg        }
583105b261ecSmrg    }
583205b261ecSmrg}
583305b261ecSmrg
583405b261ecSmrgMask
583505b261ecSmrgEventMaskForClient(WindowPtr pWin, ClientPtr client)
583605b261ecSmrg{
583735c4bbdfSmrg    OtherClientsPtr other;
583805b261ecSmrg
583935c4bbdfSmrg    if (wClient(pWin) == client)
584035c4bbdfSmrg        return pWin->eventMask;
584135c4bbdfSmrg    for (other = wOtherClients(pWin); other; other = other->next) {
584235c4bbdfSmrg        if (SameClient(other, client))
584335c4bbdfSmrg            return other->mask;
584405b261ecSmrg    }
584505b261ecSmrg    return 0;
584605b261ecSmrg}
584705b261ecSmrg
584805b261ecSmrg/**
584905b261ecSmrg * Server-side protocol handling for RecolorCursor request.
585005b261ecSmrg */
585105b261ecSmrgint
585205b261ecSmrgProcRecolorCursor(ClientPtr client)
585305b261ecSmrg{
585405b261ecSmrg    CursorPtr pCursor;
585535c4bbdfSmrg    int rc, nscr;
585635c4bbdfSmrg    ScreenPtr pscr;
585735c4bbdfSmrg    Bool displayed;
585835c4bbdfSmrg    SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
585935c4bbdfSmrg
586005b261ecSmrg    REQUEST(xRecolorCursorReq);
586105b261ecSmrg
586205b261ecSmrg    REQUEST_SIZE_MATCH(xRecolorCursorReq);
586335c4bbdfSmrg    rc = dixLookupResourceByType((void **) &pCursor, stuff->cursor, RT_CURSOR,
586435c4bbdfSmrg                                 client, DixWriteAccess);
586535c4bbdfSmrg    if (rc != Success) {
586635c4bbdfSmrg        client->errorValue = stuff->cursor;
586735c4bbdfSmrg        return rc;
586805b261ecSmrg    }
586905b261ecSmrg
587005b261ecSmrg    pCursor->foreRed = stuff->foreRed;
587105b261ecSmrg    pCursor->foreGreen = stuff->foreGreen;
587205b261ecSmrg    pCursor->foreBlue = stuff->foreBlue;
587305b261ecSmrg
587405b261ecSmrg    pCursor->backRed = stuff->backRed;
587505b261ecSmrg    pCursor->backGreen = stuff->backGreen;
587605b261ecSmrg    pCursor->backBlue = stuff->backBlue;
587705b261ecSmrg
587835c4bbdfSmrg    for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
587935c4bbdfSmrg        pscr = screenInfo.screens[nscr];
588005b261ecSmrg#ifdef PANORAMIX
588135c4bbdfSmrg        if (!noPanoramiXExtension)
588235c4bbdfSmrg            displayed = (pscr == pSprite->screen);
588335c4bbdfSmrg        else
588405b261ecSmrg#endif
588535c4bbdfSmrg            displayed = (pscr == pSprite->hotPhys.pScreen);
588635c4bbdfSmrg        (*pscr->RecolorCursor) (PickPointer(client), pscr, pCursor,
588735c4bbdfSmrg                                (pCursor == pSprite->current) && displayed);
588805b261ecSmrg    }
58896747b715Smrg    return Success;
589005b261ecSmrg}
589105b261ecSmrg
589205b261ecSmrg/**
589305b261ecSmrg * Write the given events to a client, swapping the byte order if necessary.
589405b261ecSmrg * To swap the byte ordering, a callback is called that has to be set up for
589505b261ecSmrg * the given event type.
589605b261ecSmrg *
589705b261ecSmrg * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
58984642e01fSmrg * can be more than one. Usually it's just one event.
589905b261ecSmrg *
590005b261ecSmrg * Do not modify the event structure passed in. See comment below.
59014642e01fSmrg *
590205b261ecSmrg * @param pClient Client to send events to.
590305b261ecSmrg * @param count Number of events.
590405b261ecSmrg * @param events The event list.
590505b261ecSmrg */
59066747b715Smrgvoid
590705b261ecSmrgWriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
590805b261ecSmrg{
590905b261ecSmrg#ifdef PANORAMIX
591035c4bbdfSmrg    xEvent eventCopy;
591105b261ecSmrg#endif
591235c4bbdfSmrg    xEvent *eventTo, *eventFrom;
591335c4bbdfSmrg    int i, eventlength = sizeof(xEvent);
591405b261ecSmrg
59156747b715Smrg    if (!pClient || pClient == serverClient || pClient->clientGone)
591635c4bbdfSmrg        return;
59176747b715Smrg
59186747b715Smrg    for (i = 0; i < count; i++)
591935c4bbdfSmrg        if ((events[i].u.u.type & 0x7f) != KeymapNotify)
592035c4bbdfSmrg            events[i].u.u.sequenceNumber = pClient->sequence;
59216747b715Smrg
59226747b715Smrg    /* Let XKB rewrite the state, as it depends on client preferences. */
59236747b715Smrg    XkbFilterEvents(pClient, count, events);
592405b261ecSmrg
592505b261ecSmrg#ifdef PANORAMIX
592635c4bbdfSmrg    if (!noPanoramiXExtension &&
592735c4bbdfSmrg        (screenInfo.screens[0]->x || screenInfo.screens[0]->y)) {
592835c4bbdfSmrg        switch (events->u.u.type) {
592935c4bbdfSmrg        case MotionNotify:
593035c4bbdfSmrg        case ButtonPress:
593135c4bbdfSmrg        case ButtonRelease:
593235c4bbdfSmrg        case KeyPress:
593335c4bbdfSmrg        case KeyRelease:
593435c4bbdfSmrg        case EnterNotify:
593535c4bbdfSmrg        case LeaveNotify:
593635c4bbdfSmrg            /*
593735c4bbdfSmrg               When multiple clients want the same event DeliverEventsToWindow
593835c4bbdfSmrg               passes the same event structure multiple times so we can't
593935c4bbdfSmrg               modify the one passed to us
594035c4bbdfSmrg             */
594135c4bbdfSmrg            count = 1;          /* should always be 1 */
594235c4bbdfSmrg            memcpy(&eventCopy, events, sizeof(xEvent));
594335c4bbdfSmrg            eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x;
594435c4bbdfSmrg            eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y;
594535c4bbdfSmrg            if (eventCopy.u.keyButtonPointer.event ==
594635c4bbdfSmrg                eventCopy.u.keyButtonPointer.root) {
594735c4bbdfSmrg                eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x;
594835c4bbdfSmrg                eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y;
594935c4bbdfSmrg            }
595035c4bbdfSmrg            events = &eventCopy;
595135c4bbdfSmrg            break;
595235c4bbdfSmrg        default:
595335c4bbdfSmrg            break;
595435c4bbdfSmrg        }
595505b261ecSmrg    }
595605b261ecSmrg#endif
595705b261ecSmrg
595835c4bbdfSmrg    if (EventCallback) {
595935c4bbdfSmrg        EventInfoRec eventinfo;
596035c4bbdfSmrg
596135c4bbdfSmrg        eventinfo.client = pClient;
596235c4bbdfSmrg        eventinfo.events = events;
596335c4bbdfSmrg        eventinfo.count = count;
596435c4bbdfSmrg        CallCallbacks(&EventCallback, (void *) &eventinfo);
596505b261ecSmrg    }
596605b261ecSmrg#ifdef XSERVER_DTRACE
596705b261ecSmrg    if (XSERVER_SEND_EVENT_ENABLED()) {
596835c4bbdfSmrg        for (i = 0; i < count; i++) {
596935c4bbdfSmrg            XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]);
597035c4bbdfSmrg        }
597105b261ecSmrg    }
59724642e01fSmrg#endif
59734642e01fSmrg    /* Just a safety check to make sure we only have one GenericEvent, it just
59744642e01fSmrg     * makes things easier for me right now. (whot) */
597535c4bbdfSmrg    for (i = 1; i < count; i++) {
597635c4bbdfSmrg        if (events[i].u.u.type == GenericEvent) {
59774642e01fSmrg            ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n");
59784642e01fSmrg            return;
59794642e01fSmrg        }
59804642e01fSmrg    }
59814642e01fSmrg
598235c4bbdfSmrg    if (events->u.u.type == GenericEvent) {
598335c4bbdfSmrg        eventlength += ((xGenericEvent *) events)->length * 4;
59844642e01fSmrg    }
59854642e01fSmrg
598635c4bbdfSmrg    if (pClient->swapped) {
598735c4bbdfSmrg        if (eventlength > swapEventLen) {
59884642e01fSmrg            swapEventLen = eventlength;
59896747b715Smrg            swapEvent = realloc(swapEvent, swapEventLen);
599035c4bbdfSmrg            if (!swapEvent) {
59914642e01fSmrg                FatalError("WriteEventsToClient: Out of memory.\n");
59924642e01fSmrg                return;
59934642e01fSmrg            }
59944642e01fSmrg        }
59954642e01fSmrg
599635c4bbdfSmrg        for (i = 0; i < count; i++) {
599735c4bbdfSmrg            eventFrom = &events[i];
59984642e01fSmrg            eventTo = swapEvent;
59994642e01fSmrg
600035c4bbdfSmrg            /* Remember to strip off the leading bit of type in case
600135c4bbdfSmrg               this event was sent with "SendEvent." */
600235c4bbdfSmrg            (*EventSwapVector[eventFrom->u.u.type & 0177])
600335c4bbdfSmrg                (eventFrom, eventTo);
60044642e01fSmrg
600535c4bbdfSmrg            WriteToClient(pClient, eventlength, eventTo);
600635c4bbdfSmrg        }
600705b261ecSmrg    }
600835c4bbdfSmrg    else {
60094642e01fSmrg        /* only one GenericEvent, remember? that means either count is 1 and
60104642e01fSmrg         * eventlength is arbitrary or eventlength is 32 and count doesn't
60114642e01fSmrg         * matter. And we're all set. Woohoo. */
601235c4bbdfSmrg        WriteToClient(pClient, count * eventlength, events);
601305b261ecSmrg    }
601405b261ecSmrg}
60154642e01fSmrg
60164642e01fSmrg/*
60176747b715Smrg * Set the client pointer for the given client.
60184642e01fSmrg *
60194642e01fSmrg * A client can have exactly one ClientPointer. Each time a
60204642e01fSmrg * request/reply/event is processed and the choice of devices is ambiguous
60214642e01fSmrg * (e.g. QueryPointer request), the server will pick the ClientPointer (see
60224642e01fSmrg * PickPointer()).
60234642e01fSmrg * If a keyboard is needed, the first keyboard paired with the CP is used.
60244642e01fSmrg */
60256747b715Smrgint
60266747b715SmrgSetClientPointer(ClientPtr client, DeviceIntPtr device)
60274642e01fSmrg{
60286747b715Smrg    int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess);
602935c4bbdfSmrg
60306747b715Smrg    if (rc != Success)
603135c4bbdfSmrg        return rc;
60326747b715Smrg
603335c4bbdfSmrg    if (!IsMaster(device)) {
60344642e01fSmrg        ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n");
60356747b715Smrg        return BadDevice;
603635c4bbdfSmrg    }
603735c4bbdfSmrg    else if (!device->spriteInfo->spriteOwner) {
60384642e01fSmrg        ErrorF("[dix] Device %d does not have a sprite. "
603935c4bbdfSmrg               "Cannot be ClientPointer\n", device->id);
60406747b715Smrg        return BadDevice;
60414642e01fSmrg    }
60424642e01fSmrg    client->clientPtr = device;
60436747b715Smrg    return Success;
60444642e01fSmrg}
60454642e01fSmrg
60464642e01fSmrg/* PickPointer will pick an appropriate pointer for the given client.
60474642e01fSmrg *
60484642e01fSmrg * An "appropriate device" is (in order of priority):
60494642e01fSmrg *  1) A device the given client has a core grab on.
60504642e01fSmrg *  2) A device set as ClientPointer for the given client.
60514642e01fSmrg *  3) The first master device.
60524642e01fSmrg */
60536747b715SmrgDeviceIntPtr
60544642e01fSmrgPickPointer(ClientPtr client)
60554642e01fSmrg{
60564642e01fSmrg    DeviceIntPtr it = inputInfo.devices;
60574642e01fSmrg
60584642e01fSmrg    /* First, check if the client currently has a grab on a device. Even
60594642e01fSmrg     * keyboards count. */
606035c4bbdfSmrg    for (it = inputInfo.devices; it; it = it->next) {
60614642e01fSmrg        GrabPtr grab = it->deviceGrab.grab;
606235c4bbdfSmrg
606335c4bbdfSmrg        if (grab && grab->grabtype == CORE && SameClient(grab, client)) {
60646747b715Smrg            it = GetMaster(it, MASTER_POINTER);
606535c4bbdfSmrg            return it;          /* Always return a core grabbed device */
60664642e01fSmrg        }
60674642e01fSmrg    }
60684642e01fSmrg
606935c4bbdfSmrg    if (!client->clientPtr) {
607035c4bbdfSmrg        it = inputInfo.devices;
607135c4bbdfSmrg        while (it) {
607235c4bbdfSmrg            if (IsMaster(it) && it->spriteInfo->spriteOwner) {
60734642e01fSmrg                client->clientPtr = it;
60744642e01fSmrg                break;
60754642e01fSmrg            }
60764642e01fSmrg            it = it->next;
60774642e01fSmrg        }
60784642e01fSmrg    }
60794642e01fSmrg    return client->clientPtr;
60804642e01fSmrg}
60814642e01fSmrg
60824642e01fSmrg/* PickKeyboard will pick an appropriate keyboard for the given client by
60834642e01fSmrg * searching the list of devices for the keyboard device that is paired with
60844642e01fSmrg * the client's pointer.
60854642e01fSmrg */
60866747b715SmrgDeviceIntPtr
60874642e01fSmrgPickKeyboard(ClientPtr client)
60884642e01fSmrg{
60894642e01fSmrg    DeviceIntPtr ptr = PickPointer(client);
60906747b715Smrg    DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD);
60914642e01fSmrg
609235c4bbdfSmrg    if (!kbd) {
60934642e01fSmrg        ErrorF("[dix] ClientPointer not paired with a keyboard. This "
609435c4bbdfSmrg               "is a bug.\n");
60954642e01fSmrg    }
60964642e01fSmrg
60974642e01fSmrg    return kbd;
60984642e01fSmrg}
60994642e01fSmrg
61004642e01fSmrg/* A client that has one or more core grabs does not get core events from
61014642e01fSmrg * devices it does not have a grab on. Legacy applications behave bad
61024642e01fSmrg * otherwise because they are not used to it and the events interfere.
61034642e01fSmrg * Only applies for core events.
61044642e01fSmrg *
61054642e01fSmrg * Return true if a core event from the device would interfere and should not
61064642e01fSmrg * be delivered.
61074642e01fSmrg */
61084642e01fSmrgBool
610935c4bbdfSmrgIsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent *event)
61104642e01fSmrg{
61114642e01fSmrg    DeviceIntPtr it = inputInfo.devices;
61124642e01fSmrg
611335c4bbdfSmrg    switch (event->u.u.type) {
611435c4bbdfSmrg    case KeyPress:
611535c4bbdfSmrg    case KeyRelease:
611635c4bbdfSmrg    case ButtonPress:
611735c4bbdfSmrg    case ButtonRelease:
611835c4bbdfSmrg    case MotionNotify:
611935c4bbdfSmrg    case EnterNotify:
612035c4bbdfSmrg    case LeaveNotify:
612135c4bbdfSmrg        break;
612235c4bbdfSmrg    default:
612335c4bbdfSmrg        return FALSE;
61244642e01fSmrg    }
61254642e01fSmrg
61266747b715Smrg    if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
61276747b715Smrg        return FALSE;
61286747b715Smrg
612935c4bbdfSmrg    while (it) {
613035c4bbdfSmrg        if (it != dev) {
61314642e01fSmrg            if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client)
613235c4bbdfSmrg                && !it->deviceGrab.fromPassiveGrab) {
61334642e01fSmrg                if ((IsPointerDevice(it) && IsPointerDevice(dev)) ||
613435c4bbdfSmrg                    (IsKeyboardDevice(it) && IsKeyboardDevice(dev)))
61354642e01fSmrg                    return TRUE;
61364642e01fSmrg            }
61374642e01fSmrg        }
61384642e01fSmrg        it = it->next;
61394642e01fSmrg    }
61404642e01fSmrg
61414642e01fSmrg    return FALSE;
61424642e01fSmrg}
61434642e01fSmrg
614435c4bbdfSmrg/* PointerBarrier events are only delivered to the client that created that
614535c4bbdfSmrg * barrier */
614635c4bbdfSmrgstatic Bool
614735c4bbdfSmrgIsWrongPointerBarrierClient(ClientPtr client, DeviceIntPtr dev, xEvent *event)
614835c4bbdfSmrg{
614935c4bbdfSmrg    xXIBarrierEvent *ev = (xXIBarrierEvent*)event;
615035c4bbdfSmrg
615135c4bbdfSmrg    if (ev->type != GenericEvent || ev->extension != IReqCode)
615235c4bbdfSmrg        return FALSE;
615335c4bbdfSmrg
615435c4bbdfSmrg    if (ev->evtype != XI_BarrierHit && ev->evtype != XI_BarrierLeave)
615535c4bbdfSmrg        return FALSE;
615635c4bbdfSmrg
615735c4bbdfSmrg    return client->index != CLIENT_ID(ev->barrier);
615835c4bbdfSmrg}
6159