events.c revision 6747b715
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
2505b261ecSmrg
2605b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
2705b261ecSmrg
2805b261ecSmrg                        All Rights Reserved
2905b261ecSmrg
304642e01fSmrgPermission to use, copy, modify, and distribute this software and its
314642e01fSmrgdocumentation for any purpose and without fee is hereby granted,
3205b261ecSmrgprovided that the above copyright notice appear in all copies and that
334642e01fSmrgboth that copyright notice and this permission notice appear in
3405b261ecSmrgsupporting documentation, and that the name of Digital not be
3505b261ecSmrgused in advertising or publicity pertaining to distribution of the
364642e01fSmrgsoftware without specific, written prior permission.
3705b261ecSmrg
3805b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
3905b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
4005b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
4105b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
4205b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
4305b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4405b261ecSmrgSOFTWARE.
4505b261ecSmrg
4605b261ecSmrg********************************************************/
4705b261ecSmrg
4805b261ecSmrg/* The panoramix components contained the following notice */
4905b261ecSmrg/*****************************************************************
5005b261ecSmrg
5105b261ecSmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
5205b261ecSmrg
5305b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a copy
5405b261ecSmrgof this software and associated documentation files (the "Software"), to deal
5505b261ecSmrgin the Software without restriction, including without limitation the rights
5605b261ecSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5705b261ecSmrgcopies of the Software.
5805b261ecSmrg
5905b261ecSmrgThe above copyright notice and this permission notice shall be included in
6005b261ecSmrgall copies or substantial portions of the Software.
6105b261ecSmrg
6205b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6305b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6405b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
6505b261ecSmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
6605b261ecSmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
6705b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
6805b261ecSmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6905b261ecSmrg
7005b261ecSmrgExcept as contained in this notice, the name of Digital Equipment Corporation
7105b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use or other
7205b261ecSmrgdealings in this Software without prior written authorization from Digital
7305b261ecSmrgEquipment Corporation.
7405b261ecSmrg
7505b261ecSmrg******************************************************************/
7605b261ecSmrg
776747b715Smrg/*
786747b715Smrg * Copyright © 2003-2005 Sun Microsystems, Inc.  All rights reserved.
796747b715Smrg *
806747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a
816747b715Smrg * copy of this software and associated documentation files (the "Software"),
826747b715Smrg * to deal in the Software without restriction, including without limitation
836747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
846747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the
856747b715Smrg * Software is furnished to do so, subject to the following conditions:
866747b715Smrg *
876747b715Smrg * The above copyright notice and this permission notice (including the next
886747b715Smrg * paragraph) shall be included in all copies or substantial portions of the
896747b715Smrg * Software.
906747b715Smrg *
916747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
926747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
936747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
946747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
956747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
966747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
976747b715Smrg * DEALINGS IN THE SOFTWARE.
986747b715Smrg */
9905b261ecSmrg
1006747b715Smrg/** @file events.c
10105b261ecSmrg * This file handles event delivery and a big part of the server-side protocol
10205b261ecSmrg * handling (the parts for input devices).
10305b261ecSmrg */
10405b261ecSmrg
10505b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
10605b261ecSmrg#include <dix-config.h>
10705b261ecSmrg#endif
10805b261ecSmrg
10905b261ecSmrg#include <X11/X.h>
11005b261ecSmrg#include "misc.h"
11105b261ecSmrg#include "resource.h"
11205b261ecSmrg#include <X11/Xproto.h>
11305b261ecSmrg#include "windowstr.h"
11405b261ecSmrg#include "inputstr.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"
12805b261ecSmrg
12905b261ecSmrg#ifdef XSERVER_DTRACE
13005b261ecSmrg#include <sys/types.h>
13105b261ecSmrgtypedef const char *string;
13205b261ecSmrg#include "Xserver-dtrace.h"
13305b261ecSmrg#endif
13405b261ecSmrg
13505b261ecSmrg#include <X11/extensions/XIproto.h>
1366747b715Smrg#include <X11/extensions/XI2proto.h>
1374642e01fSmrg#include <X11/extensions/XI.h>
1386747b715Smrg#include <X11/extensions/XI2.h>
13905b261ecSmrg#include "exglobals.h"
14005b261ecSmrg#include "exevents.h"
14105b261ecSmrg#include "exglobals.h"
14205b261ecSmrg#include "extnsionst.h"
14305b261ecSmrg
14405b261ecSmrg#include "dixevents.h"
14505b261ecSmrg#include "dixgrabs.h"
14605b261ecSmrg#include "dispatch.h"
1474642e01fSmrg
1484642e01fSmrg#include <X11/extensions/ge.h>
1494642e01fSmrg#include "geext.h"
1504642e01fSmrg#include "geint.h"
1514642e01fSmrg
1526747b715Smrg#include "eventstr.h"
1534642e01fSmrg#include "enterleave.h"
1546747b715Smrg#include "eventconvert.h"
1554642e01fSmrg
1566747b715Smrg/* Extension events type numbering starts at EXTENSION_EVENT_BASE.  */
15705b261ecSmrg#define NoSuchEvent 0x80000000	/* so doesn't match NoEventMask */
15805b261ecSmrg#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
15905b261ecSmrg#define AllButtonsMask ( \
16005b261ecSmrg	Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
16105b261ecSmrg#define MotionMask ( \
16205b261ecSmrg	PointerMotionMask | Button1MotionMask | \
16305b261ecSmrg	Button2MotionMask | Button3MotionMask | Button4MotionMask | \
16405b261ecSmrg	Button5MotionMask | ButtonMotionMask )
16505b261ecSmrg#define PropagateMask ( \
16605b261ecSmrg	KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
16705b261ecSmrg	MotionMask )
16805b261ecSmrg#define PointerGrabMask ( \
16905b261ecSmrg	ButtonPressMask | ButtonReleaseMask | \
17005b261ecSmrg	EnterWindowMask | LeaveWindowMask | \
17105b261ecSmrg	PointerMotionHintMask | KeymapStateMask | \
17205b261ecSmrg	MotionMask )
17305b261ecSmrg#define AllModifiersMask ( \
17405b261ecSmrg	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
17505b261ecSmrg	Mod3Mask | Mod4Mask | Mod5Mask )
1766747b715Smrg#define LastEventMask OwnerGrabButtonMask
1776747b715Smrg#define AllEventMasks (LastEventMask|(LastEventMask-1))
1786747b715Smrg
1796747b715Smrg
1806747b715Smrg#define CORE_EVENT(event) \
1816747b715Smrg    (!((event)->u.u.type & EXTENSION_EVENT_BASE) && \
1826747b715Smrg      (event)->u.u.type != GenericEvent)
1836747b715Smrg#define XI2_EVENT(event) \
1846747b715Smrg    (((event)->u.u.type == GenericEvent) && \
1856747b715Smrg    ((xGenericEvent*)(event))->extension == IReqCode)
1864642e01fSmrg
1874642e01fSmrg/**
1884642e01fSmrg * Used to indicate a implicit passive grab created by a ButtonPress event.
1894642e01fSmrg * See DeliverEventsToWindow().
1904642e01fSmrg */
1914642e01fSmrg#define ImplicitGrabMask (1 << 7)
19205b261ecSmrg
19305b261ecSmrg#define WID(w) ((w) ? ((w)->drawable.id) : 0)
19405b261ecSmrg
19505b261ecSmrg#define XE_KBPTR (xE->u.keyButtonPointer)
19605b261ecSmrg
19705b261ecSmrg
19805b261ecSmrg#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
19905b261ecSmrg
2006747b715SmrgCallbackListPtr EventCallback;
2016747b715SmrgCallbackListPtr DeviceEventCallback;
20205b261ecSmrg
20305b261ecSmrg#define DNPMCOUNT 8
20405b261ecSmrg
20505b261ecSmrgMask DontPropagateMasks[DNPMCOUNT];
20605b261ecSmrgstatic int DontPropagateRefCnts[DNPMCOUNT];
20705b261ecSmrg
2086747b715Smrgstatic void CheckVirtualMotion( DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin);
2096747b715Smrgstatic void CheckPhysLimits(DeviceIntPtr pDev,
2106747b715Smrg                            CursorPtr cursor,
2116747b715Smrg                            Bool generateEvents,
2126747b715Smrg                            Bool confineToScreen,
2136747b715Smrg                            ScreenPtr pScreen);
2146747b715Smrgstatic Bool CheckPassiveGrabsOnWindow(WindowPtr pWin,
2156747b715Smrg                                      DeviceIntPtr device,
2166747b715Smrg                                      DeviceEvent *event,
2176747b715Smrg                                      BOOL checkCore);
2186747b715Smrg
2196747b715Smrg/** Key repeat hack. Do not use but in TryClientEvents */
2206747b715Smrgextern BOOL EventIsKeyRepeat(xEvent *event);
2214642e01fSmrg
22205b261ecSmrg/**
2234642e01fSmrg * Main input device struct.
2244642e01fSmrg *     inputInfo.pointer
22505b261ecSmrg *     is the core pointer. Referred to as "virtual core pointer", "VCP",
2266747b715Smrg *     "core pointer" or inputInfo.pointer. The VCP is the first master
2274642e01fSmrg *     pointer device and cannot be deleted.
2284642e01fSmrg *
22905b261ecSmrg *     inputInfo.keyboard
23005b261ecSmrg *     is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
23105b261ecSmrg *     See inputInfo.pointer.
2324642e01fSmrg *
23305b261ecSmrg *     inputInfo.devices
2344642e01fSmrg *     linked list containing all devices including VCP and VCK.
23505b261ecSmrg *
23605b261ecSmrg *     inputInfo.off_devices
23705b261ecSmrg *     Devices that have not been initialized and are thus turned off.
23805b261ecSmrg *
23905b261ecSmrg *     inputInfo.numDevices
24005b261ecSmrg *     Total number of devices.
2416747b715Smrg *
2426747b715Smrg *     inputInfo.all_devices
2436747b715Smrg *     Virtual device used for XIAllDevices passive grabs. This device is
2446747b715Smrg *     not part of the inputInfo.devices list and mostly unset except for
2456747b715Smrg *     the deviceid. It exists because passivegrabs need a valid device
2466747b715Smrg *     reference.
2476747b715Smrg *
2486747b715Smrg *     inputInfo.all_master_devices
2496747b715Smrg *     Virtual device used for XIAllMasterDevices passive grabs. This device
2506747b715Smrg *     is not part of the inputInfo.devices list and mostly unset except for
2516747b715Smrg *     the deviceid. It exists because passivegrabs need a valid device
2526747b715Smrg *     reference.
25305b261ecSmrg */
2546747b715SmrgInputInfo inputInfo;
2556747b715Smrg
2566747b715SmrgEventSyncInfoRec syncEvents;
25705b261ecSmrg
2584642e01fSmrg/**
2596747b715Smrg * The root window the given device is currently on.
2604642e01fSmrg */
2614642e01fSmrg#define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0]
2624642e01fSmrg
2634642e01fSmrgstatic xEvent* swapEvent = NULL;
2644642e01fSmrgstatic int swapEventLen = 0;
2654642e01fSmrg
2666747b715Smrgvoid
2676747b715SmrgNotImplemented(xEvent *from, xEvent *to)
2686747b715Smrg{
2696747b715Smrg    FatalError("Not implemented");
2706747b715Smrg}
2716747b715Smrg
2724642e01fSmrg/**
2734642e01fSmrg * Convert the given event type from an XI event to a core event.
2746747b715Smrg * @param[in] The XI 1.x event type.
2754642e01fSmrg * @return The matching core event type or 0 if there is none.
27605b261ecSmrg */
2776747b715Smrgint
2784642e01fSmrgXItoCoreType(int xitype)
2794642e01fSmrg{
2804642e01fSmrg    int coretype = 0;
2814642e01fSmrg    if (xitype == DeviceMotionNotify)
2824642e01fSmrg        coretype = MotionNotify;
2834642e01fSmrg    else if (xitype == DeviceButtonPress)
2844642e01fSmrg        coretype = ButtonPress;
2854642e01fSmrg    else if (xitype == DeviceButtonRelease)
2864642e01fSmrg        coretype = ButtonRelease;
2874642e01fSmrg    else if (xitype == DeviceKeyPress)
2884642e01fSmrg        coretype = KeyPress;
2894642e01fSmrg    else if (xitype == DeviceKeyRelease)
2904642e01fSmrg        coretype = KeyRelease;
2914642e01fSmrg
2924642e01fSmrg    return coretype;
2934642e01fSmrg}
29405b261ecSmrg
29505b261ecSmrg/**
2966747b715Smrg * @return true if the device owns a cursor, false if device shares a cursor
2976747b715Smrg * sprite with another device.
29805b261ecSmrg */
2996747b715SmrgBool
3004642e01fSmrgDevHasCursor(DeviceIntPtr pDev)
3014642e01fSmrg{
3024642e01fSmrg    return pDev->spriteInfo->spriteOwner;
3034642e01fSmrg}
30405b261ecSmrg
3054642e01fSmrg/*
3066747b715Smrg * @return true if a device is a pointer, check is the same as used by XI to
3074642e01fSmrg * fill the 'use' field.
3084642e01fSmrg */
3096747b715SmrgBool
3104642e01fSmrgIsPointerDevice(DeviceIntPtr dev)
3114642e01fSmrg{
3126747b715Smrg    return (dev->type == MASTER_POINTER) ||
3136747b715Smrg            (dev->valuator && dev->button) ||
3146747b715Smrg            (dev->valuator && !dev->key);
3154642e01fSmrg}
31605b261ecSmrg
3174642e01fSmrg/*
3186747b715Smrg * @return true if a device is a keyboard, check is the same as used by XI to
3194642e01fSmrg * fill the 'use' field.
3204642e01fSmrg *
3214642e01fSmrg * Some pointer devices have keys as well (e.g. multimedia keys). Try to not
3224642e01fSmrg * count them as keyboard devices.
3234642e01fSmrg */
3246747b715SmrgBool
3254642e01fSmrgIsKeyboardDevice(DeviceIntPtr dev)
3264642e01fSmrg{
3276747b715Smrg    return (dev->type == MASTER_KEYBOARD) ||
3286747b715Smrg            ((dev->key && dev->kbdfeed) && !IsPointerDevice(dev));
3296747b715Smrg}
3306747b715Smrg
3316747b715SmrgBool
3326747b715SmrgIsMaster(DeviceIntPtr dev)
3336747b715Smrg{
3346747b715Smrg    return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
3354642e01fSmrg}
33605b261ecSmrg
33705b261ecSmrgstatic WindowPtr XYToWindow(
3384642e01fSmrg    DeviceIntPtr pDev,
33905b261ecSmrg    int x,
34005b261ecSmrg    int y
34105b261ecSmrg);
34205b261ecSmrg
34305b261ecSmrg/**
34405b261ecSmrg * Max event opcode.
34505b261ecSmrg */
34605b261ecSmrgextern int lastEvent;
34705b261ecSmrg
34805b261ecSmrgextern int DeviceMotionNotify;
34905b261ecSmrg
3506747b715Smrg#define CantBeFiltered NoEventMask
3514642e01fSmrg/**
3526747b715Smrg * Event masks for each event type.
3536747b715Smrg *
3546747b715Smrg * One set of filters for each device, but only the first layer
3554642e01fSmrg * is initialized. The rest is memcpy'd in InitEvents.
3566747b715Smrg *
3576747b715Smrg * Filters are used whether a given event may be delivered to a client,
3586747b715Smrg * usually in the form of if (window-event-mask & filter); then deliver event.
3596747b715Smrg *
3606747b715Smrg * One notable filter is for PointerMotion/DevicePointerMotion events. Each
3616747b715Smrg * time a button is pressed, the filter is modified to also contain the
3626747b715Smrg * matching ButtonXMotion mask.
3634642e01fSmrg */
3644642e01fSmrgstatic Mask filters[MAXDEVICES][128] = {
36505b261ecSmrg{
36605b261ecSmrg	NoSuchEvent,		       /* 0 */
36705b261ecSmrg	NoSuchEvent,		       /* 1 */
36805b261ecSmrg	KeyPressMask,		       /* KeyPress */
36905b261ecSmrg	KeyReleaseMask,		       /* KeyRelease */
37005b261ecSmrg	ButtonPressMask,	       /* ButtonPress */
37105b261ecSmrg	ButtonReleaseMask,	       /* ButtonRelease */
37205b261ecSmrg	PointerMotionMask,	       /* MotionNotify (initial state) */
37305b261ecSmrg	EnterWindowMask,	       /* EnterNotify */
37405b261ecSmrg	LeaveWindowMask,	       /* LeaveNotify */
37505b261ecSmrg	FocusChangeMask,	       /* FocusIn */
37605b261ecSmrg	FocusChangeMask,	       /* FocusOut */
37705b261ecSmrg	KeymapStateMask,	       /* KeymapNotify */
37805b261ecSmrg	ExposureMask,		       /* Expose */
37905b261ecSmrg	CantBeFiltered,		       /* GraphicsExpose */
38005b261ecSmrg	CantBeFiltered,		       /* NoExpose */
38105b261ecSmrg	VisibilityChangeMask,	       /* VisibilityNotify */
38205b261ecSmrg	SubstructureNotifyMask,	       /* CreateNotify */
38305b261ecSmrg	StructureAndSubMask,	       /* DestroyNotify */
38405b261ecSmrg	StructureAndSubMask,	       /* UnmapNotify */
38505b261ecSmrg	StructureAndSubMask,	       /* MapNotify */
38605b261ecSmrg	SubstructureRedirectMask,      /* MapRequest */
38705b261ecSmrg	StructureAndSubMask,	       /* ReparentNotify */
38805b261ecSmrg	StructureAndSubMask,	       /* ConfigureNotify */
38905b261ecSmrg	SubstructureRedirectMask,      /* ConfigureRequest */
39005b261ecSmrg	StructureAndSubMask,	       /* GravityNotify */
39105b261ecSmrg	ResizeRedirectMask,	       /* ResizeRequest */
39205b261ecSmrg	StructureAndSubMask,	       /* CirculateNotify */
39305b261ecSmrg	SubstructureRedirectMask,      /* CirculateRequest */
39405b261ecSmrg	PropertyChangeMask,	       /* PropertyNotify */
39505b261ecSmrg	CantBeFiltered,		       /* SelectionClear */
39605b261ecSmrg	CantBeFiltered,		       /* SelectionRequest */
39705b261ecSmrg	CantBeFiltered,		       /* SelectionNotify */
39805b261ecSmrg	ColormapChangeMask,	       /* ColormapNotify */
39905b261ecSmrg	CantBeFiltered,		       /* ClientMessage */
40005b261ecSmrg	CantBeFiltered		       /* MappingNotify */
4014642e01fSmrg}};
4024642e01fSmrg
4036747b715Smrg/**
4046747b715Smrg * For the given event, return the matching event filter. This filter may then
4056747b715Smrg * be AND'ed with the selected event mask.
4066747b715Smrg *
4076747b715Smrg * For XI2 events, the returned filter is simply the byte containing the event
4086747b715Smrg * mask we're interested in. E.g. for a mask of (1 << 13), this would be
4096747b715Smrg * byte[1].
4106747b715Smrg *
4116747b715Smrg * @param[in] dev The device the event belongs to, may be NULL.
4126747b715Smrg * @param[in] event The event to get the filter for. Only the type of the
4136747b715Smrg *                  event matters, or the extension + evtype for GenericEvents.
4146747b715Smrg * @return The filter mask for the given event.
4156747b715Smrg *
4166747b715Smrg * @see GetEventMask
4176747b715Smrg */
4186747b715SmrgMask
4196747b715SmrgGetEventFilter(DeviceIntPtr dev, xEvent *event)
4206747b715Smrg{
4216747b715Smrg    if (event->u.u.type != GenericEvent)
4226747b715Smrg        return filters[dev ? dev->id : 0][event->u.u.type];
4236747b715Smrg    else if (XI2_EVENT(event))
4246747b715Smrg        return (1 << (((xXIDeviceEvent*)event)->evtype % 8));
4256747b715Smrg    ErrorF("[dix] Unknown device type %d. No filter\n", event->u.u.type);
4266747b715Smrg    return 0;
4276747b715Smrg}
4284642e01fSmrg
4294642e01fSmrg/**
4306747b715Smrg * Return the windows complete XI2 mask for the given XI2 event type.
4314642e01fSmrg */
4326747b715SmrgMask
4336747b715SmrgGetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev)
4346747b715Smrg{
4356747b715Smrg    OtherInputMasks *inputMasks = wOtherInputMasks(win);
4366747b715Smrg    int filter;
4376747b715Smrg    int evtype;
4386747b715Smrg
4396747b715Smrg    if (!inputMasks || !XI2_EVENT(ev))
4406747b715Smrg        return 0;
4416747b715Smrg
4426747b715Smrg    evtype = ((xGenericEvent*)ev)->evtype;
4436747b715Smrg    filter = GetEventFilter(dev, ev);
4446747b715Smrg
4456747b715Smrg    return ((inputMasks->xi2mask[dev->id][evtype/8] & filter) ||
4466747b715Smrg            inputMasks->xi2mask[XIAllDevices][evtype/8] ||
4476747b715Smrg            (inputMasks->xi2mask[XIAllMasterDevices][evtype/8] && IsMaster(dev)));
4486747b715Smrg}
4496747b715Smrg
4506747b715Smrgstatic Mask
4516747b715SmrgGetEventMask(DeviceIntPtr dev, xEvent *event, InputClients* other)
4526747b715Smrg{
4536747b715Smrg    /* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */
4546747b715Smrg    if (XI2_EVENT(event))
4556747b715Smrg    {
4566747b715Smrg        int byte = ((xGenericEvent*)event)->evtype / 8;
4576747b715Smrg        return (other->xi2mask[dev->id][byte] |
4586747b715Smrg                other->xi2mask[XIAllDevices][byte] |
4596747b715Smrg                (IsMaster(dev)? other->xi2mask[XIAllMasterDevices][byte] : 0));
4606747b715Smrg    } else if (CORE_EVENT(event))
4616747b715Smrg        return other->mask[XIAllDevices];
4626747b715Smrg    else
4636747b715Smrg        return other->mask[dev->id];
4646747b715Smrg}
4656747b715Smrg
46605b261ecSmrg
46705b261ecSmrgstatic CARD8 criticalEvents[32] =
46805b261ecSmrg{
4694642e01fSmrg    0x7c, 0x30, 0x40			/* key, button, expose, and configure events */
47005b261ecSmrg};
47105b261ecSmrg
4726747b715Smrgstatic void
4736747b715SmrgSyntheticMotion(DeviceIntPtr dev, int x, int y) {
4746747b715Smrg    int screenno = 0;
4756747b715Smrg
4766747b715Smrg#ifdef PANORAMIX
4776747b715Smrg    if (!noPanoramiXExtension)
4786747b715Smrg        screenno = dev->spriteInfo->sprite->screen->myNum;
4796747b715Smrg#endif
4806747b715Smrg    PostSyntheticMotion(dev, x, y, screenno,
4816747b715Smrg            (syncEvents.playingEvents) ?  syncEvents.time.milliseconds : currentTime.milliseconds);
4826747b715Smrg
4836747b715Smrg}
4846747b715Smrg
48505b261ecSmrg#ifdef PANORAMIX
4864642e01fSmrgstatic void PostNewCursor(DeviceIntPtr pDev);
48705b261ecSmrg
4886747b715Smrgstatic Bool
4896747b715SmrgpointOnScreen(ScreenPtr pScreen, int x, int y)
4906747b715Smrg{
4916747b715Smrg    return x >= pScreen->x && x < pScreen->x + pScreen->width &&
4926747b715Smrg           y >= pScreen->y && y < pScreen->y + pScreen->height;
4936747b715Smrg}
49405b261ecSmrg
49505b261ecSmrgstatic Bool
49605b261ecSmrgXineramaSetCursorPosition(
4974642e01fSmrg    DeviceIntPtr pDev,
4984642e01fSmrg    int x,
4994642e01fSmrg    int y,
50005b261ecSmrg    Bool generateEvent
50105b261ecSmrg){
50205b261ecSmrg    ScreenPtr pScreen;
50305b261ecSmrg    int i;
5044642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
50505b261ecSmrg
50605b261ecSmrg    /* x,y are in Screen 0 coordinates.  We need to decide what Screen
5074642e01fSmrg       to send the message too and what the coordinates relative to
50805b261ecSmrg       that screen are. */
50905b261ecSmrg
5104642e01fSmrg    pScreen = pSprite->screen;
5116747b715Smrg    x += screenInfo.screens[0]->x;
5126747b715Smrg    y += screenInfo.screens[0]->y;
51305b261ecSmrg
5146747b715Smrg    if(!pointOnScreen(pScreen, x, y))
51505b261ecSmrg    {
5164642e01fSmrg	FOR_NSCREENS(i)
51705b261ecSmrg	{
5184642e01fSmrg	    if(i == pScreen->myNum)
51905b261ecSmrg		continue;
5206747b715Smrg	    if(pointOnScreen(screenInfo.screens[i], x, y))
52105b261ecSmrg	    {
52205b261ecSmrg		pScreen = screenInfo.screens[i];
52305b261ecSmrg		break;
52405b261ecSmrg	    }
52505b261ecSmrg	}
52605b261ecSmrg    }
52705b261ecSmrg
5284642e01fSmrg    pSprite->screen = pScreen;
5296747b715Smrg    pSprite->hotPhys.x = x - screenInfo.screens[0]->x;
5306747b715Smrg    pSprite->hotPhys.y = y - screenInfo.screens[0]->y;
5316747b715Smrg    x -= pScreen->x;
5326747b715Smrg    y -= pScreen->y;
53305b261ecSmrg
5344642e01fSmrg    return (*pScreen->SetCursorPosition)(pDev, pScreen, x, y, generateEvent);
53505b261ecSmrg}
53605b261ecSmrg
53705b261ecSmrg
53805b261ecSmrgstatic void
5394642e01fSmrgXineramaConstrainCursor(DeviceIntPtr pDev)
54005b261ecSmrg{
5414642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
5424642e01fSmrg    ScreenPtr pScreen;
5434642e01fSmrg    BoxRec newBox;
5444642e01fSmrg
5454642e01fSmrg    pScreen = pSprite->screen;
5464642e01fSmrg    newBox = pSprite->physLimits;
54705b261ecSmrg
54805b261ecSmrg    /* Translate the constraining box to the screen
54905b261ecSmrg       the sprite is actually on */
5506747b715Smrg    newBox.x1 += screenInfo.screens[0]->x - pScreen->x;
5516747b715Smrg    newBox.x2 += screenInfo.screens[0]->x - pScreen->x;
5526747b715Smrg    newBox.y1 += screenInfo.screens[0]->y - pScreen->y;
5536747b715Smrg    newBox.y2 += screenInfo.screens[0]->y - pScreen->y;
55405b261ecSmrg
5554642e01fSmrg    (* pScreen->ConstrainCursor)(pDev, pScreen, &newBox);
55605b261ecSmrg}
55705b261ecSmrg
55805b261ecSmrg
55905b261ecSmrgstatic Bool
5604642e01fSmrgXineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
56105b261ecSmrg{
5624642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
5634642e01fSmrg
5646747b715Smrg    if(pWin == screenInfo.screens[0]->root) {
5656747b715Smrg	int i;
5666747b715Smrg	for (i = 0; i < PanoramiXNumScreens; i++)
5676747b715Smrg	    pSprite->windows[i] = screenInfo.screens[i]->root;
56805b261ecSmrg    } else {
56905b261ecSmrg	PanoramiXRes *win;
5706747b715Smrg	int rc, i;
57105b261ecSmrg
5726747b715Smrg	rc = dixLookupResourceByType((pointer *)&win, pWin->drawable.id,
5736747b715Smrg				     XRT_WINDOW, serverClient, DixReadAccess);
5746747b715Smrg	if (rc != Success)
57505b261ecSmrg	    return FALSE;
57605b261ecSmrg
57705b261ecSmrg	for(i = 0; i < PanoramiXNumScreens; i++) {
5786747b715Smrg	    rc = dixLookupWindow(pSprite->windows + i, win->info[i].id,
5796747b715Smrg				 serverClient, DixReadAccess);
5806747b715Smrg	    if (rc != Success)  /* window is being unmapped */
58105b261ecSmrg		return FALSE;
58205b261ecSmrg	}
58305b261ecSmrg    }
58405b261ecSmrg    return TRUE;
58505b261ecSmrg}
58605b261ecSmrg
58705b261ecSmrgstatic void
5884642e01fSmrgXineramaConfineCursorToWindow(DeviceIntPtr pDev,
5894642e01fSmrg                              WindowPtr pWin,
5904642e01fSmrg                              Bool generateEvents)
59105b261ecSmrg{
5924642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
59305b261ecSmrg
5946747b715Smrg    int x, y, off_x, off_y, i;
59505b261ecSmrg
5966747b715Smrg    if(!XineramaSetWindowPntrs(pDev, pWin))
5976747b715Smrg        return;
5984642e01fSmrg
5996747b715Smrg    i = PanoramiXNumScreens - 1;
60005b261ecSmrg
6016747b715Smrg    RegionCopy(&pSprite->Reg1,
6026747b715Smrg            &pSprite->windows[i]->borderSize);
6036747b715Smrg    off_x = screenInfo.screens[i]->x;
6046747b715Smrg    off_y = screenInfo.screens[i]->y;
60505b261ecSmrg
6066747b715Smrg    while(i--) {
6076747b715Smrg        x = off_x - screenInfo.screens[i]->x;
6086747b715Smrg        y = off_y - screenInfo.screens[i]->y;
60905b261ecSmrg
6106747b715Smrg        if(x || y)
6116747b715Smrg            RegionTranslate(&pSprite->Reg1, x, y);
61205b261ecSmrg
6136747b715Smrg        RegionUnion(&pSprite->Reg1, &pSprite->Reg1,
6146747b715Smrg                &pSprite->windows[i]->borderSize);
6154642e01fSmrg
6166747b715Smrg        off_x = screenInfo.screens[i]->x;
6176747b715Smrg        off_y = screenInfo.screens[i]->y;
61805b261ecSmrg    }
61905b261ecSmrg
6206747b715Smrg    pSprite->hotLimits = *RegionExtents(&pSprite->Reg1);
62105b261ecSmrg
6226747b715Smrg    if(RegionNumRects(&pSprite->Reg1) > 1)
6236747b715Smrg        pSprite->hotShape = &pSprite->Reg1;
6246747b715Smrg    else
6256747b715Smrg        pSprite->hotShape = NullRegion;
6264642e01fSmrg
6276747b715Smrg    pSprite->confined = FALSE;
6286747b715Smrg    pSprite->confineWin = (pWin == screenInfo.screens[0]->root) ? NullWindow : pWin;
62905b261ecSmrg
6306747b715Smrg    CheckPhysLimits(pDev, pSprite->current, generateEvents, FALSE, NULL);
6316747b715Smrg}
63205b261ecSmrg
63305b261ecSmrg#endif  /* PANORAMIX */
63405b261ecSmrg
6356747b715Smrg/**
6366747b715Smrg * Modifies the filter for the given protocol event type to the given masks.
6376747b715Smrg *
6386747b715Smrg * There's only two callers: UpdateDeviceState() and XI's SetMaskForExtEvent().
6396747b715Smrg * The latter initialises masks for the matching XI events, it's a once-off
6406747b715Smrg * setting.
6416747b715Smrg * UDS however changes the mask for MotionNotify and DeviceMotionNotify each
6426747b715Smrg * time a button is pressed to include the matching ButtonXMotion mask in the
6436747b715Smrg * filter.
6446747b715Smrg *
6456747b715Smrg * @param[in] deviceid The device to modify the filter for.
6466747b715Smrg * @param[in] mask The new filter mask.
6476747b715Smrg * @param[in] event Protocol event type.
6486747b715Smrg */
64905b261ecSmrgvoid
6504642e01fSmrgSetMaskForEvent(int deviceid, Mask mask, int event)
65105b261ecSmrg{
65252397711Smrg    if (deviceid < 0 || deviceid >= MAXDEVICES)
6534642e01fSmrg        FatalError("SetMaskForEvent: bogus device id");
6544642e01fSmrg    filters[deviceid][event] = mask;
65505b261ecSmrg}
65605b261ecSmrg
6576747b715Smrgvoid
65805b261ecSmrgSetCriticalEvent(int event)
65905b261ecSmrg{
66005b261ecSmrg    if (event >= 128)
66105b261ecSmrg	FatalError("SetCriticalEvent: bogus event number");
66205b261ecSmrg    criticalEvents[event >> 3] |= 1 << (event & 7);
66305b261ecSmrg}
66405b261ecSmrg
6654642e01fSmrgvoid
6664642e01fSmrgConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
66705b261ecSmrg{
66805b261ecSmrg    BoxRec box;
66905b261ecSmrg    int x = *px, y = *py;
67005b261ecSmrg    int incx = 1, incy = 1;
6714642e01fSmrg    SpritePtr pSprite;
67205b261ecSmrg
6734642e01fSmrg    pSprite = pDev->spriteInfo->sprite;
6746747b715Smrg    if (RegionContainsPoint(shape, x, y, &box))
67505b261ecSmrg	return;
6766747b715Smrg    box = *RegionExtents(shape);
67705b261ecSmrg    /* this is rather crude */
67805b261ecSmrg    do {
67905b261ecSmrg	x += incx;
68005b261ecSmrg	if (x >= box.x2)
68105b261ecSmrg	{
68205b261ecSmrg	    incx = -1;
68305b261ecSmrg	    x = *px - 1;
68405b261ecSmrg	}
68505b261ecSmrg	else if (x < box.x1)
68605b261ecSmrg	{
68705b261ecSmrg	    incx = 1;
68805b261ecSmrg	    x = *px;
68905b261ecSmrg	    y += incy;
69005b261ecSmrg	    if (y >= box.y2)
69105b261ecSmrg	    {
69205b261ecSmrg		incy = -1;
69305b261ecSmrg		y = *py - 1;
69405b261ecSmrg	    }
69505b261ecSmrg	    else if (y < box.y1)
69605b261ecSmrg		return; /* should never get here! */
69705b261ecSmrg	}
6986747b715Smrg    } while (!RegionContainsPoint(shape, x, y, &box));
69905b261ecSmrg    *px = x;
70005b261ecSmrg    *py = y;
70105b261ecSmrg}
70205b261ecSmrg
70305b261ecSmrgstatic void
70405b261ecSmrgCheckPhysLimits(
7054642e01fSmrg    DeviceIntPtr pDev,
70605b261ecSmrg    CursorPtr cursor,
70705b261ecSmrg    Bool generateEvents,
7086747b715Smrg    Bool confineToScreen, /* unused if PanoramiX on */
7096747b715Smrg    ScreenPtr pScreen)    /* unused if PanoramiX on */
71005b261ecSmrg{
71105b261ecSmrg    HotSpot new;
7124642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
71305b261ecSmrg
71405b261ecSmrg    if (!cursor)
71505b261ecSmrg	return;
7164642e01fSmrg    new = pSprite->hotPhys;
7176747b715Smrg#ifdef PANORAMIX
7186747b715Smrg    if (!noPanoramiXExtension)
7196747b715Smrg        /* I don't care what the DDX has to say about it */
7206747b715Smrg        pSprite->physLimits = pSprite->hotLimits;
72105b261ecSmrg    else
7226747b715Smrg#endif
7236747b715Smrg    {
7246747b715Smrg        if (pScreen)
7256747b715Smrg            new.pScreen = pScreen;
7266747b715Smrg        else
7276747b715Smrg            pScreen = new.pScreen;
7286747b715Smrg        (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits,
7296747b715Smrg                &pSprite->physLimits);
7306747b715Smrg        pSprite->confined = confineToScreen;
7316747b715Smrg        (* pScreen->ConstrainCursor)(pDev, pScreen, &pSprite->physLimits);
7326747b715Smrg    }
7336747b715Smrg
7346747b715Smrg    /* constrain the pointer to those limits */
7354642e01fSmrg    if (new.x < pSprite->physLimits.x1)
7364642e01fSmrg	new.x = pSprite->physLimits.x1;
73705b261ecSmrg    else
7384642e01fSmrg	if (new.x >= pSprite->physLimits.x2)
7394642e01fSmrg	    new.x = pSprite->physLimits.x2 - 1;
7404642e01fSmrg    if (new.y < pSprite->physLimits.y1)
7414642e01fSmrg	new.y = pSprite->physLimits.y1;
74205b261ecSmrg    else
7434642e01fSmrg	if (new.y >= pSprite->physLimits.y2)
7444642e01fSmrg	    new.y = pSprite->physLimits.y2 - 1;
7454642e01fSmrg    if (pSprite->hotShape)
7464642e01fSmrg	ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y);
7476747b715Smrg    if ((
7486747b715Smrg#ifdef PANORAMIX
7496747b715Smrg            noPanoramiXExtension &&
7506747b715Smrg#endif
7516747b715Smrg            (pScreen != pSprite->hotPhys.pScreen)) ||
7524642e01fSmrg	(new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y))
7534642e01fSmrg    {
7546747b715Smrg#ifdef PANORAMIX
7556747b715Smrg        if (!noPanoramiXExtension)
7566747b715Smrg            XineramaSetCursorPosition (pDev, new.x, new.y, generateEvents);
7576747b715Smrg        else
7586747b715Smrg#endif
7596747b715Smrg        {
7606747b715Smrg            if (pScreen != pSprite->hotPhys.pScreen)
7616747b715Smrg                pSprite->hotPhys = new;
7626747b715Smrg            (*pScreen->SetCursorPosition)
7636747b715Smrg                (pDev, pScreen, new.x, new.y, generateEvents);
7646747b715Smrg        }
7654642e01fSmrg        if (!generateEvents)
7666747b715Smrg            SyntheticMotion(pDev, new.x, new.y);
76705b261ecSmrg    }
7686747b715Smrg
7696747b715Smrg#ifdef PANORAMIX
7706747b715Smrg    /* Tell DDX what the limits are */
7716747b715Smrg    if (!noPanoramiXExtension)
7726747b715Smrg        XineramaConstrainCursor(pDev);
7736747b715Smrg#endif
77405b261ecSmrg}
77505b261ecSmrg
77605b261ecSmrgstatic void
77705b261ecSmrgCheckVirtualMotion(
7784642e01fSmrg    DeviceIntPtr pDev,
77905b261ecSmrg    QdEventPtr qe,
78005b261ecSmrg    WindowPtr pWin)
78105b261ecSmrg{
7824642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
7836747b715Smrg    RegionPtr reg = NULL;
7846747b715Smrg    DeviceEvent *ev = NULL;
7854642e01fSmrg
78605b261ecSmrg    if (qe)
78705b261ecSmrg    {
7886747b715Smrg        ev = &qe->event->device_event;
7896747b715Smrg        switch(ev->type)
7906747b715Smrg        {
7916747b715Smrg            case ET_Motion:
7926747b715Smrg            case ET_ButtonPress:
7936747b715Smrg            case ET_ButtonRelease:
7946747b715Smrg            case ET_KeyPress:
7956747b715Smrg            case ET_KeyRelease:
7966747b715Smrg            case ET_ProximityIn:
7976747b715Smrg            case ET_ProximityOut:
7986747b715Smrg                pSprite->hot.pScreen = qe->pScreen;
7996747b715Smrg                pSprite->hot.x = ev->root_x;
8006747b715Smrg                pSprite->hot.y = ev->root_y;
8016747b715Smrg                pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo : NullWindow;
8026747b715Smrg                break;
8036747b715Smrg            default:
8046747b715Smrg                break;
8056747b715Smrg        }
80605b261ecSmrg    }
80705b261ecSmrg    if (pWin)
80805b261ecSmrg    {
80905b261ecSmrg	BoxRec lims;
81005b261ecSmrg
8116747b715Smrg#ifdef PANORAMIX
8126747b715Smrg        if (!noPanoramiXExtension) {
8136747b715Smrg            int x, y, off_x, off_y, i;
8146747b715Smrg
8156747b715Smrg            if(!XineramaSetWindowPntrs(pDev, pWin))
8166747b715Smrg                return;
8176747b715Smrg
8186747b715Smrg            i = PanoramiXNumScreens - 1;
8196747b715Smrg
8206747b715Smrg            RegionCopy(&pSprite->Reg2,
8216747b715Smrg                    &pSprite->windows[i]->borderSize);
8226747b715Smrg            off_x = screenInfo.screens[i]->x;
8236747b715Smrg            off_y = screenInfo.screens[i]->y;
8246747b715Smrg
8256747b715Smrg            while(i--) {
8266747b715Smrg                x = off_x - screenInfo.screens[i]->x;
8276747b715Smrg                y = off_y - screenInfo.screens[i]->y;
8286747b715Smrg
8296747b715Smrg                if(x || y)
8306747b715Smrg                    RegionTranslate(&pSprite->Reg2, x, y);
8316747b715Smrg
8326747b715Smrg                RegionUnion(&pSprite->Reg2, &pSprite->Reg2,
8336747b715Smrg                        &pSprite->windows[i]->borderSize);
8346747b715Smrg
8356747b715Smrg                off_x = screenInfo.screens[i]->x;
8366747b715Smrg                off_y = screenInfo.screens[i]->y;
8376747b715Smrg            }
8386747b715Smrg        } else
8396747b715Smrg#endif
8406747b715Smrg        {
8416747b715Smrg            if (pSprite->hot.pScreen != pWin->drawable.pScreen)
8426747b715Smrg            {
8436747b715Smrg                pSprite->hot.pScreen = pWin->drawable.pScreen;
8446747b715Smrg                pSprite->hot.x = pSprite->hot.y = 0;
8456747b715Smrg            }
8466747b715Smrg        }
8476747b715Smrg
8486747b715Smrg	lims = *RegionExtents(&pWin->borderSize);
8494642e01fSmrg	if (pSprite->hot.x < lims.x1)
8504642e01fSmrg	    pSprite->hot.x = lims.x1;
8514642e01fSmrg	else if (pSprite->hot.x >= lims.x2)
8524642e01fSmrg	    pSprite->hot.x = lims.x2 - 1;
8534642e01fSmrg	if (pSprite->hot.y < lims.y1)
8544642e01fSmrg	    pSprite->hot.y = lims.y1;
8554642e01fSmrg	else if (pSprite->hot.y >= lims.y2)
8564642e01fSmrg	    pSprite->hot.y = lims.y2 - 1;
8576747b715Smrg
8586747b715Smrg#ifdef PANORAMIX
8596747b715Smrg        if (!noPanoramiXExtension)
8606747b715Smrg        {
8616747b715Smrg            if (RegionNumRects(&pSprite->Reg2) > 1)
8626747b715Smrg                reg = &pSprite->Reg2;
8636747b715Smrg
8646747b715Smrg        } else
8656747b715Smrg#endif
8666747b715Smrg        {
8676747b715Smrg            if (wBoundingShape(pWin))
8686747b715Smrg                reg = &pWin->borderSize;
8696747b715Smrg        }
8706747b715Smrg
8716747b715Smrg        if (reg)
8726747b715Smrg            ConfineToShape(pDev, reg, &pSprite->hot.x, &pSprite->hot.y);
8736747b715Smrg
8746747b715Smrg	if (qe && ev)
87505b261ecSmrg	{
8764642e01fSmrg	    qe->pScreen = pSprite->hot.pScreen;
8776747b715Smrg	    ev->root_x = pSprite->hot.x;
8786747b715Smrg	    ev->root_y = pSprite->hot.y;
87905b261ecSmrg	}
88005b261ecSmrg    }
8816747b715Smrg#ifdef PANORAMIX
8826747b715Smrg    if (noPanoramiXExtension) /* No typo. Only set the root win if disabled */
8836747b715Smrg#endif
8846747b715Smrg        RootWindow(pDev) = pSprite->hot.pScreen->root;
88505b261ecSmrg}
88605b261ecSmrg
88705b261ecSmrgstatic void
8884642e01fSmrgConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
88905b261ecSmrg{
8904642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
89105b261ecSmrg
89205b261ecSmrg    if (syncEvents.playingEvents)
89305b261ecSmrg    {
8944642e01fSmrg	CheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin);
8954642e01fSmrg	SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y);
89605b261ecSmrg    }
89705b261ecSmrg    else
89805b261ecSmrg    {
8996747b715Smrg#ifdef PANORAMIX
9006747b715Smrg        if(!noPanoramiXExtension) {
9016747b715Smrg            XineramaConfineCursorToWindow(pDev, pWin, generateEvents);
9026747b715Smrg            return;
9036747b715Smrg        }
9046747b715Smrg#endif
9056747b715Smrg	pSprite->hotLimits = *RegionExtents(&pWin->borderSize);
9064642e01fSmrg	pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize
90705b261ecSmrg					       : NullRegion;
9084642e01fSmrg        CheckPhysLimits(pDev, pSprite->current, generateEvents,
9096747b715Smrg                        confineToScreen, pWin->drawable.pScreen);
91005b261ecSmrg    }
91105b261ecSmrg}
91205b261ecSmrg
9136747b715SmrgBool
9144642e01fSmrgPointerConfinedToScreen(DeviceIntPtr pDev)
91505b261ecSmrg{
9164642e01fSmrg    return pDev->spriteInfo->sprite->confined;
91705b261ecSmrg}
91805b261ecSmrg
91905b261ecSmrg/**
92005b261ecSmrg * Update the sprite cursor to the given cursor.
92105b261ecSmrg *
92205b261ecSmrg * ChangeToCursor() will display the new cursor and free the old cursor (if
92305b261ecSmrg * applicable). If the provided cursor is already the updated cursor, nothing
92405b261ecSmrg * happens.
92505b261ecSmrg */
92605b261ecSmrgstatic void
9274642e01fSmrgChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
92805b261ecSmrg{
9294642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
9306747b715Smrg    ScreenPtr pScreen;
93105b261ecSmrg
9324642e01fSmrg    if (cursor != pSprite->current)
93305b261ecSmrg    {
9344642e01fSmrg	if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
9354642e01fSmrg		(pSprite->current->bits->yhot != cursor->bits->yhot))
9364642e01fSmrg	    CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined,
93705b261ecSmrg			    (ScreenPtr)NULL);
9386747b715Smrg#ifdef PANORAMIX
9396747b715Smrg        /* XXX: is this really necessary?? (whot) */
9406747b715Smrg        if (!noPanoramiXExtension)
9416747b715Smrg            pScreen = pSprite->screen;
9426747b715Smrg        else
9436747b715Smrg#endif
9446747b715Smrg            pScreen = pSprite->hotPhys.pScreen;
9456747b715Smrg
9466747b715Smrg        (*pScreen->DisplayCursor)(pDev, pScreen, cursor);
9474642e01fSmrg	FreeCursor(pSprite->current, (Cursor)0);
9484642e01fSmrg	pSprite->current = cursor;
9494642e01fSmrg	pSprite->current->refcnt++;
95005b261ecSmrg    }
95105b261ecSmrg}
95205b261ecSmrg
95305b261ecSmrg/**
9544642e01fSmrg * @returns true if b is a descendent of a
95505b261ecSmrg */
95605b261ecSmrgBool
95705b261ecSmrgIsParent(WindowPtr a, WindowPtr b)
95805b261ecSmrg{
95905b261ecSmrg    for (b = b->parent; b; b = b->parent)
96005b261ecSmrg	if (b == a) return TRUE;
96105b261ecSmrg    return FALSE;
96205b261ecSmrg}
96305b261ecSmrg
96405b261ecSmrg/**
96505b261ecSmrg * Update the cursor displayed on the screen.
96605b261ecSmrg *
9674642e01fSmrg * Called whenever a cursor may have changed shape or position.
96805b261ecSmrg */
96905b261ecSmrgstatic void
9704642e01fSmrgPostNewCursor(DeviceIntPtr pDev)
97105b261ecSmrg{
97205b261ecSmrg    WindowPtr win;
9734642e01fSmrg    GrabPtr grab = pDev->deviceGrab.grab;
9744642e01fSmrg    SpritePtr   pSprite = pDev->spriteInfo->sprite;
9754642e01fSmrg    CursorPtr   pCursor;
97605b261ecSmrg
97705b261ecSmrg    if (syncEvents.playingEvents)
97805b261ecSmrg	return;
97905b261ecSmrg    if (grab)
98005b261ecSmrg    {
98105b261ecSmrg	if (grab->cursor)
98205b261ecSmrg	{
9834642e01fSmrg	    ChangeToCursor(pDev, grab->cursor);
98405b261ecSmrg	    return;
98505b261ecSmrg	}
9864642e01fSmrg	if (IsParent(grab->window, pSprite->win))
9874642e01fSmrg	    win = pSprite->win;
98805b261ecSmrg	else
98905b261ecSmrg	    win = grab->window;
99005b261ecSmrg    }
99105b261ecSmrg    else
9924642e01fSmrg	win = pSprite->win;
99305b261ecSmrg    for (; win; win = win->parent)
9944642e01fSmrg    {
9954642e01fSmrg	if (win->optional)
9964642e01fSmrg        {
9974642e01fSmrg            pCursor = WindowGetDeviceCursor(win, pDev);
9984642e01fSmrg            if (!pCursor && win->optional->cursor != NullCursor)
9994642e01fSmrg                pCursor = win->optional->cursor;
10004642e01fSmrg            if (pCursor)
10014642e01fSmrg            {
10024642e01fSmrg                ChangeToCursor(pDev, pCursor);
10034642e01fSmrg                return;
10044642e01fSmrg            }
100505b261ecSmrg	}
10064642e01fSmrg    }
100705b261ecSmrg}
100805b261ecSmrg
10094642e01fSmrg
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{
10174642e01fSmrg    return RootWindow(dev);
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;
10454642e01fSmrg    *px = pSprite->hotPhys.x;
10464642e01fSmrg    *py = pSprite->hotPhys.y;
104705b261ecSmrg}
104805b261ecSmrg
104905b261ecSmrg#ifdef PANORAMIX
10506747b715Smrgint
10514642e01fSmrgXineramaGetCursorScreen(DeviceIntPtr pDev)
105205b261ecSmrg{
105305b261ecSmrg    if(!noPanoramiXExtension) {
10544642e01fSmrg	return pDev->spriteInfo->sprite->screen->myNum;
105505b261ecSmrg    } else {
105605b261ecSmrg	return 0;
105705b261ecSmrg    }
105805b261ecSmrg}
105905b261ecSmrg#endif /* PANORAMIX */
106005b261ecSmrg
106105b261ecSmrg#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */
106205b261ecSmrg
106305b261ecSmrgstatic void
10646747b715SmrgMonthChangedOrBadTime(InternalEvent *ev)
106505b261ecSmrg{
106605b261ecSmrg    /* If the ddx/OS is careless about not processing timestamped events from
106705b261ecSmrg     * different sources in sorted order, then it's possible for time to go
106805b261ecSmrg     * backwards when it should not.  Here we ensure a decent time.
106905b261ecSmrg     */
10706747b715Smrg    if ((currentTime.milliseconds - ev->any.time) > TIMESLOP)
107105b261ecSmrg	currentTime.months++;
107205b261ecSmrg    else
10736747b715Smrg        ev->any.time = currentTime.milliseconds;
107405b261ecSmrg}
107505b261ecSmrg
10766747b715Smrgstatic void
10776747b715SmrgNoticeTime(InternalEvent *ev)
10786747b715Smrg{
10796747b715Smrg    if (ev->any.time < currentTime.milliseconds)
10806747b715Smrg        MonthChangedOrBadTime(ev);
10816747b715Smrg    currentTime.milliseconds = ev->any.time;
10826747b715Smrg    lastDeviceEventTime = currentTime;
10836747b715Smrg}
108405b261ecSmrg
108505b261ecSmrgvoid
10866747b715SmrgNoticeEventTime(InternalEvent *ev)
108705b261ecSmrg{
108805b261ecSmrg    if (!syncEvents.playingEvents)
10896747b715Smrg	NoticeTime(ev);
109005b261ecSmrg}
109105b261ecSmrg
109205b261ecSmrg/**************************************************************************
109305b261ecSmrg *            The following procedures deal with synchronous events       *
109405b261ecSmrg **************************************************************************/
109505b261ecSmrg
10964642e01fSmrg/**
10974642e01fSmrg * EnqueueEvent is a device's processInputProc if a device is frozen.
10984642e01fSmrg * Instead of delivering the events to the client, the event is tacked onto a
10994642e01fSmrg * linked list for later delivery.
11004642e01fSmrg */
110105b261ecSmrgvoid
11026747b715SmrgEnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
110305b261ecSmrg{
11044642e01fSmrg    QdEventPtr	tail = *syncEvents.pendtail;
11054642e01fSmrg    QdEventPtr	qe;
11064642e01fSmrg    SpritePtr	pSprite = device->spriteInfo->sprite;
11074642e01fSmrg    int		eventlen;
11086747b715Smrg    DeviceEvent *event = &ev->device_event;
11094642e01fSmrg
11106747b715Smrg    NoticeTime((InternalEvent*)event);
111105b261ecSmrg
111205b261ecSmrg    /* Fix for key repeating bug. */
11134642e01fSmrg    if (device->key != NULL && device->key->xkbInfo != NULL &&
11146747b715Smrg        event->type == ET_KeyRelease)
11156747b715Smrg	AccessXCancelRepeatKey(device->key->xkbInfo, event->detail.key);
111605b261ecSmrg
111705b261ecSmrg    if (DeviceEventCallback)
111805b261ecSmrg    {
111905b261ecSmrg	DeviceEventInfoRec eventinfo;
11206747b715Smrg
112105b261ecSmrg	/*  The RECORD spec says that the root window field of motion events
112205b261ecSmrg	 *  must be valid.  At this point, it hasn't been filled in yet, so
112305b261ecSmrg	 *  we do it here.  The long expression below is necessary to get
112405b261ecSmrg	 *  the current root window; the apparently reasonable alternative
112505b261ecSmrg	 *  GetCurrentRootWindow()->drawable.id doesn't give you the right
112605b261ecSmrg	 *  answer on the first motion event after a screen change because
112705b261ecSmrg	 *  the data that GetCurrentRootWindow relies on hasn't been
112805b261ecSmrg	 *  updated yet.
112905b261ecSmrg	 */
11306747b715Smrg	if (ev->any.type == ET_Motion)
11316747b715Smrg	    ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
11326747b715Smrg
11336747b715Smrg	eventinfo.event = ev;
11346747b715Smrg	eventinfo.device = device;
113505b261ecSmrg	CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
113605b261ecSmrg    }
11376747b715Smrg
11386747b715Smrg    if (event->type == ET_Motion)
113905b261ecSmrg    {
114005b261ecSmrg#ifdef PANORAMIX
114105b261ecSmrg	if(!noPanoramiXExtension) {
11426747b715Smrg	    event->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
11436747b715Smrg	    event->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
114405b261ecSmrg	}
114505b261ecSmrg#endif
11466747b715Smrg	pSprite->hotPhys.x = event->root_x;
11476747b715Smrg	pSprite->hotPhys.y = event->root_y;
114805b261ecSmrg	/* do motion compression, but not if from different devices */
114905b261ecSmrg	if (tail &&
11506747b715Smrg	    (tail->event->any.type == ET_Motion) &&
115105b261ecSmrg            (tail->device == device) &&
11524642e01fSmrg	    (tail->pScreen == pSprite->hotPhys.pScreen))
115305b261ecSmrg	{
11546747b715Smrg            DeviceEvent *tailev = &tail->event->device_event;
11556747b715Smrg	    tailev->root_x = pSprite->hotPhys.x;
11566747b715Smrg	    tailev->root_y = pSprite->hotPhys.y;
11576747b715Smrg	    tailev->time = event->time;
115805b261ecSmrg	    tail->months = currentTime.months;
115905b261ecSmrg	    return;
116005b261ecSmrg	}
116105b261ecSmrg    }
11624642e01fSmrg
11636747b715Smrg    eventlen = event->length;
11644642e01fSmrg
11656747b715Smrg    qe = malloc(sizeof(QdEventRec) + eventlen);
116605b261ecSmrg    if (!qe)
116705b261ecSmrg	return;
116805b261ecSmrg    qe->next = (QdEventPtr)NULL;
116905b261ecSmrg    qe->device = device;
11704642e01fSmrg    qe->pScreen = pSprite->hotPhys.pScreen;
117105b261ecSmrg    qe->months = currentTime.months;
11726747b715Smrg    qe->event = (InternalEvent *)(qe + 1);
11736747b715Smrg    memcpy(qe->event, event, eventlen);
117405b261ecSmrg    if (tail)
117505b261ecSmrg	syncEvents.pendtail = &tail->next;
117605b261ecSmrg    *syncEvents.pendtail = qe;
117705b261ecSmrg}
117805b261ecSmrg
11794642e01fSmrg/**
11804642e01fSmrg * Run through the list of events queued up in syncEvents.
11814642e01fSmrg * For each event do:
11824642e01fSmrg * If the device for this event is not frozen anymore, take it and process it
11834642e01fSmrg * as usually.
11844642e01fSmrg * After that, check if there's any devices in the list that are not frozen.
11854642e01fSmrg * If there is none, we're done. If there is at least one device that is not
11864642e01fSmrg * frozen, then re-run from the beginning of the event queue.
11874642e01fSmrg */
118805b261ecSmrgstatic void
118905b261ecSmrgPlayReleasedEvents(void)
119005b261ecSmrg{
119105b261ecSmrg    QdEventPtr *prev, qe;
119205b261ecSmrg    DeviceIntPtr dev;
11934642e01fSmrg    DeviceIntPtr pDev;
119405b261ecSmrg
119505b261ecSmrg    prev = &syncEvents.pending;
119605b261ecSmrg    while ( (qe = *prev) )
119705b261ecSmrg    {
11984642e01fSmrg	if (!qe->device->deviceGrab.sync.frozen)
119905b261ecSmrg	{
120005b261ecSmrg	    *prev = qe->next;
12014642e01fSmrg            pDev = qe->device;
120205b261ecSmrg	    if (*syncEvents.pendtail == *prev)
120305b261ecSmrg		syncEvents.pendtail = prev;
12046747b715Smrg	    if (qe->event->any.type == ET_Motion)
12054642e01fSmrg		CheckVirtualMotion(pDev, qe, NullWindow);
120605b261ecSmrg	    syncEvents.time.months = qe->months;
12076747b715Smrg            syncEvents.time.milliseconds = qe->event->any.time;
120805b261ecSmrg#ifdef PANORAMIX
120905b261ecSmrg	   /* Translate back to the sprite screen since processInputProc
121005b261ecSmrg	      will translate from sprite screen to screen 0 upon reentry
121105b261ecSmrg	      to the DIX layer */
121205b261ecSmrg	    if(!noPanoramiXExtension) {
12136747b715Smrg                DeviceEvent *ev = &qe->event->device_event;
12146747b715Smrg                switch(ev->type)
12156747b715Smrg                {
12166747b715Smrg                    case ET_Motion:
12176747b715Smrg                    case ET_ButtonPress:
12186747b715Smrg                    case ET_ButtonRelease:
12196747b715Smrg                    case ET_KeyPress:
12206747b715Smrg                    case ET_KeyRelease:
12216747b715Smrg                    case ET_ProximityIn:
12226747b715Smrg                    case ET_ProximityOut:
12236747b715Smrg                        ev->root_x += screenInfo.screens[0]->x -
12246747b715Smrg                            pDev->spriteInfo->sprite->screen->x;
12256747b715Smrg                        ev->root_y += screenInfo.screens[0]->y -
12266747b715Smrg                            pDev->spriteInfo->sprite->screen->y;
12276747b715Smrg                        break;
12286747b715Smrg                    default:
12296747b715Smrg                        break;
12306747b715Smrg                }
12316747b715Smrg
123205b261ecSmrg	    }
123305b261ecSmrg#endif
12346747b715Smrg	    (*qe->device->public.processInputProc)(qe->event, qe->device);
12356747b715Smrg	    free(qe);
12364642e01fSmrg	    for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; dev = dev->next)
123705b261ecSmrg		;
123805b261ecSmrg	    if (!dev)
123905b261ecSmrg		break;
124005b261ecSmrg	    /* Playing the event may have unfrozen another device. */
124105b261ecSmrg	    /* So to play it safe, restart at the head of the queue */
124205b261ecSmrg	    prev = &syncEvents.pending;
124305b261ecSmrg	}
124405b261ecSmrg	else
124505b261ecSmrg	    prev = &qe->next;
12464642e01fSmrg    }
124705b261ecSmrg}
124805b261ecSmrg
12494642e01fSmrg/**
12504642e01fSmrg * Freeze or thaw the given devices. The device's processing proc is
12514642e01fSmrg * switched to either the real processing proc (in case of thawing) or an
12524642e01fSmrg * enqueuing processing proc (usually EnqueueEvent()).
12534642e01fSmrg *
12544642e01fSmrg * @param dev The device to freeze/thaw
12554642e01fSmrg * @param frozen True to freeze or false to thaw.
12564642e01fSmrg */
125705b261ecSmrgstatic void
125805b261ecSmrgFreezeThaw(DeviceIntPtr dev, Bool frozen)
125905b261ecSmrg{
12604642e01fSmrg    dev->deviceGrab.sync.frozen = frozen;
126105b261ecSmrg    if (frozen)
126205b261ecSmrg	dev->public.processInputProc = dev->public.enqueueInputProc;
126305b261ecSmrg    else
126405b261ecSmrg	dev->public.processInputProc = dev->public.realInputProc;
126505b261ecSmrg}
126605b261ecSmrg
12674642e01fSmrg/**
12684642e01fSmrg * Unfreeze devices and replay all events to the respective clients.
12694642e01fSmrg *
12704642e01fSmrg * ComputeFreezes takes the first event in the device's frozen event queue. It
12714642e01fSmrg * runs up the sprite tree (spriteTrace) and searches for the window to replay
12724642e01fSmrg * the events from. If it is found, it checks for passive grabs one down from
12734642e01fSmrg * the window or delivers the events.
12744642e01fSmrg */
12754642e01fSmrgstatic void
127605b261ecSmrgComputeFreezes(void)
127705b261ecSmrg{
127805b261ecSmrg    DeviceIntPtr replayDev = syncEvents.replayDev;
127905b261ecSmrg    int i;
128005b261ecSmrg    WindowPtr w;
128105b261ecSmrg    GrabPtr grab;
128205b261ecSmrg    DeviceIntPtr dev;
128305b261ecSmrg
128405b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
12854642e01fSmrg	FreezeThaw(dev, dev->deviceGrab.sync.other ||
12864642e01fSmrg                (dev->deviceGrab.sync.state >= FROZEN));
128705b261ecSmrg    if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
128805b261ecSmrg	return;
128905b261ecSmrg    syncEvents.playingEvents = TRUE;
129005b261ecSmrg    if (replayDev)
129105b261ecSmrg    {
12926747b715Smrg        DeviceEvent* event = replayDev->deviceGrab.sync.event;
12936747b715Smrg
129405b261ecSmrg	syncEvents.replayDev = (DeviceIntPtr)NULL;
129505b261ecSmrg
12966747b715Smrg        w = XYToWindow(replayDev, event->root_x, event->root_y);
12974642e01fSmrg	for (i = 0; i < replayDev->spriteInfo->sprite->spriteTraceGood; i++)
129805b261ecSmrg	{
12994642e01fSmrg	    if (syncEvents.replayWin ==
13004642e01fSmrg		replayDev->spriteInfo->sprite->spriteTrace[i])
130105b261ecSmrg	    {
13026747b715Smrg		if (!CheckDeviceGrabs(replayDev, event, i+1)) {
13036747b715Smrg		    if (replayDev->focus && !IsPointerEvent((InternalEvent*)event))
13046747b715Smrg			DeliverFocusedEvent(replayDev, (InternalEvent*)event, w);
130505b261ecSmrg		    else
13066747b715Smrg			DeliverDeviceEvents(w, (InternalEvent*)event, NullGrab,
13076747b715Smrg                                            NullWindow, replayDev);
130805b261ecSmrg		}
130905b261ecSmrg		goto playmore;
131005b261ecSmrg	    }
131105b261ecSmrg	}
131205b261ecSmrg	/* must not still be in the same stack */
13136747b715Smrg	if (replayDev->focus && !IsPointerEvent((InternalEvent*)event))
13146747b715Smrg	    DeliverFocusedEvent(replayDev, (InternalEvent*)event, w);
131505b261ecSmrg	else
13166747b715Smrg	    DeliverDeviceEvents(w, (InternalEvent*)event, NullGrab,
13176747b715Smrg                                NullWindow, replayDev);
131805b261ecSmrg    }
131905b261ecSmrgplaymore:
132005b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
132105b261ecSmrg    {
13224642e01fSmrg	if (!dev->deviceGrab.sync.frozen)
132305b261ecSmrg	{
132405b261ecSmrg	    PlayReleasedEvents();
132505b261ecSmrg	    break;
132605b261ecSmrg	}
132705b261ecSmrg    }
132805b261ecSmrg    syncEvents.playingEvents = FALSE;
13294642e01fSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
133005b261ecSmrg    {
13314642e01fSmrg        if (DevHasCursor(dev))
13324642e01fSmrg        {
13334642e01fSmrg            /* the following may have been skipped during replay,
13344642e01fSmrg              so do it now */
13354642e01fSmrg            if ((grab = dev->deviceGrab.grab) && grab->confineTo)
13364642e01fSmrg            {
13374642e01fSmrg                if (grab->confineTo->drawable.pScreen !=
13384642e01fSmrg                        dev->spriteInfo->sprite->hotPhys.pScreen)
13394642e01fSmrg                    dev->spriteInfo->sprite->hotPhys.x =
13404642e01fSmrg                        dev->spriteInfo->sprite->hotPhys.y = 0;
13414642e01fSmrg                ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE);
13424642e01fSmrg            }
13434642e01fSmrg            else
13444642e01fSmrg                ConfineCursorToWindow(dev,
13456747b715Smrg                        dev->spriteInfo->sprite->hotPhys.pScreen->root,
13464642e01fSmrg                        TRUE, FALSE);
13474642e01fSmrg            PostNewCursor(dev);
13484642e01fSmrg        }
134905b261ecSmrg    }
135005b261ecSmrg}
135105b261ecSmrg
135205b261ecSmrg#ifdef RANDR
135305b261ecSmrgvoid
135405b261ecSmrgScreenRestructured (ScreenPtr pScreen)
135505b261ecSmrg{
135605b261ecSmrg    GrabPtr grab;
13574642e01fSmrg    DeviceIntPtr pDev;
135805b261ecSmrg
13594642e01fSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
136005b261ecSmrg    {
13614642e01fSmrg        if (!DevHasCursor(pDev))
13624642e01fSmrg            continue;
13634642e01fSmrg
13644642e01fSmrg        /* GrabDevice doesn't have a confineTo field, so we don't need to
13654642e01fSmrg         * worry about it. */
13664642e01fSmrg        if ((grab = pDev->deviceGrab.grab) && grab->confineTo)
13674642e01fSmrg        {
13684642e01fSmrg            if (grab->confineTo->drawable.pScreen
13694642e01fSmrg                    != pDev->spriteInfo->sprite->hotPhys.pScreen)
13704642e01fSmrg                pDev->spriteInfo->sprite->hotPhys.x = pDev->spriteInfo->sprite->hotPhys.y = 0;
13714642e01fSmrg            ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
13724642e01fSmrg        }
13734642e01fSmrg        else
13744642e01fSmrg            ConfineCursorToWindow(pDev,
13756747b715Smrg                    pDev->spriteInfo->sprite->hotPhys.pScreen->root,
13764642e01fSmrg                    TRUE, FALSE);
137705b261ecSmrg    }
137805b261ecSmrg}
137905b261ecSmrg#endif
138005b261ecSmrg
13814642e01fSmrgstatic void
138205b261ecSmrgCheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
138305b261ecSmrg{
13844642e01fSmrg    GrabPtr grab = thisDev->deviceGrab.grab;
138505b261ecSmrg    DeviceIntPtr dev;
138605b261ecSmrg
138705b261ecSmrg    if (thisMode == GrabModeSync)
13884642e01fSmrg	thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT;
138905b261ecSmrg    else
139005b261ecSmrg    {	/* free both if same client owns both */
13914642e01fSmrg	thisDev->deviceGrab.sync.state = THAWED;
13924642e01fSmrg	if (thisDev->deviceGrab.sync.other &&
13934642e01fSmrg	    (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) ==
139405b261ecSmrg	     CLIENT_BITS(grab->resource)))
13954642e01fSmrg	    thisDev->deviceGrab.sync.other = NullGrab;
139605b261ecSmrg    }
13974642e01fSmrg
13986747b715Smrg    if (IsMaster(thisDev))
13994642e01fSmrg    {
14004642e01fSmrg        dev = GetPairedDevice(thisDev);
14014642e01fSmrg        if (otherMode == GrabModeSync)
14024642e01fSmrg            dev->deviceGrab.sync.other = grab;
14034642e01fSmrg        else
14044642e01fSmrg        {	/* free both if same client owns both */
14054642e01fSmrg            if (dev->deviceGrab.sync.other &&
14064642e01fSmrg                    (CLIENT_BITS(dev->deviceGrab.sync.other->resource) ==
14074642e01fSmrg                     CLIENT_BITS(grab->resource)))
14084642e01fSmrg                dev->deviceGrab.sync.other = NullGrab;
14094642e01fSmrg        }
141005b261ecSmrg    }
141105b261ecSmrg    ComputeFreezes();
141205b261ecSmrg}
141305b261ecSmrg
14146747b715Smrg/**
14156747b715Smrg * Save the device's master device id. This needs to be done
14166747b715Smrg * if a client directly grabs a slave device that is attached to a master. For
14176747b715Smrg * the duration of the grab, the device is detached, ungrabbing re-attaches it
14186747b715Smrg * though.
14196747b715Smrg *
14206747b715Smrg * We store the ID of the master device only in case the master disappears
14216747b715Smrg * while the device has a grab.
14226747b715Smrg */
14236747b715Smrgstatic void
14246747b715SmrgDetachFromMaster(DeviceIntPtr dev)
14256747b715Smrg{
14266747b715Smrg    if (!dev->u.master)
14276747b715Smrg        return;
14286747b715Smrg
14296747b715Smrg    dev->saved_master_id = dev->u.master->id;
14306747b715Smrg
14316747b715Smrg    AttachDevice(NULL, dev, NULL);
14326747b715Smrg}
14336747b715Smrg
14346747b715Smrgstatic void
14356747b715SmrgReattachToOldMaster(DeviceIntPtr dev)
14366747b715Smrg{
14376747b715Smrg    DeviceIntPtr master = NULL;
14386747b715Smrg
14396747b715Smrg    if (IsMaster(dev))
14406747b715Smrg        return;
14416747b715Smrg
14426747b715Smrg    dixLookupDevice(&master, dev->saved_master_id, serverClient, DixUseAccess);
14436747b715Smrg
14446747b715Smrg    if (master)
14456747b715Smrg    {
14466747b715Smrg        AttachDevice(serverClient, dev, master);
14476747b715Smrg	dev->saved_master_id = 0;
14486747b715Smrg    }
14496747b715Smrg}
14506747b715Smrg
145105b261ecSmrg/**
145205b261ecSmrg * Activate a pointer grab on the given device. A pointer grab will cause all
14534642e01fSmrg * core pointer events of this device to be delivered to the grabbing client only.
14544642e01fSmrg * No other device will send core events to the grab client while the grab is
14554642e01fSmrg * on, but core events will be sent to other clients.
14564642e01fSmrg * Can cause the cursor to change if a grab cursor is set.
14574642e01fSmrg *
14584642e01fSmrg * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab
14594642e01fSmrg * is an implicit grab caused by a ButtonPress event.
14604642e01fSmrg *
146105b261ecSmrg * @param mouse The device to grab.
146205b261ecSmrg * @param grab The grab structure, needs to be setup.
146305b261ecSmrg * @param autoGrab True if the grab was caused by a button down event and not
14644642e01fSmrg * explicitely by a client.
146505b261ecSmrg */
146605b261ecSmrgvoid
14674642e01fSmrgActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
146805b261ecSmrg                    TimeStamp time, Bool autoGrab)
146905b261ecSmrg{
14704642e01fSmrg    GrabInfoPtr grabinfo = &mouse->deviceGrab;
14714642e01fSmrg    WindowPtr oldWin = (grabinfo->grab) ?
14724642e01fSmrg                        grabinfo->grab->window
14734642e01fSmrg                        : mouse->spriteInfo->sprite->win;
14744642e01fSmrg    Bool isPassive = autoGrab & ~ImplicitGrabMask;
147505b261ecSmrg
14766747b715Smrg    /* slave devices need to float for the duration of the grab. */
14776747b715Smrg    if (grab->grabtype == GRABTYPE_XI2 &&
14786747b715Smrg        !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse))
14796747b715Smrg        DetachFromMaster(mouse);
14806747b715Smrg
148105b261ecSmrg    if (grab->confineTo)
148205b261ecSmrg    {
14834642e01fSmrg	if (grab->confineTo->drawable.pScreen
14844642e01fSmrg                != mouse->spriteInfo->sprite->hotPhys.pScreen)
14854642e01fSmrg	    mouse->spriteInfo->sprite->hotPhys.x =
14864642e01fSmrg                mouse->spriteInfo->sprite->hotPhys.y = 0;
14874642e01fSmrg	ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE);
148805b261ecSmrg    }
14896747b715Smrg    DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab);
149005b261ecSmrg    mouse->valuator->motionHintWindow = NullWindow;
149105b261ecSmrg    if (syncEvents.playingEvents)
14924642e01fSmrg        grabinfo->grabTime = syncEvents.time;
149305b261ecSmrg    else
14944642e01fSmrg	grabinfo->grabTime = time;
149505b261ecSmrg    if (grab->cursor)
149605b261ecSmrg	grab->cursor->refcnt++;
14974642e01fSmrg    grabinfo->activeGrab = *grab;
14984642e01fSmrg    grabinfo->grab = &grabinfo->activeGrab;
14994642e01fSmrg    grabinfo->fromPassiveGrab = isPassive;
15004642e01fSmrg    grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
15014642e01fSmrg    PostNewCursor(mouse);
150205b261ecSmrg    CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
150305b261ecSmrg}
150405b261ecSmrg
150505b261ecSmrg/**
150605b261ecSmrg * Delete grab on given device, update the sprite.
150705b261ecSmrg *
15084642e01fSmrg * Extension devices are set up for ActivateKeyboardGrab().
150905b261ecSmrg */
151005b261ecSmrgvoid
151105b261ecSmrgDeactivatePointerGrab(DeviceIntPtr mouse)
151205b261ecSmrg{
15134642e01fSmrg    GrabPtr grab = mouse->deviceGrab.grab;
151405b261ecSmrg    DeviceIntPtr dev;
15156747b715Smrg    Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
15166747b715Smrg                        mouse->deviceGrab.implicitGrab);
151705b261ecSmrg
151805b261ecSmrg    mouse->valuator->motionHintWindow = NullWindow;
15194642e01fSmrg    mouse->deviceGrab.grab = NullGrab;
15204642e01fSmrg    mouse->deviceGrab.sync.state = NOT_GRABBED;
15214642e01fSmrg    mouse->deviceGrab.fromPassiveGrab = FALSE;
15224642e01fSmrg
152305b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
152405b261ecSmrg    {
15254642e01fSmrg	if (dev->deviceGrab.sync.other == grab)
15264642e01fSmrg	    dev->deviceGrab.sync.other = NullGrab;
152705b261ecSmrg    }
15286747b715Smrg    DoEnterLeaveEvents(mouse, mouse->id, grab->window,
15294642e01fSmrg                       mouse->spriteInfo->sprite->win, NotifyUngrab);
153005b261ecSmrg    if (grab->confineTo)
15314642e01fSmrg	ConfineCursorToWindow(mouse, RootWindow(mouse), FALSE, FALSE);
15324642e01fSmrg    PostNewCursor(mouse);
153305b261ecSmrg    if (grab->cursor)
153405b261ecSmrg	FreeCursor(grab->cursor, (Cursor)0);
15354642e01fSmrg
15366747b715Smrg    if (!wasImplicit && grab->grabtype == GRABTYPE_XI2)
15376747b715Smrg        ReattachToOldMaster(mouse);
15386747b715Smrg
153905b261ecSmrg    ComputeFreezes();
154005b261ecSmrg}
154105b261ecSmrg
154205b261ecSmrg/**
15434642e01fSmrg * Activate a keyboard grab on the given device.
154405b261ecSmrg *
154505b261ecSmrg * Extension devices have ActivateKeyboardGrab() set as their grabbing proc.
154605b261ecSmrg */
154705b261ecSmrgvoid
154805b261ecSmrgActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive)
154905b261ecSmrg{
15504642e01fSmrg    GrabInfoPtr grabinfo = &keybd->deviceGrab;
155105b261ecSmrg    WindowPtr oldWin;
155205b261ecSmrg
15536747b715Smrg    /* slave devices need to float for the duration of the grab. */
15546747b715Smrg    if (grab->grabtype == GRABTYPE_XI2 &&
15556747b715Smrg        !(passive & ImplicitGrabMask) &&
15566747b715Smrg        !IsMaster(keybd))
15576747b715Smrg        DetachFromMaster(keybd);
15586747b715Smrg
15594642e01fSmrg    if (grabinfo->grab)
15604642e01fSmrg	oldWin = grabinfo->grab->window;
156105b261ecSmrg    else if (keybd->focus)
156205b261ecSmrg	oldWin = keybd->focus->win;
156305b261ecSmrg    else
15644642e01fSmrg	oldWin = keybd->spriteInfo->sprite->win;
156505b261ecSmrg    if (oldWin == FollowKeyboardWin)
15666747b715Smrg	oldWin = keybd->focus->win;
156705b261ecSmrg    if (keybd->valuator)
156805b261ecSmrg	keybd->valuator->motionHintWindow = NullWindow;
156905b261ecSmrg    DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
157005b261ecSmrg    if (syncEvents.playingEvents)
15714642e01fSmrg	grabinfo->grabTime = syncEvents.time;
157205b261ecSmrg    else
15734642e01fSmrg	grabinfo->grabTime = time;
15744642e01fSmrg    grabinfo->activeGrab = *grab;
15754642e01fSmrg    grabinfo->grab = &grabinfo->activeGrab;
15764642e01fSmrg    grabinfo->fromPassiveGrab = passive;
15776747b715Smrg    grabinfo->implicitGrab = passive & ImplicitGrabMask;
157805b261ecSmrg    CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
157905b261ecSmrg}
158005b261ecSmrg
158105b261ecSmrg/**
15824642e01fSmrg * Delete keyboard grab for the given device.
158305b261ecSmrg */
158405b261ecSmrgvoid
158505b261ecSmrgDeactivateKeyboardGrab(DeviceIntPtr keybd)
158605b261ecSmrg{
15874642e01fSmrg    GrabPtr grab = keybd->deviceGrab.grab;
158805b261ecSmrg    DeviceIntPtr dev;
158905b261ecSmrg    WindowPtr focusWin = keybd->focus ? keybd->focus->win
15904642e01fSmrg                                           : keybd->spriteInfo->sprite->win;
15916747b715Smrg    Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab &&
15926747b715Smrg                        keybd->deviceGrab.implicitGrab);
159305b261ecSmrg
159405b261ecSmrg    if (focusWin == FollowKeyboardWin)
159505b261ecSmrg	focusWin = inputInfo.keyboard->focus->win;
159605b261ecSmrg    if (keybd->valuator)
159705b261ecSmrg	keybd->valuator->motionHintWindow = NullWindow;
15984642e01fSmrg    keybd->deviceGrab.grab = NullGrab;
15994642e01fSmrg    keybd->deviceGrab.sync.state = NOT_GRABBED;
16004642e01fSmrg    keybd->deviceGrab.fromPassiveGrab = FALSE;
16014642e01fSmrg
160205b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
160305b261ecSmrg    {
16044642e01fSmrg	if (dev->deviceGrab.sync.other == grab)
16054642e01fSmrg	    dev->deviceGrab.sync.other = NullGrab;
160605b261ecSmrg    }
160705b261ecSmrg    DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
16084642e01fSmrg
16096747b715Smrg    if (!wasImplicit && grab->grabtype == GRABTYPE_XI2)
16106747b715Smrg        ReattachToOldMaster(keybd);
16116747b715Smrg
161205b261ecSmrg    ComputeFreezes();
161305b261ecSmrg}
161405b261ecSmrg
161505b261ecSmrgvoid
16164642e01fSmrgAllowSome(ClientPtr client,
16174642e01fSmrg          TimeStamp time,
16184642e01fSmrg          DeviceIntPtr thisDev,
16196747b715Smrg          int newState)
162005b261ecSmrg{
162105b261ecSmrg    Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
162205b261ecSmrg    TimeStamp grabTime;
162305b261ecSmrg    DeviceIntPtr dev;
16244642e01fSmrg    GrabInfoPtr devgrabinfo,
16254642e01fSmrg                grabinfo = &thisDev->deviceGrab;
162605b261ecSmrg
16274642e01fSmrg    thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
162805b261ecSmrg    thisSynced = FALSE;
162905b261ecSmrg    otherGrabbed = FALSE;
16306747b715Smrg    othersFrozen = FALSE;
16314642e01fSmrg    grabTime = grabinfo->grabTime;
163205b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
163305b261ecSmrg    {
16344642e01fSmrg        devgrabinfo = &dev->deviceGrab;
16354642e01fSmrg
163605b261ecSmrg	if (dev == thisDev)
163705b261ecSmrg	    continue;
16384642e01fSmrg	if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
163905b261ecSmrg	{
164005b261ecSmrg	    if (!(thisGrabbed || otherGrabbed) ||
16414642e01fSmrg		(CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER))
16424642e01fSmrg		grabTime = devgrabinfo->grabTime;
164305b261ecSmrg	    otherGrabbed = TRUE;
16444642e01fSmrg	    if (grabinfo->sync.other == devgrabinfo->grab)
164505b261ecSmrg		thisSynced = TRUE;
16466747b715Smrg	    if (devgrabinfo->sync.state >= FROZEN)
16476747b715Smrg		othersFrozen = TRUE;
164805b261ecSmrg	}
164905b261ecSmrg    }
16504642e01fSmrg    if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced))
165105b261ecSmrg	return;
165205b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
165305b261ecSmrg	(CompareTimeStamps(time, grabTime) == EARLIER))
165405b261ecSmrg	return;
165505b261ecSmrg    switch (newState)
165605b261ecSmrg    {
16574642e01fSmrg	case THAWED:		       /* Async */
165805b261ecSmrg	    if (thisGrabbed)
16594642e01fSmrg		grabinfo->sync.state = THAWED;
166005b261ecSmrg	    if (thisSynced)
16614642e01fSmrg		grabinfo->sync.other = NullGrab;
166205b261ecSmrg	    ComputeFreezes();
166305b261ecSmrg	    break;
166405b261ecSmrg	case FREEZE_NEXT_EVENT:		/* Sync */
166505b261ecSmrg	    if (thisGrabbed)
166605b261ecSmrg	    {
16674642e01fSmrg		grabinfo->sync.state = FREEZE_NEXT_EVENT;
166805b261ecSmrg		if (thisSynced)
16694642e01fSmrg		    grabinfo->sync.other = NullGrab;
167005b261ecSmrg		ComputeFreezes();
167105b261ecSmrg	    }
167205b261ecSmrg	    break;
167305b261ecSmrg	case THAWED_BOTH:		/* AsyncBoth */
167405b261ecSmrg	    if (othersFrozen)
167505b261ecSmrg	    {
167605b261ecSmrg		for (dev = inputInfo.devices; dev; dev = dev->next)
167705b261ecSmrg		{
16784642e01fSmrg                    devgrabinfo = &dev->deviceGrab;
16794642e01fSmrg		    if (devgrabinfo->grab
16804642e01fSmrg                            && SameClient(devgrabinfo->grab, client))
16814642e01fSmrg			devgrabinfo->sync.state = THAWED;
16824642e01fSmrg		    if (devgrabinfo->sync.other &&
16834642e01fSmrg                            SameClient(devgrabinfo->sync.other, client))
16844642e01fSmrg			devgrabinfo->sync.other = NullGrab;
168505b261ecSmrg		}
168605b261ecSmrg		ComputeFreezes();
168705b261ecSmrg	    }
168805b261ecSmrg	    break;
168905b261ecSmrg	case FREEZE_BOTH_NEXT_EVENT:	/* SyncBoth */
169005b261ecSmrg	    if (othersFrozen)
169105b261ecSmrg	    {
169205b261ecSmrg		for (dev = inputInfo.devices; dev; dev = dev->next)
169305b261ecSmrg		{
16944642e01fSmrg                    devgrabinfo = &dev->deviceGrab;
16954642e01fSmrg		    if (devgrabinfo->grab
16964642e01fSmrg                            && SameClient(devgrabinfo->grab, client))
16974642e01fSmrg			devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT;
16984642e01fSmrg		    if (devgrabinfo->sync.other
16994642e01fSmrg                            && SameClient(devgrabinfo->sync.other, client))
17004642e01fSmrg			devgrabinfo->sync.other = NullGrab;
170105b261ecSmrg		}
170205b261ecSmrg		ComputeFreezes();
170305b261ecSmrg	    }
170405b261ecSmrg	    break;
170505b261ecSmrg	case NOT_GRABBED:		/* Replay */
17064642e01fSmrg	    if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT)
170705b261ecSmrg	    {
170805b261ecSmrg		if (thisSynced)
17094642e01fSmrg		    grabinfo->sync.other = NullGrab;
171005b261ecSmrg		syncEvents.replayDev = thisDev;
17114642e01fSmrg		syncEvents.replayWin = grabinfo->grab->window;
17124642e01fSmrg		(*grabinfo->DeactivateGrab)(thisDev);
171305b261ecSmrg		syncEvents.replayDev = (DeviceIntPtr)NULL;
171405b261ecSmrg	    }
171505b261ecSmrg	    break;
171605b261ecSmrg	case THAW_OTHERS:		/* AsyncOthers */
171705b261ecSmrg	    if (othersFrozen)
171805b261ecSmrg	    {
171905b261ecSmrg		for (dev = inputInfo.devices; dev; dev = dev->next)
172005b261ecSmrg		{
172105b261ecSmrg		    if (dev == thisDev)
172205b261ecSmrg			continue;
17236747b715Smrg                    devgrabinfo = &dev->deviceGrab;
17244642e01fSmrg		    if (devgrabinfo->grab
17254642e01fSmrg                            && SameClient(devgrabinfo->grab, client))
17264642e01fSmrg			devgrabinfo->sync.state = THAWED;
17274642e01fSmrg		    if (devgrabinfo->sync.other
17284642e01fSmrg                            && SameClient(devgrabinfo->sync.other, client))
17294642e01fSmrg			devgrabinfo->sync.other = NullGrab;
173005b261ecSmrg		}
173105b261ecSmrg		ComputeFreezes();
173205b261ecSmrg	    }
173305b261ecSmrg	    break;
173405b261ecSmrg    }
173505b261ecSmrg}
173605b261ecSmrg
173705b261ecSmrg/**
173805b261ecSmrg * Server-side protocol handling for AllowEvents request.
173905b261ecSmrg *
17404642e01fSmrg * Release some events from a frozen device.
174105b261ecSmrg */
174205b261ecSmrgint
174305b261ecSmrgProcAllowEvents(ClientPtr client)
174405b261ecSmrg{
174505b261ecSmrg    TimeStamp		time;
17464642e01fSmrg    DeviceIntPtr	mouse = NULL;
17474642e01fSmrg    DeviceIntPtr	keybd = NULL;
174805b261ecSmrg    REQUEST(xAllowEventsReq);
174905b261ecSmrg
175005b261ecSmrg    REQUEST_SIZE_MATCH(xAllowEventsReq);
175105b261ecSmrg    time = ClientTimeToServerTime(stuff->time);
17524642e01fSmrg
17534642e01fSmrg    mouse = PickPointer(client);
17544642e01fSmrg    keybd = PickKeyboard(client);
17554642e01fSmrg
175605b261ecSmrg    switch (stuff->mode)
175705b261ecSmrg    {
175805b261ecSmrg	case ReplayPointer:
17596747b715Smrg	    AllowSome(client, time, mouse, NOT_GRABBED);
176005b261ecSmrg	    break;
17614642e01fSmrg	case SyncPointer:
17626747b715Smrg	    AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
176305b261ecSmrg	    break;
17644642e01fSmrg	case AsyncPointer:
17656747b715Smrg	    AllowSome(client, time, mouse, THAWED);
176605b261ecSmrg	    break;
17674642e01fSmrg	case ReplayKeyboard:
17686747b715Smrg	    AllowSome(client, time, keybd, NOT_GRABBED);
176905b261ecSmrg	    break;
17704642e01fSmrg	case SyncKeyboard:
17716747b715Smrg	    AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
177205b261ecSmrg	    break;
17734642e01fSmrg	case AsyncKeyboard:
17746747b715Smrg	    AllowSome(client, time, keybd, THAWED);
177505b261ecSmrg	    break;
177605b261ecSmrg	case SyncBoth:
17776747b715Smrg	    AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
177805b261ecSmrg	    break;
177905b261ecSmrg	case AsyncBoth:
17806747b715Smrg	    AllowSome(client, time, keybd, THAWED_BOTH);
178105b261ecSmrg	    break;
17824642e01fSmrg	default:
178305b261ecSmrg	    client->errorValue = stuff->mode;
178405b261ecSmrg	    return BadValue;
178505b261ecSmrg    }
178605b261ecSmrg    return Success;
178705b261ecSmrg}
178805b261ecSmrg
178905b261ecSmrg/**
179005b261ecSmrg * Deactivate grabs from any device that has been grabbed by the client.
179105b261ecSmrg */
179205b261ecSmrgvoid
179305b261ecSmrgReleaseActiveGrabs(ClientPtr client)
179405b261ecSmrg{
179505b261ecSmrg    DeviceIntPtr dev;
179605b261ecSmrg    Bool    done;
179705b261ecSmrg
179805b261ecSmrg    /* XXX CloseDownClient should remove passive grabs before
179905b261ecSmrg     * releasing active grabs.
180005b261ecSmrg     */
180105b261ecSmrg    do {
18024642e01fSmrg	done = TRUE;
18034642e01fSmrg	for (dev = inputInfo.devices; dev; dev = dev->next)
18044642e01fSmrg	{
18054642e01fSmrg	    if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
180605b261ecSmrg	    {
18074642e01fSmrg		(*dev->deviceGrab.DeactivateGrab)(dev);
18084642e01fSmrg		done = FALSE;
180905b261ecSmrg	    }
18104642e01fSmrg	}
181105b261ecSmrg    } while (!done);
181205b261ecSmrg}
181305b261ecSmrg
181405b261ecSmrg/**************************************************************************
181505b261ecSmrg *            The following procedures deal with delivering events        *
181605b261ecSmrg **************************************************************************/
181705b261ecSmrg
181805b261ecSmrg/**
181905b261ecSmrg * Deliver the given events to the given client.
182005b261ecSmrg *
182105b261ecSmrg * More than one event may be delivered at a time. This is the case with
182205b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events.
182305b261ecSmrg *
182405b261ecSmrg * TryClientEvents() is the last station before actually writing the events to
182505b261ecSmrg * the socket. Anything that is not filtered here, will get delivered to the
18264642e01fSmrg * client.
18274642e01fSmrg * An event is only delivered if
182805b261ecSmrg *   - mask and filter match up.
182905b261ecSmrg *   - no other client has a grab on the device that caused the event.
18304642e01fSmrg *
183105b261ecSmrg *
183205b261ecSmrg * @param client The target client to deliver to.
18334642e01fSmrg * @param dev The device the event came from. May be NULL.
183405b261ecSmrg * @param pEvents The events to be delivered.
183505b261ecSmrg * @param count Number of elements in pEvents.
183605b261ecSmrg * @param mask Event mask as set by the window.
183705b261ecSmrg * @param filter Mask based on event type.
18384642e01fSmrg * @param grab Possible grab on the device that caused the event.
183905b261ecSmrg *
184005b261ecSmrg * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
184105b261ecSmrg * client.
184205b261ecSmrg */
18436747b715Smrgint
18444642e01fSmrgTryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
18454642e01fSmrg                 int count, Mask mask, Mask filter, GrabPtr grab)
184605b261ecSmrg{
184705b261ecSmrg    int type;
184805b261ecSmrg
184905b261ecSmrg#ifdef DEBUG_EVENTS
18506747b715Smrg    ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s",
18516747b715Smrg           pEvents->u.u.type, pEvents->u.u.detail, mask,
18526747b715Smrg           client ? client->index : -1,
18536747b715Smrg           (client && client->clientGone) ? " (gone)" : "");
185405b261ecSmrg#endif
18556747b715Smrg
18566747b715Smrg    if (!client || client == serverClient || client->clientGone) {
185705b261ecSmrg#ifdef DEBUG_EVENTS
18586747b715Smrg        ErrorF(" not delivered to fake/dead client\n");
185905b261ecSmrg#endif
18606747b715Smrg        return 0;
18616747b715Smrg    }
186205b261ecSmrg
18636747b715Smrg    if (filter != CantBeFiltered && !(mask & filter))
18646747b715Smrg    {
18656747b715Smrg #ifdef DEBUG_EVENTS
18666747b715Smrg        ErrorF(" filtered\n");
18676747b715Smrg #endif
18686747b715Smrg        return 0;
18696747b715Smrg    }
187005b261ecSmrg
18716747b715Smrg    if (grab && !SameClient(grab, client))
18726747b715Smrg    {
187305b261ecSmrg#ifdef DEBUG_EVENTS
18746747b715Smrg        ErrorF(" not delivered due to grab\n");
187505b261ecSmrg#endif
18766747b715Smrg        return -1; /* don't send, but notify caller */
187705b261ecSmrg    }
18786747b715Smrg
18796747b715Smrg    type = pEvents->u.u.type;
18806747b715Smrg    if (type == MotionNotify)
188105b261ecSmrg    {
18826747b715Smrg        if (mask & PointerMotionHintMask)
18836747b715Smrg        {
18846747b715Smrg            if (WID(dev->valuator->motionHintWindow) ==
18856747b715Smrg                    pEvents->u.keyButtonPointer.event)
18866747b715Smrg            {
188705b261ecSmrg#ifdef DEBUG_EVENTS
18886747b715Smrg                ErrorF("[dix] \n");
18896747b715Smrg                ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
189005b261ecSmrg#endif
18916747b715Smrg                return 1; /* don't send, but pretend we did */
18926747b715Smrg            }
18936747b715Smrg            pEvents->u.u.detail = NotifyHint;
18946747b715Smrg        }
18956747b715Smrg        else
18966747b715Smrg        {
18976747b715Smrg            pEvents->u.u.detail = NotifyNormal;
18986747b715Smrg        }
18996747b715Smrg    }
19006747b715Smrg    else if (type == DeviceMotionNotify)
19016747b715Smrg    {
19026747b715Smrg        if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer*)pEvents,
19036747b715Smrg                                            mask) != 0)
19046747b715Smrg            return 1;
19056747b715Smrg    } else if (type == KeyPress)
19066747b715Smrg    {
19076747b715Smrg        if (EventIsKeyRepeat(pEvents))
19086747b715Smrg        {
19096747b715Smrg            if (!_XkbWantsDetectableAutoRepeat(client))
19106747b715Smrg            {
19116747b715Smrg                xEvent release = *pEvents;
19126747b715Smrg                release.u.u.type = KeyRelease;
19136747b715Smrg                WriteEventsToClient(client, 1, &release);
19146747b715Smrg#ifdef DEBUG_EVENTS
19156747b715Smrg                ErrorF(" (plus fake core release for repeat)");
19166747b715Smrg#endif
19176747b715Smrg            } else
19186747b715Smrg            {
19196747b715Smrg#ifdef DEBUG_EVENTS
19206747b715Smrg                ErrorF(" (detectable autorepeat for core)");
19216747b715Smrg#endif
19226747b715Smrg            }
19236747b715Smrg        }
19246747b715Smrg
19256747b715Smrg    } else if (type == DeviceKeyPress)
19266747b715Smrg    {
19276747b715Smrg        if (EventIsKeyRepeat(pEvents))
19286747b715Smrg        {
19296747b715Smrg            if (!_XkbWantsDetectableAutoRepeat(client))
19306747b715Smrg            {
19316747b715Smrg                deviceKeyButtonPointer release = *(deviceKeyButtonPointer *)pEvents;
19326747b715Smrg                release.type = DeviceKeyRelease;
19336747b715Smrg#ifdef DEBUG_EVENTS
19346747b715Smrg                ErrorF(" (plus fake xi1 release for repeat)");
19356747b715Smrg#endif
19366747b715Smrg                WriteEventsToClient(client, 1, (xEvent *) &release);
19376747b715Smrg            }
19386747b715Smrg            else {
19396747b715Smrg#ifdef DEBUG_EVENTS
19406747b715Smrg                ErrorF(" (detectable autorepeat for core)");
19416747b715Smrg#endif
19426747b715Smrg            }
19436747b715Smrg        }
19446747b715Smrg    }
19456747b715Smrg
19466747b715Smrg    if (BitIsOn(criticalEvents, type))
19476747b715Smrg    {
19486747b715Smrg        if (client->smart_priority < SMART_MAX_PRIORITY)
19496747b715Smrg            client->smart_priority++;
19506747b715Smrg        SetCriticalOutputPending();
195105b261ecSmrg    }
19526747b715Smrg
19536747b715Smrg    WriteEventsToClient(client, count, pEvents);
19546747b715Smrg#ifdef DEBUG_EVENTS
19556747b715Smrg    ErrorF("[dix]  delivered\n");
19566747b715Smrg#endif
19576747b715Smrg    return 1;
195805b261ecSmrg}
195905b261ecSmrg
196005b261ecSmrg/**
196105b261ecSmrg * Deliver events to a window. At this point, we do not yet know if the event
196205b261ecSmrg * actually needs to be delivered. May activate a grab if the event is a
196305b261ecSmrg * button press.
196405b261ecSmrg *
19654642e01fSmrg * Core events are always delivered to the window owner. If the filter is
19664642e01fSmrg * something other than CantBeFiltered, the event is also delivered to other
19674642e01fSmrg * clients with the matching mask on the window.
19684642e01fSmrg *
196905b261ecSmrg * More than one event may be delivered at a time. This is the case with
197005b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events.
19714642e01fSmrg *
197205b261ecSmrg * @param pWin The window that would get the event.
197305b261ecSmrg * @param pEvents The events to be delivered.
197405b261ecSmrg * @param count Number of elements in pEvents.
197505b261ecSmrg * @param filter Mask based on event type.
19764642e01fSmrg * @param grab Possible grab on the device that caused the event.
197705b261ecSmrg *
197805b261ecSmrg * @return Number of events delivered to various clients.
197905b261ecSmrg */
198005b261ecSmrgint
19814642e01fSmrgDeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
19826747b715Smrg        *pEvents, int count, Mask filter, GrabPtr grab)
198305b261ecSmrg{
198405b261ecSmrg    int deliveries = 0, nondeliveries = 0;
198505b261ecSmrg    int attempt;
198605b261ecSmrg    InputClients *other;
198705b261ecSmrg    ClientPtr client = NullClient;
198805b261ecSmrg    Mask deliveryMask = 0; /* If a grab occurs due to a button press, then
198905b261ecSmrg		              this mask is the mask of the grab. */
199005b261ecSmrg    int type = pEvents->u.u.type;
199105b261ecSmrg
19926747b715Smrg
19936747b715Smrg    /* Deliver to window owner */
19946747b715Smrg    if ((filter == CantBeFiltered) || CORE_EVENT(pEvents))
199505b261ecSmrg    {
199605b261ecSmrg	/* if nobody ever wants to see this event, skip some work */
199705b261ecSmrg	if (filter != CantBeFiltered &&
199805b261ecSmrg	    !((wOtherEventMasks(pWin)|pWin->eventMask) & filter))
199905b261ecSmrg	    return 0;
20004642e01fSmrg
20016747b715Smrg        if (IsInterferingGrab(wClient(pWin), pDev, pEvents))
20024642e01fSmrg                return 0;
20034642e01fSmrg
20044642e01fSmrg	if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
20054642e01fSmrg	    /* do nothing */;
20064642e01fSmrg        else if ( (attempt = TryClientEvents(wClient(pWin), pDev, pEvents,
20074642e01fSmrg                                             count, pWin->eventMask,
20084642e01fSmrg                                             filter, grab)) )
200905b261ecSmrg	{
201005b261ecSmrg	    if (attempt > 0)
201105b261ecSmrg	    {
201205b261ecSmrg		deliveries++;
201305b261ecSmrg		client = wClient(pWin);
201405b261ecSmrg		deliveryMask = pWin->eventMask;
201505b261ecSmrg	    } else
201605b261ecSmrg		nondeliveries--;
201705b261ecSmrg	}
201805b261ecSmrg    }
20196747b715Smrg
20206747b715Smrg    /* CantBeFiltered means only window owner gets the event */
202105b261ecSmrg    if (filter != CantBeFiltered)
202205b261ecSmrg    {
20236747b715Smrg        if (CORE_EVENT(pEvents))
20246747b715Smrg            other = (InputClients *)wOtherClients(pWin);
20256747b715Smrg        else if (XI2_EVENT(pEvents))
20264642e01fSmrg        {
20276747b715Smrg            OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
20286747b715Smrg            /* Has any client selected for the event? */
20296747b715Smrg            if (!GetWindowXI2Mask(pDev, pWin, pEvents))
20304642e01fSmrg                return 0;
20316747b715Smrg            other = inputMasks->inputClients;
20326747b715Smrg        } else {
20336747b715Smrg            OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
20346747b715Smrg            /* Has any client selected for the event? */
20356747b715Smrg            if (!inputMasks ||
20366747b715Smrg                !(inputMasks->inputEvents[pDev->id] & filter))
20374642e01fSmrg                return 0;
20384642e01fSmrg
20396747b715Smrg            other = inputMasks->inputClients;
20404642e01fSmrg        }
20414642e01fSmrg
20426747b715Smrg        for (; other; other = other->next)
20436747b715Smrg        {
20446747b715Smrg            Mask mask;
20456747b715Smrg            if (IsInterferingGrab(rClient(other), pDev, pEvents))
20466747b715Smrg                continue;
20476747b715Smrg
20486747b715Smrg            mask = GetEventMask(pDev, pEvents, other);
20496747b715Smrg
20506747b715Smrg            if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin,
20516747b715Smrg                        pEvents, count))
20526747b715Smrg                /* do nothing */;
20536747b715Smrg            else if ( (attempt = TryClientEvents(rClient(other), pDev,
20546747b715Smrg                            pEvents, count,
20556747b715Smrg                            mask, filter, grab)) )
20564642e01fSmrg            {
20576747b715Smrg                if (attempt > 0)
20584642e01fSmrg                {
20596747b715Smrg                    deliveries++;
20606747b715Smrg                    client = rClient(other);
20616747b715Smrg                    deliveryMask = mask;
20626747b715Smrg                } else
20636747b715Smrg                    nondeliveries--;
20644642e01fSmrg            }
20654642e01fSmrg        }
206605b261ecSmrg    }
20674642e01fSmrg    /*
20684642e01fSmrg     * Note that since core events are delivered first, an implicit grab may
20694642e01fSmrg     * be activated on a core grab, stopping the XI events.
20704642e01fSmrg     */
20716747b715Smrg    if ((type == DeviceButtonPress || type == ButtonPress ||
20726747b715Smrg        ((XI2_EVENT(pEvents) && ((xGenericEvent*)pEvents)->evtype == XI_ButtonPress)))
20734642e01fSmrg            && deliveries
20744642e01fSmrg            && (!grab))
207505b261ecSmrg    {
207605b261ecSmrg	GrabRec tempGrab;
20774642e01fSmrg        OtherInputMasks *inputMasks;
207805b261ecSmrg
20796747b715Smrg        memset(&tempGrab, 0, sizeof(GrabRec));
20804642e01fSmrg        tempGrab.next = NULL;
20814642e01fSmrg	tempGrab.device = pDev;
208205b261ecSmrg	tempGrab.resource = client->clientAsMask;
208305b261ecSmrg	tempGrab.window = pWin;
208405b261ecSmrg	tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
208505b261ecSmrg	tempGrab.eventMask = deliveryMask;
208605b261ecSmrg	tempGrab.keyboardMode = GrabModeAsync;
208705b261ecSmrg	tempGrab.pointerMode = GrabModeAsync;
208805b261ecSmrg	tempGrab.confineTo = NullWindow;
208905b261ecSmrg	tempGrab.cursor = NullCursor;
20906747b715Smrg        tempGrab.type = type;
20916747b715Smrg        if (type == ButtonPress)
20926747b715Smrg            tempGrab.grabtype = GRABTYPE_CORE;
20936747b715Smrg        else if (type == DeviceButtonPress)
20946747b715Smrg            tempGrab.grabtype = GRABTYPE_XI;
20956747b715Smrg        else
20966747b715Smrg        {
20976747b715Smrg            tempGrab.type = ((xGenericEvent*)pEvents)->evtype;
20986747b715Smrg            tempGrab.grabtype = GRABTYPE_XI2;
20996747b715Smrg        }
21004642e01fSmrg
21016747b715Smrg        /* get the XI and XI2 device mask */
21024642e01fSmrg        inputMasks = wOtherInputMasks(pWin);
21034642e01fSmrg        tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[pDev->id]: 0;
21044642e01fSmrg
21056747b715Smrg        if (inputMasks)
21066747b715Smrg            memcpy(tempGrab.xi2mask, inputMasks->xi2mask,
21076747b715Smrg                    sizeof(tempGrab.xi2mask));
21086747b715Smrg
21094642e01fSmrg	(*pDev->deviceGrab.ActivateGrab)(pDev, &tempGrab,
21104642e01fSmrg                                        currentTime, TRUE | ImplicitGrabMask);
211105b261ecSmrg    }
211205b261ecSmrg    else if ((type == MotionNotify) && deliveries)
21134642e01fSmrg	pDev->valuator->motionHintWindow = pWin;
211405b261ecSmrg    else
211505b261ecSmrg    {
21166747b715Smrg	if ((type == DeviceMotionNotify || type == DeviceButtonPress) &&
21176747b715Smrg	    deliveries)
211805b261ecSmrg	    CheckDeviceGrabAndHintWindow (pWin, type,
211905b261ecSmrg					  (deviceKeyButtonPointer*) pEvents,
212005b261ecSmrg					  grab, client, deliveryMask);
212105b261ecSmrg    }
212205b261ecSmrg    if (deliveries)
212305b261ecSmrg	return deliveries;
212405b261ecSmrg    return nondeliveries;
212505b261ecSmrg}
212605b261ecSmrg
212705b261ecSmrg/* If the event goes to dontClient, don't send it and return 0.  if
212805b261ecSmrg   send works,  return 1 or if send didn't work, return 2.
212905b261ecSmrg   Only works for core events.
213005b261ecSmrg*/
213105b261ecSmrg
213205b261ecSmrg#ifdef PANORAMIX
21334642e01fSmrgstatic int
213405b261ecSmrgXineramaTryClientEventsResult(
213505b261ecSmrg    ClientPtr client,
213605b261ecSmrg    GrabPtr grab,
21374642e01fSmrg    Mask mask,
213805b261ecSmrg    Mask filter
213905b261ecSmrg){
214005b261ecSmrg    if ((client) && (client != serverClient) && (!client->clientGone) &&
214105b261ecSmrg        ((filter == CantBeFiltered) || (mask & filter)))
214205b261ecSmrg    {
214305b261ecSmrg        if (grab && !SameClient(grab, client)) return -1;
214405b261ecSmrg	else return 1;
214505b261ecSmrg    }
214605b261ecSmrg    return 0;
214705b261ecSmrg}
214805b261ecSmrg#endif
214905b261ecSmrg
215005b261ecSmrg/**
215105b261ecSmrg * Try to deliver events to the interested parties.
215205b261ecSmrg *
215305b261ecSmrg * @param pWin The window that would get the event.
215405b261ecSmrg * @param pEvents The events to be delivered.
215505b261ecSmrg * @param count Number of elements in pEvents.
215605b261ecSmrg * @param filter Mask based on event type.
215705b261ecSmrg * @param dontClient Don't deliver to the dontClient.
215805b261ecSmrg */
215905b261ecSmrgint
21604642e01fSmrgMaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
216105b261ecSmrg                           int count, Mask filter, ClientPtr dontClient)
216205b261ecSmrg{
216305b261ecSmrg    OtherClients *other;
216405b261ecSmrg
216505b261ecSmrg
216605b261ecSmrg    if (pWin->eventMask & filter)
216705b261ecSmrg    {
216805b261ecSmrg        if (wClient(pWin) == dontClient)
216905b261ecSmrg	    return 0;
217005b261ecSmrg#ifdef PANORAMIX
21714642e01fSmrg	if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
217205b261ecSmrg	    return XineramaTryClientEventsResult(
217305b261ecSmrg			wClient(pWin), NullGrab, pWin->eventMask, filter);
217405b261ecSmrg#endif
21754642e01fSmrg	if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
21764642e01fSmrg	    return 1; /* don't send, but pretend we did */
21774642e01fSmrg	return TryClientEvents(wClient(pWin), NULL, pEvents, count,
217805b261ecSmrg			       pWin->eventMask, filter, NullGrab);
217905b261ecSmrg    }
218005b261ecSmrg    for (other = wOtherClients(pWin); other; other = other->next)
218105b261ecSmrg    {
218205b261ecSmrg	if (other->mask & filter)
218305b261ecSmrg	{
218405b261ecSmrg            if (SameClient(other, dontClient))
218505b261ecSmrg		return 0;
218605b261ecSmrg#ifdef PANORAMIX
21874642e01fSmrg	    if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
218805b261ecSmrg	      return XineramaTryClientEventsResult(
218905b261ecSmrg			rClient(other), NullGrab, other->mask, filter);
219005b261ecSmrg#endif
21914642e01fSmrg	    if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents,
21924642e01fSmrg			 count))
21934642e01fSmrg		return 1; /* don't send, but pretend we did */
21944642e01fSmrg	    return TryClientEvents(rClient(other), NULL, pEvents, count,
219505b261ecSmrg				   other->mask, filter, NullGrab);
219605b261ecSmrg	}
219705b261ecSmrg    }
219805b261ecSmrg    return 2;
219905b261ecSmrg}
220005b261ecSmrg
22016747b715Smrgstatic Window FindChildForEvent(DeviceIntPtr dev, WindowPtr event)
22026747b715Smrg{
22036747b715Smrg    SpritePtr pSprite = dev->spriteInfo->sprite;
22046747b715Smrg    WindowPtr w = pSprite->spriteTrace[pSprite->spriteTraceGood-1];
22056747b715Smrg    Window child = None;
22066747b715Smrg
22076747b715Smrg    /* If the search ends up past the root should the child field be
22086747b715Smrg       set to none or should the value in the argument be passed
22096747b715Smrg       through. It probably doesn't matter since everyone calls
22106747b715Smrg       this function with child == None anyway. */
22116747b715Smrg    while (w)
22126747b715Smrg    {
22136747b715Smrg        /* If the source window is same as event window, child should be
22146747b715Smrg           none.  Don't bother going all all the way back to the root. */
22156747b715Smrg
22166747b715Smrg        if (w == event)
22176747b715Smrg        {
22186747b715Smrg            child = None;
22196747b715Smrg            break;
22206747b715Smrg        }
22216747b715Smrg
22226747b715Smrg        if (w->parent == event)
22236747b715Smrg        {
22246747b715Smrg            child = w->drawable.id;
22256747b715Smrg            break;
22266747b715Smrg        }
22276747b715Smrg        w = w->parent;
22286747b715Smrg    }
22296747b715Smrg    return child;
22306747b715Smrg}
22316747b715Smrg
223205b261ecSmrg/**
223305b261ecSmrg * Adjust event fields to comply with the window properties.
223405b261ecSmrg *
223505b261ecSmrg * @param xE Event to be modified in place
223605b261ecSmrg * @param pWin The window to get the information from.
223705b261ecSmrg * @param child Child window setting for event (if applicable)
223805b261ecSmrg * @param calcChild If True, calculate the child window.
223905b261ecSmrg */
22406747b715Smrgvoid
224105b261ecSmrgFixUpEventFromWindow(
22424642e01fSmrg    DeviceIntPtr pDev,
224305b261ecSmrg    xEvent *xE,
224405b261ecSmrg    WindowPtr pWin,
224505b261ecSmrg    Window child,
224605b261ecSmrg    Bool calcChild)
224705b261ecSmrg{
22484642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
22494642e01fSmrg
225005b261ecSmrg    if (calcChild)
22516747b715Smrg        child = FindChildForEvent(pDev, pWin);
22526747b715Smrg
22536747b715Smrg    if (XI2_EVENT(xE))
225405b261ecSmrg    {
22556747b715Smrg        xXIDeviceEvent* event = (xXIDeviceEvent*)xE;
22566747b715Smrg
22576747b715Smrg        if (event->evtype == XI_RawKeyPress ||
22586747b715Smrg            event->evtype == XI_RawKeyRelease ||
22596747b715Smrg            event->evtype == XI_RawButtonPress ||
22606747b715Smrg            event->evtype == XI_RawButtonRelease ||
22616747b715Smrg            event->evtype == XI_RawMotion ||
22626747b715Smrg            event->evtype == XI_DeviceChanged ||
22636747b715Smrg            event->evtype == XI_HierarchyChanged ||
22646747b715Smrg            event->evtype == XI_PropertyEvent)
22656747b715Smrg            return;
226605b261ecSmrg
22676747b715Smrg        event->root = RootWindow(pDev)->drawable.id;
22686747b715Smrg        event->event = pWin->drawable.id;
22696747b715Smrg        if (pSprite->hot.pScreen == pWin->drawable.pScreen)
22706747b715Smrg        {
22716747b715Smrg            event->event_x = event->root_x - FP1616(pWin->drawable.x, 0);
22726747b715Smrg            event->event_y = event->root_y - FP1616(pWin->drawable.y, 0);
22736747b715Smrg            event->child = child;
22746747b715Smrg        } else
227505b261ecSmrg        {
22766747b715Smrg            event->event_x = 0;
22776747b715Smrg            event->event_y = 0;
22786747b715Smrg            event->child = None;
22796747b715Smrg        }
228005b261ecSmrg
22816747b715Smrg        if (event->evtype == XI_Enter || event->evtype == XI_Leave ||
22826747b715Smrg            event->evtype == XI_FocusIn || event->evtype == XI_FocusOut)
22836747b715Smrg            ((xXIEnterEvent*)event)->same_screen =
22846747b715Smrg                (pSprite->hot.pScreen == pWin->drawable.pScreen);
22854642e01fSmrg
22866747b715Smrg    } else
228705b261ecSmrg    {
22886747b715Smrg        XE_KBPTR.root = RootWindow(pDev)->drawable.id;
22896747b715Smrg        XE_KBPTR.event = pWin->drawable.id;
22906747b715Smrg        if (pSprite->hot.pScreen == pWin->drawable.pScreen)
22916747b715Smrg        {
22926747b715Smrg            XE_KBPTR.sameScreen = xTrue;
22936747b715Smrg            XE_KBPTR.child = child;
22946747b715Smrg            XE_KBPTR.eventX =
22956747b715Smrg                XE_KBPTR.rootX - pWin->drawable.x;
22966747b715Smrg            XE_KBPTR.eventY =
22976747b715Smrg                XE_KBPTR.rootY - pWin->drawable.y;
22986747b715Smrg        }
22996747b715Smrg        else
23006747b715Smrg        {
23016747b715Smrg            XE_KBPTR.sameScreen = xFalse;
23026747b715Smrg            XE_KBPTR.child = None;
23036747b715Smrg            XE_KBPTR.eventX = 0;
23046747b715Smrg            XE_KBPTR.eventY = 0;
23056747b715Smrg        }
230605b261ecSmrg    }
230705b261ecSmrg}
230805b261ecSmrg
230905b261ecSmrg/**
23106747b715Smrg * Return masks for EventIsDeliverable.
23116747b715Smrg * @defgroup EventIsDeliverable return flags
23126747b715Smrg * @{
23136747b715Smrg */
23146747b715Smrg#define XI_MASK                 (1 << 0) /**< XI mask set on window */
23156747b715Smrg#define CORE_MASK               (1 << 1) /**< Core mask set on window */
23166747b715Smrg#define DONT_PROPAGATE_MASK     (1 << 2) /**< DontPropagate mask set on window */
23176747b715Smrg#define XI2_MASK                (1 << 3) /**< XI2 mask set on window */
23186747b715Smrg/* @} */
23196747b715Smrg
23206747b715Smrg/**
23216747b715Smrg * Check if a given event is deliverable at all on a given window.
23226747b715Smrg *
23236747b715Smrg * This function only checks if any client wants it, not for a specific
23246747b715Smrg * client.
23256747b715Smrg *
23266747b715Smrg * @param[in] dev The device this event is being sent for.
23276747b715Smrg * @param[in] event The event that is to be sent.
23286747b715Smrg * @param[in] win The current event window.
23296747b715Smrg *
23306747b715Smrg * @return Bitmask of ::XI2_MASK, ::XI_MASK, ::CORE_MASK, and
23316747b715Smrg * ::DONT_PROPAGATE_MASK.
23326747b715Smrg */
23336747b715Smrgstatic int
23346747b715SmrgEventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win)
23356747b715Smrg{
23366747b715Smrg    int rc = 0;
23376747b715Smrg    int filter = 0;
23386747b715Smrg    int type;
23396747b715Smrg    OtherInputMasks *inputMasks = wOtherInputMasks(win);
23406747b715Smrg    xEvent ev;
23416747b715Smrg
23426747b715Smrg    /* XXX: this makes me gag */
23436747b715Smrg    type = GetXI2Type(event);
23446747b715Smrg    ev.u.u.type = GenericEvent; /* GetEventFilter only cares about type and evtype*/
23456747b715Smrg    ((xGenericEvent*)&ev)->extension = IReqCode;
23466747b715Smrg    ((xGenericEvent*)&ev)->evtype = type;
23476747b715Smrg    filter = GetEventFilter(dev, &ev);
23486747b715Smrg    if (type && inputMasks &&
23496747b715Smrg        ((inputMasks->xi2mask[XIAllDevices][type/8] & filter) ||
23506747b715Smrg         ((inputMasks->xi2mask[XIAllMasterDevices][type/8] & filter) && IsMaster(dev)) ||
23516747b715Smrg         (inputMasks->xi2mask[dev->id][type/8] & filter)))
23526747b715Smrg        rc |= XI2_MASK;
23536747b715Smrg
23546747b715Smrg    type = GetXIType(event);
23556747b715Smrg    ev.u.u.type = type;
23566747b715Smrg    filter = GetEventFilter(dev, &ev);
23576747b715Smrg
23586747b715Smrg    /* Check for XI mask */
23596747b715Smrg    if (type && inputMasks &&
23606747b715Smrg        (inputMasks->deliverableEvents[dev->id] & filter) &&
23616747b715Smrg        (inputMasks->inputEvents[dev->id] & filter))
23626747b715Smrg        rc |= XI_MASK;
23636747b715Smrg
23646747b715Smrg    /* Check for XI DontPropagate mask */
23656747b715Smrg    if (type && inputMasks &&
23666747b715Smrg        (inputMasks->dontPropagateMask[dev->id] & filter))
23676747b715Smrg        rc |= DONT_PROPAGATE_MASK;
23686747b715Smrg
23696747b715Smrg    /* Check for core mask */
23706747b715Smrg    type = GetCoreType(event);
23716747b715Smrg    if (type && (win->deliverableEvents & filter) &&
23726747b715Smrg        ((wOtherEventMasks(win) | win->eventMask) & filter))
23736747b715Smrg        rc |= CORE_MASK;
23746747b715Smrg
23756747b715Smrg    /* Check for core DontPropagate mask */
23766747b715Smrg    if (type && (filter & wDontPropagateMask(win)))
23776747b715Smrg        rc |= DONT_PROPAGATE_MASK;
23786747b715Smrg
23796747b715Smrg    return rc;
23806747b715Smrg}
23816747b715Smrg
23826747b715Smrg/**
23836747b715Smrg * Deliver events caused by input devices.
23846747b715Smrg *
23854642e01fSmrg * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is
23864642e01fSmrg * called directly from the processInputProc.
23874642e01fSmrg * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call
23884642e01fSmrg * DeliverDeviceEvents.
23894642e01fSmrg * For focused events, DeliverFocusedEvent is called first, and _may_ call
23904642e01fSmrg * DeliverDeviceEvents.
239105b261ecSmrg *
239205b261ecSmrg * @param pWin Window to deliver event to.
23936747b715Smrg * @param event The events to deliver, not yet in wire format.
239405b261ecSmrg * @param grab Possible grab on a device.
239505b261ecSmrg * @param stopAt Don't recurse up to the root window.
239605b261ecSmrg * @param dev The device that is responsible for the event.
239705b261ecSmrg *
23984642e01fSmrg * @see DeliverGrabbedEvent
23994642e01fSmrg * @see DeliverFocusedEvent
240005b261ecSmrg */
240105b261ecSmrgint
24026747b715SmrgDeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
24036747b715Smrg                    WindowPtr stopAt, DeviceIntPtr dev)
240405b261ecSmrg{
240505b261ecSmrg    Window child = None;
24066747b715Smrg    Mask filter;
240705b261ecSmrg    int deliveries = 0;
24084642e01fSmrg    xEvent core;
24096747b715Smrg    xEvent *xE = NULL;
24106747b715Smrg    int rc, mask, count = 0;
24114642e01fSmrg
24126747b715Smrg    CHECKEVENT(event);
24134642e01fSmrg
24146747b715Smrg    while (pWin)
241505b261ecSmrg    {
24166747b715Smrg        if ((mask = EventIsDeliverable(dev, event, pWin)))
24174642e01fSmrg        {
24186747b715Smrg            /* XI2 events first */
24196747b715Smrg            if (mask & XI2_MASK)
24204642e01fSmrg            {
24216747b715Smrg                xEvent *xi2 = NULL;
24226747b715Smrg                rc = EventToXI2(event, &xi2);
24236747b715Smrg                if (rc == Success)
24244642e01fSmrg                {
24256747b715Smrg                    /* XXX: XACE */
24266747b715Smrg                    filter = GetEventFilter(dev, xi2);
24276747b715Smrg                    FixUpEventFromWindow(dev, xi2, pWin, child, FALSE);
24286747b715Smrg                    deliveries = DeliverEventsToWindow(dev, pWin, xi2, 1,
24296747b715Smrg                                                       filter, grab);
24306747b715Smrg                    free(xi2);
24314642e01fSmrg                    if (deliveries > 0)
24326747b715Smrg                        goto unwind;
24336747b715Smrg                } else if (rc != BadMatch)
24346747b715Smrg                    ErrorF("[dix] %s: XI2 conversion failed in DDE (%d).\n",
24356747b715Smrg                            dev->name, rc);
24364642e01fSmrg            }
24374642e01fSmrg
24386747b715Smrg            /* XI events */
24396747b715Smrg            if (mask & XI_MASK)
24406747b715Smrg            {
24416747b715Smrg                rc = EventToXI(event, &xE, &count);
24426747b715Smrg                if (rc == Success) {
24436747b715Smrg                    if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count) == Success) {
24446747b715Smrg                        filter = GetEventFilter(dev, xE);
24456747b715Smrg                        FixUpEventFromWindow(dev, xE, pWin, child, FALSE);
24466747b715Smrg                        deliveries = DeliverEventsToWindow(dev, pWin, xE, count,
24476747b715Smrg                                                           filter, grab);
24486747b715Smrg                        if (deliveries > 0)
24496747b715Smrg                            goto unwind;
24506747b715Smrg                    }
24516747b715Smrg                } else if (rc != BadMatch)
24526747b715Smrg                    ErrorF("[dix] %s: XI conversion failed in DDE (%d, %d). Skipping delivery.\n",
24536747b715Smrg                            dev->name, event->any.type, rc);
24546747b715Smrg            }
24554642e01fSmrg
24566747b715Smrg            /* Core event */
24576747b715Smrg            if ((mask & CORE_MASK) && IsMaster(dev) && dev->coreEvents)
24584642e01fSmrg            {
24596747b715Smrg                rc = EventToCore(event, &core);
24606747b715Smrg                if (rc == Success) {
24616747b715Smrg                    if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, &core, 1) == Success) {
24626747b715Smrg                        filter = GetEventFilter(dev, &core);
24636747b715Smrg                        FixUpEventFromWindow(dev, &core, pWin, child, FALSE);
24646747b715Smrg                        deliveries = DeliverEventsToWindow(dev, pWin, &core, 1,
24656747b715Smrg                                                           filter, grab);
24666747b715Smrg                        if (deliveries > 0)
24676747b715Smrg                            goto unwind;
24686747b715Smrg                    }
24696747b715Smrg                } else if (rc != BadMatch)
24706747b715Smrg                        ErrorF("[dix] %s: Core conversion failed in DDE (%d, %d).\n",
24716747b715Smrg                                dev->name, event->any.type, rc);
24724642e01fSmrg            }
24734642e01fSmrg
24744642e01fSmrg            if ((deliveries < 0) || (pWin == stopAt) ||
24756747b715Smrg                (mask & DONT_PROPAGATE_MASK))
24766747b715Smrg            {
24776747b715Smrg                deliveries = 0;
24786747b715Smrg                goto unwind;
24796747b715Smrg            }
24804642e01fSmrg        }
24814642e01fSmrg
24824642e01fSmrg        child = pWin->drawable.id;
24834642e01fSmrg        pWin = pWin->parent;
248405b261ecSmrg    }
24854642e01fSmrg
24866747b715Smrgunwind:
24876747b715Smrg    free(xE);
24886747b715Smrg    return deliveries;
248905b261ecSmrg}
249005b261ecSmrg
24916747b715Smrg#undef XI_MASK
24926747b715Smrg#undef CORE_MASK
24936747b715Smrg#undef DONT_PROPAGATE_MASK
24946747b715Smrg
249505b261ecSmrg/**
249605b261ecSmrg * Deliver event to a window and it's immediate parent. Used for most window
249705b261ecSmrg * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
24984642e01fSmrg * propagate up the tree or extension events
249905b261ecSmrg *
250005b261ecSmrg * In case of a ReparentNotify event, the event will be delivered to the
250105b261ecSmrg * otherParent as well.
250205b261ecSmrg *
250305b261ecSmrg * @param pWin Window to deliver events to.
250405b261ecSmrg * @param xE Events to deliver.
250505b261ecSmrg * @param count number of events in xE.
250605b261ecSmrg * @param otherParent Used for ReparentNotify events.
250705b261ecSmrg */
25086747b715Smrgint
25094642e01fSmrgDeliverEvents(WindowPtr pWin, xEvent *xE, int count,
251005b261ecSmrg              WindowPtr otherParent)
251105b261ecSmrg{
251205b261ecSmrg    Mask filter;
251305b261ecSmrg    int     deliveries;
25146747b715Smrg    DeviceIntRec dummy;
251505b261ecSmrg
251605b261ecSmrg#ifdef PANORAMIX
251705b261ecSmrg    if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
251805b261ecSmrg	return count;
251905b261ecSmrg#endif
252005b261ecSmrg
252105b261ecSmrg    if (!count)
252205b261ecSmrg	return 0;
25236747b715Smrg
25246747b715Smrg    dummy.id = XIAllDevices;
25256747b715Smrg    filter = GetEventFilter(&dummy, xE);
252605b261ecSmrg    if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify))
252705b261ecSmrg	xE->u.destroyNotify.event = pWin->drawable.id;
252805b261ecSmrg    if (filter != StructureAndSubMask)
25296747b715Smrg	return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab);
25306747b715Smrg    deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count,
25316747b715Smrg                                       StructureNotifyMask, NullGrab);
253205b261ecSmrg    if (pWin->parent)
253305b261ecSmrg    {
253405b261ecSmrg	xE->u.destroyNotify.event = pWin->parent->drawable.id;
25356747b715Smrg	deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count,
25366747b715Smrg					    SubstructureNotifyMask, NullGrab);
253705b261ecSmrg	if (xE->u.u.type == ReparentNotify)
253805b261ecSmrg	{
253905b261ecSmrg	    xE->u.destroyNotify.event = otherParent->drawable.id;
25406747b715Smrg            deliveries += DeliverEventsToWindow(&dummy,
25414642e01fSmrg                    otherParent, xE, count, SubstructureNotifyMask,
25426747b715Smrg						NullGrab);
254305b261ecSmrg	}
254405b261ecSmrg    }
254505b261ecSmrg    return deliveries;
254605b261ecSmrg}
254705b261ecSmrg
254805b261ecSmrg
25494642e01fSmrgstatic Bool
255005b261ecSmrgPointInBorderSize(WindowPtr pWin, int x, int y)
255105b261ecSmrg{
255205b261ecSmrg    BoxRec box;
255305b261ecSmrg
25546747b715Smrg    if(RegionContainsPoint(&pWin->borderSize, x, y, &box))
255505b261ecSmrg	return TRUE;
255605b261ecSmrg
255705b261ecSmrg#ifdef PANORAMIX
25584642e01fSmrg    if(!noPanoramiXExtension &&
25594642e01fSmrg            XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
25606747b715Smrg	SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
256105b261ecSmrg	int i;
256205b261ecSmrg
256305b261ecSmrg	for(i = 1; i < PanoramiXNumScreens; i++) {
25646747b715Smrg	   if(RegionContainsPoint(&pSprite->windows[i]->borderSize,
25656747b715Smrg				  x + screenInfo.screens[0]->x - screenInfo.screens[i]->x,
25666747b715Smrg				  y + screenInfo.screens[0]->y - screenInfo.screens[i]->y,
25676747b715Smrg				  &box))
256805b261ecSmrg		return TRUE;
256905b261ecSmrg	}
257005b261ecSmrg    }
257105b261ecSmrg#endif
257205b261ecSmrg    return FALSE;
257305b261ecSmrg}
257405b261ecSmrg
257505b261ecSmrg/**
257605b261ecSmrg * Traversed from the root window to the window at the position x/y. While
257705b261ecSmrg * traversing, it sets up the traversal history in the spriteTrace array.
257805b261ecSmrg * After completing, the spriteTrace history is set in the following way:
257905b261ecSmrg *   spriteTrace[0] ... root window
258005b261ecSmrg *   spriteTrace[1] ... top level window that encloses x/y
258105b261ecSmrg *       ...
258205b261ecSmrg *   spriteTrace[spriteTraceGood - 1] ... window at x/y
258305b261ecSmrg *
258405b261ecSmrg * @returns the window at the given coordinates.
258505b261ecSmrg */
25864642e01fSmrgstatic WindowPtr
25874642e01fSmrgXYToWindow(DeviceIntPtr pDev, int x, int y)
258805b261ecSmrg{
258905b261ecSmrg    WindowPtr  pWin;
259005b261ecSmrg    BoxRec		box;
25914642e01fSmrg    SpritePtr pSprite;
259205b261ecSmrg
25934642e01fSmrg    pSprite = pDev->spriteInfo->sprite;
25944642e01fSmrg    pSprite->spriteTraceGood = 1;	/* root window still there */
25954642e01fSmrg    pWin = RootWindow(pDev)->firstChild;
259605b261ecSmrg    while (pWin)
259705b261ecSmrg    {
259805b261ecSmrg	if ((pWin->mapped) &&
259905b261ecSmrg	    (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
260005b261ecSmrg	    (x < pWin->drawable.x + (int)pWin->drawable.width +
260105b261ecSmrg	     wBorderWidth(pWin)) &&
260205b261ecSmrg	    (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
260305b261ecSmrg	    (y < pWin->drawable.y + (int)pWin->drawable.height +
260405b261ecSmrg	     wBorderWidth (pWin))
260505b261ecSmrg	    /* When a window is shaped, a further check
260605b261ecSmrg	     * is made to see if the point is inside
260705b261ecSmrg	     * borderSize
260805b261ecSmrg	     */
260905b261ecSmrg	    && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
261005b261ecSmrg	    && (!wInputShape(pWin) ||
26116747b715Smrg		RegionContainsPoint(wInputShape(pWin),
26126747b715Smrg				    x - pWin->drawable.x,
26136747b715Smrg				    y - pWin->drawable.y, &box))
26144642e01fSmrg#ifdef ROOTLESS
26154642e01fSmrg    /* In rootless mode windows may be offscreen, even when
26164642e01fSmrg     * they're in X's stack. (E.g. if the native window system
26174642e01fSmrg     * implements some form of virtual desktop system).
26184642e01fSmrg     */
26194642e01fSmrg		&& !pWin->rootlessUnhittable
262005b261ecSmrg#endif
262105b261ecSmrg	    )
262205b261ecSmrg	{
26234642e01fSmrg	    if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize)
262405b261ecSmrg	    {
26254642e01fSmrg		pSprite->spriteTraceSize += 10;
26266747b715Smrg		pSprite->spriteTrace = realloc(pSprite->spriteTrace,
26274642e01fSmrg		                    pSprite->spriteTraceSize*sizeof(WindowPtr));
262805b261ecSmrg	    }
26294642e01fSmrg	    pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
263005b261ecSmrg	    pWin = pWin->firstChild;
263105b261ecSmrg	}
263205b261ecSmrg	else
263305b261ecSmrg	    pWin = pWin->nextSib;
263405b261ecSmrg    }
26354642e01fSmrg    return pSprite->spriteTrace[pSprite->spriteTraceGood-1];
263605b261ecSmrg}
263705b261ecSmrg
26386747b715Smrg/**
26396747b715Smrg * Ungrab a currently FocusIn grabbed device and grab the device on the
26406747b715Smrg * given window. If the win given is the NoneWin, the device is ungrabbed if
26416747b715Smrg * applicable and FALSE is returned.
26426747b715Smrg *
26436747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise.
26446747b715Smrg */
26456747b715SmrgBOOL
26466747b715SmrgActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
26476747b715Smrg{
26486747b715Smrg    BOOL rc = FALSE;
26496747b715Smrg    DeviceEvent event;
26506747b715Smrg
26516747b715Smrg    if (dev->deviceGrab.grab &&
26526747b715Smrg        dev->deviceGrab.fromPassiveGrab &&
26536747b715Smrg        dev->deviceGrab.grab->type == XI_Enter)
26546747b715Smrg    {
26556747b715Smrg        if (dev->deviceGrab.grab->window == win ||
26566747b715Smrg            IsParent(dev->deviceGrab.grab->window, win))
26576747b715Smrg            return FALSE;
26586747b715Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
26596747b715Smrg        (*dev->deviceGrab.DeactivateGrab)(dev);
26606747b715Smrg    }
26616747b715Smrg
26626747b715Smrg    if (win == NoneWin || win == PointerRootWin)
26636747b715Smrg        return FALSE;
26646747b715Smrg
26656747b715Smrg    memset(&event, 0, sizeof(DeviceEvent));
26666747b715Smrg    event.header = ET_Internal;
26676747b715Smrg    event.type = ET_FocusIn;
26686747b715Smrg    event.length = sizeof(DeviceEvent);
26696747b715Smrg    event.time = GetTimeInMillis();
26706747b715Smrg    event.deviceid = dev->id;
26716747b715Smrg    event.sourceid = dev->id;
26726747b715Smrg    event.detail.button = 0;
26736747b715Smrg    rc = CheckPassiveGrabsOnWindow(win, dev, &event, FALSE);
26746747b715Smrg    if (rc)
26756747b715Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
26766747b715Smrg    return rc;
26776747b715Smrg}
26786747b715Smrg
26796747b715Smrg/**
26806747b715Smrg * Ungrab a currently Enter grabbed device and grab the device for the given
26816747b715Smrg * window.
26826747b715Smrg *
26836747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise.
26846747b715Smrg */
26856747b715Smrgstatic BOOL
26866747b715SmrgActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
26876747b715Smrg{
26886747b715Smrg    BOOL rc = FALSE;
26896747b715Smrg    DeviceEvent event;
26906747b715Smrg
26916747b715Smrg    if (dev->deviceGrab.grab &&
26926747b715Smrg        dev->deviceGrab.fromPassiveGrab &&
26936747b715Smrg        dev->deviceGrab.grab->type == XI_Enter)
26946747b715Smrg    {
26956747b715Smrg        if (dev->deviceGrab.grab->window == win ||
26966747b715Smrg            IsParent(dev->deviceGrab.grab->window, win))
26976747b715Smrg            return FALSE;
26986747b715Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
26996747b715Smrg        (*dev->deviceGrab.DeactivateGrab)(dev);
27006747b715Smrg    }
27016747b715Smrg
27026747b715Smrg    memset(&event, 0, sizeof(DeviceEvent));
27036747b715Smrg    event.header = ET_Internal;
27046747b715Smrg    event.type = ET_Enter;
27056747b715Smrg    event.length = sizeof(DeviceEvent);
27066747b715Smrg    event.time = GetTimeInMillis();
27076747b715Smrg    event.deviceid = dev->id;
27086747b715Smrg    event.sourceid = dev->id;
27096747b715Smrg    event.detail.button = 0;
27106747b715Smrg    rc = CheckPassiveGrabsOnWindow(win, dev, &event, FALSE);
27116747b715Smrg    if (rc)
27126747b715Smrg        DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
27136747b715Smrg
27146747b715Smrg    return rc;
27156747b715Smrg}
27166747b715Smrg
271705b261ecSmrg/**
271805b261ecSmrg * Update the sprite coordinates based on the event. Update the cursor
271905b261ecSmrg * position, then update the event with the new coordinates that may have been
272005b261ecSmrg * changed. If the window underneath the sprite has changed, change to new
272105b261ecSmrg * cursor and send enter/leave events.
27224642e01fSmrg *
27234642e01fSmrg * CheckMotion() will not do anything and return FALSE if the event is not a
27244642e01fSmrg * pointer event.
27254642e01fSmrg *
27264642e01fSmrg * @return TRUE if the sprite has moved or FALSE otherwise.
272705b261ecSmrg */
27284642e01fSmrgBool
27296747b715SmrgCheckMotion(DeviceEvent *ev, DeviceIntPtr pDev)
273005b261ecSmrg{
27316747b715Smrg    WindowPtr prevSpriteWin, newSpriteWin;
27324642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
27334642e01fSmrg
27346747b715Smrg    CHECKEVENT(ev);
273505b261ecSmrg
27366747b715Smrg    prevSpriteWin = pSprite->win;
273705b261ecSmrg
27386747b715Smrg    if (ev && !syncEvents.playingEvents)
273905b261ecSmrg    {
27404642e01fSmrg        /* GetPointerEvents() guarantees that pointer events have the correct
27414642e01fSmrg           rootX/Y set already. */
27426747b715Smrg        switch (ev->type)
27434642e01fSmrg        {
27446747b715Smrg            case ET_ButtonPress:
27456747b715Smrg            case ET_ButtonRelease:
27466747b715Smrg            case ET_Motion:
27474642e01fSmrg                break;
27484642e01fSmrg            default:
27494642e01fSmrg                /* all other events return FALSE */
27504642e01fSmrg                return FALSE;
27514642e01fSmrg        }
27524642e01fSmrg
27536747b715Smrg
27546747b715Smrg#ifdef PANORAMIX
27556747b715Smrg        if (!noPanoramiXExtension)
27564642e01fSmrg        {
27576747b715Smrg            /* Motion events entering DIX get translated to Screen 0
27586747b715Smrg               coordinates.  Replayed events have already been
27596747b715Smrg               translated since they've entered DIX before */
27606747b715Smrg            ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
27616747b715Smrg            ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
27626747b715Smrg        } else
27636747b715Smrg#endif
27646747b715Smrg        {
27656747b715Smrg            if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen)
27666747b715Smrg            {
27676747b715Smrg                pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
27686747b715Smrg                RootWindow(pDev) = pSprite->hot.pScreen->root;
27696747b715Smrg            }
27704642e01fSmrg        }
27716747b715Smrg
27726747b715Smrg        pSprite->hot.x = ev->root_x;
27736747b715Smrg        pSprite->hot.y = ev->root_y;
27744642e01fSmrg        if (pSprite->hot.x < pSprite->physLimits.x1)
27754642e01fSmrg            pSprite->hot.x = pSprite->physLimits.x1;
27764642e01fSmrg        else if (pSprite->hot.x >= pSprite->physLimits.x2)
27774642e01fSmrg            pSprite->hot.x = pSprite->physLimits.x2 - 1;
27784642e01fSmrg        if (pSprite->hot.y < pSprite->physLimits.y1)
27794642e01fSmrg            pSprite->hot.y = pSprite->physLimits.y1;
27804642e01fSmrg        else if (pSprite->hot.y >= pSprite->physLimits.y2)
27814642e01fSmrg            pSprite->hot.y = pSprite->physLimits.y2 - 1;
27824642e01fSmrg	if (pSprite->hotShape)
27834642e01fSmrg	    ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y);
27844642e01fSmrg	pSprite->hotPhys = pSprite->hot;
27854642e01fSmrg
27866747b715Smrg	if ((pSprite->hotPhys.x != ev->root_x) ||
27876747b715Smrg	    (pSprite->hotPhys.y != ev->root_y))
278805b261ecSmrg	{
27896747b715Smrg#ifdef PANORAMIX
27906747b715Smrg            if (!noPanoramiXExtension)
27916747b715Smrg            {
27926747b715Smrg                XineramaSetCursorPosition(
27936747b715Smrg                        pDev, pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
27946747b715Smrg            } else
27956747b715Smrg#endif
27966747b715Smrg            {
27976747b715Smrg                (*pSprite->hotPhys.pScreen->SetCursorPosition)(
27986747b715Smrg                        pDev, pSprite->hotPhys.pScreen,
27996747b715Smrg                        pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
28006747b715Smrg            }
280105b261ecSmrg	}
28024642e01fSmrg
28036747b715Smrg	ev->root_x = pSprite->hot.x;
28046747b715Smrg	ev->root_y = pSprite->hot.y;
280505b261ecSmrg    }
280605b261ecSmrg
28076747b715Smrg    newSpriteWin = XYToWindow(pDev, pSprite->hot.x, pSprite->hot.y);
28086747b715Smrg
28096747b715Smrg    if (newSpriteWin != prevSpriteWin)
281005b261ecSmrg    {
28116747b715Smrg        int sourceid;
28126747b715Smrg        if (!ev) {
28136747b715Smrg            UpdateCurrentTimeIf();
28146747b715Smrg            sourceid = pDev->id; /* when from WindowsRestructured */
28156747b715Smrg        } else
28166747b715Smrg            sourceid = ev->sourceid;
28176747b715Smrg
281805b261ecSmrg	if (prevSpriteWin != NullWindow) {
28196747b715Smrg            if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin))
28206747b715Smrg                DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin,
28216747b715Smrg                                   newSpriteWin, NotifyNormal);
28224642e01fSmrg        }
28236747b715Smrg        /* set pSprite->win after ActivateEnterGrab, otherwise
28246747b715Smrg           sprite window == grab_window and no enter/leave events are
28256747b715Smrg           sent. */
28266747b715Smrg        pSprite->win = newSpriteWin;
28276747b715Smrg        PostNewCursor(pDev);
282805b261ecSmrg        return FALSE;
282905b261ecSmrg    }
283005b261ecSmrg    return TRUE;
283105b261ecSmrg}
283205b261ecSmrg
283305b261ecSmrg/**
283405b261ecSmrg * Windows have restructured, we need to update the sprite position and the
283505b261ecSmrg * sprite's cursor.
283605b261ecSmrg */
28374642e01fSmrgvoid
283805b261ecSmrgWindowsRestructured(void)
283905b261ecSmrg{
28404642e01fSmrg    DeviceIntPtr pDev = inputInfo.devices;
28414642e01fSmrg    while(pDev)
28424642e01fSmrg    {
28436747b715Smrg        if (IsMaster(pDev) || !pDev->u.master)
2844b1d344b3Smrg            CheckMotion(NULL, pDev);
28454642e01fSmrg        pDev = pDev->next;
28464642e01fSmrg    }
284705b261ecSmrg}
284805b261ecSmrg
284905b261ecSmrg#ifdef PANORAMIX
285005b261ecSmrg/* This was added to support reconfiguration under Xdmx.  The problem is
28516747b715Smrg * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin
285205b261ecSmrg * other than 0,0, the information in the private sprite structure must
285305b261ecSmrg * be updated accordingly, or XYToWindow (and other routines) will not
285405b261ecSmrg * compute correctly. */
285505b261ecSmrgvoid ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
285605b261ecSmrg{
285705b261ecSmrg    GrabPtr   grab;
28584642e01fSmrg    DeviceIntPtr pDev;
28594642e01fSmrg    SpritePtr pSprite;
286005b261ecSmrg
286105b261ecSmrg    if (noPanoramiXExtension) return;
286205b261ecSmrg
28634642e01fSmrg    pDev = inputInfo.devices;
28644642e01fSmrg    while(pDev)
28654642e01fSmrg    {
28664642e01fSmrg        if (DevHasCursor(pDev))
28674642e01fSmrg        {
28684642e01fSmrg            pSprite = pDev->spriteInfo->sprite;
28694642e01fSmrg            pSprite->hot.x        -= xoff;
28704642e01fSmrg            pSprite->hot.y        -= yoff;
28714642e01fSmrg
28724642e01fSmrg            pSprite->hotPhys.x    -= xoff;
28734642e01fSmrg            pSprite->hotPhys.y    -= yoff;
28744642e01fSmrg
28754642e01fSmrg            pSprite->hotLimits.x1 -= xoff;
28764642e01fSmrg            pSprite->hotLimits.y1 -= yoff;
28774642e01fSmrg            pSprite->hotLimits.x2 -= xoff;
28784642e01fSmrg            pSprite->hotLimits.y2 -= yoff;
28794642e01fSmrg
28806747b715Smrg            if (RegionNotEmpty(&pSprite->Reg1))
28816747b715Smrg                RegionTranslate(&pSprite->Reg1, xoff, yoff);
28826747b715Smrg            if (RegionNotEmpty(&pSprite->Reg2))
28836747b715Smrg                RegionTranslate(&pSprite->Reg2, xoff, yoff);
28844642e01fSmrg
28854642e01fSmrg            /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
28864642e01fSmrg            if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
28874642e01fSmrg                if (grab->confineTo->drawable.pScreen
28884642e01fSmrg                        != pSprite->hotPhys.pScreen)
28894642e01fSmrg                    pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
28904642e01fSmrg                ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
28914642e01fSmrg            } else
28924642e01fSmrg                ConfineCursorToWindow(
28934642e01fSmrg                        pDev,
28946747b715Smrg                        pSprite->hotPhys.pScreen->root,
28954642e01fSmrg                        TRUE, FALSE);
28964642e01fSmrg
28974642e01fSmrg        }
28984642e01fSmrg        pDev = pDev->next;
28994642e01fSmrg    }
29004642e01fSmrg}
29014642e01fSmrg#endif
29024642e01fSmrg
29034642e01fSmrg/**
29044642e01fSmrg * Initialize a sprite for the given device and set it to some sane values. If
29054642e01fSmrg * the device already has a sprite alloc'd, don't realloc but just reset to
29064642e01fSmrg * default values.
29074642e01fSmrg * If a window is supplied, the sprite will be initialized with the window's
29084642e01fSmrg * cursor and positioned in the center of the window's screen. The root window
29094642e01fSmrg * is a good choice to pass in here.
29104642e01fSmrg *
29114642e01fSmrg * It's a good idea to call it only for pointer devices, unless you have a
29124642e01fSmrg * really talented keyboard.
29134642e01fSmrg *
29144642e01fSmrg * @param pDev The device to initialize.
29154642e01fSmrg * @param pWin The window where to generate the sprite in.
29164642e01fSmrg *
29174642e01fSmrg */
29184642e01fSmrgvoid
29194642e01fSmrgInitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
29204642e01fSmrg{
29214642e01fSmrg    SpritePtr pSprite;
29224642e01fSmrg    ScreenPtr pScreen;
29236747b715Smrg    CursorPtr pCursor;
29244642e01fSmrg
29254642e01fSmrg    if (!pDev->spriteInfo->sprite)
29264642e01fSmrg    {
29274642e01fSmrg        DeviceIntPtr it;
29284642e01fSmrg
29296747b715Smrg        pDev->spriteInfo->sprite = (SpritePtr)calloc(1, sizeof(SpriteRec));
29304642e01fSmrg        if (!pDev->spriteInfo->sprite)
29314642e01fSmrg            FatalError("InitializeSprite: failed to allocate sprite struct");
29324642e01fSmrg
29334642e01fSmrg        /* We may have paired another device with this device before our
29344642e01fSmrg         * device had a actual sprite. We need to check for this and reset the
29354642e01fSmrg         * sprite field for all paired devices.
29364642e01fSmrg         *
29374642e01fSmrg         * The VCK is always paired with the VCP before the VCP has a sprite.
29384642e01fSmrg         */
29394642e01fSmrg        for (it = inputInfo.devices; it; it = it->next)
29404642e01fSmrg        {
29414642e01fSmrg            if (it->spriteInfo->paired == pDev)
29424642e01fSmrg                it->spriteInfo->sprite = pDev->spriteInfo->sprite;
29434642e01fSmrg        }
29444642e01fSmrg        if (inputInfo.keyboard->spriteInfo->paired == pDev)
29454642e01fSmrg            inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite;
29464642e01fSmrg    }
29474642e01fSmrg
29484642e01fSmrg    pSprite = pDev->spriteInfo->sprite;
29494642e01fSmrg    pDev->spriteInfo->spriteOwner = TRUE;
295005b261ecSmrg
29514642e01fSmrg    pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr)NULL;
29524642e01fSmrg    pSprite->hot.pScreen = pScreen;
29534642e01fSmrg    pSprite->hotPhys.pScreen = pScreen;
29544642e01fSmrg    if (pScreen)
29554642e01fSmrg    {
29564642e01fSmrg        pSprite->hotPhys.x = pScreen->width / 2;
29574642e01fSmrg        pSprite->hotPhys.y = pScreen->height / 2;
29584642e01fSmrg        pSprite->hotLimits.x2 = pScreen->width;
29594642e01fSmrg        pSprite->hotLimits.y2 = pScreen->height;
29604642e01fSmrg    }
29614642e01fSmrg
29624642e01fSmrg    pSprite->hot = pSprite->hotPhys;
29634642e01fSmrg    pSprite->win = pWin;
29644642e01fSmrg
29654642e01fSmrg    if (pWin)
29664642e01fSmrg    {
29676747b715Smrg	pCursor = wCursor(pWin);
29686747b715Smrg	pSprite->spriteTrace = (WindowPtr *)calloc(1, 32*sizeof(WindowPtr));
29694642e01fSmrg	if (!pSprite->spriteTrace)
29704642e01fSmrg	    FatalError("Failed to allocate spriteTrace");
29714642e01fSmrg	pSprite->spriteTraceSize = 32;
29724642e01fSmrg
29734642e01fSmrg	RootWindow(pDev) = pWin;
29744642e01fSmrg	pSprite->spriteTraceGood = 1;
29754642e01fSmrg
29764642e01fSmrg	pSprite->pEnqueueScreen = pScreen;
29774642e01fSmrg	pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
29784642e01fSmrg
29794642e01fSmrg    } else {
29806747b715Smrg        pCursor = NullCursor;
29814642e01fSmrg	pSprite->spriteTrace = NULL;
29824642e01fSmrg	pSprite->spriteTraceSize = 0;
29834642e01fSmrg	pSprite->spriteTraceGood = 0;
29844642e01fSmrg	pSprite->pEnqueueScreen = screenInfo.screens[0];
29854642e01fSmrg	pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
29864642e01fSmrg    }
29876747b715Smrg    if (pCursor)
29886747b715Smrg	pCursor->refcnt++;
29896747b715Smrg    if (pSprite->current)
29906747b715Smrg	FreeCursor(pSprite->current, None);
29916747b715Smrg    pSprite->current = pCursor;
29924642e01fSmrg
29934642e01fSmrg    if (pScreen)
29944642e01fSmrg    {
29954642e01fSmrg        (*pScreen->RealizeCursor) ( pDev, pScreen, pSprite->current);
29964642e01fSmrg        (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current,
29974642e01fSmrg                                   &pSprite->hotLimits, &pSprite->physLimits);
29984642e01fSmrg        pSprite->confined = FALSE;
29994642e01fSmrg
30004642e01fSmrg        (*pScreen->ConstrainCursor) (pDev, pScreen,
30014642e01fSmrg                                     &pSprite->physLimits);
30024642e01fSmrg        (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
30034642e01fSmrg                                       pSprite->hot.y,
30044642e01fSmrg                                       FALSE);
30054642e01fSmrg        (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
30064642e01fSmrg    }
300705b261ecSmrg#ifdef PANORAMIX
300805b261ecSmrg    if(!noPanoramiXExtension) {
30096747b715Smrg        pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
30106747b715Smrg        pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
30116747b715Smrg        pSprite->hotLimits.x2 = PanoramiXPixWidth  - screenInfo.screens[0]->x;
30126747b715Smrg        pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
30134642e01fSmrg        pSprite->physLimits = pSprite->hotLimits;
30144642e01fSmrg        pSprite->confineWin = NullWindow;
30154642e01fSmrg        pSprite->hotShape = NullRegion;
30164642e01fSmrg        pSprite->screen = pScreen;
30174642e01fSmrg        /* gotta UNINIT these someplace */
30186747b715Smrg        RegionNull(&pSprite->Reg1);
30196747b715Smrg        RegionNull(&pSprite->Reg2);
30204642e01fSmrg    }
302105b261ecSmrg#endif
30224642e01fSmrg}
30234642e01fSmrg
30244642e01fSmrg/**
30254642e01fSmrg * Update the mouse sprite info when the server switches from a pScreen to another.
30264642e01fSmrg * Otherwise, the pScreen of the mouse sprite is never updated when we switch
30274642e01fSmrg * from a pScreen to another. Never updating the pScreen of the mouse sprite
30284642e01fSmrg * implies that windows that are in pScreen whose pScreen->myNum >0 will never
30294642e01fSmrg * get pointer events. This is  because in CheckMotion(), sprite.hotPhys.pScreen
30304642e01fSmrg * always points to the first pScreen it has been set by
30314642e01fSmrg * DefineInitialRootWindow().
30324642e01fSmrg *
30334642e01fSmrg * Calling this function is useful for use cases where the server
30344642e01fSmrg * has more than one pScreen.
30354642e01fSmrg * This function is similar to DefineInitialRootWindow() but it does not
30364642e01fSmrg * reset the mouse pointer position.
30374642e01fSmrg * @param win must be the new pScreen we are switching to.
30384642e01fSmrg */
30394642e01fSmrgvoid
30404642e01fSmrgUpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
30414642e01fSmrg{
30424642e01fSmrg    SpritePtr pSprite = NULL;
30434642e01fSmrg    WindowPtr win = NULL;
30446747b715Smrg    CursorPtr pCursor;
30454642e01fSmrg    if (!pScreen)
30464642e01fSmrg        return ;
30474642e01fSmrg
30484642e01fSmrg    if (!pDev->spriteInfo->sprite)
30494642e01fSmrg        return;
30504642e01fSmrg
30514642e01fSmrg    pSprite = pDev->spriteInfo->sprite;
30524642e01fSmrg
30536747b715Smrg    win = pScreen->root;
30544642e01fSmrg
30554642e01fSmrg    pSprite->hotPhys.pScreen = pScreen;
30564642e01fSmrg    pSprite->hot = pSprite->hotPhys;
30574642e01fSmrg    pSprite->hotLimits.x2 = pScreen->width;
30584642e01fSmrg    pSprite->hotLimits.y2 = pScreen->height;
30594642e01fSmrg    pSprite->win = win;
30606747b715Smrg    pCursor = wCursor(win);
30616747b715Smrg    if (pCursor)
30626747b715Smrg	pCursor->refcnt++;
30636747b715Smrg    if (pSprite->current)
30646747b715Smrg	FreeCursor(pSprite->current, 0);
30656747b715Smrg    pSprite->current = pCursor;
30664642e01fSmrg    pSprite->spriteTraceGood = 1;
30674642e01fSmrg    pSprite->spriteTrace[0] = win;
30684642e01fSmrg    (*pScreen->CursorLimits) (pDev,
30694642e01fSmrg                              pScreen,
30704642e01fSmrg                              pSprite->current,
30714642e01fSmrg                              &pSprite->hotLimits,
30724642e01fSmrg                              &pSprite->physLimits);
30734642e01fSmrg    pSprite->confined = FALSE;
30744642e01fSmrg    (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
30754642e01fSmrg    (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
30764642e01fSmrg
30774642e01fSmrg#ifdef PANORAMIX
30784642e01fSmrg    if(!noPanoramiXExtension) {
30796747b715Smrg        pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
30806747b715Smrg        pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
30816747b715Smrg        pSprite->hotLimits.x2 = PanoramiXPixWidth  - screenInfo.screens[0]->x;
30826747b715Smrg        pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
30834642e01fSmrg        pSprite->physLimits = pSprite->hotLimits;
30844642e01fSmrg        pSprite->screen = pScreen;
308505b261ecSmrg    }
308605b261ecSmrg#endif
308705b261ecSmrg}
308805b261ecSmrg
308905b261ecSmrg/*
309005b261ecSmrg * This does not take any shortcuts, and even ignores its argument, since
309105b261ecSmrg * it does not happen very often, and one has to walk up the tree since
309205b261ecSmrg * this might be a newly instantiated cursor for an intermediate window
309305b261ecSmrg * between the one the pointer is in and the one that the last cursor was
309405b261ecSmrg * instantiated from.
309505b261ecSmrg */
309605b261ecSmrgvoid
309705b261ecSmrgWindowHasNewCursor(WindowPtr pWin)
309805b261ecSmrg{
30994642e01fSmrg    DeviceIntPtr pDev;
31004642e01fSmrg
31014642e01fSmrg    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
31024642e01fSmrg        if (DevHasCursor(pDev))
31034642e01fSmrg            PostNewCursor(pDev);
310405b261ecSmrg}
310505b261ecSmrg
31066747b715Smrgvoid
31074642e01fSmrgNewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
310805b261ecSmrg{
31094642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
31104642e01fSmrg
31114642e01fSmrg    pSprite->hotPhys.x = x;
31124642e01fSmrg    pSprite->hotPhys.y = y;
311305b261ecSmrg#ifdef PANORAMIX
311405b261ecSmrg    if(!noPanoramiXExtension) {
31156747b715Smrg	pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x;
31166747b715Smrg	pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y;
31174642e01fSmrg	if (newScreen != pSprite->screen) {
31184642e01fSmrg	    pSprite->screen = newScreen;
311905b261ecSmrg	    /* Make sure we tell the DDX to update its copy of the screen */
31204642e01fSmrg	    if(pSprite->confineWin)
31214642e01fSmrg		XineramaConfineCursorToWindow(pDev,
31224642e01fSmrg                        pSprite->confineWin, TRUE);
312305b261ecSmrg	    else
31246747b715Smrg		XineramaConfineCursorToWindow(pDev, screenInfo.screens[0]->root, TRUE);
31254642e01fSmrg	    /* if the pointer wasn't confined, the DDX won't get
312605b261ecSmrg	       told of the pointer warp so we reposition it here */
312705b261ecSmrg	    if(!syncEvents.playingEvents)
31284642e01fSmrg		(*pSprite->screen->SetCursorPosition)(
31294642e01fSmrg                                                      pDev,
31304642e01fSmrg                                                      pSprite->screen,
31316747b715Smrg		    pSprite->hotPhys.x + screenInfo.screens[0]->x -
31326747b715Smrg			pSprite->screen->x,
31336747b715Smrg		    pSprite->hotPhys.y + screenInfo.screens[0]->y -
31346747b715Smrg			pSprite->screen->y, FALSE);
313505b261ecSmrg	}
31364642e01fSmrg    } else
313705b261ecSmrg#endif
31384642e01fSmrg    if (newScreen != pSprite->hotPhys.pScreen)
31396747b715Smrg	ConfineCursorToWindow(pDev, newScreen->root, TRUE, FALSE);
314005b261ecSmrg}
314105b261ecSmrg
314205b261ecSmrg#ifdef PANORAMIX
314305b261ecSmrg
314405b261ecSmrgstatic Bool
314505b261ecSmrgXineramaPointInWindowIsVisible(
314605b261ecSmrg    WindowPtr pWin,
314705b261ecSmrg    int x,
314805b261ecSmrg    int y
314905b261ecSmrg)
315005b261ecSmrg{
315105b261ecSmrg    BoxRec box;
315205b261ecSmrg    int i, xoff, yoff;
315305b261ecSmrg
315405b261ecSmrg    if (!pWin->realized) return FALSE;
315505b261ecSmrg
31566747b715Smrg    if (RegionContainsPoint(&pWin->borderClip, x, y, &box))
315705b261ecSmrg        return TRUE;
315805b261ecSmrg
31594642e01fSmrg    if(!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) return FALSE;
31604642e01fSmrg
31616747b715Smrg    xoff = x + screenInfo.screens[0]->x;
31626747b715Smrg    yoff = y + screenInfo.screens[0]->y;
316305b261ecSmrg
316405b261ecSmrg    for(i = 1; i < PanoramiXNumScreens; i++) {
31654642e01fSmrg	pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
31666747b715Smrg	x = xoff - screenInfo.screens[i]->x;
31676747b715Smrg	y = yoff - screenInfo.screens[i]->y;
316805b261ecSmrg
31696747b715Smrg	if(RegionContainsPoint(&pWin->borderClip, x, y, &box)
317005b261ecSmrg	   && (!wInputShape(pWin) ||
31716747b715Smrg	       RegionContainsPoint(wInputShape(pWin),
31726747b715Smrg				   x - pWin->drawable.x,
31736747b715Smrg				   y - pWin->drawable.y, &box)))
317405b261ecSmrg            return TRUE;
317505b261ecSmrg
317605b261ecSmrg    }
317705b261ecSmrg
317805b261ecSmrg    return FALSE;
317905b261ecSmrg}
318005b261ecSmrg
318105b261ecSmrgstatic int
318205b261ecSmrgXineramaWarpPointer(ClientPtr client)
318305b261ecSmrg{
318405b261ecSmrg    WindowPtr	dest = NULL;
318505b261ecSmrg    int		x, y, rc;
31864642e01fSmrg    SpritePtr   pSprite = PickPointer(client)->spriteInfo->sprite;
318705b261ecSmrg
318805b261ecSmrg    REQUEST(xWarpPointerReq);
318905b261ecSmrg
319005b261ecSmrg
319105b261ecSmrg    if (stuff->dstWid != None) {
319205b261ecSmrg	rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
319305b261ecSmrg	if (rc != Success)
319405b261ecSmrg	    return rc;
319505b261ecSmrg    }
31964642e01fSmrg    x = pSprite->hotPhys.x;
31974642e01fSmrg    y = pSprite->hotPhys.y;
319805b261ecSmrg
319905b261ecSmrg    if (stuff->srcWid != None)
320005b261ecSmrg    {
320105b261ecSmrg	int     winX, winY;
32024642e01fSmrg	XID	winID = stuff->srcWid;
320305b261ecSmrg        WindowPtr source;
32044642e01fSmrg
320505b261ecSmrg	rc = dixLookupWindow(&source, winID, client, DixReadAccess);
320605b261ecSmrg	if (rc != Success)
320705b261ecSmrg	    return rc;
320805b261ecSmrg
320905b261ecSmrg	winX = source->drawable.x;
321005b261ecSmrg	winY = source->drawable.y;
32116747b715Smrg	if(source == screenInfo.screens[0]->root) {
32126747b715Smrg	    winX -= screenInfo.screens[0]->x;
32136747b715Smrg	    winY -= screenInfo.screens[0]->y;
321405b261ecSmrg	}
321505b261ecSmrg	if (x < winX + stuff->srcX ||
321605b261ecSmrg	    y < winY + stuff->srcY ||
321705b261ecSmrg	    (stuff->srcWidth != 0 &&
321805b261ecSmrg	     winX + stuff->srcX + (int)stuff->srcWidth < x) ||
321905b261ecSmrg	    (stuff->srcHeight != 0 &&
322005b261ecSmrg	     winY + stuff->srcY + (int)stuff->srcHeight < y) ||
322105b261ecSmrg	    !XineramaPointInWindowIsVisible(source, x, y))
322205b261ecSmrg	    return Success;
322305b261ecSmrg    }
322405b261ecSmrg    if (dest) {
322505b261ecSmrg	x = dest->drawable.x;
322605b261ecSmrg	y = dest->drawable.y;
32276747b715Smrg	if(dest == screenInfo.screens[0]->root) {
32286747b715Smrg	    x -= screenInfo.screens[0]->x;
32296747b715Smrg	    y -= screenInfo.screens[0]->y;
323005b261ecSmrg	}
32314642e01fSmrg    }
323205b261ecSmrg
323305b261ecSmrg    x += stuff->dstX;
323405b261ecSmrg    y += stuff->dstY;
323505b261ecSmrg
32364642e01fSmrg    if (x < pSprite->physLimits.x1)
32374642e01fSmrg	x = pSprite->physLimits.x1;
32384642e01fSmrg    else if (x >= pSprite->physLimits.x2)
32394642e01fSmrg	x = pSprite->physLimits.x2 - 1;
32404642e01fSmrg    if (y < pSprite->physLimits.y1)
32414642e01fSmrg	y = pSprite->physLimits.y1;
32424642e01fSmrg    else if (y >= pSprite->physLimits.y2)
32434642e01fSmrg	y = pSprite->physLimits.y2 - 1;
32444642e01fSmrg    if (pSprite->hotShape)
32454642e01fSmrg	ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
324605b261ecSmrg
32474642e01fSmrg    XineramaSetCursorPosition(PickPointer(client), x, y, TRUE);
324805b261ecSmrg
324905b261ecSmrg    return Success;
325005b261ecSmrg}
325105b261ecSmrg
325205b261ecSmrg#endif
325305b261ecSmrg
325405b261ecSmrg
325505b261ecSmrg/**
325605b261ecSmrg * Server-side protocol handling for WarpPointer request.
325705b261ecSmrg * Warps the cursor position to the coordinates given in the request.
325805b261ecSmrg */
325905b261ecSmrgint
326005b261ecSmrgProcWarpPointer(ClientPtr client)
326105b261ecSmrg{
326205b261ecSmrg    WindowPtr	dest = NULL;
326305b261ecSmrg    int		x, y, rc;
326405b261ecSmrg    ScreenPtr	newScreen;
32656747b715Smrg    DeviceIntPtr dev, tmp;
32664642e01fSmrg    SpritePtr   pSprite;
326705b261ecSmrg
326805b261ecSmrg    REQUEST(xWarpPointerReq);
326905b261ecSmrg    REQUEST_SIZE_MATCH(xWarpPointerReq);
327005b261ecSmrg
32716747b715Smrg    dev = PickPointer(client);
32726747b715Smrg
32736747b715Smrg    for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
32746747b715Smrg        if ((tmp == dev) || (!IsMaster(tmp) && tmp->u.master == dev)) {
32754642e01fSmrg	    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
32764642e01fSmrg	    if (rc != Success)
32774642e01fSmrg		return rc;
32784642e01fSmrg	}
32794642e01fSmrg    }
32804642e01fSmrg
32814642e01fSmrg    if (dev->u.lastSlave)
32824642e01fSmrg        dev = dev->u.lastSlave;
32834642e01fSmrg    pSprite = dev->spriteInfo->sprite;
32844642e01fSmrg
328505b261ecSmrg#ifdef PANORAMIX
328605b261ecSmrg    if(!noPanoramiXExtension)
328705b261ecSmrg	return XineramaWarpPointer(client);
328805b261ecSmrg#endif
328905b261ecSmrg
329005b261ecSmrg    if (stuff->dstWid != None) {
32914642e01fSmrg	rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess);
329205b261ecSmrg	if (rc != Success)
329305b261ecSmrg	    return rc;
329405b261ecSmrg    }
32954642e01fSmrg    x = pSprite->hotPhys.x;
32964642e01fSmrg    y = pSprite->hotPhys.y;
329705b261ecSmrg
329805b261ecSmrg    if (stuff->srcWid != None)
329905b261ecSmrg    {
330005b261ecSmrg	int     winX, winY;
33014642e01fSmrg	XID	winID = stuff->srcWid;
330205b261ecSmrg        WindowPtr source;
33034642e01fSmrg
33044642e01fSmrg	rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess);
330505b261ecSmrg	if (rc != Success)
330605b261ecSmrg	    return rc;
330705b261ecSmrg
330805b261ecSmrg	winX = source->drawable.x;
330905b261ecSmrg	winY = source->drawable.y;
33104642e01fSmrg	if (source->drawable.pScreen != pSprite->hotPhys.pScreen ||
331105b261ecSmrg	    x < winX + stuff->srcX ||
331205b261ecSmrg	    y < winY + stuff->srcY ||
331305b261ecSmrg	    (stuff->srcWidth != 0 &&
331405b261ecSmrg	     winX + stuff->srcX + (int)stuff->srcWidth < x) ||
331505b261ecSmrg	    (stuff->srcHeight != 0 &&
331605b261ecSmrg	     winY + stuff->srcY + (int)stuff->srcHeight < y) ||
331705b261ecSmrg	    !PointInWindowIsVisible(source, x, y))
331805b261ecSmrg	    return Success;
331905b261ecSmrg    }
33204642e01fSmrg    if (dest)
332105b261ecSmrg    {
332205b261ecSmrg	x = dest->drawable.x;
332305b261ecSmrg	y = dest->drawable.y;
332405b261ecSmrg	newScreen = dest->drawable.pScreen;
33254642e01fSmrg    } else
33264642e01fSmrg	newScreen = pSprite->hotPhys.pScreen;
332705b261ecSmrg
332805b261ecSmrg    x += stuff->dstX;
332905b261ecSmrg    y += stuff->dstY;
333005b261ecSmrg
333105b261ecSmrg    if (x < 0)
333205b261ecSmrg	x = 0;
333305b261ecSmrg    else if (x >= newScreen->width)
333405b261ecSmrg	x = newScreen->width - 1;
333505b261ecSmrg    if (y < 0)
333605b261ecSmrg	y = 0;
333705b261ecSmrg    else if (y >= newScreen->height)
333805b261ecSmrg	y = newScreen->height - 1;
333905b261ecSmrg
33404642e01fSmrg    if (newScreen == pSprite->hotPhys.pScreen)
33414642e01fSmrg    {
33424642e01fSmrg	if (x < pSprite->physLimits.x1)
33434642e01fSmrg	    x = pSprite->physLimits.x1;
33444642e01fSmrg	else if (x >= pSprite->physLimits.x2)
33454642e01fSmrg	    x = pSprite->physLimits.x2 - 1;
33464642e01fSmrg	if (y < pSprite->physLimits.y1)
33474642e01fSmrg	    y = pSprite->physLimits.y1;
33484642e01fSmrg	else if (y >= pSprite->physLimits.y2)
33494642e01fSmrg	    y = pSprite->physLimits.y2 - 1;
33504642e01fSmrg	if (pSprite->hotShape)
33514642e01fSmrg	    ConfineToShape(dev, pSprite->hotShape, &x, &y);
33524642e01fSmrg        (*newScreen->SetCursorPosition)(dev, newScreen, x, y, TRUE);
335305b261ecSmrg    }
33544642e01fSmrg    else if (!PointerConfinedToScreen(dev))
335505b261ecSmrg    {
33564642e01fSmrg	NewCurrentScreen(dev, newScreen, x, y);
335705b261ecSmrg    }
335805b261ecSmrg    return Success;
335905b261ecSmrg}
336005b261ecSmrg
33614642e01fSmrgstatic Bool
33624642e01fSmrgBorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
336305b261ecSmrg{
33646747b715Smrg     if(RegionNotEmpty(&pWin->borderSize))
336505b261ecSmrg	return TRUE;
336605b261ecSmrg
336705b261ecSmrg#ifdef PANORAMIX
33684642e01fSmrg     if(!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) {
336905b261ecSmrg	int i;
337005b261ecSmrg
337105b261ecSmrg	for(i = 1; i < PanoramiXNumScreens; i++) {
33726747b715Smrg	    if(RegionNotEmpty(&pDev->spriteInfo->sprite->windows[i]->borderSize))
337305b261ecSmrg		return TRUE;
337405b261ecSmrg	}
337505b261ecSmrg     }
337605b261ecSmrg#endif
337705b261ecSmrg     return FALSE;
337805b261ecSmrg}
337905b261ecSmrg
33804642e01fSmrg/**
338105b261ecSmrg * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
33824642e01fSmrg * passive grab set on the window to be activated.
338305b261ecSmrg * If a passive grab is activated, the event will be delivered to the client.
33844642e01fSmrg *
338505b261ecSmrg * @param pWin The window that may be subject to a passive grab.
338605b261ecSmrg * @param device Device that caused the event.
33876747b715Smrg * @param event The current device event.
33886747b715Smrg * @param checkCore Check for core grabs too.
338905b261ecSmrg */
339005b261ecSmrg
339105b261ecSmrgstatic Bool
339205b261ecSmrgCheckPassiveGrabsOnWindow(
339305b261ecSmrg    WindowPtr pWin,
339405b261ecSmrg    DeviceIntPtr device,
33956747b715Smrg    DeviceEvent *event,
33966747b715Smrg    BOOL checkCore)
339705b261ecSmrg{
339805b261ecSmrg    GrabPtr grab = wPassiveGrabs(pWin);
339905b261ecSmrg    GrabRec tempGrab;
34004642e01fSmrg    GrabInfoPtr grabinfo;
34016747b715Smrg#define CORE_MATCH      0x1
34026747b715Smrg#define XI_MATCH        0x2
34036747b715Smrg#define XI2_MATCH        0x4
34046747b715Smrg    int match = 0;
34056747b715Smrg
34066747b715Smrg    if (device->deviceGrab.grab)
34076747b715Smrg        return FALSE;
340805b261ecSmrg
340905b261ecSmrg    if (!grab)
341005b261ecSmrg	return FALSE;
34116747b715Smrg    /* Fill out the grab details, but leave the type for later before
34126747b715Smrg     * comparing */
341305b261ecSmrg    tempGrab.window = pWin;
341405b261ecSmrg    tempGrab.device = device;
34156747b715Smrg    tempGrab.detail.exact = event->detail.key;
341605b261ecSmrg    tempGrab.detail.pMask = NULL;
341705b261ecSmrg    tempGrab.modifiersDetail.pMask = NULL;
34184642e01fSmrg    tempGrab.next = NULL;
341905b261ecSmrg    for (; grab; grab = grab->next)
342005b261ecSmrg    {
342105b261ecSmrg	DeviceIntPtr	gdev;
34224642e01fSmrg	XkbSrvInfoPtr	xkbi = NULL;
342305b261ecSmrg
342405b261ecSmrg	gdev= grab->modifierDevice;
34256747b715Smrg        if (grab->grabtype == GRABTYPE_CORE)
34264642e01fSmrg        {
34274642e01fSmrg            if (IsPointerDevice(device))
34284642e01fSmrg                gdev = GetPairedDevice(device);
34294642e01fSmrg            else
34304642e01fSmrg                gdev = device;
34316747b715Smrg        } else if (grab->grabtype == GRABTYPE_XI2)
34326747b715Smrg        {
34336747b715Smrg            /* if the device is an attached slave device, gdev must be the
34346747b715Smrg             * attached master keyboard. Since the slave may have been
34356747b715Smrg             * reattached after the grab, the modifier device may not be the
34366747b715Smrg             * same. */
34376747b715Smrg            if (!IsMaster(grab->device) && device->u.master)
34386747b715Smrg                gdev = GetMaster(device, MASTER_KEYBOARD);
34394642e01fSmrg        }
34406747b715Smrg
34416747b715Smrg
34424642e01fSmrg        if (gdev && gdev->key)
34434642e01fSmrg            xkbi= gdev->key->xkbInfo;
344405b261ecSmrg	tempGrab.modifierDevice = grab->modifierDevice;
34456747b715Smrg        tempGrab.modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
34466747b715Smrg
34476747b715Smrg        /* Check for XI2 and XI grabs first */
34486747b715Smrg        tempGrab.type = GetXI2Type((InternalEvent*)event);
34496747b715Smrg        tempGrab.grabtype = GRABTYPE_XI2;
34506747b715Smrg        if (GrabMatchesSecond(&tempGrab, grab, FALSE))
34516747b715Smrg            match = XI2_MATCH;
34526747b715Smrg
34536747b715Smrg        tempGrab.detail.exact = event->detail.key;
34546747b715Smrg        if (!match)
34556747b715Smrg        {
34566747b715Smrg            tempGrab.type = GetXIType((InternalEvent*)event);
34576747b715Smrg            tempGrab.grabtype = GRABTYPE_XI;
34586747b715Smrg            if (GrabMatchesSecond(&tempGrab, grab, FALSE))
34596747b715Smrg                match = XI_MATCH;
34606747b715Smrg        }
34616747b715Smrg
34626747b715Smrg        /* Check for a core grab (ignore the device when comparing) */
34636747b715Smrg        if (!match && checkCore)
34646747b715Smrg        {
34656747b715Smrg            tempGrab.grabtype = GRABTYPE_CORE;
34666747b715Smrg            if ((tempGrab.type = GetCoreType((InternalEvent*)event)) &&
34676747b715Smrg                (GrabMatchesSecond(&tempGrab, grab, TRUE)))
34686747b715Smrg                match = CORE_MATCH;
34696747b715Smrg        }
34706747b715Smrg
34716747b715Smrg        if (match && (!grab->confineTo ||
34724642e01fSmrg	     (grab->confineTo->realized &&
34734642e01fSmrg				BorderSizeNotEmpty(device, grab->confineTo))))
347405b261ecSmrg	{
34756747b715Smrg            int rc, count = 0;
34766747b715Smrg            xEvent *xE = NULL;
34776747b715Smrg            xEvent core;
34784642e01fSmrg
34796747b715Smrg            event->corestate &= 0x1f00;
34806747b715Smrg            event->corestate |= tempGrab.modifiersDetail.exact & (~0x1f00);
34816747b715Smrg            grabinfo = &device->deviceGrab;
34824642e01fSmrg            /* In some cases a passive core grab may exist, but the client
34834642e01fSmrg             * already has a core grab on some other device. In this case we
34844642e01fSmrg             * must not get the grab, otherwise we may never ungrab the
34854642e01fSmrg             * device.
34864642e01fSmrg             */
34874642e01fSmrg
34886747b715Smrg            if (grab->grabtype == GRABTYPE_CORE)
34894642e01fSmrg            {
34904642e01fSmrg                DeviceIntPtr other;
34914642e01fSmrg                BOOL interfering = FALSE;
34926747b715Smrg
34936747b715Smrg                /* A passive grab may have been created for a different device
34946747b715Smrg                   than it is assigned to at this point in time.
34956747b715Smrg                   Update the grab's device and modifier device to reflect the
34966747b715Smrg                   current state.
34976747b715Smrg                   Since XGrabDeviceButton requires to specify the
34986747b715Smrg                   modifierDevice explicitly, we don't override this choice.
34996747b715Smrg                   */
35006747b715Smrg                if (tempGrab.type < GenericEvent)
35016747b715Smrg                {
35026747b715Smrg                    grab->device = device;
35036747b715Smrg                    grab->modifierDevice = GetPairedDevice(device);
35046747b715Smrg                }
35056747b715Smrg
35064642e01fSmrg                for (other = inputInfo.devices; other; other = other->next)
35074642e01fSmrg                {
35084642e01fSmrg                    GrabPtr othergrab = other->deviceGrab.grab;
35096747b715Smrg                    if (othergrab && othergrab->grabtype == GRABTYPE_CORE &&
35104642e01fSmrg                        SameClient(grab, rClient(othergrab)) &&
35114642e01fSmrg                        ((IsPointerDevice(grab->device) &&
35124642e01fSmrg                         IsPointerDevice(othergrab->device)) ||
35134642e01fSmrg                         (IsKeyboardDevice(grab->device) &&
35144642e01fSmrg                          IsKeyboardDevice(othergrab->device))))
35154642e01fSmrg                    {
35164642e01fSmrg                        interfering = TRUE;
35174642e01fSmrg                        break;
35184642e01fSmrg                    }
35194642e01fSmrg                }
35204642e01fSmrg                if (interfering)
35214642e01fSmrg                    continue;
35224642e01fSmrg            }
35234642e01fSmrg
35244642e01fSmrg
35256747b715Smrg            if (match & CORE_MATCH)
35266747b715Smrg            {
35276747b715Smrg                rc = EventToCore((InternalEvent*)event, &core);
35286747b715Smrg                if (rc != Success)
35296747b715Smrg                {
35306747b715Smrg                    if (rc != BadMatch)
35316747b715Smrg                        ErrorF("[dix] %s: core conversion failed in CPGFW "
35326747b715Smrg                                "(%d, %d).\n", device->name, event->type, rc);
35336747b715Smrg                    continue;
35346747b715Smrg                }
35356747b715Smrg                xE = &core;
35366747b715Smrg                count = 1;
35376747b715Smrg            } else if (match & XI2_MATCH)
35386747b715Smrg            {
35396747b715Smrg                rc = EventToXI2((InternalEvent*)event, &xE);
35406747b715Smrg                if (rc != Success)
35416747b715Smrg                {
35426747b715Smrg                    if (rc != BadMatch)
35436747b715Smrg                        ErrorF("[dix] %s: XI2 conversion failed in CPGFW "
35446747b715Smrg                                "(%d, %d).\n", device->name, event->type, rc);
35456747b715Smrg                    continue;
35466747b715Smrg                }
35476747b715Smrg                count = 1;
35486747b715Smrg            } else
35496747b715Smrg            {
35506747b715Smrg                rc = EventToXI((InternalEvent*)event, &xE, &count);
35516747b715Smrg                if (rc != Success)
35526747b715Smrg                {
35536747b715Smrg                    if (rc != BadMatch)
35546747b715Smrg                        ErrorF("[dix] %s: XI conversion failed in CPGFW "
35556747b715Smrg                                "(%d, %d).\n", device->name, event->type, rc);
35566747b715Smrg                    continue;
35576747b715Smrg                }
35586747b715Smrg            }
35596747b715Smrg
35604642e01fSmrg	    (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
35614642e01fSmrg
35626747b715Smrg            if (xE)
35636747b715Smrg            {
35646747b715Smrg                FixUpEventFromWindow(device, xE, grab->window, None, TRUE);
356505b261ecSmrg
35666747b715Smrg                TryClientEvents(rClient(grab), device, xE, count,
35676747b715Smrg                                       GetEventFilter(device, xE),
35686747b715Smrg                                       GetEventFilter(device, xE), grab);
35696747b715Smrg            }
357005b261ecSmrg
35714642e01fSmrg	    if (grabinfo->sync.state == FROZEN_NO_EVENT)
357205b261ecSmrg	    {
35736747b715Smrg                if (!grabinfo->sync.event)
35746747b715Smrg                    grabinfo->sync.event = calloc(1, sizeof(InternalEvent));
35756747b715Smrg                *grabinfo->sync.event = *event;
35764642e01fSmrg		grabinfo->sync.state = FROZEN_WITH_EVENT;
35774642e01fSmrg            }
35786747b715Smrg
35796747b715Smrg            if (match & (XI_MATCH | XI2_MATCH))
35806747b715Smrg                free(xE); /* on core match xE == &core */
358105b261ecSmrg	    return TRUE;
358205b261ecSmrg	}
358305b261ecSmrg    }
358405b261ecSmrg    return FALSE;
35856747b715Smrg#undef CORE_MATCH
35866747b715Smrg#undef XI_MATCH
35876747b715Smrg#undef XI2_MATCH
358805b261ecSmrg}
358905b261ecSmrg
359005b261ecSmrg/**
359105b261ecSmrg * CheckDeviceGrabs handles both keyboard and pointer events that may cause
35924642e01fSmrg * a passive grab to be activated.
359305b261ecSmrg *
359405b261ecSmrg * If the event is a keyboard event, the ancestors of the focus window are
359505b261ecSmrg * traced down and tried to see if they have any passive grabs to be
359605b261ecSmrg * activated.  If the focus window itself is reached and it's descendants
359705b261ecSmrg * contain the pointer, the ancestors of the window that the pointer is in
359805b261ecSmrg * are then traced down starting at the focus window, otherwise no grabs are
35994642e01fSmrg * activated.
360005b261ecSmrg * If the event is a pointer event, the ancestors of the window that the
360105b261ecSmrg * pointer is in are traced down starting at the root until CheckPassiveGrabs
360205b261ecSmrg * causes a passive grab to activate or all the windows are
360305b261ecSmrg * tried. PRH
360405b261ecSmrg *
360505b261ecSmrg * If a grab is activated, the event has been sent to the client already!
360605b261ecSmrg *
36074642e01fSmrg * The event we pass in must always be an XI event. From this, we then emulate
36084642e01fSmrg * the core event and then check for grabs.
36094642e01fSmrg *
361005b261ecSmrg * @param device The device that caused the event.
36114642e01fSmrg * @param xE The event to handle (Device{Button|Key}Press).
361205b261ecSmrg * @param count Number of events in list.
361305b261ecSmrg * @return TRUE if a grab has been activated or false otherwise.
361405b261ecSmrg*/
361505b261ecSmrg
361605b261ecSmrgBool
36176747b715SmrgCheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, int checkFirst)
361805b261ecSmrg{
361905b261ecSmrg    int i;
362005b261ecSmrg    WindowPtr pWin = NULL;
36216747b715Smrg    FocusClassPtr focus = IsPointerEvent((InternalEvent*)event) ? NULL : device->focus;
36226747b715Smrg    BOOL sendCore = (IsMaster(device) && device->coreEvents);
362305b261ecSmrg
36246747b715Smrg    if (event->type != ET_ButtonPress &&
36256747b715Smrg        event->type != ET_KeyPress)
36264642e01fSmrg        return FALSE;
36274642e01fSmrg
36286747b715Smrg    if (event->type == ET_ButtonPress
36296747b715Smrg        && (device->button->buttonsDown != 1))
36306747b715Smrg	return FALSE;
36314642e01fSmrg
363205b261ecSmrg    i = checkFirst;
363305b261ecSmrg
363405b261ecSmrg    if (focus)
363505b261ecSmrg    {
363605b261ecSmrg	for (; i < focus->traceGood; i++)
363705b261ecSmrg	{
363805b261ecSmrg	    pWin = focus->trace[i];
363905b261ecSmrg	    if (pWin->optional &&
36406747b715Smrg	        CheckPassiveGrabsOnWindow(pWin, device, event, sendCore))
364105b261ecSmrg		return TRUE;
364205b261ecSmrg	}
36434642e01fSmrg
364405b261ecSmrg	if ((focus->win == NoneWin) ||
36454642e01fSmrg	    (i >= device->spriteInfo->sprite->spriteTraceGood) ||
36464642e01fSmrg	    ((i > checkFirst) &&
36474642e01fSmrg             (pWin != device->spriteInfo->sprite->spriteTrace[i-1])))
364805b261ecSmrg	    return FALSE;
364905b261ecSmrg    }
365005b261ecSmrg
36514642e01fSmrg    for (; i < device->spriteInfo->sprite->spriteTraceGood; i++)
365205b261ecSmrg    {
36534642e01fSmrg	pWin = device->spriteInfo->sprite->spriteTrace[i];
365405b261ecSmrg	if (pWin->optional &&
36556747b715Smrg	    CheckPassiveGrabsOnWindow(pWin, device, event, sendCore))
365605b261ecSmrg	    return TRUE;
365705b261ecSmrg    }
365805b261ecSmrg
365905b261ecSmrg    return FALSE;
366005b261ecSmrg}
366105b261ecSmrg
366205b261ecSmrg/**
366305b261ecSmrg * Called for keyboard events to deliver event to whatever client owns the
36646747b715Smrg * focus.
36656747b715Smrg *
36666747b715Smrg * The event is delivered to the keyboard's focus window, the root window or
36676747b715Smrg * to the window owning the input focus.
366805b261ecSmrg *
366905b261ecSmrg * @param keybd The keyboard originating the event.
36706747b715Smrg * @param event The event, not yet in wire format.
367105b261ecSmrg * @param window Window underneath the sprite.
367205b261ecSmrg */
367305b261ecSmrgvoid
36746747b715SmrgDeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
367505b261ecSmrg{
36766747b715Smrg    DeviceIntPtr ptr;
367705b261ecSmrg    WindowPtr focus = keybd->focus->win;
36786747b715Smrg    BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents);
36794642e01fSmrg    xEvent core;
36806747b715Smrg    xEvent *xE = NULL, *xi2 = NULL;
36816747b715Smrg    int count, rc;
36824642e01fSmrg    int deliveries = 0;
368305b261ecSmrg
368405b261ecSmrg    if (focus == FollowKeyboardWin)
368505b261ecSmrg	focus = inputInfo.keyboard->focus->win;
368605b261ecSmrg    if (!focus)
368705b261ecSmrg	return;
368805b261ecSmrg    if (focus == PointerRootWin)
368905b261ecSmrg    {
36906747b715Smrg	DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd);
369105b261ecSmrg	return;
369205b261ecSmrg    }
369305b261ecSmrg    if ((focus == window) || IsParent(focus, window))
369405b261ecSmrg    {
36956747b715Smrg	if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd))
369605b261ecSmrg	    return;
369705b261ecSmrg    }
36984642e01fSmrg
369905b261ecSmrg    /* just deliver it to the focus window */
37006747b715Smrg    ptr = GetPairedDevice(keybd);
37016747b715Smrg
37026747b715Smrg
37036747b715Smrg    rc = EventToXI2(event, &xi2);
37046747b715Smrg    if (rc == Success)
37056747b715Smrg    {
37066747b715Smrg        /* XXX: XACE */
37076747b715Smrg        int filter = GetEventFilter(keybd, xi2);
37086747b715Smrg        FixUpEventFromWindow(ptr, xi2, focus, None, FALSE);
37096747b715Smrg        deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1,
37106747b715Smrg                                           filter, NullGrab);
37116747b715Smrg        if (deliveries > 0)
37126747b715Smrg            goto unwind;
37136747b715Smrg    } else if (rc != BadMatch)
37146747b715Smrg        ErrorF("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n",
37156747b715Smrg               keybd->name, event->any.type, rc);
37166747b715Smrg
37176747b715Smrg    rc = EventToXI(event, &xE, &count);
37186747b715Smrg    if (rc == Success &&
37196747b715Smrg        XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success)
37206747b715Smrg    {
37216747b715Smrg        FixUpEventFromWindow(ptr, xE, focus, None, FALSE);
37226747b715Smrg        deliveries = DeliverEventsToWindow(keybd, focus, xE, count,
37236747b715Smrg                GetEventFilter(keybd, xE),
37246747b715Smrg                NullGrab);
37256747b715Smrg
37266747b715Smrg        if (deliveries > 0)
37276747b715Smrg            goto unwind;
37286747b715Smrg    } else if (rc != BadMatch)
37296747b715Smrg        ErrorF("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n",
37306747b715Smrg               keybd->name, event->any.type, rc);
37314642e01fSmrg
37326747b715Smrg    if (sendCore)
37334642e01fSmrg    {
37346747b715Smrg        rc = EventToCore(event, &core);
37356747b715Smrg        if (rc == Success) {
37366747b715Smrg            if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, &core, 1) == Success) {
37376747b715Smrg                FixUpEventFromWindow(keybd, &core, focus, None, FALSE);
37386747b715Smrg                deliveries = DeliverEventsToWindow(keybd, focus, &core, 1,
37396747b715Smrg                                                   GetEventFilter(keybd, &core),
37406747b715Smrg                                                   NullGrab);
37416747b715Smrg            }
37426747b715Smrg        } else if (rc != BadMatch)
37436747b715Smrg            ErrorF("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n",
37446747b715Smrg                    keybd->name, event->any.type, rc);
37454642e01fSmrg    }
37466747b715Smrg
37476747b715Smrgunwind:
37486747b715Smrg    free(xE);
37496747b715Smrg    free(xi2);
37506747b715Smrg    return;
375105b261ecSmrg}
375205b261ecSmrg
375305b261ecSmrg/**
375405b261ecSmrg * Deliver an event from a device that is currently grabbed. Uses
375505b261ecSmrg * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the
375605b261ecSmrg * grab. If not, TryClientEvents() is used.
375705b261ecSmrg *
375805b261ecSmrg * @param deactivateGrab True if the device's grab should be deactivated.
375905b261ecSmrg */
376005b261ecSmrgvoid
37616747b715SmrgDeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
37626747b715Smrg                    Bool deactivateGrab)
376305b261ecSmrg{
37644642e01fSmrg    GrabPtr grab;
37654642e01fSmrg    GrabInfoPtr grabinfo;
376605b261ecSmrg    int deliveries = 0;
376705b261ecSmrg    DeviceIntPtr dev;
37684642e01fSmrg    SpritePtr pSprite = thisDev->spriteInfo->sprite;
37694642e01fSmrg    BOOL sendCore = FALSE;
37706747b715Smrg    int rc, count = 0;
37716747b715Smrg    xEvent *xi = NULL;
37726747b715Smrg    xEvent *xi2 = NULL;
37734642e01fSmrg
37744642e01fSmrg    grabinfo = &thisDev->deviceGrab;
37754642e01fSmrg    grab = grabinfo->grab;
377605b261ecSmrg
377705b261ecSmrg    if (grab->ownerEvents)
377805b261ecSmrg    {
377905b261ecSmrg	WindowPtr focus;
378005b261ecSmrg
37814642e01fSmrg        /* Hack: Some pointer device have a focus class. So we need to check
37824642e01fSmrg         * for the type of event, to see if we really want to deliver it to
37834642e01fSmrg         * the focus window. For pointer events, the answer is no.
37844642e01fSmrg         */
37856747b715Smrg        if (IsPointerEvent(event))
37864642e01fSmrg            focus = PointerRootWin;
37876747b715Smrg        else if (thisDev->focus)
378805b261ecSmrg	{
378905b261ecSmrg	    focus = thisDev->focus->win;
379005b261ecSmrg	    if (focus == FollowKeyboardWin)
379105b261ecSmrg		focus = inputInfo.keyboard->focus->win;
379205b261ecSmrg	}
379305b261ecSmrg	else
379405b261ecSmrg	    focus = PointerRootWin;
379505b261ecSmrg	if (focus == PointerRootWin)
37966747b715Smrg	    deliveries = DeliverDeviceEvents(pSprite->win, event, grab,
37976747b715Smrg                                             NullWindow, thisDev);
37984642e01fSmrg	else if (focus && (focus == pSprite->win ||
37994642e01fSmrg                    IsParent(focus, pSprite->win)))
38006747b715Smrg	    deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus,
38016747b715Smrg					     thisDev);
380205b261ecSmrg	else if (focus)
38036747b715Smrg	    deliveries = DeliverDeviceEvents(focus, event, grab, focus,
38046747b715Smrg					     thisDev);
380505b261ecSmrg    }
380605b261ecSmrg    if (!deliveries)
380705b261ecSmrg    {
38086747b715Smrg        Mask mask;
38096747b715Smrg
38106747b715Smrg        /* XXX: In theory, we could pass the internal events through to
38116747b715Smrg         * everything and only convert just before hitting the wire. We can't
38126747b715Smrg         * do that yet, so DGE is the last stop for internal events. From here
38136747b715Smrg         * onwards, we deal with core/XI events.
38146747b715Smrg         */
38156747b715Smrg
38166747b715Smrg        mask = grab->eventMask;
38176747b715Smrg
38186747b715Smrg        sendCore = (IsMaster(thisDev) && thisDev->coreEvents);
38196747b715Smrg        /* try core event */
38206747b715Smrg        if (sendCore && grab->grabtype == GRABTYPE_CORE)
38214642e01fSmrg        {
38226747b715Smrg            xEvent core;
38234642e01fSmrg
38246747b715Smrg            rc = EventToCore(event, &core);
38256747b715Smrg            if (rc == Success)
38264642e01fSmrg            {
38276747b715Smrg                FixUpEventFromWindow(thisDev, &core, grab->window,
38286747b715Smrg                        None, TRUE);
38296747b715Smrg                if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
38306747b715Smrg                            grab->window, &core, 1) ||
38316747b715Smrg                        XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
38326747b715Smrg                            grab->window, &core, 1))
38336747b715Smrg                    deliveries = 1; /* don't send, but pretend we did */
38346747b715Smrg                else if (!IsInterferingGrab(rClient(grab), thisDev, &core))
38356747b715Smrg                {
38366747b715Smrg                    deliveries = TryClientEvents(rClient(grab), thisDev,
38376747b715Smrg                            &core, 1, mask,
38386747b715Smrg                            GetEventFilter(thisDev, &core),
38396747b715Smrg                            grab);
38404642e01fSmrg                }
38416747b715Smrg            } else if (rc != BadMatch)
38426747b715Smrg                ErrorF("[dix] DeliverGrabbedEvent. Core conversion failed.\n");
38436747b715Smrg        }
38446747b715Smrg
38456747b715Smrg        if (!deliveries)
38466747b715Smrg        {
38476747b715Smrg            rc = EventToXI2(event, &xi2);
38486747b715Smrg            if (rc == Success)
38496747b715Smrg            {
38506747b715Smrg                int evtype = ((xGenericEvent*)xi2)->evtype;
38516747b715Smrg                mask = grab->xi2mask[XIAllDevices][evtype/8] |
38526747b715Smrg                    grab->xi2mask[XIAllMasterDevices][evtype/8] |
38536747b715Smrg                    grab->xi2mask[thisDev->id][evtype/8];
38546747b715Smrg                /* try XI2 event */
38556747b715Smrg                FixUpEventFromWindow(thisDev, xi2, grab->window, None, TRUE);
38566747b715Smrg                /* XXX: XACE */
38576747b715Smrg                deliveries = TryClientEvents(rClient(grab), thisDev, xi2, 1, mask,
38586747b715Smrg                        GetEventFilter(thisDev, xi2), grab);
38596747b715Smrg            } else if (rc != BadMatch)
38606747b715Smrg                ErrorF("[dix] %s: XI2 conversion failed in DGE (%d, %d). Skipping delivery.\n",
38616747b715Smrg                        thisDev->name, event->any.type, rc);
38626747b715Smrg        }
38636747b715Smrg
38646747b715Smrg        if (!deliveries)
38656747b715Smrg        {
38666747b715Smrg            rc = EventToXI(event, &xi, &count);
38676747b715Smrg            if (rc == Success)
38684642e01fSmrg            {
38694642e01fSmrg                /* try XI event */
38704642e01fSmrg                if (grabinfo->fromPassiveGrab  &&
38716747b715Smrg                        grabinfo->implicitGrab)
38724642e01fSmrg                    mask = grab->deviceMask;
38736747b715Smrg                else
38746747b715Smrg                    mask = grab->eventMask;
38756747b715Smrg
38766747b715Smrg                FixUpEventFromWindow(thisDev, xi, grab->window,
38774642e01fSmrg                        None, TRUE);
38784642e01fSmrg
38794642e01fSmrg                if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
38806747b715Smrg                            grab->window, xi, count) ||
38814642e01fSmrg                        XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
38826747b715Smrg                            grab->window, xi, count))
38834642e01fSmrg                    deliveries = 1; /* don't send, but pretend we did */
38844642e01fSmrg                else
38854642e01fSmrg                {
38864642e01fSmrg                    deliveries =
38874642e01fSmrg                        TryClientEvents(rClient(grab), thisDev,
38886747b715Smrg                                xi, count,
38894642e01fSmrg                                mask,
38906747b715Smrg                                GetEventFilter(thisDev, xi),
38914642e01fSmrg                                grab);
38924642e01fSmrg                }
38936747b715Smrg            } else if (rc != BadMatch)
38946747b715Smrg                ErrorF("[dix] %s: XI conversion failed in DGE (%d, %d). Skipping delivery.\n",
38956747b715Smrg                        thisDev->name, event->any.type, rc);
38964642e01fSmrg        }
38976747b715Smrg
38986747b715Smrg        if (deliveries && (event->any.type == ET_Motion))
38994642e01fSmrg            thisDev->valuator->motionHintWindow = grab->window;
390005b261ecSmrg    }
39016747b715Smrg    if (deliveries && !deactivateGrab && event->any.type != ET_Motion)
39024642e01fSmrg    {
39034642e01fSmrg	switch (grabinfo->sync.state)
390405b261ecSmrg	{
390505b261ecSmrg	case FREEZE_BOTH_NEXT_EVENT:
390605b261ecSmrg	    for (dev = inputInfo.devices; dev; dev = dev->next)
390705b261ecSmrg	    {
390805b261ecSmrg		if (dev == thisDev)
390905b261ecSmrg		    continue;
391005b261ecSmrg		FreezeThaw(dev, TRUE);
39116747b715Smrg		if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) &&
39124642e01fSmrg		    (CLIENT_BITS(grab->resource) ==
39136747b715Smrg		     CLIENT_BITS(dev->deviceGrab.grab->resource)))
39146747b715Smrg		    dev->deviceGrab.sync.state = FROZEN_NO_EVENT;
391505b261ecSmrg		else
39166747b715Smrg                    dev->deviceGrab.sync.other = grab;
391705b261ecSmrg	    }
391805b261ecSmrg	    /* fall through */
391905b261ecSmrg	case FREEZE_NEXT_EVENT:
39206747b715Smrg	    grabinfo->sync.state = FROZEN_WITH_EVENT;
39216747b715Smrg	    FreezeThaw(thisDev, TRUE);
39226747b715Smrg	    if (!grabinfo->sync.event)
39236747b715Smrg		grabinfo->sync.event = calloc(1, sizeof(InternalEvent));
39246747b715Smrg	    *grabinfo->sync.event = event->device_event;
39256747b715Smrg	    break;
392605b261ecSmrg	}
392705b261ecSmrg    }
392805b261ecSmrg
39296747b715Smrg    free(xi);
39306747b715Smrg    free(xi2);
39316747b715Smrg}
393205b261ecSmrg
39336747b715Smrg/* This function is used to set the key pressed or key released state -
39346747b715Smrg   this is only used when the pressing of keys does not cause
39356747b715Smrg   the device's processInputProc to be called, as in for example Mouse Keys.
39366747b715Smrg*/
39376747b715Smrgvoid
39386747b715SmrgFixKeyState (DeviceEvent *event, DeviceIntPtr keybd)
39396747b715Smrg{
39406747b715Smrg    int key = event->detail.key;
39416747b715Smrg
39426747b715Smrg    if (event->type == ET_KeyPress) {
39436747b715Smrg	DebugF("FixKeyState: Key %d %s\n",key,
39446747b715Smrg               ((event->type == ET_KeyPress) ? "down" : "up"));
394505b261ecSmrg    }
39464642e01fSmrg
39476747b715Smrg    if (event->type == ET_KeyPress)
39486747b715Smrg        set_key_down(keybd, key, KEY_PROCESSED);
39496747b715Smrg    else if (event->type == ET_KeyRelease)
39506747b715Smrg        set_key_up(keybd, key, KEY_PROCESSED);
395105b261ecSmrg    else
39526747b715Smrg        FatalError("Impossible keyboard event");
395305b261ecSmrg}
395405b261ecSmrg
395505b261ecSmrg#define AtMostOneClient \
395605b261ecSmrg	(SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
39574642e01fSmrg#define ManagerMask \
39584642e01fSmrg	(SubstructureRedirectMask | ResizeRedirectMask)
395905b261ecSmrg
396005b261ecSmrg/**
396105b261ecSmrg * Recalculate which events may be deliverable for the given window.
396205b261ecSmrg * Recalculated mask is used for quicker determination which events may be
396305b261ecSmrg * delivered to a window.
396405b261ecSmrg *
396505b261ecSmrg * The otherEventMasks on a WindowOptional is the combination of all event
396605b261ecSmrg * masks set by all clients on the window.
396705b261ecSmrg * deliverableEventMask is the combination of the eventMask and the
39686747b715Smrg * otherEventMask plus the events that may be propagated to the parent.
396905b261ecSmrg *
397005b261ecSmrg * Traverses to siblings and parents of the window.
397105b261ecSmrg */
397205b261ecSmrgvoid
39736747b715SmrgRecalculateDeliverableEvents(WindowPtr pWin)
397405b261ecSmrg{
397505b261ecSmrg    OtherClients *others;
397605b261ecSmrg    WindowPtr pChild;
397705b261ecSmrg
397805b261ecSmrg    pChild = pWin;
397905b261ecSmrg    while (1)
398005b261ecSmrg    {
398105b261ecSmrg	if (pChild->optional)
398205b261ecSmrg	{
398305b261ecSmrg	    pChild->optional->otherEventMasks = 0;
398405b261ecSmrg	    for (others = wOtherClients(pChild); others; others = others->next)
398505b261ecSmrg	    {
398605b261ecSmrg		pChild->optional->otherEventMasks |= others->mask;
398705b261ecSmrg	    }
398805b261ecSmrg	}
398905b261ecSmrg	pChild->deliverableEvents = pChild->eventMask|
399005b261ecSmrg				    wOtherEventMasks(pChild);
399105b261ecSmrg	if (pChild->parent)
399205b261ecSmrg	    pChild->deliverableEvents |=
399305b261ecSmrg		(pChild->parent->deliverableEvents &
399405b261ecSmrg		 ~wDontPropagateMask(pChild) & PropagateMask);
399505b261ecSmrg	if (pChild->firstChild)
399605b261ecSmrg	{
399705b261ecSmrg	    pChild = pChild->firstChild;
399805b261ecSmrg	    continue;
399905b261ecSmrg	}
400005b261ecSmrg	while (!pChild->nextSib && (pChild != pWin))
400105b261ecSmrg	    pChild = pChild->parent;
400205b261ecSmrg	if (pChild == pWin)
400305b261ecSmrg	    break;
400405b261ecSmrg	pChild = pChild->nextSib;
400505b261ecSmrg    }
400605b261ecSmrg}
400705b261ecSmrg
400805b261ecSmrg/**
400905b261ecSmrg *
401005b261ecSmrg *  \param value must conform to DeleteType
401105b261ecSmrg */
401205b261ecSmrgint
401305b261ecSmrgOtherClientGone(pointer value, XID id)
401405b261ecSmrg{
401505b261ecSmrg    OtherClientsPtr other, prev;
401605b261ecSmrg    WindowPtr pWin = (WindowPtr)value;
401705b261ecSmrg
401805b261ecSmrg    prev = 0;
401905b261ecSmrg    for (other = wOtherClients(pWin); other; other = other->next)
402005b261ecSmrg    {
402105b261ecSmrg	if (other->resource == id)
402205b261ecSmrg	{
402305b261ecSmrg	    if (prev)
402405b261ecSmrg		prev->next = other->next;
402505b261ecSmrg	    else
402605b261ecSmrg	    {
402705b261ecSmrg		if (!(pWin->optional->otherClients = other->next))
402805b261ecSmrg		    CheckWindowOptionalNeed (pWin);
402905b261ecSmrg	    }
40306747b715Smrg	    free(other);
403105b261ecSmrg	    RecalculateDeliverableEvents(pWin);
40326747b715Smrg	    return Success;
403305b261ecSmrg	}
403405b261ecSmrg	prev = other;
403505b261ecSmrg    }
403605b261ecSmrg    FatalError("client not on event list");
403705b261ecSmrg    /*NOTREACHED*/
403805b261ecSmrg    return -1; /* make compiler happy */
403905b261ecSmrg}
404005b261ecSmrg
404105b261ecSmrgint
404205b261ecSmrgEventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
404305b261ecSmrg{
404405b261ecSmrg    Mask check;
404505b261ecSmrg    OtherClients * others;
40464642e01fSmrg    DeviceIntPtr dev;
40474642e01fSmrg    int rc;
404805b261ecSmrg
404905b261ecSmrg    if (mask & ~AllEventMasks)
405005b261ecSmrg    {
405105b261ecSmrg	client->errorValue = mask;
405205b261ecSmrg	return BadValue;
405305b261ecSmrg    }
40544642e01fSmrg    check = (mask & ManagerMask);
40554642e01fSmrg    if (check) {
40564642e01fSmrg	rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id,
40574642e01fSmrg		      RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess);
40584642e01fSmrg	if (rc != Success)
40594642e01fSmrg	    return rc;
40604642e01fSmrg    }
406105b261ecSmrg    check = (mask & AtMostOneClient);
406205b261ecSmrg    if (check & (pWin->eventMask|wOtherEventMasks(pWin)))
406305b261ecSmrg    {				       /* It is illegal for two different
406405b261ecSmrg				          clients to select on any of the
406505b261ecSmrg				          events for AtMostOneClient. However,
406605b261ecSmrg				          it is OK, for some client to
406705b261ecSmrg				          continue selecting on one of those
406805b261ecSmrg				          events.  */
406905b261ecSmrg	if ((wClient(pWin) != client) && (check & pWin->eventMask))
407005b261ecSmrg	    return BadAccess;
407105b261ecSmrg	for (others = wOtherClients (pWin); others; others = others->next)
407205b261ecSmrg	{
407305b261ecSmrg	    if (!SameClient(others, client) && (check & others->mask))
407405b261ecSmrg		return BadAccess;
407505b261ecSmrg	}
407605b261ecSmrg    }
407705b261ecSmrg    if (wClient (pWin) == client)
407805b261ecSmrg    {
407905b261ecSmrg	check = pWin->eventMask;
408005b261ecSmrg	pWin->eventMask = mask;
408105b261ecSmrg    }
408205b261ecSmrg    else
408305b261ecSmrg    {
408405b261ecSmrg	for (others = wOtherClients (pWin); others; others = others->next)
408505b261ecSmrg	{
408605b261ecSmrg	    if (SameClient(others, client))
408705b261ecSmrg	    {
408805b261ecSmrg		check = others->mask;
408905b261ecSmrg		if (mask == 0)
409005b261ecSmrg		{
409105b261ecSmrg		    FreeResource(others->resource, RT_NONE);
409205b261ecSmrg		    return Success;
409305b261ecSmrg		}
409405b261ecSmrg		else
409505b261ecSmrg		    others->mask = mask;
409605b261ecSmrg		goto maskSet;
409705b261ecSmrg	    }
409805b261ecSmrg	}
409905b261ecSmrg	check = 0;
410005b261ecSmrg	if (!pWin->optional && !MakeWindowOptional (pWin))
410105b261ecSmrg	    return BadAlloc;
41026747b715Smrg	others = malloc(sizeof(OtherClients));
410305b261ecSmrg	if (!others)
410405b261ecSmrg	    return BadAlloc;
410505b261ecSmrg	others->mask = mask;
410605b261ecSmrg	others->resource = FakeClientID(client->index);
410705b261ecSmrg	others->next = pWin->optional->otherClients;
410805b261ecSmrg	pWin->optional->otherClients = others;
410905b261ecSmrg	if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin))
411005b261ecSmrg	    return BadAlloc;
411105b261ecSmrg    }
41124642e01fSmrgmaskSet:
41134642e01fSmrg    if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask))
41144642e01fSmrg    {
41154642e01fSmrg        for (dev = inputInfo.devices; dev; dev = dev->next)
41164642e01fSmrg        {
41174642e01fSmrg            if (dev->valuator && dev->valuator->motionHintWindow == pWin)
41184642e01fSmrg                dev->valuator->motionHintWindow = NullWindow;
41194642e01fSmrg        }
41204642e01fSmrg    }
412105b261ecSmrg    RecalculateDeliverableEvents(pWin);
412205b261ecSmrg    return Success;
412305b261ecSmrg}
412405b261ecSmrg
412505b261ecSmrgint
41264642e01fSmrgEventSuppressForWindow(WindowPtr pWin, ClientPtr client,
412705b261ecSmrg                       Mask mask, Bool *checkOptional)
412805b261ecSmrg{
412905b261ecSmrg    int i, free;
413005b261ecSmrg
413105b261ecSmrg    if (mask & ~PropagateMask)
413205b261ecSmrg    {
413305b261ecSmrg	client->errorValue = mask;
413405b261ecSmrg	return BadValue;
413505b261ecSmrg    }
413605b261ecSmrg    if (pWin->dontPropagate)
413705b261ecSmrg	DontPropagateRefCnts[pWin->dontPropagate]--;
413805b261ecSmrg    if (!mask)
413905b261ecSmrg	i = 0;
414005b261ecSmrg    else
414105b261ecSmrg    {
414205b261ecSmrg	for (i = DNPMCOUNT, free = 0; --i > 0; )
414305b261ecSmrg	{
414405b261ecSmrg	    if (!DontPropagateRefCnts[i])
414505b261ecSmrg		free = i;
414605b261ecSmrg	    else if (mask == DontPropagateMasks[i])
414705b261ecSmrg		break;
414805b261ecSmrg	}
414905b261ecSmrg	if (!i && free)
415005b261ecSmrg	{
415105b261ecSmrg	    i = free;
415205b261ecSmrg	    DontPropagateMasks[i] = mask;
415305b261ecSmrg	}
415405b261ecSmrg    }
415505b261ecSmrg    if (i || !mask)
415605b261ecSmrg    {
415705b261ecSmrg	pWin->dontPropagate = i;
415805b261ecSmrg	if (i)
415905b261ecSmrg	    DontPropagateRefCnts[i]++;
416005b261ecSmrg	if (pWin->optional)
416105b261ecSmrg	{
416205b261ecSmrg	    pWin->optional->dontPropagateMask = mask;
416305b261ecSmrg	    *checkOptional = TRUE;
416405b261ecSmrg	}
416505b261ecSmrg    }
416605b261ecSmrg    else
416705b261ecSmrg    {
416805b261ecSmrg	if (!pWin->optional && !MakeWindowOptional (pWin))
416905b261ecSmrg	{
417005b261ecSmrg	    if (pWin->dontPropagate)
417105b261ecSmrg		DontPropagateRefCnts[pWin->dontPropagate]++;
417205b261ecSmrg	    return BadAlloc;
417305b261ecSmrg	}
417405b261ecSmrg	pWin->dontPropagate = 0;
417505b261ecSmrg        pWin->optional->dontPropagateMask = mask;
417605b261ecSmrg    }
417705b261ecSmrg    RecalculateDeliverableEvents(pWin);
417805b261ecSmrg    return Success;
417905b261ecSmrg}
418005b261ecSmrg
418105b261ecSmrg/**
41824642e01fSmrg * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
41834642e01fSmrg * Uses the paired keyboard to get some additional information.
418405b261ecSmrg */
41854642e01fSmrgvoid
41864642e01fSmrgCoreEnterLeaveEvent(
41874642e01fSmrg    DeviceIntPtr mouse,
418805b261ecSmrg    int type,
418905b261ecSmrg    int mode,
419005b261ecSmrg    int detail,
419105b261ecSmrg    WindowPtr pWin,
419205b261ecSmrg    Window child)
419305b261ecSmrg{
41944642e01fSmrg    xEvent              event;
419505b261ecSmrg    WindowPtr		focus;
41964642e01fSmrg    DeviceIntPtr        keybd;
41974642e01fSmrg    GrabPtr	        grab = mouse->deviceGrab.grab;
419805b261ecSmrg    Mask		mask;
419905b261ecSmrg
42004642e01fSmrg    keybd = GetPairedDevice(mouse);
42014642e01fSmrg
420205b261ecSmrg    if ((pWin == mouse->valuator->motionHintWindow) &&
420305b261ecSmrg	(detail != NotifyInferior))
420405b261ecSmrg	mouse->valuator->motionHintWindow = NullWindow;
420505b261ecSmrg    if (grab)
420605b261ecSmrg    {
420705b261ecSmrg	mask = (pWin == grab->window) ? grab->eventMask : 0;
420805b261ecSmrg	if (grab->ownerEvents)
420905b261ecSmrg	    mask |= EventMaskForClient(pWin, rClient(grab));
421005b261ecSmrg    }
421105b261ecSmrg    else
421205b261ecSmrg    {
421305b261ecSmrg	mask = pWin->eventMask | wOtherEventMasks(pWin);
421405b261ecSmrg    }
42154642e01fSmrg
42166747b715Smrg    memset(&event, 0, sizeof(xEvent));
42174642e01fSmrg    event.u.u.type = type;
42184642e01fSmrg    event.u.u.detail = detail;
42194642e01fSmrg    event.u.enterLeave.time = currentTime.milliseconds;
42204642e01fSmrg    event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x;
42214642e01fSmrg    event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y;
42224642e01fSmrg    /* Counts on the same initial structure of crossing & button events! */
42234642e01fSmrg    FixUpEventFromWindow(mouse, &event, pWin, None, FALSE);
42244642e01fSmrg    /* Enter/Leave events always set child */
42254642e01fSmrg    event.u.enterLeave.child = child;
42264642e01fSmrg    event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
42274642e01fSmrg        ELFlagSameScreen : 0;
42286747b715Smrg    event.u.enterLeave.state = mouse->button ? (mouse->button->state & 0x1f00) : 0;
42296747b715Smrg    if (keybd)
42306747b715Smrg        event.u.enterLeave.state |=
42314642e01fSmrg                XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
42324642e01fSmrg    event.u.enterLeave.mode = mode;
42334642e01fSmrg    focus = (keybd) ? keybd->focus->win : None;
42344642e01fSmrg    if ((focus != NoneWin) &&
42354642e01fSmrg            ((pWin == focus) || (focus == PointerRootWin) ||
42364642e01fSmrg             IsParent(focus, pWin)))
42374642e01fSmrg        event.u.enterLeave.flags |= ELFlagFocus;
423805b261ecSmrg
42396747b715Smrg    if ((mask & GetEventFilter(mouse, &event)))
424005b261ecSmrg    {
42414642e01fSmrg        if (grab)
42424642e01fSmrg            TryClientEvents(rClient(grab), mouse, &event, 1, mask,
42436747b715Smrg                            GetEventFilter(mouse, &event), grab);
42444642e01fSmrg        else
42454642e01fSmrg            DeliverEventsToWindow(mouse, pWin, &event, 1,
42466747b715Smrg                                  GetEventFilter(mouse, &event),
42476747b715Smrg                                  NullGrab);
424805b261ecSmrg    }
424905b261ecSmrg
42504642e01fSmrg    if ((type == EnterNotify) && (mask & KeymapStateMask))
425105b261ecSmrg    {
42524642e01fSmrg        xKeymapEvent ke;
42536747b715Smrg        ClientPtr client = grab ? rClient(grab) : wClient(pWin);
42544642e01fSmrg        if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess))
42556747b715Smrg            memset((char *)&ke.map[0], 0, 31);
42564642e01fSmrg        else
42574642e01fSmrg            memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31);
42584642e01fSmrg
42594642e01fSmrg        ke.type = KeymapNotify;
42604642e01fSmrg        if (grab)
42614642e01fSmrg            TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1,
42624642e01fSmrg                            mask, KeymapStateMask, grab);
42634642e01fSmrg        else
42644642e01fSmrg            DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1,
42656747b715Smrg                                  KeymapStateMask, NullGrab);
42666747b715Smrg    }
42676747b715Smrg}
42686747b715Smrg
42696747b715Smrgvoid
42706747b715SmrgDeviceEnterLeaveEvent(
42716747b715Smrg    DeviceIntPtr mouse,
42726747b715Smrg    int sourceid,
42736747b715Smrg    int type,
42746747b715Smrg    int mode,
42756747b715Smrg    int detail,
42766747b715Smrg    WindowPtr pWin,
42776747b715Smrg    Window child)
42786747b715Smrg{
42796747b715Smrg    GrabPtr             grab = mouse->deviceGrab.grab;
42806747b715Smrg    xXIEnterEvent       *event;
42816747b715Smrg    int                 filter;
42826747b715Smrg    int                 btlen, len, i;
42836747b715Smrg    DeviceIntPtr        kbd;
42846747b715Smrg
42856747b715Smrg    if ((mode == XINotifyPassiveGrab && type == XI_Leave) ||
42866747b715Smrg        (mode == XINotifyPassiveUngrab && type == XI_Enter))
42876747b715Smrg        return;
42886747b715Smrg
42896747b715Smrg    btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
42906747b715Smrg    btlen = bytes_to_int32(btlen);
42916747b715Smrg    len = sizeof(xXIEnterEvent) + btlen * 4;
42926747b715Smrg
42936747b715Smrg    event = calloc(1, len);
42946747b715Smrg    event->type         = GenericEvent;
42956747b715Smrg    event->extension    = IReqCode;
42966747b715Smrg    event->evtype       = type;
42976747b715Smrg    event->length       = (len - sizeof(xEvent))/4;
42986747b715Smrg    event->buttons_len  = btlen;
42996747b715Smrg    event->detail       = detail;
43006747b715Smrg    event->time         = currentTime.milliseconds;
43016747b715Smrg    event->deviceid     = mouse->id;
43026747b715Smrg    event->sourceid     = sourceid;
43036747b715Smrg    event->mode         = mode;
43046747b715Smrg    event->root_x       = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
43056747b715Smrg    event->root_y       = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
43066747b715Smrg
43076747b715Smrg    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
43086747b715Smrg        if (BitIsOn(mouse->button->down, i))
43096747b715Smrg            SetBit(&event[1], i);
43106747b715Smrg
43116747b715Smrg    kbd = (IsMaster(mouse) || mouse->u.master) ? GetPairedDevice(mouse) : NULL;
43126747b715Smrg    if (kbd && kbd->key)
43136747b715Smrg    {
43146747b715Smrg        event->mods.base_mods = kbd->key->xkbInfo->state.base_mods;
43156747b715Smrg        event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods;
43166747b715Smrg        event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods;
43176747b715Smrg
43186747b715Smrg        event->group.base_group = kbd->key->xkbInfo->state.base_group;
43196747b715Smrg        event->group.latched_group = kbd->key->xkbInfo->state.latched_group;
43206747b715Smrg        event->group.locked_group = kbd->key->xkbInfo->state.locked_group;
432105b261ecSmrg    }
43226747b715Smrg
43236747b715Smrg    FixUpEventFromWindow(mouse, (xEvent*)event, pWin, None, FALSE);
43246747b715Smrg
43256747b715Smrg    filter = GetEventFilter(mouse, (xEvent*)event);
43266747b715Smrg
43276747b715Smrg    if (grab)
43286747b715Smrg    {
43296747b715Smrg        Mask mask;
43306747b715Smrg        mask = grab->xi2mask[XIAllDevices][type/8] |
43316747b715Smrg               grab->xi2mask[XIAllMasterDevices][type/8] |
43326747b715Smrg               grab->xi2mask[mouse->id][type/8];
43336747b715Smrg        TryClientEvents(rClient(grab), mouse, (xEvent*)event, 1, mask,
43346747b715Smrg                        filter, grab);
43356747b715Smrg    } else {
43366747b715Smrg        if (!GetWindowXI2Mask(mouse, pWin, (xEvent*)event))
43376747b715Smrg            goto out;
43386747b715Smrg        DeliverEventsToWindow(mouse, pWin, (xEvent*)event, 1, filter,
43396747b715Smrg                              NullGrab);
43406747b715Smrg    }
43416747b715Smrg
43426747b715Smrgout:
43436747b715Smrg    free(event);
434405b261ecSmrg}
434505b261ecSmrg
43464642e01fSmrgvoid
43474642e01fSmrgCoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
434805b261ecSmrg{
434905b261ecSmrg    xEvent event;
435005b261ecSmrg
43516747b715Smrg    memset(&event, 0, sizeof(xEvent));
435205b261ecSmrg    event.u.focus.mode = mode;
435305b261ecSmrg    event.u.u.type = type;
435405b261ecSmrg    event.u.u.detail = detail;
435505b261ecSmrg    event.u.focus.window = pWin->drawable.id;
43566747b715Smrg
43576747b715Smrg    DeliverEventsToWindow(dev, pWin, &event, 1,
43586747b715Smrg                          GetEventFilter(dev, &event), NullGrab);
435905b261ecSmrg    if ((type == FocusIn) &&
43604642e01fSmrg            ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
436105b261ecSmrg    {
43624642e01fSmrg        xKeymapEvent ke;
43636747b715Smrg        ClientPtr client = wClient(pWin);
436452397711Smrg        if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess))
43656747b715Smrg            memset((char *)&ke.map[0], 0, 31);
436652397711Smrg        else
436752397711Smrg            memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
436805b261ecSmrg
43694642e01fSmrg        ke.type = KeymapNotify;
43706747b715Smrg        DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1,
43716747b715Smrg                KeymapStateMask, NullGrab);
437205b261ecSmrg    }
437305b261ecSmrg}
437405b261ecSmrg
437505b261ecSmrg/**
437605b261ecSmrg * Set the input focus to the given window. Subsequent keyboard events will be
437705b261ecSmrg * delivered to the given window.
43784642e01fSmrg *
437905b261ecSmrg * Usually called from ProcSetInputFocus as result of a client request. If so,
438005b261ecSmrg * the device is the inputInfo.keyboard.
438105b261ecSmrg * If called from ProcXSetInputFocus as result of a client xinput request, the
438205b261ecSmrg * device is set to the device specified by the client.
438305b261ecSmrg *
438405b261ecSmrg * @param client Client that requested input focus change.
43854642e01fSmrg * @param dev Focus device.
438605b261ecSmrg * @param focusID The window to obtain the focus. Can be PointerRoot or None.
438705b261ecSmrg * @param revertTo Specifies where the focus reverts to when window becomes
438805b261ecSmrg * unviewable.
438905b261ecSmrg * @param ctime Specifies the time.
439005b261ecSmrg * @param followOK True if pointer is allowed to follow the keyboard.
439105b261ecSmrg */
439205b261ecSmrgint
439305b261ecSmrgSetInputFocus(
439405b261ecSmrg    ClientPtr client,
439505b261ecSmrg    DeviceIntPtr dev,
439605b261ecSmrg    Window focusID,
439705b261ecSmrg    CARD8 revertTo,
439805b261ecSmrg    Time ctime,
439905b261ecSmrg    Bool followOK)
440005b261ecSmrg{
440105b261ecSmrg    FocusClassPtr focus;
440205b261ecSmrg    WindowPtr focusWin;
440305b261ecSmrg    int mode, rc;
440405b261ecSmrg    TimeStamp time;
44054642e01fSmrg    DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */
44064642e01fSmrg
440705b261ecSmrg
440805b261ecSmrg    UpdateCurrentTime();
440905b261ecSmrg    if ((revertTo != RevertToParent) &&
441005b261ecSmrg	(revertTo != RevertToPointerRoot) &&
441105b261ecSmrg	(revertTo != RevertToNone) &&
441205b261ecSmrg	((revertTo != RevertToFollowKeyboard) || !followOK))
441305b261ecSmrg    {
441405b261ecSmrg	client->errorValue = revertTo;
441505b261ecSmrg	return BadValue;
441605b261ecSmrg    }
441705b261ecSmrg    time = ClientTimeToServerTime(ctime);
44184642e01fSmrg
44194642e01fSmrg    if (IsKeyboardDevice(dev))
44204642e01fSmrg        keybd = dev;
44214642e01fSmrg    else
44224642e01fSmrg        keybd = GetPairedDevice(dev);
44234642e01fSmrg
442405b261ecSmrg    if ((focusID == None) || (focusID == PointerRoot))
442505b261ecSmrg	focusWin = (WindowPtr)(long)focusID;
442605b261ecSmrg    else if ((focusID == FollowKeyboard) && followOK)
44274642e01fSmrg    {
44284642e01fSmrg	focusWin = keybd->focus->win;
44294642e01fSmrg    }
443005b261ecSmrg    else {
44314642e01fSmrg	rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess);
443205b261ecSmrg	if (rc != Success)
443305b261ecSmrg	    return rc;
44344642e01fSmrg	/* It is a match error to try to set the input focus to an
443505b261ecSmrg	unviewable window. */
443605b261ecSmrg	if(!focusWin->realized)
44376747b715Smrg	    return BadMatch;
443805b261ecSmrg    }
44394642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess);
44404642e01fSmrg    if (rc != Success)
44414642e01fSmrg	return Success;
44424642e01fSmrg
444305b261ecSmrg    focus = dev->focus;
444405b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
444505b261ecSmrg	(CompareTimeStamps(time, focus->time) == EARLIER))
444605b261ecSmrg	return Success;
44474642e01fSmrg    mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal;
444805b261ecSmrg    if (focus->win == FollowKeyboardWin)
44496747b715Smrg    {
44506747b715Smrg        if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin))
44516747b715Smrg            DoFocusEvents(dev, keybd->focus->win, focusWin, mode);
44526747b715Smrg    } else
44536747b715Smrg    {
44546747b715Smrg        if (!ActivateFocusInGrab(dev, focus->win, focusWin))
44556747b715Smrg            DoFocusEvents(dev, focus->win, focusWin, mode);
44566747b715Smrg    }
445705b261ecSmrg    focus->time = time;
445805b261ecSmrg    focus->revert = revertTo;
445905b261ecSmrg    if (focusID == FollowKeyboard)
446005b261ecSmrg	focus->win = FollowKeyboardWin;
446105b261ecSmrg    else
446205b261ecSmrg	focus->win = focusWin;
446305b261ecSmrg    if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
446405b261ecSmrg	focus->traceGood = 0;
446505b261ecSmrg    else
446605b261ecSmrg    {
446705b261ecSmrg        int depth = 0;
446805b261ecSmrg	WindowPtr pWin;
446905b261ecSmrg
447005b261ecSmrg        for (pWin = focusWin; pWin; pWin = pWin->parent) depth++;
447105b261ecSmrg        if (depth > focus->traceSize)
447205b261ecSmrg        {
447305b261ecSmrg	    focus->traceSize = depth+1;
44746747b715Smrg	    focus->trace = realloc(focus->trace,
44754642e01fSmrg				    focus->traceSize * sizeof(WindowPtr));
447605b261ecSmrg	}
447705b261ecSmrg	focus->traceGood = depth;
44784642e01fSmrg        for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
447905b261ecSmrg	    focus->trace[depth] = pWin;
448005b261ecSmrg    }
448105b261ecSmrg    return Success;
448205b261ecSmrg}
448305b261ecSmrg
448405b261ecSmrg/**
448505b261ecSmrg * Server-side protocol handling for SetInputFocus request.
448605b261ecSmrg *
448705b261ecSmrg * Sets the input focus for the virtual core keyboard.
448805b261ecSmrg */
448905b261ecSmrgint
44906747b715SmrgProcSetInputFocus(ClientPtr client)
449105b261ecSmrg{
44924642e01fSmrg    DeviceIntPtr kbd = PickKeyboard(client);
449305b261ecSmrg    REQUEST(xSetInputFocusReq);
449405b261ecSmrg
449505b261ecSmrg    REQUEST_SIZE_MATCH(xSetInputFocusReq);
449605b261ecSmrg
44974642e01fSmrg    return SetInputFocus(client, kbd, stuff->focus,
449805b261ecSmrg			 stuff->revertTo, stuff->time, FALSE);
449905b261ecSmrg}
450005b261ecSmrg
450105b261ecSmrg/**
450205b261ecSmrg * Server-side protocol handling for GetInputFocus request.
45034642e01fSmrg *
45044642e01fSmrg * Sends the current input focus for the client's keyboard back to the
450505b261ecSmrg * client.
450605b261ecSmrg */
450705b261ecSmrgint
450805b261ecSmrgProcGetInputFocus(ClientPtr client)
450905b261ecSmrg{
45104642e01fSmrg    DeviceIntPtr kbd = PickKeyboard(client);
451105b261ecSmrg    xGetInputFocusReply rep;
45124642e01fSmrg    FocusClassPtr focus = kbd->focus;
45134642e01fSmrg    int rc;
451405b261ecSmrg    /* REQUEST(xReq); */
451505b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
45164642e01fSmrg
45174642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess);
45184642e01fSmrg    if (rc != Success)
45194642e01fSmrg	return rc;
45204642e01fSmrg
45216747b715Smrg    memset(&rep, 0, sizeof(xGetInputFocusReply));
452205b261ecSmrg    rep.type = X_Reply;
452305b261ecSmrg    rep.length = 0;
452405b261ecSmrg    rep.sequenceNumber = client->sequence;
452505b261ecSmrg    if (focus->win == NoneWin)
452605b261ecSmrg	rep.focus = None;
452705b261ecSmrg    else if (focus->win == PointerRootWin)
452805b261ecSmrg	rep.focus = PointerRoot;
452905b261ecSmrg    else rep.focus = focus->win->drawable.id;
453005b261ecSmrg    rep.revertTo = focus->revert;
453105b261ecSmrg    WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
453205b261ecSmrg    return Success;
453305b261ecSmrg}
453405b261ecSmrg
453505b261ecSmrg/**
45364642e01fSmrg * Server-side protocol handling for GrabPointer request.
453705b261ecSmrg *
45384642e01fSmrg * Sets an active grab on the client's ClientPointer and returns success
45394642e01fSmrg * status to client.
454005b261ecSmrg */
454105b261ecSmrgint
454205b261ecSmrgProcGrabPointer(ClientPtr client)
454305b261ecSmrg{
454405b261ecSmrg    xGrabPointerReply rep;
45454642e01fSmrg    DeviceIntPtr device = PickPointer(client);
454605b261ecSmrg    GrabPtr grab;
45476747b715Smrg    GrabMask mask;
45486747b715Smrg    WindowPtr confineTo;
45496747b715Smrg    CursorPtr oldCursor;
455005b261ecSmrg    REQUEST(xGrabPointerReq);
455105b261ecSmrg    TimeStamp time;
455205b261ecSmrg    int rc;
455305b261ecSmrg
455405b261ecSmrg    REQUEST_SIZE_MATCH(xGrabPointerReq);
455505b261ecSmrg    UpdateCurrentTime();
45566747b715Smrg
455705b261ecSmrg    if (stuff->eventMask & ~PointerGrabMask)
455805b261ecSmrg    {
455905b261ecSmrg	client->errorValue = stuff->eventMask;
456005b261ecSmrg        return BadValue;
456105b261ecSmrg    }
45626747b715Smrg
456305b261ecSmrg    if (stuff->confineTo == None)
456405b261ecSmrg	confineTo = NullWindow;
45654642e01fSmrg    else
456605b261ecSmrg    {
456705b261ecSmrg	rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
45684642e01fSmrg			     DixSetAttrAccess);
456905b261ecSmrg	if (rc != Success)
457005b261ecSmrg	    return rc;
457105b261ecSmrg    }
45726747b715Smrg
45736747b715Smrg    memset(&rep, 0, sizeof(xGrabPointerReply));
45746747b715Smrg    oldCursor = NullCursor;
45756747b715Smrg    grab = device->deviceGrab.grab;
45766747b715Smrg
45776747b715Smrg    if (grab)
457805b261ecSmrg    {
45796747b715Smrg        if (grab->confineTo && !confineTo)
45806747b715Smrg            ConfineCursorToWindow(device, RootWindow(device), FALSE, FALSE);
45816747b715Smrg        oldCursor = grab->cursor;
458205b261ecSmrg    }
45836747b715Smrg
45846747b715Smrg    mask.core = stuff->eventMask;
45856747b715Smrg
45866747b715Smrg    rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode,
45876747b715Smrg                    stuff->grabWindow, stuff->ownerEvents, stuff->time,
45886747b715Smrg                    &mask, GRABTYPE_CORE, stuff->cursor,
45896747b715Smrg                    stuff->confineTo, &rep.status);
45904642e01fSmrg    if (rc != Success)
45916747b715Smrg        return rc;
45926747b715Smrg
45936747b715Smrg    if (oldCursor && rep.status == GrabSuccess)
45946747b715Smrg        FreeCursor (oldCursor, (Cursor)0);
45954642e01fSmrg
459605b261ecSmrg    time = ClientTimeToServerTime(stuff->time);
459705b261ecSmrg    rep.type = X_Reply;
459805b261ecSmrg    rep.sequenceNumber = client->sequence;
459905b261ecSmrg    rep.length = 0;
460005b261ecSmrg    WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
460105b261ecSmrg    return Success;
460205b261ecSmrg}
460305b261ecSmrg
460405b261ecSmrg/**
460505b261ecSmrg * Server-side protocol handling for ChangeActivePointerGrab request.
460605b261ecSmrg *
460705b261ecSmrg * Changes properties of the grab hold by the client. If the client does not
46084642e01fSmrg * hold an active grab on the device, nothing happens.
460905b261ecSmrg */
461005b261ecSmrgint
461105b261ecSmrgProcChangeActivePointerGrab(ClientPtr client)
461205b261ecSmrg{
46134642e01fSmrg    DeviceIntPtr device;
46144642e01fSmrg    GrabPtr      grab;
461505b261ecSmrg    CursorPtr newCursor, oldCursor;
461605b261ecSmrg    REQUEST(xChangeActivePointerGrabReq);
461705b261ecSmrg    TimeStamp time;
461805b261ecSmrg
461905b261ecSmrg    REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
462005b261ecSmrg    if (stuff->eventMask & ~PointerGrabMask)
462105b261ecSmrg    {
462205b261ecSmrg	client->errorValue = stuff->eventMask;
462305b261ecSmrg        return BadValue;
462405b261ecSmrg    }
462505b261ecSmrg    if (stuff->cursor == None)
462605b261ecSmrg	newCursor = NullCursor;
462705b261ecSmrg    else
462805b261ecSmrg    {
4629b86d567bSmrg	int rc = dixLookupResourceByType((pointer *)&newCursor, stuff->cursor,
4630b86d567bSmrg					 RT_CURSOR, client, DixUseAccess);
46314642e01fSmrg	if (rc != Success)
463205b261ecSmrg	{
463305b261ecSmrg	    client->errorValue = stuff->cursor;
46346747b715Smrg	    return rc;
463505b261ecSmrg	}
463605b261ecSmrg    }
46374642e01fSmrg
46384642e01fSmrg    device = PickPointer(client);
46394642e01fSmrg    grab = device->deviceGrab.grab;
46404642e01fSmrg
464105b261ecSmrg    if (!grab)
464205b261ecSmrg	return Success;
464305b261ecSmrg    if (!SameClient(grab, client))
464405b261ecSmrg	return Success;
464505b261ecSmrg    time = ClientTimeToServerTime(stuff->time);
464605b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
46474642e01fSmrg	     (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
464805b261ecSmrg	return Success;
464905b261ecSmrg    oldCursor = grab->cursor;
465005b261ecSmrg    grab->cursor = newCursor;
465105b261ecSmrg    if (newCursor)
465205b261ecSmrg	newCursor->refcnt++;
46534642e01fSmrg    PostNewCursor(device);
465405b261ecSmrg    if (oldCursor)
465505b261ecSmrg	FreeCursor(oldCursor, (Cursor)0);
465605b261ecSmrg    grab->eventMask = stuff->eventMask;
465705b261ecSmrg    return Success;
465805b261ecSmrg}
465905b261ecSmrg
466005b261ecSmrg/**
466105b261ecSmrg * Server-side protocol handling for UngrabPointer request.
466205b261ecSmrg *
46634642e01fSmrg * Deletes a pointer grab on a device the client has grabbed.
466405b261ecSmrg */
466505b261ecSmrgint
466605b261ecSmrgProcUngrabPointer(ClientPtr client)
466705b261ecSmrg{
46684642e01fSmrg    DeviceIntPtr device = PickPointer(client);
466905b261ecSmrg    GrabPtr grab;
467005b261ecSmrg    TimeStamp time;
467105b261ecSmrg    REQUEST(xResourceReq);
467205b261ecSmrg
467305b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
467405b261ecSmrg    UpdateCurrentTime();
46754642e01fSmrg    grab = device->deviceGrab.grab;
46764642e01fSmrg
467705b261ecSmrg    time = ClientTimeToServerTime(stuff->id);
467805b261ecSmrg    if ((CompareTimeStamps(time, currentTime) != LATER) &&
46794642e01fSmrg	    (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
468005b261ecSmrg	    (grab) && SameClient(grab, client))
46814642e01fSmrg	(*device->deviceGrab.DeactivateGrab)(device);
468205b261ecSmrg    return Success;
468305b261ecSmrg}
468405b261ecSmrg
468505b261ecSmrg/**
468605b261ecSmrg * Sets a grab on the given device.
46874642e01fSmrg *
46884642e01fSmrg * Called from ProcGrabKeyboard to work on the client's keyboard.
468905b261ecSmrg * Called from ProcXGrabDevice to work on the device specified by the client.
46904642e01fSmrg *
469105b261ecSmrg * The parameters this_mode and other_mode represent the keyboard_mode and
46924642e01fSmrg * pointer_mode parameters of XGrabKeyboard().
469305b261ecSmrg * See man page for details on all the parameters
46944642e01fSmrg *
469505b261ecSmrg * @param client Client that owns the grab.
46964642e01fSmrg * @param dev The device to grab.
469705b261ecSmrg * @param this_mode GrabModeSync or GrabModeAsync
469805b261ecSmrg * @param other_mode GrabModeSync or GrabModeAsync
469905b261ecSmrg * @param status Return code to be returned to the caller.
47004642e01fSmrg *
470105b261ecSmrg * @returns Success or BadValue.
470205b261ecSmrg */
470305b261ecSmrgint
47044642e01fSmrgGrabDevice(ClientPtr client, DeviceIntPtr dev,
47056747b715Smrg           unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow,
47066747b715Smrg           unsigned ownerEvents, Time ctime, GrabMask *mask,
47076747b715Smrg           int grabtype, Cursor curs, Window confineToWin, CARD8 *status)
470805b261ecSmrg{
47096747b715Smrg    WindowPtr pWin, confineTo;
471005b261ecSmrg    GrabPtr grab;
471105b261ecSmrg    TimeStamp time;
47124642e01fSmrg    Mask access_mode = DixGrabAccess;
471305b261ecSmrg    int rc;
47144642e01fSmrg    GrabInfoPtr grabInfo = &dev->deviceGrab;
47156747b715Smrg    CursorPtr cursor;
471605b261ecSmrg
471705b261ecSmrg    UpdateCurrentTime();
47186747b715Smrg    if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync))
471905b261ecSmrg    {
47206747b715Smrg	client->errorValue = keyboard_mode;
472105b261ecSmrg        return BadValue;
472205b261ecSmrg    }
47236747b715Smrg    if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync))
472405b261ecSmrg    {
47256747b715Smrg	client->errorValue = pointer_mode;
472605b261ecSmrg        return BadValue;
472705b261ecSmrg    }
472805b261ecSmrg    if ((ownerEvents != xFalse) && (ownerEvents != xTrue))
472905b261ecSmrg    {
473005b261ecSmrg	client->errorValue = ownerEvents;
473105b261ecSmrg        return BadValue;
473205b261ecSmrg    }
47334642e01fSmrg
47344642e01fSmrg    rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
473505b261ecSmrg    if (rc != Success)
473605b261ecSmrg	return rc;
47376747b715Smrg
47386747b715Smrg    if (confineToWin == None)
47396747b715Smrg	confineTo = NullWindow;
47406747b715Smrg    else
47416747b715Smrg    {
47426747b715Smrg	rc = dixLookupWindow(&confineTo, confineToWin, client,
47436747b715Smrg			     DixSetAttrAccess);
47446747b715Smrg	if (rc != Success)
47456747b715Smrg	    return rc;
47466747b715Smrg    }
47476747b715Smrg
47486747b715Smrg    if (curs == None)
47496747b715Smrg	cursor = NullCursor;
47506747b715Smrg    else
47516747b715Smrg    {
47526747b715Smrg	rc = dixLookupResourceByType((pointer *)&cursor, curs, RT_CURSOR,
47536747b715Smrg			       client, DixUseAccess);
47546747b715Smrg	if (rc != Success)
47556747b715Smrg	{
47566747b715Smrg	    client->errorValue = curs;
47576747b715Smrg	    return rc;
47586747b715Smrg	}
47596747b715Smrg	access_mode |= DixForceAccess;
47606747b715Smrg    }
47616747b715Smrg
47626747b715Smrg    if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync)
47634642e01fSmrg	access_mode |= DixFreezeAccess;
47644642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
47654642e01fSmrg    if (rc != Success)
47664642e01fSmrg	return rc;
47674642e01fSmrg
476805b261ecSmrg    time = ClientTimeToServerTime(ctime);
47694642e01fSmrg    grab = grabInfo->grab;
47706747b715Smrg    if (grab && grab->grabtype != grabtype)
47716747b715Smrg        *status = AlreadyGrabbed;
477205b261ecSmrg    if (grab && !SameClient(grab, client))
477305b261ecSmrg	*status = AlreadyGrabbed;
47746747b715Smrg    else if ((!pWin->realized) ||
47756747b715Smrg             (confineTo &&
47766747b715Smrg                !(confineTo->realized
47776747b715Smrg                    && BorderSizeNotEmpty(dev, confineTo))))
477805b261ecSmrg	*status = GrabNotViewable;
477905b261ecSmrg    else if ((CompareTimeStamps(time, currentTime) == LATER) ||
47804642e01fSmrg	     (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER))
478105b261ecSmrg	*status = GrabInvalidTime;
47824642e01fSmrg    else if (grabInfo->sync.frozen &&
47834642e01fSmrg	     grabInfo->sync.other && !SameClient(grabInfo->sync.other, client))
478405b261ecSmrg	*status = GrabFrozen;
478505b261ecSmrg    else
478605b261ecSmrg    {
478705b261ecSmrg	GrabRec tempGrab;
478805b261ecSmrg
47894642e01fSmrg        /* Otherwise segfaults happen on grabbed MPX devices */
47904642e01fSmrg        memset(&tempGrab, 0, sizeof(GrabRec));
47914642e01fSmrg
47924642e01fSmrg        tempGrab.next = NULL;
479305b261ecSmrg	tempGrab.window = pWin;
479405b261ecSmrg	tempGrab.resource = client->clientAsMask;
479505b261ecSmrg	tempGrab.ownerEvents = ownerEvents;
47966747b715Smrg	tempGrab.keyboardMode = keyboard_mode;
47976747b715Smrg	tempGrab.pointerMode = pointer_mode;
47986747b715Smrg	if (grabtype == GRABTYPE_CORE)
47996747b715Smrg	    tempGrab.eventMask = mask->core;
48006747b715Smrg	else if (grabtype == GRABTYPE_XI)
48016747b715Smrg	    tempGrab.eventMask = mask->xi;
48026747b715Smrg	else
48036747b715Smrg	    memcpy(tempGrab.xi2mask, mask->xi2mask, sizeof(tempGrab.xi2mask));
480405b261ecSmrg	tempGrab.device = dev;
48056747b715Smrg	tempGrab.cursor = cursor;
48066747b715Smrg	tempGrab.confineTo = confineTo;
48076747b715Smrg	tempGrab.grabtype = grabtype;
48084642e01fSmrg	(*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE);
480905b261ecSmrg	*status = GrabSuccess;
481005b261ecSmrg    }
481105b261ecSmrg    return Success;
481205b261ecSmrg}
481305b261ecSmrg
481405b261ecSmrg/**
481505b261ecSmrg * Server-side protocol handling for GrabKeyboard request.
481605b261ecSmrg *
48174642e01fSmrg * Grabs the client's keyboard and returns success status to client.
481805b261ecSmrg */
481905b261ecSmrgint
482005b261ecSmrgProcGrabKeyboard(ClientPtr client)
482105b261ecSmrg{
482205b261ecSmrg    xGrabKeyboardReply rep;
482305b261ecSmrg    REQUEST(xGrabKeyboardReq);
482405b261ecSmrg    int result;
48254642e01fSmrg    DeviceIntPtr keyboard = PickKeyboard(client);
48266747b715Smrg    GrabMask mask;
482705b261ecSmrg
482805b261ecSmrg    REQUEST_SIZE_MATCH(xGrabKeyboardReq);
482905b261ecSmrg
48306747b715Smrg    memset(&rep, 0, sizeof(xGrabKeyboardReply));
48316747b715Smrg    mask.core = KeyPressMask | KeyReleaseMask;
48326747b715Smrg
48336747b715Smrg    result = GrabDevice(client, keyboard, stuff->pointerMode,
48346747b715Smrg            stuff->keyboardMode, stuff->grabWindow, stuff->ownerEvents,
48356747b715Smrg            stuff->time, &mask, GRABTYPE_CORE, None, None,
48366747b715Smrg            &rep.status);
483705b261ecSmrg
483805b261ecSmrg    if (result != Success)
483905b261ecSmrg	return result;
484005b261ecSmrg    rep.type = X_Reply;
484105b261ecSmrg    rep.sequenceNumber = client->sequence;
484205b261ecSmrg    rep.length = 0;
484305b261ecSmrg    WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
484405b261ecSmrg    return Success;
484505b261ecSmrg}
484605b261ecSmrg
484705b261ecSmrg/**
484805b261ecSmrg * Server-side protocol handling for UngrabKeyboard request.
484905b261ecSmrg *
48504642e01fSmrg * Deletes a possible grab on the client's keyboard.
485105b261ecSmrg */
485205b261ecSmrgint
485305b261ecSmrgProcUngrabKeyboard(ClientPtr client)
485405b261ecSmrg{
48554642e01fSmrg    DeviceIntPtr device = PickKeyboard(client);
485605b261ecSmrg    GrabPtr grab;
485705b261ecSmrg    TimeStamp time;
485805b261ecSmrg    REQUEST(xResourceReq);
485905b261ecSmrg
486005b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
486105b261ecSmrg    UpdateCurrentTime();
48624642e01fSmrg
48634642e01fSmrg    grab = device->deviceGrab.grab;
48644642e01fSmrg
486505b261ecSmrg    time = ClientTimeToServerTime(stuff->id);
486605b261ecSmrg    if ((CompareTimeStamps(time, currentTime) != LATER) &&
48674642e01fSmrg	(CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
48686747b715Smrg	(grab) && SameClient(grab, client) && grab->grabtype == GRABTYPE_CORE)
48694642e01fSmrg	(*device->deviceGrab.DeactivateGrab)(device);
487005b261ecSmrg    return Success;
487105b261ecSmrg}
487205b261ecSmrg
487305b261ecSmrg/**
487405b261ecSmrg * Server-side protocol handling for QueryPointer request.
487505b261ecSmrg *
48764642e01fSmrg * Returns the current state and position of the client's ClientPointer to the
48774642e01fSmrg * client.
487805b261ecSmrg */
487905b261ecSmrgint
488005b261ecSmrgProcQueryPointer(ClientPtr client)
488105b261ecSmrg{
488205b261ecSmrg    xQueryPointerReply rep;
488305b261ecSmrg    WindowPtr pWin, t;
48844642e01fSmrg    DeviceIntPtr mouse = PickPointer(client);
48856747b715Smrg    DeviceIntPtr keyboard;
48864642e01fSmrg    SpritePtr pSprite;
488705b261ecSmrg    int rc;
48884642e01fSmrg    REQUEST(xResourceReq);
488905b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
48904642e01fSmrg
48914642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
48924642e01fSmrg    if (rc != Success)
48934642e01fSmrg	return rc;
48944642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
48956747b715Smrg    if (rc != Success && rc != BadAccess)
489605b261ecSmrg	return rc;
48974642e01fSmrg
48986747b715Smrg    keyboard = GetPairedDevice(mouse);
48996747b715Smrg
49004642e01fSmrg    pSprite = mouse->spriteInfo->sprite;
490105b261ecSmrg    if (mouse->valuator->motionHintWindow)
490205b261ecSmrg	MaybeStopHint(mouse, client);
49036747b715Smrg    memset(&rep, 0, sizeof(xQueryPointerReply));
490405b261ecSmrg    rep.type = X_Reply;
490505b261ecSmrg    rep.sequenceNumber = client->sequence;
49066747b715Smrg    rep.mask = mouse->button ? (mouse->button->state) : 0;
49076747b715Smrg    rep.mask |= XkbStateFieldFromRec(&keyboard->key->xkbInfo->state);
490805b261ecSmrg    rep.length = 0;
49094642e01fSmrg    rep.root = (RootWindow(mouse))->drawable.id;
49104642e01fSmrg    rep.rootX = pSprite->hot.x;
49114642e01fSmrg    rep.rootY = pSprite->hot.y;
491205b261ecSmrg    rep.child = None;
49134642e01fSmrg    if (pSprite->hot.pScreen == pWin->drawable.pScreen)
491405b261ecSmrg    {
491505b261ecSmrg	rep.sameScreen = xTrue;
49164642e01fSmrg	rep.winX = pSprite->hot.x - pWin->drawable.x;
49174642e01fSmrg	rep.winY = pSprite->hot.y - pWin->drawable.y;
49184642e01fSmrg	for (t = pSprite->win; t; t = t->parent)
491905b261ecSmrg	    if (t->parent == pWin)
492005b261ecSmrg	    {
492105b261ecSmrg		rep.child = t->drawable.id;
492205b261ecSmrg		break;
492305b261ecSmrg	    }
492405b261ecSmrg    }
492505b261ecSmrg    else
492605b261ecSmrg    {
492705b261ecSmrg	rep.sameScreen = xFalse;
492805b261ecSmrg	rep.winX = 0;
492905b261ecSmrg	rep.winY = 0;
493005b261ecSmrg    }
493105b261ecSmrg
493205b261ecSmrg#ifdef PANORAMIX
493305b261ecSmrg    if(!noPanoramiXExtension) {
49346747b715Smrg	rep.rootX += screenInfo.screens[0]->x;
49356747b715Smrg	rep.rootY += screenInfo.screens[0]->y;
493605b261ecSmrg	if(stuff->id == rep.root) {
49376747b715Smrg	    rep.winX += screenInfo.screens[0]->x;
49386747b715Smrg	    rep.winY += screenInfo.screens[0]->y;
493905b261ecSmrg	}
494005b261ecSmrg    }
494105b261ecSmrg#endif
494205b261ecSmrg
49436747b715Smrg    if (rc == BadAccess) {
49446747b715Smrg	rep.mask = 0;
49456747b715Smrg	rep.child = None;
49466747b715Smrg	rep.rootX = 0;
49476747b715Smrg	rep.rootY = 0;
49486747b715Smrg	rep.winX = 0;
49496747b715Smrg	rep.winY = 0;
49506747b715Smrg    }
49516747b715Smrg
495205b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
495305b261ecSmrg
49546747b715Smrg    return Success;
495505b261ecSmrg}
495605b261ecSmrg
495705b261ecSmrg/**
495805b261ecSmrg * Initializes the device list and the DIX sprite to sane values. Allocates
495905b261ecSmrg * trace memory used for quick window traversal.
496005b261ecSmrg */
496105b261ecSmrgvoid
496205b261ecSmrgInitEvents(void)
496305b261ecSmrg{
496405b261ecSmrg    int i;
496505b261ecSmrg
496605b261ecSmrg    inputInfo.numDevices = 0;
496705b261ecSmrg    inputInfo.devices = (DeviceIntPtr)NULL;
496805b261ecSmrg    inputInfo.off_devices = (DeviceIntPtr)NULL;
496905b261ecSmrg    inputInfo.keyboard = (DeviceIntPtr)NULL;
497005b261ecSmrg    inputInfo.pointer = (DeviceIntPtr)NULL;
49716747b715Smrg    /* The mask for pointer motion events may have changed in the last server
49726747b715Smrg     * generation. See comment above definition of filters. */
49734642e01fSmrg    filters[0][PointerMotionMask] = MotionNotify;
49744642e01fSmrg    for (i = 1; i < MAXDEVICES; i++)
497505b261ecSmrg    {
49764642e01fSmrg        memcpy(&filters[i], filters[0], sizeof(filters[0]));
497705b261ecSmrg    }
49784642e01fSmrg
497905b261ecSmrg    syncEvents.replayDev = (DeviceIntPtr)NULL;
498005b261ecSmrg    syncEvents.replayWin = NullWindow;
498105b261ecSmrg    while (syncEvents.pending)
498205b261ecSmrg    {
498305b261ecSmrg	QdEventPtr next = syncEvents.pending->next;
49846747b715Smrg	free(syncEvents.pending);
498505b261ecSmrg	syncEvents.pending = next;
498605b261ecSmrg    }
498705b261ecSmrg    syncEvents.pendtail = &syncEvents.pending;
498805b261ecSmrg    syncEvents.playingEvents = FALSE;
498905b261ecSmrg    syncEvents.time.months = 0;
499005b261ecSmrg    syncEvents.time.milliseconds = 0;	/* hardly matters */
499105b261ecSmrg    currentTime.months = 0;
499205b261ecSmrg    currentTime.milliseconds = GetTimeInMillis();
499305b261ecSmrg    lastDeviceEventTime = currentTime;
499405b261ecSmrg    for (i = 0; i < DNPMCOUNT; i++)
499505b261ecSmrg    {
499605b261ecSmrg	DontPropagateMasks[i] = 0;
499705b261ecSmrg	DontPropagateRefCnts[i] = 0;
499805b261ecSmrg    }
49994642e01fSmrg
50004642e01fSmrg    InputEventListLen = GetMaximumEventsNum();
50014642e01fSmrg    InputEventList = InitEventList(InputEventListLen);
50024642e01fSmrg    if (!InputEventList)
50034642e01fSmrg        FatalError("[dix] Failed to allocate input event list.\n");
500405b261ecSmrg}
500505b261ecSmrg
500605b261ecSmrgvoid
500705b261ecSmrgCloseDownEvents(void)
500805b261ecSmrg{
50096747b715Smrg    FreeEventList(InputEventList, InputEventListLen);
50106747b715Smrg    InputEventListLen = 0;
50116747b715Smrg    InputEventList = NULL;
501205b261ecSmrg}
501305b261ecSmrg
501405b261ecSmrg/**
501505b261ecSmrg * Server-side protocol handling for SendEvent request.
501605b261ecSmrg *
50174642e01fSmrg * Locates the window to send the event to and forwards the event.
501805b261ecSmrg */
501905b261ecSmrgint
502005b261ecSmrgProcSendEvent(ClientPtr client)
502105b261ecSmrg{
502205b261ecSmrg    WindowPtr pWin;
502305b261ecSmrg    WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
50246747b715Smrg    DeviceIntPtr dev = PickPointer(client);
50256747b715Smrg    DeviceIntPtr keybd = GetPairedDevice(dev);
50266747b715Smrg    SpritePtr pSprite = dev->spriteInfo->sprite;
502705b261ecSmrg    REQUEST(xSendEventReq);
502805b261ecSmrg
502905b261ecSmrg    REQUEST_SIZE_MATCH(xSendEventReq);
503005b261ecSmrg
503105b261ecSmrg    /* The client's event type must be a core event type or one defined by an
503205b261ecSmrg	extension. */
503305b261ecSmrg
503405b261ecSmrg    if ( ! ((stuff->event.u.u.type > X_Reply &&
50354642e01fSmrg	     stuff->event.u.u.type < LASTEvent) ||
503605b261ecSmrg	    (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
503705b261ecSmrg	     stuff->event.u.u.type < (unsigned)lastEvent)))
503805b261ecSmrg    {
503905b261ecSmrg	client->errorValue = stuff->event.u.u.type;
504005b261ecSmrg	return BadValue;
504105b261ecSmrg    }
504205b261ecSmrg    if (stuff->event.u.u.type == ClientMessage &&
504305b261ecSmrg	stuff->event.u.u.detail != 8 &&
504405b261ecSmrg	stuff->event.u.u.detail != 16 &&
504505b261ecSmrg	stuff->event.u.u.detail != 32)
504605b261ecSmrg    {
504705b261ecSmrg	client->errorValue = stuff->event.u.u.detail;
504805b261ecSmrg	return BadValue;
504905b261ecSmrg    }
505005b261ecSmrg    if (stuff->eventMask & ~AllEventMasks)
505105b261ecSmrg    {
505205b261ecSmrg	client->errorValue = stuff->eventMask;
505305b261ecSmrg	return BadValue;
505405b261ecSmrg    }
505505b261ecSmrg
505605b261ecSmrg    if (stuff->destination == PointerWindow)
50574642e01fSmrg	pWin = pSprite->win;
505805b261ecSmrg    else if (stuff->destination == InputFocus)
505905b261ecSmrg    {
50606747b715Smrg	WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin;
506105b261ecSmrg
506205b261ecSmrg	if (inputFocus == NoneWin)
506305b261ecSmrg	    return Success;
506405b261ecSmrg
506505b261ecSmrg	/* If the input focus is PointerRootWin, send the event to where
506605b261ecSmrg	the pointer is if possible, then perhaps propogate up to root. */
50674642e01fSmrg	if (inputFocus == PointerRootWin)
50684642e01fSmrg	    inputFocus = pSprite->spriteTrace[0]; /* Root window! */
506905b261ecSmrg
50704642e01fSmrg	if (IsParent(inputFocus, pSprite->win))
507105b261ecSmrg	{
507205b261ecSmrg	    effectiveFocus = inputFocus;
50734642e01fSmrg	    pWin = pSprite->win;
507405b261ecSmrg	}
507505b261ecSmrg	else
507605b261ecSmrg	    effectiveFocus = pWin = inputFocus;
507705b261ecSmrg    }
507805b261ecSmrg    else
50794642e01fSmrg	dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess);
508005b261ecSmrg
508105b261ecSmrg    if (!pWin)
508205b261ecSmrg	return BadWindow;
508305b261ecSmrg    if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue))
508405b261ecSmrg    {
508505b261ecSmrg	client->errorValue = stuff->propagate;
508605b261ecSmrg	return BadValue;
508705b261ecSmrg    }
508805b261ecSmrg    stuff->event.u.u.type |= 0x80;
508905b261ecSmrg    if (stuff->propagate)
509005b261ecSmrg    {
509105b261ecSmrg	for (;pWin; pWin = pWin->parent)
509205b261ecSmrg	{
50934642e01fSmrg	    if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin,
50944642e01fSmrg			 &stuff->event, 1))
50954642e01fSmrg		return Success;
50966747b715Smrg            if (DeliverEventsToWindow(dev, pWin,
50976747b715Smrg                        &stuff->event, 1, stuff->eventMask, NullGrab))
509805b261ecSmrg		return Success;
509905b261ecSmrg	    if (pWin == effectiveFocus)
510005b261ecSmrg		return Success;
510105b261ecSmrg	    stuff->eventMask &= ~wDontPropagateMask(pWin);
510205b261ecSmrg	    if (!stuff->eventMask)
510305b261ecSmrg		break;
510405b261ecSmrg	}
510505b261ecSmrg    }
51064642e01fSmrg    else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1))
51076747b715Smrg        DeliverEventsToWindow(dev, pWin, &stuff->event,
51086747b715Smrg                                    1, stuff->eventMask, NullGrab);
510905b261ecSmrg    return Success;
511005b261ecSmrg}
511105b261ecSmrg
511205b261ecSmrg/**
511305b261ecSmrg * Server-side protocol handling for UngrabKey request.
511405b261ecSmrg *
51154642e01fSmrg * Deletes a passive grab for the given key. Works on the
51164642e01fSmrg * client's keyboard.
511705b261ecSmrg */
511805b261ecSmrgint
511905b261ecSmrgProcUngrabKey(ClientPtr client)
512005b261ecSmrg{
512105b261ecSmrg    REQUEST(xUngrabKeyReq);
512205b261ecSmrg    WindowPtr pWin;
512305b261ecSmrg    GrabRec tempGrab;
51244642e01fSmrg    DeviceIntPtr keybd = PickKeyboard(client);
512505b261ecSmrg    int rc;
512605b261ecSmrg
512705b261ecSmrg    REQUEST_SIZE_MATCH(xUngrabKeyReq);
51286747b715Smrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess);
512905b261ecSmrg    if (rc != Success)
513005b261ecSmrg	return rc;
513105b261ecSmrg
51326747b715Smrg    if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
51336747b715Smrg	 (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
513405b261ecSmrg	&& (stuff->key != AnyKey))
513505b261ecSmrg    {
513605b261ecSmrg	client->errorValue = stuff->key;
513705b261ecSmrg        return BadValue;
513805b261ecSmrg    }
513905b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
514005b261ecSmrg	(stuff->modifiers & ~AllModifiersMask))
514105b261ecSmrg    {
514205b261ecSmrg	client->errorValue = stuff->modifiers;
514305b261ecSmrg	return BadValue;
514405b261ecSmrg    }
514505b261ecSmrg    tempGrab.resource = client->clientAsMask;
514605b261ecSmrg    tempGrab.device = keybd;
514705b261ecSmrg    tempGrab.window = pWin;
514805b261ecSmrg    tempGrab.modifiersDetail.exact = stuff->modifiers;
514905b261ecSmrg    tempGrab.modifiersDetail.pMask = NULL;
51506747b715Smrg    tempGrab.modifierDevice = GetPairedDevice(keybd);
515105b261ecSmrg    tempGrab.type = KeyPress;
51526747b715Smrg    tempGrab.grabtype = GRABTYPE_CORE;
515305b261ecSmrg    tempGrab.detail.exact = stuff->key;
515405b261ecSmrg    tempGrab.detail.pMask = NULL;
51554642e01fSmrg    tempGrab.next = NULL;
515605b261ecSmrg
515705b261ecSmrg    if (!DeletePassiveGrabFromList(&tempGrab))
51586747b715Smrg	return BadAlloc;
51596747b715Smrg    return Success;
516005b261ecSmrg}
516105b261ecSmrg
516205b261ecSmrg/**
516305b261ecSmrg * Server-side protocol handling for GrabKey request.
516405b261ecSmrg *
51654642e01fSmrg * Creates a grab for the client's keyboard and adds it to the list of passive
51664642e01fSmrg * grabs.
516705b261ecSmrg */
516805b261ecSmrgint
516905b261ecSmrgProcGrabKey(ClientPtr client)
517005b261ecSmrg{
517105b261ecSmrg    WindowPtr pWin;
517205b261ecSmrg    REQUEST(xGrabKeyReq);
517305b261ecSmrg    GrabPtr grab;
51744642e01fSmrg    DeviceIntPtr keybd = PickKeyboard(client);
517505b261ecSmrg    int rc;
51766747b715Smrg    GrabParameters param;
51776747b715Smrg    GrabMask mask;
517805b261ecSmrg
517905b261ecSmrg    REQUEST_SIZE_MATCH(xGrabKeyReq);
51806747b715Smrg
51816747b715Smrg    memset(&param, 0, sizeof(param));
51826747b715Smrg    param.grabtype = GRABTYPE_CORE;
51836747b715Smrg    param.ownerEvents = stuff->ownerEvents;
51846747b715Smrg    param.this_device_mode = stuff->keyboardMode;
51856747b715Smrg    param.other_devices_mode = stuff->pointerMode;
51866747b715Smrg    param.modifiers = stuff->modifiers;
51876747b715Smrg
51886747b715Smrg    rc = CheckGrabValues(client, &param);
51896747b715Smrg    if (rc != Success)
51906747b715Smrg        return rc;
51916747b715Smrg
51926747b715Smrg    if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
51936747b715Smrg	 (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
519405b261ecSmrg	&& (stuff->key != AnyKey))
519505b261ecSmrg    {
519605b261ecSmrg	client->errorValue = stuff->key;
519705b261ecSmrg        return BadValue;
519805b261ecSmrg    }
51994642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
520005b261ecSmrg    if (rc != Success)
520105b261ecSmrg	return rc;
520205b261ecSmrg
52036747b715Smrg
52046747b715Smrg    mask.core = (KeyPressMask | KeyReleaseMask);
52056747b715Smrg
52066747b715Smrg    grab = CreateGrab(client->index, keybd, keybd, pWin, GRABTYPE_CORE, &mask,
52076747b715Smrg                      &param, KeyPress, stuff->key, NullWindow, NullCursor);
520805b261ecSmrg    if (!grab)
520905b261ecSmrg	return BadAlloc;
52104642e01fSmrg    return AddPassiveGrabToList(client, grab);
521105b261ecSmrg}
521205b261ecSmrg
521305b261ecSmrg
521405b261ecSmrg/**
521505b261ecSmrg * Server-side protocol handling for GrabButton request.
521605b261ecSmrg *
52174642e01fSmrg * Creates a grab for the client's ClientPointer and adds it as a passive grab
52184642e01fSmrg * to the list.
521905b261ecSmrg */
522005b261ecSmrgint
522105b261ecSmrgProcGrabButton(ClientPtr client)
522205b261ecSmrg{
522305b261ecSmrg    WindowPtr pWin, confineTo;
522405b261ecSmrg    REQUEST(xGrabButtonReq);
522505b261ecSmrg    CursorPtr cursor;
522605b261ecSmrg    GrabPtr grab;
52274642e01fSmrg    DeviceIntPtr ptr, modifierDevice;
52284642e01fSmrg    Mask access_mode = DixGrabAccess;
52296747b715Smrg    GrabMask mask;
52306747b715Smrg    GrabParameters param;
523105b261ecSmrg    int rc;
523205b261ecSmrg
523305b261ecSmrg    REQUEST_SIZE_MATCH(xGrabButtonReq);
523405b261ecSmrg    if ((stuff->pointerMode != GrabModeSync) &&
523505b261ecSmrg	(stuff->pointerMode != GrabModeAsync))
523605b261ecSmrg    {
523705b261ecSmrg	client->errorValue = stuff->pointerMode;
523805b261ecSmrg        return BadValue;
523905b261ecSmrg    }
524005b261ecSmrg    if ((stuff->keyboardMode != GrabModeSync) &&
524105b261ecSmrg	(stuff->keyboardMode != GrabModeAsync))
524205b261ecSmrg    {
524305b261ecSmrg	client->errorValue = stuff->keyboardMode;
524405b261ecSmrg        return BadValue;
524505b261ecSmrg    }
524605b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
524705b261ecSmrg	(stuff->modifiers & ~AllModifiersMask))
524805b261ecSmrg    {
524905b261ecSmrg	client->errorValue = stuff->modifiers;
525005b261ecSmrg	return BadValue;
525105b261ecSmrg    }
525205b261ecSmrg    if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
525305b261ecSmrg    {
525405b261ecSmrg	client->errorValue = stuff->ownerEvents;
525505b261ecSmrg	return BadValue;
525605b261ecSmrg    }
525705b261ecSmrg    if (stuff->eventMask & ~PointerGrabMask)
525805b261ecSmrg    {
525905b261ecSmrg	client->errorValue = stuff->eventMask;
526005b261ecSmrg        return BadValue;
526105b261ecSmrg    }
52624642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
526305b261ecSmrg    if (rc != Success)
526405b261ecSmrg	return rc;
526505b261ecSmrg    if (stuff->confineTo == None)
526605b261ecSmrg       confineTo = NullWindow;
526705b261ecSmrg    else {
526805b261ecSmrg	rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
52694642e01fSmrg			     DixSetAttrAccess);
527005b261ecSmrg	if (rc != Success)
527105b261ecSmrg	    return rc;
527205b261ecSmrg    }
527305b261ecSmrg    if (stuff->cursor == None)
527405b261ecSmrg	cursor = NullCursor;
527505b261ecSmrg    else
527605b261ecSmrg    {
5277b86d567bSmrg	rc = dixLookupResourceByType((pointer *)&cursor, stuff->cursor, RT_CURSOR,
52784642e01fSmrg			       client, DixUseAccess);
52794642e01fSmrg	if (rc != Success)
528005b261ecSmrg	{
528105b261ecSmrg	    client->errorValue = stuff->cursor;
52826747b715Smrg	    return rc;
528305b261ecSmrg	}
52844642e01fSmrg	access_mode |= DixForceAccess;
528505b261ecSmrg    }
528605b261ecSmrg
52874642e01fSmrg    ptr = PickPointer(client);
52884642e01fSmrg    modifierDevice = GetPairedDevice(ptr);
52894642e01fSmrg    if (stuff->pointerMode == GrabModeSync ||
52904642e01fSmrg	stuff->keyboardMode == GrabModeSync)
52914642e01fSmrg	access_mode |= DixFreezeAccess;
52924642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode);
52934642e01fSmrg    if (rc != Success)
52944642e01fSmrg	return rc;
529505b261ecSmrg
52966747b715Smrg    memset(&param, 0, sizeof(param));
52976747b715Smrg    param.grabtype = GRABTYPE_CORE;
52986747b715Smrg    param.ownerEvents = stuff->ownerEvents;
52996747b715Smrg    param.this_device_mode = stuff->keyboardMode;
53006747b715Smrg    param.other_devices_mode = stuff->pointerMode;
53016747b715Smrg    param.modifiers = stuff->modifiers;
53026747b715Smrg
53036747b715Smrg    mask.core = stuff->eventMask;
53046747b715Smrg
53056747b715Smrg    grab = CreateGrab(client->index, ptr, modifierDevice, pWin,
53066747b715Smrg                      GRABTYPE_CORE, &mask, &param, ButtonPress,
53076747b715Smrg                      stuff->button, confineTo, cursor);
530805b261ecSmrg    if (!grab)
530905b261ecSmrg	return BadAlloc;
53104642e01fSmrg    return AddPassiveGrabToList(client, grab);
531105b261ecSmrg}
531205b261ecSmrg
531305b261ecSmrg/**
531405b261ecSmrg * Server-side protocol handling for UngrabButton request.
531505b261ecSmrg *
53164642e01fSmrg * Deletes a passive grab on the client's ClientPointer from the list.
531705b261ecSmrg */
531805b261ecSmrgint
531905b261ecSmrgProcUngrabButton(ClientPtr client)
532005b261ecSmrg{
532105b261ecSmrg    REQUEST(xUngrabButtonReq);
532205b261ecSmrg    WindowPtr pWin;
532305b261ecSmrg    GrabRec tempGrab;
532405b261ecSmrg    int rc;
53256747b715Smrg    DeviceIntPtr ptr;
532605b261ecSmrg
532705b261ecSmrg    REQUEST_SIZE_MATCH(xUngrabButtonReq);
532805b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
532905b261ecSmrg	(stuff->modifiers & ~AllModifiersMask))
533005b261ecSmrg    {
533105b261ecSmrg	client->errorValue = stuff->modifiers;
533205b261ecSmrg	return BadValue;
533305b261ecSmrg    }
533405b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
533505b261ecSmrg    if (rc != Success)
533605b261ecSmrg	return rc;
53376747b715Smrg
53386747b715Smrg    ptr = PickPointer(client);
53396747b715Smrg
534005b261ecSmrg    tempGrab.resource = client->clientAsMask;
53416747b715Smrg    tempGrab.device = ptr;
534205b261ecSmrg    tempGrab.window = pWin;
534305b261ecSmrg    tempGrab.modifiersDetail.exact = stuff->modifiers;
534405b261ecSmrg    tempGrab.modifiersDetail.pMask = NULL;
53456747b715Smrg    tempGrab.modifierDevice = GetPairedDevice(ptr);
534605b261ecSmrg    tempGrab.type = ButtonPress;
534705b261ecSmrg    tempGrab.detail.exact = stuff->button;
53486747b715Smrg    tempGrab.grabtype = GRABTYPE_CORE;
534905b261ecSmrg    tempGrab.detail.pMask = NULL;
53504642e01fSmrg    tempGrab.next = NULL;
535105b261ecSmrg
535205b261ecSmrg    if (!DeletePassiveGrabFromList(&tempGrab))
53536747b715Smrg	return BadAlloc;
53546747b715Smrg    return Success;
535505b261ecSmrg}
535605b261ecSmrg
535705b261ecSmrg/**
535805b261ecSmrg * Deactivate any grab that may be on the window, remove the focus.
535905b261ecSmrg * Delete any XInput extension events from the window too. Does not change the
536005b261ecSmrg * window mask. Use just before the window is deleted.
536105b261ecSmrg *
536205b261ecSmrg * If freeResources is set, passive grabs on the window are deleted.
536305b261ecSmrg *
536405b261ecSmrg * @param pWin The window to delete events from.
536505b261ecSmrg * @param freeResources True if resources associated with the window should be
536605b261ecSmrg * deleted.
536705b261ecSmrg */
536805b261ecSmrgvoid
536905b261ecSmrgDeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
537005b261ecSmrg{
537105b261ecSmrg    WindowPtr		parent;
537205b261ecSmrg    DeviceIntPtr	mouse = inputInfo.pointer;
537305b261ecSmrg    DeviceIntPtr	keybd = inputInfo.keyboard;
53744642e01fSmrg    FocusClassPtr	focus;
537505b261ecSmrg    OtherClientsPtr	oc;
537605b261ecSmrg    GrabPtr		passive;
53774642e01fSmrg    GrabPtr             grab;
537805b261ecSmrg
537905b261ecSmrg
538005b261ecSmrg    /* Deactivate any grabs performed on this window, before making any
538105b261ecSmrg	input focus changes. */
53824642e01fSmrg    grab = mouse->deviceGrab.grab;
53834642e01fSmrg    if (grab &&
53844642e01fSmrg	((grab->window == pWin) || (grab->confineTo == pWin)))
53854642e01fSmrg	(*mouse->deviceGrab.DeactivateGrab)(mouse);
538605b261ecSmrg
538705b261ecSmrg
538805b261ecSmrg    /* Deactivating a keyboard grab should cause focus events. */
53894642e01fSmrg    grab = keybd->deviceGrab.grab;
53904642e01fSmrg    if (grab && (grab->window == pWin))
53914642e01fSmrg	(*keybd->deviceGrab.DeactivateGrab)(keybd);
539205b261ecSmrg
53934642e01fSmrg    /* And now the real devices */
53944642e01fSmrg    for (mouse = inputInfo.devices; mouse; mouse = mouse->next)
539505b261ecSmrg    {
53964642e01fSmrg        grab = mouse->deviceGrab.grab;
53974642e01fSmrg        if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
53984642e01fSmrg            (*mouse->deviceGrab.DeactivateGrab)(mouse);
53994642e01fSmrg    }
540005b261ecSmrg
540105b261ecSmrg
54024642e01fSmrg    for (keybd = inputInfo.devices; keybd; keybd = keybd->next)
54034642e01fSmrg    {
54044642e01fSmrg        if (IsKeyboardDevice(keybd))
54054642e01fSmrg        {
54064642e01fSmrg            focus = keybd->focus;
54074642e01fSmrg
54084642e01fSmrg            /* If the focus window is a root window (ie. has no parent) then don't
54094642e01fSmrg               delete the focus from it. */
54104642e01fSmrg
54114642e01fSmrg            if ((pWin == focus->win) && (pWin->parent != NullWindow))
54124642e01fSmrg            {
54134642e01fSmrg                int focusEventMode = NotifyNormal;
54144642e01fSmrg
54154642e01fSmrg                /* If a grab is in progress, then alter the mode of focus events. */
54164642e01fSmrg
54174642e01fSmrg                if (keybd->deviceGrab.grab)
54184642e01fSmrg                    focusEventMode = NotifyWhileGrabbed;
54194642e01fSmrg
54204642e01fSmrg                switch (focus->revert)
54214642e01fSmrg                {
54224642e01fSmrg                    case RevertToNone:
54234642e01fSmrg                        DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
54244642e01fSmrg                        focus->win = NoneWin;
54254642e01fSmrg                        focus->traceGood = 0;
54264642e01fSmrg                        break;
54274642e01fSmrg                    case RevertToParent:
54284642e01fSmrg                        parent = pWin;
54294642e01fSmrg                        do
54304642e01fSmrg                        {
54314642e01fSmrg                            parent = parent->parent;
54324642e01fSmrg                            focus->traceGood--;
54334642e01fSmrg                        } while (!parent->realized
54344642e01fSmrg                                /* This would be a good protocol change -- windows being reparented
54354642e01fSmrg                                   during SaveSet processing would cause the focus to revert to the
54364642e01fSmrg                                   nearest enclosing window which will survive the death of the exiting
54374642e01fSmrg                                   client, instead of ending up reverting to a dying window and thence
54384642e01fSmrg                                   to None
54394642e01fSmrg                                 */
544005b261ecSmrg#ifdef NOTDEF
54416747b715Smrg				 || wClient(parent)->clientGone
544205b261ecSmrg#endif
54434642e01fSmrg                                );
54446747b715Smrg                        if (!ActivateFocusInGrab(keybd, pWin, parent))
54456747b715Smrg                            DoFocusEvents(keybd, pWin, parent, focusEventMode);
54464642e01fSmrg                        focus->win = parent;
54474642e01fSmrg                        focus->revert = RevertToNone;
54484642e01fSmrg                        break;
54494642e01fSmrg                    case RevertToPointerRoot:
54506747b715Smrg                        if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin))
54516747b715Smrg                            DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode);
54524642e01fSmrg                        focus->win = PointerRootWin;
54534642e01fSmrg                        focus->traceGood = 0;
54544642e01fSmrg                        break;
54554642e01fSmrg                }
54564642e01fSmrg            }
54574642e01fSmrg        }
545805b261ecSmrg
54594642e01fSmrg        if (IsPointerDevice(keybd))
54604642e01fSmrg        {
54614642e01fSmrg            if (keybd->valuator->motionHintWindow == pWin)
54624642e01fSmrg                keybd->valuator->motionHintWindow = NullWindow;
54634642e01fSmrg        }
54644642e01fSmrg    }
546505b261ecSmrg
546605b261ecSmrg    if (freeResources)
546705b261ecSmrg    {
546805b261ecSmrg	if (pWin->dontPropagate)
546905b261ecSmrg	    DontPropagateRefCnts[pWin->dontPropagate]--;
547005b261ecSmrg	while ( (oc = wOtherClients(pWin)) )
547105b261ecSmrg	    FreeResource(oc->resource, RT_NONE);
547205b261ecSmrg	while ( (passive = wPassiveGrabs(pWin)) )
547305b261ecSmrg	    FreeResource(passive->resource, RT_NONE);
547405b261ecSmrg     }
54754642e01fSmrg
547605b261ecSmrg    DeleteWindowFromAnyExtEvents(pWin, freeResources);
547705b261ecSmrg}
547805b261ecSmrg
547905b261ecSmrg/**
548005b261ecSmrg * Call this whenever some window at or below pWin has changed geometry. If
548105b261ecSmrg * there is a grab on the window, the cursor will be re-confined into the
548205b261ecSmrg * window.
548305b261ecSmrg */
54846747b715Smrgvoid
548505b261ecSmrgCheckCursorConfinement(WindowPtr pWin)
548605b261ecSmrg{
54874642e01fSmrg    GrabPtr grab;
548805b261ecSmrg    WindowPtr confineTo;
54894642e01fSmrg    DeviceIntPtr pDev;
549005b261ecSmrg
549105b261ecSmrg#ifdef PANORAMIX
549205b261ecSmrg    if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return;
549305b261ecSmrg#endif
549405b261ecSmrg
54954642e01fSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
549605b261ecSmrg    {
54974642e01fSmrg        if (DevHasCursor(pDev))
54984642e01fSmrg        {
54994642e01fSmrg            grab = pDev->deviceGrab.grab;
55004642e01fSmrg            if (grab && (confineTo = grab->confineTo))
55014642e01fSmrg            {
55024642e01fSmrg                if (!BorderSizeNotEmpty(pDev, confineTo))
55036747b715Smrg                    (*pDev->deviceGrab.DeactivateGrab)(pDev);
55044642e01fSmrg                else if ((pWin == confineTo) || IsParent(pWin, confineTo))
55054642e01fSmrg                    ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
55064642e01fSmrg            }
55074642e01fSmrg        }
550805b261ecSmrg    }
550905b261ecSmrg}
551005b261ecSmrg
551105b261ecSmrgMask
551205b261ecSmrgEventMaskForClient(WindowPtr pWin, ClientPtr client)
551305b261ecSmrg{
551405b261ecSmrg    OtherClientsPtr	other;
551505b261ecSmrg
551605b261ecSmrg    if (wClient (pWin) == client)
551705b261ecSmrg	return pWin->eventMask;
551805b261ecSmrg    for (other = wOtherClients(pWin); other; other = other->next)
551905b261ecSmrg    {
552005b261ecSmrg	if (SameClient(other, client))
552105b261ecSmrg	    return other->mask;
552205b261ecSmrg    }
552305b261ecSmrg    return 0;
552405b261ecSmrg}
552505b261ecSmrg
552605b261ecSmrg/**
552705b261ecSmrg * Server-side protocol handling for RecolorCursor request.
552805b261ecSmrg */
552905b261ecSmrgint
553005b261ecSmrgProcRecolorCursor(ClientPtr client)
553105b261ecSmrg{
553205b261ecSmrg    CursorPtr pCursor;
55334642e01fSmrg    int		rc, nscr;
553405b261ecSmrg    ScreenPtr	pscr;
55354642e01fSmrg    Bool	displayed;
55364642e01fSmrg    SpritePtr   pSprite = PickPointer(client)->spriteInfo->sprite;
553705b261ecSmrg    REQUEST(xRecolorCursorReq);
553805b261ecSmrg
553905b261ecSmrg    REQUEST_SIZE_MATCH(xRecolorCursorReq);
5540b86d567bSmrg    rc = dixLookupResourceByType((pointer *)&pCursor, stuff->cursor, RT_CURSOR,
55414642e01fSmrg			   client, DixWriteAccess);
55424642e01fSmrg    if (rc != Success)
554305b261ecSmrg    {
554405b261ecSmrg	client->errorValue = stuff->cursor;
55456747b715Smrg	return rc;
554605b261ecSmrg    }
554705b261ecSmrg
554805b261ecSmrg    pCursor->foreRed = stuff->foreRed;
554905b261ecSmrg    pCursor->foreGreen = stuff->foreGreen;
555005b261ecSmrg    pCursor->foreBlue = stuff->foreBlue;
555105b261ecSmrg
555205b261ecSmrg    pCursor->backRed = stuff->backRed;
555305b261ecSmrg    pCursor->backGreen = stuff->backGreen;
555405b261ecSmrg    pCursor->backBlue = stuff->backBlue;
555505b261ecSmrg
555605b261ecSmrg    for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
555705b261ecSmrg    {
555805b261ecSmrg	pscr = screenInfo.screens[nscr];
555905b261ecSmrg#ifdef PANORAMIX
556005b261ecSmrg	if(!noPanoramiXExtension)
55614642e01fSmrg	    displayed = (pscr == pSprite->screen);
556205b261ecSmrg	else
556305b261ecSmrg#endif
55644642e01fSmrg	    displayed = (pscr == pSprite->hotPhys.pScreen);
55654642e01fSmrg	( *pscr->RecolorCursor)(PickPointer(client), pscr, pCursor,
55664642e01fSmrg				(pCursor == pSprite->current) && displayed);
556705b261ecSmrg    }
55686747b715Smrg    return Success;
556905b261ecSmrg}
557005b261ecSmrg
557105b261ecSmrg/**
557205b261ecSmrg * Write the given events to a client, swapping the byte order if necessary.
557305b261ecSmrg * To swap the byte ordering, a callback is called that has to be set up for
557405b261ecSmrg * the given event type.
557505b261ecSmrg *
557605b261ecSmrg * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
55774642e01fSmrg * can be more than one. Usually it's just one event.
557805b261ecSmrg *
557905b261ecSmrg * Do not modify the event structure passed in. See comment below.
55804642e01fSmrg *
558105b261ecSmrg * @param pClient Client to send events to.
558205b261ecSmrg * @param count Number of events.
558305b261ecSmrg * @param events The event list.
558405b261ecSmrg */
55856747b715Smrgvoid
558605b261ecSmrgWriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
558705b261ecSmrg{
558805b261ecSmrg#ifdef PANORAMIX
558905b261ecSmrg    xEvent    eventCopy;
559005b261ecSmrg#endif
55914642e01fSmrg    xEvent    *eventTo, *eventFrom;
55924642e01fSmrg    int       i,
55934642e01fSmrg              eventlength = sizeof(xEvent);
559405b261ecSmrg
55956747b715Smrg    if (!pClient || pClient == serverClient || pClient->clientGone)
559605b261ecSmrg	return;
55976747b715Smrg
55986747b715Smrg    for (i = 0; i < count; i++)
55996747b715Smrg	if ((events[i].u.u.type & 0x7f) != KeymapNotify)
56006747b715Smrg	    events[i].u.u.sequenceNumber = pClient->sequence;
56016747b715Smrg
56026747b715Smrg    /* Let XKB rewrite the state, as it depends on client preferences. */
56036747b715Smrg    XkbFilterEvents(pClient, count, events);
560405b261ecSmrg
560505b261ecSmrg#ifdef PANORAMIX
56064642e01fSmrg    if(!noPanoramiXExtension &&
56076747b715Smrg       (screenInfo.screens[0]->x || screenInfo.screens[0]->y))
560805b261ecSmrg    {
560905b261ecSmrg	switch(events->u.u.type) {
561005b261ecSmrg	case MotionNotify:
561105b261ecSmrg	case ButtonPress:
561205b261ecSmrg	case ButtonRelease:
561305b261ecSmrg	case KeyPress:
561405b261ecSmrg	case KeyRelease:
561505b261ecSmrg	case EnterNotify:
561605b261ecSmrg	case LeaveNotify:
56174642e01fSmrg	/*
561805b261ecSmrg	   When multiple clients want the same event DeliverEventsToWindow
56194642e01fSmrg	   passes the same event structure multiple times so we can't
56204642e01fSmrg	   modify the one passed to us
562105b261ecSmrg        */
562205b261ecSmrg	    count = 1;  /* should always be 1 */
562305b261ecSmrg	    memcpy(&eventCopy, events, sizeof(xEvent));
56246747b715Smrg	    eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x;
56256747b715Smrg	    eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y;
56264642e01fSmrg	    if(eventCopy.u.keyButtonPointer.event ==
56274642e01fSmrg	       eventCopy.u.keyButtonPointer.root)
562805b261ecSmrg	    {
56296747b715Smrg		eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x;
56306747b715Smrg		eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y;
563105b261ecSmrg	    }
563205b261ecSmrg	    events = &eventCopy;
563305b261ecSmrg	    break;
563405b261ecSmrg	default: break;
563505b261ecSmrg	}
563605b261ecSmrg    }
563705b261ecSmrg#endif
563805b261ecSmrg
563905b261ecSmrg    if (EventCallback)
564005b261ecSmrg    {
564105b261ecSmrg	EventInfoRec eventinfo;
564205b261ecSmrg	eventinfo.client = pClient;
564305b261ecSmrg	eventinfo.events = events;
564405b261ecSmrg	eventinfo.count = count;
564505b261ecSmrg	CallCallbacks(&EventCallback, (pointer)&eventinfo);
564605b261ecSmrg    }
564705b261ecSmrg#ifdef XSERVER_DTRACE
564805b261ecSmrg    if (XSERVER_SEND_EVENT_ENABLED()) {
564905b261ecSmrg	for (i = 0; i < count; i++)
565005b261ecSmrg	{
565105b261ecSmrg	    XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]);
565205b261ecSmrg	}
565305b261ecSmrg    }
56544642e01fSmrg#endif
56554642e01fSmrg    /* Just a safety check to make sure we only have one GenericEvent, it just
56564642e01fSmrg     * makes things easier for me right now. (whot) */
56574642e01fSmrg    for (i = 1; i < count; i++)
56584642e01fSmrg    {
56594642e01fSmrg        if (events[i].u.u.type == GenericEvent)
56604642e01fSmrg        {
56614642e01fSmrg            ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n");
56624642e01fSmrg            return;
56634642e01fSmrg        }
56644642e01fSmrg    }
56654642e01fSmrg
56664642e01fSmrg    if (events->u.u.type == GenericEvent)
56674642e01fSmrg    {
56684642e01fSmrg        eventlength += ((xGenericEvent*)events)->length * 4;
56694642e01fSmrg    }
56704642e01fSmrg
567105b261ecSmrg    if(pClient->swapped)
567205b261ecSmrg    {
56734642e01fSmrg        if (eventlength > swapEventLen)
56744642e01fSmrg        {
56754642e01fSmrg            swapEventLen = eventlength;
56766747b715Smrg            swapEvent = realloc(swapEvent, swapEventLen);
56774642e01fSmrg            if (!swapEvent)
56784642e01fSmrg            {
56794642e01fSmrg                FatalError("WriteEventsToClient: Out of memory.\n");
56804642e01fSmrg                return;
56814642e01fSmrg            }
56824642e01fSmrg        }
56834642e01fSmrg
568405b261ecSmrg	for(i = 0; i < count; i++)
568505b261ecSmrg	{
568605b261ecSmrg	    eventFrom = &events[i];
56874642e01fSmrg            eventTo = swapEvent;
56884642e01fSmrg
568905b261ecSmrg	    /* Remember to strip off the leading bit of type in case
569005b261ecSmrg	       this event was sent with "SendEvent." */
569105b261ecSmrg	    (*EventSwapVector[eventFrom->u.u.type & 0177])
56924642e01fSmrg		(eventFrom, eventTo);
56934642e01fSmrg
56946747b715Smrg	    WriteToClient(pClient, eventlength, (char *)eventTo);
569505b261ecSmrg	}
569605b261ecSmrg    }
569705b261ecSmrg    else
569805b261ecSmrg    {
56994642e01fSmrg        /* only one GenericEvent, remember? that means either count is 1 and
57004642e01fSmrg         * eventlength is arbitrary or eventlength is 32 and count doesn't
57014642e01fSmrg         * matter. And we're all set. Woohoo. */
57026747b715Smrg	WriteToClient(pClient, count * eventlength, (char *) events);
570305b261ecSmrg    }
570405b261ecSmrg}
57054642e01fSmrg
57064642e01fSmrg/*
57076747b715Smrg * Set the client pointer for the given client.
57084642e01fSmrg *
57094642e01fSmrg * A client can have exactly one ClientPointer. Each time a
57104642e01fSmrg * request/reply/event is processed and the choice of devices is ambiguous
57114642e01fSmrg * (e.g. QueryPointer request), the server will pick the ClientPointer (see
57124642e01fSmrg * PickPointer()).
57134642e01fSmrg * If a keyboard is needed, the first keyboard paired with the CP is used.
57144642e01fSmrg */
57156747b715Smrgint
57166747b715SmrgSetClientPointer(ClientPtr client, DeviceIntPtr device)
57174642e01fSmrg{
57186747b715Smrg    int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess);
57196747b715Smrg    if (rc != Success)
57206747b715Smrg	return rc;
57216747b715Smrg
57226747b715Smrg    if (!IsMaster(device))
57234642e01fSmrg    {
57244642e01fSmrg        ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n");
57256747b715Smrg        return BadDevice;
57264642e01fSmrg    } else if (!device->spriteInfo->spriteOwner)
57274642e01fSmrg    {
57284642e01fSmrg        ErrorF("[dix] Device %d does not have a sprite. "
57294642e01fSmrg                "Cannot be ClientPointer\n", device->id);
57306747b715Smrg        return BadDevice;
57314642e01fSmrg    }
57324642e01fSmrg    client->clientPtr = device;
57336747b715Smrg    return Success;
57344642e01fSmrg}
57354642e01fSmrg
57364642e01fSmrg/* PickPointer will pick an appropriate pointer for the given client.
57374642e01fSmrg *
57384642e01fSmrg * An "appropriate device" is (in order of priority):
57394642e01fSmrg *  1) A device the given client has a core grab on.
57404642e01fSmrg *  2) A device set as ClientPointer for the given client.
57414642e01fSmrg *  3) The first master device.
57424642e01fSmrg */
57436747b715SmrgDeviceIntPtr
57444642e01fSmrgPickPointer(ClientPtr client)
57454642e01fSmrg{
57464642e01fSmrg    DeviceIntPtr it = inputInfo.devices;
57474642e01fSmrg
57484642e01fSmrg    /* First, check if the client currently has a grab on a device. Even
57494642e01fSmrg     * keyboards count. */
57504642e01fSmrg    for(it = inputInfo.devices; it; it = it->next)
57514642e01fSmrg    {
57524642e01fSmrg        GrabPtr grab = it->deviceGrab.grab;
57536747b715Smrg        if (grab && grab->grabtype == GRABTYPE_CORE && SameClient(grab, client))
57544642e01fSmrg        {
57556747b715Smrg            it = GetMaster(it, MASTER_POINTER);
57564642e01fSmrg            return it; /* Always return a core grabbed device */
57574642e01fSmrg        }
57584642e01fSmrg    }
57594642e01fSmrg
57604642e01fSmrg    if (!client->clientPtr)
57614642e01fSmrg    {
57624642e01fSmrg        DeviceIntPtr it = inputInfo.devices;
57634642e01fSmrg        while (it)
57644642e01fSmrg        {
57656747b715Smrg            if (IsMaster(it) && it->spriteInfo->spriteOwner)
57664642e01fSmrg            {
57674642e01fSmrg                client->clientPtr = it;
57684642e01fSmrg                break;
57694642e01fSmrg            }
57704642e01fSmrg            it = it->next;
57714642e01fSmrg        }
57724642e01fSmrg    }
57734642e01fSmrg    return client->clientPtr;
57744642e01fSmrg}
57754642e01fSmrg
57764642e01fSmrg/* PickKeyboard will pick an appropriate keyboard for the given client by
57774642e01fSmrg * searching the list of devices for the keyboard device that is paired with
57784642e01fSmrg * the client's pointer.
57794642e01fSmrg */
57806747b715SmrgDeviceIntPtr
57814642e01fSmrgPickKeyboard(ClientPtr client)
57824642e01fSmrg{
57834642e01fSmrg    DeviceIntPtr ptr = PickPointer(client);
57846747b715Smrg    DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD);
57854642e01fSmrg
57864642e01fSmrg    if (!kbd)
57874642e01fSmrg    {
57884642e01fSmrg        ErrorF("[dix] ClientPointer not paired with a keyboard. This "
57894642e01fSmrg                "is a bug.\n");
57904642e01fSmrg    }
57914642e01fSmrg
57924642e01fSmrg    return kbd;
57934642e01fSmrg}
57944642e01fSmrg
57954642e01fSmrg/* A client that has one or more core grabs does not get core events from
57964642e01fSmrg * devices it does not have a grab on. Legacy applications behave bad
57974642e01fSmrg * otherwise because they are not used to it and the events interfere.
57984642e01fSmrg * Only applies for core events.
57994642e01fSmrg *
58004642e01fSmrg * Return true if a core event from the device would interfere and should not
58014642e01fSmrg * be delivered.
58024642e01fSmrg */
58034642e01fSmrgBool
58044642e01fSmrgIsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event)
58054642e01fSmrg{
58064642e01fSmrg    DeviceIntPtr it = inputInfo.devices;
58074642e01fSmrg
58084642e01fSmrg    switch(event->u.u.type)
58094642e01fSmrg    {
58104642e01fSmrg        case KeyPress:
58114642e01fSmrg        case KeyRelease:
58124642e01fSmrg        case ButtonPress:
58134642e01fSmrg        case ButtonRelease:
58144642e01fSmrg        case MotionNotify:
58154642e01fSmrg        case EnterNotify:
58164642e01fSmrg        case LeaveNotify:
58174642e01fSmrg            break;
58184642e01fSmrg        default:
58194642e01fSmrg            return FALSE;
58204642e01fSmrg    }
58214642e01fSmrg
58226747b715Smrg    if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
58236747b715Smrg        return FALSE;
58246747b715Smrg
58254642e01fSmrg    while(it)
58264642e01fSmrg    {
58274642e01fSmrg        if (it != dev)
58284642e01fSmrg        {
58294642e01fSmrg            if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client)
58304642e01fSmrg                        && !it->deviceGrab.fromPassiveGrab)
58314642e01fSmrg            {
58324642e01fSmrg                if ((IsPointerDevice(it) && IsPointerDevice(dev)) ||
58334642e01fSmrg                        (IsKeyboardDevice(it) && IsKeyboardDevice(dev)))
58344642e01fSmrg                    return TRUE;
58354642e01fSmrg            }
58364642e01fSmrg        }
58374642e01fSmrg        it = it->next;
58384642e01fSmrg    }
58394642e01fSmrg
58404642e01fSmrg    return FALSE;
58414642e01fSmrg}
58424642e01fSmrg
5843