events.c revision 5a112b11
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
11945a112b11Smrg    eventlen = sizeof(InternalEvent);
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    GrabPtr grab;
130805b261ecSmrg    DeviceIntPtr dev;
130905b261ecSmrg
131005b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
131135c4bbdfSmrg        FreezeThaw(dev, dev->deviceGrab.sync.other ||
131235c4bbdfSmrg                   (dev->deviceGrab.sync.state >= FROZEN));
131335c4bbdfSmrg    if (syncEvents.playingEvents ||
131435c4bbdfSmrg        (!replayDev && xorg_list_is_empty(&syncEvents.pending)))
131535c4bbdfSmrg        return;
131605b261ecSmrg    syncEvents.playingEvents = TRUE;
131735c4bbdfSmrg    if (replayDev) {
13185a112b11Smrg        InternalEvent *event = replayDev->deviceGrab.sync.event;
13196747b715Smrg
132035c4bbdfSmrg        syncEvents.replayDev = (DeviceIntPtr) NULL;
132105b261ecSmrg
13225a112b11Smrg        if (!CheckDeviceGrabs(replayDev, event,
13235a112b11Smrg                              syncEvents.replayWin)) {
13245a112b11Smrg            if (IsTouchEvent(event)) {
132535c4bbdfSmrg                TouchPointInfoPtr ti =
13265a112b11Smrg                    TouchFindByClientID(replayDev, event->device_event.touchid);
132735c4bbdfSmrg                BUG_WARN(!ti);
132835c4bbdfSmrg
132935c4bbdfSmrg                TouchListenerAcceptReject(replayDev, ti, 0, XIRejectTouch);
133035c4bbdfSmrg            }
13315a112b11Smrg            else if (IsGestureEvent(event)) {
13325a112b11Smrg                GestureInfoPtr gi =
13335a112b11Smrg                    GestureFindActiveByEventType(replayDev, event->any.type);
13345a112b11Smrg                if (gi) {
13355a112b11Smrg                    GestureEmitGestureEndToOwner(replayDev, gi);
13365a112b11Smrg                    GestureEndGesture(gi);
13375a112b11Smrg                }
13385a112b11Smrg                ProcessGestureEvent(event, replayDev);
13395a112b11Smrg            }
13405a112b11Smrg            else {
13415a112b11Smrg                WindowPtr w = XYToWindow(replayDev->spriteInfo->sprite,
13425a112b11Smrg                                         event->device_event.root_x,
13435a112b11Smrg                                         event->device_event.root_y);
13445a112b11Smrg                if (replayDev->focus && !IsPointerEvent(event))
13455a112b11Smrg                    DeliverFocusedEvent(replayDev, event, w);
13465a112b11Smrg                else
13475a112b11Smrg                    DeliverDeviceEvents(w, event, NullGrab,
13485a112b11Smrg                                        NullWindow, replayDev);
13495a112b11Smrg            }
13509ace9065Smrg        }
135105b261ecSmrg    }
135235c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
135335c4bbdfSmrg        if (!dev->deviceGrab.sync.frozen) {
135435c4bbdfSmrg            PlayReleasedEvents();
135535c4bbdfSmrg            break;
135635c4bbdfSmrg        }
135705b261ecSmrg    }
135805b261ecSmrg    syncEvents.playingEvents = FALSE;
135935c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
136035c4bbdfSmrg        if (DevHasCursor(dev)) {
13614642e01fSmrg            /* the following may have been skipped during replay,
136235c4bbdfSmrg               so do it now */
136335c4bbdfSmrg            if ((grab = dev->deviceGrab.grab) && grab->confineTo) {
13644642e01fSmrg                if (grab->confineTo->drawable.pScreen !=
136535c4bbdfSmrg                    dev->spriteInfo->sprite->hotPhys.pScreen)
13664642e01fSmrg                    dev->spriteInfo->sprite->hotPhys.x =
13674642e01fSmrg                        dev->spriteInfo->sprite->hotPhys.y = 0;
13684642e01fSmrg                ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE);
13694642e01fSmrg            }
13704642e01fSmrg            else
13714642e01fSmrg                ConfineCursorToWindow(dev,
137235c4bbdfSmrg                                      dev->spriteInfo->sprite->hotPhys.pScreen->
137335c4bbdfSmrg                                      root, TRUE, FALSE);
13744642e01fSmrg            PostNewCursor(dev);
13754642e01fSmrg        }
137605b261ecSmrg    }
137705b261ecSmrg}
137805b261ecSmrg
137905b261ecSmrg#ifdef RANDR
138005b261ecSmrgvoid
138135c4bbdfSmrgScreenRestructured(ScreenPtr pScreen)
138205b261ecSmrg{
138305b261ecSmrg    GrabPtr grab;
13844642e01fSmrg    DeviceIntPtr pDev;
138505b261ecSmrg
138635c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
138735c4bbdfSmrg        if (!IsFloating(pDev) && !DevHasCursor(pDev))
13884642e01fSmrg            continue;
13894642e01fSmrg
13904642e01fSmrg        /* GrabDevice doesn't have a confineTo field, so we don't need to
13914642e01fSmrg         * worry about it. */
139235c4bbdfSmrg        if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
13934642e01fSmrg            if (grab->confineTo->drawable.pScreen
139435c4bbdfSmrg                != pDev->spriteInfo->sprite->hotPhys.pScreen)
139535c4bbdfSmrg                pDev->spriteInfo->sprite->hotPhys.x =
139635c4bbdfSmrg                    pDev->spriteInfo->sprite->hotPhys.y = 0;
13974642e01fSmrg            ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
13984642e01fSmrg        }
13994642e01fSmrg        else
14004642e01fSmrg            ConfineCursorToWindow(pDev,
140135c4bbdfSmrg                                  pDev->spriteInfo->sprite->hotPhys.pScreen->
140235c4bbdfSmrg                                  root, TRUE, FALSE);
140305b261ecSmrg    }
140405b261ecSmrg}
140505b261ecSmrg#endif
140605b261ecSmrg
14074642e01fSmrgstatic void
140805b261ecSmrgCheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
140905b261ecSmrg{
14104642e01fSmrg    GrabPtr grab = thisDev->deviceGrab.grab;
141105b261ecSmrg    DeviceIntPtr dev;
141205b261ecSmrg
141305b261ecSmrg    if (thisMode == GrabModeSync)
141435c4bbdfSmrg        thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT;
141535c4bbdfSmrg    else {                      /* free both if same client owns both */
141635c4bbdfSmrg        thisDev->deviceGrab.sync.state = THAWED;
141735c4bbdfSmrg        if (thisDev->deviceGrab.sync.other &&
141835c4bbdfSmrg            (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) ==
141935c4bbdfSmrg             CLIENT_BITS(grab->resource)))
142035c4bbdfSmrg            thisDev->deviceGrab.sync.other = NullGrab;
142105b261ecSmrg    }
14224642e01fSmrg
142335c4bbdfSmrg    if (IsMaster(thisDev)) {
14244642e01fSmrg        dev = GetPairedDevice(thisDev);
14254642e01fSmrg        if (otherMode == GrabModeSync)
14264642e01fSmrg            dev->deviceGrab.sync.other = grab;
142735c4bbdfSmrg        else {                  /* free both if same client owns both */
14284642e01fSmrg            if (dev->deviceGrab.sync.other &&
142935c4bbdfSmrg                (CLIENT_BITS(dev->deviceGrab.sync.other->resource) ==
143035c4bbdfSmrg                 CLIENT_BITS(grab->resource)))
14314642e01fSmrg                dev->deviceGrab.sync.other = NullGrab;
14324642e01fSmrg        }
143305b261ecSmrg    }
143405b261ecSmrg    ComputeFreezes();
143505b261ecSmrg}
143605b261ecSmrg
14376747b715Smrg/**
14386747b715Smrg * Save the device's master device id. This needs to be done
14396747b715Smrg * if a client directly grabs a slave device that is attached to a master. For
14406747b715Smrg * the duration of the grab, the device is detached, ungrabbing re-attaches it
14416747b715Smrg * though.
14426747b715Smrg *
14436747b715Smrg * We store the ID of the master device only in case the master disappears
14446747b715Smrg * while the device has a grab.
14456747b715Smrg */
14466747b715Smrgstatic void
14476747b715SmrgDetachFromMaster(DeviceIntPtr dev)
14486747b715Smrg{
144935c4bbdfSmrg    if (IsFloating(dev))
14506747b715Smrg        return;
14516747b715Smrg
145235c4bbdfSmrg    dev->saved_master_id = GetMaster(dev, MASTER_ATTACHED)->id;
14536747b715Smrg
14546747b715Smrg    AttachDevice(NULL, dev, NULL);
14556747b715Smrg}
14566747b715Smrg
14576747b715Smrgstatic void
14586747b715SmrgReattachToOldMaster(DeviceIntPtr dev)
14596747b715Smrg{
14606747b715Smrg    DeviceIntPtr master = NULL;
14616747b715Smrg
14626747b715Smrg    if (IsMaster(dev))
14636747b715Smrg        return;
14646747b715Smrg
14656747b715Smrg    dixLookupDevice(&master, dev->saved_master_id, serverClient, DixUseAccess);
14666747b715Smrg
146735c4bbdfSmrg    if (master) {
14686747b715Smrg        AttachDevice(serverClient, dev, master);
146935c4bbdfSmrg        dev->saved_master_id = 0;
147035c4bbdfSmrg    }
147135c4bbdfSmrg}
147235c4bbdfSmrg
147335c4bbdfSmrg/**
147435c4bbdfSmrg * Update touch records when an explicit grab is activated. Any touches owned by
147535c4bbdfSmrg * the grabbing client are updated so the listener state reflects the new grab.
147635c4bbdfSmrg */
147735c4bbdfSmrgstatic void
147835c4bbdfSmrgUpdateTouchesForGrab(DeviceIntPtr mouse)
147935c4bbdfSmrg{
148035c4bbdfSmrg    int i;
148135c4bbdfSmrg
148235c4bbdfSmrg    if (!mouse->touch || mouse->deviceGrab.fromPassiveGrab)
148335c4bbdfSmrg        return;
148435c4bbdfSmrg
148535c4bbdfSmrg    for (i = 0; i < mouse->touch->num_touches; i++) {
148635c4bbdfSmrg        TouchPointInfoPtr ti = mouse->touch->touches + i;
148735c4bbdfSmrg        TouchListener *listener = &ti->listeners[0];
148835c4bbdfSmrg        GrabPtr grab = mouse->deviceGrab.grab;
148935c4bbdfSmrg
149035c4bbdfSmrg        if (ti->active &&
149135c4bbdfSmrg            CLIENT_BITS(listener->listener) == grab->resource) {
14925a112b11Smrg            if (grab->grabtype == CORE || grab->grabtype == XI ||
14935a112b11Smrg                !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin)) {
14945a112b11Smrg
14955a112b11Smrg                if (listener->type == TOUCH_LISTENER_REGULAR &&
14965a112b11Smrg                    listener->state != TOUCH_LISTENER_AWAITING_BEGIN &&
14975a112b11Smrg                    listener->state != TOUCH_LISTENER_HAS_END) {
14985a112b11Smrg                    /* if the listener already got any events relating to the touch, we must send
14995a112b11Smrg                       a touch end because the grab overrides the previous listener and won't
15005a112b11Smrg                       itself send any touch events.
15015a112b11Smrg                    */
15025a112b11Smrg                    TouchEmitTouchEnd(mouse, ti, 0, listener->listener);
15035a112b11Smrg                }
15045a112b11Smrg                listener->type = TOUCH_LISTENER_POINTER_GRAB;
15055a112b11Smrg            } else {
15065a112b11Smrg                listener->type = TOUCH_LISTENER_GRAB;
15075a112b11Smrg            }
15085a112b11Smrg
150935c4bbdfSmrg            listener->listener = grab->resource;
151035c4bbdfSmrg            listener->level = grab->grabtype;
151135c4bbdfSmrg            listener->window = grab->window;
15125a112b11Smrg            listener->state = TOUCH_LISTENER_IS_OWNER;
151335c4bbdfSmrg
151435c4bbdfSmrg            if (listener->grab)
151535c4bbdfSmrg                FreeGrab(listener->grab);
151635c4bbdfSmrg            listener->grab = AllocGrab(grab);
151735c4bbdfSmrg        }
15186747b715Smrg    }
15196747b715Smrg}
15206747b715Smrg
15215a112b11Smrg/**
15225a112b11Smrg * Update gesture records when an explicit grab is activated. Any gestures owned
15235a112b11Smrg * by the grabbing client are updated so the listener state reflects the new
15245a112b11Smrg * grab.
15255a112b11Smrg */
15265a112b11Smrgstatic void
15275a112b11SmrgUpdateGesturesForGrab(DeviceIntPtr mouse)
15285a112b11Smrg{
15295a112b11Smrg    if (!mouse->gesture || mouse->deviceGrab.fromPassiveGrab)
15305a112b11Smrg        return;
15315a112b11Smrg
15325a112b11Smrg    GestureInfoPtr gi = &mouse->gesture->gesture;
15335a112b11Smrg    GestureListener *listener = &gi->listener;
15345a112b11Smrg    GrabPtr grab = mouse->deviceGrab.grab;
15355a112b11Smrg
15365a112b11Smrg    if (gi->active && CLIENT_BITS(listener->listener) == grab->resource) {
15375a112b11Smrg        if (grab->grabtype == CORE || grab->grabtype == XI ||
15385a112b11Smrg            !xi2mask_isset(grab->xi2mask, mouse, GetXI2Type(gi->type))) {
15395a112b11Smrg
15405a112b11Smrg            if (listener->type == GESTURE_LISTENER_REGULAR) {
15415a112b11Smrg                /* if the listener already got any events relating to the gesture, we must send
15425a112b11Smrg                   a gesture end because the grab overrides the previous listener and won't
15435a112b11Smrg                   itself send any gesture events.
15445a112b11Smrg                */
15455a112b11Smrg                GestureEmitGestureEndToOwner(mouse, gi);
15465a112b11Smrg            }
15475a112b11Smrg            listener->type = GESTURE_LISTENER_NONGESTURE_GRAB;
15485a112b11Smrg        } else {
15495a112b11Smrg            listener->type = GESTURE_LISTENER_GRAB;
15505a112b11Smrg        }
15515a112b11Smrg
15525a112b11Smrg        listener->listener = grab->resource;
15535a112b11Smrg        listener->window = grab->window;
15545a112b11Smrg
15555a112b11Smrg        if (listener->grab)
15565a112b11Smrg            FreeGrab(listener->grab);
15575a112b11Smrg        listener->grab = AllocGrab(grab);
15585a112b11Smrg    }
15595a112b11Smrg}
15605a112b11Smrg
156105b261ecSmrg/**
156205b261ecSmrg * Activate a pointer grab on the given device. A pointer grab will cause all
15634642e01fSmrg * core pointer events of this device to be delivered to the grabbing client only.
15644642e01fSmrg * No other device will send core events to the grab client while the grab is
15654642e01fSmrg * on, but core events will be sent to other clients.
15664642e01fSmrg * Can cause the cursor to change if a grab cursor is set.
15674642e01fSmrg *
15684642e01fSmrg * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab
15694642e01fSmrg * is an implicit grab caused by a ButtonPress event.
15704642e01fSmrg *
157105b261ecSmrg * @param mouse The device to grab.
157205b261ecSmrg * @param grab The grab structure, needs to be setup.
157305b261ecSmrg * @param autoGrab True if the grab was caused by a button down event and not
15745a112b11Smrg * explicitly by a client.
157505b261ecSmrg */
157605b261ecSmrgvoid
15774642e01fSmrgActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
157805b261ecSmrg                    TimeStamp time, Bool autoGrab)
157905b261ecSmrg{
15804642e01fSmrg    GrabInfoPtr grabinfo = &mouse->deviceGrab;
158135c4bbdfSmrg    GrabPtr oldgrab = grabinfo->grab;
15824642e01fSmrg    WindowPtr oldWin = (grabinfo->grab) ?
158335c4bbdfSmrg        grabinfo->grab->window : mouse->spriteInfo->sprite->win;
15844642e01fSmrg    Bool isPassive = autoGrab & ~ImplicitGrabMask;
158505b261ecSmrg
15866747b715Smrg    /* slave devices need to float for the duration of the grab. */
158735c4bbdfSmrg    if (grab->grabtype == XI2 &&
15886747b715Smrg        !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse))
15896747b715Smrg        DetachFromMaster(mouse);
15906747b715Smrg
159135c4bbdfSmrg    if (grab->confineTo) {
159235c4bbdfSmrg        if (grab->confineTo->drawable.pScreen
159335c4bbdfSmrg            != mouse->spriteInfo->sprite->hotPhys.pScreen)
159435c4bbdfSmrg            mouse->spriteInfo->sprite->hotPhys.x =
15954642e01fSmrg                mouse->spriteInfo->sprite->hotPhys.y = 0;
159635c4bbdfSmrg        ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE);
159705b261ecSmrg    }
1598806e81e9Smrg    if (! (grabinfo->grab && oldWin == grabinfo->grab->window
1599806e81e9Smrg			  && oldWin == grab->window))
1600806e81e9Smrg        DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab);
160105b261ecSmrg    mouse->valuator->motionHintWindow = NullWindow;
160205b261ecSmrg    if (syncEvents.playingEvents)
16034642e01fSmrg        grabinfo->grabTime = syncEvents.time;
160405b261ecSmrg    else
160535c4bbdfSmrg        grabinfo->grabTime = time;
160635c4bbdfSmrg    grabinfo->grab = AllocGrab(grab);
16074642e01fSmrg    grabinfo->fromPassiveGrab = isPassive;
16084642e01fSmrg    grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
16094642e01fSmrg    PostNewCursor(mouse);
161035c4bbdfSmrg    UpdateTouchesForGrab(mouse);
16115a112b11Smrg    UpdateGesturesForGrab(mouse);
161235c4bbdfSmrg    CheckGrabForSyncs(mouse, (Bool) grab->pointerMode,
161335c4bbdfSmrg                      (Bool) grab->keyboardMode);
161435c4bbdfSmrg    if (oldgrab)
161535c4bbdfSmrg        FreeGrab(oldgrab);
161605b261ecSmrg}
161705b261ecSmrg
161805b261ecSmrg/**
161905b261ecSmrg * Delete grab on given device, update the sprite.
162005b261ecSmrg *
16214642e01fSmrg * Extension devices are set up for ActivateKeyboardGrab().
162205b261ecSmrg */
162305b261ecSmrgvoid
162405b261ecSmrgDeactivatePointerGrab(DeviceIntPtr mouse)
162505b261ecSmrg{
16264642e01fSmrg    GrabPtr grab = mouse->deviceGrab.grab;
162705b261ecSmrg    DeviceIntPtr dev;
162835c4bbdfSmrg    Bool wasPassive = mouse->deviceGrab.fromPassiveGrab;
16296747b715Smrg    Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
16306747b715Smrg                        mouse->deviceGrab.implicitGrab);
163135c4bbdfSmrg    XID grab_resource = grab->resource;
163235c4bbdfSmrg    int i;
163335c4bbdfSmrg
163435c4bbdfSmrg    /* If an explicit grab was deactivated, we must remove it from the head of
163535c4bbdfSmrg     * all the touches' listener lists. */
163635c4bbdfSmrg    for (i = 0; !wasPassive && mouse->touch && i < mouse->touch->num_touches; i++) {
163735c4bbdfSmrg        TouchPointInfoPtr ti = mouse->touch->touches + i;
163835c4bbdfSmrg        if (ti->active && TouchResourceIsOwner(ti, grab_resource)) {
163935c4bbdfSmrg            int mode = XIRejectTouch;
164035c4bbdfSmrg            /* Rejecting will generate a TouchEnd, but we must not
164135c4bbdfSmrg               emulate a ButtonRelease here. So pretend the listener
164235c4bbdfSmrg               already has the end event */
164335c4bbdfSmrg            if (grab->grabtype == CORE || grab->grabtype == XI ||
16445a112b11Smrg                    !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin)) {
164535c4bbdfSmrg                mode = XIAcceptTouch;
164635c4bbdfSmrg                /* NOTE: we set the state here, but
164735c4bbdfSmrg                 * ProcessTouchOwnershipEvent() will still call
164835c4bbdfSmrg                 * TouchEmitTouchEnd for this listener. The other half of
164935c4bbdfSmrg                 * this hack is in DeliverTouchEndEvent */
16505a112b11Smrg                ti->listeners[0].state = TOUCH_LISTENER_HAS_END;
165135c4bbdfSmrg            }
165235c4bbdfSmrg            TouchListenerAcceptReject(mouse, ti, 0, mode);
165335c4bbdfSmrg        }
165435c4bbdfSmrg    }
165535c4bbdfSmrg
165635c4bbdfSmrg    TouchRemovePointerGrab(mouse);
165705b261ecSmrg
165805b261ecSmrg    mouse->valuator->motionHintWindow = NullWindow;
16594642e01fSmrg    mouse->deviceGrab.grab = NullGrab;
16604642e01fSmrg    mouse->deviceGrab.sync.state = NOT_GRABBED;
16614642e01fSmrg    mouse->deviceGrab.fromPassiveGrab = FALSE;
16624642e01fSmrg
166335c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
166435c4bbdfSmrg        if (dev->deviceGrab.sync.other == grab)
166535c4bbdfSmrg            dev->deviceGrab.sync.other = NullGrab;
166605b261ecSmrg    }
16675a112b11Smrg
16685a112b11Smrg    /* in case of explicit gesture grab, send end event to the grab client */
16695a112b11Smrg    if (!wasPassive && mouse->gesture) {
16705a112b11Smrg        GestureInfoPtr gi = &mouse->gesture->gesture;
16715a112b11Smrg        if (gi->active && GestureResourceIsOwner(gi, grab_resource)) {
16725a112b11Smrg            GestureEmitGestureEndToOwner(mouse, gi);
16735a112b11Smrg            GestureEndGesture(gi);
16745a112b11Smrg        }
16755a112b11Smrg    }
16765a112b11Smrg
16776747b715Smrg    DoEnterLeaveEvents(mouse, mouse->id, grab->window,
16784642e01fSmrg                       mouse->spriteInfo->sprite->win, NotifyUngrab);
167905b261ecSmrg    if (grab->confineTo)
168035c4bbdfSmrg        ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE);
16814642e01fSmrg    PostNewCursor(mouse);
16824642e01fSmrg
168335c4bbdfSmrg    if (!wasImplicit && grab->grabtype == XI2)
16846747b715Smrg        ReattachToOldMaster(mouse);
16856747b715Smrg
168605b261ecSmrg    ComputeFreezes();
168735c4bbdfSmrg
168835c4bbdfSmrg    FreeGrab(grab);
168905b261ecSmrg}
169005b261ecSmrg
169105b261ecSmrg/**
16924642e01fSmrg * Activate a keyboard grab on the given device.
169305b261ecSmrg *
169405b261ecSmrg * Extension devices have ActivateKeyboardGrab() set as their grabbing proc.
169505b261ecSmrg */
169605b261ecSmrgvoid
169735c4bbdfSmrgActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time,
169835c4bbdfSmrg                     Bool passive)
169905b261ecSmrg{
17004642e01fSmrg    GrabInfoPtr grabinfo = &keybd->deviceGrab;
170135c4bbdfSmrg    GrabPtr oldgrab = grabinfo->grab;
170205b261ecSmrg    WindowPtr oldWin;
170305b261ecSmrg
17046747b715Smrg    /* slave devices need to float for the duration of the grab. */
170535c4bbdfSmrg    if (grab->grabtype == XI2 && keybd->enabled &&
170635c4bbdfSmrg        !(passive & ImplicitGrabMask) && !IsMaster(keybd))
17076747b715Smrg        DetachFromMaster(keybd);
17086747b715Smrg
170935c4bbdfSmrg    if (!keybd->enabled)
171035c4bbdfSmrg        oldWin = NULL;
171135c4bbdfSmrg    else if (grabinfo->grab)
171235c4bbdfSmrg        oldWin = grabinfo->grab->window;
171305b261ecSmrg    else if (keybd->focus)
171435c4bbdfSmrg        oldWin = keybd->focus->win;
171505b261ecSmrg    else
171635c4bbdfSmrg        oldWin = keybd->spriteInfo->sprite->win;
171705b261ecSmrg    if (oldWin == FollowKeyboardWin)
171835c4bbdfSmrg        oldWin = keybd->focus->win;
171905b261ecSmrg    if (keybd->valuator)
172035c4bbdfSmrg        keybd->valuator->motionHintWindow = NullWindow;
1721806e81e9Smrg    if (oldWin &&
1722806e81e9Smrg	! (grabinfo->grab && oldWin == grabinfo->grab->window
1723806e81e9Smrg			  && oldWin == grab->window))
172435c4bbdfSmrg        DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
172505b261ecSmrg    if (syncEvents.playingEvents)
172635c4bbdfSmrg        grabinfo->grabTime = syncEvents.time;
172705b261ecSmrg    else
172835c4bbdfSmrg        grabinfo->grabTime = time;
172935c4bbdfSmrg    grabinfo->grab = AllocGrab(grab);
17304642e01fSmrg    grabinfo->fromPassiveGrab = passive;
17316747b715Smrg    grabinfo->implicitGrab = passive & ImplicitGrabMask;
173235c4bbdfSmrg    CheckGrabForSyncs(keybd, (Bool) grab->keyboardMode,
173335c4bbdfSmrg                      (Bool) grab->pointerMode);
173435c4bbdfSmrg    if (oldgrab)
173535c4bbdfSmrg        FreeGrab(oldgrab);
173605b261ecSmrg}
173705b261ecSmrg
173805b261ecSmrg/**
17394642e01fSmrg * Delete keyboard grab for the given device.
174005b261ecSmrg */
174105b261ecSmrgvoid
174205b261ecSmrgDeactivateKeyboardGrab(DeviceIntPtr keybd)
174305b261ecSmrg{
17444642e01fSmrg    GrabPtr grab = keybd->deviceGrab.grab;
174505b261ecSmrg    DeviceIntPtr dev;
174635c4bbdfSmrg    WindowPtr focusWin;
17476747b715Smrg    Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab &&
17486747b715Smrg                        keybd->deviceGrab.implicitGrab);
174905b261ecSmrg
175005b261ecSmrg    if (keybd->valuator)
175135c4bbdfSmrg        keybd->valuator->motionHintWindow = NullWindow;
17524642e01fSmrg    keybd->deviceGrab.grab = NullGrab;
17534642e01fSmrg    keybd->deviceGrab.sync.state = NOT_GRABBED;
17544642e01fSmrg    keybd->deviceGrab.fromPassiveGrab = FALSE;
17554642e01fSmrg
175635c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
175735c4bbdfSmrg        if (dev->deviceGrab.sync.other == grab)
175835c4bbdfSmrg            dev->deviceGrab.sync.other = NullGrab;
175905b261ecSmrg    }
176035c4bbdfSmrg
176135c4bbdfSmrg    if (keybd->focus)
176235c4bbdfSmrg        focusWin = keybd->focus->win;
176335c4bbdfSmrg    else if (keybd->spriteInfo->sprite)
176435c4bbdfSmrg        focusWin = keybd->spriteInfo->sprite->win;
176535c4bbdfSmrg    else
176635c4bbdfSmrg        focusWin = NullWindow;
176735c4bbdfSmrg
176835c4bbdfSmrg    if (focusWin == FollowKeyboardWin)
176935c4bbdfSmrg        focusWin = inputInfo.keyboard->focus->win;
177035c4bbdfSmrg
177105b261ecSmrg    DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
17724642e01fSmrg
177335c4bbdfSmrg    if (!wasImplicit && grab->grabtype == XI2)
17746747b715Smrg        ReattachToOldMaster(keybd);
17756747b715Smrg
177605b261ecSmrg    ComputeFreezes();
177735c4bbdfSmrg
177835c4bbdfSmrg    FreeGrab(grab);
177905b261ecSmrg}
178005b261ecSmrg
178105b261ecSmrgvoid
178235c4bbdfSmrgAllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState)
178305b261ecSmrg{
178405b261ecSmrg    Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
178505b261ecSmrg    TimeStamp grabTime;
178605b261ecSmrg    DeviceIntPtr dev;
178735c4bbdfSmrg    GrabInfoPtr devgrabinfo, grabinfo = &thisDev->deviceGrab;
178805b261ecSmrg
17894642e01fSmrg    thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
179005b261ecSmrg    thisSynced = FALSE;
179105b261ecSmrg    otherGrabbed = FALSE;
17926747b715Smrg    othersFrozen = FALSE;
17934642e01fSmrg    grabTime = grabinfo->grabTime;
179435c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
17954642e01fSmrg        devgrabinfo = &dev->deviceGrab;
17964642e01fSmrg
179735c4bbdfSmrg        if (dev == thisDev)
179835c4bbdfSmrg            continue;
179935c4bbdfSmrg        if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) {
180035c4bbdfSmrg            if (!(thisGrabbed || otherGrabbed) ||
180135c4bbdfSmrg                (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER))
180235c4bbdfSmrg                grabTime = devgrabinfo->grabTime;
180335c4bbdfSmrg            otherGrabbed = TRUE;
180435c4bbdfSmrg            if (grabinfo->sync.other == devgrabinfo->grab)
180535c4bbdfSmrg                thisSynced = TRUE;
180635c4bbdfSmrg            if (devgrabinfo->sync.state >= FROZEN)
180735c4bbdfSmrg                othersFrozen = TRUE;
180835c4bbdfSmrg        }
180905b261ecSmrg    }
18104642e01fSmrg    if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced))
181135c4bbdfSmrg        return;
181205b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
181335c4bbdfSmrg        (CompareTimeStamps(time, grabTime) == EARLIER))
181435c4bbdfSmrg        return;
181535c4bbdfSmrg    switch (newState) {
181635c4bbdfSmrg    case THAWED:               /* Async */
181735c4bbdfSmrg        if (thisGrabbed)
181835c4bbdfSmrg            grabinfo->sync.state = THAWED;
181935c4bbdfSmrg        if (thisSynced)
182035c4bbdfSmrg            grabinfo->sync.other = NullGrab;
182135c4bbdfSmrg        ComputeFreezes();
182235c4bbdfSmrg        break;
182335c4bbdfSmrg    case FREEZE_NEXT_EVENT:    /* Sync */
182435c4bbdfSmrg        if (thisGrabbed) {
182535c4bbdfSmrg            grabinfo->sync.state = FREEZE_NEXT_EVENT;
182635c4bbdfSmrg            if (thisSynced)
182735c4bbdfSmrg                grabinfo->sync.other = NullGrab;
182835c4bbdfSmrg            ComputeFreezes();
182935c4bbdfSmrg        }
183035c4bbdfSmrg        break;
183135c4bbdfSmrg    case THAWED_BOTH:          /* AsyncBoth */
183235c4bbdfSmrg        if (othersFrozen) {
183335c4bbdfSmrg            for (dev = inputInfo.devices; dev; dev = dev->next) {
183435c4bbdfSmrg                devgrabinfo = &dev->deviceGrab;
183535c4bbdfSmrg                if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
183635c4bbdfSmrg                    devgrabinfo->sync.state = THAWED;
183735c4bbdfSmrg                if (devgrabinfo->sync.other &&
183835c4bbdfSmrg                    SameClient(devgrabinfo->sync.other, client))
183935c4bbdfSmrg                    devgrabinfo->sync.other = NullGrab;
184035c4bbdfSmrg            }
184135c4bbdfSmrg            ComputeFreezes();
184235c4bbdfSmrg        }
184335c4bbdfSmrg        break;
184435c4bbdfSmrg    case FREEZE_BOTH_NEXT_EVENT:       /* SyncBoth */
184535c4bbdfSmrg        if (othersFrozen) {
184635c4bbdfSmrg            for (dev = inputInfo.devices; dev; dev = dev->next) {
184735c4bbdfSmrg                devgrabinfo = &dev->deviceGrab;
184835c4bbdfSmrg                if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
184935c4bbdfSmrg                    devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT;
185035c4bbdfSmrg                if (devgrabinfo->sync.other
185135c4bbdfSmrg                    && SameClient(devgrabinfo->sync.other, client))
185235c4bbdfSmrg                    devgrabinfo->sync.other = NullGrab;
185335c4bbdfSmrg            }
185435c4bbdfSmrg            ComputeFreezes();
185535c4bbdfSmrg        }
185635c4bbdfSmrg        break;
185735c4bbdfSmrg    case NOT_GRABBED:          /* Replay */
185835c4bbdfSmrg        if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT) {
185935c4bbdfSmrg            if (thisSynced)
186035c4bbdfSmrg                grabinfo->sync.other = NullGrab;
186135c4bbdfSmrg            syncEvents.replayDev = thisDev;
186235c4bbdfSmrg            syncEvents.replayWin = grabinfo->grab->window;
186335c4bbdfSmrg            (*grabinfo->DeactivateGrab) (thisDev);
186435c4bbdfSmrg            syncEvents.replayDev = (DeviceIntPtr) NULL;
186535c4bbdfSmrg        }
186635c4bbdfSmrg        break;
186735c4bbdfSmrg    case THAW_OTHERS:          /* AsyncOthers */
186835c4bbdfSmrg        if (othersFrozen) {
186935c4bbdfSmrg            for (dev = inputInfo.devices; dev; dev = dev->next) {
187035c4bbdfSmrg                if (dev == thisDev)
187135c4bbdfSmrg                    continue;
187235c4bbdfSmrg                devgrabinfo = &dev->deviceGrab;
187335c4bbdfSmrg                if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
187435c4bbdfSmrg                    devgrabinfo->sync.state = THAWED;
187535c4bbdfSmrg                if (devgrabinfo->sync.other
187635c4bbdfSmrg                    && SameClient(devgrabinfo->sync.other, client))
187735c4bbdfSmrg                    devgrabinfo->sync.other = NullGrab;
187835c4bbdfSmrg            }
187935c4bbdfSmrg            ComputeFreezes();
188035c4bbdfSmrg        }
188135c4bbdfSmrg        break;
188235c4bbdfSmrg    }
188335c4bbdfSmrg
188435c4bbdfSmrg    /* We've unfrozen the grab. If the grab was a touch grab, we're now the
188535c4bbdfSmrg     * owner and expected to accept/reject it. Reject == ReplayPointer which
188635c4bbdfSmrg     * we've handled in ComputeFreezes() (during DeactivateGrab) above,
188735c4bbdfSmrg     * anything else is accept.
188835c4bbdfSmrg     */
188935c4bbdfSmrg    if (newState != NOT_GRABBED /* Replay */ &&
18905a112b11Smrg        IsTouchEvent(grabinfo->sync.event)) {
18915a112b11Smrg        TouchAcceptAndEnd(thisDev, grabinfo->sync.event->device_event.touchid);
189205b261ecSmrg    }
189305b261ecSmrg}
189405b261ecSmrg
189505b261ecSmrg/**
189605b261ecSmrg * Server-side protocol handling for AllowEvents request.
189705b261ecSmrg *
18984642e01fSmrg * Release some events from a frozen device.
189905b261ecSmrg */
190005b261ecSmrgint
190105b261ecSmrgProcAllowEvents(ClientPtr client)
190205b261ecSmrg{
190335c4bbdfSmrg    TimeStamp time;
190435c4bbdfSmrg    DeviceIntPtr mouse = NULL;
190535c4bbdfSmrg    DeviceIntPtr keybd = NULL;
190635c4bbdfSmrg
190705b261ecSmrg    REQUEST(xAllowEventsReq);
190805b261ecSmrg
190905b261ecSmrg    REQUEST_SIZE_MATCH(xAllowEventsReq);
19107e31ba66Smrg    UpdateCurrentTime();
191105b261ecSmrg    time = ClientTimeToServerTime(stuff->time);
19124642e01fSmrg
19134642e01fSmrg    mouse = PickPointer(client);
19144642e01fSmrg    keybd = PickKeyboard(client);
19154642e01fSmrg
191635c4bbdfSmrg    switch (stuff->mode) {
191735c4bbdfSmrg    case ReplayPointer:
191835c4bbdfSmrg        AllowSome(client, time, mouse, NOT_GRABBED);
191935c4bbdfSmrg        break;
192035c4bbdfSmrg    case SyncPointer:
192135c4bbdfSmrg        AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
192235c4bbdfSmrg        break;
192335c4bbdfSmrg    case AsyncPointer:
192435c4bbdfSmrg        AllowSome(client, time, mouse, THAWED);
192535c4bbdfSmrg        break;
192635c4bbdfSmrg    case ReplayKeyboard:
192735c4bbdfSmrg        AllowSome(client, time, keybd, NOT_GRABBED);
192835c4bbdfSmrg        break;
192935c4bbdfSmrg    case SyncKeyboard:
193035c4bbdfSmrg        AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
193135c4bbdfSmrg        break;
193235c4bbdfSmrg    case AsyncKeyboard:
193335c4bbdfSmrg        AllowSome(client, time, keybd, THAWED);
193435c4bbdfSmrg        break;
193535c4bbdfSmrg    case SyncBoth:
193635c4bbdfSmrg        AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
193735c4bbdfSmrg        break;
193835c4bbdfSmrg    case AsyncBoth:
193935c4bbdfSmrg        AllowSome(client, time, keybd, THAWED_BOTH);
194035c4bbdfSmrg        break;
194135c4bbdfSmrg    default:
194235c4bbdfSmrg        client->errorValue = stuff->mode;
194335c4bbdfSmrg        return BadValue;
194405b261ecSmrg    }
194505b261ecSmrg    return Success;
194605b261ecSmrg}
194705b261ecSmrg
194805b261ecSmrg/**
194905b261ecSmrg * Deactivate grabs from any device that has been grabbed by the client.
195005b261ecSmrg */
195105b261ecSmrgvoid
195205b261ecSmrgReleaseActiveGrabs(ClientPtr client)
195305b261ecSmrg{
195405b261ecSmrg    DeviceIntPtr dev;
195535c4bbdfSmrg    Bool done;
195605b261ecSmrg
195705b261ecSmrg    /* XXX CloseDownClient should remove passive grabs before
195805b261ecSmrg     * releasing active grabs.
195905b261ecSmrg     */
196005b261ecSmrg    do {
196135c4bbdfSmrg        done = TRUE;
196235c4bbdfSmrg        for (dev = inputInfo.devices; dev; dev = dev->next) {
196335c4bbdfSmrg            if (dev->deviceGrab.grab &&
196435c4bbdfSmrg                SameClient(dev->deviceGrab.grab, client)) {
196535c4bbdfSmrg                (*dev->deviceGrab.DeactivateGrab) (dev);
196635c4bbdfSmrg                done = FALSE;
196735c4bbdfSmrg            }
196835c4bbdfSmrg        }
196905b261ecSmrg    } while (!done);
197005b261ecSmrg}
197105b261ecSmrg
197205b261ecSmrg/**************************************************************************
197305b261ecSmrg *            The following procedures deal with delivering events        *
197405b261ecSmrg **************************************************************************/
197505b261ecSmrg
197605b261ecSmrg/**
197705b261ecSmrg * Deliver the given events to the given client.
197805b261ecSmrg *
197905b261ecSmrg * More than one event may be delivered at a time. This is the case with
198005b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events.
198105b261ecSmrg *
198205b261ecSmrg * TryClientEvents() is the last station before actually writing the events to
198305b261ecSmrg * the socket. Anything that is not filtered here, will get delivered to the
19844642e01fSmrg * client.
19854642e01fSmrg * An event is only delivered if
198605b261ecSmrg *   - mask and filter match up.
198705b261ecSmrg *   - no other client has a grab on the device that caused the event.
19884642e01fSmrg *
198905b261ecSmrg *
199005b261ecSmrg * @param client The target client to deliver to.
19914642e01fSmrg * @param dev The device the event came from. May be NULL.
199205b261ecSmrg * @param pEvents The events to be delivered.
199305b261ecSmrg * @param count Number of elements in pEvents.
199405b261ecSmrg * @param mask Event mask as set by the window.
199505b261ecSmrg * @param filter Mask based on event type.
19964642e01fSmrg * @param grab Possible grab on the device that caused the event.
199705b261ecSmrg *
199805b261ecSmrg * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
199905b261ecSmrg * client.
200005b261ecSmrg */
20016747b715Smrgint
200235c4bbdfSmrgTryClientEvents(ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
200335c4bbdfSmrg                int count, Mask mask, Mask filter, GrabPtr grab)
200405b261ecSmrg{
200505b261ecSmrg    int type;
200605b261ecSmrg
200705b261ecSmrg#ifdef DEBUG_EVENTS
20086747b715Smrg    ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s",
20096747b715Smrg           pEvents->u.u.type, pEvents->u.u.detail, mask,
20106747b715Smrg           client ? client->index : -1,
20116747b715Smrg           (client && client->clientGone) ? " (gone)" : "");
201205b261ecSmrg#endif
20136747b715Smrg
20146747b715Smrg    if (!client || client == serverClient || client->clientGone) {
201505b261ecSmrg#ifdef DEBUG_EVENTS
20166747b715Smrg        ErrorF(" not delivered to fake/dead client\n");
201705b261ecSmrg#endif
20186747b715Smrg        return 0;
20196747b715Smrg    }
202005b261ecSmrg
202135c4bbdfSmrg    if (filter != CantBeFiltered && !(mask & filter)) {
202235c4bbdfSmrg#ifdef DEBUG_EVENTS
20236747b715Smrg        ErrorF(" filtered\n");
202435c4bbdfSmrg#endif
20256747b715Smrg        return 0;
20266747b715Smrg    }
202705b261ecSmrg
202835c4bbdfSmrg    if (grab && !SameClient(grab, client)) {
202905b261ecSmrg#ifdef DEBUG_EVENTS
20306747b715Smrg        ErrorF(" not delivered due to grab\n");
203105b261ecSmrg#endif
203235c4bbdfSmrg        return -1;              /* don't send, but notify caller */
203305b261ecSmrg    }
20346747b715Smrg
20356747b715Smrg    type = pEvents->u.u.type;
203635c4bbdfSmrg    if (type == MotionNotify) {
203735c4bbdfSmrg        if (mask & PointerMotionHintMask) {
20386747b715Smrg            if (WID(dev->valuator->motionHintWindow) ==
203935c4bbdfSmrg                pEvents->u.keyButtonPointer.event) {
204005b261ecSmrg#ifdef DEBUG_EVENTS
20416747b715Smrg                ErrorF("[dix] \n");
20426747b715Smrg                ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
204305b261ecSmrg#endif
204435c4bbdfSmrg                return 1;       /* don't send, but pretend we did */
20456747b715Smrg            }
20466747b715Smrg            pEvents->u.u.detail = NotifyHint;
20476747b715Smrg        }
204835c4bbdfSmrg        else {
20496747b715Smrg            pEvents->u.u.detail = NotifyNormal;
20506747b715Smrg        }
20516747b715Smrg    }
205235c4bbdfSmrg    else if (type == DeviceMotionNotify) {
205335c4bbdfSmrg        if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer *) pEvents,
20546747b715Smrg                                            mask) != 0)
20556747b715Smrg            return 1;
205635c4bbdfSmrg    }
205735c4bbdfSmrg    else if (type == KeyPress) {
205835c4bbdfSmrg        if (EventIsKeyRepeat(pEvents)) {
205935c4bbdfSmrg            if (!_XkbWantsDetectableAutoRepeat(client)) {
20606747b715Smrg                xEvent release = *pEvents;
206135c4bbdfSmrg
20626747b715Smrg                release.u.u.type = KeyRelease;
20636747b715Smrg                WriteEventsToClient(client, 1, &release);
20646747b715Smrg#ifdef DEBUG_EVENTS
20656747b715Smrg                ErrorF(" (plus fake core release for repeat)");
20666747b715Smrg#endif
206735c4bbdfSmrg            }
206835c4bbdfSmrg            else {
20696747b715Smrg#ifdef DEBUG_EVENTS
20706747b715Smrg                ErrorF(" (detectable autorepeat for core)");
20716747b715Smrg#endif
20726747b715Smrg            }
20736747b715Smrg        }
20746747b715Smrg
207535c4bbdfSmrg    }
207635c4bbdfSmrg    else if (type == DeviceKeyPress) {
207735c4bbdfSmrg        if (EventIsKeyRepeat(pEvents)) {
207835c4bbdfSmrg            if (!_XkbWantsDetectableAutoRepeat(client)) {
207935c4bbdfSmrg                deviceKeyButtonPointer release =
208035c4bbdfSmrg                    *(deviceKeyButtonPointer *) pEvents;
20816747b715Smrg                release.type = DeviceKeyRelease;
20826747b715Smrg#ifdef DEBUG_EVENTS
20836747b715Smrg                ErrorF(" (plus fake xi1 release for repeat)");
20846747b715Smrg#endif
20856747b715Smrg                WriteEventsToClient(client, 1, (xEvent *) &release);
20866747b715Smrg            }
20876747b715Smrg            else {
20886747b715Smrg#ifdef DEBUG_EVENTS
20896747b715Smrg                ErrorF(" (detectable autorepeat for core)");
20906747b715Smrg#endif
20916747b715Smrg            }
20926747b715Smrg        }
20936747b715Smrg    }
20946747b715Smrg
209535c4bbdfSmrg    if (BitIsOn(criticalEvents, type)) {
20966747b715Smrg        if (client->smart_priority < SMART_MAX_PRIORITY)
20976747b715Smrg            client->smart_priority++;
20986747b715Smrg        SetCriticalOutputPending();
209905b261ecSmrg    }
21006747b715Smrg
21016747b715Smrg    WriteEventsToClient(client, count, pEvents);
21026747b715Smrg#ifdef DEBUG_EVENTS
21036747b715Smrg    ErrorF("[dix]  delivered\n");
21046747b715Smrg#endif
21056747b715Smrg    return 1;
210605b261ecSmrg}
210705b261ecSmrg
210835c4bbdfSmrgstatic BOOL
210935c4bbdfSmrgActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win,
211035c4bbdfSmrg                     xEvent *event, Mask deliveryMask)
211135c4bbdfSmrg{
211235c4bbdfSmrg    GrabPtr tempGrab;
211335c4bbdfSmrg    OtherInputMasks *inputMasks;
211435c4bbdfSmrg    CARD8 type = event->u.u.type;
211535c4bbdfSmrg    enum InputLevel grabtype;
211635c4bbdfSmrg
211735c4bbdfSmrg    if (type == ButtonPress)
211835c4bbdfSmrg        grabtype = CORE;
211935c4bbdfSmrg    else if (type == DeviceButtonPress)
212035c4bbdfSmrg        grabtype = XI;
212135c4bbdfSmrg    else if ((type = xi2_get_type(event)) == XI_ButtonPress)
212235c4bbdfSmrg        grabtype = XI2;
212335c4bbdfSmrg    else
212435c4bbdfSmrg        return FALSE;
212535c4bbdfSmrg
212635c4bbdfSmrg    tempGrab = AllocGrab(NULL);
212735c4bbdfSmrg    if (!tempGrab)
212835c4bbdfSmrg        return FALSE;
212935c4bbdfSmrg    tempGrab->next = NULL;
213035c4bbdfSmrg    tempGrab->device = dev;
213135c4bbdfSmrg    tempGrab->resource = client->clientAsMask;
213235c4bbdfSmrg    tempGrab->window = win;
213335c4bbdfSmrg    tempGrab->ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
213435c4bbdfSmrg    tempGrab->eventMask = deliveryMask;
213535c4bbdfSmrg    tempGrab->keyboardMode = GrabModeAsync;
213635c4bbdfSmrg    tempGrab->pointerMode = GrabModeAsync;
213735c4bbdfSmrg    tempGrab->confineTo = NullWindow;
213835c4bbdfSmrg    tempGrab->cursor = NullCursor;
213935c4bbdfSmrg    tempGrab->type = type;
214035c4bbdfSmrg    tempGrab->grabtype = grabtype;
214135c4bbdfSmrg
214235c4bbdfSmrg    /* get the XI and XI2 device mask */
214335c4bbdfSmrg    inputMasks = wOtherInputMasks(win);
214435c4bbdfSmrg    tempGrab->deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id] : 0;
214535c4bbdfSmrg
214635c4bbdfSmrg    if (inputMasks)
214735c4bbdfSmrg        xi2mask_merge(tempGrab->xi2mask, inputMasks->xi2mask);
214835c4bbdfSmrg
214935c4bbdfSmrg    (*dev->deviceGrab.ActivateGrab) (dev, tempGrab,
215035c4bbdfSmrg                                     currentTime, TRUE | ImplicitGrabMask);
215135c4bbdfSmrg    FreeGrab(tempGrab);
215235c4bbdfSmrg    return TRUE;
215335c4bbdfSmrg}
215435c4bbdfSmrg
215535c4bbdfSmrg/**
215635c4bbdfSmrg * Attempt event delivery to the client owning the window.
215735c4bbdfSmrg */
215835c4bbdfSmrgstatic enum EventDeliveryState
215935c4bbdfSmrgDeliverToWindowOwner(DeviceIntPtr dev, WindowPtr win,
216035c4bbdfSmrg                     xEvent *events, int count, Mask filter, GrabPtr grab)
216135c4bbdfSmrg{
216235c4bbdfSmrg    /* if nobody ever wants to see this event, skip some work */
216335c4bbdfSmrg    if (filter != CantBeFiltered &&
216435c4bbdfSmrg        !((wOtherEventMasks(win) | win->eventMask) & filter))
216535c4bbdfSmrg        return EVENT_SKIP;
216635c4bbdfSmrg
216735c4bbdfSmrg    if (IsInterferingGrab(wClient(win), dev, events))
216835c4bbdfSmrg        return EVENT_SKIP;
216935c4bbdfSmrg
217035c4bbdfSmrg    if (!XaceHook(XACE_RECEIVE_ACCESS, wClient(win), win, events, count)) {
217135c4bbdfSmrg        int attempt = TryClientEvents(wClient(win), dev, events,
217235c4bbdfSmrg                                      count, win->eventMask,
217335c4bbdfSmrg                                      filter, grab);
217435c4bbdfSmrg
217535c4bbdfSmrg        if (attempt > 0)
217635c4bbdfSmrg            return EVENT_DELIVERED;
217735c4bbdfSmrg        if (attempt < 0)
217835c4bbdfSmrg            return EVENT_REJECTED;
217935c4bbdfSmrg    }
218035c4bbdfSmrg
218135c4bbdfSmrg    return EVENT_NOT_DELIVERED;
218235c4bbdfSmrg}
218335c4bbdfSmrg
218435c4bbdfSmrg/**
218535c4bbdfSmrg * Get the list of clients that should be tried for event delivery on the
218635c4bbdfSmrg * given window.
218735c4bbdfSmrg *
218835c4bbdfSmrg * @return 1 if the client list should be traversed, zero if the event
218935c4bbdfSmrg * should be skipped.
219035c4bbdfSmrg */
219135c4bbdfSmrgstatic Bool
219235c4bbdfSmrgGetClientsForDelivery(DeviceIntPtr dev, WindowPtr win,
219335c4bbdfSmrg                      xEvent *events, Mask filter, InputClients ** iclients)
219435c4bbdfSmrg{
219535c4bbdfSmrg    int rc = 0;
219635c4bbdfSmrg
219735c4bbdfSmrg    if (core_get_type(events) != 0)
219835c4bbdfSmrg        *iclients = (InputClients *) wOtherClients(win);
219935c4bbdfSmrg    else if (xi2_get_type(events) != 0) {
220035c4bbdfSmrg        OtherInputMasks *inputMasks = wOtherInputMasks(win);
220135c4bbdfSmrg
220235c4bbdfSmrg        /* Has any client selected for the event? */
220335c4bbdfSmrg        if (!WindowXI2MaskIsset(dev, win, events))
220435c4bbdfSmrg            goto out;
220535c4bbdfSmrg        *iclients = inputMasks->inputClients;
220635c4bbdfSmrg    }
220735c4bbdfSmrg    else {
220835c4bbdfSmrg        OtherInputMasks *inputMasks = wOtherInputMasks(win);
220935c4bbdfSmrg
221035c4bbdfSmrg        /* Has any client selected for the event? */
221135c4bbdfSmrg        if (!inputMasks || !(inputMasks->inputEvents[dev->id] & filter))
221235c4bbdfSmrg            goto out;
221335c4bbdfSmrg
221435c4bbdfSmrg        *iclients = inputMasks->inputClients;
221535c4bbdfSmrg    }
221635c4bbdfSmrg
221735c4bbdfSmrg    rc = 1;
221835c4bbdfSmrg out:
221935c4bbdfSmrg    return rc;
222035c4bbdfSmrg}
222135c4bbdfSmrg
222235c4bbdfSmrg/**
222335c4bbdfSmrg * Try delivery on each client in inputclients, provided the event mask
222435c4bbdfSmrg * accepts it and there is no interfering core grab..
222535c4bbdfSmrg */
222635c4bbdfSmrgstatic enum EventDeliveryState
222735c4bbdfSmrgDeliverEventToInputClients(DeviceIntPtr dev, InputClients * inputclients,
222835c4bbdfSmrg                           WindowPtr win, xEvent *events,
222935c4bbdfSmrg                           int count, Mask filter, GrabPtr grab,
223035c4bbdfSmrg                           ClientPtr *client_return, Mask *mask_return)
223135c4bbdfSmrg{
223235c4bbdfSmrg    int attempt;
223335c4bbdfSmrg    enum EventDeliveryState rc = EVENT_NOT_DELIVERED;
223435c4bbdfSmrg    Bool have_device_button_grab_class_client = FALSE;
223535c4bbdfSmrg
223635c4bbdfSmrg    for (; inputclients; inputclients = inputclients->next) {
223735c4bbdfSmrg        Mask mask;
223835c4bbdfSmrg        ClientPtr client = rClient(inputclients);
223935c4bbdfSmrg
224035c4bbdfSmrg        if (IsInterferingGrab(client, dev, events))
224135c4bbdfSmrg            continue;
224235c4bbdfSmrg
224335c4bbdfSmrg        if (IsWrongPointerBarrierClient(client, dev, events))
224435c4bbdfSmrg            continue;
224535c4bbdfSmrg
224635c4bbdfSmrg        mask = GetEventMask(dev, events, inputclients);
224735c4bbdfSmrg
224835c4bbdfSmrg        if (XaceHook(XACE_RECEIVE_ACCESS, client, win, events, count))
224935c4bbdfSmrg            /* do nothing */ ;
225035c4bbdfSmrg        else if ((attempt = TryClientEvents(client, dev,
225135c4bbdfSmrg                                            events, count,
225235c4bbdfSmrg                                            mask, filter, grab))) {
225335c4bbdfSmrg            if (attempt > 0) {
225435c4bbdfSmrg                /*
225535c4bbdfSmrg                 * The order of clients is arbitrary therefore if one
225635c4bbdfSmrg                 * client belongs to DeviceButtonGrabClass make sure to
225735c4bbdfSmrg                 * catch it.
225835c4bbdfSmrg                 */
225935c4bbdfSmrg                if (!have_device_button_grab_class_client) {
226035c4bbdfSmrg                    rc = EVENT_DELIVERED;
226135c4bbdfSmrg                    *client_return = client;
226235c4bbdfSmrg                    *mask_return = mask;
226335c4bbdfSmrg                    /* Success overrides non-success, so if we've been
226435c4bbdfSmrg                     * successful on one client, return that */
226535c4bbdfSmrg                    if (mask & DeviceButtonGrabMask)
226635c4bbdfSmrg                        have_device_button_grab_class_client = TRUE;
226735c4bbdfSmrg                }
226835c4bbdfSmrg            } else if (rc == EVENT_NOT_DELIVERED)
226935c4bbdfSmrg                rc = EVENT_REJECTED;
227035c4bbdfSmrg        }
227135c4bbdfSmrg    }
227235c4bbdfSmrg
227335c4bbdfSmrg    return rc;
227435c4bbdfSmrg}
227535c4bbdfSmrg
227635c4bbdfSmrg/**
227735c4bbdfSmrg * Deliver events to clients registered on the window.
227835c4bbdfSmrg *
227935c4bbdfSmrg * @param client_return On successful delivery, set to the recipient.
228035c4bbdfSmrg * @param mask_return On successful delivery, set to the recipient's event
228135c4bbdfSmrg * mask for this event.
228235c4bbdfSmrg */
228335c4bbdfSmrgstatic enum EventDeliveryState
228435c4bbdfSmrgDeliverEventToWindowMask(DeviceIntPtr dev, WindowPtr win, xEvent *events,
228535c4bbdfSmrg                         int count, Mask filter, GrabPtr grab,
228635c4bbdfSmrg                         ClientPtr *client_return, Mask *mask_return)
228735c4bbdfSmrg{
228835c4bbdfSmrg    InputClients *iclients;
228935c4bbdfSmrg
229035c4bbdfSmrg    if (!GetClientsForDelivery(dev, win, events, filter, &iclients))
229135c4bbdfSmrg        return EVENT_SKIP;
229235c4bbdfSmrg
229335c4bbdfSmrg    return DeliverEventToInputClients(dev, iclients, win, events, count, filter,
229435c4bbdfSmrg                                      grab, client_return, mask_return);
229535c4bbdfSmrg
229635c4bbdfSmrg}
229735c4bbdfSmrg
229805b261ecSmrg/**
229905b261ecSmrg * Deliver events to a window. At this point, we do not yet know if the event
230005b261ecSmrg * actually needs to be delivered. May activate a grab if the event is a
230105b261ecSmrg * button press.
230205b261ecSmrg *
23034642e01fSmrg * Core events are always delivered to the window owner. If the filter is
23044642e01fSmrg * something other than CantBeFiltered, the event is also delivered to other
23054642e01fSmrg * clients with the matching mask on the window.
23064642e01fSmrg *
230705b261ecSmrg * More than one event may be delivered at a time. This is the case with
230805b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events.
23094642e01fSmrg *
231005b261ecSmrg * @param pWin The window that would get the event.
231105b261ecSmrg * @param pEvents The events to be delivered.
231205b261ecSmrg * @param count Number of elements in pEvents.
231305b261ecSmrg * @param filter Mask based on event type.
23144642e01fSmrg * @param grab Possible grab on the device that caused the event.
231505b261ecSmrg *
231635c4bbdfSmrg * @return a positive number if at least one successful delivery has been
231735c4bbdfSmrg * made, 0 if no events were delivered, or a negative number if the event
231835c4bbdfSmrg * has not been delivered _and_ rejected by at least one client.
231905b261ecSmrg */
232005b261ecSmrgint
23214642e01fSmrgDeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
232235c4bbdfSmrg                      *pEvents, int count, Mask filter, GrabPtr grab)
232305b261ecSmrg{
232405b261ecSmrg    int deliveries = 0, nondeliveries = 0;
232505b261ecSmrg    ClientPtr client = NullClient;
232635c4bbdfSmrg    Mask deliveryMask = 0;      /* If a grab occurs due to a button press, then
232735c4bbdfSmrg                                   this mask is the mask of the grab. */
232805b261ecSmrg    int type = pEvents->u.u.type;
232905b261ecSmrg
23306747b715Smrg    /* Deliver to window owner */
233135c4bbdfSmrg    if ((filter == CantBeFiltered) || core_get_type(pEvents) != 0) {
233235c4bbdfSmrg        enum EventDeliveryState rc;
23334642e01fSmrg
233435c4bbdfSmrg        rc = DeliverToWindowOwner(pDev, pWin, pEvents, count, filter, grab);
23354642e01fSmrg
233635c4bbdfSmrg        switch (rc) {
233735c4bbdfSmrg        case EVENT_SKIP:
233835c4bbdfSmrg            return 0;
233935c4bbdfSmrg        case EVENT_REJECTED:
234035c4bbdfSmrg            nondeliveries--;
234135c4bbdfSmrg            break;
234235c4bbdfSmrg        case EVENT_DELIVERED:
234335c4bbdfSmrg            /* We delivered to the owner, with our event mask */
234435c4bbdfSmrg            deliveries++;
234535c4bbdfSmrg            client = wClient(pWin);
234635c4bbdfSmrg            deliveryMask = pWin->eventMask;
234735c4bbdfSmrg            break;
234835c4bbdfSmrg        case EVENT_NOT_DELIVERED:
234935c4bbdfSmrg            break;
235035c4bbdfSmrg        }
235105b261ecSmrg    }
23526747b715Smrg
23536747b715Smrg    /* CantBeFiltered means only window owner gets the event */
235435c4bbdfSmrg    if (filter != CantBeFiltered) {
235535c4bbdfSmrg        enum EventDeliveryState rc;
235635c4bbdfSmrg
235735c4bbdfSmrg        rc = DeliverEventToWindowMask(pDev, pWin, pEvents, count, filter,
235835c4bbdfSmrg                                      grab, &client, &deliveryMask);
23594642e01fSmrg
236035c4bbdfSmrg        switch (rc) {
236135c4bbdfSmrg        case EVENT_SKIP:
236235c4bbdfSmrg            return 0;
236335c4bbdfSmrg        case EVENT_REJECTED:
236435c4bbdfSmrg            nondeliveries--;
236535c4bbdfSmrg            break;
236635c4bbdfSmrg        case EVENT_DELIVERED:
236735c4bbdfSmrg            deliveries++;
236835c4bbdfSmrg            break;
236935c4bbdfSmrg        case EVENT_NOT_DELIVERED:
237035c4bbdfSmrg            break;
23714642e01fSmrg        }
237235c4bbdfSmrg    }
23734642e01fSmrg
237435c4bbdfSmrg    if (deliveries) {
237535c4bbdfSmrg        /*
237635c4bbdfSmrg         * Note that since core events are delivered first, an implicit grab may
237735c4bbdfSmrg         * be activated on a core grab, stopping the XI events.
237835c4bbdfSmrg         */
237935c4bbdfSmrg        if (!grab &&
238035c4bbdfSmrg            ActivateImplicitGrab(pDev, client, pWin, pEvents, deliveryMask))
238135c4bbdfSmrg            /* grab activated */ ;
238235c4bbdfSmrg        else if (type == MotionNotify)
238335c4bbdfSmrg            pDev->valuator->motionHintWindow = pWin;
238435c4bbdfSmrg        else if (type == DeviceMotionNotify || type == DeviceButtonPress)
238535c4bbdfSmrg            CheckDeviceGrabAndHintWindow(pWin, type,
238635c4bbdfSmrg                                         (deviceKeyButtonPointer *) pEvents,
238735c4bbdfSmrg                                         grab, client, deliveryMask);
238835c4bbdfSmrg        return deliveries;
238935c4bbdfSmrg    }
239035c4bbdfSmrg    return nondeliveries;
239135c4bbdfSmrg}
239235c4bbdfSmrg
239335c4bbdfSmrg/**
239435c4bbdfSmrg * Filter out raw events for XI 2.0 and XI 2.1 clients.
239535c4bbdfSmrg *
239635c4bbdfSmrg * If there is a grab on the device, 2.0 clients only get raw events if they
239735c4bbdfSmrg * have the grab. 2.1+ clients get raw events in all cases.
239835c4bbdfSmrg *
239935c4bbdfSmrg * @return TRUE if the event should be discarded, FALSE otherwise.
240035c4bbdfSmrg */
240135c4bbdfSmrgstatic BOOL
240235c4bbdfSmrgFilterRawEvents(const ClientPtr client, const GrabPtr grab, WindowPtr root)
240335c4bbdfSmrg{
240435c4bbdfSmrg    XIClientPtr client_xi_version;
240535c4bbdfSmrg    int cmp;
24066747b715Smrg
240735c4bbdfSmrg    /* device not grabbed -> don't filter */
240835c4bbdfSmrg    if (!grab)
240935c4bbdfSmrg        return FALSE;
24106747b715Smrg
241135c4bbdfSmrg    client_xi_version =
241235c4bbdfSmrg        dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
241335c4bbdfSmrg
241435c4bbdfSmrg    cmp = version_compare(client_xi_version->major_version,
241535c4bbdfSmrg                          client_xi_version->minor_version, 2, 0);
241635c4bbdfSmrg    /* XI 2.0: if device is grabbed, skip
241735c4bbdfSmrg       XI 2.1: if device is grabbed by us, skip, we've already delivered */
241835c4bbdfSmrg    if (cmp == 0)
241935c4bbdfSmrg        return TRUE;
242035c4bbdfSmrg
242135c4bbdfSmrg    return (grab->window != root) ? FALSE : SameClient(grab, client);
242235c4bbdfSmrg}
242335c4bbdfSmrg
242435c4bbdfSmrg/**
242535c4bbdfSmrg * Deliver a raw event to the grab owner (if any) and to all root windows.
242635c4bbdfSmrg *
242735c4bbdfSmrg * Raw event delivery differs between XI 2.0 and XI 2.1.
242835c4bbdfSmrg * XI 2.0: events delivered to the grabbing client (if any) OR to all root
242935c4bbdfSmrg * windows
243035c4bbdfSmrg * XI 2.1: events delivered to all root windows, regardless of grabbing
243135c4bbdfSmrg * state.
243235c4bbdfSmrg */
243335c4bbdfSmrgvoid
243435c4bbdfSmrgDeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
243535c4bbdfSmrg{
243635c4bbdfSmrg    GrabPtr grab = device->deviceGrab.grab;
243735c4bbdfSmrg    xEvent *xi;
243835c4bbdfSmrg    int i, rc;
243935c4bbdfSmrg    int filter;
244035c4bbdfSmrg
244135c4bbdfSmrg    rc = EventToXI2((InternalEvent *) ev, (xEvent **) &xi);
244235c4bbdfSmrg    if (rc != Success) {
244335c4bbdfSmrg        ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n",
244435c4bbdfSmrg               __func__, device->name, rc);
244535c4bbdfSmrg        return;
244605b261ecSmrg    }
24474642e01fSmrg
244835c4bbdfSmrg    if (grab)
244935c4bbdfSmrg        DeliverGrabbedEvent((InternalEvent *) ev, device, FALSE);
245035c4bbdfSmrg
245135c4bbdfSmrg    filter = GetEventFilter(device, xi);
245235c4bbdfSmrg
245335c4bbdfSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
245435c4bbdfSmrg        WindowPtr root;
245535c4bbdfSmrg        InputClients *inputclients;
245635c4bbdfSmrg
245735c4bbdfSmrg        root = screenInfo.screens[i]->root;
245835c4bbdfSmrg        if (!GetClientsForDelivery(device, root, xi, filter, &inputclients))
245935c4bbdfSmrg            continue;
246035c4bbdfSmrg
246135c4bbdfSmrg        for (; inputclients; inputclients = inputclients->next) {
246235c4bbdfSmrg            ClientPtr c;        /* unused */
246335c4bbdfSmrg            Mask m;             /* unused */
246435c4bbdfSmrg            InputClients ic = *inputclients;
24654642e01fSmrg
246635c4bbdfSmrg            /* Because we run through the list manually, copy the actual
246735c4bbdfSmrg             * list, shorten the copy to only have one client and then pass
246835c4bbdfSmrg             * that down to DeliverEventToInputClients. This way we avoid
246935c4bbdfSmrg             * double events on XI 2.1 clients that have a grab on the
247035c4bbdfSmrg             * device.
247135c4bbdfSmrg             */
247235c4bbdfSmrg            ic.next = NULL;
24736747b715Smrg
247435c4bbdfSmrg            if (!FilterRawEvents(rClient(&ic), grab, root))
247535c4bbdfSmrg                DeliverEventToInputClients(device, &ic, root, xi, 1,
247635c4bbdfSmrg                                           filter, NULL, &c, &m);
247735c4bbdfSmrg        }
247805b261ecSmrg    }
247935c4bbdfSmrg
248035c4bbdfSmrg    free(xi);
248105b261ecSmrg}
248205b261ecSmrg
248305b261ecSmrg/* If the event goes to dontClient, don't send it and return 0.  if
248405b261ecSmrg   send works,  return 1 or if send didn't work, return 2.
248505b261ecSmrg   Only works for core events.
248605b261ecSmrg*/
248705b261ecSmrg
248805b261ecSmrg#ifdef PANORAMIX
24894642e01fSmrgstatic int
249035c4bbdfSmrgXineramaTryClientEventsResult(ClientPtr client,
249135c4bbdfSmrg                              GrabPtr grab, Mask mask, Mask filter)
249235c4bbdfSmrg{
249305b261ecSmrg    if ((client) && (client != serverClient) && (!client->clientGone) &&
249435c4bbdfSmrg        ((filter == CantBeFiltered) || (mask & filter))) {
249535c4bbdfSmrg        if (grab && !SameClient(grab, client))
249635c4bbdfSmrg            return -1;
249735c4bbdfSmrg        else
249835c4bbdfSmrg            return 1;
249905b261ecSmrg    }
250005b261ecSmrg    return 0;
250105b261ecSmrg}
250205b261ecSmrg#endif
250305b261ecSmrg
250405b261ecSmrg/**
250505b261ecSmrg * Try to deliver events to the interested parties.
250605b261ecSmrg *
250705b261ecSmrg * @param pWin The window that would get the event.
250805b261ecSmrg * @param pEvents The events to be delivered.
250905b261ecSmrg * @param count Number of elements in pEvents.
251005b261ecSmrg * @param filter Mask based on event type.
251105b261ecSmrg * @param dontClient Don't deliver to the dontClient.
251205b261ecSmrg */
251305b261ecSmrgint
25144642e01fSmrgMaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
251505b261ecSmrg                           int count, Mask filter, ClientPtr dontClient)
251605b261ecSmrg{
251705b261ecSmrg    OtherClients *other;
251805b261ecSmrg
251935c4bbdfSmrg    if (pWin->eventMask & filter) {
252005b261ecSmrg        if (wClient(pWin) == dontClient)
252135c4bbdfSmrg            return 0;
252205b261ecSmrg#ifdef PANORAMIX
252335c4bbdfSmrg        if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
252435c4bbdfSmrg            return XineramaTryClientEventsResult(wClient(pWin), NullGrab,
252535c4bbdfSmrg                                                 pWin->eventMask, filter);
252605b261ecSmrg#endif
252735c4bbdfSmrg        if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
252835c4bbdfSmrg            return 1;           /* don't send, but pretend we did */
252935c4bbdfSmrg        return TryClientEvents(wClient(pWin), NULL, pEvents, count,
253035c4bbdfSmrg                               pWin->eventMask, filter, NullGrab);
253105b261ecSmrg    }
253235c4bbdfSmrg    for (other = wOtherClients(pWin); other; other = other->next) {
253335c4bbdfSmrg        if (other->mask & filter) {
253405b261ecSmrg            if (SameClient(other, dontClient))
253535c4bbdfSmrg                return 0;
253605b261ecSmrg#ifdef PANORAMIX
253735c4bbdfSmrg            if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
253835c4bbdfSmrg                return XineramaTryClientEventsResult(rClient(other), NullGrab,
253935c4bbdfSmrg                                                     other->mask, filter);
254005b261ecSmrg#endif
254135c4bbdfSmrg            if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents,
254235c4bbdfSmrg                         count))
254335c4bbdfSmrg                return 1;       /* don't send, but pretend we did */
254435c4bbdfSmrg            return TryClientEvents(rClient(other), NULL, pEvents, count,
254535c4bbdfSmrg                                   other->mask, filter, NullGrab);
254635c4bbdfSmrg        }
254705b261ecSmrg    }
254805b261ecSmrg    return 2;
254905b261ecSmrg}
255005b261ecSmrg
255135c4bbdfSmrgstatic Window
255235c4bbdfSmrgFindChildForEvent(SpritePtr pSprite, WindowPtr event)
25536747b715Smrg{
255435c4bbdfSmrg    WindowPtr w = DeepestSpriteWin(pSprite);
25556747b715Smrg    Window child = None;
25566747b715Smrg
25576747b715Smrg    /* If the search ends up past the root should the child field be
25586747b715Smrg       set to none or should the value in the argument be passed
25596747b715Smrg       through. It probably doesn't matter since everyone calls
25606747b715Smrg       this function with child == None anyway. */
256135c4bbdfSmrg    while (w) {
25626747b715Smrg        /* If the source window is same as event window, child should be
25636747b715Smrg           none.  Don't bother going all all the way back to the root. */
25646747b715Smrg
256535c4bbdfSmrg        if (w == event) {
25666747b715Smrg            child = None;
25676747b715Smrg            break;
25686747b715Smrg        }
25696747b715Smrg
257035c4bbdfSmrg        if (w->parent == event) {
25716747b715Smrg            child = w->drawable.id;
25726747b715Smrg            break;
25736747b715Smrg        }
25746747b715Smrg        w = w->parent;
25756747b715Smrg    }
25766747b715Smrg    return child;
25776747b715Smrg}
25786747b715Smrg
25795a112b11Smrgstatic void
25805a112b11SmrgFixUpXI2DeviceEventFromWindow(SpritePtr pSprite, int evtype,
25815a112b11Smrg                              xXIDeviceEvent *event, WindowPtr pWin, Window child)
25825a112b11Smrg{
25835a112b11Smrg    event->root = RootWindow(pSprite)->drawable.id;
25845a112b11Smrg    event->event = pWin->drawable.id;
25855a112b11Smrg
25865a112b11Smrg    if (evtype == XI_TouchOwnership) {
25875a112b11Smrg        event->child = child;
25885a112b11Smrg        return;
25895a112b11Smrg    }
25905a112b11Smrg
25915a112b11Smrg    if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
25925a112b11Smrg        event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x);
25935a112b11Smrg        event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y);
25945a112b11Smrg        event->child = child;
25955a112b11Smrg    }
25965a112b11Smrg    else {
25975a112b11Smrg        event->event_x = 0;
25985a112b11Smrg        event->event_y = 0;
25995a112b11Smrg        event->child = None;
26005a112b11Smrg    }
26015a112b11Smrg
26025a112b11Smrg    if (event->evtype == XI_Enter || event->evtype == XI_Leave ||
26035a112b11Smrg        event->evtype == XI_FocusIn || event->evtype == XI_FocusOut)
26045a112b11Smrg        ((xXIEnterEvent *) event)->same_screen =
26055a112b11Smrg            (pSprite->hot.pScreen == pWin->drawable.pScreen);
26065a112b11Smrg}
26075a112b11Smrg
26085a112b11Smrgstatic void
26095a112b11SmrgFixUpXI2PinchEventFromWindow(SpritePtr pSprite, xXIGesturePinchEvent *event,
26105a112b11Smrg                             WindowPtr pWin, Window child)
26115a112b11Smrg{
26125a112b11Smrg    event->root = RootWindow(pSprite)->drawable.id;
26135a112b11Smrg    event->event = pWin->drawable.id;
26145a112b11Smrg
26155a112b11Smrg    if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
26165a112b11Smrg        event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x);
26175a112b11Smrg        event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y);
26185a112b11Smrg        event->child = child;
26195a112b11Smrg    }
26205a112b11Smrg    else {
26215a112b11Smrg        event->event_x = 0;
26225a112b11Smrg        event->event_y = 0;
26235a112b11Smrg        event->child = None;
26245a112b11Smrg    }
26255a112b11Smrg}
26265a112b11Smrg
26275a112b11Smrgstatic void
26285a112b11SmrgFixUpXI2SwipeEventFromWindow(SpritePtr pSprite, xXIGestureSwipeEvent *event,
26295a112b11Smrg                             WindowPtr pWin, Window child)
26305a112b11Smrg{
26315a112b11Smrg    event->root = RootWindow(pSprite)->drawable.id;
26325a112b11Smrg    event->event = pWin->drawable.id;
26335a112b11Smrg
26345a112b11Smrg    if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
26355a112b11Smrg        event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x);
26365a112b11Smrg        event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y);
26375a112b11Smrg        event->child = child;
26385a112b11Smrg    }
26395a112b11Smrg    else {
26405a112b11Smrg        event->event_x = 0;
26415a112b11Smrg        event->event_y = 0;
26425a112b11Smrg        event->child = None;
26435a112b11Smrg    }
26445a112b11Smrg}
26455a112b11Smrg
264605b261ecSmrg/**
264705b261ecSmrg * Adjust event fields to comply with the window properties.
264805b261ecSmrg *
264905b261ecSmrg * @param xE Event to be modified in place
265005b261ecSmrg * @param pWin The window to get the information from.
265105b261ecSmrg * @param child Child window setting for event (if applicable)
265205b261ecSmrg * @param calcChild If True, calculate the child window.
265305b261ecSmrg */
26546747b715Smrgvoid
265535c4bbdfSmrgFixUpEventFromWindow(SpritePtr pSprite,
265635c4bbdfSmrg                     xEvent *xE, WindowPtr pWin, Window child, Bool calcChild)
265705b261ecSmrg{
265835c4bbdfSmrg    int evtype;
265935c4bbdfSmrg
266005b261ecSmrg    if (calcChild)
26619ace9065Smrg        child = FindChildForEvent(pSprite, pWin);
26626747b715Smrg
266335c4bbdfSmrg    if ((evtype = xi2_get_type(xE))) {
266435c4bbdfSmrg        switch (evtype) {
266535c4bbdfSmrg        case XI_RawKeyPress:
266635c4bbdfSmrg        case XI_RawKeyRelease:
266735c4bbdfSmrg        case XI_RawButtonPress:
266835c4bbdfSmrg        case XI_RawButtonRelease:
266935c4bbdfSmrg        case XI_RawMotion:
267035c4bbdfSmrg        case XI_RawTouchBegin:
267135c4bbdfSmrg        case XI_RawTouchUpdate:
267235c4bbdfSmrg        case XI_RawTouchEnd:
267335c4bbdfSmrg        case XI_DeviceChanged:
267435c4bbdfSmrg        case XI_HierarchyChanged:
267535c4bbdfSmrg        case XI_PropertyEvent:
267635c4bbdfSmrg        case XI_BarrierHit:
267735c4bbdfSmrg        case XI_BarrierLeave:
26786747b715Smrg            return;
26795a112b11Smrg        case XI_GesturePinchBegin:
26805a112b11Smrg        case XI_GesturePinchUpdate:
26815a112b11Smrg        case XI_GesturePinchEnd:
26825a112b11Smrg            FixUpXI2PinchEventFromWindow(pSprite,
26835a112b11Smrg                                         (xXIGesturePinchEvent*) xE, pWin, child);
26845a112b11Smrg            break;
26855a112b11Smrg        case XI_GestureSwipeBegin:
26865a112b11Smrg        case XI_GestureSwipeUpdate:
26875a112b11Smrg        case XI_GestureSwipeEnd:
26885a112b11Smrg            FixUpXI2SwipeEventFromWindow(pSprite,
26895a112b11Smrg                                         (xXIGestureSwipeEvent*) xE, pWin, child);
26905a112b11Smrg            break;
269135c4bbdfSmrg        default:
26925a112b11Smrg            FixUpXI2DeviceEventFromWindow(pSprite, evtype,
26935a112b11Smrg                                          (xXIDeviceEvent*) xE, pWin, child);
269435c4bbdfSmrg            break;
269535c4bbdfSmrg        }
269635c4bbdfSmrg    }
269735c4bbdfSmrg    else {
26989ace9065Smrg        XE_KBPTR.root = RootWindow(pSprite)->drawable.id;
26996747b715Smrg        XE_KBPTR.event = pWin->drawable.id;
270035c4bbdfSmrg        if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
27016747b715Smrg            XE_KBPTR.sameScreen = xTrue;
27026747b715Smrg            XE_KBPTR.child = child;
270335c4bbdfSmrg            XE_KBPTR.eventX = XE_KBPTR.rootX - pWin->drawable.x;
270435c4bbdfSmrg            XE_KBPTR.eventY = XE_KBPTR.rootY - pWin->drawable.y;
27056747b715Smrg        }
270635c4bbdfSmrg        else {
27076747b715Smrg            XE_KBPTR.sameScreen = xFalse;
27086747b715Smrg            XE_KBPTR.child = None;
27096747b715Smrg            XE_KBPTR.eventX = 0;
27106747b715Smrg            XE_KBPTR.eventY = 0;
27116747b715Smrg        }
271205b261ecSmrg    }
271305b261ecSmrg}
271405b261ecSmrg
27156747b715Smrg/**
27166747b715Smrg * Check if a given event is deliverable at all on a given window.
27176747b715Smrg *
27186747b715Smrg * This function only checks if any client wants it, not for a specific
27196747b715Smrg * client.
27206747b715Smrg *
27216747b715Smrg * @param[in] dev The device this event is being sent for.
272235c4bbdfSmrg * @param[in] evtype The event type of the event that is to be sent.
27236747b715Smrg * @param[in] win The current event window.
27246747b715Smrg *
272535c4bbdfSmrg * @return Bitmask of ::EVENT_XI2_MASK, ::EVENT_XI1_MASK, ::EVENT_CORE_MASK, and
272635c4bbdfSmrg *         ::EVENT_DONT_PROPAGATE_MASK.
27276747b715Smrg */
27289ace9065Smrgint
272935c4bbdfSmrgEventIsDeliverable(DeviceIntPtr dev, int evtype, WindowPtr win)
27306747b715Smrg{
27316747b715Smrg    int rc = 0;
27326747b715Smrg    int filter = 0;
27336747b715Smrg    int type;
27346747b715Smrg    OtherInputMasks *inputMasks = wOtherInputMasks(win);
273535c4bbdfSmrg
273635c4bbdfSmrg    if ((type = GetXI2Type(evtype)) != 0) {
273735c4bbdfSmrg        if (inputMasks && xi2mask_isset(inputMasks->xi2mask, dev, type))
273835c4bbdfSmrg            rc |= EVENT_XI2_MASK;
273935c4bbdfSmrg    }
274035c4bbdfSmrg
274135c4bbdfSmrg    if ((type = GetXIType(evtype)) != 0) {
274235c4bbdfSmrg        filter = event_get_filter_from_type(dev, type);
274335c4bbdfSmrg
274435c4bbdfSmrg        /* Check for XI mask */
274535c4bbdfSmrg        if (inputMasks &&
274635c4bbdfSmrg            (inputMasks->deliverableEvents[dev->id] & filter) &&
274735c4bbdfSmrg            (inputMasks->inputEvents[dev->id] & filter))
274835c4bbdfSmrg            rc |= EVENT_XI1_MASK;
274935c4bbdfSmrg
275035c4bbdfSmrg        /* Check for XI DontPropagate mask */
275135c4bbdfSmrg        if (inputMasks && (inputMasks->dontPropagateMask[dev->id] & filter))
275235c4bbdfSmrg            rc |= EVENT_DONT_PROPAGATE_MASK;
275335c4bbdfSmrg
275435c4bbdfSmrg    }
275535c4bbdfSmrg
275635c4bbdfSmrg    if ((type = GetCoreType(evtype)) != 0) {
275735c4bbdfSmrg        filter = event_get_filter_from_type(dev, type);
275835c4bbdfSmrg
275935c4bbdfSmrg        /* Check for core mask */
276035c4bbdfSmrg        if ((win->deliverableEvents & filter) &&
276135c4bbdfSmrg            ((wOtherEventMasks(win) | win->eventMask) & filter))
276235c4bbdfSmrg            rc |= EVENT_CORE_MASK;
276335c4bbdfSmrg
276435c4bbdfSmrg        /* Check for core DontPropagate mask */
276535c4bbdfSmrg        if (filter & wDontPropagateMask(win))
276635c4bbdfSmrg            rc |= EVENT_DONT_PROPAGATE_MASK;
276735c4bbdfSmrg    }
27686747b715Smrg
27696747b715Smrg    return rc;
27706747b715Smrg}
27716747b715Smrg
277235c4bbdfSmrgstatic int
277335c4bbdfSmrgDeliverEvent(DeviceIntPtr dev, xEvent *xE, int count,
277435c4bbdfSmrg             WindowPtr win, Window child, GrabPtr grab)
277535c4bbdfSmrg{
277635c4bbdfSmrg    SpritePtr pSprite = dev->spriteInfo->sprite;
277735c4bbdfSmrg    Mask filter;
277835c4bbdfSmrg    int deliveries = 0;
277935c4bbdfSmrg
278035c4bbdfSmrg    if (XaceHook(XACE_SEND_ACCESS, NULL, dev, win, xE, count) == Success) {
278135c4bbdfSmrg        filter = GetEventFilter(dev, xE);
278235c4bbdfSmrg        FixUpEventFromWindow(pSprite, xE, win, child, FALSE);
278335c4bbdfSmrg        deliveries = DeliverEventsToWindow(dev, win, xE, count, filter, grab);
278435c4bbdfSmrg    }
278535c4bbdfSmrg
278635c4bbdfSmrg    return deliveries;
278735c4bbdfSmrg}
278835c4bbdfSmrg
278935c4bbdfSmrgstatic int
279035c4bbdfSmrgDeliverOneEvent(InternalEvent *event, DeviceIntPtr dev, enum InputLevel level,
279135c4bbdfSmrg                WindowPtr win, Window child, GrabPtr grab)
279235c4bbdfSmrg{
279335c4bbdfSmrg    xEvent *xE = NULL;
279435c4bbdfSmrg    int count = 0;
279535c4bbdfSmrg    int deliveries = 0;
279635c4bbdfSmrg    int rc;
279735c4bbdfSmrg
279835c4bbdfSmrg    switch (level) {
279935c4bbdfSmrg    case XI2:
280035c4bbdfSmrg        rc = EventToXI2(event, &xE);
280135c4bbdfSmrg        count = 1;
280235c4bbdfSmrg        break;
280335c4bbdfSmrg    case XI:
280435c4bbdfSmrg        rc = EventToXI(event, &xE, &count);
280535c4bbdfSmrg        break;
280635c4bbdfSmrg    case CORE:
280735c4bbdfSmrg        rc = EventToCore(event, &xE, &count);
280835c4bbdfSmrg        break;
280935c4bbdfSmrg    default:
281035c4bbdfSmrg        rc = BadImplementation;
281135c4bbdfSmrg        break;
281235c4bbdfSmrg    }
281335c4bbdfSmrg
281435c4bbdfSmrg    if (rc == Success) {
281535c4bbdfSmrg        deliveries = DeliverEvent(dev, xE, count, win, child, grab);
281635c4bbdfSmrg        free(xE);
281735c4bbdfSmrg    }
281835c4bbdfSmrg    else
281935c4bbdfSmrg        BUG_WARN_MSG(rc != BadMatch,
282035c4bbdfSmrg                     "%s: conversion to level %d failed with rc %d\n",
282135c4bbdfSmrg                     dev->name, level, rc);
282235c4bbdfSmrg    return deliveries;
282335c4bbdfSmrg}
282435c4bbdfSmrg
28256747b715Smrg/**
28266747b715Smrg * Deliver events caused by input devices.
28276747b715Smrg *
28284642e01fSmrg * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is
28294642e01fSmrg * called directly from the processInputProc.
28304642e01fSmrg * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call
28314642e01fSmrg * DeliverDeviceEvents.
28324642e01fSmrg * For focused events, DeliverFocusedEvent is called first, and _may_ call
28334642e01fSmrg * DeliverDeviceEvents.
283405b261ecSmrg *
283505b261ecSmrg * @param pWin Window to deliver event to.
28366747b715Smrg * @param event The events to deliver, not yet in wire format.
283705b261ecSmrg * @param grab Possible grab on a device.
283805b261ecSmrg * @param stopAt Don't recurse up to the root window.
283905b261ecSmrg * @param dev The device that is responsible for the event.
284005b261ecSmrg *
28414642e01fSmrg * @see DeliverGrabbedEvent
28424642e01fSmrg * @see DeliverFocusedEvent
284305b261ecSmrg */
284405b261ecSmrgint
28456747b715SmrgDeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
28466747b715Smrg                    WindowPtr stopAt, DeviceIntPtr dev)
284705b261ecSmrg{
284805b261ecSmrg    Window child = None;
284905b261ecSmrg    int deliveries = 0;
285035c4bbdfSmrg    int mask;
28514642e01fSmrg
285235c4bbdfSmrg    verify_internal_event(event);
28534642e01fSmrg
285435c4bbdfSmrg    while (pWin) {
285535c4bbdfSmrg        if ((mask = EventIsDeliverable(dev, event->any.type, pWin))) {
28566747b715Smrg            /* XI2 events first */
285735c4bbdfSmrg            if (mask & EVENT_XI2_MASK) {
285835c4bbdfSmrg                deliveries =
285935c4bbdfSmrg                    DeliverOneEvent(event, dev, XI2, pWin, child, grab);
286035c4bbdfSmrg                if (deliveries > 0)
286135c4bbdfSmrg                    break;
28624642e01fSmrg            }
28634642e01fSmrg
28646747b715Smrg            /* XI events */
286535c4bbdfSmrg            if (mask & EVENT_XI1_MASK) {
286635c4bbdfSmrg                deliveries = DeliverOneEvent(event, dev, XI, pWin, child, grab);
286735c4bbdfSmrg                if (deliveries > 0)
286835c4bbdfSmrg                    break;
28696747b715Smrg            }
28704642e01fSmrg
28716747b715Smrg            /* Core event */
287235c4bbdfSmrg            if ((mask & EVENT_CORE_MASK) && IsMaster(dev) && dev->coreEvents) {
287335c4bbdfSmrg                deliveries =
287435c4bbdfSmrg                    DeliverOneEvent(event, dev, CORE, pWin, child, grab);
287535c4bbdfSmrg                if (deliveries > 0)
287635c4bbdfSmrg                    break;
28774642e01fSmrg            }
28784642e01fSmrg
287935c4bbdfSmrg        }
288035c4bbdfSmrg
288135c4bbdfSmrg        if ((deliveries < 0) || (pWin == stopAt) ||
288235c4bbdfSmrg            (mask & EVENT_DONT_PROPAGATE_MASK)) {
288335c4bbdfSmrg            deliveries = 0;
288435c4bbdfSmrg            break;
28854642e01fSmrg        }
28864642e01fSmrg
28874642e01fSmrg        child = pWin->drawable.id;
28884642e01fSmrg        pWin = pWin->parent;
288905b261ecSmrg    }
28904642e01fSmrg
28916747b715Smrg    return deliveries;
289205b261ecSmrg}
289305b261ecSmrg
289405b261ecSmrg/**
28955a112b11Smrg * Deliver event to a window and its immediate parent. Used for most window
289605b261ecSmrg * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
28974642e01fSmrg * propagate up the tree or extension events
289805b261ecSmrg *
289905b261ecSmrg * In case of a ReparentNotify event, the event will be delivered to the
290005b261ecSmrg * otherParent as well.
290105b261ecSmrg *
290205b261ecSmrg * @param pWin Window to deliver events to.
290305b261ecSmrg * @param xE Events to deliver.
290405b261ecSmrg * @param count number of events in xE.
290505b261ecSmrg * @param otherParent Used for ReparentNotify events.
290605b261ecSmrg */
29076747b715Smrgint
290835c4bbdfSmrgDeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent)
290905b261ecSmrg{
29106747b715Smrg    DeviceIntRec dummy;
291135c4bbdfSmrg    int deliveries;
291205b261ecSmrg
291305b261ecSmrg#ifdef PANORAMIX
291435c4bbdfSmrg    if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
291535c4bbdfSmrg        return count;
291605b261ecSmrg#endif
291705b261ecSmrg
291805b261ecSmrg    if (!count)
291935c4bbdfSmrg        return 0;
29206747b715Smrg
29216747b715Smrg    dummy.id = XIAllDevices;
292235c4bbdfSmrg
292335c4bbdfSmrg    switch (xE->u.u.type) {
292435c4bbdfSmrg    case DestroyNotify:
292535c4bbdfSmrg    case UnmapNotify:
292635c4bbdfSmrg    case MapNotify:
292735c4bbdfSmrg    case MapRequest:
292835c4bbdfSmrg    case ReparentNotify:
292935c4bbdfSmrg    case ConfigureNotify:
293035c4bbdfSmrg    case ConfigureRequest:
293135c4bbdfSmrg    case GravityNotify:
293235c4bbdfSmrg    case CirculateNotify:
293335c4bbdfSmrg    case CirculateRequest:
293435c4bbdfSmrg        xE->u.destroyNotify.event = pWin->drawable.id;
293535c4bbdfSmrg        break;
293635c4bbdfSmrg    }
293735c4bbdfSmrg
293835c4bbdfSmrg    switch (xE->u.u.type) {
293935c4bbdfSmrg    case DestroyNotify:
294035c4bbdfSmrg    case UnmapNotify:
294135c4bbdfSmrg    case MapNotify:
294235c4bbdfSmrg    case ReparentNotify:
294335c4bbdfSmrg    case ConfigureNotify:
294435c4bbdfSmrg    case GravityNotify:
294535c4bbdfSmrg    case CirculateNotify:
294635c4bbdfSmrg        break;
294735c4bbdfSmrg    default:
294835c4bbdfSmrg    {
294935c4bbdfSmrg        Mask filter;
295035c4bbdfSmrg
295135c4bbdfSmrg        filter = GetEventFilter(&dummy, xE);
295235c4bbdfSmrg        return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab);
295335c4bbdfSmrg    }
295435c4bbdfSmrg    }
295535c4bbdfSmrg
29566747b715Smrg    deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count,
29576747b715Smrg                                       StructureNotifyMask, NullGrab);
295835c4bbdfSmrg    if (pWin->parent) {
295935c4bbdfSmrg        xE->u.destroyNotify.event = pWin->parent->drawable.id;
296035c4bbdfSmrg        deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count,
296135c4bbdfSmrg                                            SubstructureNotifyMask, NullGrab);
296235c4bbdfSmrg        if (xE->u.u.type == ReparentNotify) {
296335c4bbdfSmrg            xE->u.destroyNotify.event = otherParent->drawable.id;
29646747b715Smrg            deliveries += DeliverEventsToWindow(&dummy,
296535c4bbdfSmrg                                                otherParent, xE, count,
296635c4bbdfSmrg                                                SubstructureNotifyMask,
296735c4bbdfSmrg                                                NullGrab);
296835c4bbdfSmrg        }
296905b261ecSmrg    }
297005b261ecSmrg    return deliveries;
297105b261ecSmrg}
297205b261ecSmrg
297335c4bbdfSmrgBool
297405b261ecSmrgPointInBorderSize(WindowPtr pWin, int x, int y)
297505b261ecSmrg{
297605b261ecSmrg    BoxRec box;
297705b261ecSmrg
297835c4bbdfSmrg    if (RegionContainsPoint(&pWin->borderSize, x, y, &box))
297935c4bbdfSmrg        return TRUE;
298005b261ecSmrg
298105b261ecSmrg#ifdef PANORAMIX
298235c4bbdfSmrg    if (!noPanoramiXExtension &&
298335c4bbdfSmrg        XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
298435c4bbdfSmrg        SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
298535c4bbdfSmrg        int i;
298635c4bbdfSmrg
298735c4bbdfSmrg        FOR_NSCREENS_FORWARD_SKIP(i) {
298835c4bbdfSmrg            if (RegionContainsPoint(&pSprite->windows[i]->borderSize,
298935c4bbdfSmrg                                    x + screenInfo.screens[0]->x -
299035c4bbdfSmrg                                    screenInfo.screens[i]->x,
299135c4bbdfSmrg                                    y + screenInfo.screens[0]->y -
299235c4bbdfSmrg                                    screenInfo.screens[i]->y, &box))
299335c4bbdfSmrg                return TRUE;
299435c4bbdfSmrg        }
299505b261ecSmrg    }
299605b261ecSmrg#endif
299705b261ecSmrg    return FALSE;
299805b261ecSmrg}
299905b261ecSmrg
300005b261ecSmrg/**
300105b261ecSmrg * Traversed from the root window to the window at the position x/y. While
300205b261ecSmrg * traversing, it sets up the traversal history in the spriteTrace array.
300305b261ecSmrg * After completing, the spriteTrace history is set in the following way:
300405b261ecSmrg *   spriteTrace[0] ... root window
300505b261ecSmrg *   spriteTrace[1] ... top level window that encloses x/y
300605b261ecSmrg *       ...
300705b261ecSmrg *   spriteTrace[spriteTraceGood - 1] ... window at x/y
300805b261ecSmrg *
300905b261ecSmrg * @returns the window at the given coordinates.
301005b261ecSmrg */
30119ace9065SmrgWindowPtr
30129ace9065SmrgXYToWindow(SpritePtr pSprite, int x, int y)
301305b261ecSmrg{
301435c4bbdfSmrg    ScreenPtr pScreen = RootWindow(pSprite)->drawable.pScreen;
301505b261ecSmrg
301635c4bbdfSmrg    return (*pScreen->XYToWindow)(pScreen, pSprite, x, y);
301705b261ecSmrg}
301805b261ecSmrg
30196747b715Smrg/**
30206747b715Smrg * Ungrab a currently FocusIn grabbed device and grab the device on the
30216747b715Smrg * given window. If the win given is the NoneWin, the device is ungrabbed if
30226747b715Smrg * applicable and FALSE is returned.
30236747b715Smrg *
30246747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise.
30256747b715Smrg */
30266747b715SmrgBOOL
30276747b715SmrgActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
30286747b715Smrg{
30296747b715Smrg    BOOL rc = FALSE;
30305a112b11Smrg    InternalEvent event;
30316747b715Smrg
303235c4bbdfSmrg    if (dev->deviceGrab.grab) {
30339ace9065Smrg        if (!dev->deviceGrab.fromPassiveGrab ||
30347e31ba66Smrg            dev->deviceGrab.grab->type != XI_FocusIn ||
30359ace9065Smrg            dev->deviceGrab.grab->window == win ||
30366747b715Smrg            IsParent(dev->deviceGrab.grab->window, win))
30376747b715Smrg            return FALSE;
30386747b715Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
303935c4bbdfSmrg        (*dev->deviceGrab.DeactivateGrab) (dev);
30406747b715Smrg    }
30416747b715Smrg
30426747b715Smrg    if (win == NoneWin || win == PointerRootWin)
30436747b715Smrg        return FALSE;
30446747b715Smrg
30455a112b11Smrg    event = (InternalEvent) {
30465a112b11Smrg        .device_event.header = ET_Internal,
30475a112b11Smrg        .device_event.type = ET_FocusIn,
30485a112b11Smrg        .device_event.length = sizeof(DeviceEvent),
30495a112b11Smrg        .device_event.time = GetTimeInMillis(),
30505a112b11Smrg        .device_event.deviceid = dev->id,
30515a112b11Smrg        .device_event.sourceid = dev->id,
30525a112b11Smrg        .device_event.detail.button = 0
305335c4bbdfSmrg    };
30545a112b11Smrg    rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE,
305535c4bbdfSmrg                                    TRUE) != NULL);
30566747b715Smrg    if (rc)
30577e31ba66Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
30586747b715Smrg    return rc;
30596747b715Smrg}
30606747b715Smrg
30616747b715Smrg/**
30626747b715Smrg * Ungrab a currently Enter grabbed device and grab the device for the given
30636747b715Smrg * window.
30646747b715Smrg *
30656747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise.
30666747b715Smrg */
30676747b715Smrgstatic BOOL
30686747b715SmrgActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
30696747b715Smrg{
30706747b715Smrg    BOOL rc = FALSE;
30715a112b11Smrg    InternalEvent event;
30726747b715Smrg
307335c4bbdfSmrg    if (dev->deviceGrab.grab) {
30749ace9065Smrg        if (!dev->deviceGrab.fromPassiveGrab ||
30759ace9065Smrg            dev->deviceGrab.grab->type != XI_Enter ||
30769ace9065Smrg            dev->deviceGrab.grab->window == win ||
30776747b715Smrg            IsParent(dev->deviceGrab.grab->window, win))
30786747b715Smrg            return FALSE;
30796747b715Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
308035c4bbdfSmrg        (*dev->deviceGrab.DeactivateGrab) (dev);
308135c4bbdfSmrg    }
308235c4bbdfSmrg
30835a112b11Smrg    event = (InternalEvent) {
30845a112b11Smrg        .device_event.header = ET_Internal,
30855a112b11Smrg        .device_event.type = ET_Enter,
30865a112b11Smrg        .device_event.length = sizeof(DeviceEvent),
30875a112b11Smrg        .device_event.time = GetTimeInMillis(),
30885a112b11Smrg        .device_event.deviceid = dev->id,
30895a112b11Smrg        .device_event.sourceid = dev->id,
30905a112b11Smrg        .device_event.detail.button = 0
309135c4bbdfSmrg    };
30925a112b11Smrg    rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE,
309335c4bbdfSmrg                                    TRUE) != NULL);
30946747b715Smrg    if (rc)
30956747b715Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
30966747b715Smrg    return rc;
30976747b715Smrg}
30986747b715Smrg
309905b261ecSmrg/**
310005b261ecSmrg * Update the sprite coordinates based on the event. Update the cursor
310105b261ecSmrg * position, then update the event with the new coordinates that may have been
310205b261ecSmrg * changed. If the window underneath the sprite has changed, change to new
310305b261ecSmrg * cursor and send enter/leave events.
31044642e01fSmrg *
31054642e01fSmrg * CheckMotion() will not do anything and return FALSE if the event is not a
31064642e01fSmrg * pointer event.
31074642e01fSmrg *
31084642e01fSmrg * @return TRUE if the sprite has moved or FALSE otherwise.
310905b261ecSmrg */
31104642e01fSmrgBool
31116747b715SmrgCheckMotion(DeviceEvent *ev, DeviceIntPtr pDev)
311205b261ecSmrg{
31136747b715Smrg    WindowPtr prevSpriteWin, newSpriteWin;
31144642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
31154642e01fSmrg
311635c4bbdfSmrg    verify_internal_event((InternalEvent *) ev);
311705b261ecSmrg
31186747b715Smrg    prevSpriteWin = pSprite->win;
311905b261ecSmrg
312035c4bbdfSmrg    if (ev && !syncEvents.playingEvents) {
31214642e01fSmrg        /* GetPointerEvents() guarantees that pointer events have the correct
31224642e01fSmrg           rootX/Y set already. */
312335c4bbdfSmrg        switch (ev->type) {
312435c4bbdfSmrg        case ET_ButtonPress:
312535c4bbdfSmrg        case ET_ButtonRelease:
312635c4bbdfSmrg        case ET_Motion:
312735c4bbdfSmrg        case ET_TouchBegin:
312835c4bbdfSmrg        case ET_TouchUpdate:
312935c4bbdfSmrg        case ET_TouchEnd:
313035c4bbdfSmrg            break;
313135c4bbdfSmrg        default:
313235c4bbdfSmrg            /* all other events return FALSE */
313335c4bbdfSmrg            return FALSE;
31344642e01fSmrg        }
31354642e01fSmrg
31366747b715Smrg#ifdef PANORAMIX
313735c4bbdfSmrg        if (!noPanoramiXExtension) {
31386747b715Smrg            /* Motion events entering DIX get translated to Screen 0
31396747b715Smrg               coordinates.  Replayed events have already been
31406747b715Smrg               translated since they've entered DIX before */
31416747b715Smrg            ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
31426747b715Smrg            ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
314335c4bbdfSmrg        }
314435c4bbdfSmrg        else
31456747b715Smrg#endif
31466747b715Smrg        {
314735c4bbdfSmrg            if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen) {
31486747b715Smrg                pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
31499ace9065Smrg                RootWindow(pDev->spriteInfo->sprite) =
31509ace9065Smrg                    pSprite->hot.pScreen->root;
31516747b715Smrg            }
31524642e01fSmrg        }
31536747b715Smrg
31546747b715Smrg        pSprite->hot.x = ev->root_x;
31556747b715Smrg        pSprite->hot.y = ev->root_y;
31564642e01fSmrg        if (pSprite->hot.x < pSprite->physLimits.x1)
31574642e01fSmrg            pSprite->hot.x = pSprite->physLimits.x1;
31584642e01fSmrg        else if (pSprite->hot.x >= pSprite->physLimits.x2)
31594642e01fSmrg            pSprite->hot.x = pSprite->physLimits.x2 - 1;
31604642e01fSmrg        if (pSprite->hot.y < pSprite->physLimits.y1)
31614642e01fSmrg            pSprite->hot.y = pSprite->physLimits.y1;
31624642e01fSmrg        else if (pSprite->hot.y >= pSprite->physLimits.y2)
31634642e01fSmrg            pSprite->hot.y = pSprite->physLimits.y2 - 1;
316435c4bbdfSmrg        if (pSprite->hotShape)
316535c4bbdfSmrg            ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x,
316635c4bbdfSmrg                           &pSprite->hot.y);
316735c4bbdfSmrg        pSprite->hotPhys = pSprite->hot;
31684642e01fSmrg
316935c4bbdfSmrg        if ((pSprite->hotPhys.x != ev->root_x) ||
317035c4bbdfSmrg            (pSprite->hotPhys.y != ev->root_y)) {
31716747b715Smrg#ifdef PANORAMIX
317235c4bbdfSmrg            if (!noPanoramiXExtension) {
317335c4bbdfSmrg                XineramaSetCursorPosition(pDev, pSprite->hotPhys.x,
317435c4bbdfSmrg                                          pSprite->hotPhys.y, FALSE);
317535c4bbdfSmrg            }
317635c4bbdfSmrg            else
31776747b715Smrg#endif
31786747b715Smrg            {
317935c4bbdfSmrg                (*pSprite->hotPhys.pScreen->SetCursorPosition) (pDev,
318035c4bbdfSmrg                                                                pSprite->
318135c4bbdfSmrg                                                                hotPhys.pScreen,
318235c4bbdfSmrg                                                                pSprite->
318335c4bbdfSmrg                                                                hotPhys.x,
318435c4bbdfSmrg                                                                pSprite->
318535c4bbdfSmrg                                                                hotPhys.y,
318635c4bbdfSmrg                                                                FALSE);
31876747b715Smrg            }
318835c4bbdfSmrg        }
31894642e01fSmrg
319035c4bbdfSmrg        ev->root_x = pSprite->hot.x;
319135c4bbdfSmrg        ev->root_y = pSprite->hot.y;
319205b261ecSmrg    }
319305b261ecSmrg
31949ace9065Smrg    newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y);
31956747b715Smrg
319635c4bbdfSmrg    if (newSpriteWin != prevSpriteWin) {
31976747b715Smrg        int sourceid;
319835c4bbdfSmrg
31996747b715Smrg        if (!ev) {
32006747b715Smrg            UpdateCurrentTimeIf();
320135c4bbdfSmrg            sourceid = pDev->id;        /* when from WindowsRestructured */
320235c4bbdfSmrg        }
320335c4bbdfSmrg        else
32046747b715Smrg            sourceid = ev->sourceid;
32056747b715Smrg
320635c4bbdfSmrg        if (prevSpriteWin != NullWindow) {
32076747b715Smrg            if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin))
32086747b715Smrg                DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin,
32096747b715Smrg                                   newSpriteWin, NotifyNormal);
32104642e01fSmrg        }
32116747b715Smrg        /* set pSprite->win after ActivateEnterGrab, otherwise
32126747b715Smrg           sprite window == grab_window and no enter/leave events are
32136747b715Smrg           sent. */
32146747b715Smrg        pSprite->win = newSpriteWin;
32156747b715Smrg        PostNewCursor(pDev);
321605b261ecSmrg        return FALSE;
321705b261ecSmrg    }
321805b261ecSmrg    return TRUE;
321905b261ecSmrg}
322005b261ecSmrg
322105b261ecSmrg/**
322205b261ecSmrg * Windows have restructured, we need to update the sprite position and the
322305b261ecSmrg * sprite's cursor.
322405b261ecSmrg */
32254642e01fSmrgvoid
322605b261ecSmrgWindowsRestructured(void)
322705b261ecSmrg{
32284642e01fSmrg    DeviceIntPtr pDev = inputInfo.devices;
322935c4bbdfSmrg
323035c4bbdfSmrg    while (pDev) {
323135c4bbdfSmrg        if (IsMaster(pDev) || IsFloating(pDev))
3232b1d344b3Smrg            CheckMotion(NULL, pDev);
32334642e01fSmrg        pDev = pDev->next;
32344642e01fSmrg    }
323505b261ecSmrg}
323605b261ecSmrg
323705b261ecSmrg#ifdef PANORAMIX
323805b261ecSmrg/* This was added to support reconfiguration under Xdmx.  The problem is
32396747b715Smrg * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin
324005b261ecSmrg * other than 0,0, the information in the private sprite structure must
324105b261ecSmrg * be updated accordingly, or XYToWindow (and other routines) will not
324205b261ecSmrg * compute correctly. */
324335c4bbdfSmrgvoid
324435c4bbdfSmrgReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
324505b261ecSmrg{
324635c4bbdfSmrg    GrabPtr grab;
32474642e01fSmrg    DeviceIntPtr pDev;
32484642e01fSmrg    SpritePtr pSprite;
324905b261ecSmrg
325035c4bbdfSmrg    if (noPanoramiXExtension)
325135c4bbdfSmrg        return;
325205b261ecSmrg
32534642e01fSmrg    pDev = inputInfo.devices;
325435c4bbdfSmrg    while (pDev) {
325535c4bbdfSmrg        if (DevHasCursor(pDev)) {
32564642e01fSmrg            pSprite = pDev->spriteInfo->sprite;
325735c4bbdfSmrg            pSprite->hot.x -= xoff;
325835c4bbdfSmrg            pSprite->hot.y -= yoff;
32594642e01fSmrg
326035c4bbdfSmrg            pSprite->hotPhys.x -= xoff;
326135c4bbdfSmrg            pSprite->hotPhys.y -= yoff;
32624642e01fSmrg
32634642e01fSmrg            pSprite->hotLimits.x1 -= xoff;
32644642e01fSmrg            pSprite->hotLimits.y1 -= yoff;
32654642e01fSmrg            pSprite->hotLimits.x2 -= xoff;
32664642e01fSmrg            pSprite->hotLimits.y2 -= yoff;
32674642e01fSmrg
32686747b715Smrg            if (RegionNotEmpty(&pSprite->Reg1))
32696747b715Smrg                RegionTranslate(&pSprite->Reg1, xoff, yoff);
32706747b715Smrg            if (RegionNotEmpty(&pSprite->Reg2))
32716747b715Smrg                RegionTranslate(&pSprite->Reg2, xoff, yoff);
32724642e01fSmrg
32734642e01fSmrg            /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
32744642e01fSmrg            if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
32754642e01fSmrg                if (grab->confineTo->drawable.pScreen
327635c4bbdfSmrg                    != pSprite->hotPhys.pScreen)
32774642e01fSmrg                    pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
32784642e01fSmrg                ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
327935c4bbdfSmrg            }
328035c4bbdfSmrg            else
328135c4bbdfSmrg                ConfineCursorToWindow(pDev,
328235c4bbdfSmrg                                      pSprite->hotPhys.pScreen->root,
328335c4bbdfSmrg                                      TRUE, FALSE);
32844642e01fSmrg
32854642e01fSmrg        }
32864642e01fSmrg        pDev = pDev->next;
32874642e01fSmrg    }
32884642e01fSmrg}
32894642e01fSmrg#endif
32904642e01fSmrg
32914642e01fSmrg/**
32924642e01fSmrg * Initialize a sprite for the given device and set it to some sane values. If
32934642e01fSmrg * the device already has a sprite alloc'd, don't realloc but just reset to
32944642e01fSmrg * default values.
32954642e01fSmrg * If a window is supplied, the sprite will be initialized with the window's
32964642e01fSmrg * cursor and positioned in the center of the window's screen. The root window
32974642e01fSmrg * is a good choice to pass in here.
32984642e01fSmrg *
32994642e01fSmrg * It's a good idea to call it only for pointer devices, unless you have a
33004642e01fSmrg * really talented keyboard.
33014642e01fSmrg *
33024642e01fSmrg * @param pDev The device to initialize.
33034642e01fSmrg * @param pWin The window where to generate the sprite in.
33044642e01fSmrg *
33054642e01fSmrg */
33064642e01fSmrgvoid
33074642e01fSmrgInitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
33084642e01fSmrg{
33094642e01fSmrg    SpritePtr pSprite;
33104642e01fSmrg    ScreenPtr pScreen;
33116747b715Smrg    CursorPtr pCursor;
33124642e01fSmrg
331335c4bbdfSmrg    if (!pDev->spriteInfo->sprite) {
33144642e01fSmrg        DeviceIntPtr it;
33154642e01fSmrg
331635c4bbdfSmrg        pDev->spriteInfo->sprite = (SpritePtr) calloc(1, sizeof(SpriteRec));
33174642e01fSmrg        if (!pDev->spriteInfo->sprite)
33184642e01fSmrg            FatalError("InitializeSprite: failed to allocate sprite struct");
33194642e01fSmrg
33204642e01fSmrg        /* We may have paired another device with this device before our
33214642e01fSmrg         * device had a actual sprite. We need to check for this and reset the
33224642e01fSmrg         * sprite field for all paired devices.
33234642e01fSmrg         *
33244642e01fSmrg         * The VCK is always paired with the VCP before the VCP has a sprite.
33254642e01fSmrg         */
332635c4bbdfSmrg        for (it = inputInfo.devices; it; it = it->next) {
33274642e01fSmrg            if (it->spriteInfo->paired == pDev)
33284642e01fSmrg                it->spriteInfo->sprite = pDev->spriteInfo->sprite;
33294642e01fSmrg        }
33304642e01fSmrg        if (inputInfo.keyboard->spriteInfo->paired == pDev)
33314642e01fSmrg            inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite;
33324642e01fSmrg    }
33334642e01fSmrg
33344642e01fSmrg    pSprite = pDev->spriteInfo->sprite;
33354642e01fSmrg    pDev->spriteInfo->spriteOwner = TRUE;
333605b261ecSmrg
333735c4bbdfSmrg    pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr) NULL;
33384642e01fSmrg    pSprite->hot.pScreen = pScreen;
33394642e01fSmrg    pSprite->hotPhys.pScreen = pScreen;
334035c4bbdfSmrg    if (pScreen) {
33414642e01fSmrg        pSprite->hotPhys.x = pScreen->width / 2;
33424642e01fSmrg        pSprite->hotPhys.y = pScreen->height / 2;
33434642e01fSmrg        pSprite->hotLimits.x2 = pScreen->width;
33444642e01fSmrg        pSprite->hotLimits.y2 = pScreen->height;
33454642e01fSmrg    }
33464642e01fSmrg
33474642e01fSmrg    pSprite->hot = pSprite->hotPhys;
33484642e01fSmrg    pSprite->win = pWin;
33494642e01fSmrg
335035c4bbdfSmrg    if (pWin) {
335135c4bbdfSmrg        pCursor = wCursor(pWin);
335235c4bbdfSmrg        pSprite->spriteTrace = (WindowPtr *) calloc(1, 32 * sizeof(WindowPtr));
335335c4bbdfSmrg        if (!pSprite->spriteTrace)
335435c4bbdfSmrg            FatalError("Failed to allocate spriteTrace");
335535c4bbdfSmrg        pSprite->spriteTraceSize = 32;
33564642e01fSmrg
335735c4bbdfSmrg        RootWindow(pDev->spriteInfo->sprite) = pWin;
335835c4bbdfSmrg        pSprite->spriteTraceGood = 1;
33594642e01fSmrg
336035c4bbdfSmrg        pSprite->pEnqueueScreen = pScreen;
336135c4bbdfSmrg        pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
33624642e01fSmrg
336335c4bbdfSmrg    }
336435c4bbdfSmrg    else {
33656747b715Smrg        pCursor = NullCursor;
336635c4bbdfSmrg        pSprite->spriteTrace = NULL;
336735c4bbdfSmrg        pSprite->spriteTraceSize = 0;
336835c4bbdfSmrg        pSprite->spriteTraceGood = 0;
336935c4bbdfSmrg        pSprite->pEnqueueScreen = screenInfo.screens[0];
337035c4bbdfSmrg        pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
337135c4bbdfSmrg    }
337235c4bbdfSmrg    pCursor = RefCursor(pCursor);
33736747b715Smrg    if (pSprite->current)
337435c4bbdfSmrg        FreeCursor(pSprite->current, None);
33756747b715Smrg    pSprite->current = pCursor;
33764642e01fSmrg
337735c4bbdfSmrg    if (pScreen) {
337835c4bbdfSmrg        (*pScreen->RealizeCursor) (pDev, pScreen, pSprite->current);
337935c4bbdfSmrg        (*pScreen->CursorLimits) (pDev, pScreen, pSprite->current,
338035c4bbdfSmrg                                  &pSprite->hotLimits, &pSprite->physLimits);
33814642e01fSmrg        pSprite->confined = FALSE;
33824642e01fSmrg
338335c4bbdfSmrg        (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
33844642e01fSmrg        (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
338535c4bbdfSmrg                                       pSprite->hot.y, FALSE);
33864642e01fSmrg        (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
33874642e01fSmrg    }
338805b261ecSmrg#ifdef PANORAMIX
338935c4bbdfSmrg    if (!noPanoramiXExtension) {
33906747b715Smrg        pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
33916747b715Smrg        pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
339235c4bbdfSmrg        pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
33936747b715Smrg        pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
33944642e01fSmrg        pSprite->physLimits = pSprite->hotLimits;
33954642e01fSmrg        pSprite->confineWin = NullWindow;
33964642e01fSmrg        pSprite->hotShape = NullRegion;
33974642e01fSmrg        pSprite->screen = pScreen;
33984642e01fSmrg        /* gotta UNINIT these someplace */
33996747b715Smrg        RegionNull(&pSprite->Reg1);
34006747b715Smrg        RegionNull(&pSprite->Reg2);
34014642e01fSmrg    }
340205b261ecSmrg#endif
34034642e01fSmrg}
34044642e01fSmrg
340535c4bbdfSmrgvoid FreeSprite(DeviceIntPtr dev)
340635c4bbdfSmrg{
340735c4bbdfSmrg    if (DevHasCursor(dev) && dev->spriteInfo->sprite) {
340835c4bbdfSmrg        if (dev->spriteInfo->sprite->current)
340935c4bbdfSmrg            FreeCursor(dev->spriteInfo->sprite->current, None);
341035c4bbdfSmrg        free(dev->spriteInfo->sprite->spriteTrace);
341135c4bbdfSmrg        free(dev->spriteInfo->sprite);
341235c4bbdfSmrg    }
341335c4bbdfSmrg    dev->spriteInfo->sprite = NULL;
341435c4bbdfSmrg}
341535c4bbdfSmrg
341635c4bbdfSmrg
34174642e01fSmrg/**
34184642e01fSmrg * Update the mouse sprite info when the server switches from a pScreen to another.
34194642e01fSmrg * Otherwise, the pScreen of the mouse sprite is never updated when we switch
34204642e01fSmrg * from a pScreen to another. Never updating the pScreen of the mouse sprite
34214642e01fSmrg * implies that windows that are in pScreen whose pScreen->myNum >0 will never
34224642e01fSmrg * get pointer events. This is  because in CheckMotion(), sprite.hotPhys.pScreen
34234642e01fSmrg * always points to the first pScreen it has been set by
34244642e01fSmrg * DefineInitialRootWindow().
34254642e01fSmrg *
34264642e01fSmrg * Calling this function is useful for use cases where the server
34274642e01fSmrg * has more than one pScreen.
34284642e01fSmrg * This function is similar to DefineInitialRootWindow() but it does not
34294642e01fSmrg * reset the mouse pointer position.
34304642e01fSmrg * @param win must be the new pScreen we are switching to.
34314642e01fSmrg */
34324642e01fSmrgvoid
34334642e01fSmrgUpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
34344642e01fSmrg{
34354642e01fSmrg    SpritePtr pSprite = NULL;
34364642e01fSmrg    WindowPtr win = NULL;
34376747b715Smrg    CursorPtr pCursor;
343835c4bbdfSmrg
34394642e01fSmrg    if (!pScreen)
344035c4bbdfSmrg        return;
34414642e01fSmrg
34424642e01fSmrg    if (!pDev->spriteInfo->sprite)
34434642e01fSmrg        return;
34444642e01fSmrg
34454642e01fSmrg    pSprite = pDev->spriteInfo->sprite;
34464642e01fSmrg
34476747b715Smrg    win = pScreen->root;
34484642e01fSmrg
34494642e01fSmrg    pSprite->hotPhys.pScreen = pScreen;
34504642e01fSmrg    pSprite->hot = pSprite->hotPhys;
34514642e01fSmrg    pSprite->hotLimits.x2 = pScreen->width;
34524642e01fSmrg    pSprite->hotLimits.y2 = pScreen->height;
34534642e01fSmrg    pSprite->win = win;
345435c4bbdfSmrg    pCursor = RefCursor(wCursor(win));
34556747b715Smrg    if (pSprite->current)
345635c4bbdfSmrg        FreeCursor(pSprite->current, 0);
34576747b715Smrg    pSprite->current = pCursor;
34584642e01fSmrg    pSprite->spriteTraceGood = 1;
34594642e01fSmrg    pSprite->spriteTrace[0] = win;
34604642e01fSmrg    (*pScreen->CursorLimits) (pDev,
34614642e01fSmrg                              pScreen,
34624642e01fSmrg                              pSprite->current,
346335c4bbdfSmrg                              &pSprite->hotLimits, &pSprite->physLimits);
34644642e01fSmrg    pSprite->confined = FALSE;
34654642e01fSmrg    (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
34664642e01fSmrg    (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
34674642e01fSmrg
34684642e01fSmrg#ifdef PANORAMIX
346935c4bbdfSmrg    if (!noPanoramiXExtension) {
34706747b715Smrg        pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
34716747b715Smrg        pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
347235c4bbdfSmrg        pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
34736747b715Smrg        pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
34744642e01fSmrg        pSprite->physLimits = pSprite->hotLimits;
34754642e01fSmrg        pSprite->screen = pScreen;
347605b261ecSmrg    }
347705b261ecSmrg#endif
347805b261ecSmrg}
347905b261ecSmrg
348005b261ecSmrg/*
348105b261ecSmrg * This does not take any shortcuts, and even ignores its argument, since
348205b261ecSmrg * it does not happen very often, and one has to walk up the tree since
348305b261ecSmrg * this might be a newly instantiated cursor for an intermediate window
348405b261ecSmrg * between the one the pointer is in and the one that the last cursor was
348505b261ecSmrg * instantiated from.
348605b261ecSmrg */
348705b261ecSmrgvoid
348805b261ecSmrgWindowHasNewCursor(WindowPtr pWin)
348905b261ecSmrg{
34904642e01fSmrg    DeviceIntPtr pDev;
34914642e01fSmrg
349235c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
34934642e01fSmrg        if (DevHasCursor(pDev))
34944642e01fSmrg            PostNewCursor(pDev);
349505b261ecSmrg}
349605b261ecSmrg
34976747b715Smrgvoid
34984642e01fSmrgNewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
349905b261ecSmrg{
350035c4bbdfSmrg    DeviceIntPtr ptr;
350135c4bbdfSmrg    SpritePtr pSprite;
350235c4bbdfSmrg
350335c4bbdfSmrg    ptr =
350435c4bbdfSmrg        IsFloating(pDev) ? pDev :
350535c4bbdfSmrg        GetXTestDevice(GetMaster(pDev, MASTER_POINTER));
350635c4bbdfSmrg    pSprite = ptr->spriteInfo->sprite;
35074642e01fSmrg
35084642e01fSmrg    pSprite->hotPhys.x = x;
35094642e01fSmrg    pSprite->hotPhys.y = y;
351005b261ecSmrg#ifdef PANORAMIX
351135c4bbdfSmrg    if (!noPanoramiXExtension) {
351235c4bbdfSmrg        pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x;
351335c4bbdfSmrg        pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y;
351435c4bbdfSmrg        if (newScreen != pSprite->screen) {
351535c4bbdfSmrg            pSprite->screen = newScreen;
351635c4bbdfSmrg            /* Make sure we tell the DDX to update its copy of the screen */
351735c4bbdfSmrg            if (pSprite->confineWin)
351835c4bbdfSmrg                XineramaConfineCursorToWindow(ptr, pSprite->confineWin, TRUE);
351935c4bbdfSmrg            else
352035c4bbdfSmrg                XineramaConfineCursorToWindow(ptr, screenInfo.screens[0]->root,
352135c4bbdfSmrg                                              TRUE);
352235c4bbdfSmrg            /* if the pointer wasn't confined, the DDX won't get
352335c4bbdfSmrg               told of the pointer warp so we reposition it here */
352435c4bbdfSmrg            if (!syncEvents.playingEvents)
352535c4bbdfSmrg                (*pSprite->screen->SetCursorPosition) (ptr,
352635c4bbdfSmrg                                                       pSprite->screen,
352735c4bbdfSmrg                                                       pSprite->hotPhys.x +
352835c4bbdfSmrg                                                       screenInfo.screens[0]->
352935c4bbdfSmrg                                                       x - pSprite->screen->x,
353035c4bbdfSmrg                                                       pSprite->hotPhys.y +
353135c4bbdfSmrg                                                       screenInfo.screens[0]->
353235c4bbdfSmrg                                                       y - pSprite->screen->y,
353335c4bbdfSmrg                                                       FALSE);
353435c4bbdfSmrg        }
353535c4bbdfSmrg    }
353635c4bbdfSmrg    else
353705b261ecSmrg#endif
35384642e01fSmrg    if (newScreen != pSprite->hotPhys.pScreen)
353935c4bbdfSmrg        ConfineCursorToWindow(ptr, newScreen->root, TRUE, FALSE);
354005b261ecSmrg}
354105b261ecSmrg
354205b261ecSmrg#ifdef PANORAMIX
354305b261ecSmrg
354405b261ecSmrgstatic Bool
354535c4bbdfSmrgXineramaPointInWindowIsVisible(WindowPtr pWin, int x, int y)
354605b261ecSmrg{
354705b261ecSmrg    BoxRec box;
354805b261ecSmrg    int i, xoff, yoff;
354905b261ecSmrg
355035c4bbdfSmrg    if (!pWin->realized)
355135c4bbdfSmrg        return FALSE;
355205b261ecSmrg
35536747b715Smrg    if (RegionContainsPoint(&pWin->borderClip, x, y, &box))
355405b261ecSmrg        return TRUE;
355505b261ecSmrg
355635c4bbdfSmrg    if (!XineramaSetWindowPntrs(inputInfo.pointer, pWin))
355735c4bbdfSmrg         return FALSE;
35584642e01fSmrg
35596747b715Smrg    xoff = x + screenInfo.screens[0]->x;
35606747b715Smrg    yoff = y + screenInfo.screens[0]->y;
356105b261ecSmrg
356235c4bbdfSmrg    FOR_NSCREENS_FORWARD_SKIP(i) {
356335c4bbdfSmrg        pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
356435c4bbdfSmrg
356535c4bbdfSmrg        x = xoff - screenInfo.screens[i]->x;
356635c4bbdfSmrg        y = yoff - screenInfo.screens[i]->y;
356705b261ecSmrg
356835c4bbdfSmrg        if (RegionContainsPoint(&pWin->borderClip, x, y, &box)
356935c4bbdfSmrg            && (!wInputShape(pWin) ||
357035c4bbdfSmrg                RegionContainsPoint(wInputShape(pWin),
357135c4bbdfSmrg                                    x - pWin->drawable.x,
357235c4bbdfSmrg                                    y - pWin->drawable.y, &box)))
357305b261ecSmrg            return TRUE;
357405b261ecSmrg
357505b261ecSmrg    }
357605b261ecSmrg
357705b261ecSmrg    return FALSE;
357805b261ecSmrg}
357905b261ecSmrg
358005b261ecSmrgstatic int
358105b261ecSmrgXineramaWarpPointer(ClientPtr client)
358205b261ecSmrg{
358335c4bbdfSmrg    WindowPtr dest = NULL;
358435c4bbdfSmrg    int x, y, rc;
358535c4bbdfSmrg    SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
358605b261ecSmrg
358705b261ecSmrg    REQUEST(xWarpPointerReq);
358805b261ecSmrg
358905b261ecSmrg    if (stuff->dstWid != None) {
359035c4bbdfSmrg        rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
359135c4bbdfSmrg        if (rc != Success)
359235c4bbdfSmrg            return rc;
359305b261ecSmrg    }
35944642e01fSmrg    x = pSprite->hotPhys.x;
35954642e01fSmrg    y = pSprite->hotPhys.y;
359605b261ecSmrg
359735c4bbdfSmrg    if (stuff->srcWid != None) {
359835c4bbdfSmrg        int winX, winY;
359935c4bbdfSmrg        XID winID = stuff->srcWid;
360005b261ecSmrg        WindowPtr source;
36014642e01fSmrg
360235c4bbdfSmrg        rc = dixLookupWindow(&source, winID, client, DixReadAccess);
360335c4bbdfSmrg        if (rc != Success)
360435c4bbdfSmrg            return rc;
360535c4bbdfSmrg
360635c4bbdfSmrg        winX = source->drawable.x;
360735c4bbdfSmrg        winY = source->drawable.y;
360835c4bbdfSmrg        if (source == screenInfo.screens[0]->root) {
360935c4bbdfSmrg            winX -= screenInfo.screens[0]->x;
361035c4bbdfSmrg            winY -= screenInfo.screens[0]->y;
361135c4bbdfSmrg        }
361235c4bbdfSmrg        if (x < winX + stuff->srcX ||
361335c4bbdfSmrg            y < winY + stuff->srcY ||
361435c4bbdfSmrg            (stuff->srcWidth != 0 &&
361535c4bbdfSmrg             winX + stuff->srcX + (int) stuff->srcWidth < x) ||
361635c4bbdfSmrg            (stuff->srcHeight != 0 &&
361735c4bbdfSmrg             winY + stuff->srcY + (int) stuff->srcHeight < y) ||
361835c4bbdfSmrg            !XineramaPointInWindowIsVisible(source, x, y))
361935c4bbdfSmrg            return Success;
362005b261ecSmrg    }
362105b261ecSmrg    if (dest) {
362235c4bbdfSmrg        x = dest->drawable.x;
362335c4bbdfSmrg        y = dest->drawable.y;
362435c4bbdfSmrg        if (dest == screenInfo.screens[0]->root) {
362535c4bbdfSmrg            x -= screenInfo.screens[0]->x;
362635c4bbdfSmrg            y -= screenInfo.screens[0]->y;
362735c4bbdfSmrg        }
36284642e01fSmrg    }
362905b261ecSmrg
363005b261ecSmrg    x += stuff->dstX;
363105b261ecSmrg    y += stuff->dstY;
363205b261ecSmrg
36334642e01fSmrg    if (x < pSprite->physLimits.x1)
363435c4bbdfSmrg        x = pSprite->physLimits.x1;
36354642e01fSmrg    else if (x >= pSprite->physLimits.x2)
363635c4bbdfSmrg        x = pSprite->physLimits.x2 - 1;
36374642e01fSmrg    if (y < pSprite->physLimits.y1)
363835c4bbdfSmrg        y = pSprite->physLimits.y1;
36394642e01fSmrg    else if (y >= pSprite->physLimits.y2)
364035c4bbdfSmrg        y = pSprite->physLimits.y2 - 1;
36414642e01fSmrg    if (pSprite->hotShape)
364235c4bbdfSmrg        ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
364305b261ecSmrg
36444642e01fSmrg    XineramaSetCursorPosition(PickPointer(client), x, y, TRUE);
364505b261ecSmrg
364605b261ecSmrg    return Success;
364705b261ecSmrg}
364805b261ecSmrg
364905b261ecSmrg#endif
365005b261ecSmrg
365105b261ecSmrg/**
365205b261ecSmrg * Server-side protocol handling for WarpPointer request.
365305b261ecSmrg * Warps the cursor position to the coordinates given in the request.
365405b261ecSmrg */
365505b261ecSmrgint
365605b261ecSmrgProcWarpPointer(ClientPtr client)
365705b261ecSmrg{
365835c4bbdfSmrg    WindowPtr dest = NULL;
365935c4bbdfSmrg    int x, y, rc;
366035c4bbdfSmrg    ScreenPtr newScreen;
36616747b715Smrg    DeviceIntPtr dev, tmp;
366235c4bbdfSmrg    SpritePtr pSprite;
366305b261ecSmrg
366405b261ecSmrg    REQUEST(xWarpPointerReq);
366505b261ecSmrg    REQUEST_SIZE_MATCH(xWarpPointerReq);
366605b261ecSmrg
36676747b715Smrg    dev = PickPointer(client);
36686747b715Smrg
36696747b715Smrg    for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
367035c4bbdfSmrg        if (GetMaster(tmp, MASTER_ATTACHED) == dev) {
367135c4bbdfSmrg            rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
367235c4bbdfSmrg            if (rc != Success)
367335c4bbdfSmrg                return rc;
367435c4bbdfSmrg        }
36754642e01fSmrg    }
36764642e01fSmrg
367735c4bbdfSmrg    if (dev->lastSlave)
367835c4bbdfSmrg        dev = dev->lastSlave;
36794642e01fSmrg    pSprite = dev->spriteInfo->sprite;
36804642e01fSmrg
368105b261ecSmrg#ifdef PANORAMIX
368235c4bbdfSmrg    if (!noPanoramiXExtension)
368335c4bbdfSmrg        return XineramaWarpPointer(client);
368405b261ecSmrg#endif
368505b261ecSmrg
368605b261ecSmrg    if (stuff->dstWid != None) {
368735c4bbdfSmrg        rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess);
368835c4bbdfSmrg        if (rc != Success)
368935c4bbdfSmrg            return rc;
369005b261ecSmrg    }
36914642e01fSmrg    x = pSprite->hotPhys.x;
36924642e01fSmrg    y = pSprite->hotPhys.y;
369305b261ecSmrg
369435c4bbdfSmrg    if (stuff->srcWid != None) {
369535c4bbdfSmrg        int winX, winY;
369635c4bbdfSmrg        XID winID = stuff->srcWid;
369705b261ecSmrg        WindowPtr source;
36984642e01fSmrg
369935c4bbdfSmrg        rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess);
370035c4bbdfSmrg        if (rc != Success)
370135c4bbdfSmrg            return rc;
370235c4bbdfSmrg
370335c4bbdfSmrg        winX = source->drawable.x;
370435c4bbdfSmrg        winY = source->drawable.y;
370535c4bbdfSmrg        if (source->drawable.pScreen != pSprite->hotPhys.pScreen ||
370635c4bbdfSmrg            x < winX + stuff->srcX ||
370735c4bbdfSmrg            y < winY + stuff->srcY ||
370835c4bbdfSmrg            (stuff->srcWidth != 0 &&
370935c4bbdfSmrg             winX + stuff->srcX + (int) stuff->srcWidth < x) ||
371035c4bbdfSmrg            (stuff->srcHeight != 0 &&
371135c4bbdfSmrg             winY + stuff->srcY + (int) stuff->srcHeight < y) ||
37127e31ba66Smrg            (source->parent && !PointInWindowIsVisible(source, x, y)))
371335c4bbdfSmrg            return Success;
371435c4bbdfSmrg    }
371535c4bbdfSmrg    if (dest) {
371635c4bbdfSmrg        x = dest->drawable.x;
371735c4bbdfSmrg        y = dest->drawable.y;
371835c4bbdfSmrg        newScreen = dest->drawable.pScreen;
371935c4bbdfSmrg    }
372035c4bbdfSmrg    else
372135c4bbdfSmrg        newScreen = pSprite->hotPhys.pScreen;
372205b261ecSmrg
372305b261ecSmrg    x += stuff->dstX;
372405b261ecSmrg    y += stuff->dstY;
372505b261ecSmrg
372605b261ecSmrg    if (x < 0)
372735c4bbdfSmrg        x = 0;
372805b261ecSmrg    else if (x >= newScreen->width)
372935c4bbdfSmrg        x = newScreen->width - 1;
373005b261ecSmrg    if (y < 0)
373135c4bbdfSmrg        y = 0;
373205b261ecSmrg    else if (y >= newScreen->height)
373335c4bbdfSmrg        y = newScreen->height - 1;
373435c4bbdfSmrg
373535c4bbdfSmrg    if (newScreen == pSprite->hotPhys.pScreen) {
373635c4bbdfSmrg        if (x < pSprite->physLimits.x1)
373735c4bbdfSmrg            x = pSprite->physLimits.x1;
373835c4bbdfSmrg        else if (x >= pSprite->physLimits.x2)
373935c4bbdfSmrg            x = pSprite->physLimits.x2 - 1;
374035c4bbdfSmrg        if (y < pSprite->physLimits.y1)
374135c4bbdfSmrg            y = pSprite->physLimits.y1;
374235c4bbdfSmrg        else if (y >= pSprite->physLimits.y2)
374335c4bbdfSmrg            y = pSprite->physLimits.y2 - 1;
374435c4bbdfSmrg        if (pSprite->hotShape)
374535c4bbdfSmrg            ConfineToShape(dev, pSprite->hotShape, &x, &y);
374635c4bbdfSmrg        (*newScreen->SetCursorPosition) (dev, newScreen, x, y, TRUE);
374735c4bbdfSmrg    }
374835c4bbdfSmrg    else if (!PointerConfinedToScreen(dev)) {
374935c4bbdfSmrg        NewCurrentScreen(dev, newScreen, x, y);
375005b261ecSmrg    }
37517e31ba66Smrg    if (*newScreen->CursorWarpedTo)
37527e31ba66Smrg        (*newScreen->CursorWarpedTo) (dev, newScreen, client,
37537e31ba66Smrg                                      dest, pSprite, x, y);
375405b261ecSmrg    return Success;
375505b261ecSmrg}
375605b261ecSmrg
37574642e01fSmrgstatic Bool
37584642e01fSmrgBorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
375905b261ecSmrg{
376035c4bbdfSmrg    if (RegionNotEmpty(&pWin->borderSize))
376135c4bbdfSmrg        return TRUE;
376205b261ecSmrg
376305b261ecSmrg#ifdef PANORAMIX
376435c4bbdfSmrg    if (!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) {
376535c4bbdfSmrg        int i;
376635c4bbdfSmrg
376735c4bbdfSmrg        FOR_NSCREENS_FORWARD_SKIP(i) {
376835c4bbdfSmrg            if (RegionNotEmpty
376935c4bbdfSmrg                (&pDev->spriteInfo->sprite->windows[i]->borderSize))
377035c4bbdfSmrg                return TRUE;
377135c4bbdfSmrg        }
377235c4bbdfSmrg    }
377305b261ecSmrg#endif
377435c4bbdfSmrg    return FALSE;
377505b261ecSmrg}
377605b261ecSmrg
37774642e01fSmrg/**
377835c4bbdfSmrg * Activate the given passive grab. If the grab is activated successfully, the
377935c4bbdfSmrg * event has been delivered to the client.
37804642e01fSmrg *
378135c4bbdfSmrg * @param device The device of the event to check.
378235c4bbdfSmrg * @param grab The grab to check.
37836747b715Smrg * @param event The current device event.
378435c4bbdfSmrg * @param real_event The original event, in case of touch emulation. The
378535c4bbdfSmrg * real event is the one stored in the sync queue.
378635c4bbdfSmrg *
378735c4bbdfSmrg * @return Whether the grab has been activated.
378805b261ecSmrg */
378935c4bbdfSmrgBool
379035c4bbdfSmrgActivatePassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event,
379135c4bbdfSmrg                    InternalEvent *real_event)
379205b261ecSmrg{
37939ace9065Smrg    SpritePtr pSprite = device->spriteInfo->sprite;
379435c4bbdfSmrg    xEvent *xE = NULL;
379535c4bbdfSmrg    int count;
379635c4bbdfSmrg    int rc;
37976747b715Smrg
379835c4bbdfSmrg    /* The only consumers of corestate are Xi 1.x and core events, which
379935c4bbdfSmrg     * are guaranteed to come from DeviceEvents. */
380035c4bbdfSmrg    if (grab->grabtype == XI || grab->grabtype == CORE) {
380135c4bbdfSmrg        DeviceIntPtr gdev;
380205b261ecSmrg
380335c4bbdfSmrg        event->device_event.corestate &= 0x1f00;
380435c4bbdfSmrg
380535c4bbdfSmrg        if (grab->grabtype == CORE)
380635c4bbdfSmrg            gdev = GetMaster(device, KEYBOARD_OR_FLOAT);
380735c4bbdfSmrg        else
380835c4bbdfSmrg            gdev = grab->modifierDevice;
380935c4bbdfSmrg
381035c4bbdfSmrg        if (gdev && gdev->key && gdev->key->xkbInfo)
381135c4bbdfSmrg            event->device_event.corestate |=
381235c4bbdfSmrg                gdev->key->xkbInfo->state.grab_mods & (~0x1f00);
381335c4bbdfSmrg    }
381435c4bbdfSmrg
381535c4bbdfSmrg    if (grab->grabtype == CORE) {
381635c4bbdfSmrg        rc = EventToCore(event, &xE, &count);
381735c4bbdfSmrg        if (rc != Success) {
381835c4bbdfSmrg            BUG_WARN_MSG(rc != BadMatch, "[dix] %s: core conversion failed"
381935c4bbdfSmrg                         "(%d, %d).\n", device->name, event->any.type, rc);
382035c4bbdfSmrg            return FALSE;
38214642e01fSmrg        }
382235c4bbdfSmrg    }
382335c4bbdfSmrg    else if (grab->grabtype == XI2) {
382435c4bbdfSmrg        rc = EventToXI2(event, &xE);
382535c4bbdfSmrg        if (rc != Success) {
382635c4bbdfSmrg            if (rc != BadMatch)
382735c4bbdfSmrg                BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI2 conversion failed"
382835c4bbdfSmrg                             "(%d, %d).\n", device->name, event->any.type, rc);
382935c4bbdfSmrg            return FALSE;
383035c4bbdfSmrg        }
383135c4bbdfSmrg        count = 1;
383235c4bbdfSmrg    }
383335c4bbdfSmrg    else {
383435c4bbdfSmrg        rc = EventToXI(event, &xE, &count);
383535c4bbdfSmrg        if (rc != Success) {
383635c4bbdfSmrg            if (rc != BadMatch)
383735c4bbdfSmrg                BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI conversion failed"
383835c4bbdfSmrg                             "(%d, %d).\n", device->name, event->any.type, rc);
383935c4bbdfSmrg            return FALSE;
384035c4bbdfSmrg        }
384135c4bbdfSmrg    }
38426747b715Smrg
38435a112b11Smrg    ActivateGrabNoDelivery(device, grab, event, real_event);
38446747b715Smrg
384535c4bbdfSmrg    if (xE) {
384635c4bbdfSmrg        FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
38476747b715Smrg
384835c4bbdfSmrg        /* XXX: XACE? */
384935c4bbdfSmrg        TryClientEvents(rClient(grab), device, xE, count,
385035c4bbdfSmrg                        GetEventFilter(device, xE),
385135c4bbdfSmrg                        GetEventFilter(device, xE), grab);
385235c4bbdfSmrg    }
38536747b715Smrg
385435c4bbdfSmrg    free(xE);
385535c4bbdfSmrg    return TRUE;
385635c4bbdfSmrg}
385735c4bbdfSmrg
38585a112b11Smrg/**
38595a112b11Smrg * Activates a grab without event delivery.
38605a112b11Smrg *
38615a112b11Smrg * @param device The device of the event to check.
38625a112b11Smrg * @param grab The grab to check.
38635a112b11Smrg * @param event The current device event.
38645a112b11Smrg * @param real_event The original event, in case of touch emulation. The
38655a112b11Smrg * real event is the one stored in the sync queue.
38665a112b11Smrg */
38675a112b11Smrgvoid ActivateGrabNoDelivery(DeviceIntPtr dev, GrabPtr grab,
38685a112b11Smrg                            InternalEvent *event, InternalEvent *real_event)
38695a112b11Smrg{
38705a112b11Smrg    GrabInfoPtr grabinfo = &dev->deviceGrab;
38715a112b11Smrg    (*grabinfo->ActivateGrab) (dev, grab,
38725a112b11Smrg                               ClientTimeToServerTime(event->any.time), TRUE);
38735a112b11Smrg
38745a112b11Smrg    if (grabinfo->sync.state == FROZEN_NO_EVENT)
38755a112b11Smrg        grabinfo->sync.state = FROZEN_WITH_EVENT;
38765a112b11Smrg    *grabinfo->sync.event = *real_event;
38775a112b11Smrg}
38785a112b11Smrg
387935c4bbdfSmrgstatic BOOL
388035c4bbdfSmrgCoreGrabInterferes(DeviceIntPtr device, GrabPtr grab)
388135c4bbdfSmrg{
388235c4bbdfSmrg    DeviceIntPtr other;
388335c4bbdfSmrg    BOOL interfering = FALSE;
388435c4bbdfSmrg
388535c4bbdfSmrg    for (other = inputInfo.devices; other; other = other->next) {
388635c4bbdfSmrg        GrabPtr othergrab = other->deviceGrab.grab;
388735c4bbdfSmrg
388835c4bbdfSmrg        if (othergrab && othergrab->grabtype == CORE &&
388935c4bbdfSmrg            SameClient(grab, rClient(othergrab)) &&
389035c4bbdfSmrg            ((IsPointerDevice(grab->device) &&
389135c4bbdfSmrg              IsPointerDevice(othergrab->device)) ||
389235c4bbdfSmrg             (IsKeyboardDevice(grab->device) &&
389335c4bbdfSmrg              IsKeyboardDevice(othergrab->device)))) {
389435c4bbdfSmrg            interfering = TRUE;
389535c4bbdfSmrg            break;
38966747b715Smrg        }
389735c4bbdfSmrg    }
38986747b715Smrg
389935c4bbdfSmrg    return interfering;
390035c4bbdfSmrg}
39014642e01fSmrg
390235c4bbdfSmrgenum MatchFlags {
390335c4bbdfSmrg    NO_MATCH = 0x0,
390435c4bbdfSmrg    CORE_MATCH = 0x1,
390535c4bbdfSmrg    XI_MATCH = 0x2,
390635c4bbdfSmrg    XI2_MATCH = 0x4,
390735c4bbdfSmrg};
39086747b715Smrg
390935c4bbdfSmrg/**
391035c4bbdfSmrg * Match the grab against the temporary grab on the given input level.
391135c4bbdfSmrg * Modifies the temporary grab pointer.
391235c4bbdfSmrg *
391335c4bbdfSmrg * @param grab The grab to match against
391435c4bbdfSmrg * @param tmp The temporary grab to use for matching
391535c4bbdfSmrg * @param level The input level we want to match on
391635c4bbdfSmrg * @param event_type Wire protocol event type
391735c4bbdfSmrg *
391835c4bbdfSmrg * @return The respective matched flag or 0 for no match
391935c4bbdfSmrg */
392035c4bbdfSmrgstatic enum MatchFlags
392135c4bbdfSmrgMatchForType(const GrabPtr grab, GrabPtr tmp, enum InputLevel level,
392235c4bbdfSmrg             int event_type)
392335c4bbdfSmrg{
392435c4bbdfSmrg    enum MatchFlags match;
392535c4bbdfSmrg    BOOL ignore_device = FALSE;
392635c4bbdfSmrg    int grabtype;
392735c4bbdfSmrg    int evtype;
39284642e01fSmrg
392935c4bbdfSmrg    switch (level) {
393035c4bbdfSmrg    case XI2:
393135c4bbdfSmrg        grabtype = XI2;
393235c4bbdfSmrg        evtype = GetXI2Type(event_type);
393335c4bbdfSmrg        BUG_WARN(!evtype);
393435c4bbdfSmrg        match = XI2_MATCH;
393535c4bbdfSmrg        break;
393635c4bbdfSmrg    case XI:
393735c4bbdfSmrg        grabtype = XI;
393835c4bbdfSmrg        evtype = GetXIType(event_type);
393935c4bbdfSmrg        match = XI_MATCH;
394035c4bbdfSmrg        break;
394135c4bbdfSmrg    case CORE:
394235c4bbdfSmrg        grabtype = CORE;
394335c4bbdfSmrg        evtype = GetCoreType(event_type);
394435c4bbdfSmrg        match = CORE_MATCH;
394535c4bbdfSmrg        ignore_device = TRUE;
394635c4bbdfSmrg        break;
394735c4bbdfSmrg    default:
394835c4bbdfSmrg        return NO_MATCH;
394935c4bbdfSmrg    }
395035c4bbdfSmrg
395135c4bbdfSmrg    tmp->grabtype = grabtype;
395235c4bbdfSmrg    tmp->type = evtype;
395335c4bbdfSmrg
395435c4bbdfSmrg    if (tmp->type && GrabMatchesSecond(tmp, grab, ignore_device))
395535c4bbdfSmrg        return match;
395635c4bbdfSmrg
395735c4bbdfSmrg    return NO_MATCH;
395835c4bbdfSmrg}
39594642e01fSmrg
396035c4bbdfSmrg/**
396135c4bbdfSmrg * Check an individual grab against an event to determine if a passive grab
396235c4bbdfSmrg * should be activated.
396335c4bbdfSmrg *
396435c4bbdfSmrg * @param device The device of the event to check.
396535c4bbdfSmrg * @param grab The grab to check.
396635c4bbdfSmrg * @param event The current device event.
396735c4bbdfSmrg * @param checkCore Check for core grabs too.
396835c4bbdfSmrg * @param tempGrab A pre-allocated temporary grab record for matching. This
396935c4bbdfSmrg *        must have the window and device values filled in.
397035c4bbdfSmrg *
397135c4bbdfSmrg * @return Whether the grab matches the event.
397235c4bbdfSmrg */
397335c4bbdfSmrgstatic Bool
397435c4bbdfSmrgCheckPassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event,
397535c4bbdfSmrg                 Bool checkCore, GrabPtr tempGrab)
397635c4bbdfSmrg{
397735c4bbdfSmrg    DeviceIntPtr gdev;
397835c4bbdfSmrg    XkbSrvInfoPtr xkbi = NULL;
397935c4bbdfSmrg    enum MatchFlags match = 0;
398035c4bbdfSmrg    int emulated_type = 0;
39816747b715Smrg
398235c4bbdfSmrg    gdev = grab->modifierDevice;
398335c4bbdfSmrg    if (grab->grabtype == CORE) {
398435c4bbdfSmrg        gdev = GetMaster(device, KEYBOARD_OR_FLOAT);
398535c4bbdfSmrg    }
398635c4bbdfSmrg    else if (grab->grabtype == XI2) {
398735c4bbdfSmrg        /* if the device is an attached slave device, gdev must be the
398835c4bbdfSmrg         * attached master keyboard. Since the slave may have been
398935c4bbdfSmrg         * reattached after the grab, the modifier device may not be the
399035c4bbdfSmrg         * same. */
399135c4bbdfSmrg        if (!IsMaster(grab->device) && !IsFloating(device))
399235c4bbdfSmrg            gdev = GetMaster(device, MASTER_KEYBOARD);
399335c4bbdfSmrg    }
39944642e01fSmrg
399535c4bbdfSmrg    if (gdev && gdev->key)
399635c4bbdfSmrg        xkbi = gdev->key->xkbInfo;
399735c4bbdfSmrg    tempGrab->modifierDevice = grab->modifierDevice;
399835c4bbdfSmrg    tempGrab->modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
399905b261ecSmrg
400035c4bbdfSmrg    /* Check for XI2 and XI grabs first */
400135c4bbdfSmrg    match = MatchForType(grab, tempGrab, XI2, event->any.type);
400205b261ecSmrg
400335c4bbdfSmrg    if (!match && IsTouchEvent(event) &&
400435c4bbdfSmrg        (event->device_event.flags & TOUCH_POINTER_EMULATED)) {
400535c4bbdfSmrg        emulated_type = TouchGetPointerEventType(event);
400635c4bbdfSmrg        match = MatchForType(grab, tempGrab, XI2, emulated_type);
400735c4bbdfSmrg    }
400835c4bbdfSmrg
400935c4bbdfSmrg    if (!match)
401035c4bbdfSmrg        match = MatchForType(grab, tempGrab, XI, event->any.type);
401135c4bbdfSmrg
401235c4bbdfSmrg    if (!match && emulated_type)
401335c4bbdfSmrg        match = MatchForType(grab, tempGrab, XI, emulated_type);
401435c4bbdfSmrg
401535c4bbdfSmrg    if (!match && checkCore) {
401635c4bbdfSmrg        match = MatchForType(grab, tempGrab, CORE, event->any.type);
401735c4bbdfSmrg        if (!match && emulated_type)
401835c4bbdfSmrg            match = MatchForType(grab, tempGrab, CORE, emulated_type);
401935c4bbdfSmrg    }
402035c4bbdfSmrg
402135c4bbdfSmrg    if (!match || (grab->confineTo &&
402235c4bbdfSmrg                   (!grab->confineTo->realized ||
402335c4bbdfSmrg                    !BorderSizeNotEmpty(device, grab->confineTo))))
402435c4bbdfSmrg        return FALSE;
402535c4bbdfSmrg
402635c4bbdfSmrg    /* In some cases a passive core grab may exist, but the client
402735c4bbdfSmrg     * already has a core grab on some other device. In this case we
402835c4bbdfSmrg     * must not get the grab, otherwise we may never ungrab the
402935c4bbdfSmrg     * device.
403035c4bbdfSmrg     */
403135c4bbdfSmrg
403235c4bbdfSmrg    if (grab->grabtype == CORE) {
403335c4bbdfSmrg        /* A passive grab may have been created for a different device
403435c4bbdfSmrg           than it is assigned to at this point in time.
403535c4bbdfSmrg           Update the grab's device and modifier device to reflect the
403635c4bbdfSmrg           current state.
403735c4bbdfSmrg           Since XGrabDeviceButton requires to specify the
403835c4bbdfSmrg           modifierDevice explicitly, we don't override this choice.
403935c4bbdfSmrg         */
404035c4bbdfSmrg        if (grab->type < GenericEvent) {
404135c4bbdfSmrg            grab->device = device;
404235c4bbdfSmrg            grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD);
404335c4bbdfSmrg        }
404435c4bbdfSmrg
404535c4bbdfSmrg        if (CoreGrabInterferes(device, grab))
404635c4bbdfSmrg            return FALSE;
404735c4bbdfSmrg    }
404835c4bbdfSmrg
404935c4bbdfSmrg    return TRUE;
405035c4bbdfSmrg}
405135c4bbdfSmrg
405235c4bbdfSmrg/**
405335c4bbdfSmrg * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
405435c4bbdfSmrg * passive grab set on the window to be activated.
405535c4bbdfSmrg * If activate is true and a passive grab is found, it will be activated,
405635c4bbdfSmrg * and the event will be delivered to the client.
405735c4bbdfSmrg *
405835c4bbdfSmrg * @param pWin The window that may be subject to a passive grab.
405935c4bbdfSmrg * @param device Device that caused the event.
406035c4bbdfSmrg * @param event The current device event.
406135c4bbdfSmrg * @param checkCore Check for core grabs too.
406235c4bbdfSmrg * @param activate If a grab is found, activate it and deliver the event.
406335c4bbdfSmrg */
406435c4bbdfSmrg
406535c4bbdfSmrgGrabPtr
406635c4bbdfSmrgCheckPassiveGrabsOnWindow(WindowPtr pWin,
406735c4bbdfSmrg                          DeviceIntPtr device,
406835c4bbdfSmrg                          InternalEvent *event, BOOL checkCore, BOOL activate)
406935c4bbdfSmrg{
407035c4bbdfSmrg    GrabPtr grab = wPassiveGrabs(pWin);
407135c4bbdfSmrg    GrabPtr tempGrab;
407235c4bbdfSmrg
407335c4bbdfSmrg    if (!grab)
407435c4bbdfSmrg        return NULL;
407535c4bbdfSmrg
407635c4bbdfSmrg    tempGrab = AllocGrab(NULL);
407735c4bbdfSmrg    if (tempGrab == NULL)
407835c4bbdfSmrg        return NULL;
407935c4bbdfSmrg
408035c4bbdfSmrg    /* Fill out the grab details, but leave the type for later before
408135c4bbdfSmrg     * comparing */
408235c4bbdfSmrg    switch (event->any.type) {
408335c4bbdfSmrg    case ET_KeyPress:
408435c4bbdfSmrg    case ET_KeyRelease:
408535c4bbdfSmrg        tempGrab->detail.exact = event->device_event.detail.key;
408635c4bbdfSmrg        break;
408735c4bbdfSmrg    case ET_ButtonPress:
408835c4bbdfSmrg    case ET_ButtonRelease:
408935c4bbdfSmrg    case ET_TouchBegin:
409035c4bbdfSmrg    case ET_TouchEnd:
409135c4bbdfSmrg        tempGrab->detail.exact = event->device_event.detail.button;
409235c4bbdfSmrg        break;
409335c4bbdfSmrg    default:
409435c4bbdfSmrg        tempGrab->detail.exact = 0;
409535c4bbdfSmrg        break;
409635c4bbdfSmrg    }
409735c4bbdfSmrg    tempGrab->window = pWin;
409835c4bbdfSmrg    tempGrab->device = device;
409935c4bbdfSmrg    tempGrab->detail.pMask = NULL;
410035c4bbdfSmrg    tempGrab->modifiersDetail.pMask = NULL;
410135c4bbdfSmrg    tempGrab->next = NULL;
410235c4bbdfSmrg
410335c4bbdfSmrg    for (; grab; grab = grab->next) {
410435c4bbdfSmrg        if (!CheckPassiveGrab(device, grab, event, checkCore, tempGrab))
410535c4bbdfSmrg            continue;
410635c4bbdfSmrg
410735c4bbdfSmrg        if (activate && !ActivatePassiveGrab(device, grab, event, event))
410835c4bbdfSmrg            continue;
41096747b715Smrg
411035c4bbdfSmrg        break;
411105b261ecSmrg    }
411235c4bbdfSmrg
411335c4bbdfSmrg    FreeGrab(tempGrab);
411435c4bbdfSmrg    return grab;
411505b261ecSmrg}
411605b261ecSmrg
411705b261ecSmrg/**
411805b261ecSmrg * CheckDeviceGrabs handles both keyboard and pointer events that may cause
41194642e01fSmrg * a passive grab to be activated.
412005b261ecSmrg *
412105b261ecSmrg * If the event is a keyboard event, the ancestors of the focus window are
412205b261ecSmrg * traced down and tried to see if they have any passive grabs to be
41235a112b11Smrg * activated.  If the focus window itself is reached and its descendants
412405b261ecSmrg * contain the pointer, the ancestors of the window that the pointer is in
412505b261ecSmrg * are then traced down starting at the focus window, otherwise no grabs are
41264642e01fSmrg * activated.
412705b261ecSmrg * If the event is a pointer event, the ancestors of the window that the
412805b261ecSmrg * pointer is in are traced down starting at the root until CheckPassiveGrabs
412905b261ecSmrg * causes a passive grab to activate or all the windows are
413005b261ecSmrg * tried. PRH
413105b261ecSmrg *
413205b261ecSmrg * If a grab is activated, the event has been sent to the client already!
413305b261ecSmrg *
41344642e01fSmrg * The event we pass in must always be an XI event. From this, we then emulate
41354642e01fSmrg * the core event and then check for grabs.
41364642e01fSmrg *
413705b261ecSmrg * @param device The device that caused the event.
41384642e01fSmrg * @param xE The event to handle (Device{Button|Key}Press).
413905b261ecSmrg * @param count Number of events in list.
414005b261ecSmrg * @return TRUE if a grab has been activated or false otherwise.
414105b261ecSmrg*/
414205b261ecSmrg
414305b261ecSmrgBool
41445a112b11SmrgCheckDeviceGrabs(DeviceIntPtr device, InternalEvent *ievent, WindowPtr ancestor)
414505b261ecSmrg{
414605b261ecSmrg    int i;
414705b261ecSmrg    WindowPtr pWin = NULL;
414835c4bbdfSmrg    FocusClassPtr focus =
41495a112b11Smrg        IsPointerEvent(ievent) ? NULL : device->focus;
41506747b715Smrg    BOOL sendCore = (IsMaster(device) && device->coreEvents);
415135c4bbdfSmrg    Bool ret = FALSE;
41525a112b11Smrg    DeviceEvent *event = &ievent->device_event;
415305b261ecSmrg
415435c4bbdfSmrg    if (event->type != ET_ButtonPress && event->type != ET_KeyPress)
41554642e01fSmrg        return FALSE;
41564642e01fSmrg
415735c4bbdfSmrg    if (event->type == ET_ButtonPress && (device->button->buttonsDown != 1))
415835c4bbdfSmrg        return FALSE;
41594642e01fSmrg
41609ace9065Smrg    if (device->deviceGrab.grab)
41619ace9065Smrg        return FALSE;
41629ace9065Smrg
41639ace9065Smrg    i = 0;
416435c4bbdfSmrg    if (ancestor) {
41659ace9065Smrg        while (i < device->spriteInfo->sprite->spriteTraceGood)
41669ace9065Smrg            if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor)
41679ace9065Smrg                break;
41689ace9065Smrg        if (i == device->spriteInfo->sprite->spriteTraceGood)
416935c4bbdfSmrg            goto out;
41709ace9065Smrg    }
417105b261ecSmrg
417235c4bbdfSmrg    if (focus) {
417335c4bbdfSmrg        for (; i < focus->traceGood; i++) {
417435c4bbdfSmrg            pWin = focus->trace[i];
41755a112b11Smrg            if (CheckPassiveGrabsOnWindow(pWin, device, ievent,
417635c4bbdfSmrg                                          sendCore, TRUE)) {
417735c4bbdfSmrg                ret = TRUE;
417835c4bbdfSmrg                goto out;
417935c4bbdfSmrg            }
418035c4bbdfSmrg        }
41814642e01fSmrg
418235c4bbdfSmrg        if ((focus->win == NoneWin) ||
418335c4bbdfSmrg            (i >= device->spriteInfo->sprite->spriteTraceGood) ||
418435c4bbdfSmrg            (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i - 1]))
418535c4bbdfSmrg            goto out;
418605b261ecSmrg    }
418705b261ecSmrg
418835c4bbdfSmrg    for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) {
418935c4bbdfSmrg        pWin = device->spriteInfo->sprite->spriteTrace[i];
41905a112b11Smrg        if (CheckPassiveGrabsOnWindow(pWin, device, ievent,
419135c4bbdfSmrg                                      sendCore, TRUE)) {
419235c4bbdfSmrg            ret = TRUE;
419335c4bbdfSmrg            goto out;
419435c4bbdfSmrg        }
419505b261ecSmrg    }
419605b261ecSmrg
419735c4bbdfSmrg out:
419835c4bbdfSmrg    if (ret == TRUE && event->type == ET_KeyPress)
419935c4bbdfSmrg        device->deviceGrab.activatingKey = event->detail.key;
420035c4bbdfSmrg    return ret;
420105b261ecSmrg}
420205b261ecSmrg
420305b261ecSmrg/**
420405b261ecSmrg * Called for keyboard events to deliver event to whatever client owns the
42056747b715Smrg * focus.
42066747b715Smrg *
42076747b715Smrg * The event is delivered to the keyboard's focus window, the root window or
42086747b715Smrg * to the window owning the input focus.
420905b261ecSmrg *
421005b261ecSmrg * @param keybd The keyboard originating the event.
42116747b715Smrg * @param event The event, not yet in wire format.
421205b261ecSmrg * @param window Window underneath the sprite.
421305b261ecSmrg */
421405b261ecSmrgvoid
42156747b715SmrgDeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
421605b261ecSmrg{
42176747b715Smrg    DeviceIntPtr ptr;
421805b261ecSmrg    WindowPtr focus = keybd->focus->win;
42196747b715Smrg    BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents);
422035c4bbdfSmrg    xEvent *core = NULL, *xE = NULL, *xi2 = NULL;
42216747b715Smrg    int count, rc;
42224642e01fSmrg    int deliveries = 0;
422305b261ecSmrg
422405b261ecSmrg    if (focus == FollowKeyboardWin)
422535c4bbdfSmrg        focus = inputInfo.keyboard->focus->win;
422605b261ecSmrg    if (!focus)
422735c4bbdfSmrg        return;
422835c4bbdfSmrg    if (focus == PointerRootWin) {
422935c4bbdfSmrg        DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd);
423035c4bbdfSmrg        return;
423105b261ecSmrg    }
423235c4bbdfSmrg    if ((focus == window) || IsParent(focus, window)) {
423335c4bbdfSmrg        if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd))
423435c4bbdfSmrg            return;
423505b261ecSmrg    }
42364642e01fSmrg
423705b261ecSmrg    /* just deliver it to the focus window */
423835c4bbdfSmrg    ptr = GetMaster(keybd, POINTER_OR_FLOAT);
42396747b715Smrg
42406747b715Smrg    rc = EventToXI2(event, &xi2);
424135c4bbdfSmrg    if (rc == Success) {
42426747b715Smrg        /* XXX: XACE */
42436747b715Smrg        int filter = GetEventFilter(keybd, xi2);
424435c4bbdfSmrg
42459ace9065Smrg        FixUpEventFromWindow(ptr->spriteInfo->sprite, xi2, focus, None, FALSE);
42466747b715Smrg        deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1,
42476747b715Smrg                                           filter, NullGrab);
42486747b715Smrg        if (deliveries > 0)
42496747b715Smrg            goto unwind;
425035c4bbdfSmrg    }
425135c4bbdfSmrg    else if (rc != BadMatch)
425235c4bbdfSmrg        ErrorF
425335c4bbdfSmrg            ("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n",
425435c4bbdfSmrg             keybd->name, event->any.type, rc);
42556747b715Smrg
42566747b715Smrg    rc = EventToXI(event, &xE, &count);
42576747b715Smrg    if (rc == Success &&
425835c4bbdfSmrg        XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success) {
42599ace9065Smrg        FixUpEventFromWindow(ptr->spriteInfo->sprite, xE, focus, None, FALSE);
42606747b715Smrg        deliveries = DeliverEventsToWindow(keybd, focus, xE, count,
426135c4bbdfSmrg                                           GetEventFilter(keybd, xE), NullGrab);
42626747b715Smrg
42636747b715Smrg        if (deliveries > 0)
42646747b715Smrg            goto unwind;
426535c4bbdfSmrg    }
426635c4bbdfSmrg    else if (rc != BadMatch)
426735c4bbdfSmrg        ErrorF
426835c4bbdfSmrg            ("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n",
426935c4bbdfSmrg             keybd->name, event->any.type, rc);
42704642e01fSmrg
427135c4bbdfSmrg    if (sendCore) {
427235c4bbdfSmrg        rc = EventToCore(event, &core, &count);
42736747b715Smrg        if (rc == Success) {
427435c4bbdfSmrg            if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, core, count) ==
427535c4bbdfSmrg                Success) {
427635c4bbdfSmrg                FixUpEventFromWindow(keybd->spriteInfo->sprite, core, focus,
42779ace9065Smrg                                     None, FALSE);
427835c4bbdfSmrg                deliveries =
427935c4bbdfSmrg                    DeliverEventsToWindow(keybd, focus, core, count,
428035c4bbdfSmrg                                          GetEventFilter(keybd, core),
428135c4bbdfSmrg                                          NullGrab);
42826747b715Smrg            }
428335c4bbdfSmrg        }
428435c4bbdfSmrg        else if (rc != BadMatch)
428535c4bbdfSmrg            ErrorF
428635c4bbdfSmrg                ("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n",
428735c4bbdfSmrg                 keybd->name, event->any.type, rc);
42884642e01fSmrg    }
42896747b715Smrg
429035c4bbdfSmrg unwind:
429135c4bbdfSmrg    free(core);
42926747b715Smrg    free(xE);
42936747b715Smrg    free(xi2);
42946747b715Smrg    return;
429505b261ecSmrg}
429605b261ecSmrg
429735c4bbdfSmrgint
429835c4bbdfSmrgDeliverOneGrabbedEvent(InternalEvent *event, DeviceIntPtr dev,
429935c4bbdfSmrg                       enum InputLevel level)
430035c4bbdfSmrg{
430135c4bbdfSmrg    SpritePtr pSprite = dev->spriteInfo->sprite;
430235c4bbdfSmrg    int rc;
430335c4bbdfSmrg    xEvent *xE = NULL;
430435c4bbdfSmrg    int count = 0;
430535c4bbdfSmrg    int deliveries = 0;
430635c4bbdfSmrg    Mask mask;
430735c4bbdfSmrg    GrabInfoPtr grabinfo = &dev->deviceGrab;
430835c4bbdfSmrg    GrabPtr grab = grabinfo->grab;
430935c4bbdfSmrg    Mask filter;
431035c4bbdfSmrg
431135c4bbdfSmrg    if (grab->grabtype != level)
431235c4bbdfSmrg        return 0;
431335c4bbdfSmrg
431435c4bbdfSmrg    switch (level) {
431535c4bbdfSmrg    case XI2:
431635c4bbdfSmrg        rc = EventToXI2(event, &xE);
431735c4bbdfSmrg        count = 1;
431835c4bbdfSmrg        if (rc == Success) {
431935c4bbdfSmrg            int evtype = xi2_get_type(xE);
432035c4bbdfSmrg
432135c4bbdfSmrg            mask = GetXI2MaskByte(grab->xi2mask, dev, evtype);
432235c4bbdfSmrg            filter = GetEventFilter(dev, xE);
432335c4bbdfSmrg        }
432435c4bbdfSmrg        break;
432535c4bbdfSmrg    case XI:
432635c4bbdfSmrg        if (grabinfo->fromPassiveGrab && grabinfo->implicitGrab)
432735c4bbdfSmrg            mask = grab->deviceMask;
432835c4bbdfSmrg        else
432935c4bbdfSmrg            mask = grab->eventMask;
433035c4bbdfSmrg        rc = EventToXI(event, &xE, &count);
433135c4bbdfSmrg        if (rc == Success)
433235c4bbdfSmrg            filter = GetEventFilter(dev, xE);
433335c4bbdfSmrg        break;
433435c4bbdfSmrg    case CORE:
433535c4bbdfSmrg        rc = EventToCore(event, &xE, &count);
433635c4bbdfSmrg        mask = grab->eventMask;
433735c4bbdfSmrg        if (rc == Success)
433835c4bbdfSmrg            filter = GetEventFilter(dev, xE);
433935c4bbdfSmrg        break;
434035c4bbdfSmrg    default:
434135c4bbdfSmrg        BUG_WARN_MSG(1, "Invalid input level %d\n", level);
434235c4bbdfSmrg        return 0;
434335c4bbdfSmrg    }
434435c4bbdfSmrg
434535c4bbdfSmrg    if (rc == Success) {
434635c4bbdfSmrg        FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
434735c4bbdfSmrg        if (XaceHook(XACE_SEND_ACCESS, 0, dev,
434835c4bbdfSmrg                     grab->window, xE, count) ||
434935c4bbdfSmrg            XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
435035c4bbdfSmrg                     grab->window, xE, count))
435135c4bbdfSmrg            deliveries = 1;     /* don't send, but pretend we did */
435235c4bbdfSmrg        else if (level != CORE || !IsInterferingGrab(rClient(grab), dev, xE)) {
435335c4bbdfSmrg            deliveries = TryClientEvents(rClient(grab), dev,
435435c4bbdfSmrg                                         xE, count, mask, filter, grab);
435535c4bbdfSmrg        }
435635c4bbdfSmrg    }
435735c4bbdfSmrg    else
435835c4bbdfSmrg        BUG_WARN_MSG(rc != BadMatch,
435935c4bbdfSmrg                     "%s: conversion to mode %d failed on %d with %d\n",
436035c4bbdfSmrg                     dev->name, level, event->any.type, rc);
436135c4bbdfSmrg
436235c4bbdfSmrg    free(xE);
436335c4bbdfSmrg    return deliveries;
436435c4bbdfSmrg}
436535c4bbdfSmrg
436605b261ecSmrg/**
436705b261ecSmrg * Deliver an event from a device that is currently grabbed. Uses
436805b261ecSmrg * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the
436905b261ecSmrg * grab. If not, TryClientEvents() is used.
437005b261ecSmrg *
437105b261ecSmrg * @param deactivateGrab True if the device's grab should be deactivated.
437235c4bbdfSmrg *
437335c4bbdfSmrg * @return The number of events delivered.
437405b261ecSmrg */
437535c4bbdfSmrgint
43766747b715SmrgDeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
43776747b715Smrg                    Bool deactivateGrab)
437805b261ecSmrg{
43794642e01fSmrg    GrabPtr grab;
43804642e01fSmrg    GrabInfoPtr grabinfo;
438105b261ecSmrg    int deliveries = 0;
43824642e01fSmrg    SpritePtr pSprite = thisDev->spriteInfo->sprite;
43834642e01fSmrg    BOOL sendCore = FALSE;
43844642e01fSmrg
43854642e01fSmrg    grabinfo = &thisDev->deviceGrab;
43864642e01fSmrg    grab = grabinfo->grab;
438705b261ecSmrg
438835c4bbdfSmrg    if (grab->ownerEvents) {
438935c4bbdfSmrg        WindowPtr focus;
439005b261ecSmrg
43914642e01fSmrg        /* Hack: Some pointer device have a focus class. So we need to check
43924642e01fSmrg         * for the type of event, to see if we really want to deliver it to
43934642e01fSmrg         * the focus window. For pointer events, the answer is no.
43944642e01fSmrg         */
43956747b715Smrg        if (IsPointerEvent(event))
43964642e01fSmrg            focus = PointerRootWin;
439735c4bbdfSmrg        else if (thisDev->focus) {
439835c4bbdfSmrg            focus = thisDev->focus->win;
439935c4bbdfSmrg            if (focus == FollowKeyboardWin)
440035c4bbdfSmrg                focus = inputInfo.keyboard->focus->win;
440135c4bbdfSmrg        }
440235c4bbdfSmrg        else
440335c4bbdfSmrg            focus = PointerRootWin;
440435c4bbdfSmrg        if (focus == PointerRootWin)
440535c4bbdfSmrg            deliveries = DeliverDeviceEvents(pSprite->win, event, grab,
44066747b715Smrg                                             NullWindow, thisDev);
440735c4bbdfSmrg        else if (focus && (focus == pSprite->win ||
440835c4bbdfSmrg                           IsParent(focus, pSprite->win)))
440935c4bbdfSmrg            deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus,
441035c4bbdfSmrg                                             thisDev);
441135c4bbdfSmrg        else if (focus)
441235c4bbdfSmrg            deliveries = DeliverDeviceEvents(focus, event, grab, focus,
441335c4bbdfSmrg                                             thisDev);
441435c4bbdfSmrg    }
441535c4bbdfSmrg    if (!deliveries) {
44166747b715Smrg        sendCore = (IsMaster(thisDev) && thisDev->coreEvents);
44176747b715Smrg        /* try core event */
441835c4bbdfSmrg        if ((sendCore && grab->grabtype == CORE) || grab->grabtype != CORE)
441935c4bbdfSmrg            deliveries = DeliverOneGrabbedEvent(event, thisDev, grab->grabtype);
44206747b715Smrg
44216747b715Smrg        if (deliveries && (event->any.type == ET_Motion))
44224642e01fSmrg            thisDev->valuator->motionHintWindow = grab->window;
442305b261ecSmrg    }
442435c4bbdfSmrg    if (deliveries && !deactivateGrab &&
442535c4bbdfSmrg        (event->any.type == ET_KeyPress ||
442635c4bbdfSmrg         event->any.type == ET_KeyRelease ||
442735c4bbdfSmrg         event->any.type == ET_ButtonPress ||
442835c4bbdfSmrg         event->any.type == ET_ButtonRelease)) {
44295a112b11Smrg        FreezeThisEventIfNeededForSyncGrab(thisDev, event);
443005b261ecSmrg    }
443105b261ecSmrg
443235c4bbdfSmrg    return deliveries;
44336747b715Smrg}
443405b261ecSmrg
44355a112b11Smrgvoid
44365a112b11SmrgFreezeThisEventIfNeededForSyncGrab(DeviceIntPtr thisDev, InternalEvent *event)
44375a112b11Smrg{
44385a112b11Smrg    GrabInfoPtr grabinfo = &thisDev->deviceGrab;
44395a112b11Smrg    GrabPtr grab = grabinfo->grab;
44405a112b11Smrg    DeviceIntPtr dev;
44415a112b11Smrg
44425a112b11Smrg    switch (grabinfo->sync.state) {
44435a112b11Smrg    case FREEZE_BOTH_NEXT_EVENT:
44445a112b11Smrg        dev = GetPairedDevice(thisDev);
44455a112b11Smrg        if (dev) {
44465a112b11Smrg            FreezeThaw(dev, TRUE);
44475a112b11Smrg            if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) &&
44485a112b11Smrg                (CLIENT_BITS(grab->resource) ==
44495a112b11Smrg                 CLIENT_BITS(dev->deviceGrab.grab->resource)))
44505a112b11Smrg                dev->deviceGrab.sync.state = FROZEN_NO_EVENT;
44515a112b11Smrg            else
44525a112b11Smrg                dev->deviceGrab.sync.other = grab;
44535a112b11Smrg        }
44545a112b11Smrg        /* fall through */
44555a112b11Smrg    case FREEZE_NEXT_EVENT:
44565a112b11Smrg        grabinfo->sync.state = FROZEN_WITH_EVENT;
44575a112b11Smrg        FreezeThaw(thisDev, TRUE);
44585a112b11Smrg        *grabinfo->sync.event = *event;
44595a112b11Smrg        break;
44605a112b11Smrg    }
44615a112b11Smrg}
44625a112b11Smrg
44636747b715Smrg/* This function is used to set the key pressed or key released state -
44646747b715Smrg   this is only used when the pressing of keys does not cause
44656747b715Smrg   the device's processInputProc to be called, as in for example Mouse Keys.
44666747b715Smrg*/
44676747b715Smrgvoid
446835c4bbdfSmrgFixKeyState(DeviceEvent *event, DeviceIntPtr keybd)
44696747b715Smrg{
44706747b715Smrg    int key = event->detail.key;
44716747b715Smrg
44726747b715Smrg    if (event->type == ET_KeyPress) {
447335c4bbdfSmrg        DebugF("FixKeyState: Key %d %s\n", key,
44746747b715Smrg               ((event->type == ET_KeyPress) ? "down" : "up"));
447505b261ecSmrg    }
44764642e01fSmrg
44776747b715Smrg    if (event->type == ET_KeyPress)
44786747b715Smrg        set_key_down(keybd, key, KEY_PROCESSED);
44796747b715Smrg    else if (event->type == ET_KeyRelease)
44806747b715Smrg        set_key_up(keybd, key, KEY_PROCESSED);
448105b261ecSmrg    else
44826747b715Smrg        FatalError("Impossible keyboard event");
448305b261ecSmrg}
448405b261ecSmrg
448505b261ecSmrg#define AtMostOneClient \
448605b261ecSmrg	(SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
44874642e01fSmrg#define ManagerMask \
44884642e01fSmrg	(SubstructureRedirectMask | ResizeRedirectMask)
448905b261ecSmrg
449005b261ecSmrg/**
449105b261ecSmrg * Recalculate which events may be deliverable for the given window.
449205b261ecSmrg * Recalculated mask is used for quicker determination which events may be
449305b261ecSmrg * delivered to a window.
449405b261ecSmrg *
449505b261ecSmrg * The otherEventMasks on a WindowOptional is the combination of all event
449605b261ecSmrg * masks set by all clients on the window.
449705b261ecSmrg * deliverableEventMask is the combination of the eventMask and the
44986747b715Smrg * otherEventMask plus the events that may be propagated to the parent.
449905b261ecSmrg *
450005b261ecSmrg * Traverses to siblings and parents of the window.
450105b261ecSmrg */
450205b261ecSmrgvoid
45036747b715SmrgRecalculateDeliverableEvents(WindowPtr pWin)
450405b261ecSmrg{
450505b261ecSmrg    OtherClients *others;
450605b261ecSmrg    WindowPtr pChild;
450705b261ecSmrg
450805b261ecSmrg    pChild = pWin;
450935c4bbdfSmrg    while (1) {
451035c4bbdfSmrg        if (pChild->optional) {
451135c4bbdfSmrg            pChild->optional->otherEventMasks = 0;
451235c4bbdfSmrg            for (others = wOtherClients(pChild); others; others = others->next) {
451335c4bbdfSmrg                pChild->optional->otherEventMasks |= others->mask;
451435c4bbdfSmrg            }
451535c4bbdfSmrg        }
451635c4bbdfSmrg        pChild->deliverableEvents = pChild->eventMask |
451735c4bbdfSmrg            wOtherEventMasks(pChild);
451835c4bbdfSmrg        if (pChild->parent)
451935c4bbdfSmrg            pChild->deliverableEvents |=
452035c4bbdfSmrg                (pChild->parent->deliverableEvents &
452135c4bbdfSmrg                 ~wDontPropagateMask(pChild) & PropagateMask);
452235c4bbdfSmrg        if (pChild->firstChild) {
452335c4bbdfSmrg            pChild = pChild->firstChild;
452435c4bbdfSmrg            continue;
452535c4bbdfSmrg        }
452635c4bbdfSmrg        while (!pChild->nextSib && (pChild != pWin))
452735c4bbdfSmrg            pChild = pChild->parent;
452835c4bbdfSmrg        if (pChild == pWin)
452935c4bbdfSmrg            break;
453035c4bbdfSmrg        pChild = pChild->nextSib;
453105b261ecSmrg    }
453205b261ecSmrg}
453305b261ecSmrg
453405b261ecSmrg/**
453505b261ecSmrg *
453605b261ecSmrg *  \param value must conform to DeleteType
453705b261ecSmrg */
453805b261ecSmrgint
453935c4bbdfSmrgOtherClientGone(void *value, XID id)
454005b261ecSmrg{
454105b261ecSmrg    OtherClientsPtr other, prev;
454235c4bbdfSmrg    WindowPtr pWin = (WindowPtr) value;
454305b261ecSmrg
454405b261ecSmrg    prev = 0;
454535c4bbdfSmrg    for (other = wOtherClients(pWin); other; other = other->next) {
454635c4bbdfSmrg        if (other->resource == id) {
454735c4bbdfSmrg            if (prev)
454835c4bbdfSmrg                prev->next = other->next;
454935c4bbdfSmrg            else {
455035c4bbdfSmrg                if (!(pWin->optional->otherClients = other->next))
455135c4bbdfSmrg                    CheckWindowOptionalNeed(pWin);
455235c4bbdfSmrg            }
455335c4bbdfSmrg            free(other);
455435c4bbdfSmrg            RecalculateDeliverableEvents(pWin);
455535c4bbdfSmrg            return Success;
455635c4bbdfSmrg        }
455735c4bbdfSmrg        prev = other;
455805b261ecSmrg    }
455905b261ecSmrg    FatalError("client not on event list");
456005b261ecSmrg}
456105b261ecSmrg
456205b261ecSmrgint
456305b261ecSmrgEventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
456405b261ecSmrg{
456505b261ecSmrg    Mask check;
456635c4bbdfSmrg    OtherClients *others;
45674642e01fSmrg    DeviceIntPtr dev;
45684642e01fSmrg    int rc;
456905b261ecSmrg
457035c4bbdfSmrg    if (mask & ~AllEventMasks) {
457135c4bbdfSmrg        client->errorValue = mask;
457235c4bbdfSmrg        return BadValue;
457305b261ecSmrg    }
45744642e01fSmrg    check = (mask & ManagerMask);
45754642e01fSmrg    if (check) {
457635c4bbdfSmrg        rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id,
457735c4bbdfSmrg                      RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess);
457835c4bbdfSmrg        if (rc != Success)
457935c4bbdfSmrg            return rc;
45804642e01fSmrg    }
458105b261ecSmrg    check = (mask & AtMostOneClient);
458235c4bbdfSmrg    if (check & (pWin->eventMask | wOtherEventMasks(pWin))) {
458335c4bbdfSmrg        /* It is illegal for two different clients to select on any of the
458435c4bbdfSmrg           events for AtMostOneClient. However, it is OK, for some client to
458535c4bbdfSmrg           continue selecting on one of those events.  */
458635c4bbdfSmrg        if ((wClient(pWin) != client) && (check & pWin->eventMask))
458735c4bbdfSmrg            return BadAccess;
458835c4bbdfSmrg        for (others = wOtherClients(pWin); others; others = others->next) {
458935c4bbdfSmrg            if (!SameClient(others, client) && (check & others->mask))
459035c4bbdfSmrg                return BadAccess;
459135c4bbdfSmrg        }
459205b261ecSmrg    }
459335c4bbdfSmrg    if (wClient(pWin) == client) {
459435c4bbdfSmrg        check = pWin->eventMask;
459535c4bbdfSmrg        pWin->eventMask = mask;
459635c4bbdfSmrg    }
459735c4bbdfSmrg    else {
459835c4bbdfSmrg        for (others = wOtherClients(pWin); others; others = others->next) {
459935c4bbdfSmrg            if (SameClient(others, client)) {
460035c4bbdfSmrg                check = others->mask;
460135c4bbdfSmrg                if (mask == 0) {
460235c4bbdfSmrg                    FreeResource(others->resource, RT_NONE);
460335c4bbdfSmrg                    return Success;
460435c4bbdfSmrg                }
460535c4bbdfSmrg                else
460635c4bbdfSmrg                    others->mask = mask;
460735c4bbdfSmrg                goto maskSet;
460835c4bbdfSmrg            }
460935c4bbdfSmrg        }
461035c4bbdfSmrg        check = 0;
461135c4bbdfSmrg        if (!pWin->optional && !MakeWindowOptional(pWin))
461235c4bbdfSmrg            return BadAlloc;
461335c4bbdfSmrg        others = malloc(sizeof(OtherClients));
461435c4bbdfSmrg        if (!others)
461535c4bbdfSmrg            return BadAlloc;
461635c4bbdfSmrg        others->mask = mask;
461735c4bbdfSmrg        others->resource = FakeClientID(client->index);
461835c4bbdfSmrg        others->next = pWin->optional->otherClients;
461935c4bbdfSmrg        pWin->optional->otherClients = others;
462035c4bbdfSmrg        if (!AddResource(others->resource, RT_OTHERCLIENT, (void *) pWin))
462135c4bbdfSmrg            return BadAlloc;
462235c4bbdfSmrg    }
462335c4bbdfSmrg maskSet:
462435c4bbdfSmrg    if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask)) {
462535c4bbdfSmrg        for (dev = inputInfo.devices; dev; dev = dev->next) {
46264642e01fSmrg            if (dev->valuator && dev->valuator->motionHintWindow == pWin)
46274642e01fSmrg                dev->valuator->motionHintWindow = NullWindow;
46284642e01fSmrg        }
46294642e01fSmrg    }
463005b261ecSmrg    RecalculateDeliverableEvents(pWin);
463105b261ecSmrg    return Success;
463205b261ecSmrg}
463305b261ecSmrg
463405b261ecSmrgint
46354642e01fSmrgEventSuppressForWindow(WindowPtr pWin, ClientPtr client,
463605b261ecSmrg                       Mask mask, Bool *checkOptional)
463705b261ecSmrg{
463835c4bbdfSmrg    int i, freed;
463905b261ecSmrg
464035c4bbdfSmrg    if (mask & ~PropagateMask) {
464135c4bbdfSmrg        client->errorValue = mask;
464235c4bbdfSmrg        return BadValue;
464305b261ecSmrg    }
464405b261ecSmrg    if (pWin->dontPropagate)
464535c4bbdfSmrg        DontPropagateRefCnts[pWin->dontPropagate]--;
464605b261ecSmrg    if (!mask)
464735c4bbdfSmrg        i = 0;
464835c4bbdfSmrg    else {
464935c4bbdfSmrg        for (i = DNPMCOUNT, freed = 0; --i > 0;) {
465035c4bbdfSmrg            if (!DontPropagateRefCnts[i])
465135c4bbdfSmrg                freed = i;
465235c4bbdfSmrg            else if (mask == DontPropagateMasks[i])
465335c4bbdfSmrg                break;
465435c4bbdfSmrg        }
465535c4bbdfSmrg        if (!i && freed) {
465635c4bbdfSmrg            i = freed;
465735c4bbdfSmrg            DontPropagateMasks[i] = mask;
465835c4bbdfSmrg        }
465905b261ecSmrg    }
466035c4bbdfSmrg    if (i || !mask) {
466135c4bbdfSmrg        pWin->dontPropagate = i;
466235c4bbdfSmrg        if (i)
466335c4bbdfSmrg            DontPropagateRefCnts[i]++;
466435c4bbdfSmrg        if (pWin->optional) {
466535c4bbdfSmrg            pWin->optional->dontPropagateMask = mask;
466635c4bbdfSmrg            *checkOptional = TRUE;
466735c4bbdfSmrg        }
466835c4bbdfSmrg    }
466935c4bbdfSmrg    else {
467035c4bbdfSmrg        if (!pWin->optional && !MakeWindowOptional(pWin)) {
467135c4bbdfSmrg            if (pWin->dontPropagate)
467235c4bbdfSmrg                DontPropagateRefCnts[pWin->dontPropagate]++;
467335c4bbdfSmrg            return BadAlloc;
467435c4bbdfSmrg        }
467535c4bbdfSmrg        pWin->dontPropagate = 0;
467605b261ecSmrg        pWin->optional->dontPropagateMask = mask;
467705b261ecSmrg    }
467805b261ecSmrg    RecalculateDeliverableEvents(pWin);
467905b261ecSmrg    return Success;
468005b261ecSmrg}
468105b261ecSmrg
468205b261ecSmrg/**
46834642e01fSmrg * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
46844642e01fSmrg * Uses the paired keyboard to get some additional information.
468505b261ecSmrg */
46864642e01fSmrgvoid
468735c4bbdfSmrgCoreEnterLeaveEvent(DeviceIntPtr mouse,
468835c4bbdfSmrg                    int type,
468935c4bbdfSmrg                    int mode, int detail, WindowPtr pWin, Window child)
469035c4bbdfSmrg{
469135c4bbdfSmrg    xEvent event = {
469235c4bbdfSmrg        .u.u.type = type,
469335c4bbdfSmrg        .u.u.detail = detail
469435c4bbdfSmrg    };
469535c4bbdfSmrg    WindowPtr focus;
469635c4bbdfSmrg    DeviceIntPtr keybd;
469735c4bbdfSmrg    GrabPtr grab = mouse->deviceGrab.grab;
469835c4bbdfSmrg    Mask mask;
469935c4bbdfSmrg
470035c4bbdfSmrg    keybd = GetMaster(mouse, KEYBOARD_OR_FLOAT);
47014642e01fSmrg
470205b261ecSmrg    if ((pWin == mouse->valuator->motionHintWindow) &&
470335c4bbdfSmrg        (detail != NotifyInferior))
470435c4bbdfSmrg        mouse->valuator->motionHintWindow = NullWindow;
470535c4bbdfSmrg    if (grab) {
470635c4bbdfSmrg        mask = (pWin == grab->window) ? grab->eventMask : 0;
470735c4bbdfSmrg        if (grab->ownerEvents)
470835c4bbdfSmrg            mask |= EventMaskForClient(pWin, rClient(grab));
470905b261ecSmrg    }
471035c4bbdfSmrg    else {
471135c4bbdfSmrg        mask = pWin->eventMask | wOtherEventMasks(pWin);
471205b261ecSmrg    }
47134642e01fSmrg
47144642e01fSmrg    event.u.enterLeave.time = currentTime.milliseconds;
47154642e01fSmrg    event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x;
47164642e01fSmrg    event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y;
47174642e01fSmrg    /* Counts on the same initial structure of crossing & button events! */
47189ace9065Smrg    FixUpEventFromWindow(mouse->spriteInfo->sprite, &event, pWin, None, FALSE);
47194642e01fSmrg    /* Enter/Leave events always set child */
47204642e01fSmrg    event.u.enterLeave.child = child;
47214642e01fSmrg    event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
47224642e01fSmrg        ELFlagSameScreen : 0;
472335c4bbdfSmrg    event.u.enterLeave.state =
472435c4bbdfSmrg        mouse->button ? (mouse->button->state & 0x1f00) : 0;
47256747b715Smrg    if (keybd)
47266747b715Smrg        event.u.enterLeave.state |=
472735c4bbdfSmrg            XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
47284642e01fSmrg    event.u.enterLeave.mode = mode;
47294642e01fSmrg    focus = (keybd) ? keybd->focus->win : None;
47304642e01fSmrg    if ((focus != NoneWin) &&
473135c4bbdfSmrg        ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin)))
47324642e01fSmrg        event.u.enterLeave.flags |= ELFlagFocus;
473305b261ecSmrg
473435c4bbdfSmrg    if ((mask & GetEventFilter(mouse, &event))) {
47354642e01fSmrg        if (grab)
47364642e01fSmrg            TryClientEvents(rClient(grab), mouse, &event, 1, mask,
47376747b715Smrg                            GetEventFilter(mouse, &event), grab);
47384642e01fSmrg        else
47394642e01fSmrg            DeliverEventsToWindow(mouse, pWin, &event, 1,
474035c4bbdfSmrg                                  GetEventFilter(mouse, &event), NullGrab);
474105b261ecSmrg    }
474205b261ecSmrg
474335c4bbdfSmrg    if ((type == EnterNotify) && (mask & KeymapStateMask)) {
474435c4bbdfSmrg        xKeymapEvent ke = {
474535c4bbdfSmrg            .type = KeymapNotify
474635c4bbdfSmrg        };
47476747b715Smrg        ClientPtr client = grab ? rClient(grab) : wClient(pWin);
474835c4bbdfSmrg        int rc;
474935c4bbdfSmrg
475035c4bbdfSmrg        rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess);
475135c4bbdfSmrg        if (rc == Success)
475235c4bbdfSmrg            memcpy((char *) &ke.map[0], (char *) &keybd->key->down[1], 31);
47534642e01fSmrg
47544642e01fSmrg        if (grab)
475535c4bbdfSmrg            TryClientEvents(rClient(grab), keybd, (xEvent *) &ke, 1,
47564642e01fSmrg                            mask, KeymapStateMask, grab);
47574642e01fSmrg        else
475835c4bbdfSmrg            DeliverEventsToWindow(mouse, pWin, (xEvent *) &ke, 1,
47596747b715Smrg                                  KeymapStateMask, NullGrab);
47606747b715Smrg    }
47616747b715Smrg}
47626747b715Smrg
47636747b715Smrgvoid
476435c4bbdfSmrgDeviceEnterLeaveEvent(DeviceIntPtr mouse,
476535c4bbdfSmrg                      int sourceid,
476635c4bbdfSmrg                      int type,
476735c4bbdfSmrg                      int mode, int detail, WindowPtr pWin, Window child)
476835c4bbdfSmrg{
476935c4bbdfSmrg    GrabPtr grab = mouse->deviceGrab.grab;
477035c4bbdfSmrg    xXIEnterEvent *event;
477135c4bbdfSmrg    WindowPtr focus;
477235c4bbdfSmrg    int filter;
477335c4bbdfSmrg    int btlen, len, i;
477435c4bbdfSmrg    DeviceIntPtr kbd;
47756747b715Smrg
47766747b715Smrg    if ((mode == XINotifyPassiveGrab && type == XI_Leave) ||
47776747b715Smrg        (mode == XINotifyPassiveUngrab && type == XI_Enter))
47786747b715Smrg        return;
47796747b715Smrg
47806747b715Smrg    btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
47816747b715Smrg    btlen = bytes_to_int32(btlen);
47826747b715Smrg    len = sizeof(xXIEnterEvent) + btlen * 4;
47836747b715Smrg
47846747b715Smrg    event = calloc(1, len);
478535c4bbdfSmrg    event->type = GenericEvent;
478635c4bbdfSmrg    event->extension = IReqCode;
478735c4bbdfSmrg    event->evtype = type;
478835c4bbdfSmrg    event->length = (len - sizeof(xEvent)) / 4;
478935c4bbdfSmrg    event->buttons_len = btlen;
479035c4bbdfSmrg    event->detail = detail;
479135c4bbdfSmrg    event->time = currentTime.milliseconds;
479235c4bbdfSmrg    event->deviceid = mouse->id;
479335c4bbdfSmrg    event->sourceid = sourceid;
479435c4bbdfSmrg    event->mode = mode;
479535c4bbdfSmrg    event->root_x = double_to_fp1616(mouse->spriteInfo->sprite->hot.x);
479635c4bbdfSmrg    event->root_y = double_to_fp1616(mouse->spriteInfo->sprite->hot.y);
47976747b715Smrg
47986747b715Smrg    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
47996747b715Smrg        if (BitIsOn(mouse->button->down, i))
48006747b715Smrg            SetBit(&event[1], i);
48016747b715Smrg
480235c4bbdfSmrg    kbd = GetMaster(mouse, MASTER_KEYBOARD);
480335c4bbdfSmrg    if (kbd && kbd->key) {
48046747b715Smrg        event->mods.base_mods = kbd->key->xkbInfo->state.base_mods;
48056747b715Smrg        event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods;
48066747b715Smrg        event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods;
48076747b715Smrg
48086747b715Smrg        event->group.base_group = kbd->key->xkbInfo->state.base_group;
48096747b715Smrg        event->group.latched_group = kbd->key->xkbInfo->state.latched_group;
48106747b715Smrg        event->group.locked_group = kbd->key->xkbInfo->state.locked_group;
481105b261ecSmrg    }
48126747b715Smrg
481335c4bbdfSmrg    focus = (kbd) ? kbd->focus->win : None;
481435c4bbdfSmrg    if ((focus != NoneWin) &&
481535c4bbdfSmrg        ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin)))
481635c4bbdfSmrg        event->focus = TRUE;
481735c4bbdfSmrg
481835c4bbdfSmrg    FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent *) event, pWin,
48199ace9065Smrg                         None, FALSE);
48206747b715Smrg
482135c4bbdfSmrg    filter = GetEventFilter(mouse, (xEvent *) event);
48226747b715Smrg
482335c4bbdfSmrg    if (grab && grab->grabtype == XI2) {
48246747b715Smrg        Mask mask;
482535c4bbdfSmrg
482635c4bbdfSmrg        mask = xi2mask_isset(grab->xi2mask, mouse, type);
482735c4bbdfSmrg        TryClientEvents(rClient(grab), mouse, (xEvent *) event, 1, mask, 1,
482835c4bbdfSmrg                        grab);
482935c4bbdfSmrg    }
483035c4bbdfSmrg    else {
483135c4bbdfSmrg        if (!WindowXI2MaskIsset(mouse, pWin, (xEvent *) event))
48326747b715Smrg            goto out;
483335c4bbdfSmrg        DeliverEventsToWindow(mouse, pWin, (xEvent *) event, 1, filter,
48346747b715Smrg                              NullGrab);
48356747b715Smrg    }
48366747b715Smrg
483735c4bbdfSmrg out:
48386747b715Smrg    free(event);
483905b261ecSmrg}
484005b261ecSmrg
48414642e01fSmrgvoid
48424642e01fSmrgCoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
484305b261ecSmrg{
484435c4bbdfSmrg    xEvent event = {
484535c4bbdfSmrg        .u.u.type = type,
484635c4bbdfSmrg        .u.u.detail = detail
484735c4bbdfSmrg    };
484805b261ecSmrg    event.u.focus.mode = mode;
484905b261ecSmrg    event.u.focus.window = pWin->drawable.id;
48506747b715Smrg
48516747b715Smrg    DeliverEventsToWindow(dev, pWin, &event, 1,
48526747b715Smrg                          GetEventFilter(dev, &event), NullGrab);
485305b261ecSmrg    if ((type == FocusIn) &&
485435c4bbdfSmrg        ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) {
485535c4bbdfSmrg        xKeymapEvent ke = {
485635c4bbdfSmrg            .type = KeymapNotify
485735c4bbdfSmrg        };
48586747b715Smrg        ClientPtr client = wClient(pWin);
485935c4bbdfSmrg        int rc;
486005b261ecSmrg
486135c4bbdfSmrg        rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess);
486235c4bbdfSmrg        if (rc == Success)
486335c4bbdfSmrg            memcpy((char *) &ke.map[0], (char *) &dev->key->down[1], 31);
486435c4bbdfSmrg
486535c4bbdfSmrg        DeliverEventsToWindow(dev, pWin, (xEvent *) &ke, 1,
486635c4bbdfSmrg                              KeymapStateMask, NullGrab);
486705b261ecSmrg    }
486805b261ecSmrg}
486905b261ecSmrg
487005b261ecSmrg/**
487105b261ecSmrg * Set the input focus to the given window. Subsequent keyboard events will be
487205b261ecSmrg * delivered to the given window.
48734642e01fSmrg *
487405b261ecSmrg * Usually called from ProcSetInputFocus as result of a client request. If so,
487505b261ecSmrg * the device is the inputInfo.keyboard.
487605b261ecSmrg * If called from ProcXSetInputFocus as result of a client xinput request, the
487705b261ecSmrg * device is set to the device specified by the client.
487805b261ecSmrg *
487905b261ecSmrg * @param client Client that requested input focus change.
48804642e01fSmrg * @param dev Focus device.
488105b261ecSmrg * @param focusID The window to obtain the focus. Can be PointerRoot or None.
488205b261ecSmrg * @param revertTo Specifies where the focus reverts to when window becomes
488305b261ecSmrg * unviewable.
488405b261ecSmrg * @param ctime Specifies the time.
488505b261ecSmrg * @param followOK True if pointer is allowed to follow the keyboard.
488605b261ecSmrg */
488705b261ecSmrgint
488835c4bbdfSmrgSetInputFocus(ClientPtr client,
488935c4bbdfSmrg              DeviceIntPtr dev,
489035c4bbdfSmrg              Window focusID, CARD8 revertTo, Time ctime, Bool followOK)
489105b261ecSmrg{
489205b261ecSmrg    FocusClassPtr focus;
489305b261ecSmrg    WindowPtr focusWin;
489405b261ecSmrg    int mode, rc;
489505b261ecSmrg    TimeStamp time;
489635c4bbdfSmrg    DeviceIntPtr keybd;         /* used for FollowKeyboard or FollowKeyboardWin */
489705b261ecSmrg
489805b261ecSmrg    UpdateCurrentTime();
489905b261ecSmrg    if ((revertTo != RevertToParent) &&
490035c4bbdfSmrg        (revertTo != RevertToPointerRoot) &&
490135c4bbdfSmrg        (revertTo != RevertToNone) &&
490235c4bbdfSmrg        ((revertTo != RevertToFollowKeyboard) || !followOK)) {
490335c4bbdfSmrg        client->errorValue = revertTo;
490435c4bbdfSmrg        return BadValue;
490505b261ecSmrg    }
490605b261ecSmrg    time = ClientTimeToServerTime(ctime);
49074642e01fSmrg
490835c4bbdfSmrg    keybd = GetMaster(dev, KEYBOARD_OR_FLOAT);
49094642e01fSmrg
491005b261ecSmrg    if ((focusID == None) || (focusID == PointerRoot))
491135c4bbdfSmrg        focusWin = (WindowPtr) (long) focusID;
491235c4bbdfSmrg    else if ((focusID == FollowKeyboard) && followOK) {
491335c4bbdfSmrg        focusWin = keybd->focus->win;
49144642e01fSmrg    }
491505b261ecSmrg    else {
491635c4bbdfSmrg        rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess);
491735c4bbdfSmrg        if (rc != Success)
491835c4bbdfSmrg            return rc;
491935c4bbdfSmrg        /* It is a match error to try to set the input focus to an
492035c4bbdfSmrg           unviewable window. */
492135c4bbdfSmrg        if (!focusWin->realized)
492235c4bbdfSmrg            return BadMatch;
492305b261ecSmrg    }
49244642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess);
49254642e01fSmrg    if (rc != Success)
492635c4bbdfSmrg        return Success;
49274642e01fSmrg
492805b261ecSmrg    focus = dev->focus;
492905b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
493035c4bbdfSmrg        (CompareTimeStamps(time, focus->time) == EARLIER))
493135c4bbdfSmrg        return Success;
49324642e01fSmrg    mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal;
493335c4bbdfSmrg    if (focus->win == FollowKeyboardWin) {
49346747b715Smrg        if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin))
49356747b715Smrg            DoFocusEvents(dev, keybd->focus->win, focusWin, mode);
493635c4bbdfSmrg    }
493735c4bbdfSmrg    else {
49386747b715Smrg        if (!ActivateFocusInGrab(dev, focus->win, focusWin))
49396747b715Smrg            DoFocusEvents(dev, focus->win, focusWin, mode);
49406747b715Smrg    }
494105b261ecSmrg    focus->time = time;
494205b261ecSmrg    focus->revert = revertTo;
494305b261ecSmrg    if (focusID == FollowKeyboard)
494435c4bbdfSmrg        focus->win = FollowKeyboardWin;
494505b261ecSmrg    else
494635c4bbdfSmrg        focus->win = focusWin;
494705b261ecSmrg    if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
494835c4bbdfSmrg        focus->traceGood = 0;
494935c4bbdfSmrg    else {
495005b261ecSmrg        int depth = 0;
495135c4bbdfSmrg        WindowPtr pWin;
495235c4bbdfSmrg
495335c4bbdfSmrg        for (pWin = focusWin; pWin; pWin = pWin->parent)
495435c4bbdfSmrg            depth++;
495535c4bbdfSmrg        if (depth > focus->traceSize) {
495635c4bbdfSmrg            focus->traceSize = depth + 1;
495735c4bbdfSmrg            focus->trace = reallocarray(focus->trace, focus->traceSize,
495835c4bbdfSmrg                                        sizeof(WindowPtr));
495935c4bbdfSmrg        }
496035c4bbdfSmrg        focus->traceGood = depth;
49614642e01fSmrg        for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
496235c4bbdfSmrg            focus->trace[depth] = pWin;
496305b261ecSmrg    }
496405b261ecSmrg    return Success;
496505b261ecSmrg}
496605b261ecSmrg
496705b261ecSmrg/**
496805b261ecSmrg * Server-side protocol handling for SetInputFocus request.
496905b261ecSmrg *
497005b261ecSmrg * Sets the input focus for the virtual core keyboard.
497105b261ecSmrg */
497205b261ecSmrgint
49736747b715SmrgProcSetInputFocus(ClientPtr client)
497405b261ecSmrg{
49754642e01fSmrg    DeviceIntPtr kbd = PickKeyboard(client);
497635c4bbdfSmrg
497705b261ecSmrg    REQUEST(xSetInputFocusReq);
497805b261ecSmrg
497905b261ecSmrg    REQUEST_SIZE_MATCH(xSetInputFocusReq);
498005b261ecSmrg
49814642e01fSmrg    return SetInputFocus(client, kbd, stuff->focus,
498235c4bbdfSmrg                         stuff->revertTo, stuff->time, FALSE);
498305b261ecSmrg}
498405b261ecSmrg
498505b261ecSmrg/**
498605b261ecSmrg * Server-side protocol handling for GetInputFocus request.
49874642e01fSmrg *
49884642e01fSmrg * Sends the current input focus for the client's keyboard back to the
498905b261ecSmrg * client.
499005b261ecSmrg */
499105b261ecSmrgint
499205b261ecSmrgProcGetInputFocus(ClientPtr client)
499305b261ecSmrg{
49944642e01fSmrg    DeviceIntPtr kbd = PickKeyboard(client);
499505b261ecSmrg    xGetInputFocusReply rep;
49964642e01fSmrg    FocusClassPtr focus = kbd->focus;
49974642e01fSmrg    int rc;
499835c4bbdfSmrg
499905b261ecSmrg    /* REQUEST(xReq); */
500005b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
50014642e01fSmrg
50024642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess);
50034642e01fSmrg    if (rc != Success)
500435c4bbdfSmrg        return rc;
500535c4bbdfSmrg
500635c4bbdfSmrg    rep = (xGetInputFocusReply) {
500735c4bbdfSmrg        .type = X_Reply,
500835c4bbdfSmrg        .length = 0,
500935c4bbdfSmrg        .sequenceNumber = client->sequence,
501035c4bbdfSmrg        .revertTo = focus->revert
501135c4bbdfSmrg    };
50124642e01fSmrg
501305b261ecSmrg    if (focus->win == NoneWin)
501435c4bbdfSmrg        rep.focus = None;
501505b261ecSmrg    else if (focus->win == PointerRootWin)
501635c4bbdfSmrg        rep.focus = PointerRoot;
501735c4bbdfSmrg    else
501835c4bbdfSmrg        rep.focus = focus->win->drawable.id;
501935c4bbdfSmrg
502005b261ecSmrg    WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
502105b261ecSmrg    return Success;
502205b261ecSmrg}
502305b261ecSmrg
502405b261ecSmrg/**
50254642e01fSmrg * Server-side protocol handling for GrabPointer request.
502605b261ecSmrg *
50274642e01fSmrg * Sets an active grab on the client's ClientPointer and returns success
50284642e01fSmrg * status to client.
502905b261ecSmrg */
503005b261ecSmrgint
503105b261ecSmrgProcGrabPointer(ClientPtr client)
503205b261ecSmrg{
503305b261ecSmrg    xGrabPointerReply rep;
50344642e01fSmrg    DeviceIntPtr device = PickPointer(client);
503505b261ecSmrg    GrabPtr grab;
50366747b715Smrg    GrabMask mask;
50376747b715Smrg    WindowPtr confineTo;
503835c4bbdfSmrg    BYTE status;
503935c4bbdfSmrg
504005b261ecSmrg    REQUEST(xGrabPointerReq);
504105b261ecSmrg    int rc;
504205b261ecSmrg
504305b261ecSmrg    REQUEST_SIZE_MATCH(xGrabPointerReq);
504405b261ecSmrg    UpdateCurrentTime();
50456747b715Smrg
504635c4bbdfSmrg    if (stuff->eventMask & ~PointerGrabMask) {
504735c4bbdfSmrg        client->errorValue = stuff->eventMask;
504805b261ecSmrg        return BadValue;
504905b261ecSmrg    }
50506747b715Smrg
505105b261ecSmrg    if (stuff->confineTo == None)
505235c4bbdfSmrg        confineTo = NullWindow;
505335c4bbdfSmrg    else {
505435c4bbdfSmrg        rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
505535c4bbdfSmrg                             DixSetAttrAccess);
505635c4bbdfSmrg        if (rc != Success)
505735c4bbdfSmrg            return rc;
505805b261ecSmrg    }
50596747b715Smrg
50606747b715Smrg    grab = device->deviceGrab.grab;
50616747b715Smrg
506235c4bbdfSmrg    if (grab && grab->confineTo && !confineTo)
506335c4bbdfSmrg        ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE, FALSE);
50646747b715Smrg
50656747b715Smrg    mask.core = stuff->eventMask;
50666747b715Smrg
50676747b715Smrg    rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode,
50686747b715Smrg                    stuff->grabWindow, stuff->ownerEvents, stuff->time,
506935c4bbdfSmrg                    &mask, CORE, stuff->cursor, stuff->confineTo, &status);
50704642e01fSmrg    if (rc != Success)
50716747b715Smrg        return rc;
50726747b715Smrg
507335c4bbdfSmrg    rep = (xGrabPointerReply) {
507435c4bbdfSmrg        .type = X_Reply,
507535c4bbdfSmrg        .status = status,
507635c4bbdfSmrg        .sequenceNumber = client->sequence,
507735c4bbdfSmrg        .length = 0
507835c4bbdfSmrg    };
507905b261ecSmrg    WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
508005b261ecSmrg    return Success;
508105b261ecSmrg}
508205b261ecSmrg
508305b261ecSmrg/**
508405b261ecSmrg * Server-side protocol handling for ChangeActivePointerGrab request.
508505b261ecSmrg *
508605b261ecSmrg * Changes properties of the grab hold by the client. If the client does not
50874642e01fSmrg * hold an active grab on the device, nothing happens.
508805b261ecSmrg */
508905b261ecSmrgint
509005b261ecSmrgProcChangeActivePointerGrab(ClientPtr client)
509105b261ecSmrg{
50924642e01fSmrg    DeviceIntPtr device;
509335c4bbdfSmrg    GrabPtr grab;
509405b261ecSmrg    CursorPtr newCursor, oldCursor;
509535c4bbdfSmrg
509605b261ecSmrg    REQUEST(xChangeActivePointerGrabReq);
509705b261ecSmrg    TimeStamp time;
509805b261ecSmrg
509905b261ecSmrg    REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
510035c4bbdfSmrg    if (stuff->eventMask & ~PointerGrabMask) {
510135c4bbdfSmrg        client->errorValue = stuff->eventMask;
510205b261ecSmrg        return BadValue;
510305b261ecSmrg    }
510405b261ecSmrg    if (stuff->cursor == None)
510535c4bbdfSmrg        newCursor = NullCursor;
510635c4bbdfSmrg    else {
510735c4bbdfSmrg        int rc = dixLookupResourceByType((void **) &newCursor, stuff->cursor,
510835c4bbdfSmrg                                         RT_CURSOR, client, DixUseAccess);
510935c4bbdfSmrg
511035c4bbdfSmrg        if (rc != Success) {
511135c4bbdfSmrg            client->errorValue = stuff->cursor;
511235c4bbdfSmrg            return rc;
511335c4bbdfSmrg        }
511405b261ecSmrg    }
51154642e01fSmrg
51164642e01fSmrg    device = PickPointer(client);
51174642e01fSmrg    grab = device->deviceGrab.grab;
51184642e01fSmrg
511905b261ecSmrg    if (!grab)
512035c4bbdfSmrg        return Success;
512105b261ecSmrg    if (!SameClient(grab, client))
512235c4bbdfSmrg        return Success;
51237e31ba66Smrg    UpdateCurrentTime();
512405b261ecSmrg    time = ClientTimeToServerTime(stuff->time);
512505b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
512635c4bbdfSmrg        (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
512735c4bbdfSmrg        return Success;
512805b261ecSmrg    oldCursor = grab->cursor;
512935c4bbdfSmrg    grab->cursor = RefCursor(newCursor);
51304642e01fSmrg    PostNewCursor(device);
513105b261ecSmrg    if (oldCursor)
513235c4bbdfSmrg        FreeCursor(oldCursor, (Cursor) 0);
513305b261ecSmrg    grab->eventMask = stuff->eventMask;
513405b261ecSmrg    return Success;
513505b261ecSmrg}
513605b261ecSmrg
513705b261ecSmrg/**
513805b261ecSmrg * Server-side protocol handling for UngrabPointer request.
513905b261ecSmrg *
51404642e01fSmrg * Deletes a pointer grab on a device the client has grabbed.
514105b261ecSmrg */
514205b261ecSmrgint
514305b261ecSmrgProcUngrabPointer(ClientPtr client)
514405b261ecSmrg{
51454642e01fSmrg    DeviceIntPtr device = PickPointer(client);
514605b261ecSmrg    GrabPtr grab;
514705b261ecSmrg    TimeStamp time;
514835c4bbdfSmrg
514905b261ecSmrg    REQUEST(xResourceReq);
515005b261ecSmrg
515105b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
515205b261ecSmrg    UpdateCurrentTime();
51534642e01fSmrg    grab = device->deviceGrab.grab;
51544642e01fSmrg
515505b261ecSmrg    time = ClientTimeToServerTime(stuff->id);
515605b261ecSmrg    if ((CompareTimeStamps(time, currentTime) != LATER) &&
515735c4bbdfSmrg        (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
515835c4bbdfSmrg        (grab) && SameClient(grab, client))
515935c4bbdfSmrg        (*device->deviceGrab.DeactivateGrab) (device);
516005b261ecSmrg    return Success;
516105b261ecSmrg}
516205b261ecSmrg
516305b261ecSmrg/**
516405b261ecSmrg * Sets a grab on the given device.
51654642e01fSmrg *
51664642e01fSmrg * Called from ProcGrabKeyboard to work on the client's keyboard.
516705b261ecSmrg * Called from ProcXGrabDevice to work on the device specified by the client.
51684642e01fSmrg *
516905b261ecSmrg * The parameters this_mode and other_mode represent the keyboard_mode and
51704642e01fSmrg * pointer_mode parameters of XGrabKeyboard().
517105b261ecSmrg * See man page for details on all the parameters
51724642e01fSmrg *
517305b261ecSmrg * @param client Client that owns the grab.
51744642e01fSmrg * @param dev The device to grab.
517505b261ecSmrg * @param this_mode GrabModeSync or GrabModeAsync
517605b261ecSmrg * @param other_mode GrabModeSync or GrabModeAsync
517705b261ecSmrg * @param status Return code to be returned to the caller.
51784642e01fSmrg *
517935c4bbdfSmrg * @returns Success or BadValue or BadAlloc.
518005b261ecSmrg */
518105b261ecSmrgint
51824642e01fSmrgGrabDevice(ClientPtr client, DeviceIntPtr dev,
51836747b715Smrg           unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow,
51846747b715Smrg           unsigned ownerEvents, Time ctime, GrabMask *mask,
51856747b715Smrg           int grabtype, Cursor curs, Window confineToWin, CARD8 *status)
518605b261ecSmrg{
51876747b715Smrg    WindowPtr pWin, confineTo;
518805b261ecSmrg    GrabPtr grab;
518905b261ecSmrg    TimeStamp time;
51904642e01fSmrg    Mask access_mode = DixGrabAccess;
519105b261ecSmrg    int rc;
51924642e01fSmrg    GrabInfoPtr grabInfo = &dev->deviceGrab;
51936747b715Smrg    CursorPtr cursor;
519405b261ecSmrg
519505b261ecSmrg    UpdateCurrentTime();
519635c4bbdfSmrg    if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync)) {
519735c4bbdfSmrg        client->errorValue = keyboard_mode;
519805b261ecSmrg        return BadValue;
519905b261ecSmrg    }
520035c4bbdfSmrg    if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync)) {
520135c4bbdfSmrg        client->errorValue = pointer_mode;
520205b261ecSmrg        return BadValue;
520305b261ecSmrg    }
520435c4bbdfSmrg    if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) {
520535c4bbdfSmrg        client->errorValue = ownerEvents;
520605b261ecSmrg        return BadValue;
520705b261ecSmrg    }
52084642e01fSmrg
52094642e01fSmrg    rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
521005b261ecSmrg    if (rc != Success)
521135c4bbdfSmrg        return rc;
52126747b715Smrg
52136747b715Smrg    if (confineToWin == None)
521435c4bbdfSmrg        confineTo = NullWindow;
521535c4bbdfSmrg    else {
521635c4bbdfSmrg        rc = dixLookupWindow(&confineTo, confineToWin, client,
521735c4bbdfSmrg                             DixSetAttrAccess);
521835c4bbdfSmrg        if (rc != Success)
521935c4bbdfSmrg            return rc;
52206747b715Smrg    }
52216747b715Smrg
52226747b715Smrg    if (curs == None)
522335c4bbdfSmrg        cursor = NullCursor;
522435c4bbdfSmrg    else {
522535c4bbdfSmrg        rc = dixLookupResourceByType((void **) &cursor, curs, RT_CURSOR,
522635c4bbdfSmrg                                     client, DixUseAccess);
522735c4bbdfSmrg        if (rc != Success) {
522835c4bbdfSmrg            client->errorValue = curs;
522935c4bbdfSmrg            return rc;
523035c4bbdfSmrg        }
523135c4bbdfSmrg        access_mode |= DixForceAccess;
52326747b715Smrg    }
52336747b715Smrg
52346747b715Smrg    if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync)
523535c4bbdfSmrg        access_mode |= DixFreezeAccess;
52364642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
52374642e01fSmrg    if (rc != Success)
523835c4bbdfSmrg        return rc;
52394642e01fSmrg
524005b261ecSmrg    time = ClientTimeToServerTime(ctime);
52414642e01fSmrg    grab = grabInfo->grab;
52426747b715Smrg    if (grab && grab->grabtype != grabtype)
52436747b715Smrg        *status = AlreadyGrabbed;
524435c4bbdfSmrg    else if (grab && !SameClient(grab, client))
524535c4bbdfSmrg        *status = AlreadyGrabbed;
52466747b715Smrg    else if ((!pWin->realized) ||
52476747b715Smrg             (confineTo &&
524835c4bbdfSmrg              !(confineTo->realized && BorderSizeNotEmpty(dev, confineTo))))
524935c4bbdfSmrg        *status = GrabNotViewable;
525005b261ecSmrg    else if ((CompareTimeStamps(time, currentTime) == LATER) ||
525135c4bbdfSmrg             (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER))
525235c4bbdfSmrg        *status = GrabInvalidTime;
52534642e01fSmrg    else if (grabInfo->sync.frozen &&
525435c4bbdfSmrg             grabInfo->sync.other && !SameClient(grabInfo->sync.other, client))
525535c4bbdfSmrg        *status = GrabFrozen;
525635c4bbdfSmrg    else {
525735c4bbdfSmrg        GrabPtr tempGrab;
525835c4bbdfSmrg
525935c4bbdfSmrg        tempGrab = AllocGrab(NULL);
526035c4bbdfSmrg        if (tempGrab == NULL)
526135c4bbdfSmrg            return BadAlloc;
526235c4bbdfSmrg
526335c4bbdfSmrg        tempGrab->next = NULL;
526435c4bbdfSmrg        tempGrab->window = pWin;
526535c4bbdfSmrg        tempGrab->resource = client->clientAsMask;
526635c4bbdfSmrg        tempGrab->ownerEvents = ownerEvents;
526735c4bbdfSmrg        tempGrab->keyboardMode = keyboard_mode;
526835c4bbdfSmrg        tempGrab->pointerMode = pointer_mode;
526935c4bbdfSmrg        if (grabtype == CORE)
527035c4bbdfSmrg            tempGrab->eventMask = mask->core;
527135c4bbdfSmrg        else if (grabtype == XI)
527235c4bbdfSmrg            tempGrab->eventMask = mask->xi;
527335c4bbdfSmrg        else
527435c4bbdfSmrg            xi2mask_merge(tempGrab->xi2mask, mask->xi2mask);
527535c4bbdfSmrg        tempGrab->device = dev;
527635c4bbdfSmrg        tempGrab->cursor = RefCursor(cursor);
527735c4bbdfSmrg        tempGrab->confineTo = confineTo;
527835c4bbdfSmrg        tempGrab->grabtype = grabtype;
527935c4bbdfSmrg        (*grabInfo->ActivateGrab) (dev, tempGrab, time, FALSE);
528035c4bbdfSmrg        *status = GrabSuccess;
528135c4bbdfSmrg
528235c4bbdfSmrg        FreeGrab(tempGrab);
528305b261ecSmrg    }
528405b261ecSmrg    return Success;
528505b261ecSmrg}
528605b261ecSmrg
528705b261ecSmrg/**
528805b261ecSmrg * Server-side protocol handling for GrabKeyboard request.
528905b261ecSmrg *
52904642e01fSmrg * Grabs the client's keyboard and returns success status to client.
529105b261ecSmrg */
529205b261ecSmrgint
529305b261ecSmrgProcGrabKeyboard(ClientPtr client)
529405b261ecSmrg{
529505b261ecSmrg    xGrabKeyboardReply rep;
529635c4bbdfSmrg    BYTE status;
529735c4bbdfSmrg
529805b261ecSmrg    REQUEST(xGrabKeyboardReq);
529905b261ecSmrg    int result;
53004642e01fSmrg    DeviceIntPtr keyboard = PickKeyboard(client);
53016747b715Smrg    GrabMask mask;
530205b261ecSmrg
530305b261ecSmrg    REQUEST_SIZE_MATCH(xGrabKeyboardReq);
53047e31ba66Smrg    UpdateCurrentTime();
530505b261ecSmrg
53066747b715Smrg    mask.core = KeyPressMask | KeyReleaseMask;
53076747b715Smrg
53086747b715Smrg    result = GrabDevice(client, keyboard, stuff->pointerMode,
530935c4bbdfSmrg                        stuff->keyboardMode, stuff->grabWindow,
531035c4bbdfSmrg                        stuff->ownerEvents, stuff->time, &mask, CORE, None,
531135c4bbdfSmrg                        None, &status);
531205b261ecSmrg
531305b261ecSmrg    if (result != Success)
531435c4bbdfSmrg        return result;
531535c4bbdfSmrg
531635c4bbdfSmrg    rep = (xGrabKeyboardReply) {
531735c4bbdfSmrg        .type = X_Reply,
531835c4bbdfSmrg        .status = status,
531935c4bbdfSmrg        .sequenceNumber = client->sequence,
532035c4bbdfSmrg        .length = 0
532135c4bbdfSmrg    };
532205b261ecSmrg    WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
532305b261ecSmrg    return Success;
532405b261ecSmrg}
532505b261ecSmrg
532605b261ecSmrg/**
532705b261ecSmrg * Server-side protocol handling for UngrabKeyboard request.
532805b261ecSmrg *
53294642e01fSmrg * Deletes a possible grab on the client's keyboard.
533005b261ecSmrg */
533105b261ecSmrgint
533205b261ecSmrgProcUngrabKeyboard(ClientPtr client)
533305b261ecSmrg{
53344642e01fSmrg    DeviceIntPtr device = PickKeyboard(client);
533505b261ecSmrg    GrabPtr grab;
533605b261ecSmrg    TimeStamp time;
533735c4bbdfSmrg
533805b261ecSmrg    REQUEST(xResourceReq);
533905b261ecSmrg
534005b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
534105b261ecSmrg    UpdateCurrentTime();
53424642e01fSmrg
53434642e01fSmrg    grab = device->deviceGrab.grab;
53444642e01fSmrg
534505b261ecSmrg    time = ClientTimeToServerTime(stuff->id);
534605b261ecSmrg    if ((CompareTimeStamps(time, currentTime) != LATER) &&
534735c4bbdfSmrg        (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
534835c4bbdfSmrg        (grab) && SameClient(grab, client) && grab->grabtype == CORE)
534935c4bbdfSmrg        (*device->deviceGrab.DeactivateGrab) (device);
535005b261ecSmrg    return Success;
535105b261ecSmrg}
535205b261ecSmrg
535305b261ecSmrg/**
535405b261ecSmrg * Server-side protocol handling for QueryPointer request.
535505b261ecSmrg *
53564642e01fSmrg * Returns the current state and position of the client's ClientPointer to the
53574642e01fSmrg * client.
535805b261ecSmrg */
535905b261ecSmrgint
536005b261ecSmrgProcQueryPointer(ClientPtr client)
536105b261ecSmrg{
536205b261ecSmrg    xQueryPointerReply rep;
536305b261ecSmrg    WindowPtr pWin, t;
53644642e01fSmrg    DeviceIntPtr mouse = PickPointer(client);
53656747b715Smrg    DeviceIntPtr keyboard;
53664642e01fSmrg    SpritePtr pSprite;
536705b261ecSmrg    int rc;
536835c4bbdfSmrg
53694642e01fSmrg    REQUEST(xResourceReq);
537005b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
53714642e01fSmrg
53724642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
53734642e01fSmrg    if (rc != Success)
537435c4bbdfSmrg        return rc;
53754642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
53766747b715Smrg    if (rc != Success && rc != BadAccess)
537735c4bbdfSmrg        return rc;
53784642e01fSmrg
537935c4bbdfSmrg    keyboard = GetMaster(mouse, MASTER_KEYBOARD);
53806747b715Smrg
53814642e01fSmrg    pSprite = mouse->spriteInfo->sprite;
538205b261ecSmrg    if (mouse->valuator->motionHintWindow)
538335c4bbdfSmrg        MaybeStopHint(mouse, client);
538435c4bbdfSmrg    rep = (xQueryPointerReply) {
538535c4bbdfSmrg        .type = X_Reply,
538635c4bbdfSmrg        .sequenceNumber = client->sequence,
538735c4bbdfSmrg        .length = 0,
538835c4bbdfSmrg        .mask = event_get_corestate(mouse, keyboard),
538935c4bbdfSmrg        .root = (GetCurrentRootWindow(mouse))->drawable.id,
539035c4bbdfSmrg        .rootX = pSprite->hot.x,
539135c4bbdfSmrg        .rootY = pSprite->hot.y,
539235c4bbdfSmrg        .child = None
539335c4bbdfSmrg    };
539435c4bbdfSmrg    if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
539535c4bbdfSmrg        rep.sameScreen = xTrue;
539635c4bbdfSmrg        rep.winX = pSprite->hot.x - pWin->drawable.x;
539735c4bbdfSmrg        rep.winY = pSprite->hot.y - pWin->drawable.y;
539835c4bbdfSmrg        for (t = pSprite->win; t; t = t->parent)
539935c4bbdfSmrg            if (t->parent == pWin) {
540035c4bbdfSmrg                rep.child = t->drawable.id;
540135c4bbdfSmrg                break;
540235c4bbdfSmrg            }
540305b261ecSmrg    }
540435c4bbdfSmrg    else {
540535c4bbdfSmrg        rep.sameScreen = xFalse;
540635c4bbdfSmrg        rep.winX = 0;
540735c4bbdfSmrg        rep.winY = 0;
540805b261ecSmrg    }
540905b261ecSmrg
541005b261ecSmrg#ifdef PANORAMIX
541135c4bbdfSmrg    if (!noPanoramiXExtension) {
541235c4bbdfSmrg        rep.rootX += screenInfo.screens[0]->x;
541335c4bbdfSmrg        rep.rootY += screenInfo.screens[0]->y;
541435c4bbdfSmrg        if (stuff->id == rep.root) {
541535c4bbdfSmrg            rep.winX += screenInfo.screens[0]->x;
541635c4bbdfSmrg            rep.winY += screenInfo.screens[0]->y;
541735c4bbdfSmrg        }
541805b261ecSmrg    }
541905b261ecSmrg#endif
542005b261ecSmrg
54216747b715Smrg    if (rc == BadAccess) {
542235c4bbdfSmrg        rep.mask = 0;
542335c4bbdfSmrg        rep.child = None;
542435c4bbdfSmrg        rep.rootX = 0;
542535c4bbdfSmrg        rep.rootY = 0;
542635c4bbdfSmrg        rep.winX = 0;
542735c4bbdfSmrg        rep.winY = 0;
54286747b715Smrg    }
54296747b715Smrg
543005b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
543105b261ecSmrg
54326747b715Smrg    return Success;
543305b261ecSmrg}
543405b261ecSmrg
543505b261ecSmrg/**
543605b261ecSmrg * Initializes the device list and the DIX sprite to sane values. Allocates
543705b261ecSmrg * trace memory used for quick window traversal.
543805b261ecSmrg */
543905b261ecSmrgvoid
544005b261ecSmrgInitEvents(void)
544105b261ecSmrg{
544205b261ecSmrg    int i;
544335c4bbdfSmrg    QdEventPtr qe, tmp;
544405b261ecSmrg
544505b261ecSmrg    inputInfo.numDevices = 0;
544635c4bbdfSmrg    inputInfo.devices = (DeviceIntPtr) NULL;
544735c4bbdfSmrg    inputInfo.off_devices = (DeviceIntPtr) NULL;
544835c4bbdfSmrg    inputInfo.keyboard = (DeviceIntPtr) NULL;
544935c4bbdfSmrg    inputInfo.pointer = (DeviceIntPtr) NULL;
545035c4bbdfSmrg
545135c4bbdfSmrg    for (i = 0; i < MAXDEVICES; i++) {
545235c4bbdfSmrg        DeviceIntRec dummy;
545335c4bbdfSmrg        memcpy(&event_filters[i], default_filter, sizeof(default_filter));
545435c4bbdfSmrg
545535c4bbdfSmrg        dummy.id = i;
545635c4bbdfSmrg        NoticeTime(&dummy, currentTime);
545735c4bbdfSmrg        LastEventTimeToggleResetFlag(i, FALSE);
545805b261ecSmrg    }
54594642e01fSmrg
546035c4bbdfSmrg    syncEvents.replayDev = (DeviceIntPtr) NULL;
546105b261ecSmrg    syncEvents.replayWin = NullWindow;
546235c4bbdfSmrg    if (syncEvents.pending.next)
546335c4bbdfSmrg        xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next)
546435c4bbdfSmrg            free(qe);
546535c4bbdfSmrg    xorg_list_init(&syncEvents.pending);
546605b261ecSmrg    syncEvents.playingEvents = FALSE;
546705b261ecSmrg    syncEvents.time.months = 0;
546835c4bbdfSmrg    syncEvents.time.milliseconds = 0;   /* hardly matters */
546905b261ecSmrg    currentTime.months = 0;
547005b261ecSmrg    currentTime.milliseconds = GetTimeInMillis();
547135c4bbdfSmrg    for (i = 0; i < DNPMCOUNT; i++) {
547235c4bbdfSmrg        DontPropagateMasks[i] = 0;
547335c4bbdfSmrg        DontPropagateRefCnts[i] = 0;
547405b261ecSmrg    }
54754642e01fSmrg
547635c4bbdfSmrg    InputEventList = InitEventList(GetMaximumEventsNum());
54774642e01fSmrg    if (!InputEventList)
54784642e01fSmrg        FatalError("[dix] Failed to allocate input event list.\n");
547905b261ecSmrg}
548005b261ecSmrg
548105b261ecSmrgvoid
548205b261ecSmrgCloseDownEvents(void)
548305b261ecSmrg{
548435c4bbdfSmrg    FreeEventList(InputEventList, GetMaximumEventsNum());
54856747b715Smrg    InputEventList = NULL;
548605b261ecSmrg}
548705b261ecSmrg
5488475c125cSmrg#define SEND_EVENT_BIT 0x80
5489475c125cSmrg
549005b261ecSmrg/**
549105b261ecSmrg * Server-side protocol handling for SendEvent request.
549205b261ecSmrg *
54934642e01fSmrg * Locates the window to send the event to and forwards the event.
549405b261ecSmrg */
549505b261ecSmrgint
549605b261ecSmrgProcSendEvent(ClientPtr client)
549705b261ecSmrg{
549805b261ecSmrg    WindowPtr pWin;
549935c4bbdfSmrg    WindowPtr effectiveFocus = NullWindow;      /* only set if dest==InputFocus */
55006747b715Smrg    DeviceIntPtr dev = PickPointer(client);
550135c4bbdfSmrg    DeviceIntPtr keybd = GetMaster(dev, MASTER_KEYBOARD);
55026747b715Smrg    SpritePtr pSprite = dev->spriteInfo->sprite;
550335c4bbdfSmrg
550405b261ecSmrg    REQUEST(xSendEventReq);
550505b261ecSmrg
550605b261ecSmrg    REQUEST_SIZE_MATCH(xSendEventReq);
550705b261ecSmrg
5508475c125cSmrg    /* libXext and other extension libraries may set the bit indicating
5509475c125cSmrg     * that this event came from a SendEvent request so remove it
5510475c125cSmrg     * since otherwise the event type may fail the range checks
5511475c125cSmrg     * and cause an invalid BadValue error to be returned.
5512475c125cSmrg     *
5513475c125cSmrg     * This is safe to do since we later add the SendEvent bit (0x80)
5514475c125cSmrg     * back in once we send the event to the client */
5515475c125cSmrg
5516475c125cSmrg    stuff->event.u.u.type &= ~(SEND_EVENT_BIT);
5517475c125cSmrg
551805b261ecSmrg    /* The client's event type must be a core event type or one defined by an
551935c4bbdfSmrg       extension. */
552005b261ecSmrg
552135c4bbdfSmrg    if (!((stuff->event.u.u.type > X_Reply &&
552235c4bbdfSmrg           stuff->event.u.u.type < LASTEvent) ||
552335c4bbdfSmrg          (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
552435c4bbdfSmrg           stuff->event.u.u.type < (unsigned) lastEvent))) {
552535c4bbdfSmrg        client->errorValue = stuff->event.u.u.type;
552635c4bbdfSmrg        return BadValue;
552705b261ecSmrg    }
55280679523aSmrg    /* Generic events can have variable size, but SendEvent request holds
55290679523aSmrg       exactly 32B of event data. */
55300679523aSmrg    if (stuff->event.u.u.type == GenericEvent) {
55310679523aSmrg        client->errorValue = stuff->event.u.u.type;
55320679523aSmrg        return BadValue;
55330679523aSmrg    }
553405b261ecSmrg    if (stuff->event.u.u.type == ClientMessage &&
553535c4bbdfSmrg        stuff->event.u.u.detail != 8 &&
553635c4bbdfSmrg        stuff->event.u.u.detail != 16 && stuff->event.u.u.detail != 32) {
553735c4bbdfSmrg        client->errorValue = stuff->event.u.u.detail;
553835c4bbdfSmrg        return BadValue;
553905b261ecSmrg    }
554035c4bbdfSmrg    if (stuff->eventMask & ~AllEventMasks) {
554135c4bbdfSmrg        client->errorValue = stuff->eventMask;
554235c4bbdfSmrg        return BadValue;
554305b261ecSmrg    }
554405b261ecSmrg
554505b261ecSmrg    if (stuff->destination == PointerWindow)
554635c4bbdfSmrg        pWin = pSprite->win;
554735c4bbdfSmrg    else if (stuff->destination == InputFocus) {
554835c4bbdfSmrg        WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin;
554905b261ecSmrg
555035c4bbdfSmrg        if (inputFocus == NoneWin)
555135c4bbdfSmrg            return Success;
555205b261ecSmrg
555335c4bbdfSmrg        /* If the input focus is PointerRootWin, send the event to where
55545a112b11Smrg           the pointer is if possible, then perhaps propagate up to root. */
555535c4bbdfSmrg        if (inputFocus == PointerRootWin)
555635c4bbdfSmrg            inputFocus = GetCurrentRootWindow(dev);
555705b261ecSmrg
555835c4bbdfSmrg        if (IsParent(inputFocus, pSprite->win)) {
555935c4bbdfSmrg            effectiveFocus = inputFocus;
556035c4bbdfSmrg            pWin = pSprite->win;
556135c4bbdfSmrg        }
556235c4bbdfSmrg        else
556335c4bbdfSmrg            effectiveFocus = pWin = inputFocus;
556405b261ecSmrg    }
556505b261ecSmrg    else
556635c4bbdfSmrg        dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess);
556705b261ecSmrg
556805b261ecSmrg    if (!pWin)
556935c4bbdfSmrg        return BadWindow;
557035c4bbdfSmrg    if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) {
557135c4bbdfSmrg        client->errorValue = stuff->propagate;
557235c4bbdfSmrg        return BadValue;
557305b261ecSmrg    }
5574475c125cSmrg    stuff->event.u.u.type |= SEND_EVENT_BIT;
557535c4bbdfSmrg    if (stuff->propagate) {
557635c4bbdfSmrg        for (; pWin; pWin = pWin->parent) {
557735c4bbdfSmrg            if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin,
557835c4bbdfSmrg                         &stuff->event, 1))
557935c4bbdfSmrg                return Success;
55806747b715Smrg            if (DeliverEventsToWindow(dev, pWin,
558135c4bbdfSmrg                                      &stuff->event, 1, stuff->eventMask,
558235c4bbdfSmrg                                      NullGrab))
558335c4bbdfSmrg                return Success;
558435c4bbdfSmrg            if (pWin == effectiveFocus)
558535c4bbdfSmrg                return Success;
558635c4bbdfSmrg            stuff->eventMask &= ~wDontPropagateMask(pWin);
558735c4bbdfSmrg            if (!stuff->eventMask)
558835c4bbdfSmrg                break;
558935c4bbdfSmrg        }
559005b261ecSmrg    }
55914642e01fSmrg    else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1))
55926747b715Smrg        DeliverEventsToWindow(dev, pWin, &stuff->event,
559335c4bbdfSmrg                              1, stuff->eventMask, NullGrab);
559405b261ecSmrg    return Success;
559505b261ecSmrg}
559605b261ecSmrg
559705b261ecSmrg/**
559805b261ecSmrg * Server-side protocol handling for UngrabKey request.
559905b261ecSmrg *
56004642e01fSmrg * Deletes a passive grab for the given key. Works on the
56014642e01fSmrg * client's keyboard.
560205b261ecSmrg */
560305b261ecSmrgint
560405b261ecSmrgProcUngrabKey(ClientPtr client)
560505b261ecSmrg{
560605b261ecSmrg    REQUEST(xUngrabKeyReq);
560705b261ecSmrg    WindowPtr pWin;
560835c4bbdfSmrg    GrabPtr tempGrab;
56094642e01fSmrg    DeviceIntPtr keybd = PickKeyboard(client);
561005b261ecSmrg    int rc;
561105b261ecSmrg
561205b261ecSmrg    REQUEST_SIZE_MATCH(xUngrabKeyReq);
56136747b715Smrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess);
561405b261ecSmrg    if (rc != Success)
561535c4bbdfSmrg        return rc;
561605b261ecSmrg
56176747b715Smrg    if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
561835c4bbdfSmrg         (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
561935c4bbdfSmrg        && (stuff->key != AnyKey)) {
562035c4bbdfSmrg        client->errorValue = stuff->key;
562105b261ecSmrg        return BadValue;
562205b261ecSmrg    }
562305b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
562435c4bbdfSmrg        (stuff->modifiers & ~AllModifiersMask)) {
562535c4bbdfSmrg        client->errorValue = stuff->modifiers;
562635c4bbdfSmrg        return BadValue;
562735c4bbdfSmrg    }
562835c4bbdfSmrg    tempGrab = AllocGrab(NULL);
562935c4bbdfSmrg    if (!tempGrab)
563035c4bbdfSmrg        return BadAlloc;
563135c4bbdfSmrg    tempGrab->resource = client->clientAsMask;
563235c4bbdfSmrg    tempGrab->device = keybd;
563335c4bbdfSmrg    tempGrab->window = pWin;
563435c4bbdfSmrg    tempGrab->modifiersDetail.exact = stuff->modifiers;
563535c4bbdfSmrg    tempGrab->modifiersDetail.pMask = NULL;
563635c4bbdfSmrg    tempGrab->modifierDevice = keybd;
563735c4bbdfSmrg    tempGrab->type = KeyPress;
563835c4bbdfSmrg    tempGrab->grabtype = CORE;
563935c4bbdfSmrg    tempGrab->detail.exact = stuff->key;
564035c4bbdfSmrg    tempGrab->detail.pMask = NULL;
564135c4bbdfSmrg    tempGrab->next = NULL;
564235c4bbdfSmrg
564335c4bbdfSmrg    if (!DeletePassiveGrabFromList(tempGrab))
564435c4bbdfSmrg        rc = BadAlloc;
564535c4bbdfSmrg
564635c4bbdfSmrg    FreeGrab(tempGrab);
564735c4bbdfSmrg
564835c4bbdfSmrg    return rc;
564905b261ecSmrg}
565005b261ecSmrg
565105b261ecSmrg/**
565205b261ecSmrg * Server-side protocol handling for GrabKey request.
565305b261ecSmrg *
56544642e01fSmrg * Creates a grab for the client's keyboard and adds it to the list of passive
56554642e01fSmrg * grabs.
565605b261ecSmrg */
565705b261ecSmrgint
565805b261ecSmrgProcGrabKey(ClientPtr client)
565905b261ecSmrg{
566005b261ecSmrg    WindowPtr pWin;
566135c4bbdfSmrg
566205b261ecSmrg    REQUEST(xGrabKeyReq);
566305b261ecSmrg    GrabPtr grab;
56644642e01fSmrg    DeviceIntPtr keybd = PickKeyboard(client);
566505b261ecSmrg    int rc;
56666747b715Smrg    GrabParameters param;
56676747b715Smrg    GrabMask mask;
566805b261ecSmrg
566905b261ecSmrg    REQUEST_SIZE_MATCH(xGrabKeyReq);
56706747b715Smrg
567135c4bbdfSmrg    param = (GrabParameters) {
567235c4bbdfSmrg        .grabtype = CORE,
567335c4bbdfSmrg        .ownerEvents = stuff->ownerEvents,
567435c4bbdfSmrg        .this_device_mode = stuff->keyboardMode,
567535c4bbdfSmrg        .other_devices_mode = stuff->pointerMode,
567635c4bbdfSmrg        .modifiers = stuff->modifiers
567735c4bbdfSmrg    };
56786747b715Smrg
56796747b715Smrg    rc = CheckGrabValues(client, &param);
56806747b715Smrg    if (rc != Success)
56816747b715Smrg        return rc;
56826747b715Smrg
56836747b715Smrg    if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
568435c4bbdfSmrg         (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
568535c4bbdfSmrg        && (stuff->key != AnyKey)) {
568635c4bbdfSmrg        client->errorValue = stuff->key;
568705b261ecSmrg        return BadValue;
568805b261ecSmrg    }
56894642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
569005b261ecSmrg    if (rc != Success)
569135c4bbdfSmrg        return rc;
56926747b715Smrg
56936747b715Smrg    mask.core = (KeyPressMask | KeyReleaseMask);
56946747b715Smrg
569535c4bbdfSmrg    grab = CreateGrab(client->index, keybd, keybd, pWin, CORE, &mask,
56966747b715Smrg                      &param, KeyPress, stuff->key, NullWindow, NullCursor);
569705b261ecSmrg    if (!grab)
569835c4bbdfSmrg        return BadAlloc;
56994642e01fSmrg    return AddPassiveGrabToList(client, grab);
570005b261ecSmrg}
570105b261ecSmrg
570205b261ecSmrg/**
570305b261ecSmrg * Server-side protocol handling for GrabButton request.
570405b261ecSmrg *
57054642e01fSmrg * Creates a grab for the client's ClientPointer and adds it as a passive grab
57064642e01fSmrg * to the list.
570705b261ecSmrg */
570805b261ecSmrgint
570905b261ecSmrgProcGrabButton(ClientPtr client)
571005b261ecSmrg{
571105b261ecSmrg    WindowPtr pWin, confineTo;
571235c4bbdfSmrg
571305b261ecSmrg    REQUEST(xGrabButtonReq);
571405b261ecSmrg    CursorPtr cursor;
571505b261ecSmrg    GrabPtr grab;
57164642e01fSmrg    DeviceIntPtr ptr, modifierDevice;
57174642e01fSmrg    Mask access_mode = DixGrabAccess;
57186747b715Smrg    GrabMask mask;
57196747b715Smrg    GrabParameters param;
572005b261ecSmrg    int rc;
572105b261ecSmrg
572205b261ecSmrg    REQUEST_SIZE_MATCH(xGrabButtonReq);
57237e31ba66Smrg    UpdateCurrentTime();
572405b261ecSmrg    if ((stuff->pointerMode != GrabModeSync) &&
572535c4bbdfSmrg        (stuff->pointerMode != GrabModeAsync)) {
572635c4bbdfSmrg        client->errorValue = stuff->pointerMode;
572705b261ecSmrg        return BadValue;
572805b261ecSmrg    }
572905b261ecSmrg    if ((stuff->keyboardMode != GrabModeSync) &&
573035c4bbdfSmrg        (stuff->keyboardMode != GrabModeAsync)) {
573135c4bbdfSmrg        client->errorValue = stuff->keyboardMode;
573205b261ecSmrg        return BadValue;
573305b261ecSmrg    }
573405b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
573535c4bbdfSmrg        (stuff->modifiers & ~AllModifiersMask)) {
573635c4bbdfSmrg        client->errorValue = stuff->modifiers;
573735c4bbdfSmrg        return BadValue;
573805b261ecSmrg    }
573935c4bbdfSmrg    if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) {
574035c4bbdfSmrg        client->errorValue = stuff->ownerEvents;
574135c4bbdfSmrg        return BadValue;
574205b261ecSmrg    }
574335c4bbdfSmrg    if (stuff->eventMask & ~PointerGrabMask) {
574435c4bbdfSmrg        client->errorValue = stuff->eventMask;
574505b261ecSmrg        return BadValue;
574605b261ecSmrg    }
57474642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
574805b261ecSmrg    if (rc != Success)
574935c4bbdfSmrg        return rc;
575005b261ecSmrg    if (stuff->confineTo == None)
575135c4bbdfSmrg        confineTo = NullWindow;
575205b261ecSmrg    else {
575335c4bbdfSmrg        rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
575435c4bbdfSmrg                             DixSetAttrAccess);
575535c4bbdfSmrg        if (rc != Success)
575635c4bbdfSmrg            return rc;
575705b261ecSmrg    }
575805b261ecSmrg    if (stuff->cursor == None)
575935c4bbdfSmrg        cursor = NullCursor;
576035c4bbdfSmrg    else {
576135c4bbdfSmrg        rc = dixLookupResourceByType((void **) &cursor, stuff->cursor,
576235c4bbdfSmrg                                     RT_CURSOR, client, DixUseAccess);
576335c4bbdfSmrg        if (rc != Success) {
576435c4bbdfSmrg            client->errorValue = stuff->cursor;
576535c4bbdfSmrg            return rc;
576635c4bbdfSmrg        }
576735c4bbdfSmrg        access_mode |= DixForceAccess;
576805b261ecSmrg    }
576905b261ecSmrg
57704642e01fSmrg    ptr = PickPointer(client);
577135c4bbdfSmrg    modifierDevice = GetMaster(ptr, MASTER_KEYBOARD);
57724642e01fSmrg    if (stuff->pointerMode == GrabModeSync ||
577335c4bbdfSmrg        stuff->keyboardMode == GrabModeSync)
577435c4bbdfSmrg        access_mode |= DixFreezeAccess;
57754642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode);
57764642e01fSmrg    if (rc != Success)
577735c4bbdfSmrg        return rc;
577805b261ecSmrg
577935c4bbdfSmrg    param = (GrabParameters) {
578035c4bbdfSmrg        .grabtype = CORE,
578135c4bbdfSmrg        .ownerEvents = stuff->ownerEvents,
578235c4bbdfSmrg        .this_device_mode = stuff->keyboardMode,
578335c4bbdfSmrg        .other_devices_mode = stuff->pointerMode,
578435c4bbdfSmrg        .modifiers = stuff->modifiers
578535c4bbdfSmrg    };
57866747b715Smrg
57876747b715Smrg    mask.core = stuff->eventMask;
57886747b715Smrg
57896747b715Smrg    grab = CreateGrab(client->index, ptr, modifierDevice, pWin,
579035c4bbdfSmrg                      CORE, &mask, &param, ButtonPress,
57916747b715Smrg                      stuff->button, confineTo, cursor);
579205b261ecSmrg    if (!grab)
579335c4bbdfSmrg        return BadAlloc;
57944642e01fSmrg    return AddPassiveGrabToList(client, grab);
579505b261ecSmrg}
579605b261ecSmrg
579705b261ecSmrg/**
579805b261ecSmrg * Server-side protocol handling for UngrabButton request.
579905b261ecSmrg *
58004642e01fSmrg * Deletes a passive grab on the client's ClientPointer from the list.
580105b261ecSmrg */
580205b261ecSmrgint
580305b261ecSmrgProcUngrabButton(ClientPtr client)
580405b261ecSmrg{
580505b261ecSmrg    REQUEST(xUngrabButtonReq);
580605b261ecSmrg    WindowPtr pWin;
580735c4bbdfSmrg    GrabPtr tempGrab;
580805b261ecSmrg    int rc;
58096747b715Smrg    DeviceIntPtr ptr;
581005b261ecSmrg
581105b261ecSmrg    REQUEST_SIZE_MATCH(xUngrabButtonReq);
58127e31ba66Smrg    UpdateCurrentTime();
581305b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
581435c4bbdfSmrg        (stuff->modifiers & ~AllModifiersMask)) {
581535c4bbdfSmrg        client->errorValue = stuff->modifiers;
581635c4bbdfSmrg        return BadValue;
581705b261ecSmrg    }
581805b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
581905b261ecSmrg    if (rc != Success)
582035c4bbdfSmrg        return rc;
58216747b715Smrg
58226747b715Smrg    ptr = PickPointer(client);
58236747b715Smrg
582435c4bbdfSmrg    tempGrab = AllocGrab(NULL);
582535c4bbdfSmrg    if (!tempGrab)
582635c4bbdfSmrg        return BadAlloc;
582735c4bbdfSmrg    tempGrab->resource = client->clientAsMask;
582835c4bbdfSmrg    tempGrab->device = ptr;
582935c4bbdfSmrg    tempGrab->window = pWin;
583035c4bbdfSmrg    tempGrab->modifiersDetail.exact = stuff->modifiers;
583135c4bbdfSmrg    tempGrab->modifiersDetail.pMask = NULL;
583235c4bbdfSmrg    tempGrab->modifierDevice = GetMaster(ptr, MASTER_KEYBOARD);
583335c4bbdfSmrg    tempGrab->type = ButtonPress;
583435c4bbdfSmrg    tempGrab->detail.exact = stuff->button;
583535c4bbdfSmrg    tempGrab->grabtype = CORE;
583635c4bbdfSmrg    tempGrab->detail.pMask = NULL;
583735c4bbdfSmrg    tempGrab->next = NULL;
583835c4bbdfSmrg
583935c4bbdfSmrg    if (!DeletePassiveGrabFromList(tempGrab))
584035c4bbdfSmrg        rc = BadAlloc;
584135c4bbdfSmrg
584235c4bbdfSmrg    FreeGrab(tempGrab);
584335c4bbdfSmrg    return rc;
584405b261ecSmrg}
584505b261ecSmrg
584605b261ecSmrg/**
584705b261ecSmrg * Deactivate any grab that may be on the window, remove the focus.
584805b261ecSmrg * Delete any XInput extension events from the window too. Does not change the
584905b261ecSmrg * window mask. Use just before the window is deleted.
585005b261ecSmrg *
585105b261ecSmrg * If freeResources is set, passive grabs on the window are deleted.
585205b261ecSmrg *
585305b261ecSmrg * @param pWin The window to delete events from.
585405b261ecSmrg * @param freeResources True if resources associated with the window should be
585505b261ecSmrg * deleted.
585605b261ecSmrg */
585705b261ecSmrgvoid
585805b261ecSmrgDeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
585905b261ecSmrg{
586035c4bbdfSmrg    WindowPtr parent;
586135c4bbdfSmrg    DeviceIntPtr mouse = inputInfo.pointer;
586235c4bbdfSmrg    DeviceIntPtr keybd = inputInfo.keyboard;
586335c4bbdfSmrg    FocusClassPtr focus;
586435c4bbdfSmrg    OtherClientsPtr oc;
586535c4bbdfSmrg    GrabPtr passive;
586635c4bbdfSmrg    GrabPtr grab;
586705b261ecSmrg
586805b261ecSmrg    /* Deactivate any grabs performed on this window, before making any
586935c4bbdfSmrg       input focus changes. */
58704642e01fSmrg    grab = mouse->deviceGrab.grab;
587135c4bbdfSmrg    if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
587235c4bbdfSmrg        (*mouse->deviceGrab.DeactivateGrab) (mouse);
587305b261ecSmrg
587405b261ecSmrg    /* Deactivating a keyboard grab should cause focus events. */
58754642e01fSmrg    grab = keybd->deviceGrab.grab;
58764642e01fSmrg    if (grab && (grab->window == pWin))
587735c4bbdfSmrg        (*keybd->deviceGrab.DeactivateGrab) (keybd);
587805b261ecSmrg
58794642e01fSmrg    /* And now the real devices */
588035c4bbdfSmrg    for (mouse = inputInfo.devices; mouse; mouse = mouse->next) {
58814642e01fSmrg        grab = mouse->deviceGrab.grab;
58824642e01fSmrg        if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
588335c4bbdfSmrg            (*mouse->deviceGrab.DeactivateGrab) (mouse);
58844642e01fSmrg    }
588505b261ecSmrg
588635c4bbdfSmrg    for (keybd = inputInfo.devices; keybd; keybd = keybd->next) {
588735c4bbdfSmrg        if (IsKeyboardDevice(keybd)) {
58884642e01fSmrg            focus = keybd->focus;
58894642e01fSmrg
589035c4bbdfSmrg            /* If the focus window is a root window (ie. has no parent)
589135c4bbdfSmrg               then don't delete the focus from it. */
58924642e01fSmrg
589335c4bbdfSmrg            if ((pWin == focus->win) && (pWin->parent != NullWindow)) {
58944642e01fSmrg                int focusEventMode = NotifyNormal;
58954642e01fSmrg
58964642e01fSmrg                /* If a grab is in progress, then alter the mode of focus events. */
58974642e01fSmrg
58984642e01fSmrg                if (keybd->deviceGrab.grab)
58994642e01fSmrg                    focusEventMode = NotifyWhileGrabbed;
59004642e01fSmrg
590135c4bbdfSmrg                switch (focus->revert) {
590235c4bbdfSmrg                case RevertToNone:
590335c4bbdfSmrg                    DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
590435c4bbdfSmrg                    focus->win = NoneWin;
590535c4bbdfSmrg                    focus->traceGood = 0;
590635c4bbdfSmrg                    break;
590735c4bbdfSmrg                case RevertToParent:
590835c4bbdfSmrg                    parent = pWin;
590935c4bbdfSmrg                    do {
591035c4bbdfSmrg                        parent = parent->parent;
591135c4bbdfSmrg                        focus->traceGood--;
591235c4bbdfSmrg                    } while (!parent->realized
591335c4bbdfSmrg                    /* This would be a good protocol change -- windows being
591435c4bbdfSmrg                       reparented during SaveSet processing would cause the
591535c4bbdfSmrg                       focus to revert to the nearest enclosing window which
591635c4bbdfSmrg                       will survive the death of the exiting client, instead
591735c4bbdfSmrg                       of ending up reverting to a dying window and thence
591835c4bbdfSmrg                       to None */
591905b261ecSmrg#ifdef NOTDEF
592035c4bbdfSmrg                             || wClient(parent)->clientGone
592105b261ecSmrg#endif
592235c4bbdfSmrg                        );
592335c4bbdfSmrg                    if (!ActivateFocusInGrab(keybd, pWin, parent))
592435c4bbdfSmrg                        DoFocusEvents(keybd, pWin, parent, focusEventMode);
592535c4bbdfSmrg                    focus->win = parent;
592635c4bbdfSmrg                    focus->revert = RevertToNone;
592735c4bbdfSmrg                    break;
592835c4bbdfSmrg                case RevertToPointerRoot:
592935c4bbdfSmrg                    if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin))
593035c4bbdfSmrg                        DoFocusEvents(keybd, pWin, PointerRootWin,
593135c4bbdfSmrg                                      focusEventMode);
593235c4bbdfSmrg                    focus->win = PointerRootWin;
593335c4bbdfSmrg                    focus->traceGood = 0;
593435c4bbdfSmrg                    break;
59354642e01fSmrg                }
59364642e01fSmrg            }
59374642e01fSmrg        }
593805b261ecSmrg
593935c4bbdfSmrg        if (IsPointerDevice(keybd)) {
59404642e01fSmrg            if (keybd->valuator->motionHintWindow == pWin)
59414642e01fSmrg                keybd->valuator->motionHintWindow = NullWindow;
59424642e01fSmrg        }
59434642e01fSmrg    }
594405b261ecSmrg
594535c4bbdfSmrg    if (freeResources) {
594635c4bbdfSmrg        if (pWin->dontPropagate)
594735c4bbdfSmrg            DontPropagateRefCnts[pWin->dontPropagate]--;
594835c4bbdfSmrg        while ((oc = wOtherClients(pWin)))
594935c4bbdfSmrg            FreeResource(oc->resource, RT_NONE);
595035c4bbdfSmrg        while ((passive = wPassiveGrabs(pWin)))
595135c4bbdfSmrg            FreeResource(passive->resource, RT_NONE);
595235c4bbdfSmrg    }
59534642e01fSmrg
595405b261ecSmrg    DeleteWindowFromAnyExtEvents(pWin, freeResources);
595505b261ecSmrg}
595605b261ecSmrg
595705b261ecSmrg/**
595805b261ecSmrg * Call this whenever some window at or below pWin has changed geometry. If
595905b261ecSmrg * there is a grab on the window, the cursor will be re-confined into the
596005b261ecSmrg * window.
596105b261ecSmrg */
59626747b715Smrgvoid
596305b261ecSmrgCheckCursorConfinement(WindowPtr pWin)
596405b261ecSmrg{
59654642e01fSmrg    GrabPtr grab;
596605b261ecSmrg    WindowPtr confineTo;
59674642e01fSmrg    DeviceIntPtr pDev;
596805b261ecSmrg
596905b261ecSmrg#ifdef PANORAMIX
597035c4bbdfSmrg    if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
597135c4bbdfSmrg        return;
597205b261ecSmrg#endif
597305b261ecSmrg
597435c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
597535c4bbdfSmrg        if (DevHasCursor(pDev)) {
59764642e01fSmrg            grab = pDev->deviceGrab.grab;
597735c4bbdfSmrg            if (grab && (confineTo = grab->confineTo)) {
59784642e01fSmrg                if (!BorderSizeNotEmpty(pDev, confineTo))
597935c4bbdfSmrg                    (*pDev->deviceGrab.DeactivateGrab) (pDev);
59804642e01fSmrg                else if ((pWin == confineTo) || IsParent(pWin, confineTo))
59814642e01fSmrg                    ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
59824642e01fSmrg            }
59834642e01fSmrg        }
598405b261ecSmrg    }
598505b261ecSmrg}
598605b261ecSmrg
598705b261ecSmrgMask
598805b261ecSmrgEventMaskForClient(WindowPtr pWin, ClientPtr client)
598905b261ecSmrg{
599035c4bbdfSmrg    OtherClientsPtr other;
599105b261ecSmrg
599235c4bbdfSmrg    if (wClient(pWin) == client)
599335c4bbdfSmrg        return pWin->eventMask;
599435c4bbdfSmrg    for (other = wOtherClients(pWin); other; other = other->next) {
599535c4bbdfSmrg        if (SameClient(other, client))
599635c4bbdfSmrg            return other->mask;
599705b261ecSmrg    }
599805b261ecSmrg    return 0;
599905b261ecSmrg}
600005b261ecSmrg
600105b261ecSmrg/**
600205b261ecSmrg * Server-side protocol handling for RecolorCursor request.
600305b261ecSmrg */
600405b261ecSmrgint
600505b261ecSmrgProcRecolorCursor(ClientPtr client)
600605b261ecSmrg{
600705b261ecSmrg    CursorPtr pCursor;
600835c4bbdfSmrg    int rc, nscr;
600935c4bbdfSmrg    ScreenPtr pscr;
601035c4bbdfSmrg    Bool displayed;
601135c4bbdfSmrg    SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
601235c4bbdfSmrg
601305b261ecSmrg    REQUEST(xRecolorCursorReq);
601405b261ecSmrg
601505b261ecSmrg    REQUEST_SIZE_MATCH(xRecolorCursorReq);
601635c4bbdfSmrg    rc = dixLookupResourceByType((void **) &pCursor, stuff->cursor, RT_CURSOR,
601735c4bbdfSmrg                                 client, DixWriteAccess);
601835c4bbdfSmrg    if (rc != Success) {
601935c4bbdfSmrg        client->errorValue = stuff->cursor;
602035c4bbdfSmrg        return rc;
602105b261ecSmrg    }
602205b261ecSmrg
602305b261ecSmrg    pCursor->foreRed = stuff->foreRed;
602405b261ecSmrg    pCursor->foreGreen = stuff->foreGreen;
602505b261ecSmrg    pCursor->foreBlue = stuff->foreBlue;
602605b261ecSmrg
602705b261ecSmrg    pCursor->backRed = stuff->backRed;
602805b261ecSmrg    pCursor->backGreen = stuff->backGreen;
602905b261ecSmrg    pCursor->backBlue = stuff->backBlue;
603005b261ecSmrg
603135c4bbdfSmrg    for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
603235c4bbdfSmrg        pscr = screenInfo.screens[nscr];
603305b261ecSmrg#ifdef PANORAMIX
603435c4bbdfSmrg        if (!noPanoramiXExtension)
603535c4bbdfSmrg            displayed = (pscr == pSprite->screen);
603635c4bbdfSmrg        else
603705b261ecSmrg#endif
603835c4bbdfSmrg            displayed = (pscr == pSprite->hotPhys.pScreen);
603935c4bbdfSmrg        (*pscr->RecolorCursor) (PickPointer(client), pscr, pCursor,
604035c4bbdfSmrg                                (pCursor == pSprite->current) && displayed);
604105b261ecSmrg    }
60426747b715Smrg    return Success;
604305b261ecSmrg}
604405b261ecSmrg
604505b261ecSmrg/**
604605b261ecSmrg * Write the given events to a client, swapping the byte order if necessary.
604705b261ecSmrg * To swap the byte ordering, a callback is called that has to be set up for
604805b261ecSmrg * the given event type.
604905b261ecSmrg *
605005b261ecSmrg * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
60514642e01fSmrg * can be more than one. Usually it's just one event.
605205b261ecSmrg *
605305b261ecSmrg * Do not modify the event structure passed in. See comment below.
60544642e01fSmrg *
605505b261ecSmrg * @param pClient Client to send events to.
605605b261ecSmrg * @param count Number of events.
605705b261ecSmrg * @param events The event list.
605805b261ecSmrg */
60596747b715Smrgvoid
606005b261ecSmrgWriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
606105b261ecSmrg{
606205b261ecSmrg#ifdef PANORAMIX
606335c4bbdfSmrg    xEvent eventCopy;
606405b261ecSmrg#endif
606535c4bbdfSmrg    xEvent *eventTo, *eventFrom;
606635c4bbdfSmrg    int i, eventlength = sizeof(xEvent);
606705b261ecSmrg
60686747b715Smrg    if (!pClient || pClient == serverClient || pClient->clientGone)
606935c4bbdfSmrg        return;
60706747b715Smrg
60716747b715Smrg    for (i = 0; i < count; i++)
607235c4bbdfSmrg        if ((events[i].u.u.type & 0x7f) != KeymapNotify)
607335c4bbdfSmrg            events[i].u.u.sequenceNumber = pClient->sequence;
60746747b715Smrg
60756747b715Smrg    /* Let XKB rewrite the state, as it depends on client preferences. */
60766747b715Smrg    XkbFilterEvents(pClient, count, events);
607705b261ecSmrg
607805b261ecSmrg#ifdef PANORAMIX
607935c4bbdfSmrg    if (!noPanoramiXExtension &&
608035c4bbdfSmrg        (screenInfo.screens[0]->x || screenInfo.screens[0]->y)) {
608135c4bbdfSmrg        switch (events->u.u.type) {
608235c4bbdfSmrg        case MotionNotify:
608335c4bbdfSmrg        case ButtonPress:
608435c4bbdfSmrg        case ButtonRelease:
608535c4bbdfSmrg        case KeyPress:
608635c4bbdfSmrg        case KeyRelease:
608735c4bbdfSmrg        case EnterNotify:
608835c4bbdfSmrg        case LeaveNotify:
608935c4bbdfSmrg            /*
609035c4bbdfSmrg               When multiple clients want the same event DeliverEventsToWindow
609135c4bbdfSmrg               passes the same event structure multiple times so we can't
609235c4bbdfSmrg               modify the one passed to us
609335c4bbdfSmrg             */
609435c4bbdfSmrg            count = 1;          /* should always be 1 */
609535c4bbdfSmrg            memcpy(&eventCopy, events, sizeof(xEvent));
609635c4bbdfSmrg            eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x;
609735c4bbdfSmrg            eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y;
609835c4bbdfSmrg            if (eventCopy.u.keyButtonPointer.event ==
609935c4bbdfSmrg                eventCopy.u.keyButtonPointer.root) {
610035c4bbdfSmrg                eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x;
610135c4bbdfSmrg                eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y;
610235c4bbdfSmrg            }
610335c4bbdfSmrg            events = &eventCopy;
610435c4bbdfSmrg            break;
610535c4bbdfSmrg        default:
610635c4bbdfSmrg            break;
610735c4bbdfSmrg        }
610805b261ecSmrg    }
610905b261ecSmrg#endif
611005b261ecSmrg
611135c4bbdfSmrg    if (EventCallback) {
611235c4bbdfSmrg        EventInfoRec eventinfo;
611335c4bbdfSmrg
611435c4bbdfSmrg        eventinfo.client = pClient;
611535c4bbdfSmrg        eventinfo.events = events;
611635c4bbdfSmrg        eventinfo.count = count;
611735c4bbdfSmrg        CallCallbacks(&EventCallback, (void *) &eventinfo);
611805b261ecSmrg    }
611905b261ecSmrg#ifdef XSERVER_DTRACE
612005b261ecSmrg    if (XSERVER_SEND_EVENT_ENABLED()) {
612135c4bbdfSmrg        for (i = 0; i < count; i++) {
612235c4bbdfSmrg            XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]);
612335c4bbdfSmrg        }
612405b261ecSmrg    }
61254642e01fSmrg#endif
61264642e01fSmrg    /* Just a safety check to make sure we only have one GenericEvent, it just
61274642e01fSmrg     * makes things easier for me right now. (whot) */
612835c4bbdfSmrg    for (i = 1; i < count; i++) {
612935c4bbdfSmrg        if (events[i].u.u.type == GenericEvent) {
61304642e01fSmrg            ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n");
61314642e01fSmrg            return;
61324642e01fSmrg        }
61334642e01fSmrg    }
61344642e01fSmrg
613535c4bbdfSmrg    if (events->u.u.type == GenericEvent) {
613635c4bbdfSmrg        eventlength += ((xGenericEvent *) events)->length * 4;
61374642e01fSmrg    }
61384642e01fSmrg
613935c4bbdfSmrg    if (pClient->swapped) {
614035c4bbdfSmrg        if (eventlength > swapEventLen) {
61414642e01fSmrg            swapEventLen = eventlength;
61426747b715Smrg            swapEvent = realloc(swapEvent, swapEventLen);
614335c4bbdfSmrg            if (!swapEvent) {
61444642e01fSmrg                FatalError("WriteEventsToClient: Out of memory.\n");
61454642e01fSmrg                return;
61464642e01fSmrg            }
61474642e01fSmrg        }
61484642e01fSmrg
614935c4bbdfSmrg        for (i = 0; i < count; i++) {
615035c4bbdfSmrg            eventFrom = &events[i];
61514642e01fSmrg            eventTo = swapEvent;
61524642e01fSmrg
615335c4bbdfSmrg            /* Remember to strip off the leading bit of type in case
615435c4bbdfSmrg               this event was sent with "SendEvent." */
615535c4bbdfSmrg            (*EventSwapVector[eventFrom->u.u.type & 0177])
615635c4bbdfSmrg                (eventFrom, eventTo);
61574642e01fSmrg
615835c4bbdfSmrg            WriteToClient(pClient, eventlength, eventTo);
615935c4bbdfSmrg        }
616005b261ecSmrg    }
616135c4bbdfSmrg    else {
61624642e01fSmrg        /* only one GenericEvent, remember? that means either count is 1 and
61634642e01fSmrg         * eventlength is arbitrary or eventlength is 32 and count doesn't
61644642e01fSmrg         * matter. And we're all set. Woohoo. */
616535c4bbdfSmrg        WriteToClient(pClient, count * eventlength, events);
616605b261ecSmrg    }
616705b261ecSmrg}
61684642e01fSmrg
61694642e01fSmrg/*
61706747b715Smrg * Set the client pointer for the given client.
61714642e01fSmrg *
61724642e01fSmrg * A client can have exactly one ClientPointer. Each time a
61734642e01fSmrg * request/reply/event is processed and the choice of devices is ambiguous
61744642e01fSmrg * (e.g. QueryPointer request), the server will pick the ClientPointer (see
61754642e01fSmrg * PickPointer()).
61764642e01fSmrg * If a keyboard is needed, the first keyboard paired with the CP is used.
61774642e01fSmrg */
61786747b715Smrgint
61796747b715SmrgSetClientPointer(ClientPtr client, DeviceIntPtr device)
61804642e01fSmrg{
61816747b715Smrg    int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess);
618235c4bbdfSmrg
61836747b715Smrg    if (rc != Success)
618435c4bbdfSmrg        return rc;
61856747b715Smrg
618635c4bbdfSmrg    if (!IsMaster(device)) {
61874642e01fSmrg        ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n");
61886747b715Smrg        return BadDevice;
618935c4bbdfSmrg    }
619035c4bbdfSmrg    else if (!device->spriteInfo->spriteOwner) {
61914642e01fSmrg        ErrorF("[dix] Device %d does not have a sprite. "
619235c4bbdfSmrg               "Cannot be ClientPointer\n", device->id);
61936747b715Smrg        return BadDevice;
61944642e01fSmrg    }
61954642e01fSmrg    client->clientPtr = device;
61966747b715Smrg    return Success;
61974642e01fSmrg}
61984642e01fSmrg
61994642e01fSmrg/* PickPointer will pick an appropriate pointer for the given client.
62004642e01fSmrg *
62014642e01fSmrg * An "appropriate device" is (in order of priority):
62024642e01fSmrg *  1) A device the given client has a core grab on.
62034642e01fSmrg *  2) A device set as ClientPointer for the given client.
62044642e01fSmrg *  3) The first master device.
62054642e01fSmrg */
62066747b715SmrgDeviceIntPtr
62074642e01fSmrgPickPointer(ClientPtr client)
62084642e01fSmrg{
62094642e01fSmrg    DeviceIntPtr it = inputInfo.devices;
62104642e01fSmrg
62114642e01fSmrg    /* First, check if the client currently has a grab on a device. Even
62124642e01fSmrg     * keyboards count. */
621335c4bbdfSmrg    for (it = inputInfo.devices; it; it = it->next) {
62144642e01fSmrg        GrabPtr grab = it->deviceGrab.grab;
621535c4bbdfSmrg
621635c4bbdfSmrg        if (grab && grab->grabtype == CORE && SameClient(grab, client)) {
62176747b715Smrg            it = GetMaster(it, MASTER_POINTER);
621835c4bbdfSmrg            return it;          /* Always return a core grabbed device */
62194642e01fSmrg        }
62204642e01fSmrg    }
62214642e01fSmrg
622235c4bbdfSmrg    if (!client->clientPtr) {
622335c4bbdfSmrg        it = inputInfo.devices;
622435c4bbdfSmrg        while (it) {
622535c4bbdfSmrg            if (IsMaster(it) && it->spriteInfo->spriteOwner) {
62264642e01fSmrg                client->clientPtr = it;
62274642e01fSmrg                break;
62284642e01fSmrg            }
62294642e01fSmrg            it = it->next;
62304642e01fSmrg        }
62314642e01fSmrg    }
62324642e01fSmrg    return client->clientPtr;
62334642e01fSmrg}
62344642e01fSmrg
62354642e01fSmrg/* PickKeyboard will pick an appropriate keyboard for the given client by
62364642e01fSmrg * searching the list of devices for the keyboard device that is paired with
62374642e01fSmrg * the client's pointer.
62384642e01fSmrg */
62396747b715SmrgDeviceIntPtr
62404642e01fSmrgPickKeyboard(ClientPtr client)
62414642e01fSmrg{
62424642e01fSmrg    DeviceIntPtr ptr = PickPointer(client);
62436747b715Smrg    DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD);
62444642e01fSmrg
624535c4bbdfSmrg    if (!kbd) {
62464642e01fSmrg        ErrorF("[dix] ClientPointer not paired with a keyboard. This "
624735c4bbdfSmrg               "is a bug.\n");
62484642e01fSmrg    }
62494642e01fSmrg
62504642e01fSmrg    return kbd;
62514642e01fSmrg}
62524642e01fSmrg
62534642e01fSmrg/* A client that has one or more core grabs does not get core events from
62544642e01fSmrg * devices it does not have a grab on. Legacy applications behave bad
62554642e01fSmrg * otherwise because they are not used to it and the events interfere.
62564642e01fSmrg * Only applies for core events.
62574642e01fSmrg *
62584642e01fSmrg * Return true if a core event from the device would interfere and should not
62594642e01fSmrg * be delivered.
62604642e01fSmrg */
62614642e01fSmrgBool
626235c4bbdfSmrgIsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent *event)
62634642e01fSmrg{
62644642e01fSmrg    DeviceIntPtr it = inputInfo.devices;
62654642e01fSmrg
626635c4bbdfSmrg    switch (event->u.u.type) {
626735c4bbdfSmrg    case KeyPress:
626835c4bbdfSmrg    case KeyRelease:
626935c4bbdfSmrg    case ButtonPress:
627035c4bbdfSmrg    case ButtonRelease:
627135c4bbdfSmrg    case MotionNotify:
627235c4bbdfSmrg    case EnterNotify:
627335c4bbdfSmrg    case LeaveNotify:
627435c4bbdfSmrg        break;
627535c4bbdfSmrg    default:
627635c4bbdfSmrg        return FALSE;
62774642e01fSmrg    }
62784642e01fSmrg
62796747b715Smrg    if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
62806747b715Smrg        return FALSE;
62816747b715Smrg
628235c4bbdfSmrg    while (it) {
628335c4bbdfSmrg        if (it != dev) {
62844642e01fSmrg            if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client)
628535c4bbdfSmrg                && !it->deviceGrab.fromPassiveGrab) {
62864642e01fSmrg                if ((IsPointerDevice(it) && IsPointerDevice(dev)) ||
628735c4bbdfSmrg                    (IsKeyboardDevice(it) && IsKeyboardDevice(dev)))
62884642e01fSmrg                    return TRUE;
62894642e01fSmrg            }
62904642e01fSmrg        }
62914642e01fSmrg        it = it->next;
62924642e01fSmrg    }
62934642e01fSmrg
62944642e01fSmrg    return FALSE;
62954642e01fSmrg}
62964642e01fSmrg
629735c4bbdfSmrg/* PointerBarrier events are only delivered to the client that created that
629835c4bbdfSmrg * barrier */
629935c4bbdfSmrgstatic Bool
630035c4bbdfSmrgIsWrongPointerBarrierClient(ClientPtr client, DeviceIntPtr dev, xEvent *event)
630135c4bbdfSmrg{
630235c4bbdfSmrg    xXIBarrierEvent *ev = (xXIBarrierEvent*)event;
630335c4bbdfSmrg
630435c4bbdfSmrg    if (ev->type != GenericEvent || ev->extension != IReqCode)
630535c4bbdfSmrg        return FALSE;
630635c4bbdfSmrg
630735c4bbdfSmrg    if (ev->evtype != XI_BarrierHit && ev->evtype != XI_BarrierLeave)
630835c4bbdfSmrg        return FALSE;
630935c4bbdfSmrg
631035c4bbdfSmrg    return client->index != CLIENT_ID(ev->barrier);
631135c4bbdfSmrg}
6312