events.c revision 90bea6a0
105b261ecSmrg/************************************************************
205b261ecSmrg
305b261ecSmrgCopyright 1987, 1998  The Open Group
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthe above copyright notice appear in all copies and that both that
805b261ecSmrgcopyright notice and this permission notice appear in supporting
905b261ecSmrgdocumentation.
1005b261ecSmrg
1105b261ecSmrgThe above copyright notice and this permission notice shall be included in
1205b261ecSmrgall copies or substantial portions of the Software.
1305b261ecSmrg
1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2005b261ecSmrg
2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be
2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings
2305b261ecSmrgin this Software without prior written authorization from The Open Group.
2405b261ecSmrg
2505b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
2605b261ecSmrg
2705b261ecSmrg                        All Rights Reserved
2805b261ecSmrg
294642e01fSmrgPermission to use, copy, modify, and distribute this software and its
304642e01fSmrgdocumentation for any purpose and without fee is hereby granted,
3105b261ecSmrgprovided that the above copyright notice appear in all copies and that
324642e01fSmrgboth that copyright notice and this permission notice appear in
3305b261ecSmrgsupporting documentation, and that the name of Digital not be
3405b261ecSmrgused in advertising or publicity pertaining to distribution of the
354642e01fSmrgsoftware without specific, written prior permission.
3605b261ecSmrg
3705b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
3805b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
3905b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
4005b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
4205b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4305b261ecSmrgSOFTWARE.
4405b261ecSmrg
4505b261ecSmrg********************************************************/
4605b261ecSmrg
4705b261ecSmrg/* The panoramix components contained the following notice */
4805b261ecSmrg/*****************************************************************
4905b261ecSmrg
5005b261ecSmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
5105b261ecSmrg
5205b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a copy
5305b261ecSmrgof this software and associated documentation files (the "Software"), to deal
5405b261ecSmrgin the Software without restriction, including without limitation the rights
5505b261ecSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5605b261ecSmrgcopies of the Software.
5705b261ecSmrg
5805b261ecSmrgThe above copyright notice and this permission notice shall be included in
5905b261ecSmrgall copies or substantial portions of the Software.
6005b261ecSmrg
6105b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6205b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6305b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
6405b261ecSmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
6505b261ecSmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
6605b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
6705b261ecSmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6805b261ecSmrg
6905b261ecSmrgExcept as contained in this notice, the name of Digital Equipment Corporation
7005b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use or other
7105b261ecSmrgdealings in this Software without prior written authorization from Digital
7205b261ecSmrgEquipment Corporation.
7305b261ecSmrg
7405b261ecSmrg******************************************************************/
7505b261ecSmrg
766747b715Smrg/*
779ace9065Smrg * Copyright (c) 2003-2005, Oracle and/or its affiliates. All rights reserved.
786747b715Smrg *
796747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a
806747b715Smrg * copy of this software and associated documentation files (the "Software"),
816747b715Smrg * to deal in the Software without restriction, including without limitation
826747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
836747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the
846747b715Smrg * Software is furnished to do so, subject to the following conditions:
856747b715Smrg *
866747b715Smrg * The above copyright notice and this permission notice (including the next
876747b715Smrg * paragraph) shall be included in all copies or substantial portions of the
886747b715Smrg * Software.
896747b715Smrg *
906747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
916747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
926747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
936747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
946747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
956747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
966747b715Smrg * DEALINGS IN THE SOFTWARE.
976747b715Smrg */
9805b261ecSmrg
996747b715Smrg/** @file events.c
10005b261ecSmrg * This file handles event delivery and a big part of the server-side protocol
10105b261ecSmrg * handling (the parts for input devices).
10205b261ecSmrg */
10305b261ecSmrg
10405b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
10505b261ecSmrg#include <dix-config.h>
10605b261ecSmrg#endif
10705b261ecSmrg
10805b261ecSmrg#include <X11/X.h>
10905b261ecSmrg#include "misc.h"
11005b261ecSmrg#include "resource.h"
11105b261ecSmrg#include <X11/Xproto.h>
11205b261ecSmrg#include "windowstr.h"
11305b261ecSmrg#include "inputstr.h"
11435c4bbdfSmrg#include "inpututils.h"
11505b261ecSmrg#include "scrnintstr.h"
11605b261ecSmrg#include "cursorstr.h"
11705b261ecSmrg
11805b261ecSmrg#include "dixstruct.h"
11905b261ecSmrg#ifdef PANORAMIX
12005b261ecSmrg#include "panoramiX.h"
12105b261ecSmrg#include "panoramiXsrv.h"
12205b261ecSmrg#endif
12305b261ecSmrg#include "globals.h"
12405b261ecSmrg
12505b261ecSmrg#include <X11/extensions/XKBproto.h>
1266747b715Smrg#include "xkbsrv.h"
12705b261ecSmrg#include "xace.h"
12835c4bbdfSmrg#include "probes.h"
12905b261ecSmrg
13005b261ecSmrg#include <X11/extensions/XIproto.h>
1316747b715Smrg#include <X11/extensions/XI2proto.h>
1324642e01fSmrg#include <X11/extensions/XI.h>
1336747b715Smrg#include <X11/extensions/XI2.h>
13405b261ecSmrg#include "exglobals.h"
13505b261ecSmrg#include "exevents.h"
13605b261ecSmrg#include "extnsionst.h"
13705b261ecSmrg
13805b261ecSmrg#include "dixevents.h"
13905b261ecSmrg#include "dixgrabs.h"
14005b261ecSmrg#include "dispatch.h"
1414642e01fSmrg
1424642e01fSmrg#include <X11/extensions/ge.h>
1434642e01fSmrg#include "geext.h"
1444642e01fSmrg#include "geint.h"
1454642e01fSmrg
1466747b715Smrg#include "eventstr.h"
1474642e01fSmrg#include "enterleave.h"
1486747b715Smrg#include "eventconvert.h"
14935c4bbdfSmrg#include "mi.h"
1504642e01fSmrg
1516747b715Smrg/* Extension events type numbering starts at EXTENSION_EVENT_BASE.  */
15235c4bbdfSmrg#define NoSuchEvent 0x80000000  /* so doesn't match NoEventMask */
15305b261ecSmrg#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
15405b261ecSmrg#define AllButtonsMask ( \
15505b261ecSmrg	Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
15605b261ecSmrg#define MotionMask ( \
15705b261ecSmrg	PointerMotionMask | Button1MotionMask | \
15805b261ecSmrg	Button2MotionMask | Button3MotionMask | Button4MotionMask | \
15905b261ecSmrg	Button5MotionMask | ButtonMotionMask )
16005b261ecSmrg#define PropagateMask ( \
16105b261ecSmrg	KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
16205b261ecSmrg	MotionMask )
16305b261ecSmrg#define PointerGrabMask ( \
16405b261ecSmrg	ButtonPressMask | ButtonReleaseMask | \
16505b261ecSmrg	EnterWindowMask | LeaveWindowMask | \
16605b261ecSmrg	PointerMotionHintMask | KeymapStateMask | \
16705b261ecSmrg	MotionMask )
16805b261ecSmrg#define AllModifiersMask ( \
16905b261ecSmrg	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
17005b261ecSmrg	Mod3Mask | Mod4Mask | Mod5Mask )
1716747b715Smrg#define LastEventMask OwnerGrabButtonMask
1726747b715Smrg#define AllEventMasks (LastEventMask|(LastEventMask-1))
1736747b715Smrg
17435c4bbdfSmrg/* @return the core event type or 0 if the event is not a core event */
17535c4bbdfSmrgstatic inline int
17635c4bbdfSmrgcore_get_type(const xEvent *event)
17735c4bbdfSmrg{
17835c4bbdfSmrg    int type = event->u.u.type;
17935c4bbdfSmrg
18035c4bbdfSmrg    return ((type & EXTENSION_EVENT_BASE) || type == GenericEvent) ? 0 : type;
18135c4bbdfSmrg}
18235c4bbdfSmrg
18335c4bbdfSmrg/* @return the XI2 event type or 0 if the event is not a XI2 event */
18435c4bbdfSmrgstatic inline int
18535c4bbdfSmrgxi2_get_type(const xEvent *event)
18635c4bbdfSmrg{
18735c4bbdfSmrg    const xGenericEvent *e = (const xGenericEvent *) event;
1886747b715Smrg
18935c4bbdfSmrg    return (e->type != GenericEvent ||
19035c4bbdfSmrg            e->extension != IReqCode) ? 0 : e->evtype;
19135c4bbdfSmrg}
1924642e01fSmrg
1934642e01fSmrg/**
1944642e01fSmrg * Used to indicate a implicit passive grab created by a ButtonPress event.
1954642e01fSmrg * See DeliverEventsToWindow().
1964642e01fSmrg */
1974642e01fSmrg#define ImplicitGrabMask (1 << 7)
19805b261ecSmrg
19905b261ecSmrg#define WID(w) ((w) ? ((w)->drawable.id) : 0)
20005b261ecSmrg
20105b261ecSmrg#define XE_KBPTR (xE->u.keyButtonPointer)
20205b261ecSmrg
2036747b715SmrgCallbackListPtr EventCallback;
2046747b715SmrgCallbackListPtr DeviceEventCallback;
20505b261ecSmrg
20605b261ecSmrg#define DNPMCOUNT 8
20705b261ecSmrg
20805b261ecSmrgMask DontPropagateMasks[DNPMCOUNT];
20905b261ecSmrgstatic int DontPropagateRefCnts[DNPMCOUNT];
21005b261ecSmrg
21135c4bbdfSmrgstatic void CheckVirtualMotion(DeviceIntPtr pDev, QdEventPtr qe,
21235c4bbdfSmrg                               WindowPtr pWin);
21335c4bbdfSmrgstatic void CheckPhysLimits(DeviceIntPtr pDev, CursorPtr cursor,
21435c4bbdfSmrg                            Bool generateEvents, Bool confineToScreen,
2156747b715Smrg                            ScreenPtr pScreen);
21635c4bbdfSmrgstatic Bool IsWrongPointerBarrierClient(ClientPtr client,
21735c4bbdfSmrg                                        DeviceIntPtr dev,
21835c4bbdfSmrg                                        xEvent *event);
2196747b715Smrg
2206747b715Smrg/** Key repeat hack. Do not use but in TryClientEvents */
2216747b715Smrgextern BOOL EventIsKeyRepeat(xEvent *event);
2224642e01fSmrg
22305b261ecSmrg/**
2244642e01fSmrg * Main input device struct.
2254642e01fSmrg *     inputInfo.pointer
22605b261ecSmrg *     is the core pointer. Referred to as "virtual core pointer", "VCP",
2276747b715Smrg *     "core pointer" or inputInfo.pointer. The VCP is the first master
2284642e01fSmrg *     pointer device and cannot be deleted.
2294642e01fSmrg *
23005b261ecSmrg *     inputInfo.keyboard
23105b261ecSmrg *     is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
23205b261ecSmrg *     See inputInfo.pointer.
2334642e01fSmrg *
23405b261ecSmrg *     inputInfo.devices
2354642e01fSmrg *     linked list containing all devices including VCP and VCK.
23605b261ecSmrg *
23705b261ecSmrg *     inputInfo.off_devices
23805b261ecSmrg *     Devices that have not been initialized and are thus turned off.
23905b261ecSmrg *
24005b261ecSmrg *     inputInfo.numDevices
24105b261ecSmrg *     Total number of devices.
2426747b715Smrg *
2436747b715Smrg *     inputInfo.all_devices
2446747b715Smrg *     Virtual device used for XIAllDevices passive grabs. This device is
2456747b715Smrg *     not part of the inputInfo.devices list and mostly unset except for
2466747b715Smrg *     the deviceid. It exists because passivegrabs need a valid device
2476747b715Smrg *     reference.
2486747b715Smrg *
2496747b715Smrg *     inputInfo.all_master_devices
2506747b715Smrg *     Virtual device used for XIAllMasterDevices passive grabs. This device
2516747b715Smrg *     is not part of the inputInfo.devices list and mostly unset except for
2526747b715Smrg *     the deviceid. It exists because passivegrabs need a valid device
2536747b715Smrg *     reference.
25405b261ecSmrg */
2556747b715SmrgInputInfo inputInfo;
2566747b715Smrg
2576747b715SmrgEventSyncInfoRec syncEvents;
25805b261ecSmrg
25935c4bbdfSmrgstatic struct DeviceEventTime {
26035c4bbdfSmrg    Bool reset;
26135c4bbdfSmrg    TimeStamp time;
26235c4bbdfSmrg} lastDeviceEventTime[MAXDEVICES];
26335c4bbdfSmrg
2644642e01fSmrg/**
2656747b715Smrg * The root window the given device is currently on.
2664642e01fSmrg */
2679ace9065Smrg#define RootWindow(sprite) sprite->spriteTrace[0]
2684642e01fSmrg
26935c4bbdfSmrgstatic xEvent *swapEvent = NULL;
2704642e01fSmrgstatic int swapEventLen = 0;
2714642e01fSmrg
2726747b715Smrgvoid
2736747b715SmrgNotImplemented(xEvent *from, xEvent *to)
2746747b715Smrg{
2756747b715Smrg    FatalError("Not implemented");
2766747b715Smrg}
2776747b715Smrg
2784642e01fSmrg/**
2794642e01fSmrg * Convert the given event type from an XI event to a core event.
2806747b715Smrg * @param[in] The XI 1.x event type.
2814642e01fSmrg * @return The matching core event type or 0 if there is none.
28205b261ecSmrg */
2836747b715Smrgint
2844642e01fSmrgXItoCoreType(int xitype)
2854642e01fSmrg{
2864642e01fSmrg    int coretype = 0;
28735c4bbdfSmrg
2884642e01fSmrg    if (xitype == DeviceMotionNotify)
2894642e01fSmrg        coretype = MotionNotify;
2904642e01fSmrg    else if (xitype == DeviceButtonPress)
2914642e01fSmrg        coretype = ButtonPress;
2924642e01fSmrg    else if (xitype == DeviceButtonRelease)
2934642e01fSmrg        coretype = ButtonRelease;
2944642e01fSmrg    else if (xitype == DeviceKeyPress)
2954642e01fSmrg        coretype = KeyPress;
2964642e01fSmrg    else if (xitype == DeviceKeyRelease)
2974642e01fSmrg        coretype = KeyRelease;
2984642e01fSmrg
2994642e01fSmrg    return coretype;
3004642e01fSmrg}
30105b261ecSmrg
30205b261ecSmrg/**
3036747b715Smrg * @return true if the device owns a cursor, false if device shares a cursor
3046747b715Smrg * sprite with another device.
30505b261ecSmrg */
3066747b715SmrgBool
3074642e01fSmrgDevHasCursor(DeviceIntPtr pDev)
3084642e01fSmrg{
3094642e01fSmrg    return pDev->spriteInfo->spriteOwner;
3104642e01fSmrg}
31105b261ecSmrg
3124642e01fSmrg/*
3136747b715Smrg * @return true if a device is a pointer, check is the same as used by XI to
3144642e01fSmrg * fill the 'use' field.
3154642e01fSmrg */
3166747b715SmrgBool
3174642e01fSmrgIsPointerDevice(DeviceIntPtr dev)
3184642e01fSmrg{
3196747b715Smrg    return (dev->type == MASTER_POINTER) ||
32035c4bbdfSmrg        (dev->valuator && dev->button) || (dev->valuator && !dev->key);
3214642e01fSmrg}
32205b261ecSmrg
3234642e01fSmrg/*
3246747b715Smrg * @return true if a device is a keyboard, check is the same as used by XI to
3254642e01fSmrg * fill the 'use' field.
3264642e01fSmrg *
3274642e01fSmrg * Some pointer devices have keys as well (e.g. multimedia keys). Try to not
3284642e01fSmrg * count them as keyboard devices.
3294642e01fSmrg */
3306747b715SmrgBool
3314642e01fSmrgIsKeyboardDevice(DeviceIntPtr dev)
3324642e01fSmrg{
3336747b715Smrg    return (dev->type == MASTER_KEYBOARD) ||
33435c4bbdfSmrg        ((dev->key && dev->kbdfeed) && !IsPointerDevice(dev));
3356747b715Smrg}
3366747b715Smrg
3376747b715SmrgBool
3386747b715SmrgIsMaster(DeviceIntPtr dev)
3396747b715Smrg{
3406747b715Smrg    return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
3414642e01fSmrg}
34205b261ecSmrg
34335c4bbdfSmrgBool
34435c4bbdfSmrgIsFloating(DeviceIntPtr dev)
34535c4bbdfSmrg{
34635c4bbdfSmrg    return !IsMaster(dev) && GetMaster(dev, MASTER_KEYBOARD) == NULL;
34735c4bbdfSmrg}
34835c4bbdfSmrg
34905b261ecSmrg/**
35005b261ecSmrg * Max event opcode.
35105b261ecSmrg */
35205b261ecSmrgextern int lastEvent;
35305b261ecSmrg
3546747b715Smrg#define CantBeFiltered NoEventMask
3554642e01fSmrg/**
3566747b715Smrg * Event masks for each event type.
3576747b715Smrg *
35835c4bbdfSmrg * One set of filters for each device, initialized by memcpy of
35935c4bbdfSmrg * default_filter in InitEvents.
3606747b715Smrg *
3616747b715Smrg * Filters are used whether a given event may be delivered to a client,
3626747b715Smrg * usually in the form of if (window-event-mask & filter); then deliver event.
3636747b715Smrg *
3646747b715Smrg * One notable filter is for PointerMotion/DevicePointerMotion events. Each
3656747b715Smrg * time a button is pressed, the filter is modified to also contain the
3666747b715Smrg * matching ButtonXMotion mask.
3674642e01fSmrg */
36835c4bbdfSmrgMask event_filters[MAXDEVICES][MAXEVENTS];
36935c4bbdfSmrg
37035c4bbdfSmrgstatic const Mask default_filter[MAXEVENTS] = {
37135c4bbdfSmrg    NoSuchEvent,                /* 0 */
37235c4bbdfSmrg    NoSuchEvent,                /* 1 */
37335c4bbdfSmrg    KeyPressMask,               /* KeyPress */
37435c4bbdfSmrg    KeyReleaseMask,             /* KeyRelease */
37535c4bbdfSmrg    ButtonPressMask,            /* ButtonPress */
37635c4bbdfSmrg    ButtonReleaseMask,          /* ButtonRelease */
37735c4bbdfSmrg    PointerMotionMask,          /* MotionNotify (initial state) */
37835c4bbdfSmrg    EnterWindowMask,            /* EnterNotify */
37935c4bbdfSmrg    LeaveWindowMask,            /* LeaveNotify */
38035c4bbdfSmrg    FocusChangeMask,            /* FocusIn */
38135c4bbdfSmrg    FocusChangeMask,            /* FocusOut */
38235c4bbdfSmrg    KeymapStateMask,            /* KeymapNotify */
38335c4bbdfSmrg    ExposureMask,               /* Expose */
38435c4bbdfSmrg    CantBeFiltered,             /* GraphicsExpose */
38535c4bbdfSmrg    CantBeFiltered,             /* NoExpose */
38635c4bbdfSmrg    VisibilityChangeMask,       /* VisibilityNotify */
38735c4bbdfSmrg    SubstructureNotifyMask,     /* CreateNotify */
38835c4bbdfSmrg    StructureAndSubMask,        /* DestroyNotify */
38935c4bbdfSmrg    StructureAndSubMask,        /* UnmapNotify */
39035c4bbdfSmrg    StructureAndSubMask,        /* MapNotify */
39135c4bbdfSmrg    SubstructureRedirectMask,   /* MapRequest */
39235c4bbdfSmrg    StructureAndSubMask,        /* ReparentNotify */
39335c4bbdfSmrg    StructureAndSubMask,        /* ConfigureNotify */
39435c4bbdfSmrg    SubstructureRedirectMask,   /* ConfigureRequest */
39535c4bbdfSmrg    StructureAndSubMask,        /* GravityNotify */
39635c4bbdfSmrg    ResizeRedirectMask,         /* ResizeRequest */
39735c4bbdfSmrg    StructureAndSubMask,        /* CirculateNotify */
39835c4bbdfSmrg    SubstructureRedirectMask,   /* CirculateRequest */
39935c4bbdfSmrg    PropertyChangeMask,         /* PropertyNotify */
40035c4bbdfSmrg    CantBeFiltered,             /* SelectionClear */
40135c4bbdfSmrg    CantBeFiltered,             /* SelectionRequest */
40235c4bbdfSmrg    CantBeFiltered,             /* SelectionNotify */
40335c4bbdfSmrg    ColormapChangeMask,         /* ColormapNotify */
40435c4bbdfSmrg    CantBeFiltered,             /* ClientMessage */
40535c4bbdfSmrg    CantBeFiltered              /* MappingNotify */
40635c4bbdfSmrg};
4074642e01fSmrg
4086747b715Smrg/**
4096747b715Smrg * For the given event, return the matching event filter. This filter may then
4106747b715Smrg * be AND'ed with the selected event mask.
4116747b715Smrg *
4126747b715Smrg * For XI2 events, the returned filter is simply the byte containing the event
4136747b715Smrg * mask we're interested in. E.g. for a mask of (1 << 13), this would be
4146747b715Smrg * byte[1].
4156747b715Smrg *
4166747b715Smrg * @param[in] dev The device the event belongs to, may be NULL.
4176747b715Smrg * @param[in] event The event to get the filter for. Only the type of the
4186747b715Smrg *                  event matters, or the extension + evtype for GenericEvents.
4196747b715Smrg * @return The filter mask for the given event.
4206747b715Smrg *
4216747b715Smrg * @see GetEventMask
4226747b715Smrg */
4236747b715SmrgMask
4246747b715SmrgGetEventFilter(DeviceIntPtr dev, xEvent *event)
4256747b715Smrg{
42635c4bbdfSmrg    int evtype = 0;
42735c4bbdfSmrg
4286747b715Smrg    if (event->u.u.type != GenericEvent)
42935c4bbdfSmrg        return event_get_filter_from_type(dev, event->u.u.type);
43035c4bbdfSmrg    else if ((evtype = xi2_get_type(event)))
43135c4bbdfSmrg        return event_get_filter_from_xi2type(evtype);
4329ace9065Smrg    ErrorF("[dix] Unknown event type %d. No filter\n", event->u.u.type);
4336747b715Smrg    return 0;
4346747b715Smrg}
4354642e01fSmrg
4364642e01fSmrg/**
43735c4bbdfSmrg * Return the single byte of the device's XI2 mask that contains the mask
43835c4bbdfSmrg * for the event_type.
4394642e01fSmrg */
44035c4bbdfSmrgint
44135c4bbdfSmrgGetXI2MaskByte(XI2Mask *mask, DeviceIntPtr dev, int event_type)
44235c4bbdfSmrg{
44335c4bbdfSmrg    /* we just return the matching filter because that's the only use
44435c4bbdfSmrg     * for this mask anyway.
44535c4bbdfSmrg     */
44635c4bbdfSmrg    if (xi2mask_isset(mask, dev, event_type))
44735c4bbdfSmrg        return event_get_filter_from_xi2type(event_type);
44835c4bbdfSmrg    else
44935c4bbdfSmrg        return 0;
45035c4bbdfSmrg}
45135c4bbdfSmrg
45235c4bbdfSmrg/**
45335c4bbdfSmrg * @return TRUE if the mask is set for this event from this device on the
45435c4bbdfSmrg * window, or FALSE otherwise.
45535c4bbdfSmrg */
45635c4bbdfSmrgBool
45735c4bbdfSmrgWindowXI2MaskIsset(DeviceIntPtr dev, WindowPtr win, xEvent *ev)
4586747b715Smrg{
4596747b715Smrg    OtherInputMasks *inputMasks = wOtherInputMasks(win);
4606747b715Smrg    int evtype;
4616747b715Smrg
46235c4bbdfSmrg    if (!inputMasks || xi2_get_type(ev) == 0)
4636747b715Smrg        return 0;
4646747b715Smrg
46535c4bbdfSmrg    evtype = ((xGenericEvent *) ev)->evtype;
4666747b715Smrg
46735c4bbdfSmrg    return xi2mask_isset(inputMasks->xi2mask, dev, evtype);
4686747b715Smrg}
4696747b715Smrg
47090bea6a0Smrg/**
47190bea6a0Smrg * When processing events we operate on InternalEvent pointers. They may actually refer to a
47290bea6a0Smrg * an instance of DeviceEvent, GestureEvent or any other event that comprises the InternalEvent
47390bea6a0Smrg * union. This works well in practice because we always look into event type before doing anything,
47490bea6a0Smrg * except in the case of copying the event. Any copying of InternalEvent should use this function
47590bea6a0Smrg * instead of doing *dst_event = *src_event whenever it's not clear whether source event actually
47690bea6a0Smrg * points to full InternalEvent instance.
47790bea6a0Smrg */
47890bea6a0Smrgvoid
47990bea6a0SmrgCopyPartialInternalEvent(InternalEvent* dst_event, const InternalEvent* src_event)
48090bea6a0Smrg{
48190bea6a0Smrg    memcpy(dst_event, src_event, src_event->any.length);
48290bea6a0Smrg}
48390bea6a0Smrg
4849ace9065SmrgMask
48535c4bbdfSmrgGetEventMask(DeviceIntPtr dev, xEvent *event, InputClients * other)
4866747b715Smrg{
48735c4bbdfSmrg    int evtype;
48835c4bbdfSmrg
4896747b715Smrg    /* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */
49035c4bbdfSmrg    if ((evtype = xi2_get_type(event))) {
49135c4bbdfSmrg        return GetXI2MaskByte(other->xi2mask, dev, evtype);
49235c4bbdfSmrg    }
49335c4bbdfSmrg    else if (core_get_type(event) != 0)
4946747b715Smrg        return other->mask[XIAllDevices];
4956747b715Smrg    else
4966747b715Smrg        return other->mask[dev->id];
4976747b715Smrg}
4986747b715Smrg
49935c4bbdfSmrgstatic CARD8 criticalEvents[32] = {
50035c4bbdfSmrg    0x7c, 0x30, 0x40            /* key, button, expose, and configure events */
50105b261ecSmrg};
50205b261ecSmrg
5036747b715Smrgstatic void
50435c4bbdfSmrgSyntheticMotion(DeviceIntPtr dev, int x, int y)
50535c4bbdfSmrg{
5066747b715Smrg    int screenno = 0;
5076747b715Smrg
5086747b715Smrg#ifdef PANORAMIX
5096747b715Smrg    if (!noPanoramiXExtension)
5106747b715Smrg        screenno = dev->spriteInfo->sprite->screen->myNum;
5116747b715Smrg#endif
5126747b715Smrg    PostSyntheticMotion(dev, x, y, screenno,
51335c4bbdfSmrg                        (syncEvents.playingEvents) ? syncEvents.time.
51435c4bbdfSmrg                        milliseconds : currentTime.milliseconds);
5156747b715Smrg
5166747b715Smrg}
5176747b715Smrg
51805b261ecSmrg#ifdef PANORAMIX
5194642e01fSmrgstatic void PostNewCursor(DeviceIntPtr pDev);
52005b261ecSmrg
5216747b715Smrgstatic Bool
52235c4bbdfSmrgXineramaSetCursorPosition(DeviceIntPtr pDev, int x, int y, Bool generateEvent)
5236747b715Smrg{
52405b261ecSmrg    ScreenPtr pScreen;
52505b261ecSmrg    int i;
5264642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
52705b261ecSmrg
52805b261ecSmrg    /* x,y are in Screen 0 coordinates.  We need to decide what Screen
5294642e01fSmrg       to send the message too and what the coordinates relative to
53005b261ecSmrg       that screen are. */
53105b261ecSmrg
5324642e01fSmrg    pScreen = pSprite->screen;
5336747b715Smrg    x += screenInfo.screens[0]->x;
5346747b715Smrg    y += screenInfo.screens[0]->y;
53505b261ecSmrg
53635c4bbdfSmrg    if (!point_on_screen(pScreen, x, y)) {
53735c4bbdfSmrg        FOR_NSCREENS(i) {
53835c4bbdfSmrg            if (i == pScreen->myNum)
53935c4bbdfSmrg                continue;
54035c4bbdfSmrg            if (point_on_screen(screenInfo.screens[i], x, y)) {
54135c4bbdfSmrg                pScreen = screenInfo.screens[i];
54235c4bbdfSmrg                break;
54335c4bbdfSmrg            }
54435c4bbdfSmrg        }
54505b261ecSmrg    }
54605b261ecSmrg
5474642e01fSmrg    pSprite->screen = pScreen;
5486747b715Smrg    pSprite->hotPhys.x = x - screenInfo.screens[0]->x;
5496747b715Smrg    pSprite->hotPhys.y = y - screenInfo.screens[0]->y;
5506747b715Smrg    x -= pScreen->x;
5516747b715Smrg    y -= pScreen->y;
55205b261ecSmrg
55335c4bbdfSmrg    return (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent);
55405b261ecSmrg}
55505b261ecSmrg
55605b261ecSmrgstatic void
5574642e01fSmrgXineramaConstrainCursor(DeviceIntPtr pDev)
55805b261ecSmrg{
5594642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
5604642e01fSmrg    ScreenPtr pScreen;
5614642e01fSmrg    BoxRec newBox;
5624642e01fSmrg
5634642e01fSmrg    pScreen = pSprite->screen;
5644642e01fSmrg    newBox = pSprite->physLimits;
56505b261ecSmrg
56605b261ecSmrg    /* Translate the constraining box to the screen
56705b261ecSmrg       the sprite is actually on */
5686747b715Smrg    newBox.x1 += screenInfo.screens[0]->x - pScreen->x;
5696747b715Smrg    newBox.x2 += screenInfo.screens[0]->x - pScreen->x;
5706747b715Smrg    newBox.y1 += screenInfo.screens[0]->y - pScreen->y;
5716747b715Smrg    newBox.y2 += screenInfo.screens[0]->y - pScreen->y;
57205b261ecSmrg
57335c4bbdfSmrg    (*pScreen->ConstrainCursor) (pDev, pScreen, &newBox);
57405b261ecSmrg}
57505b261ecSmrg
57605b261ecSmrgstatic Bool
5774642e01fSmrgXineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
57805b261ecSmrg{
5794642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
5804642e01fSmrg
58135c4bbdfSmrg    if (pWin == screenInfo.screens[0]->root) {
58235c4bbdfSmrg        int i;
58335c4bbdfSmrg
58435c4bbdfSmrg        FOR_NSCREENS(i)
58535c4bbdfSmrg            pSprite->windows[i] = screenInfo.screens[i]->root;
58635c4bbdfSmrg    }
58735c4bbdfSmrg    else {
58835c4bbdfSmrg        PanoramiXRes *win;
58935c4bbdfSmrg        int rc, i;
59035c4bbdfSmrg
59135c4bbdfSmrg        rc = dixLookupResourceByType((void **) &win, pWin->drawable.id,
59235c4bbdfSmrg                                     XRT_WINDOW, serverClient, DixReadAccess);
59335c4bbdfSmrg        if (rc != Success)
59435c4bbdfSmrg            return FALSE;
59535c4bbdfSmrg
59635c4bbdfSmrg        FOR_NSCREENS(i) {
59735c4bbdfSmrg            rc = dixLookupWindow(pSprite->windows + i, win->info[i].id,
59835c4bbdfSmrg                                 serverClient, DixReadAccess);
59935c4bbdfSmrg            if (rc != Success)  /* window is being unmapped */
60035c4bbdfSmrg                return FALSE;
60135c4bbdfSmrg        }
60205b261ecSmrg    }
60305b261ecSmrg    return TRUE;
60405b261ecSmrg}
60505b261ecSmrg
60605b261ecSmrgstatic void
6074642e01fSmrgXineramaConfineCursorToWindow(DeviceIntPtr pDev,
60835c4bbdfSmrg                              WindowPtr pWin, Bool generateEvents)
60905b261ecSmrg{
6104642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
61105b261ecSmrg
6126747b715Smrg    int x, y, off_x, off_y, i;
61305b261ecSmrg
6144e185dc0Smrg    assert(!noPanoramiXExtension);
6154e185dc0Smrg
61635c4bbdfSmrg    if (!XineramaSetWindowPntrs(pDev, pWin))
6176747b715Smrg        return;
6184642e01fSmrg
6196747b715Smrg    i = PanoramiXNumScreens - 1;
62005b261ecSmrg
62135c4bbdfSmrg    RegionCopy(&pSprite->Reg1, &pSprite->windows[i]->borderSize);
6226747b715Smrg    off_x = screenInfo.screens[i]->x;
6236747b715Smrg    off_y = screenInfo.screens[i]->y;
62405b261ecSmrg
62535c4bbdfSmrg    while (i--) {
6266747b715Smrg        x = off_x - screenInfo.screens[i]->x;
6276747b715Smrg        y = off_y - screenInfo.screens[i]->y;
62805b261ecSmrg
62935c4bbdfSmrg        if (x || y)
6306747b715Smrg            RegionTranslate(&pSprite->Reg1, x, y);
63105b261ecSmrg
6326747b715Smrg        RegionUnion(&pSprite->Reg1, &pSprite->Reg1,
63335c4bbdfSmrg                    &pSprite->windows[i]->borderSize);
6344642e01fSmrg
6356747b715Smrg        off_x = screenInfo.screens[i]->x;
6366747b715Smrg        off_y = screenInfo.screens[i]->y;
63705b261ecSmrg    }
63805b261ecSmrg
6396747b715Smrg    pSprite->hotLimits = *RegionExtents(&pSprite->Reg1);
64005b261ecSmrg
64135c4bbdfSmrg    if (RegionNumRects(&pSprite->Reg1) > 1)
6426747b715Smrg        pSprite->hotShape = &pSprite->Reg1;
6436747b715Smrg    else
6446747b715Smrg        pSprite->hotShape = NullRegion;
6454642e01fSmrg
6466747b715Smrg    pSprite->confined = FALSE;
64735c4bbdfSmrg    pSprite->confineWin =
64835c4bbdfSmrg        (pWin == screenInfo.screens[0]->root) ? NullWindow : pWin;
64905b261ecSmrg
6506747b715Smrg    CheckPhysLimits(pDev, pSprite->current, generateEvents, FALSE, NULL);
6516747b715Smrg}
65205b261ecSmrg
65335c4bbdfSmrg#endif                          /* PANORAMIX */
65405b261ecSmrg
6556747b715Smrg/**
6566747b715Smrg * Modifies the filter for the given protocol event type to the given masks.
6576747b715Smrg *
6586747b715Smrg * There's only two callers: UpdateDeviceState() and XI's SetMaskForExtEvent().
6596747b715Smrg * The latter initialises masks for the matching XI events, it's a once-off
6606747b715Smrg * setting.
6616747b715Smrg * UDS however changes the mask for MotionNotify and DeviceMotionNotify each
6626747b715Smrg * time a button is pressed to include the matching ButtonXMotion mask in the
6636747b715Smrg * filter.
6646747b715Smrg *
6656747b715Smrg * @param[in] deviceid The device to modify the filter for.
6666747b715Smrg * @param[in] mask The new filter mask.
6676747b715Smrg * @param[in] event Protocol event type.
6686747b715Smrg */
66905b261ecSmrgvoid
6704642e01fSmrgSetMaskForEvent(int deviceid, Mask mask, int event)
67105b261ecSmrg{
67252397711Smrg    if (deviceid < 0 || deviceid >= MAXDEVICES)
6734642e01fSmrg        FatalError("SetMaskForEvent: bogus device id");
67435c4bbdfSmrg    event_filters[deviceid][event] = mask;
67505b261ecSmrg}
67605b261ecSmrg
6776747b715Smrgvoid
67805b261ecSmrgSetCriticalEvent(int event)
67905b261ecSmrg{
68035c4bbdfSmrg    if (event >= MAXEVENTS)
68135c4bbdfSmrg        FatalError("SetCriticalEvent: bogus event number");
68205b261ecSmrg    criticalEvents[event >> 3] |= 1 << (event & 7);
68305b261ecSmrg}
68405b261ecSmrg
6854642e01fSmrgvoid
6864642e01fSmrgConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
68705b261ecSmrg{
68805b261ecSmrg    BoxRec box;
68905b261ecSmrg    int x = *px, y = *py;
69005b261ecSmrg    int incx = 1, incy = 1;
69105b261ecSmrg
6926747b715Smrg    if (RegionContainsPoint(shape, x, y, &box))
69335c4bbdfSmrg        return;
6946747b715Smrg    box = *RegionExtents(shape);
69505b261ecSmrg    /* this is rather crude */
69605b261ecSmrg    do {
69735c4bbdfSmrg        x += incx;
69835c4bbdfSmrg        if (x >= box.x2) {
69935c4bbdfSmrg            incx = -1;
70035c4bbdfSmrg            x = *px - 1;
70135c4bbdfSmrg        }
70235c4bbdfSmrg        else if (x < box.x1) {
70335c4bbdfSmrg            incx = 1;
70435c4bbdfSmrg            x = *px;
70535c4bbdfSmrg            y += incy;
70635c4bbdfSmrg            if (y >= box.y2) {
70735c4bbdfSmrg                incy = -1;
70835c4bbdfSmrg                y = *py - 1;
70935c4bbdfSmrg            }
71035c4bbdfSmrg            else if (y < box.y1)
71135c4bbdfSmrg                return;         /* should never get here! */
71235c4bbdfSmrg        }
7136747b715Smrg    } while (!RegionContainsPoint(shape, x, y, &box));
71405b261ecSmrg    *px = x;
71505b261ecSmrg    *py = y;
71605b261ecSmrg}
71705b261ecSmrg
71805b261ecSmrgstatic void
71935c4bbdfSmrgCheckPhysLimits(DeviceIntPtr pDev, CursorPtr cursor, Bool generateEvents,
72035c4bbdfSmrg                Bool confineToScreen, /* unused if PanoramiX on */
72135c4bbdfSmrg                ScreenPtr pScreen)    /* unused if PanoramiX on */
72205b261ecSmrg{
72305b261ecSmrg    HotSpot new;
7244642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
72505b261ecSmrg
72605b261ecSmrg    if (!cursor)
72735c4bbdfSmrg        return;
7284642e01fSmrg    new = pSprite->hotPhys;
7296747b715Smrg#ifdef PANORAMIX
7306747b715Smrg    if (!noPanoramiXExtension)
7316747b715Smrg        /* I don't care what the DDX has to say about it */
7326747b715Smrg        pSprite->physLimits = pSprite->hotLimits;
73305b261ecSmrg    else
7346747b715Smrg#endif
7356747b715Smrg    {
7366747b715Smrg        if (pScreen)
7376747b715Smrg            new.pScreen = pScreen;
7386747b715Smrg        else
7396747b715Smrg            pScreen = new.pScreen;
7406747b715Smrg        (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits,
74135c4bbdfSmrg                                  &pSprite->physLimits);
7426747b715Smrg        pSprite->confined = confineToScreen;
74335c4bbdfSmrg        (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
7446747b715Smrg    }
7456747b715Smrg
7466747b715Smrg    /* constrain the pointer to those limits */
7474642e01fSmrg    if (new.x < pSprite->physLimits.x1)
74835c4bbdfSmrg        new.x = pSprite->physLimits.x1;
74935c4bbdfSmrg    else if (new.x >= pSprite->physLimits.x2)
75035c4bbdfSmrg        new.x = pSprite->physLimits.x2 - 1;
7514642e01fSmrg    if (new.y < pSprite->physLimits.y1)
75235c4bbdfSmrg        new.y = pSprite->physLimits.y1;
75335c4bbdfSmrg    else if (new.y >= pSprite->physLimits.y2)
75435c4bbdfSmrg        new.y = pSprite->physLimits.y2 - 1;
7554642e01fSmrg    if (pSprite->hotShape)
75635c4bbdfSmrg        ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y);
7576747b715Smrg    if ((
7586747b715Smrg#ifdef PANORAMIX
7596747b715Smrg            noPanoramiXExtension &&
7606747b715Smrg#endif
7616747b715Smrg            (pScreen != pSprite->hotPhys.pScreen)) ||
76235c4bbdfSmrg        (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y)) {
7636747b715Smrg#ifdef PANORAMIX
7646747b715Smrg        if (!noPanoramiXExtension)
76535c4bbdfSmrg            XineramaSetCursorPosition(pDev, new.x, new.y, generateEvents);
7666747b715Smrg        else
7676747b715Smrg#endif
7686747b715Smrg        {
7696747b715Smrg            if (pScreen != pSprite->hotPhys.pScreen)
7706747b715Smrg                pSprite->hotPhys = new;
7716747b715Smrg            (*pScreen->SetCursorPosition)
7726747b715Smrg                (pDev, pScreen, new.x, new.y, generateEvents);
7736747b715Smrg        }
7744642e01fSmrg        if (!generateEvents)
7756747b715Smrg            SyntheticMotion(pDev, new.x, new.y);
77605b261ecSmrg    }
7776747b715Smrg
7786747b715Smrg#ifdef PANORAMIX
7796747b715Smrg    /* Tell DDX what the limits are */
7806747b715Smrg    if (!noPanoramiXExtension)
7816747b715Smrg        XineramaConstrainCursor(pDev);
7826747b715Smrg#endif
78305b261ecSmrg}
78405b261ecSmrg
78505b261ecSmrgstatic void
78635c4bbdfSmrgCheckVirtualMotion(DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin)
78705b261ecSmrg{
7884642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
7896747b715Smrg    RegionPtr reg = NULL;
7906747b715Smrg    DeviceEvent *ev = NULL;
7914642e01fSmrg
79235c4bbdfSmrg    if (qe) {
7936747b715Smrg        ev = &qe->event->device_event;
79435c4bbdfSmrg        switch (ev->type) {
79535c4bbdfSmrg        case ET_Motion:
79635c4bbdfSmrg        case ET_ButtonPress:
79735c4bbdfSmrg        case ET_ButtonRelease:
79835c4bbdfSmrg        case ET_KeyPress:
79935c4bbdfSmrg        case ET_KeyRelease:
80035c4bbdfSmrg        case ET_ProximityIn:
80135c4bbdfSmrg        case ET_ProximityOut:
80235c4bbdfSmrg            pSprite->hot.pScreen = qe->pScreen;
80335c4bbdfSmrg            pSprite->hot.x = ev->root_x;
80435c4bbdfSmrg            pSprite->hot.y = ev->root_y;
80535c4bbdfSmrg            pWin =
80635c4bbdfSmrg                pDev->deviceGrab.grab ? pDev->deviceGrab.grab->
80735c4bbdfSmrg                confineTo : NullWindow;
80835c4bbdfSmrg            break;
80935c4bbdfSmrg        default:
81035c4bbdfSmrg            break;
8116747b715Smrg        }
81205b261ecSmrg    }
81335c4bbdfSmrg    if (pWin) {
81435c4bbdfSmrg        BoxRec lims;
81505b261ecSmrg
8166747b715Smrg#ifdef PANORAMIX
8176747b715Smrg        if (!noPanoramiXExtension) {
8186747b715Smrg            int x, y, off_x, off_y, i;
8196747b715Smrg
82035c4bbdfSmrg            if (!XineramaSetWindowPntrs(pDev, pWin))
8216747b715Smrg                return;
8226747b715Smrg
8236747b715Smrg            i = PanoramiXNumScreens - 1;
8246747b715Smrg
82535c4bbdfSmrg            RegionCopy(&pSprite->Reg2, &pSprite->windows[i]->borderSize);
8266747b715Smrg            off_x = screenInfo.screens[i]->x;
8276747b715Smrg            off_y = screenInfo.screens[i]->y;
8286747b715Smrg
82935c4bbdfSmrg            while (i--) {
8306747b715Smrg                x = off_x - screenInfo.screens[i]->x;
8316747b715Smrg                y = off_y - screenInfo.screens[i]->y;
8326747b715Smrg
83335c4bbdfSmrg                if (x || y)
8346747b715Smrg                    RegionTranslate(&pSprite->Reg2, x, y);
8356747b715Smrg
8366747b715Smrg                RegionUnion(&pSprite->Reg2, &pSprite->Reg2,
83735c4bbdfSmrg                            &pSprite->windows[i]->borderSize);
8386747b715Smrg
8396747b715Smrg                off_x = screenInfo.screens[i]->x;
8406747b715Smrg                off_y = screenInfo.screens[i]->y;
8416747b715Smrg            }
84235c4bbdfSmrg        }
84335c4bbdfSmrg        else
8446747b715Smrg#endif
8456747b715Smrg        {
84635c4bbdfSmrg            if (pSprite->hot.pScreen != pWin->drawable.pScreen) {
8476747b715Smrg                pSprite->hot.pScreen = pWin->drawable.pScreen;
8486747b715Smrg                pSprite->hot.x = pSprite->hot.y = 0;
8496747b715Smrg            }
8506747b715Smrg        }
8516747b715Smrg
85235c4bbdfSmrg        lims = *RegionExtents(&pWin->borderSize);
85335c4bbdfSmrg        if (pSprite->hot.x < lims.x1)
85435c4bbdfSmrg            pSprite->hot.x = lims.x1;
85535c4bbdfSmrg        else if (pSprite->hot.x >= lims.x2)
85635c4bbdfSmrg            pSprite->hot.x = lims.x2 - 1;
85735c4bbdfSmrg        if (pSprite->hot.y < lims.y1)
85835c4bbdfSmrg            pSprite->hot.y = lims.y1;
85935c4bbdfSmrg        else if (pSprite->hot.y >= lims.y2)
86035c4bbdfSmrg            pSprite->hot.y = lims.y2 - 1;
8616747b715Smrg
8626747b715Smrg#ifdef PANORAMIX
86335c4bbdfSmrg        if (!noPanoramiXExtension) {
8646747b715Smrg            if (RegionNumRects(&pSprite->Reg2) > 1)
8656747b715Smrg                reg = &pSprite->Reg2;
8666747b715Smrg
86735c4bbdfSmrg        }
86835c4bbdfSmrg        else
8696747b715Smrg#endif
8706747b715Smrg        {
8716747b715Smrg            if (wBoundingShape(pWin))
8726747b715Smrg                reg = &pWin->borderSize;
8736747b715Smrg        }
8746747b715Smrg
8756747b715Smrg        if (reg)
8766747b715Smrg            ConfineToShape(pDev, reg, &pSprite->hot.x, &pSprite->hot.y);
8776747b715Smrg
87835c4bbdfSmrg        if (qe && ev) {
87935c4bbdfSmrg            qe->pScreen = pSprite->hot.pScreen;
88035c4bbdfSmrg            ev->root_x = pSprite->hot.x;
88135c4bbdfSmrg            ev->root_y = pSprite->hot.y;
88235c4bbdfSmrg        }
88305b261ecSmrg    }
8846747b715Smrg#ifdef PANORAMIX
88535c4bbdfSmrg    if (noPanoramiXExtension)   /* No typo. Only set the root win if disabled */
8866747b715Smrg#endif
8879ace9065Smrg        RootWindow(pDev->spriteInfo->sprite) = pSprite->hot.pScreen->root;
88805b261ecSmrg}
88905b261ecSmrg
89005b261ecSmrgstatic void
89135c4bbdfSmrgConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents,
89235c4bbdfSmrg                      Bool confineToScreen)
89305b261ecSmrg{
8944642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
89505b261ecSmrg
89635c4bbdfSmrg    if (syncEvents.playingEvents) {
89735c4bbdfSmrg        CheckVirtualMotion(pDev, (QdEventPtr) NULL, pWin);
89835c4bbdfSmrg        SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y);
89905b261ecSmrg    }
90035c4bbdfSmrg    else {
9017e31ba66Smrg        ScreenPtr pScreen = pWin->drawable.pScreen;
9027e31ba66Smrg
9036747b715Smrg#ifdef PANORAMIX
90435c4bbdfSmrg        if (!noPanoramiXExtension) {
9056747b715Smrg            XineramaConfineCursorToWindow(pDev, pWin, generateEvents);
9066747b715Smrg            return;
9076747b715Smrg        }
9086747b715Smrg#endif
90935c4bbdfSmrg        pSprite->hotLimits = *RegionExtents(&pWin->borderSize);
91035c4bbdfSmrg        pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize
91135c4bbdfSmrg            : NullRegion;
9124642e01fSmrg        CheckPhysLimits(pDev, pSprite->current, generateEvents,
9136747b715Smrg                        confineToScreen, pWin->drawable.pScreen);
9147e31ba66Smrg
9157e31ba66Smrg        if (*pScreen->CursorConfinedTo)
9167e31ba66Smrg            (*pScreen->CursorConfinedTo) (pDev, pScreen, pWin);
91705b261ecSmrg    }
91805b261ecSmrg}
91905b261ecSmrg
9206747b715SmrgBool
9214642e01fSmrgPointerConfinedToScreen(DeviceIntPtr pDev)
92205b261ecSmrg{
9234642e01fSmrg    return pDev->spriteInfo->sprite->confined;
92405b261ecSmrg}
92505b261ecSmrg
92605b261ecSmrg/**
92705b261ecSmrg * Update the sprite cursor to the given cursor.
92805b261ecSmrg *
92905b261ecSmrg * ChangeToCursor() will display the new cursor and free the old cursor (if
93005b261ecSmrg * applicable). If the provided cursor is already the updated cursor, nothing
93105b261ecSmrg * happens.
93205b261ecSmrg */
93305b261ecSmrgstatic void
9344642e01fSmrgChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
93505b261ecSmrg{
9364642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
9376747b715Smrg    ScreenPtr pScreen;
93805b261ecSmrg
93935c4bbdfSmrg    if (cursor != pSprite->current) {
94035c4bbdfSmrg        if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
94135c4bbdfSmrg            (pSprite->current->bits->yhot != cursor->bits->yhot))
94235c4bbdfSmrg            CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined,
94335c4bbdfSmrg                            (ScreenPtr) NULL);
9446747b715Smrg#ifdef PANORAMIX
9456747b715Smrg        /* XXX: is this really necessary?? (whot) */
9466747b715Smrg        if (!noPanoramiXExtension)
9476747b715Smrg            pScreen = pSprite->screen;
9486747b715Smrg        else
9496747b715Smrg#endif
9506747b715Smrg            pScreen = pSprite->hotPhys.pScreen;
9516747b715Smrg
95235c4bbdfSmrg        (*pScreen->DisplayCursor) (pDev, pScreen, cursor);
95335c4bbdfSmrg        FreeCursor(pSprite->current, (Cursor) 0);
95435c4bbdfSmrg        pSprite->current = RefCursor(cursor);
95505b261ecSmrg    }
95605b261ecSmrg}
95705b261ecSmrg
95805b261ecSmrg/**
9594642e01fSmrg * @returns true if b is a descendent of a
96005b261ecSmrg */
96105b261ecSmrgBool
96205b261ecSmrgIsParent(WindowPtr a, WindowPtr b)
96305b261ecSmrg{
96405b261ecSmrg    for (b = b->parent; b; b = b->parent)
96535c4bbdfSmrg        if (b == a)
96635c4bbdfSmrg            return TRUE;
96705b261ecSmrg    return FALSE;
96805b261ecSmrg}
96905b261ecSmrg
97005b261ecSmrg/**
97105b261ecSmrg * Update the cursor displayed on the screen.
97205b261ecSmrg *
9734642e01fSmrg * Called whenever a cursor may have changed shape or position.
97405b261ecSmrg */
97505b261ecSmrgstatic void
9764642e01fSmrgPostNewCursor(DeviceIntPtr pDev)
97705b261ecSmrg{
97805b261ecSmrg    WindowPtr win;
9794642e01fSmrg    GrabPtr grab = pDev->deviceGrab.grab;
98035c4bbdfSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
98135c4bbdfSmrg    CursorPtr pCursor;
98205b261ecSmrg
98305b261ecSmrg    if (syncEvents.playingEvents)
98435c4bbdfSmrg        return;
98535c4bbdfSmrg    if (grab) {
98635c4bbdfSmrg        if (grab->cursor) {
98735c4bbdfSmrg            ChangeToCursor(pDev, grab->cursor);
98835c4bbdfSmrg            return;
98935c4bbdfSmrg        }
99035c4bbdfSmrg        if (IsParent(grab->window, pSprite->win))
99135c4bbdfSmrg            win = pSprite->win;
99235c4bbdfSmrg        else
99335c4bbdfSmrg            win = grab->window;
99405b261ecSmrg    }
99505b261ecSmrg    else
99635c4bbdfSmrg        win = pSprite->win;
99735c4bbdfSmrg    for (; win; win = win->parent) {
99835c4bbdfSmrg        if (win->optional) {
9994642e01fSmrg            pCursor = WindowGetDeviceCursor(win, pDev);
10004642e01fSmrg            if (!pCursor && win->optional->cursor != NullCursor)
10014642e01fSmrg                pCursor = win->optional->cursor;
100235c4bbdfSmrg            if (pCursor) {
10034642e01fSmrg                ChangeToCursor(pDev, pCursor);
10044642e01fSmrg                return;
10054642e01fSmrg            }
100635c4bbdfSmrg        }
10074642e01fSmrg    }
100805b261ecSmrg}
100905b261ecSmrg
101005b261ecSmrg/**
10114642e01fSmrg * @param dev device which you want to know its current root window
10124642e01fSmrg * @return root window where dev's sprite is located
101305b261ecSmrg */
10146747b715SmrgWindowPtr
10154642e01fSmrgGetCurrentRootWindow(DeviceIntPtr dev)
101605b261ecSmrg{
10179ace9065Smrg    return RootWindow(dev->spriteInfo->sprite);
101805b261ecSmrg}
101905b261ecSmrg
102005b261ecSmrg/**
102105b261ecSmrg * @return window underneath the cursor sprite.
102205b261ecSmrg */
10236747b715SmrgWindowPtr
10244642e01fSmrgGetSpriteWindow(DeviceIntPtr pDev)
102505b261ecSmrg{
10264642e01fSmrg    return pDev->spriteInfo->sprite->win;
102705b261ecSmrg}
102805b261ecSmrg
102905b261ecSmrg/**
103005b261ecSmrg * @return current sprite cursor.
103105b261ecSmrg */
10326747b715SmrgCursorPtr
10334642e01fSmrgGetSpriteCursor(DeviceIntPtr pDev)
103405b261ecSmrg{
10354642e01fSmrg    return pDev->spriteInfo->sprite->current;
103605b261ecSmrg}
103705b261ecSmrg
103805b261ecSmrg/**
103905b261ecSmrg * Set x/y current sprite position in screen coordinates.
104005b261ecSmrg */
10416747b715Smrgvoid
10424642e01fSmrgGetSpritePosition(DeviceIntPtr pDev, int *px, int *py)
104305b261ecSmrg{
10444642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
104535c4bbdfSmrg
10464642e01fSmrg    *px = pSprite->hotPhys.x;
10474642e01fSmrg    *py = pSprite->hotPhys.y;
104805b261ecSmrg}
104905b261ecSmrg
105005b261ecSmrg#ifdef PANORAMIX
10516747b715Smrgint
10524642e01fSmrgXineramaGetCursorScreen(DeviceIntPtr pDev)
105305b261ecSmrg{
105435c4bbdfSmrg    if (!noPanoramiXExtension) {
105535c4bbdfSmrg        return pDev->spriteInfo->sprite->screen->myNum;
105635c4bbdfSmrg    }
105735c4bbdfSmrg    else {
105835c4bbdfSmrg        return 0;
105905b261ecSmrg    }
106005b261ecSmrg}
106135c4bbdfSmrg#endif                          /* PANORAMIX */
106205b261ecSmrg
106335c4bbdfSmrg#define TIMESLOP (5 * 60 * 1000)        /* 5 minutes */
106405b261ecSmrg
106505b261ecSmrgstatic void
106635c4bbdfSmrgMonthChangedOrBadTime(CARD32 *ms)
106705b261ecSmrg{
106805b261ecSmrg    /* If the ddx/OS is careless about not processing timestamped events from
106905b261ecSmrg     * different sources in sorted order, then it's possible for time to go
107005b261ecSmrg     * backwards when it should not.  Here we ensure a decent time.
107105b261ecSmrg     */
107235c4bbdfSmrg    if ((currentTime.milliseconds - *ms) > TIMESLOP)
107335c4bbdfSmrg        currentTime.months++;
107405b261ecSmrg    else
107535c4bbdfSmrg        *ms = currentTime.milliseconds;
107635c4bbdfSmrg}
107735c4bbdfSmrg
107835c4bbdfSmrgvoid
107935c4bbdfSmrgNoticeTime(const DeviceIntPtr dev, TimeStamp time)
108035c4bbdfSmrg{
108135c4bbdfSmrg    currentTime = time;
108235c4bbdfSmrg    lastDeviceEventTime[XIAllDevices].time = currentTime;
108335c4bbdfSmrg    lastDeviceEventTime[dev->id].time = currentTime;
108435c4bbdfSmrg
108535c4bbdfSmrg    LastEventTimeToggleResetFlag(dev->id, TRUE);
108635c4bbdfSmrg    LastEventTimeToggleResetFlag(XIAllDevices, TRUE);
108705b261ecSmrg}
108805b261ecSmrg
10896747b715Smrgstatic void
109035c4bbdfSmrgNoticeTimeMillis(const DeviceIntPtr dev, CARD32 *ms)
10916747b715Smrg{
109235c4bbdfSmrg    TimeStamp time;
109335c4bbdfSmrg    if (*ms < currentTime.milliseconds)
109435c4bbdfSmrg        MonthChangedOrBadTime(ms);
109535c4bbdfSmrg    time.months = currentTime.months;
109635c4bbdfSmrg    time.milliseconds = *ms;
109735c4bbdfSmrg    NoticeTime(dev, time);
10986747b715Smrg}
109905b261ecSmrg
110005b261ecSmrgvoid
110135c4bbdfSmrgNoticeEventTime(InternalEvent *ev, DeviceIntPtr dev)
110205b261ecSmrg{
110305b261ecSmrg    if (!syncEvents.playingEvents)
110435c4bbdfSmrg        NoticeTimeMillis(dev, &ev->any.time);
110535c4bbdfSmrg}
110635c4bbdfSmrg
110735c4bbdfSmrgTimeStamp
110835c4bbdfSmrgLastEventTime(int deviceid)
110935c4bbdfSmrg{
111035c4bbdfSmrg    return lastDeviceEventTime[deviceid].time;
111135c4bbdfSmrg}
111235c4bbdfSmrg
111335c4bbdfSmrgBool
111435c4bbdfSmrgLastEventTimeWasReset(int deviceid)
111535c4bbdfSmrg{
111635c4bbdfSmrg    return lastDeviceEventTime[deviceid].reset;
111735c4bbdfSmrg}
111835c4bbdfSmrg
111935c4bbdfSmrgvoid
112035c4bbdfSmrgLastEventTimeToggleResetFlag(int deviceid, Bool state)
112135c4bbdfSmrg{
112235c4bbdfSmrg    lastDeviceEventTime[deviceid].reset = state;
112335c4bbdfSmrg}
112435c4bbdfSmrg
112535c4bbdfSmrgvoid
112635c4bbdfSmrgLastEventTimeToggleResetAll(Bool state)
112735c4bbdfSmrg{
112835c4bbdfSmrg    DeviceIntPtr dev;
112935c4bbdfSmrg    nt_list_for_each_entry(dev, inputInfo.devices, next) {
113035c4bbdfSmrg        LastEventTimeToggleResetFlag(dev->id, FALSE);
113135c4bbdfSmrg    }
113235c4bbdfSmrg    LastEventTimeToggleResetFlag(XIAllDevices, FALSE);
113335c4bbdfSmrg    LastEventTimeToggleResetFlag(XIAllMasterDevices, FALSE);
113405b261ecSmrg}
113505b261ecSmrg
113605b261ecSmrg/**************************************************************************
113705b261ecSmrg *            The following procedures deal with synchronous events       *
113805b261ecSmrg **************************************************************************/
113905b261ecSmrg
11404642e01fSmrg/**
11414642e01fSmrg * EnqueueEvent is a device's processInputProc if a device is frozen.
11424642e01fSmrg * Instead of delivering the events to the client, the event is tacked onto a
11434642e01fSmrg * linked list for later delivery.
11444642e01fSmrg */
114505b261ecSmrgvoid
11466747b715SmrgEnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
114705b261ecSmrg{
114835c4bbdfSmrg    QdEventPtr tail = NULL;
114935c4bbdfSmrg    QdEventPtr qe;
115035c4bbdfSmrg    SpritePtr pSprite = device->spriteInfo->sprite;
115135c4bbdfSmrg    int eventlen;
11526747b715Smrg    DeviceEvent *event = &ev->device_event;
11534642e01fSmrg
115435c4bbdfSmrg    if (!xorg_list_is_empty(&syncEvents.pending))
115535c4bbdfSmrg        tail = xorg_list_last_entry(&syncEvents.pending, QdEventRec, next);
115635c4bbdfSmrg
115735c4bbdfSmrg    NoticeTimeMillis(device, &ev->any.time);
115805b261ecSmrg
115905b261ecSmrg    /* Fix for key repeating bug. */
11604642e01fSmrg    if (device->key != NULL && device->key->xkbInfo != NULL &&
11616747b715Smrg        event->type == ET_KeyRelease)
116235c4bbdfSmrg        AccessXCancelRepeatKey(device->key->xkbInfo, event->detail.key);
116335c4bbdfSmrg
116435c4bbdfSmrg    if (DeviceEventCallback) {
116535c4bbdfSmrg        DeviceEventInfoRec eventinfo;
116635c4bbdfSmrg
116735c4bbdfSmrg        /*  The RECORD spec says that the root window field of motion events
116835c4bbdfSmrg         *  must be valid.  At this point, it hasn't been filled in yet, so
116935c4bbdfSmrg         *  we do it here.  The long expression below is necessary to get
117035c4bbdfSmrg         *  the current root window; the apparently reasonable alternative
117135c4bbdfSmrg         *  GetCurrentRootWindow()->drawable.id doesn't give you the right
117235c4bbdfSmrg         *  answer on the first motion event after a screen change because
117335c4bbdfSmrg         *  the data that GetCurrentRootWindow relies on hasn't been
117435c4bbdfSmrg         *  updated yet.
117535c4bbdfSmrg         */
117635c4bbdfSmrg        if (ev->any.type == ET_Motion)
117735c4bbdfSmrg            ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
117805b261ecSmrg
117935c4bbdfSmrg        eventinfo.event = ev;
118035c4bbdfSmrg        eventinfo.device = device;
118135c4bbdfSmrg        CallCallbacks(&DeviceEventCallback, (void *) &eventinfo);
118235c4bbdfSmrg    }
118335c4bbdfSmrg
118435c4bbdfSmrg    if (event->type == ET_Motion) {
118505b261ecSmrg#ifdef PANORAMIX
118635c4bbdfSmrg        if (!noPanoramiXExtension) {
118735c4bbdfSmrg            event->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
118835c4bbdfSmrg            event->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
118935c4bbdfSmrg        }
119005b261ecSmrg#endif
119135c4bbdfSmrg        pSprite->hotPhys.x = event->root_x;
119235c4bbdfSmrg        pSprite->hotPhys.y = event->root_y;
119335c4bbdfSmrg        /* do motion compression, but not if from different devices */
119435c4bbdfSmrg        if (tail &&
119535c4bbdfSmrg            (tail->event->any.type == ET_Motion) &&
119605b261ecSmrg            (tail->device == device) &&
119735c4bbdfSmrg            (tail->pScreen == pSprite->hotPhys.pScreen)) {
11986747b715Smrg            DeviceEvent *tailev = &tail->event->device_event;
119935c4bbdfSmrg
120035c4bbdfSmrg            tailev->root_x = pSprite->hotPhys.x;
120135c4bbdfSmrg            tailev->root_y = pSprite->hotPhys.y;
120235c4bbdfSmrg            tailev->time = event->time;
120335c4bbdfSmrg            tail->months = currentTime.months;
120435c4bbdfSmrg            return;
120535c4bbdfSmrg        }
120605b261ecSmrg    }
12074642e01fSmrg
12085a112b11Smrg    eventlen = sizeof(InternalEvent);
12094642e01fSmrg
12106747b715Smrg    qe = malloc(sizeof(QdEventRec) + eventlen);
121105b261ecSmrg    if (!qe)
121235c4bbdfSmrg        return;
121335c4bbdfSmrg    xorg_list_init(&qe->next);
121405b261ecSmrg    qe->device = device;
12154642e01fSmrg    qe->pScreen = pSprite->hotPhys.pScreen;
121605b261ecSmrg    qe->months = currentTime.months;
121735c4bbdfSmrg    qe->event = (InternalEvent *) (qe + 1);
12186747b715Smrg    memcpy(qe->event, event, eventlen);
121935c4bbdfSmrg    xorg_list_append(&qe->next, &syncEvents.pending);
122005b261ecSmrg}
122105b261ecSmrg
12224642e01fSmrg/**
12234642e01fSmrg * Run through the list of events queued up in syncEvents.
12244642e01fSmrg * For each event do:
12254642e01fSmrg * If the device for this event is not frozen anymore, take it and process it
12264642e01fSmrg * as usually.
12274642e01fSmrg * After that, check if there's any devices in the list that are not frozen.
12284642e01fSmrg * If there is none, we're done. If there is at least one device that is not
12294642e01fSmrg * frozen, then re-run from the beginning of the event queue.
12304642e01fSmrg */
123135c4bbdfSmrgvoid
123205b261ecSmrgPlayReleasedEvents(void)
123305b261ecSmrg{
123435c4bbdfSmrg    QdEventPtr tmp;
123535c4bbdfSmrg    QdEventPtr qe;
123605b261ecSmrg    DeviceIntPtr dev;
12374642e01fSmrg    DeviceIntPtr pDev;
123805b261ecSmrg
123935c4bbdfSmrg restart:
124035c4bbdfSmrg    xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) {
124135c4bbdfSmrg        if (!qe->device->deviceGrab.sync.frozen) {
124235c4bbdfSmrg            xorg_list_del(&qe->next);
12434642e01fSmrg            pDev = qe->device;
124435c4bbdfSmrg            if (qe->event->any.type == ET_Motion)
124535c4bbdfSmrg                CheckVirtualMotion(pDev, qe, NullWindow);
124635c4bbdfSmrg            syncEvents.time.months = qe->months;
12476747b715Smrg            syncEvents.time.milliseconds = qe->event->any.time;
124805b261ecSmrg#ifdef PANORAMIX
124935c4bbdfSmrg            /* Translate back to the sprite screen since processInputProc
125035c4bbdfSmrg               will translate from sprite screen to screen 0 upon reentry
125135c4bbdfSmrg               to the DIX layer */
125235c4bbdfSmrg            if (!noPanoramiXExtension) {
12536747b715Smrg                DeviceEvent *ev = &qe->event->device_event;
125435c4bbdfSmrg
125535c4bbdfSmrg                switch (ev->type) {
125635c4bbdfSmrg                case ET_Motion:
125735c4bbdfSmrg                case ET_ButtonPress:
125835c4bbdfSmrg                case ET_ButtonRelease:
125935c4bbdfSmrg                case ET_KeyPress:
126035c4bbdfSmrg                case ET_KeyRelease:
126135c4bbdfSmrg                case ET_ProximityIn:
126235c4bbdfSmrg                case ET_ProximityOut:
126335c4bbdfSmrg                case ET_TouchBegin:
126435c4bbdfSmrg                case ET_TouchUpdate:
126535c4bbdfSmrg                case ET_TouchEnd:
126635c4bbdfSmrg                    ev->root_x += screenInfo.screens[0]->x -
126735c4bbdfSmrg                        pDev->spriteInfo->sprite->screen->x;
126835c4bbdfSmrg                    ev->root_y += screenInfo.screens[0]->y -
126935c4bbdfSmrg                        pDev->spriteInfo->sprite->screen->y;
127035c4bbdfSmrg                    break;
127135c4bbdfSmrg                default:
127235c4bbdfSmrg                    break;
12736747b715Smrg                }
12746747b715Smrg
127535c4bbdfSmrg            }
127605b261ecSmrg#endif
127735c4bbdfSmrg            (*qe->device->public.processInputProc) (qe->event, qe->device);
127835c4bbdfSmrg            free(qe);
127935c4bbdfSmrg            for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen;
128035c4bbdfSmrg                 dev = dev->next);
128135c4bbdfSmrg            if (!dev)
128235c4bbdfSmrg                break;
128335c4bbdfSmrg
128435c4bbdfSmrg            /* Playing the event may have unfrozen another device. */
128535c4bbdfSmrg            /* So to play it safe, restart at the head of the queue */
128635c4bbdfSmrg            goto restart;
128735c4bbdfSmrg        }
12884642e01fSmrg    }
128905b261ecSmrg}
129005b261ecSmrg
12914642e01fSmrg/**
12924642e01fSmrg * Freeze or thaw the given devices. The device's processing proc is
12934642e01fSmrg * switched to either the real processing proc (in case of thawing) or an
12944642e01fSmrg * enqueuing processing proc (usually EnqueueEvent()).
12954642e01fSmrg *
12964642e01fSmrg * @param dev The device to freeze/thaw
12974642e01fSmrg * @param frozen True to freeze or false to thaw.
12984642e01fSmrg */
129905b261ecSmrgstatic void
130005b261ecSmrgFreezeThaw(DeviceIntPtr dev, Bool frozen)
130105b261ecSmrg{
13024642e01fSmrg    dev->deviceGrab.sync.frozen = frozen;
130305b261ecSmrg    if (frozen)
130435c4bbdfSmrg        dev->public.processInputProc = dev->public.enqueueInputProc;
130505b261ecSmrg    else
130635c4bbdfSmrg        dev->public.processInputProc = dev->public.realInputProc;
130705b261ecSmrg}
130805b261ecSmrg
13094642e01fSmrg/**
13104642e01fSmrg * Unfreeze devices and replay all events to the respective clients.
13114642e01fSmrg *
13124642e01fSmrg * ComputeFreezes takes the first event in the device's frozen event queue. It
13134642e01fSmrg * runs up the sprite tree (spriteTrace) and searches for the window to replay
13144642e01fSmrg * the events from. If it is found, it checks for passive grabs one down from
13154642e01fSmrg * the window or delivers the events.
13164642e01fSmrg */
13174642e01fSmrgstatic void
131805b261ecSmrgComputeFreezes(void)
131905b261ecSmrg{
132005b261ecSmrg    DeviceIntPtr replayDev = syncEvents.replayDev;
132105b261ecSmrg    GrabPtr grab;
132205b261ecSmrg    DeviceIntPtr dev;
132305b261ecSmrg
132405b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
132535c4bbdfSmrg        FreezeThaw(dev, dev->deviceGrab.sync.other ||
132635c4bbdfSmrg                   (dev->deviceGrab.sync.state >= FROZEN));
132735c4bbdfSmrg    if (syncEvents.playingEvents ||
132835c4bbdfSmrg        (!replayDev && xorg_list_is_empty(&syncEvents.pending)))
132935c4bbdfSmrg        return;
133005b261ecSmrg    syncEvents.playingEvents = TRUE;
133135c4bbdfSmrg    if (replayDev) {
13325a112b11Smrg        InternalEvent *event = replayDev->deviceGrab.sync.event;
13336747b715Smrg
133435c4bbdfSmrg        syncEvents.replayDev = (DeviceIntPtr) NULL;
133505b261ecSmrg
13365a112b11Smrg        if (!CheckDeviceGrabs(replayDev, event,
13375a112b11Smrg                              syncEvents.replayWin)) {
13385a112b11Smrg            if (IsTouchEvent(event)) {
133935c4bbdfSmrg                TouchPointInfoPtr ti =
13405a112b11Smrg                    TouchFindByClientID(replayDev, event->device_event.touchid);
134135c4bbdfSmrg                BUG_WARN(!ti);
134235c4bbdfSmrg
134335c4bbdfSmrg                TouchListenerAcceptReject(replayDev, ti, 0, XIRejectTouch);
134435c4bbdfSmrg            }
13455a112b11Smrg            else if (IsGestureEvent(event)) {
13465a112b11Smrg                GestureInfoPtr gi =
13475a112b11Smrg                    GestureFindActiveByEventType(replayDev, event->any.type);
13485a112b11Smrg                if (gi) {
13495a112b11Smrg                    GestureEmitGestureEndToOwner(replayDev, gi);
13505a112b11Smrg                    GestureEndGesture(gi);
13515a112b11Smrg                }
13525a112b11Smrg                ProcessGestureEvent(event, replayDev);
13535a112b11Smrg            }
13545a112b11Smrg            else {
13555a112b11Smrg                WindowPtr w = XYToWindow(replayDev->spriteInfo->sprite,
13565a112b11Smrg                                         event->device_event.root_x,
13575a112b11Smrg                                         event->device_event.root_y);
13585a112b11Smrg                if (replayDev->focus && !IsPointerEvent(event))
13595a112b11Smrg                    DeliverFocusedEvent(replayDev, event, w);
13605a112b11Smrg                else
13615a112b11Smrg                    DeliverDeviceEvents(w, event, NullGrab,
13625a112b11Smrg                                        NullWindow, replayDev);
13635a112b11Smrg            }
13649ace9065Smrg        }
136505b261ecSmrg    }
136635c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
136735c4bbdfSmrg        if (!dev->deviceGrab.sync.frozen) {
136835c4bbdfSmrg            PlayReleasedEvents();
136935c4bbdfSmrg            break;
137035c4bbdfSmrg        }
137105b261ecSmrg    }
137205b261ecSmrg    syncEvents.playingEvents = FALSE;
137335c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
137435c4bbdfSmrg        if (DevHasCursor(dev)) {
13754642e01fSmrg            /* the following may have been skipped during replay,
137635c4bbdfSmrg               so do it now */
137735c4bbdfSmrg            if ((grab = dev->deviceGrab.grab) && grab->confineTo) {
13784642e01fSmrg                if (grab->confineTo->drawable.pScreen !=
137935c4bbdfSmrg                    dev->spriteInfo->sprite->hotPhys.pScreen)
13804642e01fSmrg                    dev->spriteInfo->sprite->hotPhys.x =
13814642e01fSmrg                        dev->spriteInfo->sprite->hotPhys.y = 0;
13824642e01fSmrg                ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE);
13834642e01fSmrg            }
13844642e01fSmrg            else
13854642e01fSmrg                ConfineCursorToWindow(dev,
138635c4bbdfSmrg                                      dev->spriteInfo->sprite->hotPhys.pScreen->
138735c4bbdfSmrg                                      root, TRUE, FALSE);
13884642e01fSmrg            PostNewCursor(dev);
13894642e01fSmrg        }
139005b261ecSmrg    }
139105b261ecSmrg}
139205b261ecSmrg
139305b261ecSmrg#ifdef RANDR
139405b261ecSmrgvoid
139535c4bbdfSmrgScreenRestructured(ScreenPtr pScreen)
139605b261ecSmrg{
139705b261ecSmrg    GrabPtr grab;
13984642e01fSmrg    DeviceIntPtr pDev;
139905b261ecSmrg
140035c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
140135c4bbdfSmrg        if (!IsFloating(pDev) && !DevHasCursor(pDev))
14024642e01fSmrg            continue;
14034642e01fSmrg
14044642e01fSmrg        /* GrabDevice doesn't have a confineTo field, so we don't need to
14054642e01fSmrg         * worry about it. */
140635c4bbdfSmrg        if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
14074642e01fSmrg            if (grab->confineTo->drawable.pScreen
140835c4bbdfSmrg                != pDev->spriteInfo->sprite->hotPhys.pScreen)
140935c4bbdfSmrg                pDev->spriteInfo->sprite->hotPhys.x =
141035c4bbdfSmrg                    pDev->spriteInfo->sprite->hotPhys.y = 0;
14114642e01fSmrg            ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
14124642e01fSmrg        }
14134642e01fSmrg        else
14144642e01fSmrg            ConfineCursorToWindow(pDev,
141535c4bbdfSmrg                                  pDev->spriteInfo->sprite->hotPhys.pScreen->
141635c4bbdfSmrg                                  root, TRUE, FALSE);
141705b261ecSmrg    }
141805b261ecSmrg}
141905b261ecSmrg#endif
142005b261ecSmrg
14214642e01fSmrgstatic void
142205b261ecSmrgCheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
142305b261ecSmrg{
14244642e01fSmrg    GrabPtr grab = thisDev->deviceGrab.grab;
142505b261ecSmrg    DeviceIntPtr dev;
142605b261ecSmrg
142705b261ecSmrg    if (thisMode == GrabModeSync)
142835c4bbdfSmrg        thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT;
142935c4bbdfSmrg    else {                      /* free both if same client owns both */
143035c4bbdfSmrg        thisDev->deviceGrab.sync.state = THAWED;
143135c4bbdfSmrg        if (thisDev->deviceGrab.sync.other &&
143235c4bbdfSmrg            (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) ==
143335c4bbdfSmrg             CLIENT_BITS(grab->resource)))
143435c4bbdfSmrg            thisDev->deviceGrab.sync.other = NullGrab;
143505b261ecSmrg    }
14364642e01fSmrg
143735c4bbdfSmrg    if (IsMaster(thisDev)) {
14384642e01fSmrg        dev = GetPairedDevice(thisDev);
14394642e01fSmrg        if (otherMode == GrabModeSync)
14404642e01fSmrg            dev->deviceGrab.sync.other = grab;
144135c4bbdfSmrg        else {                  /* free both if same client owns both */
14424642e01fSmrg            if (dev->deviceGrab.sync.other &&
144335c4bbdfSmrg                (CLIENT_BITS(dev->deviceGrab.sync.other->resource) ==
144435c4bbdfSmrg                 CLIENT_BITS(grab->resource)))
14454642e01fSmrg                dev->deviceGrab.sync.other = NullGrab;
14464642e01fSmrg        }
144705b261ecSmrg    }
144805b261ecSmrg    ComputeFreezes();
144905b261ecSmrg}
145005b261ecSmrg
14516747b715Smrg/**
14526747b715Smrg * Save the device's master device id. This needs to be done
14536747b715Smrg * if a client directly grabs a slave device that is attached to a master. For
14546747b715Smrg * the duration of the grab, the device is detached, ungrabbing re-attaches it
14556747b715Smrg * though.
14566747b715Smrg *
14576747b715Smrg * We store the ID of the master device only in case the master disappears
14586747b715Smrg * while the device has a grab.
14596747b715Smrg */
14606747b715Smrgstatic void
14616747b715SmrgDetachFromMaster(DeviceIntPtr dev)
14626747b715Smrg{
146335c4bbdfSmrg    if (IsFloating(dev))
14646747b715Smrg        return;
14656747b715Smrg
146635c4bbdfSmrg    dev->saved_master_id = GetMaster(dev, MASTER_ATTACHED)->id;
14676747b715Smrg
14686747b715Smrg    AttachDevice(NULL, dev, NULL);
14696747b715Smrg}
14706747b715Smrg
14716747b715Smrgstatic void
14726747b715SmrgReattachToOldMaster(DeviceIntPtr dev)
14736747b715Smrg{
14746747b715Smrg    DeviceIntPtr master = NULL;
14756747b715Smrg
14766747b715Smrg    if (IsMaster(dev))
14776747b715Smrg        return;
14786747b715Smrg
14796747b715Smrg    dixLookupDevice(&master, dev->saved_master_id, serverClient, DixUseAccess);
14806747b715Smrg
148135c4bbdfSmrg    if (master) {
14826747b715Smrg        AttachDevice(serverClient, dev, master);
148335c4bbdfSmrg        dev->saved_master_id = 0;
148435c4bbdfSmrg    }
148535c4bbdfSmrg}
148635c4bbdfSmrg
148735c4bbdfSmrg/**
148835c4bbdfSmrg * Update touch records when an explicit grab is activated. Any touches owned by
148935c4bbdfSmrg * the grabbing client are updated so the listener state reflects the new grab.
149035c4bbdfSmrg */
149135c4bbdfSmrgstatic void
149235c4bbdfSmrgUpdateTouchesForGrab(DeviceIntPtr mouse)
149335c4bbdfSmrg{
149435c4bbdfSmrg    int i;
149535c4bbdfSmrg
149635c4bbdfSmrg    if (!mouse->touch || mouse->deviceGrab.fromPassiveGrab)
149735c4bbdfSmrg        return;
149835c4bbdfSmrg
149935c4bbdfSmrg    for (i = 0; i < mouse->touch->num_touches; i++) {
150035c4bbdfSmrg        TouchPointInfoPtr ti = mouse->touch->touches + i;
150135c4bbdfSmrg        TouchListener *listener = &ti->listeners[0];
150235c4bbdfSmrg        GrabPtr grab = mouse->deviceGrab.grab;
150335c4bbdfSmrg
150435c4bbdfSmrg        if (ti->active &&
150535c4bbdfSmrg            CLIENT_BITS(listener->listener) == grab->resource) {
15065a112b11Smrg            if (grab->grabtype == CORE || grab->grabtype == XI ||
15075a112b11Smrg                !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin)) {
150890bea6a0Smrg                /*  Note that the grab will override any current listeners and if these listeners
150990bea6a0Smrg                    already received touch events then this is the place to send touch end event
151090bea6a0Smrg                    to complete the touch sequence.
15115a112b11Smrg
151290bea6a0Smrg                    Unfortunately GTK3 menu widget implementation relies on not getting touch end
151390bea6a0Smrg                    event, so we can't fix the current behavior.
151490bea6a0Smrg                */
15155a112b11Smrg                listener->type = TOUCH_LISTENER_POINTER_GRAB;
15165a112b11Smrg            } else {
15175a112b11Smrg                listener->type = TOUCH_LISTENER_GRAB;
15185a112b11Smrg            }
15195a112b11Smrg
152035c4bbdfSmrg            listener->listener = grab->resource;
152135c4bbdfSmrg            listener->level = grab->grabtype;
152235c4bbdfSmrg            listener->window = grab->window;
15235a112b11Smrg            listener->state = TOUCH_LISTENER_IS_OWNER;
152435c4bbdfSmrg
152535c4bbdfSmrg            if (listener->grab)
152635c4bbdfSmrg                FreeGrab(listener->grab);
152735c4bbdfSmrg            listener->grab = AllocGrab(grab);
152835c4bbdfSmrg        }
15296747b715Smrg    }
15306747b715Smrg}
15316747b715Smrg
15325a112b11Smrg/**
15335a112b11Smrg * Update gesture records when an explicit grab is activated. Any gestures owned
15345a112b11Smrg * by the grabbing client are updated so the listener state reflects the new
15355a112b11Smrg * grab.
15365a112b11Smrg */
15375a112b11Smrgstatic void
15385a112b11SmrgUpdateGesturesForGrab(DeviceIntPtr mouse)
15395a112b11Smrg{
15405a112b11Smrg    if (!mouse->gesture || mouse->deviceGrab.fromPassiveGrab)
15415a112b11Smrg        return;
15425a112b11Smrg
15435a112b11Smrg    GestureInfoPtr gi = &mouse->gesture->gesture;
15445a112b11Smrg    GestureListener *listener = &gi->listener;
15455a112b11Smrg    GrabPtr grab = mouse->deviceGrab.grab;
15465a112b11Smrg
15475a112b11Smrg    if (gi->active && CLIENT_BITS(listener->listener) == grab->resource) {
15485a112b11Smrg        if (grab->grabtype == CORE || grab->grabtype == XI ||
15495a112b11Smrg            !xi2mask_isset(grab->xi2mask, mouse, GetXI2Type(gi->type))) {
15505a112b11Smrg
15515a112b11Smrg            if (listener->type == GESTURE_LISTENER_REGULAR) {
15525a112b11Smrg                /* if the listener already got any events relating to the gesture, we must send
15535a112b11Smrg                   a gesture end because the grab overrides the previous listener and won't
15545a112b11Smrg                   itself send any gesture events.
15555a112b11Smrg                */
15565a112b11Smrg                GestureEmitGestureEndToOwner(mouse, gi);
15575a112b11Smrg            }
15585a112b11Smrg            listener->type = GESTURE_LISTENER_NONGESTURE_GRAB;
15595a112b11Smrg        } else {
15605a112b11Smrg            listener->type = GESTURE_LISTENER_GRAB;
15615a112b11Smrg        }
15625a112b11Smrg
15635a112b11Smrg        listener->listener = grab->resource;
15645a112b11Smrg        listener->window = grab->window;
15655a112b11Smrg
15665a112b11Smrg        if (listener->grab)
15675a112b11Smrg            FreeGrab(listener->grab);
15685a112b11Smrg        listener->grab = AllocGrab(grab);
15695a112b11Smrg    }
15705a112b11Smrg}
15715a112b11Smrg
157205b261ecSmrg/**
157305b261ecSmrg * Activate a pointer grab on the given device. A pointer grab will cause all
15744642e01fSmrg * core pointer events of this device to be delivered to the grabbing client only.
15754642e01fSmrg * No other device will send core events to the grab client while the grab is
15764642e01fSmrg * on, but core events will be sent to other clients.
15774642e01fSmrg * Can cause the cursor to change if a grab cursor is set.
15784642e01fSmrg *
15794642e01fSmrg * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab
15804642e01fSmrg * is an implicit grab caused by a ButtonPress event.
15814642e01fSmrg *
158205b261ecSmrg * @param mouse The device to grab.
158305b261ecSmrg * @param grab The grab structure, needs to be setup.
158405b261ecSmrg * @param autoGrab True if the grab was caused by a button down event and not
15855a112b11Smrg * explicitly by a client.
158605b261ecSmrg */
158705b261ecSmrgvoid
15884642e01fSmrgActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
158905b261ecSmrg                    TimeStamp time, Bool autoGrab)
159005b261ecSmrg{
15914642e01fSmrg    GrabInfoPtr grabinfo = &mouse->deviceGrab;
159235c4bbdfSmrg    GrabPtr oldgrab = grabinfo->grab;
15934642e01fSmrg    WindowPtr oldWin = (grabinfo->grab) ?
159435c4bbdfSmrg        grabinfo->grab->window : mouse->spriteInfo->sprite->win;
15954642e01fSmrg    Bool isPassive = autoGrab & ~ImplicitGrabMask;
159605b261ecSmrg
15976747b715Smrg    /* slave devices need to float for the duration of the grab. */
159835c4bbdfSmrg    if (grab->grabtype == XI2 &&
15996747b715Smrg        !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse))
16006747b715Smrg        DetachFromMaster(mouse);
16016747b715Smrg
160235c4bbdfSmrg    if (grab->confineTo) {
160335c4bbdfSmrg        if (grab->confineTo->drawable.pScreen
160435c4bbdfSmrg            != mouse->spriteInfo->sprite->hotPhys.pScreen)
160535c4bbdfSmrg            mouse->spriteInfo->sprite->hotPhys.x =
16064642e01fSmrg                mouse->spriteInfo->sprite->hotPhys.y = 0;
160735c4bbdfSmrg        ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE);
160805b261ecSmrg    }
1609806e81e9Smrg    if (! (grabinfo->grab && oldWin == grabinfo->grab->window
1610806e81e9Smrg			  && oldWin == grab->window))
1611806e81e9Smrg        DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab);
161205b261ecSmrg    mouse->valuator->motionHintWindow = NullWindow;
161305b261ecSmrg    if (syncEvents.playingEvents)
16144642e01fSmrg        grabinfo->grabTime = syncEvents.time;
161505b261ecSmrg    else
161635c4bbdfSmrg        grabinfo->grabTime = time;
161735c4bbdfSmrg    grabinfo->grab = AllocGrab(grab);
16184642e01fSmrg    grabinfo->fromPassiveGrab = isPassive;
16194642e01fSmrg    grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
16204642e01fSmrg    PostNewCursor(mouse);
162135c4bbdfSmrg    UpdateTouchesForGrab(mouse);
16225a112b11Smrg    UpdateGesturesForGrab(mouse);
162335c4bbdfSmrg    CheckGrabForSyncs(mouse, (Bool) grab->pointerMode,
162435c4bbdfSmrg                      (Bool) grab->keyboardMode);
162535c4bbdfSmrg    if (oldgrab)
162635c4bbdfSmrg        FreeGrab(oldgrab);
162705b261ecSmrg}
162805b261ecSmrg
162905b261ecSmrg/**
163005b261ecSmrg * Delete grab on given device, update the sprite.
163105b261ecSmrg *
16324642e01fSmrg * Extension devices are set up for ActivateKeyboardGrab().
163305b261ecSmrg */
163405b261ecSmrgvoid
163505b261ecSmrgDeactivatePointerGrab(DeviceIntPtr mouse)
163605b261ecSmrg{
16374642e01fSmrg    GrabPtr grab = mouse->deviceGrab.grab;
163805b261ecSmrg    DeviceIntPtr dev;
163935c4bbdfSmrg    Bool wasPassive = mouse->deviceGrab.fromPassiveGrab;
16406747b715Smrg    Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
16416747b715Smrg                        mouse->deviceGrab.implicitGrab);
164235c4bbdfSmrg    XID grab_resource = grab->resource;
164335c4bbdfSmrg    int i;
164435c4bbdfSmrg
164535c4bbdfSmrg    /* If an explicit grab was deactivated, we must remove it from the head of
164635c4bbdfSmrg     * all the touches' listener lists. */
164735c4bbdfSmrg    for (i = 0; !wasPassive && mouse->touch && i < mouse->touch->num_touches; i++) {
164835c4bbdfSmrg        TouchPointInfoPtr ti = mouse->touch->touches + i;
164935c4bbdfSmrg        if (ti->active && TouchResourceIsOwner(ti, grab_resource)) {
165035c4bbdfSmrg            int mode = XIRejectTouch;
165135c4bbdfSmrg            /* Rejecting will generate a TouchEnd, but we must not
165235c4bbdfSmrg               emulate a ButtonRelease here. So pretend the listener
165335c4bbdfSmrg               already has the end event */
165435c4bbdfSmrg            if (grab->grabtype == CORE || grab->grabtype == XI ||
16555a112b11Smrg                    !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin)) {
165635c4bbdfSmrg                mode = XIAcceptTouch;
165735c4bbdfSmrg                /* NOTE: we set the state here, but
165835c4bbdfSmrg                 * ProcessTouchOwnershipEvent() will still call
165935c4bbdfSmrg                 * TouchEmitTouchEnd for this listener. The other half of
166035c4bbdfSmrg                 * this hack is in DeliverTouchEndEvent */
16615a112b11Smrg                ti->listeners[0].state = TOUCH_LISTENER_HAS_END;
166235c4bbdfSmrg            }
166335c4bbdfSmrg            TouchListenerAcceptReject(mouse, ti, 0, mode);
166435c4bbdfSmrg        }
166535c4bbdfSmrg    }
166635c4bbdfSmrg
166735c4bbdfSmrg    TouchRemovePointerGrab(mouse);
166805b261ecSmrg
166905b261ecSmrg    mouse->valuator->motionHintWindow = NullWindow;
16704642e01fSmrg    mouse->deviceGrab.grab = NullGrab;
16714642e01fSmrg    mouse->deviceGrab.sync.state = NOT_GRABBED;
16724642e01fSmrg    mouse->deviceGrab.fromPassiveGrab = FALSE;
16734642e01fSmrg
167435c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
167535c4bbdfSmrg        if (dev->deviceGrab.sync.other == grab)
167635c4bbdfSmrg            dev->deviceGrab.sync.other = NullGrab;
167705b261ecSmrg    }
16785a112b11Smrg
16795a112b11Smrg    /* in case of explicit gesture grab, send end event to the grab client */
16805a112b11Smrg    if (!wasPassive && mouse->gesture) {
16815a112b11Smrg        GestureInfoPtr gi = &mouse->gesture->gesture;
16825a112b11Smrg        if (gi->active && GestureResourceIsOwner(gi, grab_resource)) {
16835a112b11Smrg            GestureEmitGestureEndToOwner(mouse, gi);
16845a112b11Smrg            GestureEndGesture(gi);
16855a112b11Smrg        }
16865a112b11Smrg    }
16875a112b11Smrg
16886747b715Smrg    DoEnterLeaveEvents(mouse, mouse->id, grab->window,
16894642e01fSmrg                       mouse->spriteInfo->sprite->win, NotifyUngrab);
169005b261ecSmrg    if (grab->confineTo)
169135c4bbdfSmrg        ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE);
16924642e01fSmrg    PostNewCursor(mouse);
16934642e01fSmrg
169435c4bbdfSmrg    if (!wasImplicit && grab->grabtype == XI2)
16956747b715Smrg        ReattachToOldMaster(mouse);
16966747b715Smrg
169705b261ecSmrg    ComputeFreezes();
169835c4bbdfSmrg
169935c4bbdfSmrg    FreeGrab(grab);
170005b261ecSmrg}
170105b261ecSmrg
170205b261ecSmrg/**
17034642e01fSmrg * Activate a keyboard grab on the given device.
170405b261ecSmrg *
170505b261ecSmrg * Extension devices have ActivateKeyboardGrab() set as their grabbing proc.
170605b261ecSmrg */
170705b261ecSmrgvoid
170835c4bbdfSmrgActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time,
170935c4bbdfSmrg                     Bool passive)
171005b261ecSmrg{
17114642e01fSmrg    GrabInfoPtr grabinfo = &keybd->deviceGrab;
171235c4bbdfSmrg    GrabPtr oldgrab = grabinfo->grab;
171305b261ecSmrg    WindowPtr oldWin;
171405b261ecSmrg
17156747b715Smrg    /* slave devices need to float for the duration of the grab. */
171635c4bbdfSmrg    if (grab->grabtype == XI2 && keybd->enabled &&
171735c4bbdfSmrg        !(passive & ImplicitGrabMask) && !IsMaster(keybd))
17186747b715Smrg        DetachFromMaster(keybd);
17196747b715Smrg
172035c4bbdfSmrg    if (!keybd->enabled)
172135c4bbdfSmrg        oldWin = NULL;
172235c4bbdfSmrg    else if (grabinfo->grab)
172335c4bbdfSmrg        oldWin = grabinfo->grab->window;
172405b261ecSmrg    else if (keybd->focus)
172535c4bbdfSmrg        oldWin = keybd->focus->win;
172605b261ecSmrg    else
172735c4bbdfSmrg        oldWin = keybd->spriteInfo->sprite->win;
172805b261ecSmrg    if (oldWin == FollowKeyboardWin)
172935c4bbdfSmrg        oldWin = keybd->focus->win;
173005b261ecSmrg    if (keybd->valuator)
173135c4bbdfSmrg        keybd->valuator->motionHintWindow = NullWindow;
1732806e81e9Smrg    if (oldWin &&
1733806e81e9Smrg	! (grabinfo->grab && oldWin == grabinfo->grab->window
1734806e81e9Smrg			  && oldWin == grab->window))
173535c4bbdfSmrg        DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
173605b261ecSmrg    if (syncEvents.playingEvents)
173735c4bbdfSmrg        grabinfo->grabTime = syncEvents.time;
173805b261ecSmrg    else
173935c4bbdfSmrg        grabinfo->grabTime = time;
174035c4bbdfSmrg    grabinfo->grab = AllocGrab(grab);
17414642e01fSmrg    grabinfo->fromPassiveGrab = passive;
17426747b715Smrg    grabinfo->implicitGrab = passive & ImplicitGrabMask;
174335c4bbdfSmrg    CheckGrabForSyncs(keybd, (Bool) grab->keyboardMode,
174435c4bbdfSmrg                      (Bool) grab->pointerMode);
174535c4bbdfSmrg    if (oldgrab)
174635c4bbdfSmrg        FreeGrab(oldgrab);
174705b261ecSmrg}
174805b261ecSmrg
174905b261ecSmrg/**
17504642e01fSmrg * Delete keyboard grab for the given device.
175105b261ecSmrg */
175205b261ecSmrgvoid
175305b261ecSmrgDeactivateKeyboardGrab(DeviceIntPtr keybd)
175405b261ecSmrg{
17554642e01fSmrg    GrabPtr grab = keybd->deviceGrab.grab;
175605b261ecSmrg    DeviceIntPtr dev;
175735c4bbdfSmrg    WindowPtr focusWin;
17586747b715Smrg    Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab &&
17596747b715Smrg                        keybd->deviceGrab.implicitGrab);
176005b261ecSmrg
176105b261ecSmrg    if (keybd->valuator)
176235c4bbdfSmrg        keybd->valuator->motionHintWindow = NullWindow;
17634642e01fSmrg    keybd->deviceGrab.grab = NullGrab;
17644642e01fSmrg    keybd->deviceGrab.sync.state = NOT_GRABBED;
17654642e01fSmrg    keybd->deviceGrab.fromPassiveGrab = FALSE;
17664642e01fSmrg
176735c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
176835c4bbdfSmrg        if (dev->deviceGrab.sync.other == grab)
176935c4bbdfSmrg            dev->deviceGrab.sync.other = NullGrab;
177005b261ecSmrg    }
177135c4bbdfSmrg
177235c4bbdfSmrg    if (keybd->focus)
177335c4bbdfSmrg        focusWin = keybd->focus->win;
177435c4bbdfSmrg    else if (keybd->spriteInfo->sprite)
177535c4bbdfSmrg        focusWin = keybd->spriteInfo->sprite->win;
177635c4bbdfSmrg    else
177735c4bbdfSmrg        focusWin = NullWindow;
177835c4bbdfSmrg
177935c4bbdfSmrg    if (focusWin == FollowKeyboardWin)
178035c4bbdfSmrg        focusWin = inputInfo.keyboard->focus->win;
178135c4bbdfSmrg
178205b261ecSmrg    DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
17834642e01fSmrg
178435c4bbdfSmrg    if (!wasImplicit && grab->grabtype == XI2)
17856747b715Smrg        ReattachToOldMaster(keybd);
17866747b715Smrg
178705b261ecSmrg    ComputeFreezes();
178835c4bbdfSmrg
178935c4bbdfSmrg    FreeGrab(grab);
179005b261ecSmrg}
179105b261ecSmrg
179205b261ecSmrgvoid
179335c4bbdfSmrgAllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState)
179405b261ecSmrg{
179505b261ecSmrg    Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
179605b261ecSmrg    TimeStamp grabTime;
179705b261ecSmrg    DeviceIntPtr dev;
179835c4bbdfSmrg    GrabInfoPtr devgrabinfo, grabinfo = &thisDev->deviceGrab;
179905b261ecSmrg
18004642e01fSmrg    thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
180105b261ecSmrg    thisSynced = FALSE;
180205b261ecSmrg    otherGrabbed = FALSE;
18036747b715Smrg    othersFrozen = FALSE;
18044642e01fSmrg    grabTime = grabinfo->grabTime;
180535c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
18064642e01fSmrg        devgrabinfo = &dev->deviceGrab;
18074642e01fSmrg
180835c4bbdfSmrg        if (dev == thisDev)
180935c4bbdfSmrg            continue;
181035c4bbdfSmrg        if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) {
181135c4bbdfSmrg            if (!(thisGrabbed || otherGrabbed) ||
181235c4bbdfSmrg                (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER))
181335c4bbdfSmrg                grabTime = devgrabinfo->grabTime;
181435c4bbdfSmrg            otherGrabbed = TRUE;
181535c4bbdfSmrg            if (grabinfo->sync.other == devgrabinfo->grab)
181635c4bbdfSmrg                thisSynced = TRUE;
181735c4bbdfSmrg            if (devgrabinfo->sync.state >= FROZEN)
181835c4bbdfSmrg                othersFrozen = TRUE;
181935c4bbdfSmrg        }
182005b261ecSmrg    }
18214642e01fSmrg    if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced))
182235c4bbdfSmrg        return;
182305b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
182435c4bbdfSmrg        (CompareTimeStamps(time, grabTime) == EARLIER))
182535c4bbdfSmrg        return;
182635c4bbdfSmrg    switch (newState) {
182735c4bbdfSmrg    case THAWED:               /* Async */
182835c4bbdfSmrg        if (thisGrabbed)
182935c4bbdfSmrg            grabinfo->sync.state = THAWED;
183035c4bbdfSmrg        if (thisSynced)
183135c4bbdfSmrg            grabinfo->sync.other = NullGrab;
183235c4bbdfSmrg        ComputeFreezes();
183335c4bbdfSmrg        break;
183435c4bbdfSmrg    case FREEZE_NEXT_EVENT:    /* Sync */
183535c4bbdfSmrg        if (thisGrabbed) {
183635c4bbdfSmrg            grabinfo->sync.state = FREEZE_NEXT_EVENT;
183735c4bbdfSmrg            if (thisSynced)
183835c4bbdfSmrg                grabinfo->sync.other = NullGrab;
183935c4bbdfSmrg            ComputeFreezes();
184035c4bbdfSmrg        }
184135c4bbdfSmrg        break;
184235c4bbdfSmrg    case THAWED_BOTH:          /* AsyncBoth */
184335c4bbdfSmrg        if (othersFrozen) {
184435c4bbdfSmrg            for (dev = inputInfo.devices; dev; dev = dev->next) {
184535c4bbdfSmrg                devgrabinfo = &dev->deviceGrab;
184635c4bbdfSmrg                if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
184735c4bbdfSmrg                    devgrabinfo->sync.state = THAWED;
184835c4bbdfSmrg                if (devgrabinfo->sync.other &&
184935c4bbdfSmrg                    SameClient(devgrabinfo->sync.other, client))
185035c4bbdfSmrg                    devgrabinfo->sync.other = NullGrab;
185135c4bbdfSmrg            }
185235c4bbdfSmrg            ComputeFreezes();
185335c4bbdfSmrg        }
185435c4bbdfSmrg        break;
185535c4bbdfSmrg    case FREEZE_BOTH_NEXT_EVENT:       /* SyncBoth */
185635c4bbdfSmrg        if (othersFrozen) {
185735c4bbdfSmrg            for (dev = inputInfo.devices; dev; dev = dev->next) {
185835c4bbdfSmrg                devgrabinfo = &dev->deviceGrab;
185935c4bbdfSmrg                if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
186035c4bbdfSmrg                    devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT;
186135c4bbdfSmrg                if (devgrabinfo->sync.other
186235c4bbdfSmrg                    && SameClient(devgrabinfo->sync.other, client))
186335c4bbdfSmrg                    devgrabinfo->sync.other = NullGrab;
186435c4bbdfSmrg            }
186535c4bbdfSmrg            ComputeFreezes();
186635c4bbdfSmrg        }
186735c4bbdfSmrg        break;
186835c4bbdfSmrg    case NOT_GRABBED:          /* Replay */
186935c4bbdfSmrg        if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT) {
187035c4bbdfSmrg            if (thisSynced)
187135c4bbdfSmrg                grabinfo->sync.other = NullGrab;
187235c4bbdfSmrg            syncEvents.replayDev = thisDev;
187335c4bbdfSmrg            syncEvents.replayWin = grabinfo->grab->window;
187435c4bbdfSmrg            (*grabinfo->DeactivateGrab) (thisDev);
187535c4bbdfSmrg            syncEvents.replayDev = (DeviceIntPtr) NULL;
187635c4bbdfSmrg        }
187735c4bbdfSmrg        break;
187835c4bbdfSmrg    case THAW_OTHERS:          /* AsyncOthers */
187935c4bbdfSmrg        if (othersFrozen) {
188035c4bbdfSmrg            for (dev = inputInfo.devices; dev; dev = dev->next) {
188135c4bbdfSmrg                if (dev == thisDev)
188235c4bbdfSmrg                    continue;
188335c4bbdfSmrg                devgrabinfo = &dev->deviceGrab;
188435c4bbdfSmrg                if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
188535c4bbdfSmrg                    devgrabinfo->sync.state = THAWED;
188635c4bbdfSmrg                if (devgrabinfo->sync.other
188735c4bbdfSmrg                    && SameClient(devgrabinfo->sync.other, client))
188835c4bbdfSmrg                    devgrabinfo->sync.other = NullGrab;
188935c4bbdfSmrg            }
189035c4bbdfSmrg            ComputeFreezes();
189135c4bbdfSmrg        }
189235c4bbdfSmrg        break;
189335c4bbdfSmrg    }
189435c4bbdfSmrg
189535c4bbdfSmrg    /* We've unfrozen the grab. If the grab was a touch grab, we're now the
189635c4bbdfSmrg     * owner and expected to accept/reject it. Reject == ReplayPointer which
189735c4bbdfSmrg     * we've handled in ComputeFreezes() (during DeactivateGrab) above,
189835c4bbdfSmrg     * anything else is accept.
189935c4bbdfSmrg     */
190035c4bbdfSmrg    if (newState != NOT_GRABBED /* Replay */ &&
19015a112b11Smrg        IsTouchEvent(grabinfo->sync.event)) {
19025a112b11Smrg        TouchAcceptAndEnd(thisDev, grabinfo->sync.event->device_event.touchid);
190305b261ecSmrg    }
190405b261ecSmrg}
190505b261ecSmrg
190605b261ecSmrg/**
190705b261ecSmrg * Server-side protocol handling for AllowEvents request.
190805b261ecSmrg *
19094642e01fSmrg * Release some events from a frozen device.
191005b261ecSmrg */
191105b261ecSmrgint
191205b261ecSmrgProcAllowEvents(ClientPtr client)
191305b261ecSmrg{
191435c4bbdfSmrg    TimeStamp time;
191535c4bbdfSmrg    DeviceIntPtr mouse = NULL;
191635c4bbdfSmrg    DeviceIntPtr keybd = NULL;
191735c4bbdfSmrg
191805b261ecSmrg    REQUEST(xAllowEventsReq);
191905b261ecSmrg
192005b261ecSmrg    REQUEST_SIZE_MATCH(xAllowEventsReq);
19217e31ba66Smrg    UpdateCurrentTime();
192205b261ecSmrg    time = ClientTimeToServerTime(stuff->time);
19234642e01fSmrg
19244642e01fSmrg    mouse = PickPointer(client);
19254642e01fSmrg    keybd = PickKeyboard(client);
19264642e01fSmrg
192735c4bbdfSmrg    switch (stuff->mode) {
192835c4bbdfSmrg    case ReplayPointer:
192935c4bbdfSmrg        AllowSome(client, time, mouse, NOT_GRABBED);
193035c4bbdfSmrg        break;
193135c4bbdfSmrg    case SyncPointer:
193235c4bbdfSmrg        AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
193335c4bbdfSmrg        break;
193435c4bbdfSmrg    case AsyncPointer:
193535c4bbdfSmrg        AllowSome(client, time, mouse, THAWED);
193635c4bbdfSmrg        break;
193735c4bbdfSmrg    case ReplayKeyboard:
193835c4bbdfSmrg        AllowSome(client, time, keybd, NOT_GRABBED);
193935c4bbdfSmrg        break;
194035c4bbdfSmrg    case SyncKeyboard:
194135c4bbdfSmrg        AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
194235c4bbdfSmrg        break;
194335c4bbdfSmrg    case AsyncKeyboard:
194435c4bbdfSmrg        AllowSome(client, time, keybd, THAWED);
194535c4bbdfSmrg        break;
194635c4bbdfSmrg    case SyncBoth:
194735c4bbdfSmrg        AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
194835c4bbdfSmrg        break;
194935c4bbdfSmrg    case AsyncBoth:
195035c4bbdfSmrg        AllowSome(client, time, keybd, THAWED_BOTH);
195135c4bbdfSmrg        break;
195235c4bbdfSmrg    default:
195335c4bbdfSmrg        client->errorValue = stuff->mode;
195435c4bbdfSmrg        return BadValue;
195505b261ecSmrg    }
195605b261ecSmrg    return Success;
195705b261ecSmrg}
195805b261ecSmrg
195905b261ecSmrg/**
196005b261ecSmrg * Deactivate grabs from any device that has been grabbed by the client.
196105b261ecSmrg */
196205b261ecSmrgvoid
196305b261ecSmrgReleaseActiveGrabs(ClientPtr client)
196405b261ecSmrg{
196505b261ecSmrg    DeviceIntPtr dev;
196635c4bbdfSmrg    Bool done;
196705b261ecSmrg
196805b261ecSmrg    /* XXX CloseDownClient should remove passive grabs before
196905b261ecSmrg     * releasing active grabs.
197005b261ecSmrg     */
197105b261ecSmrg    do {
197235c4bbdfSmrg        done = TRUE;
197335c4bbdfSmrg        for (dev = inputInfo.devices; dev; dev = dev->next) {
197435c4bbdfSmrg            if (dev->deviceGrab.grab &&
197535c4bbdfSmrg                SameClient(dev->deviceGrab.grab, client)) {
197635c4bbdfSmrg                (*dev->deviceGrab.DeactivateGrab) (dev);
197735c4bbdfSmrg                done = FALSE;
197835c4bbdfSmrg            }
197935c4bbdfSmrg        }
198005b261ecSmrg    } while (!done);
198105b261ecSmrg}
198205b261ecSmrg
198305b261ecSmrg/**************************************************************************
198405b261ecSmrg *            The following procedures deal with delivering events        *
198505b261ecSmrg **************************************************************************/
198605b261ecSmrg
198705b261ecSmrg/**
198805b261ecSmrg * Deliver the given events to the given client.
198905b261ecSmrg *
199005b261ecSmrg * More than one event may be delivered at a time. This is the case with
199105b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events.
199205b261ecSmrg *
199305b261ecSmrg * TryClientEvents() is the last station before actually writing the events to
199405b261ecSmrg * the socket. Anything that is not filtered here, will get delivered to the
19954642e01fSmrg * client.
19964642e01fSmrg * An event is only delivered if
199705b261ecSmrg *   - mask and filter match up.
199805b261ecSmrg *   - no other client has a grab on the device that caused the event.
19994642e01fSmrg *
200005b261ecSmrg *
200105b261ecSmrg * @param client The target client to deliver to.
20024642e01fSmrg * @param dev The device the event came from. May be NULL.
200305b261ecSmrg * @param pEvents The events to be delivered.
200405b261ecSmrg * @param count Number of elements in pEvents.
200505b261ecSmrg * @param mask Event mask as set by the window.
200605b261ecSmrg * @param filter Mask based on event type.
20074642e01fSmrg * @param grab Possible grab on the device that caused the event.
200805b261ecSmrg *
200905b261ecSmrg * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
201005b261ecSmrg * client.
201105b261ecSmrg */
20126747b715Smrgint
201335c4bbdfSmrgTryClientEvents(ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
201435c4bbdfSmrg                int count, Mask mask, Mask filter, GrabPtr grab)
201505b261ecSmrg{
201605b261ecSmrg    int type;
201705b261ecSmrg
201805b261ecSmrg#ifdef DEBUG_EVENTS
20196747b715Smrg    ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s",
20206747b715Smrg           pEvents->u.u.type, pEvents->u.u.detail, mask,
20216747b715Smrg           client ? client->index : -1,
20226747b715Smrg           (client && client->clientGone) ? " (gone)" : "");
202305b261ecSmrg#endif
20246747b715Smrg
20256747b715Smrg    if (!client || client == serverClient || client->clientGone) {
202605b261ecSmrg#ifdef DEBUG_EVENTS
20276747b715Smrg        ErrorF(" not delivered to fake/dead client\n");
202805b261ecSmrg#endif
20296747b715Smrg        return 0;
20306747b715Smrg    }
203105b261ecSmrg
203235c4bbdfSmrg    if (filter != CantBeFiltered && !(mask & filter)) {
203335c4bbdfSmrg#ifdef DEBUG_EVENTS
20346747b715Smrg        ErrorF(" filtered\n");
203535c4bbdfSmrg#endif
20366747b715Smrg        return 0;
20376747b715Smrg    }
203805b261ecSmrg
203935c4bbdfSmrg    if (grab && !SameClient(grab, client)) {
204005b261ecSmrg#ifdef DEBUG_EVENTS
20416747b715Smrg        ErrorF(" not delivered due to grab\n");
204205b261ecSmrg#endif
204335c4bbdfSmrg        return -1;              /* don't send, but notify caller */
204405b261ecSmrg    }
20456747b715Smrg
20466747b715Smrg    type = pEvents->u.u.type;
204735c4bbdfSmrg    if (type == MotionNotify) {
204835c4bbdfSmrg        if (mask & PointerMotionHintMask) {
20496747b715Smrg            if (WID(dev->valuator->motionHintWindow) ==
205035c4bbdfSmrg                pEvents->u.keyButtonPointer.event) {
205105b261ecSmrg#ifdef DEBUG_EVENTS
20526747b715Smrg                ErrorF("[dix] \n");
20536747b715Smrg                ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
205405b261ecSmrg#endif
205535c4bbdfSmrg                return 1;       /* don't send, but pretend we did */
20566747b715Smrg            }
20576747b715Smrg            pEvents->u.u.detail = NotifyHint;
20586747b715Smrg        }
205935c4bbdfSmrg        else {
20606747b715Smrg            pEvents->u.u.detail = NotifyNormal;
20616747b715Smrg        }
20626747b715Smrg    }
206335c4bbdfSmrg    else if (type == DeviceMotionNotify) {
206435c4bbdfSmrg        if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer *) pEvents,
20656747b715Smrg                                            mask) != 0)
20666747b715Smrg            return 1;
206735c4bbdfSmrg    }
206835c4bbdfSmrg    else if (type == KeyPress) {
206935c4bbdfSmrg        if (EventIsKeyRepeat(pEvents)) {
207035c4bbdfSmrg            if (!_XkbWantsDetectableAutoRepeat(client)) {
20716747b715Smrg                xEvent release = *pEvents;
207235c4bbdfSmrg
20736747b715Smrg                release.u.u.type = KeyRelease;
20746747b715Smrg                WriteEventsToClient(client, 1, &release);
20756747b715Smrg#ifdef DEBUG_EVENTS
20766747b715Smrg                ErrorF(" (plus fake core release for repeat)");
20776747b715Smrg#endif
207835c4bbdfSmrg            }
207935c4bbdfSmrg            else {
20806747b715Smrg#ifdef DEBUG_EVENTS
20816747b715Smrg                ErrorF(" (detectable autorepeat for core)");
20826747b715Smrg#endif
20836747b715Smrg            }
20846747b715Smrg        }
20856747b715Smrg
208635c4bbdfSmrg    }
208735c4bbdfSmrg    else if (type == DeviceKeyPress) {
208835c4bbdfSmrg        if (EventIsKeyRepeat(pEvents)) {
208935c4bbdfSmrg            if (!_XkbWantsDetectableAutoRepeat(client)) {
209035c4bbdfSmrg                deviceKeyButtonPointer release =
209135c4bbdfSmrg                    *(deviceKeyButtonPointer *) pEvents;
20926747b715Smrg                release.type = DeviceKeyRelease;
20936747b715Smrg#ifdef DEBUG_EVENTS
20946747b715Smrg                ErrorF(" (plus fake xi1 release for repeat)");
20956747b715Smrg#endif
20966747b715Smrg                WriteEventsToClient(client, 1, (xEvent *) &release);
20976747b715Smrg            }
20986747b715Smrg            else {
20996747b715Smrg#ifdef DEBUG_EVENTS
21006747b715Smrg                ErrorF(" (detectable autorepeat for core)");
21016747b715Smrg#endif
21026747b715Smrg            }
21036747b715Smrg        }
21046747b715Smrg    }
21056747b715Smrg
210635c4bbdfSmrg    if (BitIsOn(criticalEvents, type)) {
21076747b715Smrg        if (client->smart_priority < SMART_MAX_PRIORITY)
21086747b715Smrg            client->smart_priority++;
21096747b715Smrg        SetCriticalOutputPending();
211005b261ecSmrg    }
21116747b715Smrg
21126747b715Smrg    WriteEventsToClient(client, count, pEvents);
21136747b715Smrg#ifdef DEBUG_EVENTS
21146747b715Smrg    ErrorF("[dix]  delivered\n");
21156747b715Smrg#endif
21166747b715Smrg    return 1;
211705b261ecSmrg}
211805b261ecSmrg
211935c4bbdfSmrgstatic BOOL
212035c4bbdfSmrgActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win,
212135c4bbdfSmrg                     xEvent *event, Mask deliveryMask)
212235c4bbdfSmrg{
212335c4bbdfSmrg    GrabPtr tempGrab;
212435c4bbdfSmrg    OtherInputMasks *inputMasks;
212535c4bbdfSmrg    CARD8 type = event->u.u.type;
212635c4bbdfSmrg    enum InputLevel grabtype;
212735c4bbdfSmrg
212835c4bbdfSmrg    if (type == ButtonPress)
212935c4bbdfSmrg        grabtype = CORE;
213035c4bbdfSmrg    else if (type == DeviceButtonPress)
213135c4bbdfSmrg        grabtype = XI;
213235c4bbdfSmrg    else if ((type = xi2_get_type(event)) == XI_ButtonPress)
213335c4bbdfSmrg        grabtype = XI2;
213435c4bbdfSmrg    else
213535c4bbdfSmrg        return FALSE;
213635c4bbdfSmrg
213735c4bbdfSmrg    tempGrab = AllocGrab(NULL);
213835c4bbdfSmrg    if (!tempGrab)
213935c4bbdfSmrg        return FALSE;
214035c4bbdfSmrg    tempGrab->next = NULL;
214135c4bbdfSmrg    tempGrab->device = dev;
214235c4bbdfSmrg    tempGrab->resource = client->clientAsMask;
214335c4bbdfSmrg    tempGrab->window = win;
214435c4bbdfSmrg    tempGrab->ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
214535c4bbdfSmrg    tempGrab->eventMask = deliveryMask;
214635c4bbdfSmrg    tempGrab->keyboardMode = GrabModeAsync;
214735c4bbdfSmrg    tempGrab->pointerMode = GrabModeAsync;
214835c4bbdfSmrg    tempGrab->confineTo = NullWindow;
214935c4bbdfSmrg    tempGrab->cursor = NullCursor;
215035c4bbdfSmrg    tempGrab->type = type;
215135c4bbdfSmrg    tempGrab->grabtype = grabtype;
215235c4bbdfSmrg
215335c4bbdfSmrg    /* get the XI and XI2 device mask */
215435c4bbdfSmrg    inputMasks = wOtherInputMasks(win);
215535c4bbdfSmrg    tempGrab->deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id] : 0;
215635c4bbdfSmrg
215735c4bbdfSmrg    if (inputMasks)
215835c4bbdfSmrg        xi2mask_merge(tempGrab->xi2mask, inputMasks->xi2mask);
215935c4bbdfSmrg
216035c4bbdfSmrg    (*dev->deviceGrab.ActivateGrab) (dev, tempGrab,
216135c4bbdfSmrg                                     currentTime, TRUE | ImplicitGrabMask);
216235c4bbdfSmrg    FreeGrab(tempGrab);
216335c4bbdfSmrg    return TRUE;
216435c4bbdfSmrg}
216535c4bbdfSmrg
216635c4bbdfSmrg/**
216735c4bbdfSmrg * Attempt event delivery to the client owning the window.
216835c4bbdfSmrg */
216935c4bbdfSmrgstatic enum EventDeliveryState
217035c4bbdfSmrgDeliverToWindowOwner(DeviceIntPtr dev, WindowPtr win,
217135c4bbdfSmrg                     xEvent *events, int count, Mask filter, GrabPtr grab)
217235c4bbdfSmrg{
217335c4bbdfSmrg    /* if nobody ever wants to see this event, skip some work */
217435c4bbdfSmrg    if (filter != CantBeFiltered &&
217535c4bbdfSmrg        !((wOtherEventMasks(win) | win->eventMask) & filter))
217635c4bbdfSmrg        return EVENT_SKIP;
217735c4bbdfSmrg
217835c4bbdfSmrg    if (IsInterferingGrab(wClient(win), dev, events))
217935c4bbdfSmrg        return EVENT_SKIP;
218035c4bbdfSmrg
218135c4bbdfSmrg    if (!XaceHook(XACE_RECEIVE_ACCESS, wClient(win), win, events, count)) {
218235c4bbdfSmrg        int attempt = TryClientEvents(wClient(win), dev, events,
218335c4bbdfSmrg                                      count, win->eventMask,
218435c4bbdfSmrg                                      filter, grab);
218535c4bbdfSmrg
218635c4bbdfSmrg        if (attempt > 0)
218735c4bbdfSmrg            return EVENT_DELIVERED;
218835c4bbdfSmrg        if (attempt < 0)
218935c4bbdfSmrg            return EVENT_REJECTED;
219035c4bbdfSmrg    }
219135c4bbdfSmrg
219235c4bbdfSmrg    return EVENT_NOT_DELIVERED;
219335c4bbdfSmrg}
219435c4bbdfSmrg
219535c4bbdfSmrg/**
219635c4bbdfSmrg * Get the list of clients that should be tried for event delivery on the
219735c4bbdfSmrg * given window.
219835c4bbdfSmrg *
219935c4bbdfSmrg * @return 1 if the client list should be traversed, zero if the event
220035c4bbdfSmrg * should be skipped.
220135c4bbdfSmrg */
220235c4bbdfSmrgstatic Bool
220335c4bbdfSmrgGetClientsForDelivery(DeviceIntPtr dev, WindowPtr win,
220435c4bbdfSmrg                      xEvent *events, Mask filter, InputClients ** iclients)
220535c4bbdfSmrg{
220635c4bbdfSmrg    int rc = 0;
220735c4bbdfSmrg
220835c4bbdfSmrg    if (core_get_type(events) != 0)
220935c4bbdfSmrg        *iclients = (InputClients *) wOtherClients(win);
221035c4bbdfSmrg    else if (xi2_get_type(events) != 0) {
221135c4bbdfSmrg        OtherInputMasks *inputMasks = wOtherInputMasks(win);
221235c4bbdfSmrg
221335c4bbdfSmrg        /* Has any client selected for the event? */
221435c4bbdfSmrg        if (!WindowXI2MaskIsset(dev, win, events))
221535c4bbdfSmrg            goto out;
221635c4bbdfSmrg        *iclients = inputMasks->inputClients;
221735c4bbdfSmrg    }
221835c4bbdfSmrg    else {
221935c4bbdfSmrg        OtherInputMasks *inputMasks = wOtherInputMasks(win);
222035c4bbdfSmrg
222135c4bbdfSmrg        /* Has any client selected for the event? */
222235c4bbdfSmrg        if (!inputMasks || !(inputMasks->inputEvents[dev->id] & filter))
222335c4bbdfSmrg            goto out;
222435c4bbdfSmrg
222535c4bbdfSmrg        *iclients = inputMasks->inputClients;
222635c4bbdfSmrg    }
222735c4bbdfSmrg
222835c4bbdfSmrg    rc = 1;
222935c4bbdfSmrg out:
223035c4bbdfSmrg    return rc;
223135c4bbdfSmrg}
223235c4bbdfSmrg
223335c4bbdfSmrg/**
223435c4bbdfSmrg * Try delivery on each client in inputclients, provided the event mask
223535c4bbdfSmrg * accepts it and there is no interfering core grab..
223635c4bbdfSmrg */
223735c4bbdfSmrgstatic enum EventDeliveryState
223835c4bbdfSmrgDeliverEventToInputClients(DeviceIntPtr dev, InputClients * inputclients,
223935c4bbdfSmrg                           WindowPtr win, xEvent *events,
224035c4bbdfSmrg                           int count, Mask filter, GrabPtr grab,
224135c4bbdfSmrg                           ClientPtr *client_return, Mask *mask_return)
224235c4bbdfSmrg{
224335c4bbdfSmrg    int attempt;
224435c4bbdfSmrg    enum EventDeliveryState rc = EVENT_NOT_DELIVERED;
224535c4bbdfSmrg    Bool have_device_button_grab_class_client = FALSE;
224635c4bbdfSmrg
224735c4bbdfSmrg    for (; inputclients; inputclients = inputclients->next) {
224835c4bbdfSmrg        Mask mask;
224935c4bbdfSmrg        ClientPtr client = rClient(inputclients);
225035c4bbdfSmrg
225135c4bbdfSmrg        if (IsInterferingGrab(client, dev, events))
225235c4bbdfSmrg            continue;
225335c4bbdfSmrg
225435c4bbdfSmrg        if (IsWrongPointerBarrierClient(client, dev, events))
225535c4bbdfSmrg            continue;
225635c4bbdfSmrg
225735c4bbdfSmrg        mask = GetEventMask(dev, events, inputclients);
225835c4bbdfSmrg
225935c4bbdfSmrg        if (XaceHook(XACE_RECEIVE_ACCESS, client, win, events, count))
226035c4bbdfSmrg            /* do nothing */ ;
226135c4bbdfSmrg        else if ((attempt = TryClientEvents(client, dev,
226235c4bbdfSmrg                                            events, count,
226335c4bbdfSmrg                                            mask, filter, grab))) {
226435c4bbdfSmrg            if (attempt > 0) {
226535c4bbdfSmrg                /*
226635c4bbdfSmrg                 * The order of clients is arbitrary therefore if one
226735c4bbdfSmrg                 * client belongs to DeviceButtonGrabClass make sure to
226835c4bbdfSmrg                 * catch it.
226935c4bbdfSmrg                 */
227035c4bbdfSmrg                if (!have_device_button_grab_class_client) {
227135c4bbdfSmrg                    rc = EVENT_DELIVERED;
227235c4bbdfSmrg                    *client_return = client;
227335c4bbdfSmrg                    *mask_return = mask;
227435c4bbdfSmrg                    /* Success overrides non-success, so if we've been
227535c4bbdfSmrg                     * successful on one client, return that */
227635c4bbdfSmrg                    if (mask & DeviceButtonGrabMask)
227735c4bbdfSmrg                        have_device_button_grab_class_client = TRUE;
227835c4bbdfSmrg                }
227935c4bbdfSmrg            } else if (rc == EVENT_NOT_DELIVERED)
228035c4bbdfSmrg                rc = EVENT_REJECTED;
228135c4bbdfSmrg        }
228235c4bbdfSmrg    }
228335c4bbdfSmrg
228435c4bbdfSmrg    return rc;
228535c4bbdfSmrg}
228635c4bbdfSmrg
228735c4bbdfSmrg/**
228835c4bbdfSmrg * Deliver events to clients registered on the window.
228935c4bbdfSmrg *
229035c4bbdfSmrg * @param client_return On successful delivery, set to the recipient.
229135c4bbdfSmrg * @param mask_return On successful delivery, set to the recipient's event
229235c4bbdfSmrg * mask for this event.
229335c4bbdfSmrg */
229435c4bbdfSmrgstatic enum EventDeliveryState
229535c4bbdfSmrgDeliverEventToWindowMask(DeviceIntPtr dev, WindowPtr win, xEvent *events,
229635c4bbdfSmrg                         int count, Mask filter, GrabPtr grab,
229735c4bbdfSmrg                         ClientPtr *client_return, Mask *mask_return)
229835c4bbdfSmrg{
229935c4bbdfSmrg    InputClients *iclients;
230035c4bbdfSmrg
230135c4bbdfSmrg    if (!GetClientsForDelivery(dev, win, events, filter, &iclients))
230235c4bbdfSmrg        return EVENT_SKIP;
230335c4bbdfSmrg
230435c4bbdfSmrg    return DeliverEventToInputClients(dev, iclients, win, events, count, filter,
230535c4bbdfSmrg                                      grab, client_return, mask_return);
230635c4bbdfSmrg
230735c4bbdfSmrg}
230835c4bbdfSmrg
230905b261ecSmrg/**
231005b261ecSmrg * Deliver events to a window. At this point, we do not yet know if the event
231105b261ecSmrg * actually needs to be delivered. May activate a grab if the event is a
231205b261ecSmrg * button press.
231305b261ecSmrg *
23144642e01fSmrg * Core events are always delivered to the window owner. If the filter is
23154642e01fSmrg * something other than CantBeFiltered, the event is also delivered to other
23164642e01fSmrg * clients with the matching mask on the window.
23174642e01fSmrg *
231805b261ecSmrg * More than one event may be delivered at a time. This is the case with
231905b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events.
23204642e01fSmrg *
232105b261ecSmrg * @param pWin The window that would get the event.
232205b261ecSmrg * @param pEvents The events to be delivered.
232305b261ecSmrg * @param count Number of elements in pEvents.
232405b261ecSmrg * @param filter Mask based on event type.
23254642e01fSmrg * @param grab Possible grab on the device that caused the event.
232605b261ecSmrg *
232735c4bbdfSmrg * @return a positive number if at least one successful delivery has been
232835c4bbdfSmrg * made, 0 if no events were delivered, or a negative number if the event
232935c4bbdfSmrg * has not been delivered _and_ rejected by at least one client.
233005b261ecSmrg */
233105b261ecSmrgint
23324642e01fSmrgDeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
233335c4bbdfSmrg                      *pEvents, int count, Mask filter, GrabPtr grab)
233405b261ecSmrg{
233505b261ecSmrg    int deliveries = 0, nondeliveries = 0;
233605b261ecSmrg    ClientPtr client = NullClient;
233735c4bbdfSmrg    Mask deliveryMask = 0;      /* If a grab occurs due to a button press, then
233835c4bbdfSmrg                                   this mask is the mask of the grab. */
233905b261ecSmrg    int type = pEvents->u.u.type;
234005b261ecSmrg
23416747b715Smrg    /* Deliver to window owner */
234235c4bbdfSmrg    if ((filter == CantBeFiltered) || core_get_type(pEvents) != 0) {
234335c4bbdfSmrg        enum EventDeliveryState rc;
23444642e01fSmrg
234535c4bbdfSmrg        rc = DeliverToWindowOwner(pDev, pWin, pEvents, count, filter, grab);
23464642e01fSmrg
234735c4bbdfSmrg        switch (rc) {
234835c4bbdfSmrg        case EVENT_SKIP:
234935c4bbdfSmrg            return 0;
235035c4bbdfSmrg        case EVENT_REJECTED:
235135c4bbdfSmrg            nondeliveries--;
235235c4bbdfSmrg            break;
235335c4bbdfSmrg        case EVENT_DELIVERED:
235435c4bbdfSmrg            /* We delivered to the owner, with our event mask */
235535c4bbdfSmrg            deliveries++;
235635c4bbdfSmrg            client = wClient(pWin);
235735c4bbdfSmrg            deliveryMask = pWin->eventMask;
235835c4bbdfSmrg            break;
235935c4bbdfSmrg        case EVENT_NOT_DELIVERED:
236035c4bbdfSmrg            break;
236135c4bbdfSmrg        }
236205b261ecSmrg    }
23636747b715Smrg
23646747b715Smrg    /* CantBeFiltered means only window owner gets the event */
236535c4bbdfSmrg    if (filter != CantBeFiltered) {
236635c4bbdfSmrg        enum EventDeliveryState rc;
236735c4bbdfSmrg
236835c4bbdfSmrg        rc = DeliverEventToWindowMask(pDev, pWin, pEvents, count, filter,
236935c4bbdfSmrg                                      grab, &client, &deliveryMask);
23704642e01fSmrg
237135c4bbdfSmrg        switch (rc) {
237235c4bbdfSmrg        case EVENT_SKIP:
237335c4bbdfSmrg            return 0;
237435c4bbdfSmrg        case EVENT_REJECTED:
237535c4bbdfSmrg            nondeliveries--;
237635c4bbdfSmrg            break;
237735c4bbdfSmrg        case EVENT_DELIVERED:
237835c4bbdfSmrg            deliveries++;
237935c4bbdfSmrg            break;
238035c4bbdfSmrg        case EVENT_NOT_DELIVERED:
238135c4bbdfSmrg            break;
23824642e01fSmrg        }
238335c4bbdfSmrg    }
23844642e01fSmrg
238535c4bbdfSmrg    if (deliveries) {
238635c4bbdfSmrg        /*
238735c4bbdfSmrg         * Note that since core events are delivered first, an implicit grab may
238835c4bbdfSmrg         * be activated on a core grab, stopping the XI events.
238935c4bbdfSmrg         */
239035c4bbdfSmrg        if (!grab &&
239135c4bbdfSmrg            ActivateImplicitGrab(pDev, client, pWin, pEvents, deliveryMask))
239235c4bbdfSmrg            /* grab activated */ ;
239335c4bbdfSmrg        else if (type == MotionNotify)
239435c4bbdfSmrg            pDev->valuator->motionHintWindow = pWin;
239535c4bbdfSmrg        else if (type == DeviceMotionNotify || type == DeviceButtonPress)
239635c4bbdfSmrg            CheckDeviceGrabAndHintWindow(pWin, type,
239735c4bbdfSmrg                                         (deviceKeyButtonPointer *) pEvents,
239835c4bbdfSmrg                                         grab, client, deliveryMask);
239935c4bbdfSmrg        return deliveries;
240035c4bbdfSmrg    }
240135c4bbdfSmrg    return nondeliveries;
240235c4bbdfSmrg}
240335c4bbdfSmrg
240435c4bbdfSmrg/**
240535c4bbdfSmrg * Filter out raw events for XI 2.0 and XI 2.1 clients.
240635c4bbdfSmrg *
240735c4bbdfSmrg * If there is a grab on the device, 2.0 clients only get raw events if they
240835c4bbdfSmrg * have the grab. 2.1+ clients get raw events in all cases.
240935c4bbdfSmrg *
241035c4bbdfSmrg * @return TRUE if the event should be discarded, FALSE otherwise.
241135c4bbdfSmrg */
241235c4bbdfSmrgstatic BOOL
241335c4bbdfSmrgFilterRawEvents(const ClientPtr client, const GrabPtr grab, WindowPtr root)
241435c4bbdfSmrg{
241535c4bbdfSmrg    XIClientPtr client_xi_version;
241635c4bbdfSmrg    int cmp;
24176747b715Smrg
241835c4bbdfSmrg    /* device not grabbed -> don't filter */
241935c4bbdfSmrg    if (!grab)
242035c4bbdfSmrg        return FALSE;
24216747b715Smrg
242235c4bbdfSmrg    client_xi_version =
242335c4bbdfSmrg        dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
242435c4bbdfSmrg
242535c4bbdfSmrg    cmp = version_compare(client_xi_version->major_version,
242635c4bbdfSmrg                          client_xi_version->minor_version, 2, 0);
242735c4bbdfSmrg    /* XI 2.0: if device is grabbed, skip
242835c4bbdfSmrg       XI 2.1: if device is grabbed by us, skip, we've already delivered */
242935c4bbdfSmrg    if (cmp == 0)
243035c4bbdfSmrg        return TRUE;
243135c4bbdfSmrg
243235c4bbdfSmrg    return (grab->window != root) ? FALSE : SameClient(grab, client);
243335c4bbdfSmrg}
243435c4bbdfSmrg
243535c4bbdfSmrg/**
243635c4bbdfSmrg * Deliver a raw event to the grab owner (if any) and to all root windows.
243735c4bbdfSmrg *
243835c4bbdfSmrg * Raw event delivery differs between XI 2.0 and XI 2.1.
243935c4bbdfSmrg * XI 2.0: events delivered to the grabbing client (if any) OR to all root
244035c4bbdfSmrg * windows
244135c4bbdfSmrg * XI 2.1: events delivered to all root windows, regardless of grabbing
244235c4bbdfSmrg * state.
244335c4bbdfSmrg */
244435c4bbdfSmrgvoid
244535c4bbdfSmrgDeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
244635c4bbdfSmrg{
244735c4bbdfSmrg    GrabPtr grab = device->deviceGrab.grab;
244835c4bbdfSmrg    xEvent *xi;
244935c4bbdfSmrg    int i, rc;
245035c4bbdfSmrg    int filter;
245135c4bbdfSmrg
245235c4bbdfSmrg    rc = EventToXI2((InternalEvent *) ev, (xEvent **) &xi);
245335c4bbdfSmrg    if (rc != Success) {
245435c4bbdfSmrg        ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n",
245535c4bbdfSmrg               __func__, device->name, rc);
245635c4bbdfSmrg        return;
245705b261ecSmrg    }
24584642e01fSmrg
245935c4bbdfSmrg    if (grab)
246035c4bbdfSmrg        DeliverGrabbedEvent((InternalEvent *) ev, device, FALSE);
246135c4bbdfSmrg
246235c4bbdfSmrg    filter = GetEventFilter(device, xi);
246335c4bbdfSmrg
246435c4bbdfSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
246535c4bbdfSmrg        WindowPtr root;
246635c4bbdfSmrg        InputClients *inputclients;
246735c4bbdfSmrg
246835c4bbdfSmrg        root = screenInfo.screens[i]->root;
246935c4bbdfSmrg        if (!GetClientsForDelivery(device, root, xi, filter, &inputclients))
247035c4bbdfSmrg            continue;
247135c4bbdfSmrg
247235c4bbdfSmrg        for (; inputclients; inputclients = inputclients->next) {
247335c4bbdfSmrg            ClientPtr c;        /* unused */
247435c4bbdfSmrg            Mask m;             /* unused */
247535c4bbdfSmrg            InputClients ic = *inputclients;
24764642e01fSmrg
247735c4bbdfSmrg            /* Because we run through the list manually, copy the actual
247835c4bbdfSmrg             * list, shorten the copy to only have one client and then pass
247935c4bbdfSmrg             * that down to DeliverEventToInputClients. This way we avoid
248035c4bbdfSmrg             * double events on XI 2.1 clients that have a grab on the
248135c4bbdfSmrg             * device.
248235c4bbdfSmrg             */
248335c4bbdfSmrg            ic.next = NULL;
24846747b715Smrg
248535c4bbdfSmrg            if (!FilterRawEvents(rClient(&ic), grab, root))
248635c4bbdfSmrg                DeliverEventToInputClients(device, &ic, root, xi, 1,
248735c4bbdfSmrg                                           filter, NULL, &c, &m);
248835c4bbdfSmrg        }
248905b261ecSmrg    }
249035c4bbdfSmrg
249135c4bbdfSmrg    free(xi);
249205b261ecSmrg}
249305b261ecSmrg
249405b261ecSmrg/* If the event goes to dontClient, don't send it and return 0.  if
249505b261ecSmrg   send works,  return 1 or if send didn't work, return 2.
249605b261ecSmrg   Only works for core events.
249705b261ecSmrg*/
249805b261ecSmrg
249905b261ecSmrg#ifdef PANORAMIX
25004642e01fSmrgstatic int
250135c4bbdfSmrgXineramaTryClientEventsResult(ClientPtr client,
250235c4bbdfSmrg                              GrabPtr grab, Mask mask, Mask filter)
250335c4bbdfSmrg{
250405b261ecSmrg    if ((client) && (client != serverClient) && (!client->clientGone) &&
250535c4bbdfSmrg        ((filter == CantBeFiltered) || (mask & filter))) {
250635c4bbdfSmrg        if (grab && !SameClient(grab, client))
250735c4bbdfSmrg            return -1;
250835c4bbdfSmrg        else
250935c4bbdfSmrg            return 1;
251005b261ecSmrg    }
251105b261ecSmrg    return 0;
251205b261ecSmrg}
251305b261ecSmrg#endif
251405b261ecSmrg
251505b261ecSmrg/**
251605b261ecSmrg * Try to deliver events to the interested parties.
251705b261ecSmrg *
251805b261ecSmrg * @param pWin The window that would get the event.
251905b261ecSmrg * @param pEvents The events to be delivered.
252005b261ecSmrg * @param count Number of elements in pEvents.
252105b261ecSmrg * @param filter Mask based on event type.
252205b261ecSmrg * @param dontClient Don't deliver to the dontClient.
252305b261ecSmrg */
252405b261ecSmrgint
25254642e01fSmrgMaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
252605b261ecSmrg                           int count, Mask filter, ClientPtr dontClient)
252705b261ecSmrg{
252805b261ecSmrg    OtherClients *other;
252905b261ecSmrg
253035c4bbdfSmrg    if (pWin->eventMask & filter) {
253105b261ecSmrg        if (wClient(pWin) == dontClient)
253235c4bbdfSmrg            return 0;
253305b261ecSmrg#ifdef PANORAMIX
253435c4bbdfSmrg        if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
253535c4bbdfSmrg            return XineramaTryClientEventsResult(wClient(pWin), NullGrab,
253635c4bbdfSmrg                                                 pWin->eventMask, filter);
253705b261ecSmrg#endif
253835c4bbdfSmrg        if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
253935c4bbdfSmrg            return 1;           /* don't send, but pretend we did */
254035c4bbdfSmrg        return TryClientEvents(wClient(pWin), NULL, pEvents, count,
254135c4bbdfSmrg                               pWin->eventMask, filter, NullGrab);
254205b261ecSmrg    }
254335c4bbdfSmrg    for (other = wOtherClients(pWin); other; other = other->next) {
254435c4bbdfSmrg        if (other->mask & filter) {
254505b261ecSmrg            if (SameClient(other, dontClient))
254635c4bbdfSmrg                return 0;
254705b261ecSmrg#ifdef PANORAMIX
254835c4bbdfSmrg            if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
254935c4bbdfSmrg                return XineramaTryClientEventsResult(rClient(other), NullGrab,
255035c4bbdfSmrg                                                     other->mask, filter);
255105b261ecSmrg#endif
255235c4bbdfSmrg            if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents,
255335c4bbdfSmrg                         count))
255435c4bbdfSmrg                return 1;       /* don't send, but pretend we did */
255535c4bbdfSmrg            return TryClientEvents(rClient(other), NULL, pEvents, count,
255635c4bbdfSmrg                                   other->mask, filter, NullGrab);
255735c4bbdfSmrg        }
255805b261ecSmrg    }
255905b261ecSmrg    return 2;
256005b261ecSmrg}
256105b261ecSmrg
256235c4bbdfSmrgstatic Window
256335c4bbdfSmrgFindChildForEvent(SpritePtr pSprite, WindowPtr event)
25646747b715Smrg{
256535c4bbdfSmrg    WindowPtr w = DeepestSpriteWin(pSprite);
25666747b715Smrg    Window child = None;
25676747b715Smrg
25686747b715Smrg    /* If the search ends up past the root should the child field be
25696747b715Smrg       set to none or should the value in the argument be passed
25706747b715Smrg       through. It probably doesn't matter since everyone calls
25716747b715Smrg       this function with child == None anyway. */
257235c4bbdfSmrg    while (w) {
25736747b715Smrg        /* If the source window is same as event window, child should be
25746747b715Smrg           none.  Don't bother going all all the way back to the root. */
25756747b715Smrg
257635c4bbdfSmrg        if (w == event) {
25776747b715Smrg            child = None;
25786747b715Smrg            break;
25796747b715Smrg        }
25806747b715Smrg
258135c4bbdfSmrg        if (w->parent == event) {
25826747b715Smrg            child = w->drawable.id;
25836747b715Smrg            break;
25846747b715Smrg        }
25856747b715Smrg        w = w->parent;
25866747b715Smrg    }
25876747b715Smrg    return child;
25886747b715Smrg}
25896747b715Smrg
25905a112b11Smrgstatic void
25915a112b11SmrgFixUpXI2DeviceEventFromWindow(SpritePtr pSprite, int evtype,
25925a112b11Smrg                              xXIDeviceEvent *event, WindowPtr pWin, Window child)
25935a112b11Smrg{
25945a112b11Smrg    event->root = RootWindow(pSprite)->drawable.id;
25955a112b11Smrg    event->event = pWin->drawable.id;
25965a112b11Smrg
25975a112b11Smrg    if (evtype == XI_TouchOwnership) {
25985a112b11Smrg        event->child = child;
25995a112b11Smrg        return;
26005a112b11Smrg    }
26015a112b11Smrg
26025a112b11Smrg    if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
26035a112b11Smrg        event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x);
26045a112b11Smrg        event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y);
26055a112b11Smrg        event->child = child;
26065a112b11Smrg    }
26075a112b11Smrg    else {
26085a112b11Smrg        event->event_x = 0;
26095a112b11Smrg        event->event_y = 0;
26105a112b11Smrg        event->child = None;
26115a112b11Smrg    }
26125a112b11Smrg
26135a112b11Smrg    if (event->evtype == XI_Enter || event->evtype == XI_Leave ||
26145a112b11Smrg        event->evtype == XI_FocusIn || event->evtype == XI_FocusOut)
26155a112b11Smrg        ((xXIEnterEvent *) event)->same_screen =
26165a112b11Smrg            (pSprite->hot.pScreen == pWin->drawable.pScreen);
26175a112b11Smrg}
26185a112b11Smrg
26195a112b11Smrgstatic void
26205a112b11SmrgFixUpXI2PinchEventFromWindow(SpritePtr pSprite, xXIGesturePinchEvent *event,
26215a112b11Smrg                             WindowPtr pWin, Window child)
26225a112b11Smrg{
26235a112b11Smrg    event->root = RootWindow(pSprite)->drawable.id;
26245a112b11Smrg    event->event = pWin->drawable.id;
26255a112b11Smrg
26265a112b11Smrg    if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
26275a112b11Smrg        event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x);
26285a112b11Smrg        event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y);
26295a112b11Smrg        event->child = child;
26305a112b11Smrg    }
26315a112b11Smrg    else {
26325a112b11Smrg        event->event_x = 0;
26335a112b11Smrg        event->event_y = 0;
26345a112b11Smrg        event->child = None;
26355a112b11Smrg    }
26365a112b11Smrg}
26375a112b11Smrg
26385a112b11Smrgstatic void
26395a112b11SmrgFixUpXI2SwipeEventFromWindow(SpritePtr pSprite, xXIGestureSwipeEvent *event,
26405a112b11Smrg                             WindowPtr pWin, Window child)
26415a112b11Smrg{
26425a112b11Smrg    event->root = RootWindow(pSprite)->drawable.id;
26435a112b11Smrg    event->event = pWin->drawable.id;
26445a112b11Smrg
26455a112b11Smrg    if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
26465a112b11Smrg        event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x);
26475a112b11Smrg        event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y);
26485a112b11Smrg        event->child = child;
26495a112b11Smrg    }
26505a112b11Smrg    else {
26515a112b11Smrg        event->event_x = 0;
26525a112b11Smrg        event->event_y = 0;
26535a112b11Smrg        event->child = None;
26545a112b11Smrg    }
26555a112b11Smrg}
26565a112b11Smrg
265705b261ecSmrg/**
265805b261ecSmrg * Adjust event fields to comply with the window properties.
265905b261ecSmrg *
266005b261ecSmrg * @param xE Event to be modified in place
266105b261ecSmrg * @param pWin The window to get the information from.
266205b261ecSmrg * @param child Child window setting for event (if applicable)
266305b261ecSmrg * @param calcChild If True, calculate the child window.
266405b261ecSmrg */
26656747b715Smrgvoid
266635c4bbdfSmrgFixUpEventFromWindow(SpritePtr pSprite,
266735c4bbdfSmrg                     xEvent *xE, WindowPtr pWin, Window child, Bool calcChild)
266805b261ecSmrg{
266935c4bbdfSmrg    int evtype;
267035c4bbdfSmrg
267105b261ecSmrg    if (calcChild)
26729ace9065Smrg        child = FindChildForEvent(pSprite, pWin);
26736747b715Smrg
267435c4bbdfSmrg    if ((evtype = xi2_get_type(xE))) {
267535c4bbdfSmrg        switch (evtype) {
267635c4bbdfSmrg        case XI_RawKeyPress:
267735c4bbdfSmrg        case XI_RawKeyRelease:
267835c4bbdfSmrg        case XI_RawButtonPress:
267935c4bbdfSmrg        case XI_RawButtonRelease:
268035c4bbdfSmrg        case XI_RawMotion:
268135c4bbdfSmrg        case XI_RawTouchBegin:
268235c4bbdfSmrg        case XI_RawTouchUpdate:
268335c4bbdfSmrg        case XI_RawTouchEnd:
268435c4bbdfSmrg        case XI_DeviceChanged:
268535c4bbdfSmrg        case XI_HierarchyChanged:
268635c4bbdfSmrg        case XI_PropertyEvent:
268735c4bbdfSmrg        case XI_BarrierHit:
268835c4bbdfSmrg        case XI_BarrierLeave:
26896747b715Smrg            return;
26905a112b11Smrg        case XI_GesturePinchBegin:
26915a112b11Smrg        case XI_GesturePinchUpdate:
26925a112b11Smrg        case XI_GesturePinchEnd:
26935a112b11Smrg            FixUpXI2PinchEventFromWindow(pSprite,
26945a112b11Smrg                                         (xXIGesturePinchEvent*) xE, pWin, child);
26955a112b11Smrg            break;
26965a112b11Smrg        case XI_GestureSwipeBegin:
26975a112b11Smrg        case XI_GestureSwipeUpdate:
26985a112b11Smrg        case XI_GestureSwipeEnd:
26995a112b11Smrg            FixUpXI2SwipeEventFromWindow(pSprite,
27005a112b11Smrg                                         (xXIGestureSwipeEvent*) xE, pWin, child);
27015a112b11Smrg            break;
270235c4bbdfSmrg        default:
27035a112b11Smrg            FixUpXI2DeviceEventFromWindow(pSprite, evtype,
27045a112b11Smrg                                          (xXIDeviceEvent*) xE, pWin, child);
270535c4bbdfSmrg            break;
270635c4bbdfSmrg        }
270735c4bbdfSmrg    }
270835c4bbdfSmrg    else {
27099ace9065Smrg        XE_KBPTR.root = RootWindow(pSprite)->drawable.id;
27106747b715Smrg        XE_KBPTR.event = pWin->drawable.id;
271135c4bbdfSmrg        if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
27126747b715Smrg            XE_KBPTR.sameScreen = xTrue;
27136747b715Smrg            XE_KBPTR.child = child;
271435c4bbdfSmrg            XE_KBPTR.eventX = XE_KBPTR.rootX - pWin->drawable.x;
271535c4bbdfSmrg            XE_KBPTR.eventY = XE_KBPTR.rootY - pWin->drawable.y;
27166747b715Smrg        }
271735c4bbdfSmrg        else {
27186747b715Smrg            XE_KBPTR.sameScreen = xFalse;
27196747b715Smrg            XE_KBPTR.child = None;
27206747b715Smrg            XE_KBPTR.eventX = 0;
27216747b715Smrg            XE_KBPTR.eventY = 0;
27226747b715Smrg        }
272305b261ecSmrg    }
272405b261ecSmrg}
272505b261ecSmrg
27266747b715Smrg/**
27276747b715Smrg * Check if a given event is deliverable at all on a given window.
27286747b715Smrg *
27296747b715Smrg * This function only checks if any client wants it, not for a specific
27306747b715Smrg * client.
27316747b715Smrg *
27326747b715Smrg * @param[in] dev The device this event is being sent for.
273335c4bbdfSmrg * @param[in] evtype The event type of the event that is to be sent.
27346747b715Smrg * @param[in] win The current event window.
27356747b715Smrg *
273635c4bbdfSmrg * @return Bitmask of ::EVENT_XI2_MASK, ::EVENT_XI1_MASK, ::EVENT_CORE_MASK, and
273735c4bbdfSmrg *         ::EVENT_DONT_PROPAGATE_MASK.
27386747b715Smrg */
27399ace9065Smrgint
274035c4bbdfSmrgEventIsDeliverable(DeviceIntPtr dev, int evtype, WindowPtr win)
27416747b715Smrg{
27426747b715Smrg    int rc = 0;
27436747b715Smrg    int filter = 0;
27446747b715Smrg    int type;
27456747b715Smrg    OtherInputMasks *inputMasks = wOtherInputMasks(win);
274635c4bbdfSmrg
274735c4bbdfSmrg    if ((type = GetXI2Type(evtype)) != 0) {
274835c4bbdfSmrg        if (inputMasks && xi2mask_isset(inputMasks->xi2mask, dev, type))
274935c4bbdfSmrg            rc |= EVENT_XI2_MASK;
275035c4bbdfSmrg    }
275135c4bbdfSmrg
275235c4bbdfSmrg    if ((type = GetXIType(evtype)) != 0) {
275335c4bbdfSmrg        filter = event_get_filter_from_type(dev, type);
275435c4bbdfSmrg
275535c4bbdfSmrg        /* Check for XI mask */
275635c4bbdfSmrg        if (inputMasks &&
275735c4bbdfSmrg            (inputMasks->deliverableEvents[dev->id] & filter) &&
275835c4bbdfSmrg            (inputMasks->inputEvents[dev->id] & filter))
275935c4bbdfSmrg            rc |= EVENT_XI1_MASK;
276035c4bbdfSmrg
276135c4bbdfSmrg        /* Check for XI DontPropagate mask */
276235c4bbdfSmrg        if (inputMasks && (inputMasks->dontPropagateMask[dev->id] & filter))
276335c4bbdfSmrg            rc |= EVENT_DONT_PROPAGATE_MASK;
276435c4bbdfSmrg
276535c4bbdfSmrg    }
276635c4bbdfSmrg
276735c4bbdfSmrg    if ((type = GetCoreType(evtype)) != 0) {
276835c4bbdfSmrg        filter = event_get_filter_from_type(dev, type);
276935c4bbdfSmrg
277035c4bbdfSmrg        /* Check for core mask */
277135c4bbdfSmrg        if ((win->deliverableEvents & filter) &&
277235c4bbdfSmrg            ((wOtherEventMasks(win) | win->eventMask) & filter))
277335c4bbdfSmrg            rc |= EVENT_CORE_MASK;
277435c4bbdfSmrg
277535c4bbdfSmrg        /* Check for core DontPropagate mask */
277635c4bbdfSmrg        if (filter & wDontPropagateMask(win))
277735c4bbdfSmrg            rc |= EVENT_DONT_PROPAGATE_MASK;
277835c4bbdfSmrg    }
27796747b715Smrg
27806747b715Smrg    return rc;
27816747b715Smrg}
27826747b715Smrg
278335c4bbdfSmrgstatic int
278435c4bbdfSmrgDeliverEvent(DeviceIntPtr dev, xEvent *xE, int count,
278535c4bbdfSmrg             WindowPtr win, Window child, GrabPtr grab)
278635c4bbdfSmrg{
278735c4bbdfSmrg    SpritePtr pSprite = dev->spriteInfo->sprite;
278835c4bbdfSmrg    Mask filter;
278935c4bbdfSmrg    int deliveries = 0;
279035c4bbdfSmrg
279135c4bbdfSmrg    if (XaceHook(XACE_SEND_ACCESS, NULL, dev, win, xE, count) == Success) {
279235c4bbdfSmrg        filter = GetEventFilter(dev, xE);
279335c4bbdfSmrg        FixUpEventFromWindow(pSprite, xE, win, child, FALSE);
279435c4bbdfSmrg        deliveries = DeliverEventsToWindow(dev, win, xE, count, filter, grab);
279535c4bbdfSmrg    }
279635c4bbdfSmrg
279735c4bbdfSmrg    return deliveries;
279835c4bbdfSmrg}
279935c4bbdfSmrg
280035c4bbdfSmrgstatic int
280135c4bbdfSmrgDeliverOneEvent(InternalEvent *event, DeviceIntPtr dev, enum InputLevel level,
280235c4bbdfSmrg                WindowPtr win, Window child, GrabPtr grab)
280335c4bbdfSmrg{
280435c4bbdfSmrg    xEvent *xE = NULL;
280535c4bbdfSmrg    int count = 0;
280635c4bbdfSmrg    int deliveries = 0;
280735c4bbdfSmrg    int rc;
280835c4bbdfSmrg
280935c4bbdfSmrg    switch (level) {
281035c4bbdfSmrg    case XI2:
281135c4bbdfSmrg        rc = EventToXI2(event, &xE);
281235c4bbdfSmrg        count = 1;
281335c4bbdfSmrg        break;
281435c4bbdfSmrg    case XI:
281535c4bbdfSmrg        rc = EventToXI(event, &xE, &count);
281635c4bbdfSmrg        break;
281735c4bbdfSmrg    case CORE:
281835c4bbdfSmrg        rc = EventToCore(event, &xE, &count);
281935c4bbdfSmrg        break;
282035c4bbdfSmrg    default:
282135c4bbdfSmrg        rc = BadImplementation;
282235c4bbdfSmrg        break;
282335c4bbdfSmrg    }
282435c4bbdfSmrg
282535c4bbdfSmrg    if (rc == Success) {
282635c4bbdfSmrg        deliveries = DeliverEvent(dev, xE, count, win, child, grab);
282735c4bbdfSmrg        free(xE);
282835c4bbdfSmrg    }
282935c4bbdfSmrg    else
283035c4bbdfSmrg        BUG_WARN_MSG(rc != BadMatch,
283135c4bbdfSmrg                     "%s: conversion to level %d failed with rc %d\n",
283235c4bbdfSmrg                     dev->name, level, rc);
283335c4bbdfSmrg    return deliveries;
283435c4bbdfSmrg}
283535c4bbdfSmrg
28366747b715Smrg/**
28376747b715Smrg * Deliver events caused by input devices.
28386747b715Smrg *
28394642e01fSmrg * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is
28404642e01fSmrg * called directly from the processInputProc.
28414642e01fSmrg * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call
28424642e01fSmrg * DeliverDeviceEvents.
28434642e01fSmrg * For focused events, DeliverFocusedEvent is called first, and _may_ call
28444642e01fSmrg * DeliverDeviceEvents.
284505b261ecSmrg *
284605b261ecSmrg * @param pWin Window to deliver event to.
28476747b715Smrg * @param event The events to deliver, not yet in wire format.
284805b261ecSmrg * @param grab Possible grab on a device.
284905b261ecSmrg * @param stopAt Don't recurse up to the root window.
285005b261ecSmrg * @param dev The device that is responsible for the event.
285105b261ecSmrg *
28524642e01fSmrg * @see DeliverGrabbedEvent
28534642e01fSmrg * @see DeliverFocusedEvent
285405b261ecSmrg */
285505b261ecSmrgint
28566747b715SmrgDeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
28576747b715Smrg                    WindowPtr stopAt, DeviceIntPtr dev)
285805b261ecSmrg{
285905b261ecSmrg    Window child = None;
286005b261ecSmrg    int deliveries = 0;
286135c4bbdfSmrg    int mask;
28624642e01fSmrg
286335c4bbdfSmrg    verify_internal_event(event);
28644642e01fSmrg
286535c4bbdfSmrg    while (pWin) {
286635c4bbdfSmrg        if ((mask = EventIsDeliverable(dev, event->any.type, pWin))) {
28676747b715Smrg            /* XI2 events first */
286835c4bbdfSmrg            if (mask & EVENT_XI2_MASK) {
286935c4bbdfSmrg                deliveries =
287035c4bbdfSmrg                    DeliverOneEvent(event, dev, XI2, pWin, child, grab);
287135c4bbdfSmrg                if (deliveries > 0)
287235c4bbdfSmrg                    break;
28734642e01fSmrg            }
28744642e01fSmrg
28756747b715Smrg            /* XI events */
287635c4bbdfSmrg            if (mask & EVENT_XI1_MASK) {
287735c4bbdfSmrg                deliveries = DeliverOneEvent(event, dev, XI, pWin, child, grab);
287835c4bbdfSmrg                if (deliveries > 0)
287935c4bbdfSmrg                    break;
28806747b715Smrg            }
28814642e01fSmrg
28826747b715Smrg            /* Core event */
288335c4bbdfSmrg            if ((mask & EVENT_CORE_MASK) && IsMaster(dev) && dev->coreEvents) {
288435c4bbdfSmrg                deliveries =
288535c4bbdfSmrg                    DeliverOneEvent(event, dev, CORE, pWin, child, grab);
288635c4bbdfSmrg                if (deliveries > 0)
288735c4bbdfSmrg                    break;
28884642e01fSmrg            }
28894642e01fSmrg
289035c4bbdfSmrg        }
289135c4bbdfSmrg
289235c4bbdfSmrg        if ((deliveries < 0) || (pWin == stopAt) ||
289335c4bbdfSmrg            (mask & EVENT_DONT_PROPAGATE_MASK)) {
289435c4bbdfSmrg            deliveries = 0;
289535c4bbdfSmrg            break;
28964642e01fSmrg        }
28974642e01fSmrg
28984642e01fSmrg        child = pWin->drawable.id;
28994642e01fSmrg        pWin = pWin->parent;
290005b261ecSmrg    }
29014642e01fSmrg
29026747b715Smrg    return deliveries;
290305b261ecSmrg}
290405b261ecSmrg
290505b261ecSmrg/**
29065a112b11Smrg * Deliver event to a window and its immediate parent. Used for most window
290705b261ecSmrg * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
29084642e01fSmrg * propagate up the tree or extension events
290905b261ecSmrg *
291005b261ecSmrg * In case of a ReparentNotify event, the event will be delivered to the
291105b261ecSmrg * otherParent as well.
291205b261ecSmrg *
291305b261ecSmrg * @param pWin Window to deliver events to.
291405b261ecSmrg * @param xE Events to deliver.
291505b261ecSmrg * @param count number of events in xE.
291605b261ecSmrg * @param otherParent Used for ReparentNotify events.
291705b261ecSmrg */
29186747b715Smrgint
291935c4bbdfSmrgDeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent)
292005b261ecSmrg{
29216747b715Smrg    DeviceIntRec dummy;
292235c4bbdfSmrg    int deliveries;
292305b261ecSmrg
292405b261ecSmrg#ifdef PANORAMIX
292535c4bbdfSmrg    if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
292635c4bbdfSmrg        return count;
292705b261ecSmrg#endif
292805b261ecSmrg
292905b261ecSmrg    if (!count)
293035c4bbdfSmrg        return 0;
29316747b715Smrg
29326747b715Smrg    dummy.id = XIAllDevices;
293335c4bbdfSmrg
293435c4bbdfSmrg    switch (xE->u.u.type) {
293535c4bbdfSmrg    case DestroyNotify:
293635c4bbdfSmrg    case UnmapNotify:
293735c4bbdfSmrg    case MapNotify:
293835c4bbdfSmrg    case MapRequest:
293935c4bbdfSmrg    case ReparentNotify:
294035c4bbdfSmrg    case ConfigureNotify:
294135c4bbdfSmrg    case ConfigureRequest:
294235c4bbdfSmrg    case GravityNotify:
294335c4bbdfSmrg    case CirculateNotify:
294435c4bbdfSmrg    case CirculateRequest:
294535c4bbdfSmrg        xE->u.destroyNotify.event = pWin->drawable.id;
294635c4bbdfSmrg        break;
294735c4bbdfSmrg    }
294835c4bbdfSmrg
294935c4bbdfSmrg    switch (xE->u.u.type) {
295035c4bbdfSmrg    case DestroyNotify:
295135c4bbdfSmrg    case UnmapNotify:
295235c4bbdfSmrg    case MapNotify:
295335c4bbdfSmrg    case ReparentNotify:
295435c4bbdfSmrg    case ConfigureNotify:
295535c4bbdfSmrg    case GravityNotify:
295635c4bbdfSmrg    case CirculateNotify:
295735c4bbdfSmrg        break;
295835c4bbdfSmrg    default:
295935c4bbdfSmrg    {
296035c4bbdfSmrg        Mask filter;
296135c4bbdfSmrg
296235c4bbdfSmrg        filter = GetEventFilter(&dummy, xE);
296335c4bbdfSmrg        return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab);
296435c4bbdfSmrg    }
296535c4bbdfSmrg    }
296635c4bbdfSmrg
29676747b715Smrg    deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count,
29686747b715Smrg                                       StructureNotifyMask, NullGrab);
296935c4bbdfSmrg    if (pWin->parent) {
297035c4bbdfSmrg        xE->u.destroyNotify.event = pWin->parent->drawable.id;
297135c4bbdfSmrg        deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count,
297235c4bbdfSmrg                                            SubstructureNotifyMask, NullGrab);
297335c4bbdfSmrg        if (xE->u.u.type == ReparentNotify) {
297435c4bbdfSmrg            xE->u.destroyNotify.event = otherParent->drawable.id;
29756747b715Smrg            deliveries += DeliverEventsToWindow(&dummy,
297635c4bbdfSmrg                                                otherParent, xE, count,
297735c4bbdfSmrg                                                SubstructureNotifyMask,
297835c4bbdfSmrg                                                NullGrab);
297935c4bbdfSmrg        }
298005b261ecSmrg    }
298105b261ecSmrg    return deliveries;
298205b261ecSmrg}
298305b261ecSmrg
298435c4bbdfSmrgBool
298505b261ecSmrgPointInBorderSize(WindowPtr pWin, int x, int y)
298605b261ecSmrg{
298705b261ecSmrg    BoxRec box;
298805b261ecSmrg
298935c4bbdfSmrg    if (RegionContainsPoint(&pWin->borderSize, x, y, &box))
299035c4bbdfSmrg        return TRUE;
299105b261ecSmrg
299205b261ecSmrg#ifdef PANORAMIX
299335c4bbdfSmrg    if (!noPanoramiXExtension &&
299435c4bbdfSmrg        XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
299535c4bbdfSmrg        SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
299635c4bbdfSmrg        int i;
299735c4bbdfSmrg
299835c4bbdfSmrg        FOR_NSCREENS_FORWARD_SKIP(i) {
299935c4bbdfSmrg            if (RegionContainsPoint(&pSprite->windows[i]->borderSize,
300035c4bbdfSmrg                                    x + screenInfo.screens[0]->x -
300135c4bbdfSmrg                                    screenInfo.screens[i]->x,
300235c4bbdfSmrg                                    y + screenInfo.screens[0]->y -
300335c4bbdfSmrg                                    screenInfo.screens[i]->y, &box))
300435c4bbdfSmrg                return TRUE;
300535c4bbdfSmrg        }
300605b261ecSmrg    }
300705b261ecSmrg#endif
300805b261ecSmrg    return FALSE;
300905b261ecSmrg}
301005b261ecSmrg
301105b261ecSmrg/**
301205b261ecSmrg * Traversed from the root window to the window at the position x/y. While
301305b261ecSmrg * traversing, it sets up the traversal history in the spriteTrace array.
301405b261ecSmrg * After completing, the spriteTrace history is set in the following way:
301505b261ecSmrg *   spriteTrace[0] ... root window
301605b261ecSmrg *   spriteTrace[1] ... top level window that encloses x/y
301705b261ecSmrg *       ...
301805b261ecSmrg *   spriteTrace[spriteTraceGood - 1] ... window at x/y
301905b261ecSmrg *
302005b261ecSmrg * @returns the window at the given coordinates.
302105b261ecSmrg */
30229ace9065SmrgWindowPtr
30239ace9065SmrgXYToWindow(SpritePtr pSprite, int x, int y)
302405b261ecSmrg{
302535c4bbdfSmrg    ScreenPtr pScreen = RootWindow(pSprite)->drawable.pScreen;
302605b261ecSmrg
302735c4bbdfSmrg    return (*pScreen->XYToWindow)(pScreen, pSprite, x, y);
302805b261ecSmrg}
302905b261ecSmrg
30306747b715Smrg/**
30316747b715Smrg * Ungrab a currently FocusIn grabbed device and grab the device on the
30326747b715Smrg * given window. If the win given is the NoneWin, the device is ungrabbed if
30336747b715Smrg * applicable and FALSE is returned.
30346747b715Smrg *
30356747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise.
30366747b715Smrg */
30376747b715SmrgBOOL
30386747b715SmrgActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
30396747b715Smrg{
30406747b715Smrg    BOOL rc = FALSE;
30415a112b11Smrg    InternalEvent event;
30426747b715Smrg
304335c4bbdfSmrg    if (dev->deviceGrab.grab) {
30449ace9065Smrg        if (!dev->deviceGrab.fromPassiveGrab ||
30457e31ba66Smrg            dev->deviceGrab.grab->type != XI_FocusIn ||
30469ace9065Smrg            dev->deviceGrab.grab->window == win ||
30476747b715Smrg            IsParent(dev->deviceGrab.grab->window, win))
30486747b715Smrg            return FALSE;
30496747b715Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
305035c4bbdfSmrg        (*dev->deviceGrab.DeactivateGrab) (dev);
30516747b715Smrg    }
30526747b715Smrg
30536747b715Smrg    if (win == NoneWin || win == PointerRootWin)
30546747b715Smrg        return FALSE;
30556747b715Smrg
30565a112b11Smrg    event = (InternalEvent) {
30575a112b11Smrg        .device_event.header = ET_Internal,
30585a112b11Smrg        .device_event.type = ET_FocusIn,
30595a112b11Smrg        .device_event.length = sizeof(DeviceEvent),
30605a112b11Smrg        .device_event.time = GetTimeInMillis(),
30615a112b11Smrg        .device_event.deviceid = dev->id,
30625a112b11Smrg        .device_event.sourceid = dev->id,
30635a112b11Smrg        .device_event.detail.button = 0
306435c4bbdfSmrg    };
30655a112b11Smrg    rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE,
306635c4bbdfSmrg                                    TRUE) != NULL);
30676747b715Smrg    if (rc)
30687e31ba66Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
30696747b715Smrg    return rc;
30706747b715Smrg}
30716747b715Smrg
30726747b715Smrg/**
30736747b715Smrg * Ungrab a currently Enter grabbed device and grab the device for the given
30746747b715Smrg * window.
30756747b715Smrg *
30766747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise.
30776747b715Smrg */
30786747b715Smrgstatic BOOL
30796747b715SmrgActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
30806747b715Smrg{
30816747b715Smrg    BOOL rc = FALSE;
30825a112b11Smrg    InternalEvent event;
30836747b715Smrg
308435c4bbdfSmrg    if (dev->deviceGrab.grab) {
30859ace9065Smrg        if (!dev->deviceGrab.fromPassiveGrab ||
30869ace9065Smrg            dev->deviceGrab.grab->type != XI_Enter ||
30879ace9065Smrg            dev->deviceGrab.grab->window == win ||
30886747b715Smrg            IsParent(dev->deviceGrab.grab->window, win))
30896747b715Smrg            return FALSE;
30906747b715Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
309135c4bbdfSmrg        (*dev->deviceGrab.DeactivateGrab) (dev);
309235c4bbdfSmrg    }
309335c4bbdfSmrg
30945a112b11Smrg    event = (InternalEvent) {
30955a112b11Smrg        .device_event.header = ET_Internal,
30965a112b11Smrg        .device_event.type = ET_Enter,
30975a112b11Smrg        .device_event.length = sizeof(DeviceEvent),
30985a112b11Smrg        .device_event.time = GetTimeInMillis(),
30995a112b11Smrg        .device_event.deviceid = dev->id,
31005a112b11Smrg        .device_event.sourceid = dev->id,
31015a112b11Smrg        .device_event.detail.button = 0
310235c4bbdfSmrg    };
31035a112b11Smrg    rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE,
310435c4bbdfSmrg                                    TRUE) != NULL);
31056747b715Smrg    if (rc)
31066747b715Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
31076747b715Smrg    return rc;
31086747b715Smrg}
31096747b715Smrg
311005b261ecSmrg/**
311105b261ecSmrg * Update the sprite coordinates based on the event. Update the cursor
311205b261ecSmrg * position, then update the event with the new coordinates that may have been
311305b261ecSmrg * changed. If the window underneath the sprite has changed, change to new
311405b261ecSmrg * cursor and send enter/leave events.
31154642e01fSmrg *
31164642e01fSmrg * CheckMotion() will not do anything and return FALSE if the event is not a
31174642e01fSmrg * pointer event.
31184642e01fSmrg *
31194642e01fSmrg * @return TRUE if the sprite has moved or FALSE otherwise.
312005b261ecSmrg */
31214642e01fSmrgBool
31226747b715SmrgCheckMotion(DeviceEvent *ev, DeviceIntPtr pDev)
312305b261ecSmrg{
31246747b715Smrg    WindowPtr prevSpriteWin, newSpriteWin;
31254642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
31264642e01fSmrg
312735c4bbdfSmrg    verify_internal_event((InternalEvent *) ev);
312805b261ecSmrg
31296747b715Smrg    prevSpriteWin = pSprite->win;
313005b261ecSmrg
313135c4bbdfSmrg    if (ev && !syncEvents.playingEvents) {
31324642e01fSmrg        /* GetPointerEvents() guarantees that pointer events have the correct
31334642e01fSmrg           rootX/Y set already. */
313435c4bbdfSmrg        switch (ev->type) {
313535c4bbdfSmrg        case ET_ButtonPress:
313635c4bbdfSmrg        case ET_ButtonRelease:
313735c4bbdfSmrg        case ET_Motion:
313835c4bbdfSmrg        case ET_TouchBegin:
313935c4bbdfSmrg        case ET_TouchUpdate:
314035c4bbdfSmrg        case ET_TouchEnd:
314135c4bbdfSmrg            break;
314235c4bbdfSmrg        default:
314335c4bbdfSmrg            /* all other events return FALSE */
314435c4bbdfSmrg            return FALSE;
31454642e01fSmrg        }
31464642e01fSmrg
31476747b715Smrg#ifdef PANORAMIX
314835c4bbdfSmrg        if (!noPanoramiXExtension) {
31496747b715Smrg            /* Motion events entering DIX get translated to Screen 0
31506747b715Smrg               coordinates.  Replayed events have already been
31516747b715Smrg               translated since they've entered DIX before */
31526747b715Smrg            ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
31536747b715Smrg            ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
315435c4bbdfSmrg        }
315535c4bbdfSmrg        else
31566747b715Smrg#endif
31576747b715Smrg        {
315835c4bbdfSmrg            if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen) {
31596747b715Smrg                pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
31609ace9065Smrg                RootWindow(pDev->spriteInfo->sprite) =
31619ace9065Smrg                    pSprite->hot.pScreen->root;
31626747b715Smrg            }
31634642e01fSmrg        }
31646747b715Smrg
31656747b715Smrg        pSprite->hot.x = ev->root_x;
31666747b715Smrg        pSprite->hot.y = ev->root_y;
31674642e01fSmrg        if (pSprite->hot.x < pSprite->physLimits.x1)
31684642e01fSmrg            pSprite->hot.x = pSprite->physLimits.x1;
31694642e01fSmrg        else if (pSprite->hot.x >= pSprite->physLimits.x2)
31704642e01fSmrg            pSprite->hot.x = pSprite->physLimits.x2 - 1;
31714642e01fSmrg        if (pSprite->hot.y < pSprite->physLimits.y1)
31724642e01fSmrg            pSprite->hot.y = pSprite->physLimits.y1;
31734642e01fSmrg        else if (pSprite->hot.y >= pSprite->physLimits.y2)
31744642e01fSmrg            pSprite->hot.y = pSprite->physLimits.y2 - 1;
317535c4bbdfSmrg        if (pSprite->hotShape)
317635c4bbdfSmrg            ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x,
317735c4bbdfSmrg                           &pSprite->hot.y);
317835c4bbdfSmrg        pSprite->hotPhys = pSprite->hot;
31794642e01fSmrg
318035c4bbdfSmrg        if ((pSprite->hotPhys.x != ev->root_x) ||
318135c4bbdfSmrg            (pSprite->hotPhys.y != ev->root_y)) {
31826747b715Smrg#ifdef PANORAMIX
318335c4bbdfSmrg            if (!noPanoramiXExtension) {
318435c4bbdfSmrg                XineramaSetCursorPosition(pDev, pSprite->hotPhys.x,
318535c4bbdfSmrg                                          pSprite->hotPhys.y, FALSE);
318635c4bbdfSmrg            }
318735c4bbdfSmrg            else
31886747b715Smrg#endif
31896747b715Smrg            {
319035c4bbdfSmrg                (*pSprite->hotPhys.pScreen->SetCursorPosition) (pDev,
319135c4bbdfSmrg                                                                pSprite->
319235c4bbdfSmrg                                                                hotPhys.pScreen,
319335c4bbdfSmrg                                                                pSprite->
319435c4bbdfSmrg                                                                hotPhys.x,
319535c4bbdfSmrg                                                                pSprite->
319635c4bbdfSmrg                                                                hotPhys.y,
319735c4bbdfSmrg                                                                FALSE);
31986747b715Smrg            }
319935c4bbdfSmrg        }
32004642e01fSmrg
320135c4bbdfSmrg        ev->root_x = pSprite->hot.x;
320235c4bbdfSmrg        ev->root_y = pSprite->hot.y;
320305b261ecSmrg    }
320405b261ecSmrg
32059ace9065Smrg    newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y);
32066747b715Smrg
320735c4bbdfSmrg    if (newSpriteWin != prevSpriteWin) {
32086747b715Smrg        int sourceid;
320935c4bbdfSmrg
32106747b715Smrg        if (!ev) {
32116747b715Smrg            UpdateCurrentTimeIf();
321235c4bbdfSmrg            sourceid = pDev->id;        /* when from WindowsRestructured */
321335c4bbdfSmrg        }
321435c4bbdfSmrg        else
32156747b715Smrg            sourceid = ev->sourceid;
32166747b715Smrg
321735c4bbdfSmrg        if (prevSpriteWin != NullWindow) {
32186747b715Smrg            if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin))
32196747b715Smrg                DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin,
32206747b715Smrg                                   newSpriteWin, NotifyNormal);
32214642e01fSmrg        }
32226747b715Smrg        /* set pSprite->win after ActivateEnterGrab, otherwise
32236747b715Smrg           sprite window == grab_window and no enter/leave events are
32246747b715Smrg           sent. */
32256747b715Smrg        pSprite->win = newSpriteWin;
32266747b715Smrg        PostNewCursor(pDev);
322705b261ecSmrg        return FALSE;
322805b261ecSmrg    }
322905b261ecSmrg    return TRUE;
323005b261ecSmrg}
323105b261ecSmrg
323205b261ecSmrg/**
323305b261ecSmrg * Windows have restructured, we need to update the sprite position and the
323405b261ecSmrg * sprite's cursor.
323505b261ecSmrg */
32364642e01fSmrgvoid
323705b261ecSmrgWindowsRestructured(void)
323805b261ecSmrg{
32394642e01fSmrg    DeviceIntPtr pDev = inputInfo.devices;
324035c4bbdfSmrg
324135c4bbdfSmrg    while (pDev) {
324235c4bbdfSmrg        if (IsMaster(pDev) || IsFloating(pDev))
3243b1d344b3Smrg            CheckMotion(NULL, pDev);
32444642e01fSmrg        pDev = pDev->next;
32454642e01fSmrg    }
324605b261ecSmrg}
324705b261ecSmrg
324805b261ecSmrg#ifdef PANORAMIX
324905b261ecSmrg/* This was added to support reconfiguration under Xdmx.  The problem is
32506747b715Smrg * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin
325105b261ecSmrg * other than 0,0, the information in the private sprite structure must
325205b261ecSmrg * be updated accordingly, or XYToWindow (and other routines) will not
325305b261ecSmrg * compute correctly. */
325435c4bbdfSmrgvoid
325535c4bbdfSmrgReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
325605b261ecSmrg{
325735c4bbdfSmrg    GrabPtr grab;
32584642e01fSmrg    DeviceIntPtr pDev;
32594642e01fSmrg    SpritePtr pSprite;
326005b261ecSmrg
326135c4bbdfSmrg    if (noPanoramiXExtension)
326235c4bbdfSmrg        return;
326305b261ecSmrg
32644642e01fSmrg    pDev = inputInfo.devices;
326535c4bbdfSmrg    while (pDev) {
326635c4bbdfSmrg        if (DevHasCursor(pDev)) {
32674642e01fSmrg            pSprite = pDev->spriteInfo->sprite;
326835c4bbdfSmrg            pSprite->hot.x -= xoff;
326935c4bbdfSmrg            pSprite->hot.y -= yoff;
32704642e01fSmrg
327135c4bbdfSmrg            pSprite->hotPhys.x -= xoff;
327235c4bbdfSmrg            pSprite->hotPhys.y -= yoff;
32734642e01fSmrg
32744642e01fSmrg            pSprite->hotLimits.x1 -= xoff;
32754642e01fSmrg            pSprite->hotLimits.y1 -= yoff;
32764642e01fSmrg            pSprite->hotLimits.x2 -= xoff;
32774642e01fSmrg            pSprite->hotLimits.y2 -= yoff;
32784642e01fSmrg
32796747b715Smrg            if (RegionNotEmpty(&pSprite->Reg1))
32806747b715Smrg                RegionTranslate(&pSprite->Reg1, xoff, yoff);
32816747b715Smrg            if (RegionNotEmpty(&pSprite->Reg2))
32826747b715Smrg                RegionTranslate(&pSprite->Reg2, xoff, yoff);
32834642e01fSmrg
32844642e01fSmrg            /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
32854642e01fSmrg            if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
32864642e01fSmrg                if (grab->confineTo->drawable.pScreen
328735c4bbdfSmrg                    != pSprite->hotPhys.pScreen)
32884642e01fSmrg                    pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
32894642e01fSmrg                ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
329035c4bbdfSmrg            }
329135c4bbdfSmrg            else
329235c4bbdfSmrg                ConfineCursorToWindow(pDev,
329335c4bbdfSmrg                                      pSprite->hotPhys.pScreen->root,
329435c4bbdfSmrg                                      TRUE, FALSE);
32954642e01fSmrg
32964642e01fSmrg        }
32974642e01fSmrg        pDev = pDev->next;
32984642e01fSmrg    }
32994642e01fSmrg}
33004642e01fSmrg#endif
33014642e01fSmrg
33024642e01fSmrg/**
33034642e01fSmrg * Initialize a sprite for the given device and set it to some sane values. If
33044642e01fSmrg * the device already has a sprite alloc'd, don't realloc but just reset to
33054642e01fSmrg * default values.
33064642e01fSmrg * If a window is supplied, the sprite will be initialized with the window's
33074642e01fSmrg * cursor and positioned in the center of the window's screen. The root window
33084642e01fSmrg * is a good choice to pass in here.
33094642e01fSmrg *
33104642e01fSmrg * It's a good idea to call it only for pointer devices, unless you have a
33114642e01fSmrg * really talented keyboard.
33124642e01fSmrg *
33134642e01fSmrg * @param pDev The device to initialize.
33144642e01fSmrg * @param pWin The window where to generate the sprite in.
33154642e01fSmrg *
33164642e01fSmrg */
33174642e01fSmrgvoid
33184642e01fSmrgInitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
33194642e01fSmrg{
33204642e01fSmrg    SpritePtr pSprite;
33214642e01fSmrg    ScreenPtr pScreen;
33226747b715Smrg    CursorPtr pCursor;
33234642e01fSmrg
332435c4bbdfSmrg    if (!pDev->spriteInfo->sprite) {
33254642e01fSmrg        DeviceIntPtr it;
33264642e01fSmrg
332735c4bbdfSmrg        pDev->spriteInfo->sprite = (SpritePtr) calloc(1, sizeof(SpriteRec));
33284642e01fSmrg        if (!pDev->spriteInfo->sprite)
33294642e01fSmrg            FatalError("InitializeSprite: failed to allocate sprite struct");
33304642e01fSmrg
33314642e01fSmrg        /* We may have paired another device with this device before our
33324642e01fSmrg         * device had a actual sprite. We need to check for this and reset the
33334642e01fSmrg         * sprite field for all paired devices.
33344642e01fSmrg         *
33354642e01fSmrg         * The VCK is always paired with the VCP before the VCP has a sprite.
33364642e01fSmrg         */
333735c4bbdfSmrg        for (it = inputInfo.devices; it; it = it->next) {
33384642e01fSmrg            if (it->spriteInfo->paired == pDev)
33394642e01fSmrg                it->spriteInfo->sprite = pDev->spriteInfo->sprite;
33404642e01fSmrg        }
33414642e01fSmrg        if (inputInfo.keyboard->spriteInfo->paired == pDev)
33424642e01fSmrg            inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite;
33434642e01fSmrg    }
33444642e01fSmrg
33454642e01fSmrg    pSprite = pDev->spriteInfo->sprite;
33464642e01fSmrg    pDev->spriteInfo->spriteOwner = TRUE;
334705b261ecSmrg
334835c4bbdfSmrg    pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr) NULL;
33494642e01fSmrg    pSprite->hot.pScreen = pScreen;
33504642e01fSmrg    pSprite->hotPhys.pScreen = pScreen;
335135c4bbdfSmrg    if (pScreen) {
33524642e01fSmrg        pSprite->hotPhys.x = pScreen->width / 2;
33534642e01fSmrg        pSprite->hotPhys.y = pScreen->height / 2;
33544642e01fSmrg        pSprite->hotLimits.x2 = pScreen->width;
33554642e01fSmrg        pSprite->hotLimits.y2 = pScreen->height;
33564642e01fSmrg    }
33574642e01fSmrg
33584642e01fSmrg    pSprite->hot = pSprite->hotPhys;
33594642e01fSmrg    pSprite->win = pWin;
33604642e01fSmrg
336135c4bbdfSmrg    if (pWin) {
336235c4bbdfSmrg        pCursor = wCursor(pWin);
336335c4bbdfSmrg        pSprite->spriteTrace = (WindowPtr *) calloc(1, 32 * sizeof(WindowPtr));
336435c4bbdfSmrg        if (!pSprite->spriteTrace)
336535c4bbdfSmrg            FatalError("Failed to allocate spriteTrace");
336635c4bbdfSmrg        pSprite->spriteTraceSize = 32;
33674642e01fSmrg
336835c4bbdfSmrg        RootWindow(pDev->spriteInfo->sprite) = pWin;
336935c4bbdfSmrg        pSprite->spriteTraceGood = 1;
33704642e01fSmrg
337135c4bbdfSmrg        pSprite->pEnqueueScreen = pScreen;
337235c4bbdfSmrg        pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
33734642e01fSmrg
337435c4bbdfSmrg    }
337535c4bbdfSmrg    else {
33766747b715Smrg        pCursor = NullCursor;
337735c4bbdfSmrg        pSprite->spriteTrace = NULL;
337835c4bbdfSmrg        pSprite->spriteTraceSize = 0;
337935c4bbdfSmrg        pSprite->spriteTraceGood = 0;
338035c4bbdfSmrg        pSprite->pEnqueueScreen = screenInfo.screens[0];
338135c4bbdfSmrg        pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
338235c4bbdfSmrg    }
338335c4bbdfSmrg    pCursor = RefCursor(pCursor);
33846747b715Smrg    if (pSprite->current)
338535c4bbdfSmrg        FreeCursor(pSprite->current, None);
33866747b715Smrg    pSprite->current = pCursor;
33874642e01fSmrg
338835c4bbdfSmrg    if (pScreen) {
338935c4bbdfSmrg        (*pScreen->RealizeCursor) (pDev, pScreen, pSprite->current);
339035c4bbdfSmrg        (*pScreen->CursorLimits) (pDev, pScreen, pSprite->current,
339135c4bbdfSmrg                                  &pSprite->hotLimits, &pSprite->physLimits);
33924642e01fSmrg        pSprite->confined = FALSE;
33934642e01fSmrg
339435c4bbdfSmrg        (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
33954642e01fSmrg        (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
339635c4bbdfSmrg                                       pSprite->hot.y, FALSE);
33974642e01fSmrg        (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
33984642e01fSmrg    }
339905b261ecSmrg#ifdef PANORAMIX
340035c4bbdfSmrg    if (!noPanoramiXExtension) {
34016747b715Smrg        pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
34026747b715Smrg        pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
340335c4bbdfSmrg        pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
34046747b715Smrg        pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
34054642e01fSmrg        pSprite->physLimits = pSprite->hotLimits;
34064642e01fSmrg        pSprite->confineWin = NullWindow;
34074642e01fSmrg        pSprite->hotShape = NullRegion;
34084642e01fSmrg        pSprite->screen = pScreen;
34094642e01fSmrg        /* gotta UNINIT these someplace */
34106747b715Smrg        RegionNull(&pSprite->Reg1);
34116747b715Smrg        RegionNull(&pSprite->Reg2);
34124642e01fSmrg    }
341305b261ecSmrg#endif
34144642e01fSmrg}
34154642e01fSmrg
341635c4bbdfSmrgvoid FreeSprite(DeviceIntPtr dev)
341735c4bbdfSmrg{
341835c4bbdfSmrg    if (DevHasCursor(dev) && dev->spriteInfo->sprite) {
341935c4bbdfSmrg        if (dev->spriteInfo->sprite->current)
342035c4bbdfSmrg            FreeCursor(dev->spriteInfo->sprite->current, None);
342135c4bbdfSmrg        free(dev->spriteInfo->sprite->spriteTrace);
342235c4bbdfSmrg        free(dev->spriteInfo->sprite);
342335c4bbdfSmrg    }
342435c4bbdfSmrg    dev->spriteInfo->sprite = NULL;
342535c4bbdfSmrg}
342635c4bbdfSmrg
342735c4bbdfSmrg
34284642e01fSmrg/**
34294642e01fSmrg * Update the mouse sprite info when the server switches from a pScreen to another.
34304642e01fSmrg * Otherwise, the pScreen of the mouse sprite is never updated when we switch
34314642e01fSmrg * from a pScreen to another. Never updating the pScreen of the mouse sprite
34324642e01fSmrg * implies that windows that are in pScreen whose pScreen->myNum >0 will never
34334642e01fSmrg * get pointer events. This is  because in CheckMotion(), sprite.hotPhys.pScreen
34344642e01fSmrg * always points to the first pScreen it has been set by
34354642e01fSmrg * DefineInitialRootWindow().
34364642e01fSmrg *
34374642e01fSmrg * Calling this function is useful for use cases where the server
34384642e01fSmrg * has more than one pScreen.
34394642e01fSmrg * This function is similar to DefineInitialRootWindow() but it does not
34404642e01fSmrg * reset the mouse pointer position.
34414642e01fSmrg * @param win must be the new pScreen we are switching to.
34424642e01fSmrg */
34434642e01fSmrgvoid
34444642e01fSmrgUpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
34454642e01fSmrg{
34464642e01fSmrg    SpritePtr pSprite = NULL;
34474642e01fSmrg    WindowPtr win = NULL;
34486747b715Smrg    CursorPtr pCursor;
344935c4bbdfSmrg
34504642e01fSmrg    if (!pScreen)
345135c4bbdfSmrg        return;
34524642e01fSmrg
34534642e01fSmrg    if (!pDev->spriteInfo->sprite)
34544642e01fSmrg        return;
34554642e01fSmrg
34564642e01fSmrg    pSprite = pDev->spriteInfo->sprite;
34574642e01fSmrg
34586747b715Smrg    win = pScreen->root;
34594642e01fSmrg
34604642e01fSmrg    pSprite->hotPhys.pScreen = pScreen;
34614642e01fSmrg    pSprite->hot = pSprite->hotPhys;
34624642e01fSmrg    pSprite->hotLimits.x2 = pScreen->width;
34634642e01fSmrg    pSprite->hotLimits.y2 = pScreen->height;
34644642e01fSmrg    pSprite->win = win;
346535c4bbdfSmrg    pCursor = RefCursor(wCursor(win));
34666747b715Smrg    if (pSprite->current)
346735c4bbdfSmrg        FreeCursor(pSprite->current, 0);
34686747b715Smrg    pSprite->current = pCursor;
34694642e01fSmrg    pSprite->spriteTraceGood = 1;
34704642e01fSmrg    pSprite->spriteTrace[0] = win;
34714642e01fSmrg    (*pScreen->CursorLimits) (pDev,
34724642e01fSmrg                              pScreen,
34734642e01fSmrg                              pSprite->current,
347435c4bbdfSmrg                              &pSprite->hotLimits, &pSprite->physLimits);
34754642e01fSmrg    pSprite->confined = FALSE;
34764642e01fSmrg    (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
34774642e01fSmrg    (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
34784642e01fSmrg
34794642e01fSmrg#ifdef PANORAMIX
348035c4bbdfSmrg    if (!noPanoramiXExtension) {
34816747b715Smrg        pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
34826747b715Smrg        pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
348335c4bbdfSmrg        pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
34846747b715Smrg        pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
34854642e01fSmrg        pSprite->physLimits = pSprite->hotLimits;
34864642e01fSmrg        pSprite->screen = pScreen;
348705b261ecSmrg    }
348805b261ecSmrg#endif
348905b261ecSmrg}
349005b261ecSmrg
349105b261ecSmrg/*
349205b261ecSmrg * This does not take any shortcuts, and even ignores its argument, since
349305b261ecSmrg * it does not happen very often, and one has to walk up the tree since
349405b261ecSmrg * this might be a newly instantiated cursor for an intermediate window
349505b261ecSmrg * between the one the pointer is in and the one that the last cursor was
349605b261ecSmrg * instantiated from.
349705b261ecSmrg */
349805b261ecSmrgvoid
349905b261ecSmrgWindowHasNewCursor(WindowPtr pWin)
350005b261ecSmrg{
35014642e01fSmrg    DeviceIntPtr pDev;
35024642e01fSmrg
350335c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
35044642e01fSmrg        if (DevHasCursor(pDev))
35054642e01fSmrg            PostNewCursor(pDev);
350605b261ecSmrg}
350705b261ecSmrg
35086747b715Smrgvoid
35094642e01fSmrgNewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
351005b261ecSmrg{
351135c4bbdfSmrg    DeviceIntPtr ptr;
351235c4bbdfSmrg    SpritePtr pSprite;
351335c4bbdfSmrg
351435c4bbdfSmrg    ptr =
351535c4bbdfSmrg        IsFloating(pDev) ? pDev :
351635c4bbdfSmrg        GetXTestDevice(GetMaster(pDev, MASTER_POINTER));
351735c4bbdfSmrg    pSprite = ptr->spriteInfo->sprite;
35184642e01fSmrg
35194642e01fSmrg    pSprite->hotPhys.x = x;
35204642e01fSmrg    pSprite->hotPhys.y = y;
352105b261ecSmrg#ifdef PANORAMIX
352235c4bbdfSmrg    if (!noPanoramiXExtension) {
352335c4bbdfSmrg        pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x;
352435c4bbdfSmrg        pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y;
352535c4bbdfSmrg        if (newScreen != pSprite->screen) {
352635c4bbdfSmrg            pSprite->screen = newScreen;
352735c4bbdfSmrg            /* Make sure we tell the DDX to update its copy of the screen */
352835c4bbdfSmrg            if (pSprite->confineWin)
352935c4bbdfSmrg                XineramaConfineCursorToWindow(ptr, pSprite->confineWin, TRUE);
353035c4bbdfSmrg            else
353135c4bbdfSmrg                XineramaConfineCursorToWindow(ptr, screenInfo.screens[0]->root,
353235c4bbdfSmrg                                              TRUE);
353335c4bbdfSmrg            /* if the pointer wasn't confined, the DDX won't get
353435c4bbdfSmrg               told of the pointer warp so we reposition it here */
353535c4bbdfSmrg            if (!syncEvents.playingEvents)
353635c4bbdfSmrg                (*pSprite->screen->SetCursorPosition) (ptr,
353735c4bbdfSmrg                                                       pSprite->screen,
353835c4bbdfSmrg                                                       pSprite->hotPhys.x +
353935c4bbdfSmrg                                                       screenInfo.screens[0]->
354035c4bbdfSmrg                                                       x - pSprite->screen->x,
354135c4bbdfSmrg                                                       pSprite->hotPhys.y +
354235c4bbdfSmrg                                                       screenInfo.screens[0]->
354335c4bbdfSmrg                                                       y - pSprite->screen->y,
354435c4bbdfSmrg                                                       FALSE);
354535c4bbdfSmrg        }
354635c4bbdfSmrg    }
354735c4bbdfSmrg    else
354805b261ecSmrg#endif
35494642e01fSmrg    if (newScreen != pSprite->hotPhys.pScreen)
355035c4bbdfSmrg        ConfineCursorToWindow(ptr, newScreen->root, TRUE, FALSE);
355105b261ecSmrg}
355205b261ecSmrg
355305b261ecSmrg#ifdef PANORAMIX
355405b261ecSmrg
355505b261ecSmrgstatic Bool
355635c4bbdfSmrgXineramaPointInWindowIsVisible(WindowPtr pWin, int x, int y)
355705b261ecSmrg{
355805b261ecSmrg    BoxRec box;
355905b261ecSmrg    int i, xoff, yoff;
356005b261ecSmrg
356135c4bbdfSmrg    if (!pWin->realized)
356235c4bbdfSmrg        return FALSE;
356305b261ecSmrg
35646747b715Smrg    if (RegionContainsPoint(&pWin->borderClip, x, y, &box))
356505b261ecSmrg        return TRUE;
356605b261ecSmrg
356735c4bbdfSmrg    if (!XineramaSetWindowPntrs(inputInfo.pointer, pWin))
356835c4bbdfSmrg         return FALSE;
35694642e01fSmrg
35706747b715Smrg    xoff = x + screenInfo.screens[0]->x;
35716747b715Smrg    yoff = y + screenInfo.screens[0]->y;
357205b261ecSmrg
357335c4bbdfSmrg    FOR_NSCREENS_FORWARD_SKIP(i) {
357435c4bbdfSmrg        pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
357535c4bbdfSmrg
357635c4bbdfSmrg        x = xoff - screenInfo.screens[i]->x;
357735c4bbdfSmrg        y = yoff - screenInfo.screens[i]->y;
357805b261ecSmrg
357935c4bbdfSmrg        if (RegionContainsPoint(&pWin->borderClip, x, y, &box)
358035c4bbdfSmrg            && (!wInputShape(pWin) ||
358135c4bbdfSmrg                RegionContainsPoint(wInputShape(pWin),
358235c4bbdfSmrg                                    x - pWin->drawable.x,
358335c4bbdfSmrg                                    y - pWin->drawable.y, &box)))
358405b261ecSmrg            return TRUE;
358505b261ecSmrg
358605b261ecSmrg    }
358705b261ecSmrg
358805b261ecSmrg    return FALSE;
358905b261ecSmrg}
359005b261ecSmrg
359105b261ecSmrgstatic int
359205b261ecSmrgXineramaWarpPointer(ClientPtr client)
359305b261ecSmrg{
359435c4bbdfSmrg    WindowPtr dest = NULL;
359535c4bbdfSmrg    int x, y, rc;
359635c4bbdfSmrg    SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
359705b261ecSmrg
359805b261ecSmrg    REQUEST(xWarpPointerReq);
359905b261ecSmrg
360005b261ecSmrg    if (stuff->dstWid != None) {
360135c4bbdfSmrg        rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
360235c4bbdfSmrg        if (rc != Success)
360335c4bbdfSmrg            return rc;
360405b261ecSmrg    }
36054642e01fSmrg    x = pSprite->hotPhys.x;
36064642e01fSmrg    y = pSprite->hotPhys.y;
360705b261ecSmrg
360835c4bbdfSmrg    if (stuff->srcWid != None) {
360935c4bbdfSmrg        int winX, winY;
361035c4bbdfSmrg        XID winID = stuff->srcWid;
361105b261ecSmrg        WindowPtr source;
36124642e01fSmrg
361335c4bbdfSmrg        rc = dixLookupWindow(&source, winID, client, DixReadAccess);
361435c4bbdfSmrg        if (rc != Success)
361535c4bbdfSmrg            return rc;
361635c4bbdfSmrg
361735c4bbdfSmrg        winX = source->drawable.x;
361835c4bbdfSmrg        winY = source->drawable.y;
361935c4bbdfSmrg        if (source == screenInfo.screens[0]->root) {
362035c4bbdfSmrg            winX -= screenInfo.screens[0]->x;
362135c4bbdfSmrg            winY -= screenInfo.screens[0]->y;
362235c4bbdfSmrg        }
362335c4bbdfSmrg        if (x < winX + stuff->srcX ||
362435c4bbdfSmrg            y < winY + stuff->srcY ||
362535c4bbdfSmrg            (stuff->srcWidth != 0 &&
362635c4bbdfSmrg             winX + stuff->srcX + (int) stuff->srcWidth < x) ||
362735c4bbdfSmrg            (stuff->srcHeight != 0 &&
362835c4bbdfSmrg             winY + stuff->srcY + (int) stuff->srcHeight < y) ||
362935c4bbdfSmrg            !XineramaPointInWindowIsVisible(source, x, y))
363035c4bbdfSmrg            return Success;
363105b261ecSmrg    }
363205b261ecSmrg    if (dest) {
363335c4bbdfSmrg        x = dest->drawable.x;
363435c4bbdfSmrg        y = dest->drawable.y;
363535c4bbdfSmrg        if (dest == screenInfo.screens[0]->root) {
363635c4bbdfSmrg            x -= screenInfo.screens[0]->x;
363735c4bbdfSmrg            y -= screenInfo.screens[0]->y;
363835c4bbdfSmrg        }
36394642e01fSmrg    }
364005b261ecSmrg
364105b261ecSmrg    x += stuff->dstX;
364205b261ecSmrg    y += stuff->dstY;
364305b261ecSmrg
36444642e01fSmrg    if (x < pSprite->physLimits.x1)
364535c4bbdfSmrg        x = pSprite->physLimits.x1;
36464642e01fSmrg    else if (x >= pSprite->physLimits.x2)
364735c4bbdfSmrg        x = pSprite->physLimits.x2 - 1;
36484642e01fSmrg    if (y < pSprite->physLimits.y1)
364935c4bbdfSmrg        y = pSprite->physLimits.y1;
36504642e01fSmrg    else if (y >= pSprite->physLimits.y2)
365135c4bbdfSmrg        y = pSprite->physLimits.y2 - 1;
36524642e01fSmrg    if (pSprite->hotShape)
365335c4bbdfSmrg        ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
365405b261ecSmrg
36554642e01fSmrg    XineramaSetCursorPosition(PickPointer(client), x, y, TRUE);
365605b261ecSmrg
365705b261ecSmrg    return Success;
365805b261ecSmrg}
365905b261ecSmrg
366005b261ecSmrg#endif
366105b261ecSmrg
366205b261ecSmrg/**
366305b261ecSmrg * Server-side protocol handling for WarpPointer request.
366405b261ecSmrg * Warps the cursor position to the coordinates given in the request.
366505b261ecSmrg */
366605b261ecSmrgint
366705b261ecSmrgProcWarpPointer(ClientPtr client)
366805b261ecSmrg{
366935c4bbdfSmrg    WindowPtr dest = NULL;
367035c4bbdfSmrg    int x, y, rc;
367135c4bbdfSmrg    ScreenPtr newScreen;
36726747b715Smrg    DeviceIntPtr dev, tmp;
367335c4bbdfSmrg    SpritePtr pSprite;
367405b261ecSmrg
367505b261ecSmrg    REQUEST(xWarpPointerReq);
367605b261ecSmrg    REQUEST_SIZE_MATCH(xWarpPointerReq);
367705b261ecSmrg
36786747b715Smrg    dev = PickPointer(client);
36796747b715Smrg
36806747b715Smrg    for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
368135c4bbdfSmrg        if (GetMaster(tmp, MASTER_ATTACHED) == dev) {
368235c4bbdfSmrg            rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
368335c4bbdfSmrg            if (rc != Success)
368435c4bbdfSmrg                return rc;
368535c4bbdfSmrg        }
36864642e01fSmrg    }
36874642e01fSmrg
368835c4bbdfSmrg    if (dev->lastSlave)
368935c4bbdfSmrg        dev = dev->lastSlave;
36904642e01fSmrg    pSprite = dev->spriteInfo->sprite;
36914642e01fSmrg
369205b261ecSmrg#ifdef PANORAMIX
369335c4bbdfSmrg    if (!noPanoramiXExtension)
369435c4bbdfSmrg        return XineramaWarpPointer(client);
369505b261ecSmrg#endif
369605b261ecSmrg
369705b261ecSmrg    if (stuff->dstWid != None) {
369835c4bbdfSmrg        rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess);
369935c4bbdfSmrg        if (rc != Success)
370035c4bbdfSmrg            return rc;
370105b261ecSmrg    }
37024642e01fSmrg    x = pSprite->hotPhys.x;
37034642e01fSmrg    y = pSprite->hotPhys.y;
370405b261ecSmrg
370535c4bbdfSmrg    if (stuff->srcWid != None) {
370635c4bbdfSmrg        int winX, winY;
370735c4bbdfSmrg        XID winID = stuff->srcWid;
370805b261ecSmrg        WindowPtr source;
37094642e01fSmrg
371035c4bbdfSmrg        rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess);
371135c4bbdfSmrg        if (rc != Success)
371235c4bbdfSmrg            return rc;
371335c4bbdfSmrg
371435c4bbdfSmrg        winX = source->drawable.x;
371535c4bbdfSmrg        winY = source->drawable.y;
371635c4bbdfSmrg        if (source->drawable.pScreen != pSprite->hotPhys.pScreen ||
371735c4bbdfSmrg            x < winX + stuff->srcX ||
371835c4bbdfSmrg            y < winY + stuff->srcY ||
371935c4bbdfSmrg            (stuff->srcWidth != 0 &&
372035c4bbdfSmrg             winX + stuff->srcX + (int) stuff->srcWidth < x) ||
372135c4bbdfSmrg            (stuff->srcHeight != 0 &&
372235c4bbdfSmrg             winY + stuff->srcY + (int) stuff->srcHeight < y) ||
37237e31ba66Smrg            (source->parent && !PointInWindowIsVisible(source, x, y)))
372435c4bbdfSmrg            return Success;
372535c4bbdfSmrg    }
372635c4bbdfSmrg    if (dest) {
372735c4bbdfSmrg        x = dest->drawable.x;
372835c4bbdfSmrg        y = dest->drawable.y;
372935c4bbdfSmrg        newScreen = dest->drawable.pScreen;
373035c4bbdfSmrg    }
373135c4bbdfSmrg    else
373235c4bbdfSmrg        newScreen = pSprite->hotPhys.pScreen;
373305b261ecSmrg
373405b261ecSmrg    x += stuff->dstX;
373505b261ecSmrg    y += stuff->dstY;
373605b261ecSmrg
373705b261ecSmrg    if (x < 0)
373835c4bbdfSmrg        x = 0;
373905b261ecSmrg    else if (x >= newScreen->width)
374035c4bbdfSmrg        x = newScreen->width - 1;
374105b261ecSmrg    if (y < 0)
374235c4bbdfSmrg        y = 0;
374305b261ecSmrg    else if (y >= newScreen->height)
374435c4bbdfSmrg        y = newScreen->height - 1;
374535c4bbdfSmrg
374635c4bbdfSmrg    if (newScreen == pSprite->hotPhys.pScreen) {
374735c4bbdfSmrg        if (x < pSprite->physLimits.x1)
374835c4bbdfSmrg            x = pSprite->physLimits.x1;
374935c4bbdfSmrg        else if (x >= pSprite->physLimits.x2)
375035c4bbdfSmrg            x = pSprite->physLimits.x2 - 1;
375135c4bbdfSmrg        if (y < pSprite->physLimits.y1)
375235c4bbdfSmrg            y = pSprite->physLimits.y1;
375335c4bbdfSmrg        else if (y >= pSprite->physLimits.y2)
375435c4bbdfSmrg            y = pSprite->physLimits.y2 - 1;
375535c4bbdfSmrg        if (pSprite->hotShape)
375635c4bbdfSmrg            ConfineToShape(dev, pSprite->hotShape, &x, &y);
375735c4bbdfSmrg        (*newScreen->SetCursorPosition) (dev, newScreen, x, y, TRUE);
375835c4bbdfSmrg    }
375935c4bbdfSmrg    else if (!PointerConfinedToScreen(dev)) {
376035c4bbdfSmrg        NewCurrentScreen(dev, newScreen, x, y);
376105b261ecSmrg    }
37627e31ba66Smrg    if (*newScreen->CursorWarpedTo)
37637e31ba66Smrg        (*newScreen->CursorWarpedTo) (dev, newScreen, client,
37647e31ba66Smrg                                      dest, pSprite, x, y);
376505b261ecSmrg    return Success;
376605b261ecSmrg}
376705b261ecSmrg
37684642e01fSmrgstatic Bool
37694642e01fSmrgBorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
377005b261ecSmrg{
377135c4bbdfSmrg    if (RegionNotEmpty(&pWin->borderSize))
377235c4bbdfSmrg        return TRUE;
377305b261ecSmrg
377405b261ecSmrg#ifdef PANORAMIX
377535c4bbdfSmrg    if (!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) {
377635c4bbdfSmrg        int i;
377735c4bbdfSmrg
377835c4bbdfSmrg        FOR_NSCREENS_FORWARD_SKIP(i) {
377935c4bbdfSmrg            if (RegionNotEmpty
378035c4bbdfSmrg                (&pDev->spriteInfo->sprite->windows[i]->borderSize))
378135c4bbdfSmrg                return TRUE;
378235c4bbdfSmrg        }
378335c4bbdfSmrg    }
378405b261ecSmrg#endif
378535c4bbdfSmrg    return FALSE;
378605b261ecSmrg}
378705b261ecSmrg
37884642e01fSmrg/**
378935c4bbdfSmrg * Activate the given passive grab. If the grab is activated successfully, the
379035c4bbdfSmrg * event has been delivered to the client.
37914642e01fSmrg *
379235c4bbdfSmrg * @param device The device of the event to check.
379335c4bbdfSmrg * @param grab The grab to check.
37946747b715Smrg * @param event The current device event.
379535c4bbdfSmrg * @param real_event The original event, in case of touch emulation. The
379635c4bbdfSmrg * real event is the one stored in the sync queue.
379735c4bbdfSmrg *
379835c4bbdfSmrg * @return Whether the grab has been activated.
379905b261ecSmrg */
380035c4bbdfSmrgBool
380135c4bbdfSmrgActivatePassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event,
380235c4bbdfSmrg                    InternalEvent *real_event)
380305b261ecSmrg{
38049ace9065Smrg    SpritePtr pSprite = device->spriteInfo->sprite;
380535c4bbdfSmrg    xEvent *xE = NULL;
380635c4bbdfSmrg    int count;
380735c4bbdfSmrg    int rc;
38086747b715Smrg
380935c4bbdfSmrg    /* The only consumers of corestate are Xi 1.x and core events, which
381035c4bbdfSmrg     * are guaranteed to come from DeviceEvents. */
381135c4bbdfSmrg    if (grab->grabtype == XI || grab->grabtype == CORE) {
381235c4bbdfSmrg        DeviceIntPtr gdev;
381305b261ecSmrg
381435c4bbdfSmrg        event->device_event.corestate &= 0x1f00;
381535c4bbdfSmrg
381635c4bbdfSmrg        if (grab->grabtype == CORE)
381735c4bbdfSmrg            gdev = GetMaster(device, KEYBOARD_OR_FLOAT);
381835c4bbdfSmrg        else
381935c4bbdfSmrg            gdev = grab->modifierDevice;
382035c4bbdfSmrg
382135c4bbdfSmrg        if (gdev && gdev->key && gdev->key->xkbInfo)
382235c4bbdfSmrg            event->device_event.corestate |=
382335c4bbdfSmrg                gdev->key->xkbInfo->state.grab_mods & (~0x1f00);
382435c4bbdfSmrg    }
382535c4bbdfSmrg
382635c4bbdfSmrg    if (grab->grabtype == CORE) {
382735c4bbdfSmrg        rc = EventToCore(event, &xE, &count);
382835c4bbdfSmrg        if (rc != Success) {
382935c4bbdfSmrg            BUG_WARN_MSG(rc != BadMatch, "[dix] %s: core conversion failed"
383035c4bbdfSmrg                         "(%d, %d).\n", device->name, event->any.type, rc);
383135c4bbdfSmrg            return FALSE;
38324642e01fSmrg        }
383335c4bbdfSmrg    }
383435c4bbdfSmrg    else if (grab->grabtype == XI2) {
383535c4bbdfSmrg        rc = EventToXI2(event, &xE);
383635c4bbdfSmrg        if (rc != Success) {
383735c4bbdfSmrg            if (rc != BadMatch)
383835c4bbdfSmrg                BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI2 conversion failed"
383935c4bbdfSmrg                             "(%d, %d).\n", device->name, event->any.type, rc);
384035c4bbdfSmrg            return FALSE;
384135c4bbdfSmrg        }
384235c4bbdfSmrg        count = 1;
384335c4bbdfSmrg    }
384435c4bbdfSmrg    else {
384535c4bbdfSmrg        rc = EventToXI(event, &xE, &count);
384635c4bbdfSmrg        if (rc != Success) {
384735c4bbdfSmrg            if (rc != BadMatch)
384835c4bbdfSmrg                BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI conversion failed"
384935c4bbdfSmrg                             "(%d, %d).\n", device->name, event->any.type, rc);
385035c4bbdfSmrg            return FALSE;
385135c4bbdfSmrg        }
385235c4bbdfSmrg    }
38536747b715Smrg
38545a112b11Smrg    ActivateGrabNoDelivery(device, grab, event, real_event);
38556747b715Smrg
385635c4bbdfSmrg    if (xE) {
385735c4bbdfSmrg        FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
38586747b715Smrg
385935c4bbdfSmrg        /* XXX: XACE? */
386035c4bbdfSmrg        TryClientEvents(rClient(grab), device, xE, count,
386135c4bbdfSmrg                        GetEventFilter(device, xE),
386235c4bbdfSmrg                        GetEventFilter(device, xE), grab);
386335c4bbdfSmrg    }
38646747b715Smrg
386535c4bbdfSmrg    free(xE);
386635c4bbdfSmrg    return TRUE;
386735c4bbdfSmrg}
386835c4bbdfSmrg
38695a112b11Smrg/**
38705a112b11Smrg * Activates a grab without event delivery.
38715a112b11Smrg *
38725a112b11Smrg * @param device The device of the event to check.
38735a112b11Smrg * @param grab The grab to check.
38745a112b11Smrg * @param event The current device event.
38755a112b11Smrg * @param real_event The original event, in case of touch emulation. The
38765a112b11Smrg * real event is the one stored in the sync queue.
38775a112b11Smrg */
38785a112b11Smrgvoid ActivateGrabNoDelivery(DeviceIntPtr dev, GrabPtr grab,
38795a112b11Smrg                            InternalEvent *event, InternalEvent *real_event)
38805a112b11Smrg{
38815a112b11Smrg    GrabInfoPtr grabinfo = &dev->deviceGrab;
38825a112b11Smrg    (*grabinfo->ActivateGrab) (dev, grab,
38835a112b11Smrg                               ClientTimeToServerTime(event->any.time), TRUE);
38845a112b11Smrg
38855a112b11Smrg    if (grabinfo->sync.state == FROZEN_NO_EVENT)
38865a112b11Smrg        grabinfo->sync.state = FROZEN_WITH_EVENT;
388790bea6a0Smrg    CopyPartialInternalEvent(grabinfo->sync.event, real_event);
38885a112b11Smrg}
38895a112b11Smrg
389035c4bbdfSmrgstatic BOOL
389135c4bbdfSmrgCoreGrabInterferes(DeviceIntPtr device, GrabPtr grab)
389235c4bbdfSmrg{
389335c4bbdfSmrg    DeviceIntPtr other;
389435c4bbdfSmrg    BOOL interfering = FALSE;
389535c4bbdfSmrg
389635c4bbdfSmrg    for (other = inputInfo.devices; other; other = other->next) {
389735c4bbdfSmrg        GrabPtr othergrab = other->deviceGrab.grab;
389835c4bbdfSmrg
389935c4bbdfSmrg        if (othergrab && othergrab->grabtype == CORE &&
390035c4bbdfSmrg            SameClient(grab, rClient(othergrab)) &&
390135c4bbdfSmrg            ((IsPointerDevice(grab->device) &&
390235c4bbdfSmrg              IsPointerDevice(othergrab->device)) ||
390335c4bbdfSmrg             (IsKeyboardDevice(grab->device) &&
390435c4bbdfSmrg              IsKeyboardDevice(othergrab->device)))) {
390535c4bbdfSmrg            interfering = TRUE;
390635c4bbdfSmrg            break;
39076747b715Smrg        }
390835c4bbdfSmrg    }
39096747b715Smrg
391035c4bbdfSmrg    return interfering;
391135c4bbdfSmrg}
39124642e01fSmrg
391335c4bbdfSmrgenum MatchFlags {
391435c4bbdfSmrg    NO_MATCH = 0x0,
391535c4bbdfSmrg    CORE_MATCH = 0x1,
391635c4bbdfSmrg    XI_MATCH = 0x2,
391735c4bbdfSmrg    XI2_MATCH = 0x4,
391835c4bbdfSmrg};
39196747b715Smrg
392035c4bbdfSmrg/**
392135c4bbdfSmrg * Match the grab against the temporary grab on the given input level.
392235c4bbdfSmrg * Modifies the temporary grab pointer.
392335c4bbdfSmrg *
392435c4bbdfSmrg * @param grab The grab to match against
392535c4bbdfSmrg * @param tmp The temporary grab to use for matching
392635c4bbdfSmrg * @param level The input level we want to match on
392735c4bbdfSmrg * @param event_type Wire protocol event type
392835c4bbdfSmrg *
392935c4bbdfSmrg * @return The respective matched flag or 0 for no match
393035c4bbdfSmrg */
393135c4bbdfSmrgstatic enum MatchFlags
393235c4bbdfSmrgMatchForType(const GrabPtr grab, GrabPtr tmp, enum InputLevel level,
393335c4bbdfSmrg             int event_type)
393435c4bbdfSmrg{
393535c4bbdfSmrg    enum MatchFlags match;
393635c4bbdfSmrg    BOOL ignore_device = FALSE;
393735c4bbdfSmrg    int grabtype;
393835c4bbdfSmrg    int evtype;
39394642e01fSmrg
394035c4bbdfSmrg    switch (level) {
394135c4bbdfSmrg    case XI2:
394235c4bbdfSmrg        grabtype = XI2;
394335c4bbdfSmrg        evtype = GetXI2Type(event_type);
394435c4bbdfSmrg        BUG_WARN(!evtype);
394535c4bbdfSmrg        match = XI2_MATCH;
394635c4bbdfSmrg        break;
394735c4bbdfSmrg    case XI:
394835c4bbdfSmrg        grabtype = XI;
394935c4bbdfSmrg        evtype = GetXIType(event_type);
395035c4bbdfSmrg        match = XI_MATCH;
395135c4bbdfSmrg        break;
395235c4bbdfSmrg    case CORE:
395335c4bbdfSmrg        grabtype = CORE;
395435c4bbdfSmrg        evtype = GetCoreType(event_type);
395535c4bbdfSmrg        match = CORE_MATCH;
395635c4bbdfSmrg        ignore_device = TRUE;
395735c4bbdfSmrg        break;
395835c4bbdfSmrg    default:
395935c4bbdfSmrg        return NO_MATCH;
396035c4bbdfSmrg    }
396135c4bbdfSmrg
396235c4bbdfSmrg    tmp->grabtype = grabtype;
396335c4bbdfSmrg    tmp->type = evtype;
396435c4bbdfSmrg
396535c4bbdfSmrg    if (tmp->type && GrabMatchesSecond(tmp, grab, ignore_device))
396635c4bbdfSmrg        return match;
396735c4bbdfSmrg
396835c4bbdfSmrg    return NO_MATCH;
396935c4bbdfSmrg}
39704642e01fSmrg
397135c4bbdfSmrg/**
397235c4bbdfSmrg * Check an individual grab against an event to determine if a passive grab
397335c4bbdfSmrg * should be activated.
397435c4bbdfSmrg *
397535c4bbdfSmrg * @param device The device of the event to check.
397635c4bbdfSmrg * @param grab The grab to check.
397735c4bbdfSmrg * @param event The current device event.
397835c4bbdfSmrg * @param checkCore Check for core grabs too.
397935c4bbdfSmrg * @param tempGrab A pre-allocated temporary grab record for matching. This
398035c4bbdfSmrg *        must have the window and device values filled in.
398135c4bbdfSmrg *
398235c4bbdfSmrg * @return Whether the grab matches the event.
398335c4bbdfSmrg */
398435c4bbdfSmrgstatic Bool
398535c4bbdfSmrgCheckPassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event,
398635c4bbdfSmrg                 Bool checkCore, GrabPtr tempGrab)
398735c4bbdfSmrg{
398835c4bbdfSmrg    DeviceIntPtr gdev;
398935c4bbdfSmrg    XkbSrvInfoPtr xkbi = NULL;
399035c4bbdfSmrg    enum MatchFlags match = 0;
399135c4bbdfSmrg    int emulated_type = 0;
39926747b715Smrg
399335c4bbdfSmrg    gdev = grab->modifierDevice;
399435c4bbdfSmrg    if (grab->grabtype == CORE) {
399535c4bbdfSmrg        gdev = GetMaster(device, KEYBOARD_OR_FLOAT);
399635c4bbdfSmrg    }
399735c4bbdfSmrg    else if (grab->grabtype == XI2) {
399835c4bbdfSmrg        /* if the device is an attached slave device, gdev must be the
399935c4bbdfSmrg         * attached master keyboard. Since the slave may have been
400035c4bbdfSmrg         * reattached after the grab, the modifier device may not be the
400135c4bbdfSmrg         * same. */
400235c4bbdfSmrg        if (!IsMaster(grab->device) && !IsFloating(device))
400335c4bbdfSmrg            gdev = GetMaster(device, MASTER_KEYBOARD);
400435c4bbdfSmrg    }
40054642e01fSmrg
400635c4bbdfSmrg    if (gdev && gdev->key)
400735c4bbdfSmrg        xkbi = gdev->key->xkbInfo;
400835c4bbdfSmrg    tempGrab->modifierDevice = grab->modifierDevice;
400935c4bbdfSmrg    tempGrab->modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
401005b261ecSmrg
401135c4bbdfSmrg    /* Check for XI2 and XI grabs first */
401235c4bbdfSmrg    match = MatchForType(grab, tempGrab, XI2, event->any.type);
401305b261ecSmrg
401435c4bbdfSmrg    if (!match && IsTouchEvent(event) &&
401535c4bbdfSmrg        (event->device_event.flags & TOUCH_POINTER_EMULATED)) {
401635c4bbdfSmrg        emulated_type = TouchGetPointerEventType(event);
401735c4bbdfSmrg        match = MatchForType(grab, tempGrab, XI2, emulated_type);
401835c4bbdfSmrg    }
401935c4bbdfSmrg
402035c4bbdfSmrg    if (!match)
402135c4bbdfSmrg        match = MatchForType(grab, tempGrab, XI, event->any.type);
402235c4bbdfSmrg
402335c4bbdfSmrg    if (!match && emulated_type)
402435c4bbdfSmrg        match = MatchForType(grab, tempGrab, XI, emulated_type);
402535c4bbdfSmrg
402635c4bbdfSmrg    if (!match && checkCore) {
402735c4bbdfSmrg        match = MatchForType(grab, tempGrab, CORE, event->any.type);
402835c4bbdfSmrg        if (!match && emulated_type)
402935c4bbdfSmrg            match = MatchForType(grab, tempGrab, CORE, emulated_type);
403035c4bbdfSmrg    }
403135c4bbdfSmrg
403235c4bbdfSmrg    if (!match || (grab->confineTo &&
403335c4bbdfSmrg                   (!grab->confineTo->realized ||
403435c4bbdfSmrg                    !BorderSizeNotEmpty(device, grab->confineTo))))
403535c4bbdfSmrg        return FALSE;
403635c4bbdfSmrg
403735c4bbdfSmrg    /* In some cases a passive core grab may exist, but the client
403835c4bbdfSmrg     * already has a core grab on some other device. In this case we
403935c4bbdfSmrg     * must not get the grab, otherwise we may never ungrab the
404035c4bbdfSmrg     * device.
404135c4bbdfSmrg     */
404235c4bbdfSmrg
404335c4bbdfSmrg    if (grab->grabtype == CORE) {
404435c4bbdfSmrg        /* A passive grab may have been created for a different device
404535c4bbdfSmrg           than it is assigned to at this point in time.
404635c4bbdfSmrg           Update the grab's device and modifier device to reflect the
404735c4bbdfSmrg           current state.
404835c4bbdfSmrg           Since XGrabDeviceButton requires to specify the
404935c4bbdfSmrg           modifierDevice explicitly, we don't override this choice.
405035c4bbdfSmrg         */
405135c4bbdfSmrg        if (grab->type < GenericEvent) {
405235c4bbdfSmrg            grab->device = device;
405335c4bbdfSmrg            grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD);
405435c4bbdfSmrg        }
405535c4bbdfSmrg
405635c4bbdfSmrg        if (CoreGrabInterferes(device, grab))
405735c4bbdfSmrg            return FALSE;
405835c4bbdfSmrg    }
405935c4bbdfSmrg
406035c4bbdfSmrg    return TRUE;
406135c4bbdfSmrg}
406235c4bbdfSmrg
406335c4bbdfSmrg/**
406435c4bbdfSmrg * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
406535c4bbdfSmrg * passive grab set on the window to be activated.
406635c4bbdfSmrg * If activate is true and a passive grab is found, it will be activated,
406735c4bbdfSmrg * and the event will be delivered to the client.
406835c4bbdfSmrg *
406935c4bbdfSmrg * @param pWin The window that may be subject to a passive grab.
407035c4bbdfSmrg * @param device Device that caused the event.
407135c4bbdfSmrg * @param event The current device event.
407235c4bbdfSmrg * @param checkCore Check for core grabs too.
407335c4bbdfSmrg * @param activate If a grab is found, activate it and deliver the event.
407435c4bbdfSmrg */
407535c4bbdfSmrg
407635c4bbdfSmrgGrabPtr
407735c4bbdfSmrgCheckPassiveGrabsOnWindow(WindowPtr pWin,
407835c4bbdfSmrg                          DeviceIntPtr device,
407935c4bbdfSmrg                          InternalEvent *event, BOOL checkCore, BOOL activate)
408035c4bbdfSmrg{
408135c4bbdfSmrg    GrabPtr grab = wPassiveGrabs(pWin);
408235c4bbdfSmrg    GrabPtr tempGrab;
408335c4bbdfSmrg
408435c4bbdfSmrg    if (!grab)
408535c4bbdfSmrg        return NULL;
408635c4bbdfSmrg
408735c4bbdfSmrg    tempGrab = AllocGrab(NULL);
408835c4bbdfSmrg    if (tempGrab == NULL)
408935c4bbdfSmrg        return NULL;
409035c4bbdfSmrg
409135c4bbdfSmrg    /* Fill out the grab details, but leave the type for later before
409235c4bbdfSmrg     * comparing */
409335c4bbdfSmrg    switch (event->any.type) {
409435c4bbdfSmrg    case ET_KeyPress:
409535c4bbdfSmrg    case ET_KeyRelease:
409635c4bbdfSmrg        tempGrab->detail.exact = event->device_event.detail.key;
409735c4bbdfSmrg        break;
409835c4bbdfSmrg    case ET_ButtonPress:
409935c4bbdfSmrg    case ET_ButtonRelease:
410035c4bbdfSmrg    case ET_TouchBegin:
410135c4bbdfSmrg    case ET_TouchEnd:
410235c4bbdfSmrg        tempGrab->detail.exact = event->device_event.detail.button;
410335c4bbdfSmrg        break;
410435c4bbdfSmrg    default:
410535c4bbdfSmrg        tempGrab->detail.exact = 0;
410635c4bbdfSmrg        break;
410735c4bbdfSmrg    }
410835c4bbdfSmrg    tempGrab->window = pWin;
410935c4bbdfSmrg    tempGrab->device = device;
411035c4bbdfSmrg    tempGrab->detail.pMask = NULL;
411135c4bbdfSmrg    tempGrab->modifiersDetail.pMask = NULL;
411235c4bbdfSmrg    tempGrab->next = NULL;
411335c4bbdfSmrg
411435c4bbdfSmrg    for (; grab; grab = grab->next) {
411535c4bbdfSmrg        if (!CheckPassiveGrab(device, grab, event, checkCore, tempGrab))
411635c4bbdfSmrg            continue;
411735c4bbdfSmrg
411835c4bbdfSmrg        if (activate && !ActivatePassiveGrab(device, grab, event, event))
411935c4bbdfSmrg            continue;
41206747b715Smrg
412135c4bbdfSmrg        break;
412205b261ecSmrg    }
412335c4bbdfSmrg
412435c4bbdfSmrg    FreeGrab(tempGrab);
412535c4bbdfSmrg    return grab;
412605b261ecSmrg}
412705b261ecSmrg
412805b261ecSmrg/**
412905b261ecSmrg * CheckDeviceGrabs handles both keyboard and pointer events that may cause
41304642e01fSmrg * a passive grab to be activated.
413105b261ecSmrg *
413205b261ecSmrg * If the event is a keyboard event, the ancestors of the focus window are
413305b261ecSmrg * traced down and tried to see if they have any passive grabs to be
41345a112b11Smrg * activated.  If the focus window itself is reached and its descendants
413505b261ecSmrg * contain the pointer, the ancestors of the window that the pointer is in
413605b261ecSmrg * are then traced down starting at the focus window, otherwise no grabs are
41374642e01fSmrg * activated.
413805b261ecSmrg * If the event is a pointer event, the ancestors of the window that the
413905b261ecSmrg * pointer is in are traced down starting at the root until CheckPassiveGrabs
414005b261ecSmrg * causes a passive grab to activate or all the windows are
414105b261ecSmrg * tried. PRH
414205b261ecSmrg *
414305b261ecSmrg * If a grab is activated, the event has been sent to the client already!
414405b261ecSmrg *
41454642e01fSmrg * The event we pass in must always be an XI event. From this, we then emulate
41464642e01fSmrg * the core event and then check for grabs.
41474642e01fSmrg *
414805b261ecSmrg * @param device The device that caused the event.
41494642e01fSmrg * @param xE The event to handle (Device{Button|Key}Press).
415005b261ecSmrg * @param count Number of events in list.
415105b261ecSmrg * @return TRUE if a grab has been activated or false otherwise.
415205b261ecSmrg*/
415305b261ecSmrg
415405b261ecSmrgBool
41555a112b11SmrgCheckDeviceGrabs(DeviceIntPtr device, InternalEvent *ievent, WindowPtr ancestor)
415605b261ecSmrg{
415705b261ecSmrg    int i;
415805b261ecSmrg    WindowPtr pWin = NULL;
415935c4bbdfSmrg    FocusClassPtr focus =
41605a112b11Smrg        IsPointerEvent(ievent) ? NULL : device->focus;
41616747b715Smrg    BOOL sendCore = (IsMaster(device) && device->coreEvents);
416235c4bbdfSmrg    Bool ret = FALSE;
41635a112b11Smrg    DeviceEvent *event = &ievent->device_event;
416405b261ecSmrg
416535c4bbdfSmrg    if (event->type != ET_ButtonPress && event->type != ET_KeyPress)
41664642e01fSmrg        return FALSE;
41674642e01fSmrg
416835c4bbdfSmrg    if (event->type == ET_ButtonPress && (device->button->buttonsDown != 1))
416935c4bbdfSmrg        return FALSE;
41704642e01fSmrg
41719ace9065Smrg    if (device->deviceGrab.grab)
41729ace9065Smrg        return FALSE;
41739ace9065Smrg
41749ace9065Smrg    i = 0;
417535c4bbdfSmrg    if (ancestor) {
41769ace9065Smrg        while (i < device->spriteInfo->sprite->spriteTraceGood)
41779ace9065Smrg            if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor)
41789ace9065Smrg                break;
41799ace9065Smrg        if (i == device->spriteInfo->sprite->spriteTraceGood)
418035c4bbdfSmrg            goto out;
41819ace9065Smrg    }
418205b261ecSmrg
418335c4bbdfSmrg    if (focus) {
418435c4bbdfSmrg        for (; i < focus->traceGood; i++) {
418535c4bbdfSmrg            pWin = focus->trace[i];
41865a112b11Smrg            if (CheckPassiveGrabsOnWindow(pWin, device, ievent,
418735c4bbdfSmrg                                          sendCore, TRUE)) {
418835c4bbdfSmrg                ret = TRUE;
418935c4bbdfSmrg                goto out;
419035c4bbdfSmrg            }
419135c4bbdfSmrg        }
41924642e01fSmrg
419335c4bbdfSmrg        if ((focus->win == NoneWin) ||
419435c4bbdfSmrg            (i >= device->spriteInfo->sprite->spriteTraceGood) ||
419535c4bbdfSmrg            (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i - 1]))
419635c4bbdfSmrg            goto out;
419705b261ecSmrg    }
419805b261ecSmrg
419935c4bbdfSmrg    for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) {
420035c4bbdfSmrg        pWin = device->spriteInfo->sprite->spriteTrace[i];
42015a112b11Smrg        if (CheckPassiveGrabsOnWindow(pWin, device, ievent,
420235c4bbdfSmrg                                      sendCore, TRUE)) {
420335c4bbdfSmrg            ret = TRUE;
420435c4bbdfSmrg            goto out;
420535c4bbdfSmrg        }
420605b261ecSmrg    }
420705b261ecSmrg
420835c4bbdfSmrg out:
420935c4bbdfSmrg    if (ret == TRUE && event->type == ET_KeyPress)
421035c4bbdfSmrg        device->deviceGrab.activatingKey = event->detail.key;
421135c4bbdfSmrg    return ret;
421205b261ecSmrg}
421305b261ecSmrg
421405b261ecSmrg/**
421505b261ecSmrg * Called for keyboard events to deliver event to whatever client owns the
42166747b715Smrg * focus.
42176747b715Smrg *
42186747b715Smrg * The event is delivered to the keyboard's focus window, the root window or
42196747b715Smrg * to the window owning the input focus.
422005b261ecSmrg *
422105b261ecSmrg * @param keybd The keyboard originating the event.
42226747b715Smrg * @param event The event, not yet in wire format.
422305b261ecSmrg * @param window Window underneath the sprite.
422405b261ecSmrg */
422505b261ecSmrgvoid
42266747b715SmrgDeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
422705b261ecSmrg{
42286747b715Smrg    DeviceIntPtr ptr;
422905b261ecSmrg    WindowPtr focus = keybd->focus->win;
42306747b715Smrg    BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents);
423135c4bbdfSmrg    xEvent *core = NULL, *xE = NULL, *xi2 = NULL;
42326747b715Smrg    int count, rc;
42334642e01fSmrg    int deliveries = 0;
423405b261ecSmrg
423505b261ecSmrg    if (focus == FollowKeyboardWin)
423635c4bbdfSmrg        focus = inputInfo.keyboard->focus->win;
423705b261ecSmrg    if (!focus)
423835c4bbdfSmrg        return;
423935c4bbdfSmrg    if (focus == PointerRootWin) {
424035c4bbdfSmrg        DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd);
424135c4bbdfSmrg        return;
424205b261ecSmrg    }
424335c4bbdfSmrg    if ((focus == window) || IsParent(focus, window)) {
424435c4bbdfSmrg        if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd))
424535c4bbdfSmrg            return;
424605b261ecSmrg    }
42474642e01fSmrg
424805b261ecSmrg    /* just deliver it to the focus window */
424935c4bbdfSmrg    ptr = GetMaster(keybd, POINTER_OR_FLOAT);
42506747b715Smrg
42516747b715Smrg    rc = EventToXI2(event, &xi2);
425235c4bbdfSmrg    if (rc == Success) {
42536747b715Smrg        /* XXX: XACE */
42546747b715Smrg        int filter = GetEventFilter(keybd, xi2);
425535c4bbdfSmrg
42569ace9065Smrg        FixUpEventFromWindow(ptr->spriteInfo->sprite, xi2, focus, None, FALSE);
42576747b715Smrg        deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1,
42586747b715Smrg                                           filter, NullGrab);
42596747b715Smrg        if (deliveries > 0)
42606747b715Smrg            goto unwind;
426135c4bbdfSmrg    }
426235c4bbdfSmrg    else if (rc != BadMatch)
426335c4bbdfSmrg        ErrorF
426435c4bbdfSmrg            ("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n",
426535c4bbdfSmrg             keybd->name, event->any.type, rc);
42666747b715Smrg
42676747b715Smrg    rc = EventToXI(event, &xE, &count);
42686747b715Smrg    if (rc == Success &&
426935c4bbdfSmrg        XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success) {
42709ace9065Smrg        FixUpEventFromWindow(ptr->spriteInfo->sprite, xE, focus, None, FALSE);
42716747b715Smrg        deliveries = DeliverEventsToWindow(keybd, focus, xE, count,
427235c4bbdfSmrg                                           GetEventFilter(keybd, xE), NullGrab);
42736747b715Smrg
42746747b715Smrg        if (deliveries > 0)
42756747b715Smrg            goto unwind;
427635c4bbdfSmrg    }
427735c4bbdfSmrg    else if (rc != BadMatch)
427835c4bbdfSmrg        ErrorF
427935c4bbdfSmrg            ("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n",
428035c4bbdfSmrg             keybd->name, event->any.type, rc);
42814642e01fSmrg
428235c4bbdfSmrg    if (sendCore) {
428335c4bbdfSmrg        rc = EventToCore(event, &core, &count);
42846747b715Smrg        if (rc == Success) {
428535c4bbdfSmrg            if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, core, count) ==
428635c4bbdfSmrg                Success) {
428735c4bbdfSmrg                FixUpEventFromWindow(keybd->spriteInfo->sprite, core, focus,
42889ace9065Smrg                                     None, FALSE);
428935c4bbdfSmrg                deliveries =
429035c4bbdfSmrg                    DeliverEventsToWindow(keybd, focus, core, count,
429135c4bbdfSmrg                                          GetEventFilter(keybd, core),
429235c4bbdfSmrg                                          NullGrab);
42936747b715Smrg            }
429435c4bbdfSmrg        }
429535c4bbdfSmrg        else if (rc != BadMatch)
429635c4bbdfSmrg            ErrorF
429735c4bbdfSmrg                ("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n",
429835c4bbdfSmrg                 keybd->name, event->any.type, rc);
42994642e01fSmrg    }
43006747b715Smrg
430135c4bbdfSmrg unwind:
430235c4bbdfSmrg    free(core);
43036747b715Smrg    free(xE);
43046747b715Smrg    free(xi2);
43056747b715Smrg    return;
430605b261ecSmrg}
430705b261ecSmrg
430835c4bbdfSmrgint
430935c4bbdfSmrgDeliverOneGrabbedEvent(InternalEvent *event, DeviceIntPtr dev,
431035c4bbdfSmrg                       enum InputLevel level)
431135c4bbdfSmrg{
431235c4bbdfSmrg    SpritePtr pSprite = dev->spriteInfo->sprite;
431335c4bbdfSmrg    int rc;
431435c4bbdfSmrg    xEvent *xE = NULL;
431535c4bbdfSmrg    int count = 0;
431635c4bbdfSmrg    int deliveries = 0;
431735c4bbdfSmrg    Mask mask;
431835c4bbdfSmrg    GrabInfoPtr grabinfo = &dev->deviceGrab;
431935c4bbdfSmrg    GrabPtr grab = grabinfo->grab;
432035c4bbdfSmrg    Mask filter;
432135c4bbdfSmrg
432235c4bbdfSmrg    if (grab->grabtype != level)
432335c4bbdfSmrg        return 0;
432435c4bbdfSmrg
432535c4bbdfSmrg    switch (level) {
432635c4bbdfSmrg    case XI2:
432735c4bbdfSmrg        rc = EventToXI2(event, &xE);
432835c4bbdfSmrg        count = 1;
432935c4bbdfSmrg        if (rc == Success) {
433035c4bbdfSmrg            int evtype = xi2_get_type(xE);
433135c4bbdfSmrg
433235c4bbdfSmrg            mask = GetXI2MaskByte(grab->xi2mask, dev, evtype);
433335c4bbdfSmrg            filter = GetEventFilter(dev, xE);
433435c4bbdfSmrg        }
433535c4bbdfSmrg        break;
433635c4bbdfSmrg    case XI:
433735c4bbdfSmrg        if (grabinfo->fromPassiveGrab && grabinfo->implicitGrab)
433835c4bbdfSmrg            mask = grab->deviceMask;
433935c4bbdfSmrg        else
434035c4bbdfSmrg            mask = grab->eventMask;
434135c4bbdfSmrg        rc = EventToXI(event, &xE, &count);
434235c4bbdfSmrg        if (rc == Success)
434335c4bbdfSmrg            filter = GetEventFilter(dev, xE);
434435c4bbdfSmrg        break;
434535c4bbdfSmrg    case CORE:
434635c4bbdfSmrg        rc = EventToCore(event, &xE, &count);
434735c4bbdfSmrg        mask = grab->eventMask;
434835c4bbdfSmrg        if (rc == Success)
434935c4bbdfSmrg            filter = GetEventFilter(dev, xE);
435035c4bbdfSmrg        break;
435135c4bbdfSmrg    default:
435235c4bbdfSmrg        BUG_WARN_MSG(1, "Invalid input level %d\n", level);
435335c4bbdfSmrg        return 0;
435435c4bbdfSmrg    }
435535c4bbdfSmrg
435635c4bbdfSmrg    if (rc == Success) {
435735c4bbdfSmrg        FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
435835c4bbdfSmrg        if (XaceHook(XACE_SEND_ACCESS, 0, dev,
435935c4bbdfSmrg                     grab->window, xE, count) ||
436035c4bbdfSmrg            XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
436135c4bbdfSmrg                     grab->window, xE, count))
436235c4bbdfSmrg            deliveries = 1;     /* don't send, but pretend we did */
436335c4bbdfSmrg        else if (level != CORE || !IsInterferingGrab(rClient(grab), dev, xE)) {
436435c4bbdfSmrg            deliveries = TryClientEvents(rClient(grab), dev,
436535c4bbdfSmrg                                         xE, count, mask, filter, grab);
436635c4bbdfSmrg        }
436735c4bbdfSmrg    }
436835c4bbdfSmrg    else
436935c4bbdfSmrg        BUG_WARN_MSG(rc != BadMatch,
437035c4bbdfSmrg                     "%s: conversion to mode %d failed on %d with %d\n",
437135c4bbdfSmrg                     dev->name, level, event->any.type, rc);
437235c4bbdfSmrg
437335c4bbdfSmrg    free(xE);
437435c4bbdfSmrg    return deliveries;
437535c4bbdfSmrg}
437635c4bbdfSmrg
437705b261ecSmrg/**
437805b261ecSmrg * Deliver an event from a device that is currently grabbed. Uses
437905b261ecSmrg * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the
438005b261ecSmrg * grab. If not, TryClientEvents() is used.
438105b261ecSmrg *
438205b261ecSmrg * @param deactivateGrab True if the device's grab should be deactivated.
438335c4bbdfSmrg *
438435c4bbdfSmrg * @return The number of events delivered.
438505b261ecSmrg */
438635c4bbdfSmrgint
43876747b715SmrgDeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
43886747b715Smrg                    Bool deactivateGrab)
438905b261ecSmrg{
43904642e01fSmrg    GrabPtr grab;
43914642e01fSmrg    GrabInfoPtr grabinfo;
439205b261ecSmrg    int deliveries = 0;
43934642e01fSmrg    SpritePtr pSprite = thisDev->spriteInfo->sprite;
43944642e01fSmrg    BOOL sendCore = FALSE;
43954642e01fSmrg
43964642e01fSmrg    grabinfo = &thisDev->deviceGrab;
43974642e01fSmrg    grab = grabinfo->grab;
439805b261ecSmrg
439935c4bbdfSmrg    if (grab->ownerEvents) {
440035c4bbdfSmrg        WindowPtr focus;
440105b261ecSmrg
44024642e01fSmrg        /* Hack: Some pointer device have a focus class. So we need to check
44034642e01fSmrg         * for the type of event, to see if we really want to deliver it to
44044642e01fSmrg         * the focus window. For pointer events, the answer is no.
44054642e01fSmrg         */
44066747b715Smrg        if (IsPointerEvent(event))
44074642e01fSmrg            focus = PointerRootWin;
440835c4bbdfSmrg        else if (thisDev->focus) {
440935c4bbdfSmrg            focus = thisDev->focus->win;
441035c4bbdfSmrg            if (focus == FollowKeyboardWin)
441135c4bbdfSmrg                focus = inputInfo.keyboard->focus->win;
441235c4bbdfSmrg        }
441335c4bbdfSmrg        else
441435c4bbdfSmrg            focus = PointerRootWin;
441535c4bbdfSmrg        if (focus == PointerRootWin)
441635c4bbdfSmrg            deliveries = DeliverDeviceEvents(pSprite->win, event, grab,
44176747b715Smrg                                             NullWindow, thisDev);
441835c4bbdfSmrg        else if (focus && (focus == pSprite->win ||
441935c4bbdfSmrg                           IsParent(focus, pSprite->win)))
442035c4bbdfSmrg            deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus,
442135c4bbdfSmrg                                             thisDev);
442235c4bbdfSmrg        else if (focus)
442335c4bbdfSmrg            deliveries = DeliverDeviceEvents(focus, event, grab, focus,
442435c4bbdfSmrg                                             thisDev);
442535c4bbdfSmrg    }
442635c4bbdfSmrg    if (!deliveries) {
44276747b715Smrg        sendCore = (IsMaster(thisDev) && thisDev->coreEvents);
44286747b715Smrg        /* try core event */
442935c4bbdfSmrg        if ((sendCore && grab->grabtype == CORE) || grab->grabtype != CORE)
443035c4bbdfSmrg            deliveries = DeliverOneGrabbedEvent(event, thisDev, grab->grabtype);
44316747b715Smrg
44326747b715Smrg        if (deliveries && (event->any.type == ET_Motion))
44334642e01fSmrg            thisDev->valuator->motionHintWindow = grab->window;
443405b261ecSmrg    }
443535c4bbdfSmrg    if (deliveries && !deactivateGrab &&
443635c4bbdfSmrg        (event->any.type == ET_KeyPress ||
443735c4bbdfSmrg         event->any.type == ET_KeyRelease ||
443835c4bbdfSmrg         event->any.type == ET_ButtonPress ||
443935c4bbdfSmrg         event->any.type == ET_ButtonRelease)) {
44405a112b11Smrg        FreezeThisEventIfNeededForSyncGrab(thisDev, event);
444105b261ecSmrg    }
444205b261ecSmrg
444335c4bbdfSmrg    return deliveries;
44446747b715Smrg}
444505b261ecSmrg
44465a112b11Smrgvoid
44475a112b11SmrgFreezeThisEventIfNeededForSyncGrab(DeviceIntPtr thisDev, InternalEvent *event)
44485a112b11Smrg{
44495a112b11Smrg    GrabInfoPtr grabinfo = &thisDev->deviceGrab;
44505a112b11Smrg    GrabPtr grab = grabinfo->grab;
44515a112b11Smrg    DeviceIntPtr dev;
44525a112b11Smrg
44535a112b11Smrg    switch (grabinfo->sync.state) {
44545a112b11Smrg    case FREEZE_BOTH_NEXT_EVENT:
44555a112b11Smrg        dev = GetPairedDevice(thisDev);
44565a112b11Smrg        if (dev) {
44575a112b11Smrg            FreezeThaw(dev, TRUE);
44585a112b11Smrg            if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) &&
44595a112b11Smrg                (CLIENT_BITS(grab->resource) ==
44605a112b11Smrg                 CLIENT_BITS(dev->deviceGrab.grab->resource)))
44615a112b11Smrg                dev->deviceGrab.sync.state = FROZEN_NO_EVENT;
44625a112b11Smrg            else
44635a112b11Smrg                dev->deviceGrab.sync.other = grab;
44645a112b11Smrg        }
44655a112b11Smrg        /* fall through */
44665a112b11Smrg    case FREEZE_NEXT_EVENT:
44675a112b11Smrg        grabinfo->sync.state = FROZEN_WITH_EVENT;
44685a112b11Smrg        FreezeThaw(thisDev, TRUE);
446990bea6a0Smrg        CopyPartialInternalEvent(grabinfo->sync.event, event);
44705a112b11Smrg        break;
44715a112b11Smrg    }
44725a112b11Smrg}
44735a112b11Smrg
44746747b715Smrg/* This function is used to set the key pressed or key released state -
44756747b715Smrg   this is only used when the pressing of keys does not cause
44766747b715Smrg   the device's processInputProc to be called, as in for example Mouse Keys.
44776747b715Smrg*/
44786747b715Smrgvoid
447935c4bbdfSmrgFixKeyState(DeviceEvent *event, DeviceIntPtr keybd)
44806747b715Smrg{
44816747b715Smrg    int key = event->detail.key;
44826747b715Smrg
44836747b715Smrg    if (event->type == ET_KeyPress) {
448435c4bbdfSmrg        DebugF("FixKeyState: Key %d %s\n", key,
44856747b715Smrg               ((event->type == ET_KeyPress) ? "down" : "up"));
448605b261ecSmrg    }
44874642e01fSmrg
44886747b715Smrg    if (event->type == ET_KeyPress)
44896747b715Smrg        set_key_down(keybd, key, KEY_PROCESSED);
44906747b715Smrg    else if (event->type == ET_KeyRelease)
44916747b715Smrg        set_key_up(keybd, key, KEY_PROCESSED);
449205b261ecSmrg    else
44936747b715Smrg        FatalError("Impossible keyboard event");
449405b261ecSmrg}
449505b261ecSmrg
449605b261ecSmrg#define AtMostOneClient \
449705b261ecSmrg	(SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
44984642e01fSmrg#define ManagerMask \
44994642e01fSmrg	(SubstructureRedirectMask | ResizeRedirectMask)
450005b261ecSmrg
450105b261ecSmrg/**
450205b261ecSmrg * Recalculate which events may be deliverable for the given window.
450305b261ecSmrg * Recalculated mask is used for quicker determination which events may be
450405b261ecSmrg * delivered to a window.
450505b261ecSmrg *
450605b261ecSmrg * The otherEventMasks on a WindowOptional is the combination of all event
450705b261ecSmrg * masks set by all clients on the window.
450805b261ecSmrg * deliverableEventMask is the combination of the eventMask and the
45096747b715Smrg * otherEventMask plus the events that may be propagated to the parent.
451005b261ecSmrg *
451105b261ecSmrg * Traverses to siblings and parents of the window.
451205b261ecSmrg */
451305b261ecSmrgvoid
45146747b715SmrgRecalculateDeliverableEvents(WindowPtr pWin)
451505b261ecSmrg{
451605b261ecSmrg    OtherClients *others;
451705b261ecSmrg    WindowPtr pChild;
451805b261ecSmrg
451905b261ecSmrg    pChild = pWin;
452035c4bbdfSmrg    while (1) {
452135c4bbdfSmrg        if (pChild->optional) {
452235c4bbdfSmrg            pChild->optional->otherEventMasks = 0;
452335c4bbdfSmrg            for (others = wOtherClients(pChild); others; others = others->next) {
452435c4bbdfSmrg                pChild->optional->otherEventMasks |= others->mask;
452535c4bbdfSmrg            }
452635c4bbdfSmrg        }
452735c4bbdfSmrg        pChild->deliverableEvents = pChild->eventMask |
452835c4bbdfSmrg            wOtherEventMasks(pChild);
452935c4bbdfSmrg        if (pChild->parent)
453035c4bbdfSmrg            pChild->deliverableEvents |=
453135c4bbdfSmrg                (pChild->parent->deliverableEvents &
453235c4bbdfSmrg                 ~wDontPropagateMask(pChild) & PropagateMask);
453335c4bbdfSmrg        if (pChild->firstChild) {
453435c4bbdfSmrg            pChild = pChild->firstChild;
453535c4bbdfSmrg            continue;
453635c4bbdfSmrg        }
453735c4bbdfSmrg        while (!pChild->nextSib && (pChild != pWin))
453835c4bbdfSmrg            pChild = pChild->parent;
453935c4bbdfSmrg        if (pChild == pWin)
454035c4bbdfSmrg            break;
454135c4bbdfSmrg        pChild = pChild->nextSib;
454205b261ecSmrg    }
454305b261ecSmrg}
454405b261ecSmrg
454505b261ecSmrg/**
454605b261ecSmrg *
454705b261ecSmrg *  \param value must conform to DeleteType
454805b261ecSmrg */
454905b261ecSmrgint
455035c4bbdfSmrgOtherClientGone(void *value, XID id)
455105b261ecSmrg{
455205b261ecSmrg    OtherClientsPtr other, prev;
455335c4bbdfSmrg    WindowPtr pWin = (WindowPtr) value;
455405b261ecSmrg
455505b261ecSmrg    prev = 0;
455635c4bbdfSmrg    for (other = wOtherClients(pWin); other; other = other->next) {
455735c4bbdfSmrg        if (other->resource == id) {
455835c4bbdfSmrg            if (prev)
455935c4bbdfSmrg                prev->next = other->next;
456035c4bbdfSmrg            else {
456135c4bbdfSmrg                if (!(pWin->optional->otherClients = other->next))
456235c4bbdfSmrg                    CheckWindowOptionalNeed(pWin);
456335c4bbdfSmrg            }
456435c4bbdfSmrg            free(other);
456535c4bbdfSmrg            RecalculateDeliverableEvents(pWin);
456635c4bbdfSmrg            return Success;
456735c4bbdfSmrg        }
456835c4bbdfSmrg        prev = other;
456905b261ecSmrg    }
457005b261ecSmrg    FatalError("client not on event list");
457105b261ecSmrg}
457205b261ecSmrg
457305b261ecSmrgint
457405b261ecSmrgEventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
457505b261ecSmrg{
457605b261ecSmrg    Mask check;
457735c4bbdfSmrg    OtherClients *others;
45784642e01fSmrg    DeviceIntPtr dev;
45794642e01fSmrg    int rc;
458005b261ecSmrg
458135c4bbdfSmrg    if (mask & ~AllEventMasks) {
458235c4bbdfSmrg        client->errorValue = mask;
458335c4bbdfSmrg        return BadValue;
458405b261ecSmrg    }
45854642e01fSmrg    check = (mask & ManagerMask);
45864642e01fSmrg    if (check) {
458735c4bbdfSmrg        rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id,
458835c4bbdfSmrg                      RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess);
458935c4bbdfSmrg        if (rc != Success)
459035c4bbdfSmrg            return rc;
45914642e01fSmrg    }
459205b261ecSmrg    check = (mask & AtMostOneClient);
459335c4bbdfSmrg    if (check & (pWin->eventMask | wOtherEventMasks(pWin))) {
459435c4bbdfSmrg        /* It is illegal for two different clients to select on any of the
459535c4bbdfSmrg           events for AtMostOneClient. However, it is OK, for some client to
459635c4bbdfSmrg           continue selecting on one of those events.  */
459735c4bbdfSmrg        if ((wClient(pWin) != client) && (check & pWin->eventMask))
459835c4bbdfSmrg            return BadAccess;
459935c4bbdfSmrg        for (others = wOtherClients(pWin); others; others = others->next) {
460035c4bbdfSmrg            if (!SameClient(others, client) && (check & others->mask))
460135c4bbdfSmrg                return BadAccess;
460235c4bbdfSmrg        }
460305b261ecSmrg    }
460435c4bbdfSmrg    if (wClient(pWin) == client) {
460535c4bbdfSmrg        check = pWin->eventMask;
460635c4bbdfSmrg        pWin->eventMask = mask;
460735c4bbdfSmrg    }
460835c4bbdfSmrg    else {
460935c4bbdfSmrg        for (others = wOtherClients(pWin); others; others = others->next) {
461035c4bbdfSmrg            if (SameClient(others, client)) {
461135c4bbdfSmrg                check = others->mask;
461235c4bbdfSmrg                if (mask == 0) {
461335c4bbdfSmrg                    FreeResource(others->resource, RT_NONE);
461435c4bbdfSmrg                    return Success;
461535c4bbdfSmrg                }
461635c4bbdfSmrg                else
461735c4bbdfSmrg                    others->mask = mask;
461835c4bbdfSmrg                goto maskSet;
461935c4bbdfSmrg            }
462035c4bbdfSmrg        }
462135c4bbdfSmrg        check = 0;
462235c4bbdfSmrg        if (!pWin->optional && !MakeWindowOptional(pWin))
462335c4bbdfSmrg            return BadAlloc;
462435c4bbdfSmrg        others = malloc(sizeof(OtherClients));
462535c4bbdfSmrg        if (!others)
462635c4bbdfSmrg            return BadAlloc;
462735c4bbdfSmrg        others->mask = mask;
462835c4bbdfSmrg        others->resource = FakeClientID(client->index);
462935c4bbdfSmrg        others->next = pWin->optional->otherClients;
463035c4bbdfSmrg        pWin->optional->otherClients = others;
463135c4bbdfSmrg        if (!AddResource(others->resource, RT_OTHERCLIENT, (void *) pWin))
463235c4bbdfSmrg            return BadAlloc;
463335c4bbdfSmrg    }
463435c4bbdfSmrg maskSet:
463535c4bbdfSmrg    if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask)) {
463635c4bbdfSmrg        for (dev = inputInfo.devices; dev; dev = dev->next) {
46374642e01fSmrg            if (dev->valuator && dev->valuator->motionHintWindow == pWin)
46384642e01fSmrg                dev->valuator->motionHintWindow = NullWindow;
46394642e01fSmrg        }
46404642e01fSmrg    }
464105b261ecSmrg    RecalculateDeliverableEvents(pWin);
464205b261ecSmrg    return Success;
464305b261ecSmrg}
464405b261ecSmrg
464505b261ecSmrgint
46464642e01fSmrgEventSuppressForWindow(WindowPtr pWin, ClientPtr client,
464705b261ecSmrg                       Mask mask, Bool *checkOptional)
464805b261ecSmrg{
464935c4bbdfSmrg    int i, freed;
465005b261ecSmrg
465135c4bbdfSmrg    if (mask & ~PropagateMask) {
465235c4bbdfSmrg        client->errorValue = mask;
465335c4bbdfSmrg        return BadValue;
465405b261ecSmrg    }
465505b261ecSmrg    if (pWin->dontPropagate)
465635c4bbdfSmrg        DontPropagateRefCnts[pWin->dontPropagate]--;
465705b261ecSmrg    if (!mask)
465835c4bbdfSmrg        i = 0;
465935c4bbdfSmrg    else {
466035c4bbdfSmrg        for (i = DNPMCOUNT, freed = 0; --i > 0;) {
466135c4bbdfSmrg            if (!DontPropagateRefCnts[i])
466235c4bbdfSmrg                freed = i;
466335c4bbdfSmrg            else if (mask == DontPropagateMasks[i])
466435c4bbdfSmrg                break;
466535c4bbdfSmrg        }
466635c4bbdfSmrg        if (!i && freed) {
466735c4bbdfSmrg            i = freed;
466835c4bbdfSmrg            DontPropagateMasks[i] = mask;
466935c4bbdfSmrg        }
467005b261ecSmrg    }
467135c4bbdfSmrg    if (i || !mask) {
467235c4bbdfSmrg        pWin->dontPropagate = i;
467335c4bbdfSmrg        if (i)
467435c4bbdfSmrg            DontPropagateRefCnts[i]++;
467535c4bbdfSmrg        if (pWin->optional) {
467635c4bbdfSmrg            pWin->optional->dontPropagateMask = mask;
467735c4bbdfSmrg            *checkOptional = TRUE;
467835c4bbdfSmrg        }
467935c4bbdfSmrg    }
468035c4bbdfSmrg    else {
468135c4bbdfSmrg        if (!pWin->optional && !MakeWindowOptional(pWin)) {
468235c4bbdfSmrg            if (pWin->dontPropagate)
468335c4bbdfSmrg                DontPropagateRefCnts[pWin->dontPropagate]++;
468435c4bbdfSmrg            return BadAlloc;
468535c4bbdfSmrg        }
468635c4bbdfSmrg        pWin->dontPropagate = 0;
468705b261ecSmrg        pWin->optional->dontPropagateMask = mask;
468805b261ecSmrg    }
468905b261ecSmrg    RecalculateDeliverableEvents(pWin);
469005b261ecSmrg    return Success;
469105b261ecSmrg}
469205b261ecSmrg
469305b261ecSmrg/**
46944642e01fSmrg * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
46954642e01fSmrg * Uses the paired keyboard to get some additional information.
469605b261ecSmrg */
46974642e01fSmrgvoid
469835c4bbdfSmrgCoreEnterLeaveEvent(DeviceIntPtr mouse,
469935c4bbdfSmrg                    int type,
470035c4bbdfSmrg                    int mode, int detail, WindowPtr pWin, Window child)
470135c4bbdfSmrg{
470235c4bbdfSmrg    xEvent event = {
470335c4bbdfSmrg        .u.u.type = type,
470435c4bbdfSmrg        .u.u.detail = detail
470535c4bbdfSmrg    };
470635c4bbdfSmrg    WindowPtr focus;
470735c4bbdfSmrg    DeviceIntPtr keybd;
470835c4bbdfSmrg    GrabPtr grab = mouse->deviceGrab.grab;
470935c4bbdfSmrg    Mask mask;
471035c4bbdfSmrg
471135c4bbdfSmrg    keybd = GetMaster(mouse, KEYBOARD_OR_FLOAT);
47124642e01fSmrg
471305b261ecSmrg    if ((pWin == mouse->valuator->motionHintWindow) &&
471435c4bbdfSmrg        (detail != NotifyInferior))
471535c4bbdfSmrg        mouse->valuator->motionHintWindow = NullWindow;
471635c4bbdfSmrg    if (grab) {
471735c4bbdfSmrg        mask = (pWin == grab->window) ? grab->eventMask : 0;
471835c4bbdfSmrg        if (grab->ownerEvents)
471935c4bbdfSmrg            mask |= EventMaskForClient(pWin, rClient(grab));
472005b261ecSmrg    }
472135c4bbdfSmrg    else {
472235c4bbdfSmrg        mask = pWin->eventMask | wOtherEventMasks(pWin);
472305b261ecSmrg    }
47244642e01fSmrg
47254642e01fSmrg    event.u.enterLeave.time = currentTime.milliseconds;
47264642e01fSmrg    event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x;
47274642e01fSmrg    event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y;
47284642e01fSmrg    /* Counts on the same initial structure of crossing & button events! */
47299ace9065Smrg    FixUpEventFromWindow(mouse->spriteInfo->sprite, &event, pWin, None, FALSE);
47304642e01fSmrg    /* Enter/Leave events always set child */
47314642e01fSmrg    event.u.enterLeave.child = child;
47324642e01fSmrg    event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
47334642e01fSmrg        ELFlagSameScreen : 0;
473435c4bbdfSmrg    event.u.enterLeave.state =
473535c4bbdfSmrg        mouse->button ? (mouse->button->state & 0x1f00) : 0;
47366747b715Smrg    if (keybd)
47376747b715Smrg        event.u.enterLeave.state |=
473835c4bbdfSmrg            XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
47394642e01fSmrg    event.u.enterLeave.mode = mode;
47404642e01fSmrg    focus = (keybd) ? keybd->focus->win : None;
47414642e01fSmrg    if ((focus != NoneWin) &&
474235c4bbdfSmrg        ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin)))
47434642e01fSmrg        event.u.enterLeave.flags |= ELFlagFocus;
474405b261ecSmrg
474535c4bbdfSmrg    if ((mask & GetEventFilter(mouse, &event))) {
47464642e01fSmrg        if (grab)
47474642e01fSmrg            TryClientEvents(rClient(grab), mouse, &event, 1, mask,
47486747b715Smrg                            GetEventFilter(mouse, &event), grab);
47494642e01fSmrg        else
47504642e01fSmrg            DeliverEventsToWindow(mouse, pWin, &event, 1,
475135c4bbdfSmrg                                  GetEventFilter(mouse, &event), NullGrab);
475205b261ecSmrg    }
475305b261ecSmrg
475435c4bbdfSmrg    if ((type == EnterNotify) && (mask & KeymapStateMask)) {
475535c4bbdfSmrg        xKeymapEvent ke = {
475635c4bbdfSmrg            .type = KeymapNotify
475735c4bbdfSmrg        };
47586747b715Smrg        ClientPtr client = grab ? rClient(grab) : wClient(pWin);
475935c4bbdfSmrg        int rc;
476035c4bbdfSmrg
476135c4bbdfSmrg        rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess);
476235c4bbdfSmrg        if (rc == Success)
476335c4bbdfSmrg            memcpy((char *) &ke.map[0], (char *) &keybd->key->down[1], 31);
47644642e01fSmrg
47654642e01fSmrg        if (grab)
476635c4bbdfSmrg            TryClientEvents(rClient(grab), keybd, (xEvent *) &ke, 1,
47674642e01fSmrg                            mask, KeymapStateMask, grab);
47684642e01fSmrg        else
476935c4bbdfSmrg            DeliverEventsToWindow(mouse, pWin, (xEvent *) &ke, 1,
47706747b715Smrg                                  KeymapStateMask, NullGrab);
47716747b715Smrg    }
47726747b715Smrg}
47736747b715Smrg
47746747b715Smrgvoid
477535c4bbdfSmrgDeviceEnterLeaveEvent(DeviceIntPtr mouse,
477635c4bbdfSmrg                      int sourceid,
477735c4bbdfSmrg                      int type,
477835c4bbdfSmrg                      int mode, int detail, WindowPtr pWin, Window child)
477935c4bbdfSmrg{
478035c4bbdfSmrg    GrabPtr grab = mouse->deviceGrab.grab;
478135c4bbdfSmrg    xXIEnterEvent *event;
478235c4bbdfSmrg    WindowPtr focus;
478335c4bbdfSmrg    int filter;
478435c4bbdfSmrg    int btlen, len, i;
478535c4bbdfSmrg    DeviceIntPtr kbd;
47866747b715Smrg
47876747b715Smrg    if ((mode == XINotifyPassiveGrab && type == XI_Leave) ||
47886747b715Smrg        (mode == XINotifyPassiveUngrab && type == XI_Enter))
47896747b715Smrg        return;
47906747b715Smrg
47916747b715Smrg    btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
47926747b715Smrg    btlen = bytes_to_int32(btlen);
47936747b715Smrg    len = sizeof(xXIEnterEvent) + btlen * 4;
47946747b715Smrg
47956747b715Smrg    event = calloc(1, len);
479635c4bbdfSmrg    event->type = GenericEvent;
479735c4bbdfSmrg    event->extension = IReqCode;
479835c4bbdfSmrg    event->evtype = type;
479935c4bbdfSmrg    event->length = (len - sizeof(xEvent)) / 4;
480035c4bbdfSmrg    event->buttons_len = btlen;
480135c4bbdfSmrg    event->detail = detail;
480235c4bbdfSmrg    event->time = currentTime.milliseconds;
480335c4bbdfSmrg    event->deviceid = mouse->id;
480435c4bbdfSmrg    event->sourceid = sourceid;
480535c4bbdfSmrg    event->mode = mode;
480635c4bbdfSmrg    event->root_x = double_to_fp1616(mouse->spriteInfo->sprite->hot.x);
480735c4bbdfSmrg    event->root_y = double_to_fp1616(mouse->spriteInfo->sprite->hot.y);
48086747b715Smrg
48096747b715Smrg    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
48106747b715Smrg        if (BitIsOn(mouse->button->down, i))
48116747b715Smrg            SetBit(&event[1], i);
48126747b715Smrg
481335c4bbdfSmrg    kbd = GetMaster(mouse, MASTER_KEYBOARD);
481435c4bbdfSmrg    if (kbd && kbd->key) {
48156747b715Smrg        event->mods.base_mods = kbd->key->xkbInfo->state.base_mods;
48166747b715Smrg        event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods;
48176747b715Smrg        event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods;
48186747b715Smrg
48196747b715Smrg        event->group.base_group = kbd->key->xkbInfo->state.base_group;
48206747b715Smrg        event->group.latched_group = kbd->key->xkbInfo->state.latched_group;
48216747b715Smrg        event->group.locked_group = kbd->key->xkbInfo->state.locked_group;
482205b261ecSmrg    }
48236747b715Smrg
482435c4bbdfSmrg    focus = (kbd) ? kbd->focus->win : None;
482535c4bbdfSmrg    if ((focus != NoneWin) &&
482635c4bbdfSmrg        ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin)))
482735c4bbdfSmrg        event->focus = TRUE;
482835c4bbdfSmrg
482935c4bbdfSmrg    FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent *) event, pWin,
48309ace9065Smrg                         None, FALSE);
48316747b715Smrg
483235c4bbdfSmrg    filter = GetEventFilter(mouse, (xEvent *) event);
48336747b715Smrg
483435c4bbdfSmrg    if (grab && grab->grabtype == XI2) {
48356747b715Smrg        Mask mask;
483635c4bbdfSmrg
483735c4bbdfSmrg        mask = xi2mask_isset(grab->xi2mask, mouse, type);
483835c4bbdfSmrg        TryClientEvents(rClient(grab), mouse, (xEvent *) event, 1, mask, 1,
483935c4bbdfSmrg                        grab);
484035c4bbdfSmrg    }
484135c4bbdfSmrg    else {
484235c4bbdfSmrg        if (!WindowXI2MaskIsset(mouse, pWin, (xEvent *) event))
48436747b715Smrg            goto out;
484435c4bbdfSmrg        DeliverEventsToWindow(mouse, pWin, (xEvent *) event, 1, filter,
48456747b715Smrg                              NullGrab);
48466747b715Smrg    }
48476747b715Smrg
484835c4bbdfSmrg out:
48496747b715Smrg    free(event);
485005b261ecSmrg}
485105b261ecSmrg
48524642e01fSmrgvoid
48534642e01fSmrgCoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
485405b261ecSmrg{
485535c4bbdfSmrg    xEvent event = {
485635c4bbdfSmrg        .u.u.type = type,
485735c4bbdfSmrg        .u.u.detail = detail
485835c4bbdfSmrg    };
485905b261ecSmrg    event.u.focus.mode = mode;
486005b261ecSmrg    event.u.focus.window = pWin->drawable.id;
48616747b715Smrg
48626747b715Smrg    DeliverEventsToWindow(dev, pWin, &event, 1,
48636747b715Smrg                          GetEventFilter(dev, &event), NullGrab);
486405b261ecSmrg    if ((type == FocusIn) &&
486535c4bbdfSmrg        ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) {
486635c4bbdfSmrg        xKeymapEvent ke = {
486735c4bbdfSmrg            .type = KeymapNotify
486835c4bbdfSmrg        };
48696747b715Smrg        ClientPtr client = wClient(pWin);
487035c4bbdfSmrg        int rc;
487105b261ecSmrg
487235c4bbdfSmrg        rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess);
487335c4bbdfSmrg        if (rc == Success)
487435c4bbdfSmrg            memcpy((char *) &ke.map[0], (char *) &dev->key->down[1], 31);
487535c4bbdfSmrg
487635c4bbdfSmrg        DeliverEventsToWindow(dev, pWin, (xEvent *) &ke, 1,
487735c4bbdfSmrg                              KeymapStateMask, NullGrab);
487805b261ecSmrg    }
487905b261ecSmrg}
488005b261ecSmrg
488105b261ecSmrg/**
488205b261ecSmrg * Set the input focus to the given window. Subsequent keyboard events will be
488305b261ecSmrg * delivered to the given window.
48844642e01fSmrg *
488505b261ecSmrg * Usually called from ProcSetInputFocus as result of a client request. If so,
488605b261ecSmrg * the device is the inputInfo.keyboard.
488705b261ecSmrg * If called from ProcXSetInputFocus as result of a client xinput request, the
488805b261ecSmrg * device is set to the device specified by the client.
488905b261ecSmrg *
489005b261ecSmrg * @param client Client that requested input focus change.
48914642e01fSmrg * @param dev Focus device.
489205b261ecSmrg * @param focusID The window to obtain the focus. Can be PointerRoot or None.
489305b261ecSmrg * @param revertTo Specifies where the focus reverts to when window becomes
489405b261ecSmrg * unviewable.
489505b261ecSmrg * @param ctime Specifies the time.
489605b261ecSmrg * @param followOK True if pointer is allowed to follow the keyboard.
489705b261ecSmrg */
489805b261ecSmrgint
489935c4bbdfSmrgSetInputFocus(ClientPtr client,
490035c4bbdfSmrg              DeviceIntPtr dev,
490135c4bbdfSmrg              Window focusID, CARD8 revertTo, Time ctime, Bool followOK)
490205b261ecSmrg{
490305b261ecSmrg    FocusClassPtr focus;
490405b261ecSmrg    WindowPtr focusWin;
490505b261ecSmrg    int mode, rc;
490605b261ecSmrg    TimeStamp time;
490735c4bbdfSmrg    DeviceIntPtr keybd;         /* used for FollowKeyboard or FollowKeyboardWin */
490805b261ecSmrg
490905b261ecSmrg    UpdateCurrentTime();
491005b261ecSmrg    if ((revertTo != RevertToParent) &&
491135c4bbdfSmrg        (revertTo != RevertToPointerRoot) &&
491235c4bbdfSmrg        (revertTo != RevertToNone) &&
491335c4bbdfSmrg        ((revertTo != RevertToFollowKeyboard) || !followOK)) {
491435c4bbdfSmrg        client->errorValue = revertTo;
491535c4bbdfSmrg        return BadValue;
491605b261ecSmrg    }
491705b261ecSmrg    time = ClientTimeToServerTime(ctime);
49184642e01fSmrg
491935c4bbdfSmrg    keybd = GetMaster(dev, KEYBOARD_OR_FLOAT);
49204642e01fSmrg
492105b261ecSmrg    if ((focusID == None) || (focusID == PointerRoot))
492235c4bbdfSmrg        focusWin = (WindowPtr) (long) focusID;
492335c4bbdfSmrg    else if ((focusID == FollowKeyboard) && followOK) {
492435c4bbdfSmrg        focusWin = keybd->focus->win;
49254642e01fSmrg    }
492605b261ecSmrg    else {
492735c4bbdfSmrg        rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess);
492835c4bbdfSmrg        if (rc != Success)
492935c4bbdfSmrg            return rc;
493035c4bbdfSmrg        /* It is a match error to try to set the input focus to an
493135c4bbdfSmrg           unviewable window. */
493235c4bbdfSmrg        if (!focusWin->realized)
493335c4bbdfSmrg            return BadMatch;
493405b261ecSmrg    }
49354642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess);
49364642e01fSmrg    if (rc != Success)
493735c4bbdfSmrg        return Success;
49384642e01fSmrg
493905b261ecSmrg    focus = dev->focus;
494005b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
494135c4bbdfSmrg        (CompareTimeStamps(time, focus->time) == EARLIER))
494235c4bbdfSmrg        return Success;
49434642e01fSmrg    mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal;
494435c4bbdfSmrg    if (focus->win == FollowKeyboardWin) {
49456747b715Smrg        if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin))
49466747b715Smrg            DoFocusEvents(dev, keybd->focus->win, focusWin, mode);
494735c4bbdfSmrg    }
494835c4bbdfSmrg    else {
49496747b715Smrg        if (!ActivateFocusInGrab(dev, focus->win, focusWin))
49506747b715Smrg            DoFocusEvents(dev, focus->win, focusWin, mode);
49516747b715Smrg    }
495205b261ecSmrg    focus->time = time;
495305b261ecSmrg    focus->revert = revertTo;
495405b261ecSmrg    if (focusID == FollowKeyboard)
495535c4bbdfSmrg        focus->win = FollowKeyboardWin;
495605b261ecSmrg    else
495735c4bbdfSmrg        focus->win = focusWin;
495805b261ecSmrg    if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
495935c4bbdfSmrg        focus->traceGood = 0;
496035c4bbdfSmrg    else {
496105b261ecSmrg        int depth = 0;
496235c4bbdfSmrg        WindowPtr pWin;
496335c4bbdfSmrg
496435c4bbdfSmrg        for (pWin = focusWin; pWin; pWin = pWin->parent)
496535c4bbdfSmrg            depth++;
496635c4bbdfSmrg        if (depth > focus->traceSize) {
496735c4bbdfSmrg            focus->traceSize = depth + 1;
496835c4bbdfSmrg            focus->trace = reallocarray(focus->trace, focus->traceSize,
496935c4bbdfSmrg                                        sizeof(WindowPtr));
497035c4bbdfSmrg        }
497135c4bbdfSmrg        focus->traceGood = depth;
49724642e01fSmrg        for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
497335c4bbdfSmrg            focus->trace[depth] = pWin;
497405b261ecSmrg    }
497505b261ecSmrg    return Success;
497605b261ecSmrg}
497705b261ecSmrg
497805b261ecSmrg/**
497905b261ecSmrg * Server-side protocol handling for SetInputFocus request.
498005b261ecSmrg *
498105b261ecSmrg * Sets the input focus for the virtual core keyboard.
498205b261ecSmrg */
498305b261ecSmrgint
49846747b715SmrgProcSetInputFocus(ClientPtr client)
498505b261ecSmrg{
49864642e01fSmrg    DeviceIntPtr kbd = PickKeyboard(client);
498735c4bbdfSmrg
498805b261ecSmrg    REQUEST(xSetInputFocusReq);
498905b261ecSmrg
499005b261ecSmrg    REQUEST_SIZE_MATCH(xSetInputFocusReq);
499105b261ecSmrg
49924642e01fSmrg    return SetInputFocus(client, kbd, stuff->focus,
499335c4bbdfSmrg                         stuff->revertTo, stuff->time, FALSE);
499405b261ecSmrg}
499505b261ecSmrg
499605b261ecSmrg/**
499705b261ecSmrg * Server-side protocol handling for GetInputFocus request.
49984642e01fSmrg *
49994642e01fSmrg * Sends the current input focus for the client's keyboard back to the
500005b261ecSmrg * client.
500105b261ecSmrg */
500205b261ecSmrgint
500305b261ecSmrgProcGetInputFocus(ClientPtr client)
500405b261ecSmrg{
50054642e01fSmrg    DeviceIntPtr kbd = PickKeyboard(client);
500605b261ecSmrg    xGetInputFocusReply rep;
50074642e01fSmrg    FocusClassPtr focus = kbd->focus;
50084642e01fSmrg    int rc;
500935c4bbdfSmrg
501005b261ecSmrg    /* REQUEST(xReq); */
501105b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
50124642e01fSmrg
50134642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess);
50144642e01fSmrg    if (rc != Success)
501535c4bbdfSmrg        return rc;
501635c4bbdfSmrg
501735c4bbdfSmrg    rep = (xGetInputFocusReply) {
501835c4bbdfSmrg        .type = X_Reply,
501935c4bbdfSmrg        .length = 0,
502035c4bbdfSmrg        .sequenceNumber = client->sequence,
502135c4bbdfSmrg        .revertTo = focus->revert
502235c4bbdfSmrg    };
50234642e01fSmrg
502405b261ecSmrg    if (focus->win == NoneWin)
502535c4bbdfSmrg        rep.focus = None;
502605b261ecSmrg    else if (focus->win == PointerRootWin)
502735c4bbdfSmrg        rep.focus = PointerRoot;
502835c4bbdfSmrg    else
502935c4bbdfSmrg        rep.focus = focus->win->drawable.id;
503035c4bbdfSmrg
503105b261ecSmrg    WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
503205b261ecSmrg    return Success;
503305b261ecSmrg}
503405b261ecSmrg
503505b261ecSmrg/**
50364642e01fSmrg * Server-side protocol handling for GrabPointer request.
503705b261ecSmrg *
50384642e01fSmrg * Sets an active grab on the client's ClientPointer and returns success
50394642e01fSmrg * status to client.
504005b261ecSmrg */
504105b261ecSmrgint
504205b261ecSmrgProcGrabPointer(ClientPtr client)
504305b261ecSmrg{
504405b261ecSmrg    xGrabPointerReply rep;
50454642e01fSmrg    DeviceIntPtr device = PickPointer(client);
504605b261ecSmrg    GrabPtr grab;
50476747b715Smrg    GrabMask mask;
50486747b715Smrg    WindowPtr confineTo;
504935c4bbdfSmrg    BYTE status;
505035c4bbdfSmrg
505105b261ecSmrg    REQUEST(xGrabPointerReq);
505205b261ecSmrg    int rc;
505305b261ecSmrg
505405b261ecSmrg    REQUEST_SIZE_MATCH(xGrabPointerReq);
505505b261ecSmrg    UpdateCurrentTime();
50566747b715Smrg
505735c4bbdfSmrg    if (stuff->eventMask & ~PointerGrabMask) {
505835c4bbdfSmrg        client->errorValue = stuff->eventMask;
505905b261ecSmrg        return BadValue;
506005b261ecSmrg    }
50616747b715Smrg
506205b261ecSmrg    if (stuff->confineTo == None)
506335c4bbdfSmrg        confineTo = NullWindow;
506435c4bbdfSmrg    else {
506535c4bbdfSmrg        rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
506635c4bbdfSmrg                             DixSetAttrAccess);
506735c4bbdfSmrg        if (rc != Success)
506835c4bbdfSmrg            return rc;
506905b261ecSmrg    }
50706747b715Smrg
50716747b715Smrg    grab = device->deviceGrab.grab;
50726747b715Smrg
507335c4bbdfSmrg    if (grab && grab->confineTo && !confineTo)
507435c4bbdfSmrg        ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE, FALSE);
50756747b715Smrg
50766747b715Smrg    mask.core = stuff->eventMask;
50776747b715Smrg
50786747b715Smrg    rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode,
50796747b715Smrg                    stuff->grabWindow, stuff->ownerEvents, stuff->time,
508035c4bbdfSmrg                    &mask, CORE, stuff->cursor, stuff->confineTo, &status);
50814642e01fSmrg    if (rc != Success)
50826747b715Smrg        return rc;
50836747b715Smrg
508435c4bbdfSmrg    rep = (xGrabPointerReply) {
508535c4bbdfSmrg        .type = X_Reply,
508635c4bbdfSmrg        .status = status,
508735c4bbdfSmrg        .sequenceNumber = client->sequence,
508835c4bbdfSmrg        .length = 0
508935c4bbdfSmrg    };
509005b261ecSmrg    WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
509105b261ecSmrg    return Success;
509205b261ecSmrg}
509305b261ecSmrg
509405b261ecSmrg/**
509505b261ecSmrg * Server-side protocol handling for ChangeActivePointerGrab request.
509605b261ecSmrg *
509705b261ecSmrg * Changes properties of the grab hold by the client. If the client does not
50984642e01fSmrg * hold an active grab on the device, nothing happens.
509905b261ecSmrg */
510005b261ecSmrgint
510105b261ecSmrgProcChangeActivePointerGrab(ClientPtr client)
510205b261ecSmrg{
51034642e01fSmrg    DeviceIntPtr device;
510435c4bbdfSmrg    GrabPtr grab;
510505b261ecSmrg    CursorPtr newCursor, oldCursor;
510635c4bbdfSmrg
510705b261ecSmrg    REQUEST(xChangeActivePointerGrabReq);
510805b261ecSmrg    TimeStamp time;
510905b261ecSmrg
511005b261ecSmrg    REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
511135c4bbdfSmrg    if (stuff->eventMask & ~PointerGrabMask) {
511235c4bbdfSmrg        client->errorValue = stuff->eventMask;
511305b261ecSmrg        return BadValue;
511405b261ecSmrg    }
511505b261ecSmrg    if (stuff->cursor == None)
511635c4bbdfSmrg        newCursor = NullCursor;
511735c4bbdfSmrg    else {
511835c4bbdfSmrg        int rc = dixLookupResourceByType((void **) &newCursor, stuff->cursor,
511935c4bbdfSmrg                                         RT_CURSOR, client, DixUseAccess);
512035c4bbdfSmrg
512135c4bbdfSmrg        if (rc != Success) {
512235c4bbdfSmrg            client->errorValue = stuff->cursor;
512335c4bbdfSmrg            return rc;
512435c4bbdfSmrg        }
512505b261ecSmrg    }
51264642e01fSmrg
51274642e01fSmrg    device = PickPointer(client);
51284642e01fSmrg    grab = device->deviceGrab.grab;
51294642e01fSmrg
513005b261ecSmrg    if (!grab)
513135c4bbdfSmrg        return Success;
513205b261ecSmrg    if (!SameClient(grab, client))
513335c4bbdfSmrg        return Success;
51347e31ba66Smrg    UpdateCurrentTime();
513505b261ecSmrg    time = ClientTimeToServerTime(stuff->time);
513605b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
513735c4bbdfSmrg        (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
513835c4bbdfSmrg        return Success;
513905b261ecSmrg    oldCursor = grab->cursor;
514035c4bbdfSmrg    grab->cursor = RefCursor(newCursor);
51414642e01fSmrg    PostNewCursor(device);
514205b261ecSmrg    if (oldCursor)
514335c4bbdfSmrg        FreeCursor(oldCursor, (Cursor) 0);
514405b261ecSmrg    grab->eventMask = stuff->eventMask;
514505b261ecSmrg    return Success;
514605b261ecSmrg}
514705b261ecSmrg
514805b261ecSmrg/**
514905b261ecSmrg * Server-side protocol handling for UngrabPointer request.
515005b261ecSmrg *
51514642e01fSmrg * Deletes a pointer grab on a device the client has grabbed.
515205b261ecSmrg */
515305b261ecSmrgint
515405b261ecSmrgProcUngrabPointer(ClientPtr client)
515505b261ecSmrg{
51564642e01fSmrg    DeviceIntPtr device = PickPointer(client);
515705b261ecSmrg    GrabPtr grab;
515805b261ecSmrg    TimeStamp time;
515935c4bbdfSmrg
516005b261ecSmrg    REQUEST(xResourceReq);
516105b261ecSmrg
516205b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
516305b261ecSmrg    UpdateCurrentTime();
51644642e01fSmrg    grab = device->deviceGrab.grab;
51654642e01fSmrg
516605b261ecSmrg    time = ClientTimeToServerTime(stuff->id);
516705b261ecSmrg    if ((CompareTimeStamps(time, currentTime) != LATER) &&
516835c4bbdfSmrg        (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
516935c4bbdfSmrg        (grab) && SameClient(grab, client))
517035c4bbdfSmrg        (*device->deviceGrab.DeactivateGrab) (device);
517105b261ecSmrg    return Success;
517205b261ecSmrg}
517305b261ecSmrg
517405b261ecSmrg/**
517505b261ecSmrg * Sets a grab on the given device.
51764642e01fSmrg *
51774642e01fSmrg * Called from ProcGrabKeyboard to work on the client's keyboard.
517805b261ecSmrg * Called from ProcXGrabDevice to work on the device specified by the client.
51794642e01fSmrg *
518005b261ecSmrg * The parameters this_mode and other_mode represent the keyboard_mode and
51814642e01fSmrg * pointer_mode parameters of XGrabKeyboard().
518205b261ecSmrg * See man page for details on all the parameters
51834642e01fSmrg *
518405b261ecSmrg * @param client Client that owns the grab.
51854642e01fSmrg * @param dev The device to grab.
518605b261ecSmrg * @param this_mode GrabModeSync or GrabModeAsync
518705b261ecSmrg * @param other_mode GrabModeSync or GrabModeAsync
518805b261ecSmrg * @param status Return code to be returned to the caller.
51894642e01fSmrg *
519035c4bbdfSmrg * @returns Success or BadValue or BadAlloc.
519105b261ecSmrg */
519205b261ecSmrgint
51934642e01fSmrgGrabDevice(ClientPtr client, DeviceIntPtr dev,
51946747b715Smrg           unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow,
51956747b715Smrg           unsigned ownerEvents, Time ctime, GrabMask *mask,
51966747b715Smrg           int grabtype, Cursor curs, Window confineToWin, CARD8 *status)
519705b261ecSmrg{
51986747b715Smrg    WindowPtr pWin, confineTo;
519905b261ecSmrg    GrabPtr grab;
520005b261ecSmrg    TimeStamp time;
52014642e01fSmrg    Mask access_mode = DixGrabAccess;
520205b261ecSmrg    int rc;
52034642e01fSmrg    GrabInfoPtr grabInfo = &dev->deviceGrab;
52046747b715Smrg    CursorPtr cursor;
520505b261ecSmrg
520605b261ecSmrg    UpdateCurrentTime();
520735c4bbdfSmrg    if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync)) {
520835c4bbdfSmrg        client->errorValue = keyboard_mode;
520905b261ecSmrg        return BadValue;
521005b261ecSmrg    }
521135c4bbdfSmrg    if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync)) {
521235c4bbdfSmrg        client->errorValue = pointer_mode;
521305b261ecSmrg        return BadValue;
521405b261ecSmrg    }
521535c4bbdfSmrg    if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) {
521635c4bbdfSmrg        client->errorValue = ownerEvents;
521705b261ecSmrg        return BadValue;
521805b261ecSmrg    }
52194642e01fSmrg
52204642e01fSmrg    rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
522105b261ecSmrg    if (rc != Success)
522235c4bbdfSmrg        return rc;
52236747b715Smrg
52246747b715Smrg    if (confineToWin == None)
522535c4bbdfSmrg        confineTo = NullWindow;
522635c4bbdfSmrg    else {
522735c4bbdfSmrg        rc = dixLookupWindow(&confineTo, confineToWin, client,
522835c4bbdfSmrg                             DixSetAttrAccess);
522935c4bbdfSmrg        if (rc != Success)
523035c4bbdfSmrg            return rc;
52316747b715Smrg    }
52326747b715Smrg
52336747b715Smrg    if (curs == None)
523435c4bbdfSmrg        cursor = NullCursor;
523535c4bbdfSmrg    else {
523635c4bbdfSmrg        rc = dixLookupResourceByType((void **) &cursor, curs, RT_CURSOR,
523735c4bbdfSmrg                                     client, DixUseAccess);
523835c4bbdfSmrg        if (rc != Success) {
523935c4bbdfSmrg            client->errorValue = curs;
524035c4bbdfSmrg            return rc;
524135c4bbdfSmrg        }
524235c4bbdfSmrg        access_mode |= DixForceAccess;
52436747b715Smrg    }
52446747b715Smrg
52456747b715Smrg    if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync)
524635c4bbdfSmrg        access_mode |= DixFreezeAccess;
52474642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
52484642e01fSmrg    if (rc != Success)
524935c4bbdfSmrg        return rc;
52504642e01fSmrg
525105b261ecSmrg    time = ClientTimeToServerTime(ctime);
52524642e01fSmrg    grab = grabInfo->grab;
52536747b715Smrg    if (grab && grab->grabtype != grabtype)
52546747b715Smrg        *status = AlreadyGrabbed;
525535c4bbdfSmrg    else if (grab && !SameClient(grab, client))
525635c4bbdfSmrg        *status = AlreadyGrabbed;
52576747b715Smrg    else if ((!pWin->realized) ||
52586747b715Smrg             (confineTo &&
525935c4bbdfSmrg              !(confineTo->realized && BorderSizeNotEmpty(dev, confineTo))))
526035c4bbdfSmrg        *status = GrabNotViewable;
526105b261ecSmrg    else if ((CompareTimeStamps(time, currentTime) == LATER) ||
526235c4bbdfSmrg             (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER))
526335c4bbdfSmrg        *status = GrabInvalidTime;
52644642e01fSmrg    else if (grabInfo->sync.frozen &&
526535c4bbdfSmrg             grabInfo->sync.other && !SameClient(grabInfo->sync.other, client))
526635c4bbdfSmrg        *status = GrabFrozen;
526735c4bbdfSmrg    else {
526835c4bbdfSmrg        GrabPtr tempGrab;
526935c4bbdfSmrg
527035c4bbdfSmrg        tempGrab = AllocGrab(NULL);
527135c4bbdfSmrg        if (tempGrab == NULL)
527235c4bbdfSmrg            return BadAlloc;
527335c4bbdfSmrg
527435c4bbdfSmrg        tempGrab->next = NULL;
527535c4bbdfSmrg        tempGrab->window = pWin;
527635c4bbdfSmrg        tempGrab->resource = client->clientAsMask;
527735c4bbdfSmrg        tempGrab->ownerEvents = ownerEvents;
527835c4bbdfSmrg        tempGrab->keyboardMode = keyboard_mode;
527935c4bbdfSmrg        tempGrab->pointerMode = pointer_mode;
528035c4bbdfSmrg        if (grabtype == CORE)
528135c4bbdfSmrg            tempGrab->eventMask = mask->core;
528235c4bbdfSmrg        else if (grabtype == XI)
528335c4bbdfSmrg            tempGrab->eventMask = mask->xi;
528435c4bbdfSmrg        else
528535c4bbdfSmrg            xi2mask_merge(tempGrab->xi2mask, mask->xi2mask);
528635c4bbdfSmrg        tempGrab->device = dev;
528735c4bbdfSmrg        tempGrab->cursor = RefCursor(cursor);
528835c4bbdfSmrg        tempGrab->confineTo = confineTo;
528935c4bbdfSmrg        tempGrab->grabtype = grabtype;
529035c4bbdfSmrg        (*grabInfo->ActivateGrab) (dev, tempGrab, time, FALSE);
529135c4bbdfSmrg        *status = GrabSuccess;
529235c4bbdfSmrg
529335c4bbdfSmrg        FreeGrab(tempGrab);
529405b261ecSmrg    }
529505b261ecSmrg    return Success;
529605b261ecSmrg}
529705b261ecSmrg
529805b261ecSmrg/**
529905b261ecSmrg * Server-side protocol handling for GrabKeyboard request.
530005b261ecSmrg *
53014642e01fSmrg * Grabs the client's keyboard and returns success status to client.
530205b261ecSmrg */
530305b261ecSmrgint
530405b261ecSmrgProcGrabKeyboard(ClientPtr client)
530505b261ecSmrg{
530605b261ecSmrg    xGrabKeyboardReply rep;
530735c4bbdfSmrg    BYTE status;
530835c4bbdfSmrg
530905b261ecSmrg    REQUEST(xGrabKeyboardReq);
531005b261ecSmrg    int result;
53114642e01fSmrg    DeviceIntPtr keyboard = PickKeyboard(client);
53126747b715Smrg    GrabMask mask;
531305b261ecSmrg
531405b261ecSmrg    REQUEST_SIZE_MATCH(xGrabKeyboardReq);
53157e31ba66Smrg    UpdateCurrentTime();
531605b261ecSmrg
53176747b715Smrg    mask.core = KeyPressMask | KeyReleaseMask;
53186747b715Smrg
53196747b715Smrg    result = GrabDevice(client, keyboard, stuff->pointerMode,
532035c4bbdfSmrg                        stuff->keyboardMode, stuff->grabWindow,
532135c4bbdfSmrg                        stuff->ownerEvents, stuff->time, &mask, CORE, None,
532235c4bbdfSmrg                        None, &status);
532305b261ecSmrg
532405b261ecSmrg    if (result != Success)
532535c4bbdfSmrg        return result;
532635c4bbdfSmrg
532735c4bbdfSmrg    rep = (xGrabKeyboardReply) {
532835c4bbdfSmrg        .type = X_Reply,
532935c4bbdfSmrg        .status = status,
533035c4bbdfSmrg        .sequenceNumber = client->sequence,
533135c4bbdfSmrg        .length = 0
533235c4bbdfSmrg    };
533305b261ecSmrg    WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
533405b261ecSmrg    return Success;
533505b261ecSmrg}
533605b261ecSmrg
533705b261ecSmrg/**
533805b261ecSmrg * Server-side protocol handling for UngrabKeyboard request.
533905b261ecSmrg *
53404642e01fSmrg * Deletes a possible grab on the client's keyboard.
534105b261ecSmrg */
534205b261ecSmrgint
534305b261ecSmrgProcUngrabKeyboard(ClientPtr client)
534405b261ecSmrg{
53454642e01fSmrg    DeviceIntPtr device = PickKeyboard(client);
534605b261ecSmrg    GrabPtr grab;
534705b261ecSmrg    TimeStamp time;
534835c4bbdfSmrg
534905b261ecSmrg    REQUEST(xResourceReq);
535005b261ecSmrg
535105b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
535205b261ecSmrg    UpdateCurrentTime();
53534642e01fSmrg
53544642e01fSmrg    grab = device->deviceGrab.grab;
53554642e01fSmrg
535605b261ecSmrg    time = ClientTimeToServerTime(stuff->id);
535705b261ecSmrg    if ((CompareTimeStamps(time, currentTime) != LATER) &&
535835c4bbdfSmrg        (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
535935c4bbdfSmrg        (grab) && SameClient(grab, client) && grab->grabtype == CORE)
536035c4bbdfSmrg        (*device->deviceGrab.DeactivateGrab) (device);
536105b261ecSmrg    return Success;
536205b261ecSmrg}
536305b261ecSmrg
536405b261ecSmrg/**
536505b261ecSmrg * Server-side protocol handling for QueryPointer request.
536605b261ecSmrg *
53674642e01fSmrg * Returns the current state and position of the client's ClientPointer to the
53684642e01fSmrg * client.
536905b261ecSmrg */
537005b261ecSmrgint
537105b261ecSmrgProcQueryPointer(ClientPtr client)
537205b261ecSmrg{
537305b261ecSmrg    xQueryPointerReply rep;
537405b261ecSmrg    WindowPtr pWin, t;
53754642e01fSmrg    DeviceIntPtr mouse = PickPointer(client);
53766747b715Smrg    DeviceIntPtr keyboard;
53774642e01fSmrg    SpritePtr pSprite;
537805b261ecSmrg    int rc;
537935c4bbdfSmrg
53804642e01fSmrg    REQUEST(xResourceReq);
538105b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
53824642e01fSmrg
53834642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
53844642e01fSmrg    if (rc != Success)
538535c4bbdfSmrg        return rc;
53864642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
53876747b715Smrg    if (rc != Success && rc != BadAccess)
538835c4bbdfSmrg        return rc;
53894642e01fSmrg
539035c4bbdfSmrg    keyboard = GetMaster(mouse, MASTER_KEYBOARD);
53916747b715Smrg
53924642e01fSmrg    pSprite = mouse->spriteInfo->sprite;
539305b261ecSmrg    if (mouse->valuator->motionHintWindow)
539435c4bbdfSmrg        MaybeStopHint(mouse, client);
539535c4bbdfSmrg    rep = (xQueryPointerReply) {
539635c4bbdfSmrg        .type = X_Reply,
539735c4bbdfSmrg        .sequenceNumber = client->sequence,
539835c4bbdfSmrg        .length = 0,
539935c4bbdfSmrg        .mask = event_get_corestate(mouse, keyboard),
540035c4bbdfSmrg        .root = (GetCurrentRootWindow(mouse))->drawable.id,
540135c4bbdfSmrg        .rootX = pSprite->hot.x,
540235c4bbdfSmrg        .rootY = pSprite->hot.y,
540335c4bbdfSmrg        .child = None
540435c4bbdfSmrg    };
540535c4bbdfSmrg    if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
540635c4bbdfSmrg        rep.sameScreen = xTrue;
540735c4bbdfSmrg        rep.winX = pSprite->hot.x - pWin->drawable.x;
540835c4bbdfSmrg        rep.winY = pSprite->hot.y - pWin->drawable.y;
540935c4bbdfSmrg        for (t = pSprite->win; t; t = t->parent)
541035c4bbdfSmrg            if (t->parent == pWin) {
541135c4bbdfSmrg                rep.child = t->drawable.id;
541235c4bbdfSmrg                break;
541335c4bbdfSmrg            }
541405b261ecSmrg    }
541535c4bbdfSmrg    else {
541635c4bbdfSmrg        rep.sameScreen = xFalse;
541735c4bbdfSmrg        rep.winX = 0;
541835c4bbdfSmrg        rep.winY = 0;
541905b261ecSmrg    }
542005b261ecSmrg
542105b261ecSmrg#ifdef PANORAMIX
542235c4bbdfSmrg    if (!noPanoramiXExtension) {
542335c4bbdfSmrg        rep.rootX += screenInfo.screens[0]->x;
542435c4bbdfSmrg        rep.rootY += screenInfo.screens[0]->y;
542535c4bbdfSmrg        if (stuff->id == rep.root) {
542635c4bbdfSmrg            rep.winX += screenInfo.screens[0]->x;
542735c4bbdfSmrg            rep.winY += screenInfo.screens[0]->y;
542835c4bbdfSmrg        }
542905b261ecSmrg    }
543005b261ecSmrg#endif
543105b261ecSmrg
54326747b715Smrg    if (rc == BadAccess) {
543335c4bbdfSmrg        rep.mask = 0;
543435c4bbdfSmrg        rep.child = None;
543535c4bbdfSmrg        rep.rootX = 0;
543635c4bbdfSmrg        rep.rootY = 0;
543735c4bbdfSmrg        rep.winX = 0;
543835c4bbdfSmrg        rep.winY = 0;
54396747b715Smrg    }
54406747b715Smrg
544105b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
544205b261ecSmrg
54436747b715Smrg    return Success;
544405b261ecSmrg}
544505b261ecSmrg
544605b261ecSmrg/**
544705b261ecSmrg * Initializes the device list and the DIX sprite to sane values. Allocates
544805b261ecSmrg * trace memory used for quick window traversal.
544905b261ecSmrg */
545005b261ecSmrgvoid
545105b261ecSmrgInitEvents(void)
545205b261ecSmrg{
545305b261ecSmrg    int i;
545435c4bbdfSmrg    QdEventPtr qe, tmp;
545505b261ecSmrg
545605b261ecSmrg    inputInfo.numDevices = 0;
545735c4bbdfSmrg    inputInfo.devices = (DeviceIntPtr) NULL;
545835c4bbdfSmrg    inputInfo.off_devices = (DeviceIntPtr) NULL;
545935c4bbdfSmrg    inputInfo.keyboard = (DeviceIntPtr) NULL;
546035c4bbdfSmrg    inputInfo.pointer = (DeviceIntPtr) NULL;
546135c4bbdfSmrg
546235c4bbdfSmrg    for (i = 0; i < MAXDEVICES; i++) {
546335c4bbdfSmrg        DeviceIntRec dummy;
546435c4bbdfSmrg        memcpy(&event_filters[i], default_filter, sizeof(default_filter));
546535c4bbdfSmrg
546635c4bbdfSmrg        dummy.id = i;
546735c4bbdfSmrg        NoticeTime(&dummy, currentTime);
546835c4bbdfSmrg        LastEventTimeToggleResetFlag(i, FALSE);
546905b261ecSmrg    }
54704642e01fSmrg
547135c4bbdfSmrg    syncEvents.replayDev = (DeviceIntPtr) NULL;
547205b261ecSmrg    syncEvents.replayWin = NullWindow;
547335c4bbdfSmrg    if (syncEvents.pending.next)
547435c4bbdfSmrg        xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next)
547535c4bbdfSmrg            free(qe);
547635c4bbdfSmrg    xorg_list_init(&syncEvents.pending);
547705b261ecSmrg    syncEvents.playingEvents = FALSE;
547805b261ecSmrg    syncEvents.time.months = 0;
547935c4bbdfSmrg    syncEvents.time.milliseconds = 0;   /* hardly matters */
548005b261ecSmrg    currentTime.months = 0;
548105b261ecSmrg    currentTime.milliseconds = GetTimeInMillis();
548235c4bbdfSmrg    for (i = 0; i < DNPMCOUNT; i++) {
548335c4bbdfSmrg        DontPropagateMasks[i] = 0;
548435c4bbdfSmrg        DontPropagateRefCnts[i] = 0;
548505b261ecSmrg    }
54864642e01fSmrg
548735c4bbdfSmrg    InputEventList = InitEventList(GetMaximumEventsNum());
54884642e01fSmrg    if (!InputEventList)
54894642e01fSmrg        FatalError("[dix] Failed to allocate input event list.\n");
549005b261ecSmrg}
549105b261ecSmrg
549205b261ecSmrgvoid
549305b261ecSmrgCloseDownEvents(void)
549405b261ecSmrg{
549535c4bbdfSmrg    FreeEventList(InputEventList, GetMaximumEventsNum());
54966747b715Smrg    InputEventList = NULL;
549705b261ecSmrg}
549805b261ecSmrg
5499475c125cSmrg#define SEND_EVENT_BIT 0x80
5500475c125cSmrg
550105b261ecSmrg/**
550205b261ecSmrg * Server-side protocol handling for SendEvent request.
550305b261ecSmrg *
55044642e01fSmrg * Locates the window to send the event to and forwards the event.
550505b261ecSmrg */
550605b261ecSmrgint
550705b261ecSmrgProcSendEvent(ClientPtr client)
550805b261ecSmrg{
550905b261ecSmrg    WindowPtr pWin;
551035c4bbdfSmrg    WindowPtr effectiveFocus = NullWindow;      /* only set if dest==InputFocus */
55116747b715Smrg    DeviceIntPtr dev = PickPointer(client);
551235c4bbdfSmrg    DeviceIntPtr keybd = GetMaster(dev, MASTER_KEYBOARD);
55136747b715Smrg    SpritePtr pSprite = dev->spriteInfo->sprite;
551435c4bbdfSmrg
551505b261ecSmrg    REQUEST(xSendEventReq);
551605b261ecSmrg
551705b261ecSmrg    REQUEST_SIZE_MATCH(xSendEventReq);
551805b261ecSmrg
5519475c125cSmrg    /* libXext and other extension libraries may set the bit indicating
5520475c125cSmrg     * that this event came from a SendEvent request so remove it
5521475c125cSmrg     * since otherwise the event type may fail the range checks
5522475c125cSmrg     * and cause an invalid BadValue error to be returned.
5523475c125cSmrg     *
5524475c125cSmrg     * This is safe to do since we later add the SendEvent bit (0x80)
5525475c125cSmrg     * back in once we send the event to the client */
5526475c125cSmrg
5527475c125cSmrg    stuff->event.u.u.type &= ~(SEND_EVENT_BIT);
5528475c125cSmrg
552905b261ecSmrg    /* The client's event type must be a core event type or one defined by an
553035c4bbdfSmrg       extension. */
553105b261ecSmrg
553235c4bbdfSmrg    if (!((stuff->event.u.u.type > X_Reply &&
553335c4bbdfSmrg           stuff->event.u.u.type < LASTEvent) ||
553435c4bbdfSmrg          (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
553535c4bbdfSmrg           stuff->event.u.u.type < (unsigned) lastEvent))) {
553635c4bbdfSmrg        client->errorValue = stuff->event.u.u.type;
553735c4bbdfSmrg        return BadValue;
553805b261ecSmrg    }
55390679523aSmrg    /* Generic events can have variable size, but SendEvent request holds
55400679523aSmrg       exactly 32B of event data. */
55410679523aSmrg    if (stuff->event.u.u.type == GenericEvent) {
55420679523aSmrg        client->errorValue = stuff->event.u.u.type;
55430679523aSmrg        return BadValue;
55440679523aSmrg    }
554505b261ecSmrg    if (stuff->event.u.u.type == ClientMessage &&
554635c4bbdfSmrg        stuff->event.u.u.detail != 8 &&
554735c4bbdfSmrg        stuff->event.u.u.detail != 16 && stuff->event.u.u.detail != 32) {
554835c4bbdfSmrg        client->errorValue = stuff->event.u.u.detail;
554935c4bbdfSmrg        return BadValue;
555005b261ecSmrg    }
555135c4bbdfSmrg    if (stuff->eventMask & ~AllEventMasks) {
555235c4bbdfSmrg        client->errorValue = stuff->eventMask;
555335c4bbdfSmrg        return BadValue;
555405b261ecSmrg    }
555505b261ecSmrg
555605b261ecSmrg    if (stuff->destination == PointerWindow)
555735c4bbdfSmrg        pWin = pSprite->win;
555835c4bbdfSmrg    else if (stuff->destination == InputFocus) {
555935c4bbdfSmrg        WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin;
556005b261ecSmrg
556135c4bbdfSmrg        if (inputFocus == NoneWin)
556235c4bbdfSmrg            return Success;
556305b261ecSmrg
556435c4bbdfSmrg        /* If the input focus is PointerRootWin, send the event to where
55655a112b11Smrg           the pointer is if possible, then perhaps propagate up to root. */
556635c4bbdfSmrg        if (inputFocus == PointerRootWin)
556735c4bbdfSmrg            inputFocus = GetCurrentRootWindow(dev);
556805b261ecSmrg
556935c4bbdfSmrg        if (IsParent(inputFocus, pSprite->win)) {
557035c4bbdfSmrg            effectiveFocus = inputFocus;
557135c4bbdfSmrg            pWin = pSprite->win;
557235c4bbdfSmrg        }
557335c4bbdfSmrg        else
557435c4bbdfSmrg            effectiveFocus = pWin = inputFocus;
557505b261ecSmrg    }
557605b261ecSmrg    else
557735c4bbdfSmrg        dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess);
557805b261ecSmrg
557905b261ecSmrg    if (!pWin)
558035c4bbdfSmrg        return BadWindow;
558135c4bbdfSmrg    if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) {
558235c4bbdfSmrg        client->errorValue = stuff->propagate;
558335c4bbdfSmrg        return BadValue;
558405b261ecSmrg    }
5585475c125cSmrg    stuff->event.u.u.type |= SEND_EVENT_BIT;
558635c4bbdfSmrg    if (stuff->propagate) {
558735c4bbdfSmrg        for (; pWin; pWin = pWin->parent) {
558835c4bbdfSmrg            if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin,
558935c4bbdfSmrg                         &stuff->event, 1))
559035c4bbdfSmrg                return Success;
55916747b715Smrg            if (DeliverEventsToWindow(dev, pWin,
559235c4bbdfSmrg                                      &stuff->event, 1, stuff->eventMask,
559335c4bbdfSmrg                                      NullGrab))
559435c4bbdfSmrg                return Success;
559535c4bbdfSmrg            if (pWin == effectiveFocus)
559635c4bbdfSmrg                return Success;
559735c4bbdfSmrg            stuff->eventMask &= ~wDontPropagateMask(pWin);
559835c4bbdfSmrg            if (!stuff->eventMask)
559935c4bbdfSmrg                break;
560035c4bbdfSmrg        }
560105b261ecSmrg    }
56024642e01fSmrg    else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1))
56036747b715Smrg        DeliverEventsToWindow(dev, pWin, &stuff->event,
560435c4bbdfSmrg                              1, stuff->eventMask, NullGrab);
560505b261ecSmrg    return Success;
560605b261ecSmrg}
560705b261ecSmrg
560805b261ecSmrg/**
560905b261ecSmrg * Server-side protocol handling for UngrabKey request.
561005b261ecSmrg *
56114642e01fSmrg * Deletes a passive grab for the given key. Works on the
56124642e01fSmrg * client's keyboard.
561305b261ecSmrg */
561405b261ecSmrgint
561505b261ecSmrgProcUngrabKey(ClientPtr client)
561605b261ecSmrg{
561705b261ecSmrg    REQUEST(xUngrabKeyReq);
561805b261ecSmrg    WindowPtr pWin;
561935c4bbdfSmrg    GrabPtr tempGrab;
56204642e01fSmrg    DeviceIntPtr keybd = PickKeyboard(client);
562105b261ecSmrg    int rc;
562205b261ecSmrg
562305b261ecSmrg    REQUEST_SIZE_MATCH(xUngrabKeyReq);
56246747b715Smrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess);
562505b261ecSmrg    if (rc != Success)
562635c4bbdfSmrg        return rc;
562705b261ecSmrg
56286747b715Smrg    if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
562935c4bbdfSmrg         (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
563035c4bbdfSmrg        && (stuff->key != AnyKey)) {
563135c4bbdfSmrg        client->errorValue = stuff->key;
563205b261ecSmrg        return BadValue;
563305b261ecSmrg    }
563405b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
563535c4bbdfSmrg        (stuff->modifiers & ~AllModifiersMask)) {
563635c4bbdfSmrg        client->errorValue = stuff->modifiers;
563735c4bbdfSmrg        return BadValue;
563835c4bbdfSmrg    }
563935c4bbdfSmrg    tempGrab = AllocGrab(NULL);
564035c4bbdfSmrg    if (!tempGrab)
564135c4bbdfSmrg        return BadAlloc;
564235c4bbdfSmrg    tempGrab->resource = client->clientAsMask;
564335c4bbdfSmrg    tempGrab->device = keybd;
564435c4bbdfSmrg    tempGrab->window = pWin;
564535c4bbdfSmrg    tempGrab->modifiersDetail.exact = stuff->modifiers;
564635c4bbdfSmrg    tempGrab->modifiersDetail.pMask = NULL;
564735c4bbdfSmrg    tempGrab->modifierDevice = keybd;
564835c4bbdfSmrg    tempGrab->type = KeyPress;
564935c4bbdfSmrg    tempGrab->grabtype = CORE;
565035c4bbdfSmrg    tempGrab->detail.exact = stuff->key;
565135c4bbdfSmrg    tempGrab->detail.pMask = NULL;
565235c4bbdfSmrg    tempGrab->next = NULL;
565335c4bbdfSmrg
565435c4bbdfSmrg    if (!DeletePassiveGrabFromList(tempGrab))
565535c4bbdfSmrg        rc = BadAlloc;
565635c4bbdfSmrg
565735c4bbdfSmrg    FreeGrab(tempGrab);
565835c4bbdfSmrg
565935c4bbdfSmrg    return rc;
566005b261ecSmrg}
566105b261ecSmrg
566205b261ecSmrg/**
566305b261ecSmrg * Server-side protocol handling for GrabKey request.
566405b261ecSmrg *
56654642e01fSmrg * Creates a grab for the client's keyboard and adds it to the list of passive
56664642e01fSmrg * grabs.
566705b261ecSmrg */
566805b261ecSmrgint
566905b261ecSmrgProcGrabKey(ClientPtr client)
567005b261ecSmrg{
567105b261ecSmrg    WindowPtr pWin;
567235c4bbdfSmrg
567305b261ecSmrg    REQUEST(xGrabKeyReq);
567405b261ecSmrg    GrabPtr grab;
56754642e01fSmrg    DeviceIntPtr keybd = PickKeyboard(client);
567605b261ecSmrg    int rc;
56776747b715Smrg    GrabParameters param;
56786747b715Smrg    GrabMask mask;
567905b261ecSmrg
568005b261ecSmrg    REQUEST_SIZE_MATCH(xGrabKeyReq);
56816747b715Smrg
568235c4bbdfSmrg    param = (GrabParameters) {
568335c4bbdfSmrg        .grabtype = CORE,
568435c4bbdfSmrg        .ownerEvents = stuff->ownerEvents,
568535c4bbdfSmrg        .this_device_mode = stuff->keyboardMode,
568635c4bbdfSmrg        .other_devices_mode = stuff->pointerMode,
568735c4bbdfSmrg        .modifiers = stuff->modifiers
568835c4bbdfSmrg    };
56896747b715Smrg
56906747b715Smrg    rc = CheckGrabValues(client, &param);
56916747b715Smrg    if (rc != Success)
56926747b715Smrg        return rc;
56936747b715Smrg
56946747b715Smrg    if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
569535c4bbdfSmrg         (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
569635c4bbdfSmrg        && (stuff->key != AnyKey)) {
569735c4bbdfSmrg        client->errorValue = stuff->key;
569805b261ecSmrg        return BadValue;
569905b261ecSmrg    }
57004642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
570105b261ecSmrg    if (rc != Success)
570235c4bbdfSmrg        return rc;
57036747b715Smrg
57046747b715Smrg    mask.core = (KeyPressMask | KeyReleaseMask);
57056747b715Smrg
570635c4bbdfSmrg    grab = CreateGrab(client->index, keybd, keybd, pWin, CORE, &mask,
57076747b715Smrg                      &param, KeyPress, stuff->key, NullWindow, NullCursor);
570805b261ecSmrg    if (!grab)
570935c4bbdfSmrg        return BadAlloc;
57104642e01fSmrg    return AddPassiveGrabToList(client, grab);
571105b261ecSmrg}
571205b261ecSmrg
571305b261ecSmrg/**
571405b261ecSmrg * Server-side protocol handling for GrabButton request.
571505b261ecSmrg *
57164642e01fSmrg * Creates a grab for the client's ClientPointer and adds it as a passive grab
57174642e01fSmrg * to the list.
571805b261ecSmrg */
571905b261ecSmrgint
572005b261ecSmrgProcGrabButton(ClientPtr client)
572105b261ecSmrg{
572205b261ecSmrg    WindowPtr pWin, confineTo;
572335c4bbdfSmrg
572405b261ecSmrg    REQUEST(xGrabButtonReq);
572505b261ecSmrg    CursorPtr cursor;
572605b261ecSmrg    GrabPtr grab;
57274642e01fSmrg    DeviceIntPtr ptr, modifierDevice;
57284642e01fSmrg    Mask access_mode = DixGrabAccess;
57296747b715Smrg    GrabMask mask;
57306747b715Smrg    GrabParameters param;
573105b261ecSmrg    int rc;
573205b261ecSmrg
573305b261ecSmrg    REQUEST_SIZE_MATCH(xGrabButtonReq);
57347e31ba66Smrg    UpdateCurrentTime();
573505b261ecSmrg    if ((stuff->pointerMode != GrabModeSync) &&
573635c4bbdfSmrg        (stuff->pointerMode != GrabModeAsync)) {
573735c4bbdfSmrg        client->errorValue = stuff->pointerMode;
573805b261ecSmrg        return BadValue;
573905b261ecSmrg    }
574005b261ecSmrg    if ((stuff->keyboardMode != GrabModeSync) &&
574135c4bbdfSmrg        (stuff->keyboardMode != GrabModeAsync)) {
574235c4bbdfSmrg        client->errorValue = stuff->keyboardMode;
574305b261ecSmrg        return BadValue;
574405b261ecSmrg    }
574505b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
574635c4bbdfSmrg        (stuff->modifiers & ~AllModifiersMask)) {
574735c4bbdfSmrg        client->errorValue = stuff->modifiers;
574835c4bbdfSmrg        return BadValue;
574905b261ecSmrg    }
575035c4bbdfSmrg    if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) {
575135c4bbdfSmrg        client->errorValue = stuff->ownerEvents;
575235c4bbdfSmrg        return BadValue;
575305b261ecSmrg    }
575435c4bbdfSmrg    if (stuff->eventMask & ~PointerGrabMask) {
575535c4bbdfSmrg        client->errorValue = stuff->eventMask;
575605b261ecSmrg        return BadValue;
575705b261ecSmrg    }
57584642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
575905b261ecSmrg    if (rc != Success)
576035c4bbdfSmrg        return rc;
576105b261ecSmrg    if (stuff->confineTo == None)
576235c4bbdfSmrg        confineTo = NullWindow;
576305b261ecSmrg    else {
576435c4bbdfSmrg        rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
576535c4bbdfSmrg                             DixSetAttrAccess);
576635c4bbdfSmrg        if (rc != Success)
576735c4bbdfSmrg            return rc;
576805b261ecSmrg    }
576905b261ecSmrg    if (stuff->cursor == None)
577035c4bbdfSmrg        cursor = NullCursor;
577135c4bbdfSmrg    else {
577235c4bbdfSmrg        rc = dixLookupResourceByType((void **) &cursor, stuff->cursor,
577335c4bbdfSmrg                                     RT_CURSOR, client, DixUseAccess);
577435c4bbdfSmrg        if (rc != Success) {
577535c4bbdfSmrg            client->errorValue = stuff->cursor;
577635c4bbdfSmrg            return rc;
577735c4bbdfSmrg        }
577835c4bbdfSmrg        access_mode |= DixForceAccess;
577905b261ecSmrg    }
578005b261ecSmrg
57814642e01fSmrg    ptr = PickPointer(client);
578235c4bbdfSmrg    modifierDevice = GetMaster(ptr, MASTER_KEYBOARD);
57834642e01fSmrg    if (stuff->pointerMode == GrabModeSync ||
578435c4bbdfSmrg        stuff->keyboardMode == GrabModeSync)
578535c4bbdfSmrg        access_mode |= DixFreezeAccess;
57864642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode);
57874642e01fSmrg    if (rc != Success)
578835c4bbdfSmrg        return rc;
578905b261ecSmrg
579035c4bbdfSmrg    param = (GrabParameters) {
579135c4bbdfSmrg        .grabtype = CORE,
579235c4bbdfSmrg        .ownerEvents = stuff->ownerEvents,
579335c4bbdfSmrg        .this_device_mode = stuff->keyboardMode,
579435c4bbdfSmrg        .other_devices_mode = stuff->pointerMode,
579535c4bbdfSmrg        .modifiers = stuff->modifiers
579635c4bbdfSmrg    };
57976747b715Smrg
57986747b715Smrg    mask.core = stuff->eventMask;
57996747b715Smrg
58006747b715Smrg    grab = CreateGrab(client->index, ptr, modifierDevice, pWin,
580135c4bbdfSmrg                      CORE, &mask, &param, ButtonPress,
58026747b715Smrg                      stuff->button, confineTo, cursor);
580305b261ecSmrg    if (!grab)
580435c4bbdfSmrg        return BadAlloc;
58054642e01fSmrg    return AddPassiveGrabToList(client, grab);
580605b261ecSmrg}
580705b261ecSmrg
580805b261ecSmrg/**
580905b261ecSmrg * Server-side protocol handling for UngrabButton request.
581005b261ecSmrg *
58114642e01fSmrg * Deletes a passive grab on the client's ClientPointer from the list.
581205b261ecSmrg */
581305b261ecSmrgint
581405b261ecSmrgProcUngrabButton(ClientPtr client)
581505b261ecSmrg{
581605b261ecSmrg    REQUEST(xUngrabButtonReq);
581705b261ecSmrg    WindowPtr pWin;
581835c4bbdfSmrg    GrabPtr tempGrab;
581905b261ecSmrg    int rc;
58206747b715Smrg    DeviceIntPtr ptr;
582105b261ecSmrg
582205b261ecSmrg    REQUEST_SIZE_MATCH(xUngrabButtonReq);
58237e31ba66Smrg    UpdateCurrentTime();
582405b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
582535c4bbdfSmrg        (stuff->modifiers & ~AllModifiersMask)) {
582635c4bbdfSmrg        client->errorValue = stuff->modifiers;
582735c4bbdfSmrg        return BadValue;
582805b261ecSmrg    }
582905b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
583005b261ecSmrg    if (rc != Success)
583135c4bbdfSmrg        return rc;
58326747b715Smrg
58336747b715Smrg    ptr = PickPointer(client);
58346747b715Smrg
583535c4bbdfSmrg    tempGrab = AllocGrab(NULL);
583635c4bbdfSmrg    if (!tempGrab)
583735c4bbdfSmrg        return BadAlloc;
583835c4bbdfSmrg    tempGrab->resource = client->clientAsMask;
583935c4bbdfSmrg    tempGrab->device = ptr;
584035c4bbdfSmrg    tempGrab->window = pWin;
584135c4bbdfSmrg    tempGrab->modifiersDetail.exact = stuff->modifiers;
584235c4bbdfSmrg    tempGrab->modifiersDetail.pMask = NULL;
584335c4bbdfSmrg    tempGrab->modifierDevice = GetMaster(ptr, MASTER_KEYBOARD);
584435c4bbdfSmrg    tempGrab->type = ButtonPress;
584535c4bbdfSmrg    tempGrab->detail.exact = stuff->button;
584635c4bbdfSmrg    tempGrab->grabtype = CORE;
584735c4bbdfSmrg    tempGrab->detail.pMask = NULL;
584835c4bbdfSmrg    tempGrab->next = NULL;
584935c4bbdfSmrg
585035c4bbdfSmrg    if (!DeletePassiveGrabFromList(tempGrab))
585135c4bbdfSmrg        rc = BadAlloc;
585235c4bbdfSmrg
585335c4bbdfSmrg    FreeGrab(tempGrab);
585435c4bbdfSmrg    return rc;
585505b261ecSmrg}
585605b261ecSmrg
585705b261ecSmrg/**
585805b261ecSmrg * Deactivate any grab that may be on the window, remove the focus.
585905b261ecSmrg * Delete any XInput extension events from the window too. Does not change the
586005b261ecSmrg * window mask. Use just before the window is deleted.
586105b261ecSmrg *
586205b261ecSmrg * If freeResources is set, passive grabs on the window are deleted.
586305b261ecSmrg *
586405b261ecSmrg * @param pWin The window to delete events from.
586505b261ecSmrg * @param freeResources True if resources associated with the window should be
586605b261ecSmrg * deleted.
586705b261ecSmrg */
586805b261ecSmrgvoid
586905b261ecSmrgDeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
587005b261ecSmrg{
587135c4bbdfSmrg    WindowPtr parent;
587235c4bbdfSmrg    DeviceIntPtr mouse = inputInfo.pointer;
587335c4bbdfSmrg    DeviceIntPtr keybd = inputInfo.keyboard;
587435c4bbdfSmrg    FocusClassPtr focus;
587535c4bbdfSmrg    OtherClientsPtr oc;
587635c4bbdfSmrg    GrabPtr passive;
587735c4bbdfSmrg    GrabPtr grab;
587805b261ecSmrg
587905b261ecSmrg    /* Deactivate any grabs performed on this window, before making any
588035c4bbdfSmrg       input focus changes. */
58814642e01fSmrg    grab = mouse->deviceGrab.grab;
588235c4bbdfSmrg    if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
588335c4bbdfSmrg        (*mouse->deviceGrab.DeactivateGrab) (mouse);
588405b261ecSmrg
588505b261ecSmrg    /* Deactivating a keyboard grab should cause focus events. */
58864642e01fSmrg    grab = keybd->deviceGrab.grab;
58874642e01fSmrg    if (grab && (grab->window == pWin))
588835c4bbdfSmrg        (*keybd->deviceGrab.DeactivateGrab) (keybd);
588905b261ecSmrg
58904642e01fSmrg    /* And now the real devices */
589135c4bbdfSmrg    for (mouse = inputInfo.devices; mouse; mouse = mouse->next) {
58924642e01fSmrg        grab = mouse->deviceGrab.grab;
58934642e01fSmrg        if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
589435c4bbdfSmrg            (*mouse->deviceGrab.DeactivateGrab) (mouse);
58954642e01fSmrg    }
589605b261ecSmrg
589735c4bbdfSmrg    for (keybd = inputInfo.devices; keybd; keybd = keybd->next) {
589835c4bbdfSmrg        if (IsKeyboardDevice(keybd)) {
58994642e01fSmrg            focus = keybd->focus;
59004642e01fSmrg
590135c4bbdfSmrg            /* If the focus window is a root window (ie. has no parent)
590235c4bbdfSmrg               then don't delete the focus from it. */
59034642e01fSmrg
590435c4bbdfSmrg            if ((pWin == focus->win) && (pWin->parent != NullWindow)) {
59054642e01fSmrg                int focusEventMode = NotifyNormal;
59064642e01fSmrg
59074642e01fSmrg                /* If a grab is in progress, then alter the mode of focus events. */
59084642e01fSmrg
59094642e01fSmrg                if (keybd->deviceGrab.grab)
59104642e01fSmrg                    focusEventMode = NotifyWhileGrabbed;
59114642e01fSmrg
591235c4bbdfSmrg                switch (focus->revert) {
591335c4bbdfSmrg                case RevertToNone:
591435c4bbdfSmrg                    DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
591535c4bbdfSmrg                    focus->win = NoneWin;
591635c4bbdfSmrg                    focus->traceGood = 0;
591735c4bbdfSmrg                    break;
591835c4bbdfSmrg                case RevertToParent:
591935c4bbdfSmrg                    parent = pWin;
592035c4bbdfSmrg                    do {
592135c4bbdfSmrg                        parent = parent->parent;
592235c4bbdfSmrg                        focus->traceGood--;
592335c4bbdfSmrg                    } while (!parent->realized
592435c4bbdfSmrg                    /* This would be a good protocol change -- windows being
592535c4bbdfSmrg                       reparented during SaveSet processing would cause the
592635c4bbdfSmrg                       focus to revert to the nearest enclosing window which
592735c4bbdfSmrg                       will survive the death of the exiting client, instead
592835c4bbdfSmrg                       of ending up reverting to a dying window and thence
592935c4bbdfSmrg                       to None */
593005b261ecSmrg#ifdef NOTDEF
593135c4bbdfSmrg                             || wClient(parent)->clientGone
593205b261ecSmrg#endif
593335c4bbdfSmrg                        );
593435c4bbdfSmrg                    if (!ActivateFocusInGrab(keybd, pWin, parent))
593535c4bbdfSmrg                        DoFocusEvents(keybd, pWin, parent, focusEventMode);
593635c4bbdfSmrg                    focus->win = parent;
593735c4bbdfSmrg                    focus->revert = RevertToNone;
593835c4bbdfSmrg                    break;
593935c4bbdfSmrg                case RevertToPointerRoot:
594035c4bbdfSmrg                    if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin))
594135c4bbdfSmrg                        DoFocusEvents(keybd, pWin, PointerRootWin,
594235c4bbdfSmrg                                      focusEventMode);
594335c4bbdfSmrg                    focus->win = PointerRootWin;
594435c4bbdfSmrg                    focus->traceGood = 0;
594535c4bbdfSmrg                    break;
59464642e01fSmrg                }
59474642e01fSmrg            }
59484642e01fSmrg        }
594905b261ecSmrg
595035c4bbdfSmrg        if (IsPointerDevice(keybd)) {
59514642e01fSmrg            if (keybd->valuator->motionHintWindow == pWin)
59524642e01fSmrg                keybd->valuator->motionHintWindow = NullWindow;
59534642e01fSmrg        }
59544642e01fSmrg    }
595505b261ecSmrg
595635c4bbdfSmrg    if (freeResources) {
595735c4bbdfSmrg        if (pWin->dontPropagate)
595835c4bbdfSmrg            DontPropagateRefCnts[pWin->dontPropagate]--;
595935c4bbdfSmrg        while ((oc = wOtherClients(pWin)))
596035c4bbdfSmrg            FreeResource(oc->resource, RT_NONE);
596135c4bbdfSmrg        while ((passive = wPassiveGrabs(pWin)))
596235c4bbdfSmrg            FreeResource(passive->resource, RT_NONE);
596335c4bbdfSmrg    }
59644642e01fSmrg
596505b261ecSmrg    DeleteWindowFromAnyExtEvents(pWin, freeResources);
596605b261ecSmrg}
596705b261ecSmrg
596805b261ecSmrg/**
596905b261ecSmrg * Call this whenever some window at or below pWin has changed geometry. If
597005b261ecSmrg * there is a grab on the window, the cursor will be re-confined into the
597105b261ecSmrg * window.
597205b261ecSmrg */
59736747b715Smrgvoid
597405b261ecSmrgCheckCursorConfinement(WindowPtr pWin)
597505b261ecSmrg{
59764642e01fSmrg    GrabPtr grab;
597705b261ecSmrg    WindowPtr confineTo;
59784642e01fSmrg    DeviceIntPtr pDev;
597905b261ecSmrg
598005b261ecSmrg#ifdef PANORAMIX
598135c4bbdfSmrg    if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
598235c4bbdfSmrg        return;
598305b261ecSmrg#endif
598405b261ecSmrg
598535c4bbdfSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
598635c4bbdfSmrg        if (DevHasCursor(pDev)) {
59874642e01fSmrg            grab = pDev->deviceGrab.grab;
598835c4bbdfSmrg            if (grab && (confineTo = grab->confineTo)) {
59894642e01fSmrg                if (!BorderSizeNotEmpty(pDev, confineTo))
599035c4bbdfSmrg                    (*pDev->deviceGrab.DeactivateGrab) (pDev);
59914642e01fSmrg                else if ((pWin == confineTo) || IsParent(pWin, confineTo))
59924642e01fSmrg                    ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
59934642e01fSmrg            }
59944642e01fSmrg        }
599505b261ecSmrg    }
599605b261ecSmrg}
599705b261ecSmrg
599805b261ecSmrgMask
599905b261ecSmrgEventMaskForClient(WindowPtr pWin, ClientPtr client)
600005b261ecSmrg{
600135c4bbdfSmrg    OtherClientsPtr other;
600205b261ecSmrg
600335c4bbdfSmrg    if (wClient(pWin) == client)
600435c4bbdfSmrg        return pWin->eventMask;
600535c4bbdfSmrg    for (other = wOtherClients(pWin); other; other = other->next) {
600635c4bbdfSmrg        if (SameClient(other, client))
600735c4bbdfSmrg            return other->mask;
600805b261ecSmrg    }
600905b261ecSmrg    return 0;
601005b261ecSmrg}
601105b261ecSmrg
601205b261ecSmrg/**
601305b261ecSmrg * Server-side protocol handling for RecolorCursor request.
601405b261ecSmrg */
601505b261ecSmrgint
601605b261ecSmrgProcRecolorCursor(ClientPtr client)
601705b261ecSmrg{
601805b261ecSmrg    CursorPtr pCursor;
601935c4bbdfSmrg    int rc, nscr;
602035c4bbdfSmrg    ScreenPtr pscr;
602135c4bbdfSmrg    Bool displayed;
602235c4bbdfSmrg    SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
602335c4bbdfSmrg
602405b261ecSmrg    REQUEST(xRecolorCursorReq);
602505b261ecSmrg
602605b261ecSmrg    REQUEST_SIZE_MATCH(xRecolorCursorReq);
602735c4bbdfSmrg    rc = dixLookupResourceByType((void **) &pCursor, stuff->cursor, RT_CURSOR,
602835c4bbdfSmrg                                 client, DixWriteAccess);
602935c4bbdfSmrg    if (rc != Success) {
603035c4bbdfSmrg        client->errorValue = stuff->cursor;
603135c4bbdfSmrg        return rc;
603205b261ecSmrg    }
603305b261ecSmrg
603405b261ecSmrg    pCursor->foreRed = stuff->foreRed;
603505b261ecSmrg    pCursor->foreGreen = stuff->foreGreen;
603605b261ecSmrg    pCursor->foreBlue = stuff->foreBlue;
603705b261ecSmrg
603805b261ecSmrg    pCursor->backRed = stuff->backRed;
603905b261ecSmrg    pCursor->backGreen = stuff->backGreen;
604005b261ecSmrg    pCursor->backBlue = stuff->backBlue;
604105b261ecSmrg
604235c4bbdfSmrg    for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
604335c4bbdfSmrg        pscr = screenInfo.screens[nscr];
604405b261ecSmrg#ifdef PANORAMIX
604535c4bbdfSmrg        if (!noPanoramiXExtension)
604635c4bbdfSmrg            displayed = (pscr == pSprite->screen);
604735c4bbdfSmrg        else
604805b261ecSmrg#endif
604935c4bbdfSmrg            displayed = (pscr == pSprite->hotPhys.pScreen);
605035c4bbdfSmrg        (*pscr->RecolorCursor) (PickPointer(client), pscr, pCursor,
605135c4bbdfSmrg                                (pCursor == pSprite->current) && displayed);
605205b261ecSmrg    }
60536747b715Smrg    return Success;
605405b261ecSmrg}
605505b261ecSmrg
605605b261ecSmrg/**
605705b261ecSmrg * Write the given events to a client, swapping the byte order if necessary.
605805b261ecSmrg * To swap the byte ordering, a callback is called that has to be set up for
605905b261ecSmrg * the given event type.
606005b261ecSmrg *
606105b261ecSmrg * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
60624642e01fSmrg * can be more than one. Usually it's just one event.
606305b261ecSmrg *
606405b261ecSmrg * Do not modify the event structure passed in. See comment below.
60654642e01fSmrg *
606605b261ecSmrg * @param pClient Client to send events to.
606705b261ecSmrg * @param count Number of events.
606805b261ecSmrg * @param events The event list.
606905b261ecSmrg */
60706747b715Smrgvoid
607105b261ecSmrgWriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
607205b261ecSmrg{
607305b261ecSmrg#ifdef PANORAMIX
607435c4bbdfSmrg    xEvent eventCopy;
607505b261ecSmrg#endif
607635c4bbdfSmrg    xEvent *eventTo, *eventFrom;
607735c4bbdfSmrg    int i, eventlength = sizeof(xEvent);
607805b261ecSmrg
60796747b715Smrg    if (!pClient || pClient == serverClient || pClient->clientGone)
608035c4bbdfSmrg        return;
60816747b715Smrg
60826747b715Smrg    for (i = 0; i < count; i++)
608335c4bbdfSmrg        if ((events[i].u.u.type & 0x7f) != KeymapNotify)
608435c4bbdfSmrg            events[i].u.u.sequenceNumber = pClient->sequence;
60856747b715Smrg
60866747b715Smrg    /* Let XKB rewrite the state, as it depends on client preferences. */
60876747b715Smrg    XkbFilterEvents(pClient, count, events);
608805b261ecSmrg
608905b261ecSmrg#ifdef PANORAMIX
609035c4bbdfSmrg    if (!noPanoramiXExtension &&
609135c4bbdfSmrg        (screenInfo.screens[0]->x || screenInfo.screens[0]->y)) {
609235c4bbdfSmrg        switch (events->u.u.type) {
609335c4bbdfSmrg        case MotionNotify:
609435c4bbdfSmrg        case ButtonPress:
609535c4bbdfSmrg        case ButtonRelease:
609635c4bbdfSmrg        case KeyPress:
609735c4bbdfSmrg        case KeyRelease:
609835c4bbdfSmrg        case EnterNotify:
609935c4bbdfSmrg        case LeaveNotify:
610035c4bbdfSmrg            /*
610135c4bbdfSmrg               When multiple clients want the same event DeliverEventsToWindow
610235c4bbdfSmrg               passes the same event structure multiple times so we can't
610335c4bbdfSmrg               modify the one passed to us
610435c4bbdfSmrg             */
610535c4bbdfSmrg            count = 1;          /* should always be 1 */
610635c4bbdfSmrg            memcpy(&eventCopy, events, sizeof(xEvent));
610735c4bbdfSmrg            eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x;
610835c4bbdfSmrg            eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y;
610935c4bbdfSmrg            if (eventCopy.u.keyButtonPointer.event ==
611035c4bbdfSmrg                eventCopy.u.keyButtonPointer.root) {
611135c4bbdfSmrg                eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x;
611235c4bbdfSmrg                eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y;
611335c4bbdfSmrg            }
611435c4bbdfSmrg            events = &eventCopy;
611535c4bbdfSmrg            break;
611635c4bbdfSmrg        default:
611735c4bbdfSmrg            break;
611835c4bbdfSmrg        }
611905b261ecSmrg    }
612005b261ecSmrg#endif
612105b261ecSmrg
612235c4bbdfSmrg    if (EventCallback) {
612335c4bbdfSmrg        EventInfoRec eventinfo;
612435c4bbdfSmrg
612535c4bbdfSmrg        eventinfo.client = pClient;
612635c4bbdfSmrg        eventinfo.events = events;
612735c4bbdfSmrg        eventinfo.count = count;
612835c4bbdfSmrg        CallCallbacks(&EventCallback, (void *) &eventinfo);
612905b261ecSmrg    }
613005b261ecSmrg#ifdef XSERVER_DTRACE
613105b261ecSmrg    if (XSERVER_SEND_EVENT_ENABLED()) {
613235c4bbdfSmrg        for (i = 0; i < count; i++) {
613335c4bbdfSmrg            XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]);
613435c4bbdfSmrg        }
613505b261ecSmrg    }
61364642e01fSmrg#endif
61374642e01fSmrg    /* Just a safety check to make sure we only have one GenericEvent, it just
61384642e01fSmrg     * makes things easier for me right now. (whot) */
613935c4bbdfSmrg    for (i = 1; i < count; i++) {
614035c4bbdfSmrg        if (events[i].u.u.type == GenericEvent) {
61414642e01fSmrg            ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n");
61424642e01fSmrg            return;
61434642e01fSmrg        }
61444642e01fSmrg    }
61454642e01fSmrg
614635c4bbdfSmrg    if (events->u.u.type == GenericEvent) {
614735c4bbdfSmrg        eventlength += ((xGenericEvent *) events)->length * 4;
61484642e01fSmrg    }
61494642e01fSmrg
615035c4bbdfSmrg    if (pClient->swapped) {
615135c4bbdfSmrg        if (eventlength > swapEventLen) {
61524642e01fSmrg            swapEventLen = eventlength;
61536747b715Smrg            swapEvent = realloc(swapEvent, swapEventLen);
615435c4bbdfSmrg            if (!swapEvent) {
61554642e01fSmrg                FatalError("WriteEventsToClient: Out of memory.\n");
61564642e01fSmrg                return;
61574642e01fSmrg            }
61584642e01fSmrg        }
61594642e01fSmrg
616035c4bbdfSmrg        for (i = 0; i < count; i++) {
616135c4bbdfSmrg            eventFrom = &events[i];
61624642e01fSmrg            eventTo = swapEvent;
61634642e01fSmrg
616435c4bbdfSmrg            /* Remember to strip off the leading bit of type in case
616535c4bbdfSmrg               this event was sent with "SendEvent." */
616635c4bbdfSmrg            (*EventSwapVector[eventFrom->u.u.type & 0177])
616735c4bbdfSmrg                (eventFrom, eventTo);
61684642e01fSmrg
616935c4bbdfSmrg            WriteToClient(pClient, eventlength, eventTo);
617035c4bbdfSmrg        }
617105b261ecSmrg    }
617235c4bbdfSmrg    else {
61734642e01fSmrg        /* only one GenericEvent, remember? that means either count is 1 and
61744642e01fSmrg         * eventlength is arbitrary or eventlength is 32 and count doesn't
61754642e01fSmrg         * matter. And we're all set. Woohoo. */
617635c4bbdfSmrg        WriteToClient(pClient, count * eventlength, events);
617705b261ecSmrg    }
617805b261ecSmrg}
61794642e01fSmrg
61804642e01fSmrg/*
61816747b715Smrg * Set the client pointer for the given client.
61824642e01fSmrg *
61834642e01fSmrg * A client can have exactly one ClientPointer. Each time a
61844642e01fSmrg * request/reply/event is processed and the choice of devices is ambiguous
61854642e01fSmrg * (e.g. QueryPointer request), the server will pick the ClientPointer (see
61864642e01fSmrg * PickPointer()).
61874642e01fSmrg * If a keyboard is needed, the first keyboard paired with the CP is used.
61884642e01fSmrg */
61896747b715Smrgint
61906747b715SmrgSetClientPointer(ClientPtr client, DeviceIntPtr device)
61914642e01fSmrg{
61926747b715Smrg    int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess);
619335c4bbdfSmrg
61946747b715Smrg    if (rc != Success)
619535c4bbdfSmrg        return rc;
61966747b715Smrg
619735c4bbdfSmrg    if (!IsMaster(device)) {
61984642e01fSmrg        ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n");
61996747b715Smrg        return BadDevice;
620035c4bbdfSmrg    }
620135c4bbdfSmrg    else if (!device->spriteInfo->spriteOwner) {
62024642e01fSmrg        ErrorF("[dix] Device %d does not have a sprite. "
620335c4bbdfSmrg               "Cannot be ClientPointer\n", device->id);
62046747b715Smrg        return BadDevice;
62054642e01fSmrg    }
62064642e01fSmrg    client->clientPtr = device;
62076747b715Smrg    return Success;
62084642e01fSmrg}
62094642e01fSmrg
62104642e01fSmrg/* PickPointer will pick an appropriate pointer for the given client.
62114642e01fSmrg *
62124642e01fSmrg * An "appropriate device" is (in order of priority):
62134642e01fSmrg *  1) A device the given client has a core grab on.
62144642e01fSmrg *  2) A device set as ClientPointer for the given client.
62154642e01fSmrg *  3) The first master device.
62164642e01fSmrg */
62176747b715SmrgDeviceIntPtr
62184642e01fSmrgPickPointer(ClientPtr client)
62194642e01fSmrg{
62204642e01fSmrg    DeviceIntPtr it = inputInfo.devices;
62214642e01fSmrg
62224642e01fSmrg    /* First, check if the client currently has a grab on a device. Even
62234642e01fSmrg     * keyboards count. */
622435c4bbdfSmrg    for (it = inputInfo.devices; it; it = it->next) {
62254642e01fSmrg        GrabPtr grab = it->deviceGrab.grab;
622635c4bbdfSmrg
622735c4bbdfSmrg        if (grab && grab->grabtype == CORE && SameClient(grab, client)) {
62286747b715Smrg            it = GetMaster(it, MASTER_POINTER);
622935c4bbdfSmrg            return it;          /* Always return a core grabbed device */
62304642e01fSmrg        }
62314642e01fSmrg    }
62324642e01fSmrg
623335c4bbdfSmrg    if (!client->clientPtr) {
623435c4bbdfSmrg        it = inputInfo.devices;
623535c4bbdfSmrg        while (it) {
623635c4bbdfSmrg            if (IsMaster(it) && it->spriteInfo->spriteOwner) {
62374642e01fSmrg                client->clientPtr = it;
62384642e01fSmrg                break;
62394642e01fSmrg            }
62404642e01fSmrg            it = it->next;
62414642e01fSmrg        }
62424642e01fSmrg    }
62434642e01fSmrg    return client->clientPtr;
62444642e01fSmrg}
62454642e01fSmrg
62464642e01fSmrg/* PickKeyboard will pick an appropriate keyboard for the given client by
62474642e01fSmrg * searching the list of devices for the keyboard device that is paired with
62484642e01fSmrg * the client's pointer.
62494642e01fSmrg */
62506747b715SmrgDeviceIntPtr
62514642e01fSmrgPickKeyboard(ClientPtr client)
62524642e01fSmrg{
62534642e01fSmrg    DeviceIntPtr ptr = PickPointer(client);
62546747b715Smrg    DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD);
62554642e01fSmrg
625635c4bbdfSmrg    if (!kbd) {
62574642e01fSmrg        ErrorF("[dix] ClientPointer not paired with a keyboard. This "
625835c4bbdfSmrg               "is a bug.\n");
62594642e01fSmrg    }
62604642e01fSmrg
62614642e01fSmrg    return kbd;
62624642e01fSmrg}
62634642e01fSmrg
62644642e01fSmrg/* A client that has one or more core grabs does not get core events from
62654642e01fSmrg * devices it does not have a grab on. Legacy applications behave bad
62664642e01fSmrg * otherwise because they are not used to it and the events interfere.
62674642e01fSmrg * Only applies for core events.
62684642e01fSmrg *
62694642e01fSmrg * Return true if a core event from the device would interfere and should not
62704642e01fSmrg * be delivered.
62714642e01fSmrg */
62724642e01fSmrgBool
627335c4bbdfSmrgIsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent *event)
62744642e01fSmrg{
62754642e01fSmrg    DeviceIntPtr it = inputInfo.devices;
62764642e01fSmrg
627735c4bbdfSmrg    switch (event->u.u.type) {
627835c4bbdfSmrg    case KeyPress:
627935c4bbdfSmrg    case KeyRelease:
628035c4bbdfSmrg    case ButtonPress:
628135c4bbdfSmrg    case ButtonRelease:
628235c4bbdfSmrg    case MotionNotify:
628335c4bbdfSmrg    case EnterNotify:
628435c4bbdfSmrg    case LeaveNotify:
628535c4bbdfSmrg        break;
628635c4bbdfSmrg    default:
628735c4bbdfSmrg        return FALSE;
62884642e01fSmrg    }
62894642e01fSmrg
62906747b715Smrg    if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
62916747b715Smrg        return FALSE;
62926747b715Smrg
629335c4bbdfSmrg    while (it) {
629435c4bbdfSmrg        if (it != dev) {
62954642e01fSmrg            if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client)
629635c4bbdfSmrg                && !it->deviceGrab.fromPassiveGrab) {
62974642e01fSmrg                if ((IsPointerDevice(it) && IsPointerDevice(dev)) ||
629835c4bbdfSmrg                    (IsKeyboardDevice(it) && IsKeyboardDevice(dev)))
62994642e01fSmrg                    return TRUE;
63004642e01fSmrg            }
63014642e01fSmrg        }
63024642e01fSmrg        it = it->next;
63034642e01fSmrg    }
63044642e01fSmrg
63054642e01fSmrg    return FALSE;
63064642e01fSmrg}
63074642e01fSmrg
630835c4bbdfSmrg/* PointerBarrier events are only delivered to the client that created that
630935c4bbdfSmrg * barrier */
631035c4bbdfSmrgstatic Bool
631135c4bbdfSmrgIsWrongPointerBarrierClient(ClientPtr client, DeviceIntPtr dev, xEvent *event)
631235c4bbdfSmrg{
631335c4bbdfSmrg    xXIBarrierEvent *ev = (xXIBarrierEvent*)event;
631435c4bbdfSmrg
631535c4bbdfSmrg    if (ev->type != GenericEvent || ev->extension != IReqCode)
631635c4bbdfSmrg        return FALSE;
631735c4bbdfSmrg
631835c4bbdfSmrg    if (ev->evtype != XI_BarrierHit && ev->evtype != XI_BarrierLeave)
631935c4bbdfSmrg        return FALSE;
632035c4bbdfSmrg
632135c4bbdfSmrg    return client->index != CLIENT_ID(ev->barrier);
632235c4bbdfSmrg}
6323