events.c revision 4642e01f
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
7705b261ecSmrg/*****************************************************************
7805b261ecSmrg
7905b261ecSmrgCopyright 2003-2005 Sun Microsystems, Inc.
8005b261ecSmrg
8105b261ecSmrgAll rights reserved.
8205b261ecSmrg
8305b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a
8405b261ecSmrgcopy of this software and associated documentation files (the
8505b261ecSmrg"Software"), to deal in the Software without restriction, including
8605b261ecSmrgwithout limitation the rights to use, copy, modify, merge, publish,
8705b261ecSmrgdistribute, and/or sell copies of the Software, and to permit persons
8805b261ecSmrgto whom the Software is furnished to do so, provided that the above
8905b261ecSmrgcopyright notice(s) and this permission notice appear in all copies of
9005b261ecSmrgthe Software and that both the above copyright notice(s) and this
9105b261ecSmrgpermission notice appear in supporting documentation.
9205b261ecSmrg
9305b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
9405b261ecSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
9505b261ecSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
9605b261ecSmrgOF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
9705b261ecSmrgHOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
9805b261ecSmrgINDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
9905b261ecSmrgFROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
10005b261ecSmrgNEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
10105b261ecSmrgWITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
10205b261ecSmrg
10305b261ecSmrgExcept as contained in this notice, the name of a copyright holder
10405b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use
10505b261ecSmrgor other dealings in this Software without prior written authorization
10605b261ecSmrgof the copyright holder.
10705b261ecSmrg
10805b261ecSmrg******************************************************************/
10905b261ecSmrg
11005b261ecSmrg/** @file
11105b261ecSmrg * This file handles event delivery and a big part of the server-side protocol
11205b261ecSmrg * handling (the parts for input devices).
11305b261ecSmrg */
11405b261ecSmrg
11505b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
11605b261ecSmrg#include <dix-config.h>
11705b261ecSmrg#endif
11805b261ecSmrg
11905b261ecSmrg#include <X11/X.h>
12005b261ecSmrg#include <X11/keysym.h>
12105b261ecSmrg#include "misc.h"
12205b261ecSmrg#include "resource.h"
12305b261ecSmrg#define NEED_EVENTS
12405b261ecSmrg#define NEED_REPLIES
12505b261ecSmrg#include <X11/Xproto.h>
12605b261ecSmrg#include "windowstr.h"
12705b261ecSmrg#include "inputstr.h"
12805b261ecSmrg#include "scrnintstr.h"
12905b261ecSmrg#include "cursorstr.h"
13005b261ecSmrg
13105b261ecSmrg#include "dixstruct.h"
13205b261ecSmrg#ifdef PANORAMIX
13305b261ecSmrg#include "panoramiX.h"
13405b261ecSmrg#include "panoramiXsrv.h"
13505b261ecSmrg#endif
13605b261ecSmrg#include "globals.h"
13705b261ecSmrg
13805b261ecSmrg#ifdef XKB
13905b261ecSmrg#include <X11/extensions/XKBproto.h>
14005b261ecSmrg#include <xkbsrv.h>
14105b261ecSmrgextern Bool XkbFilterEvents(ClientPtr, int, xEvent *);
14205b261ecSmrg#endif
14305b261ecSmrg
14405b261ecSmrg#include "xace.h"
14505b261ecSmrg
14605b261ecSmrg#ifdef XSERVER_DTRACE
14705b261ecSmrg#include <sys/types.h>
14805b261ecSmrgtypedef const char *string;
14905b261ecSmrg#include "Xserver-dtrace.h"
15005b261ecSmrg#endif
15105b261ecSmrg
15205b261ecSmrg#include <X11/extensions/XIproto.h>
1534642e01fSmrg#include <X11/extensions/XI.h>
15405b261ecSmrg#include "exglobals.h"
15505b261ecSmrg#include "exevents.h"
15605b261ecSmrg#include "exglobals.h"
15705b261ecSmrg#include "extnsionst.h"
15805b261ecSmrg
15905b261ecSmrg#include "dixevents.h"
16005b261ecSmrg#include "dixgrabs.h"
16105b261ecSmrg#include "dispatch.h"
1624642e01fSmrg
1634642e01fSmrg#include <X11/extensions/ge.h>
1644642e01fSmrg#include "geext.h"
1654642e01fSmrg#include "geint.h"
1664642e01fSmrg
1674642e01fSmrg#include "enterleave.h"
1684642e01fSmrg
16905b261ecSmrg/**
17005b261ecSmrg * Extension events type numbering starts at EXTENSION_EVENT_BASE.
17105b261ecSmrg */
17205b261ecSmrg#define NoSuchEvent 0x80000000	/* so doesn't match NoEventMask */
17305b261ecSmrg#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
17405b261ecSmrg#define AllButtonsMask ( \
17505b261ecSmrg	Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
17605b261ecSmrg#define MotionMask ( \
17705b261ecSmrg	PointerMotionMask | Button1MotionMask | \
17805b261ecSmrg	Button2MotionMask | Button3MotionMask | Button4MotionMask | \
17905b261ecSmrg	Button5MotionMask | ButtonMotionMask )
18005b261ecSmrg#define PropagateMask ( \
18105b261ecSmrg	KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
18205b261ecSmrg	MotionMask )
18305b261ecSmrg#define PointerGrabMask ( \
18405b261ecSmrg	ButtonPressMask | ButtonReleaseMask | \
18505b261ecSmrg	EnterWindowMask | LeaveWindowMask | \
18605b261ecSmrg	PointerMotionHintMask | KeymapStateMask | \
18705b261ecSmrg	MotionMask )
18805b261ecSmrg#define AllModifiersMask ( \
18905b261ecSmrg	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
19005b261ecSmrg	Mod3Mask | Mod4Mask | Mod5Mask )
19105b261ecSmrg#define AllEventMasks (lastEventMask|(lastEventMask-1))
1924642e01fSmrg
1934642e01fSmrg/**
1944642e01fSmrg * Used to indicate a implicit passive grab created by a ButtonPress event.
1954642e01fSmrg * See DeliverEventsToWindow().
1964642e01fSmrg */
1974642e01fSmrg#define ImplicitGrabMask (1 << 7)
19805b261ecSmrg/*
19905b261ecSmrg * The following relies on the fact that the Button<n>MotionMasks are equal
20005b261ecSmrg * to the corresponding Button<n>Masks from the current modifier/button state.
20105b261ecSmrg */
20205b261ecSmrg#define Motion_Filter(class) (PointerMotionMask | \
20305b261ecSmrg			      (class)->state | (class)->motionMask)
20405b261ecSmrg
20505b261ecSmrg
20605b261ecSmrg#define WID(w) ((w) ? ((w)->drawable.id) : 0)
20705b261ecSmrg
20805b261ecSmrg#define XE_KBPTR (xE->u.keyButtonPointer)
20905b261ecSmrg
21005b261ecSmrg
21105b261ecSmrg#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
21205b261ecSmrg
21305b261ecSmrg_X_EXPORT CallbackListPtr EventCallback;
21405b261ecSmrg_X_EXPORT CallbackListPtr DeviceEventCallback;
21505b261ecSmrg
21605b261ecSmrg#define DNPMCOUNT 8
21705b261ecSmrg
21805b261ecSmrgMask DontPropagateMasks[DNPMCOUNT];
21905b261ecSmrgstatic int DontPropagateRefCnts[DNPMCOUNT];
22005b261ecSmrg
2214642e01fSmrg
22205b261ecSmrg/**
2234642e01fSmrg * Main input device struct.
2244642e01fSmrg *     inputInfo.pointer
22505b261ecSmrg *     is the core pointer. Referred to as "virtual core pointer", "VCP",
22605b261ecSmrg *     "core pointer" or inputInfo.pointer. There is exactly one core pointer,
2274642e01fSmrg *     but multiple devices may send core events. The VCP is the first master
2284642e01fSmrg *     pointer device and cannot be deleted.
2294642e01fSmrg *
23005b261ecSmrg *     inputInfo.keyboard
23105b261ecSmrg *     is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
23205b261ecSmrg *     See inputInfo.pointer.
2334642e01fSmrg *
23405b261ecSmrg *     inputInfo.devices
2354642e01fSmrg *     linked list containing all devices including VCP and VCK.
23605b261ecSmrg *
23705b261ecSmrg *     inputInfo.off_devices
23805b261ecSmrg *     Devices that have not been initialized and are thus turned off.
23905b261ecSmrg *
24005b261ecSmrg *     inputInfo.numDevices
24105b261ecSmrg *     Total number of devices.
24205b261ecSmrg */
24305b261ecSmrg_X_EXPORT InputInfo inputInfo;
24405b261ecSmrg
2454642e01fSmrg/**
2464642e01fSmrg * syncEvents is the global structure for queued events.
2474642e01fSmrg * Devices can be frozen through GrabModeSync pointer grabs. If this is the
2484642e01fSmrg * case, events from these devices are added to "pending" instead of being
2494642e01fSmrg * processed normally. When the device is unfrozen, events in "pending" are
2504642e01fSmrg * replayed and processed as if they would come from the device directly.
2514642e01fSmrg *
2524642e01fSmrg * pending ... list of queued events
2534642e01fSmrg * pendtail ... last event in list
2544642e01fSmrg * replayDev ... The device to replay events for. Only set in AllowEvents, in
2554642e01fSmrg *               which case it is set to the device specified in the request.
2564642e01fSmrg * replayWin ... the window the events are supposed to be replayed on. This
2574642e01fSmrg *               window may be set to the grab's window (but only when
2584642e01fSmrg *               Replay{Pointer|Keyboard} is given in the XAllowEvents
2594642e01fSmrg *               request.
2604642e01fSmrg * playingEvents ... flag to indicate whether we're in the process of
2614642e01fSmrg *                   replaying events. Only set in ComputeFreezes().
2624642e01fSmrg */
26305b261ecSmrgstatic struct {
26405b261ecSmrg    QdEventPtr		pending, *pendtail;
26505b261ecSmrg    DeviceIntPtr	replayDev;	/* kludgy rock to put flag for */
26605b261ecSmrg    WindowPtr		replayWin;	/*   ComputeFreezes            */
26705b261ecSmrg    Bool		playingEvents;
26805b261ecSmrg    TimeStamp		time;
26905b261ecSmrg} syncEvents;
27005b261ecSmrg
2714642e01fSmrg#define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0]
2724642e01fSmrg
2734642e01fSmrgstatic xEvent* swapEvent = NULL;
2744642e01fSmrgstatic int swapEventLen = 0;
2754642e01fSmrg
2764642e01fSmrg/**
2774642e01fSmrg * Convert the given event type from an XI event to a core event.
2784642e01fSmrg * @return The matching core event type or 0 if there is none.
27905b261ecSmrg */
2804642e01fSmrg_X_EXPORT int
2814642e01fSmrgXItoCoreType(int xitype)
2824642e01fSmrg{
2834642e01fSmrg    int coretype = 0;
2844642e01fSmrg    if (xitype == DeviceMotionNotify)
2854642e01fSmrg        coretype = MotionNotify;
2864642e01fSmrg    else if (xitype == DeviceButtonPress)
2874642e01fSmrg        coretype = ButtonPress;
2884642e01fSmrg    else if (xitype == DeviceButtonRelease)
2894642e01fSmrg        coretype = ButtonRelease;
2904642e01fSmrg    else if (xitype == DeviceKeyPress)
2914642e01fSmrg        coretype = KeyPress;
2924642e01fSmrg    else if (xitype == DeviceKeyRelease)
2934642e01fSmrg        coretype = KeyRelease;
2944642e01fSmrg
2954642e01fSmrg    return coretype;
2964642e01fSmrg}
29705b261ecSmrg
29805b261ecSmrg/**
2994642e01fSmrg * True if device owns a cursor, false if device shares a cursor sprite with
3004642e01fSmrg * another device.
30105b261ecSmrg */
3024642e01fSmrg_X_EXPORT Bool
3034642e01fSmrgDevHasCursor(DeviceIntPtr pDev)
3044642e01fSmrg{
3054642e01fSmrg    return pDev->spriteInfo->spriteOwner;
3064642e01fSmrg}
30705b261ecSmrg
3084642e01fSmrg/*
3094642e01fSmrg * Return true if a device is a pointer, check is the same as used by XI to
3104642e01fSmrg * fill the 'use' field.
3114642e01fSmrg */
3124642e01fSmrg_X_EXPORT Bool
3134642e01fSmrgIsPointerDevice(DeviceIntPtr dev)
3144642e01fSmrg{
3154642e01fSmrg    return (dev->valuator && dev->button);
3164642e01fSmrg}
31705b261ecSmrg
3184642e01fSmrg/*
3194642e01fSmrg * Return true if a device is a keyboard, check is the same as used by XI to
3204642e01fSmrg * fill the 'use' field.
3214642e01fSmrg *
3224642e01fSmrg * Some pointer devices have keys as well (e.g. multimedia keys). Try to not
3234642e01fSmrg * count them as keyboard devices.
3244642e01fSmrg */
3254642e01fSmrg_X_EXPORT Bool
3264642e01fSmrgIsKeyboardDevice(DeviceIntPtr dev)
3274642e01fSmrg{
3284642e01fSmrg    return (dev->key && dev->kbdfeed) && !IsPointerDevice(dev);
3294642e01fSmrg}
33005b261ecSmrg
33105b261ecSmrgstatic WindowPtr XYToWindow(
3324642e01fSmrg    DeviceIntPtr pDev,
33305b261ecSmrg    int x,
33405b261ecSmrg    int y
33505b261ecSmrg);
33605b261ecSmrg
33705b261ecSmrg/**
33805b261ecSmrg * Max event opcode.
33905b261ecSmrg */
34005b261ecSmrgextern int lastEvent;
34105b261ecSmrg
34205b261ecSmrgstatic Mask lastEventMask;
34305b261ecSmrg
34405b261ecSmrgextern int DeviceMotionNotify;
34505b261ecSmrg
3464642e01fSmrg/**
3474642e01fSmrg * Event filters. One set of filters for each device, but only the first layer
3484642e01fSmrg * is initialized. The rest is memcpy'd in InitEvents.
3494642e01fSmrg */
35005b261ecSmrg#define CantBeFiltered NoEventMask
3514642e01fSmrgstatic Mask filters[MAXDEVICES][128] = {
35205b261ecSmrg{
35305b261ecSmrg	NoSuchEvent,		       /* 0 */
35405b261ecSmrg	NoSuchEvent,		       /* 1 */
35505b261ecSmrg	KeyPressMask,		       /* KeyPress */
35605b261ecSmrg	KeyReleaseMask,		       /* KeyRelease */
35705b261ecSmrg	ButtonPressMask,	       /* ButtonPress */
35805b261ecSmrg	ButtonReleaseMask,	       /* ButtonRelease */
35905b261ecSmrg	PointerMotionMask,	       /* MotionNotify (initial state) */
36005b261ecSmrg	EnterWindowMask,	       /* EnterNotify */
36105b261ecSmrg	LeaveWindowMask,	       /* LeaveNotify */
36205b261ecSmrg	FocusChangeMask,	       /* FocusIn */
36305b261ecSmrg	FocusChangeMask,	       /* FocusOut */
36405b261ecSmrg	KeymapStateMask,	       /* KeymapNotify */
36505b261ecSmrg	ExposureMask,		       /* Expose */
36605b261ecSmrg	CantBeFiltered,		       /* GraphicsExpose */
36705b261ecSmrg	CantBeFiltered,		       /* NoExpose */
36805b261ecSmrg	VisibilityChangeMask,	       /* VisibilityNotify */
36905b261ecSmrg	SubstructureNotifyMask,	       /* CreateNotify */
37005b261ecSmrg	StructureAndSubMask,	       /* DestroyNotify */
37105b261ecSmrg	StructureAndSubMask,	       /* UnmapNotify */
37205b261ecSmrg	StructureAndSubMask,	       /* MapNotify */
37305b261ecSmrg	SubstructureRedirectMask,      /* MapRequest */
37405b261ecSmrg	StructureAndSubMask,	       /* ReparentNotify */
37505b261ecSmrg	StructureAndSubMask,	       /* ConfigureNotify */
37605b261ecSmrg	SubstructureRedirectMask,      /* ConfigureRequest */
37705b261ecSmrg	StructureAndSubMask,	       /* GravityNotify */
37805b261ecSmrg	ResizeRedirectMask,	       /* ResizeRequest */
37905b261ecSmrg	StructureAndSubMask,	       /* CirculateNotify */
38005b261ecSmrg	SubstructureRedirectMask,      /* CirculateRequest */
38105b261ecSmrg	PropertyChangeMask,	       /* PropertyNotify */
38205b261ecSmrg	CantBeFiltered,		       /* SelectionClear */
38305b261ecSmrg	CantBeFiltered,		       /* SelectionRequest */
38405b261ecSmrg	CantBeFiltered,		       /* SelectionNotify */
38505b261ecSmrg	ColormapChangeMask,	       /* ColormapNotify */
38605b261ecSmrg	CantBeFiltered,		       /* ClientMessage */
38705b261ecSmrg	CantBeFiltered		       /* MappingNotify */
3884642e01fSmrg}};
3894642e01fSmrg
3904642e01fSmrg
3914642e01fSmrg/**
3924642e01fSmrg * same principle as filters, but one set of filters for each extension.
3934642e01fSmrg * The extension is responsible for setting the filters by calling
3944642e01fSmrg * SetGenericFilter().
3954642e01fSmrg */
3964642e01fSmrgstatic Mask* generic_filters[MAXEXTENSIONS];
39705b261ecSmrg
39805b261ecSmrgstatic CARD8 criticalEvents[32] =
39905b261ecSmrg{
4004642e01fSmrg    0x7c, 0x30, 0x40			/* key, button, expose, and configure events */
40105b261ecSmrg};
40205b261ecSmrg
40305b261ecSmrg#ifdef PANORAMIX
4044642e01fSmrgstatic void PostNewCursor(DeviceIntPtr pDev);
40505b261ecSmrg
4064642e01fSmrg#define SyntheticMotion(dev, x, y) \
4074642e01fSmrg    PostSyntheticMotion(dev, x, y, noPanoramiXExtension ? 0 : \
4084642e01fSmrg                              dev->spriteInfo->sprite->screen->myNum, \
40905b261ecSmrg                        syncEvents.playingEvents ? \
41005b261ecSmrg                          syncEvents.time.milliseconds : \
41105b261ecSmrg                          currentTime.milliseconds);
41205b261ecSmrg
41305b261ecSmrgstatic Bool
41405b261ecSmrgXineramaSetCursorPosition(
4154642e01fSmrg    DeviceIntPtr pDev,
4164642e01fSmrg    int x,
4174642e01fSmrg    int y,
41805b261ecSmrg    Bool generateEvent
41905b261ecSmrg){
42005b261ecSmrg    ScreenPtr pScreen;
42105b261ecSmrg    BoxRec box;
42205b261ecSmrg    int i;
4234642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
42405b261ecSmrg
42505b261ecSmrg    /* x,y are in Screen 0 coordinates.  We need to decide what Screen
4264642e01fSmrg       to send the message too and what the coordinates relative to
42705b261ecSmrg       that screen are. */
42805b261ecSmrg
4294642e01fSmrg    pScreen = pSprite->screen;
43005b261ecSmrg    x += panoramiXdataPtr[0].x;
43105b261ecSmrg    y += panoramiXdataPtr[0].y;
43205b261ecSmrg
43305b261ecSmrg    if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum],
4344642e01fSmrg								x, y, &box))
43505b261ecSmrg    {
4364642e01fSmrg	FOR_NSCREENS(i)
43705b261ecSmrg	{
4384642e01fSmrg	    if(i == pScreen->myNum)
43905b261ecSmrg		continue;
44005b261ecSmrg	    if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box))
44105b261ecSmrg	    {
44205b261ecSmrg		pScreen = screenInfo.screens[i];
44305b261ecSmrg		break;
44405b261ecSmrg	    }
44505b261ecSmrg	}
44605b261ecSmrg    }
44705b261ecSmrg
4484642e01fSmrg    pSprite->screen = pScreen;
4494642e01fSmrg    pSprite->hotPhys.x = x - panoramiXdataPtr[0].x;
4504642e01fSmrg    pSprite->hotPhys.y = y - panoramiXdataPtr[0].y;
45105b261ecSmrg    x -= panoramiXdataPtr[pScreen->myNum].x;
45205b261ecSmrg    y -= panoramiXdataPtr[pScreen->myNum].y;
45305b261ecSmrg
4544642e01fSmrg    return (*pScreen->SetCursorPosition)(pDev, pScreen, x, y, generateEvent);
45505b261ecSmrg}
45605b261ecSmrg
45705b261ecSmrg
45805b261ecSmrgstatic void
4594642e01fSmrgXineramaConstrainCursor(DeviceIntPtr pDev)
46005b261ecSmrg{
4614642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
4624642e01fSmrg    ScreenPtr pScreen;
4634642e01fSmrg    BoxRec newBox;
4644642e01fSmrg
4654642e01fSmrg    pScreen = pSprite->screen;
4664642e01fSmrg    newBox = pSprite->physLimits;
46705b261ecSmrg
46805b261ecSmrg    /* Translate the constraining box to the screen
46905b261ecSmrg       the sprite is actually on */
47005b261ecSmrg    newBox.x1 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x;
47105b261ecSmrg    newBox.x2 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x;
47205b261ecSmrg    newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
47305b261ecSmrg    newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
47405b261ecSmrg
4754642e01fSmrg    (* pScreen->ConstrainCursor)(pDev, pScreen, &newBox);
47605b261ecSmrg}
47705b261ecSmrg
47805b261ecSmrgstatic void
47905b261ecSmrgXineramaCheckPhysLimits(
4804642e01fSmrg    DeviceIntPtr pDev,
48105b261ecSmrg    CursorPtr cursor,
48205b261ecSmrg    Bool generateEvents
48305b261ecSmrg){
48405b261ecSmrg    HotSpot new;
4854642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
48605b261ecSmrg
48705b261ecSmrg    if (!cursor)
48805b261ecSmrg	return;
4894642e01fSmrg
4904642e01fSmrg    new = pSprite->hotPhys;
49105b261ecSmrg
49205b261ecSmrg    /* I don't care what the DDX has to say about it */
4934642e01fSmrg    pSprite->physLimits = pSprite->hotLimits;
49405b261ecSmrg
49505b261ecSmrg    /* constrain the pointer to those limits */
4964642e01fSmrg    if (new.x < pSprite->physLimits.x1)
4974642e01fSmrg	new.x = pSprite->physLimits.x1;
49805b261ecSmrg    else
4994642e01fSmrg	if (new.x >= pSprite->physLimits.x2)
5004642e01fSmrg	    new.x = pSprite->physLimits.x2 - 1;
5014642e01fSmrg    if (new.y < pSprite->physLimits.y1)
5024642e01fSmrg	new.y = pSprite->physLimits.y1;
50305b261ecSmrg    else
5044642e01fSmrg	if (new.y >= pSprite->physLimits.y2)
5054642e01fSmrg	    new.y = pSprite->physLimits.y2 - 1;
50605b261ecSmrg
5074642e01fSmrg    if (pSprite->hotShape)  /* more work if the shape is a mess */
5084642e01fSmrg	ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y);
50905b261ecSmrg
5104642e01fSmrg    if((new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y))
51105b261ecSmrg    {
5124642e01fSmrg	XineramaSetCursorPosition (pDev, new.x, new.y, generateEvents);
51305b261ecSmrg	if (!generateEvents)
5144642e01fSmrg	    SyntheticMotion(pDev, new.x, new.y);
51505b261ecSmrg    }
51605b261ecSmrg
51705b261ecSmrg    /* Tell DDX what the limits are */
5184642e01fSmrg    XineramaConstrainCursor(pDev);
51905b261ecSmrg}
52005b261ecSmrg
52105b261ecSmrg
52205b261ecSmrgstatic Bool
5234642e01fSmrgXineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
52405b261ecSmrg{
5254642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
5264642e01fSmrg
52705b261ecSmrg    if(pWin == WindowTable[0]) {
5284642e01fSmrg	    memcpy(pSprite->windows, WindowTable,
52905b261ecSmrg				PanoramiXNumScreens*sizeof(WindowPtr));
53005b261ecSmrg    } else {
53105b261ecSmrg	PanoramiXRes *win;
53205b261ecSmrg	int i;
53305b261ecSmrg
53405b261ecSmrg	win = (PanoramiXRes*)LookupIDByType(pWin->drawable.id, XRT_WINDOW);
53505b261ecSmrg
53605b261ecSmrg	if(!win)
53705b261ecSmrg	    return FALSE;
53805b261ecSmrg
53905b261ecSmrg	for(i = 0; i < PanoramiXNumScreens; i++) {
5404642e01fSmrg	   pSprite->windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW);
5414642e01fSmrg	   if(!pSprite->windows[i])  /* window is being unmapped */
54205b261ecSmrg		return FALSE;
54305b261ecSmrg	}
54405b261ecSmrg    }
54505b261ecSmrg    return TRUE;
54605b261ecSmrg}
54705b261ecSmrg
54805b261ecSmrgstatic void
54905b261ecSmrgXineramaCheckVirtualMotion(
5504642e01fSmrg   DeviceIntPtr pDev,
55105b261ecSmrg   QdEventPtr qe,
5524642e01fSmrg   WindowPtr pWin)
5534642e01fSmrg{
5544642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
55505b261ecSmrg
55605b261ecSmrg    if (qe)
55705b261ecSmrg    {
5584642e01fSmrg	pSprite->hot.pScreen = qe->pScreen;  /* should always be Screen 0 */
5594642e01fSmrg	pSprite->hot.x = qe->event->u.keyButtonPointer.rootX;
5604642e01fSmrg	pSprite->hot.y = qe->event->u.keyButtonPointer.rootY;
5614642e01fSmrg	pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo :
56205b261ecSmrg					 NullWindow;
56305b261ecSmrg    }
56405b261ecSmrg    if (pWin)
56505b261ecSmrg    {
56605b261ecSmrg	int x, y, off_x, off_y, i;
56705b261ecSmrg	BoxRec lims;
56805b261ecSmrg
5694642e01fSmrg	if(!XineramaSetWindowPntrs(pDev, pWin))
57005b261ecSmrg	    return;
57105b261ecSmrg
57205b261ecSmrg	i = PanoramiXNumScreens - 1;
5734642e01fSmrg
5744642e01fSmrg	REGION_COPY(pSprite->screen, &pSprite->Reg2,
5754642e01fSmrg					&pSprite->windows[i]->borderSize);
57605b261ecSmrg	off_x = panoramiXdataPtr[i].x;
57705b261ecSmrg	off_y = panoramiXdataPtr[i].y;
57805b261ecSmrg
57905b261ecSmrg	while(i--) {
58005b261ecSmrg	    x = off_x - panoramiXdataPtr[i].x;
58105b261ecSmrg	    y = off_y - panoramiXdataPtr[i].y;
58205b261ecSmrg
58305b261ecSmrg	    if(x || y)
5844642e01fSmrg		REGION_TRANSLATE(pSprite->screen, &pSprite->Reg2, x, y);
5854642e01fSmrg
5864642e01fSmrg	    REGION_UNION(pSprite->screen, &pSprite->Reg2, &pSprite->Reg2,
5874642e01fSmrg					&pSprite->windows[i]->borderSize);
58805b261ecSmrg
58905b261ecSmrg	    off_x = panoramiXdataPtr[i].x;
59005b261ecSmrg	    off_y = panoramiXdataPtr[i].y;
59105b261ecSmrg	}
59205b261ecSmrg
5934642e01fSmrg	lims = *REGION_EXTENTS(pSprite->screen, &pSprite->Reg2);
59405b261ecSmrg
5954642e01fSmrg        if (pSprite->hot.x < lims.x1)
5964642e01fSmrg            pSprite->hot.x = lims.x1;
5974642e01fSmrg        else if (pSprite->hot.x >= lims.x2)
5984642e01fSmrg            pSprite->hot.x = lims.x2 - 1;
5994642e01fSmrg        if (pSprite->hot.y < lims.y1)
6004642e01fSmrg            pSprite->hot.y = lims.y1;
6014642e01fSmrg        else if (pSprite->hot.y >= lims.y2)
6024642e01fSmrg            pSprite->hot.y = lims.y2 - 1;
60305b261ecSmrg
6044642e01fSmrg	if (REGION_NUM_RECTS(&pSprite->Reg2) > 1)
6054642e01fSmrg	    ConfineToShape(pDev, &pSprite->Reg2,
6064642e01fSmrg                    &pSprite->hot.x, &pSprite->hot.y);
60705b261ecSmrg
60805b261ecSmrg	if (qe)
60905b261ecSmrg	{
6104642e01fSmrg	    qe->pScreen = pSprite->hot.pScreen;
6114642e01fSmrg	    qe->event->u.keyButtonPointer.rootX = pSprite->hot.x;
6124642e01fSmrg	    qe->event->u.keyButtonPointer.rootY = pSprite->hot.y;
61305b261ecSmrg	}
61405b261ecSmrg    }
61505b261ecSmrg}
61605b261ecSmrg
61705b261ecSmrg
61805b261ecSmrgstatic Bool
6194642e01fSmrgXineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev)
62005b261ecSmrg{
6214642e01fSmrg    WindowPtr prevSpriteWin;
6224642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
6234642e01fSmrg
6244642e01fSmrg    prevSpriteWin = pSprite->win;
62505b261ecSmrg
62605b261ecSmrg    if (xE && !syncEvents.playingEvents)
62705b261ecSmrg    {
6284642e01fSmrg        /* GetPointerEvents() guarantees that pointer events have the correct
6294642e01fSmrg           rootX/Y set already. */
6304642e01fSmrg        switch(xE->u.u.type)
6314642e01fSmrg        {
6324642e01fSmrg            case ButtonPress:
6334642e01fSmrg            case ButtonRelease:
6344642e01fSmrg            case MotionNotify:
6354642e01fSmrg                break;
6364642e01fSmrg            default:
6374642e01fSmrg                if (xE->u.u.type == DeviceButtonPress ||
6384642e01fSmrg                        xE->u.u.type == DeviceButtonRelease ||
6394642e01fSmrg                        xE->u.u.type == DeviceMotionNotify)
6404642e01fSmrg                    break;
6414642e01fSmrg                /* all other events return FALSE */
6424642e01fSmrg                return FALSE;
6434642e01fSmrg        }
6444642e01fSmrg
64505b261ecSmrg	/* Motion events entering DIX get translated to Screen 0
6464642e01fSmrg	   coordinates.  Replayed events have already been
64705b261ecSmrg	   translated since they've entered DIX before */
6484642e01fSmrg	XE_KBPTR.rootX += panoramiXdataPtr[pSprite->screen->myNum].x -
64905b261ecSmrg			  panoramiXdataPtr[0].x;
6504642e01fSmrg	XE_KBPTR.rootY += panoramiXdataPtr[pSprite->screen->myNum].y -
65105b261ecSmrg			  panoramiXdataPtr[0].y;
6524642e01fSmrg	pSprite->hot.x = XE_KBPTR.rootX;
6534642e01fSmrg	pSprite->hot.y = XE_KBPTR.rootY;
6544642e01fSmrg	if (pSprite->hot.x < pSprite->physLimits.x1)
6554642e01fSmrg	    pSprite->hot.x = pSprite->physLimits.x1;
6564642e01fSmrg	else if (pSprite->hot.x >= pSprite->physLimits.x2)
6574642e01fSmrg	    pSprite->hot.x = pSprite->physLimits.x2 - 1;
6584642e01fSmrg	if (pSprite->hot.y < pSprite->physLimits.y1)
6594642e01fSmrg	    pSprite->hot.y = pSprite->physLimits.y1;
6604642e01fSmrg	else if (pSprite->hot.y >= pSprite->physLimits.y2)
6614642e01fSmrg	    pSprite->hot.y = pSprite->physLimits.y2 - 1;
6624642e01fSmrg
6634642e01fSmrg	if (pSprite->hotShape)
6644642e01fSmrg	    ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y);
6654642e01fSmrg
6664642e01fSmrg	pSprite->hotPhys = pSprite->hot;
6674642e01fSmrg	if ((pSprite->hotPhys.x != XE_KBPTR.rootX) ||
6684642e01fSmrg	    (pSprite->hotPhys.y != XE_KBPTR.rootY))
66905b261ecSmrg	{
67005b261ecSmrg	    XineramaSetCursorPosition(
6714642e01fSmrg			pDev, pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
67205b261ecSmrg	}
6734642e01fSmrg	XE_KBPTR.rootX = pSprite->hot.x;
6744642e01fSmrg	XE_KBPTR.rootY = pSprite->hot.y;
67505b261ecSmrg    }
67605b261ecSmrg
6774642e01fSmrg    pSprite->win = XYToWindow(pDev, pSprite->hot.x, pSprite->hot.y);
67805b261ecSmrg
6794642e01fSmrg    if (pSprite->win != prevSpriteWin)
68005b261ecSmrg    {
68105b261ecSmrg	if (prevSpriteWin != NullWindow) {
68205b261ecSmrg	    if (!xE)
68305b261ecSmrg		UpdateCurrentTimeIf();
6844642e01fSmrg            DoEnterLeaveEvents(pDev, prevSpriteWin, pSprite->win,
6854642e01fSmrg                               NotifyNormal);
6864642e01fSmrg        }
6874642e01fSmrg	PostNewCursor(pDev);
68805b261ecSmrg        return FALSE;
68905b261ecSmrg    }
69005b261ecSmrg    return TRUE;
69105b261ecSmrg}
69205b261ecSmrg
69305b261ecSmrg
69405b261ecSmrgstatic void
6954642e01fSmrgXineramaConfineCursorToWindow(DeviceIntPtr pDev,
6964642e01fSmrg                              WindowPtr pWin,
6974642e01fSmrg                              Bool generateEvents)
69805b261ecSmrg{
6994642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
70005b261ecSmrg
70105b261ecSmrg    if (syncEvents.playingEvents)
70205b261ecSmrg    {
7034642e01fSmrg	XineramaCheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin);
7044642e01fSmrg	SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y);
70505b261ecSmrg    }
70605b261ecSmrg    else
70705b261ecSmrg    {
70805b261ecSmrg	int x, y, off_x, off_y, i;
70905b261ecSmrg
7104642e01fSmrg	if(!XineramaSetWindowPntrs(pDev, pWin))
71105b261ecSmrg	    return;
71205b261ecSmrg
71305b261ecSmrg	i = PanoramiXNumScreens - 1;
7144642e01fSmrg
7154642e01fSmrg	REGION_COPY(pSprite->screen, &pSprite->Reg1,
7164642e01fSmrg					&pSprite->windows[i]->borderSize);
71705b261ecSmrg	off_x = panoramiXdataPtr[i].x;
71805b261ecSmrg	off_y = panoramiXdataPtr[i].y;
71905b261ecSmrg
72005b261ecSmrg	while(i--) {
72105b261ecSmrg	    x = off_x - panoramiXdataPtr[i].x;
72205b261ecSmrg	    y = off_y - panoramiXdataPtr[i].y;
72305b261ecSmrg
72405b261ecSmrg	    if(x || y)
7254642e01fSmrg		REGION_TRANSLATE(pSprite->screen, &pSprite->Reg1, x, y);
7264642e01fSmrg
7274642e01fSmrg	    REGION_UNION(pSprite->screen, &pSprite->Reg1, &pSprite->Reg1,
7284642e01fSmrg					&pSprite->windows[i]->borderSize);
72905b261ecSmrg
73005b261ecSmrg	    off_x = panoramiXdataPtr[i].x;
73105b261ecSmrg	    off_y = panoramiXdataPtr[i].y;
73205b261ecSmrg	}
73305b261ecSmrg
7344642e01fSmrg	pSprite->hotLimits = *REGION_EXTENTS(pSprite->screen, &pSprite->Reg1);
73505b261ecSmrg
7364642e01fSmrg	if(REGION_NUM_RECTS(&pSprite->Reg1) > 1)
7374642e01fSmrg	   pSprite->hotShape = &pSprite->Reg1;
73805b261ecSmrg	else
7394642e01fSmrg	   pSprite->hotShape = NullRegion;
74005b261ecSmrg
7414642e01fSmrg	pSprite->confined = FALSE;
7424642e01fSmrg	pSprite->confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin;
7434642e01fSmrg
7444642e01fSmrg        XineramaCheckPhysLimits(pDev, pSprite->current,
7454642e01fSmrg                                generateEvents);
74605b261ecSmrg    }
74705b261ecSmrg}
74805b261ecSmrg
74905b261ecSmrg
75005b261ecSmrgstatic void
7514642e01fSmrgXineramaChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
75205b261ecSmrg{
7534642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
7544642e01fSmrg
7554642e01fSmrg    if (cursor != pSprite->current)
75605b261ecSmrg    {
7574642e01fSmrg	if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
7584642e01fSmrg		(pSprite->current->bits->yhot != cursor->bits->yhot))
7594642e01fSmrg	    XineramaCheckPhysLimits(pDev, cursor, FALSE);
7604642e01fSmrg	(*pSprite->screen->DisplayCursor)(pDev, pSprite->screen, cursor);
7614642e01fSmrg	FreeCursor(pSprite->current, (Cursor)0);
7624642e01fSmrg	pSprite->current = cursor;
7634642e01fSmrg	pSprite->current->refcnt++;
76405b261ecSmrg    }
76505b261ecSmrg}
76605b261ecSmrg
76705b261ecSmrg#else
7684642e01fSmrg#define SyntheticMotion(dev, x, y) \
7694642e01fSmrg     PostSyntheticMotion(dev, x, y, \
77005b261ecSmrg                         0, \
77105b261ecSmrg                         syncEvents.playingEvents ? \
77205b261ecSmrg                           syncEvents.time.milliseconds : \
77305b261ecSmrg                           currentTime.milliseconds);
77405b261ecSmrg
77505b261ecSmrg#endif  /* PANORAMIX */
77605b261ecSmrg
77705b261ecSmrgvoid
7784642e01fSmrgSetMaskForEvent(int deviceid, Mask mask, int event)
77905b261ecSmrg{
7804642e01fSmrg    int coretype;
7814642e01fSmrg    if (deviceid < 0 || deviceid > MAXDEVICES)
7824642e01fSmrg        FatalError("SetMaskForEvent: bogus device id");
78305b261ecSmrg    if ((event < LASTEvent) || (event >= 128))
78405b261ecSmrg	FatalError("SetMaskForEvent: bogus event number");
7854642e01fSmrg    filters[deviceid][event] = mask;
7864642e01fSmrg
7874642e01fSmrg    /* Need to change the mask for the core events too */
7884642e01fSmrg    coretype = XItoCoreType(event);
7894642e01fSmrg    if (coretype)
7904642e01fSmrg        filters[deviceid][coretype] = mask;
79105b261ecSmrg}
79205b261ecSmrg
79305b261ecSmrg_X_EXPORT void
79405b261ecSmrgSetCriticalEvent(int event)
79505b261ecSmrg{
79605b261ecSmrg    if (event >= 128)
79705b261ecSmrg	FatalError("SetCriticalEvent: bogus event number");
79805b261ecSmrg    criticalEvents[event >> 3] |= 1 << (event & 7);
79905b261ecSmrg}
80005b261ecSmrg
8014642e01fSmrgvoid
8024642e01fSmrgConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
80305b261ecSmrg{
80405b261ecSmrg    BoxRec box;
80505b261ecSmrg    int x = *px, y = *py;
80605b261ecSmrg    int incx = 1, incy = 1;
8074642e01fSmrg    SpritePtr pSprite;
80805b261ecSmrg
8094642e01fSmrg    pSprite = pDev->spriteInfo->sprite;
8104642e01fSmrg    if (POINT_IN_REGION(pSprite->hot.pScreen, shape, x, y, &box))
81105b261ecSmrg	return;
8124642e01fSmrg    box = *REGION_EXTENTS(pSprite->hot.pScreen, shape);
81305b261ecSmrg    /* this is rather crude */
81405b261ecSmrg    do {
81505b261ecSmrg	x += incx;
81605b261ecSmrg	if (x >= box.x2)
81705b261ecSmrg	{
81805b261ecSmrg	    incx = -1;
81905b261ecSmrg	    x = *px - 1;
82005b261ecSmrg	}
82105b261ecSmrg	else if (x < box.x1)
82205b261ecSmrg	{
82305b261ecSmrg	    incx = 1;
82405b261ecSmrg	    x = *px;
82505b261ecSmrg	    y += incy;
82605b261ecSmrg	    if (y >= box.y2)
82705b261ecSmrg	    {
82805b261ecSmrg		incy = -1;
82905b261ecSmrg		y = *py - 1;
83005b261ecSmrg	    }
83105b261ecSmrg	    else if (y < box.y1)
83205b261ecSmrg		return; /* should never get here! */
83305b261ecSmrg	}
8344642e01fSmrg    } while (!POINT_IN_REGION(pSprite->hot.pScreen, shape, x, y, &box));
83505b261ecSmrg    *px = x;
83605b261ecSmrg    *py = y;
83705b261ecSmrg}
83805b261ecSmrg
83905b261ecSmrgstatic void
84005b261ecSmrgCheckPhysLimits(
8414642e01fSmrg    DeviceIntPtr pDev,
84205b261ecSmrg    CursorPtr cursor,
84305b261ecSmrg    Bool generateEvents,
84405b261ecSmrg    Bool confineToScreen,
84505b261ecSmrg    ScreenPtr pScreen)
84605b261ecSmrg{
84705b261ecSmrg    HotSpot new;
8484642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
84905b261ecSmrg
85005b261ecSmrg    if (!cursor)
85105b261ecSmrg	return;
8524642e01fSmrg    new = pSprite->hotPhys;
85305b261ecSmrg    if (pScreen)
85405b261ecSmrg	new.pScreen = pScreen;
85505b261ecSmrg    else
85605b261ecSmrg	pScreen = new.pScreen;
8574642e01fSmrg    (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits,
8584642e01fSmrg			      &pSprite->physLimits);
8594642e01fSmrg    pSprite->confined = confineToScreen;
8604642e01fSmrg    (* pScreen->ConstrainCursor)(pDev, pScreen, &pSprite->physLimits);
8614642e01fSmrg    if (new.x < pSprite->physLimits.x1)
8624642e01fSmrg	new.x = pSprite->physLimits.x1;
86305b261ecSmrg    else
8644642e01fSmrg	if (new.x >= pSprite->physLimits.x2)
8654642e01fSmrg	    new.x = pSprite->physLimits.x2 - 1;
8664642e01fSmrg    if (new.y < pSprite->physLimits.y1)
8674642e01fSmrg	new.y = pSprite->physLimits.y1;
86805b261ecSmrg    else
8694642e01fSmrg	if (new.y >= pSprite->physLimits.y2)
8704642e01fSmrg	    new.y = pSprite->physLimits.y2 - 1;
8714642e01fSmrg    if (pSprite->hotShape)
8724642e01fSmrg	ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y);
8734642e01fSmrg    if ((pScreen != pSprite->hotPhys.pScreen) ||
8744642e01fSmrg	(new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y))
8754642e01fSmrg    {
8764642e01fSmrg	if (pScreen != pSprite->hotPhys.pScreen)
8774642e01fSmrg	    pSprite->hotPhys = new;
8784642e01fSmrg        (*pScreen->SetCursorPosition)
8794642e01fSmrg            (pDev, pScreen, new.x, new.y, generateEvents);
8804642e01fSmrg        if (!generateEvents)
8814642e01fSmrg	    SyntheticMotion(pDev, new.x, new.y);
88205b261ecSmrg    }
88305b261ecSmrg}
88405b261ecSmrg
88505b261ecSmrgstatic void
88605b261ecSmrgCheckVirtualMotion(
8874642e01fSmrg    DeviceIntPtr pDev,
88805b261ecSmrg    QdEventPtr qe,
88905b261ecSmrg    WindowPtr pWin)
89005b261ecSmrg{
8914642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
8924642e01fSmrg
89305b261ecSmrg#ifdef PANORAMIX
89405b261ecSmrg    if(!noPanoramiXExtension) {
8954642e01fSmrg	XineramaCheckVirtualMotion(pDev, qe, pWin);
89605b261ecSmrg	return;
89705b261ecSmrg    }
89805b261ecSmrg#endif
89905b261ecSmrg    if (qe)
90005b261ecSmrg    {
9014642e01fSmrg	pSprite->hot.pScreen = qe->pScreen;
9024642e01fSmrg	pSprite->hot.x = qe->event->u.keyButtonPointer.rootX;
9034642e01fSmrg	pSprite->hot.y = qe->event->u.keyButtonPointer.rootY;
9044642e01fSmrg	pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo : NullWindow;
90505b261ecSmrg    }
90605b261ecSmrg    if (pWin)
90705b261ecSmrg    {
90805b261ecSmrg	BoxRec lims;
90905b261ecSmrg
9104642e01fSmrg	if (pSprite->hot.pScreen != pWin->drawable.pScreen)
91105b261ecSmrg	{
9124642e01fSmrg	    pSprite->hot.pScreen = pWin->drawable.pScreen;
9134642e01fSmrg	    pSprite->hot.x = pSprite->hot.y = 0;
91405b261ecSmrg	}
91505b261ecSmrg	lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize);
9164642e01fSmrg	if (pSprite->hot.x < lims.x1)
9174642e01fSmrg	    pSprite->hot.x = lims.x1;
9184642e01fSmrg	else if (pSprite->hot.x >= lims.x2)
9194642e01fSmrg	    pSprite->hot.x = lims.x2 - 1;
9204642e01fSmrg	if (pSprite->hot.y < lims.y1)
9214642e01fSmrg	    pSprite->hot.y = lims.y1;
9224642e01fSmrg	else if (pSprite->hot.y >= lims.y2)
9234642e01fSmrg	    pSprite->hot.y = lims.y2 - 1;
92405b261ecSmrg	if (wBoundingShape(pWin))
9254642e01fSmrg	    ConfineToShape(pDev, &pWin->borderSize,
9264642e01fSmrg                    &pSprite->hot.x, &pSprite->hot.y);
92705b261ecSmrg	if (qe)
92805b261ecSmrg	{
9294642e01fSmrg	    qe->pScreen = pSprite->hot.pScreen;
9304642e01fSmrg	    qe->event->u.keyButtonPointer.rootX = pSprite->hot.x;
9314642e01fSmrg	    qe->event->u.keyButtonPointer.rootY = pSprite->hot.y;
93205b261ecSmrg	}
93305b261ecSmrg    }
9344642e01fSmrg    RootWindow(pDev) = WindowTable[pSprite->hot.pScreen->myNum];
93505b261ecSmrg}
93605b261ecSmrg
93705b261ecSmrgstatic void
9384642e01fSmrgConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
93905b261ecSmrg{
94005b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
9414642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
94205b261ecSmrg
94305b261ecSmrg#ifdef PANORAMIX
94405b261ecSmrg    if(!noPanoramiXExtension) {
9454642e01fSmrg	XineramaConfineCursorToWindow(pDev, pWin, generateEvents);
94605b261ecSmrg	return;
9474642e01fSmrg    }
94805b261ecSmrg#endif
94905b261ecSmrg
95005b261ecSmrg    if (syncEvents.playingEvents)
95105b261ecSmrg    {
9524642e01fSmrg	CheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin);
9534642e01fSmrg	SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y);
95405b261ecSmrg    }
95505b261ecSmrg    else
95605b261ecSmrg    {
9574642e01fSmrg	pSprite->hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize);
9584642e01fSmrg	pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize
95905b261ecSmrg					       : NullRegion;
9604642e01fSmrg        CheckPhysLimits(pDev, pSprite->current, generateEvents,
9614642e01fSmrg                        confineToScreen, pScreen);
96205b261ecSmrg    }
96305b261ecSmrg}
96405b261ecSmrg
96505b261ecSmrg_X_EXPORT Bool
9664642e01fSmrgPointerConfinedToScreen(DeviceIntPtr pDev)
96705b261ecSmrg{
9684642e01fSmrg    return pDev->spriteInfo->sprite->confined;
96905b261ecSmrg}
97005b261ecSmrg
97105b261ecSmrg/**
97205b261ecSmrg * Update the sprite cursor to the given cursor.
97305b261ecSmrg *
97405b261ecSmrg * ChangeToCursor() will display the new cursor and free the old cursor (if
97505b261ecSmrg * applicable). If the provided cursor is already the updated cursor, nothing
97605b261ecSmrg * happens.
97705b261ecSmrg */
97805b261ecSmrgstatic void
9794642e01fSmrgChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
98005b261ecSmrg{
9814642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
9824642e01fSmrg
98305b261ecSmrg#ifdef PANORAMIX
98405b261ecSmrg    if(!noPanoramiXExtension) {
9854642e01fSmrg	XineramaChangeToCursor(pDev, cursor);
98605b261ecSmrg	return;
98705b261ecSmrg    }
98805b261ecSmrg#endif
98905b261ecSmrg
9904642e01fSmrg    if (cursor != pSprite->current)
99105b261ecSmrg    {
9924642e01fSmrg	if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
9934642e01fSmrg		(pSprite->current->bits->yhot != cursor->bits->yhot))
9944642e01fSmrg	    CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined,
99505b261ecSmrg			    (ScreenPtr)NULL);
9964642e01fSmrg        (*pSprite->hotPhys.pScreen->DisplayCursor) (pDev,
9974642e01fSmrg                                                   pSprite->hotPhys.pScreen,
9984642e01fSmrg                                                   cursor);
9994642e01fSmrg	FreeCursor(pSprite->current, (Cursor)0);
10004642e01fSmrg	pSprite->current = cursor;
10014642e01fSmrg	pSprite->current->refcnt++;
100205b261ecSmrg    }
100305b261ecSmrg}
100405b261ecSmrg
100505b261ecSmrg/**
10064642e01fSmrg * @returns true if b is a descendent of a
100705b261ecSmrg */
100805b261ecSmrgBool
100905b261ecSmrgIsParent(WindowPtr a, WindowPtr b)
101005b261ecSmrg{
101105b261ecSmrg    for (b = b->parent; b; b = b->parent)
101205b261ecSmrg	if (b == a) return TRUE;
101305b261ecSmrg    return FALSE;
101405b261ecSmrg}
101505b261ecSmrg
101605b261ecSmrg/**
101705b261ecSmrg * Update the cursor displayed on the screen.
101805b261ecSmrg *
10194642e01fSmrg * Called whenever a cursor may have changed shape or position.
102005b261ecSmrg */
102105b261ecSmrgstatic void
10224642e01fSmrgPostNewCursor(DeviceIntPtr pDev)
102305b261ecSmrg{
102405b261ecSmrg    WindowPtr win;
10254642e01fSmrg    GrabPtr grab = pDev->deviceGrab.grab;
10264642e01fSmrg    SpritePtr   pSprite = pDev->spriteInfo->sprite;
10274642e01fSmrg    CursorPtr   pCursor;
102805b261ecSmrg
102905b261ecSmrg    if (syncEvents.playingEvents)
103005b261ecSmrg	return;
103105b261ecSmrg    if (grab)
103205b261ecSmrg    {
103305b261ecSmrg	if (grab->cursor)
103405b261ecSmrg	{
10354642e01fSmrg	    ChangeToCursor(pDev, grab->cursor);
103605b261ecSmrg	    return;
103705b261ecSmrg	}
10384642e01fSmrg	if (IsParent(grab->window, pSprite->win))
10394642e01fSmrg	    win = pSprite->win;
104005b261ecSmrg	else
104105b261ecSmrg	    win = grab->window;
104205b261ecSmrg    }
104305b261ecSmrg    else
10444642e01fSmrg	win = pSprite->win;
104505b261ecSmrg    for (; win; win = win->parent)
10464642e01fSmrg    {
10474642e01fSmrg	if (win->optional)
10484642e01fSmrg        {
10494642e01fSmrg            pCursor = WindowGetDeviceCursor(win, pDev);
10504642e01fSmrg            if (!pCursor && win->optional->cursor != NullCursor)
10514642e01fSmrg                pCursor = win->optional->cursor;
10524642e01fSmrg            if (pCursor)
10534642e01fSmrg            {
10544642e01fSmrg                ChangeToCursor(pDev, pCursor);
10554642e01fSmrg                return;
10564642e01fSmrg            }
105705b261ecSmrg	}
10584642e01fSmrg    }
105905b261ecSmrg}
106005b261ecSmrg
10614642e01fSmrg
106205b261ecSmrg/**
10634642e01fSmrg * @param dev device which you want to know its current root window
10644642e01fSmrg * @return root window where dev's sprite is located
106505b261ecSmrg */
106605b261ecSmrg_X_EXPORT WindowPtr
10674642e01fSmrgGetCurrentRootWindow(DeviceIntPtr dev)
106805b261ecSmrg{
10694642e01fSmrg    return RootWindow(dev);
107005b261ecSmrg}
107105b261ecSmrg
107205b261ecSmrg/**
107305b261ecSmrg * @return window underneath the cursor sprite.
107405b261ecSmrg */
107505b261ecSmrg_X_EXPORT WindowPtr
10764642e01fSmrgGetSpriteWindow(DeviceIntPtr pDev)
107705b261ecSmrg{
10784642e01fSmrg    return pDev->spriteInfo->sprite->win;
107905b261ecSmrg}
108005b261ecSmrg
108105b261ecSmrg/**
108205b261ecSmrg * @return current sprite cursor.
108305b261ecSmrg */
108405b261ecSmrg_X_EXPORT CursorPtr
10854642e01fSmrgGetSpriteCursor(DeviceIntPtr pDev)
108605b261ecSmrg{
10874642e01fSmrg    return pDev->spriteInfo->sprite->current;
108805b261ecSmrg}
108905b261ecSmrg
109005b261ecSmrg/**
109105b261ecSmrg * Set x/y current sprite position in screen coordinates.
109205b261ecSmrg */
109305b261ecSmrg_X_EXPORT void
10944642e01fSmrgGetSpritePosition(DeviceIntPtr pDev, int *px, int *py)
109505b261ecSmrg{
10964642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
10974642e01fSmrg    *px = pSprite->hotPhys.x;
10984642e01fSmrg    *py = pSprite->hotPhys.y;
109905b261ecSmrg}
110005b261ecSmrg
110105b261ecSmrg#ifdef PANORAMIX
110205b261ecSmrg_X_EXPORT int
11034642e01fSmrgXineramaGetCursorScreen(DeviceIntPtr pDev)
110405b261ecSmrg{
110505b261ecSmrg    if(!noPanoramiXExtension) {
11064642e01fSmrg	return pDev->spriteInfo->sprite->screen->myNum;
110705b261ecSmrg    } else {
110805b261ecSmrg	return 0;
110905b261ecSmrg    }
111005b261ecSmrg}
111105b261ecSmrg#endif /* PANORAMIX */
111205b261ecSmrg
111305b261ecSmrg#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */
111405b261ecSmrg
111505b261ecSmrgstatic void
111605b261ecSmrgMonthChangedOrBadTime(xEvent *xE)
111705b261ecSmrg{
111805b261ecSmrg    /* If the ddx/OS is careless about not processing timestamped events from
111905b261ecSmrg     * different sources in sorted order, then it's possible for time to go
112005b261ecSmrg     * backwards when it should not.  Here we ensure a decent time.
112105b261ecSmrg     */
112205b261ecSmrg    if ((currentTime.milliseconds - XE_KBPTR.time) > TIMESLOP)
112305b261ecSmrg	currentTime.months++;
112405b261ecSmrg    else
112505b261ecSmrg	XE_KBPTR.time = currentTime.milliseconds;
112605b261ecSmrg}
112705b261ecSmrg
112805b261ecSmrg#define NoticeTime(xE) { \
112905b261ecSmrg    if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \
113005b261ecSmrg	MonthChangedOrBadTime(xE); \
113105b261ecSmrg    currentTime.milliseconds = (xE)->u.keyButtonPointer.time; \
113205b261ecSmrg    lastDeviceEventTime = currentTime; }
113305b261ecSmrg
113405b261ecSmrgvoid
113505b261ecSmrgNoticeEventTime(xEvent *xE)
113605b261ecSmrg{
113705b261ecSmrg    if (!syncEvents.playingEvents)
113805b261ecSmrg	NoticeTime(xE);
113905b261ecSmrg}
114005b261ecSmrg
114105b261ecSmrg/**************************************************************************
114205b261ecSmrg *            The following procedures deal with synchronous events       *
114305b261ecSmrg **************************************************************************/
114405b261ecSmrg
11454642e01fSmrg/**
11464642e01fSmrg * EnqueueEvent is a device's processInputProc if a device is frozen.
11474642e01fSmrg * Instead of delivering the events to the client, the event is tacked onto a
11484642e01fSmrg * linked list for later delivery.
11494642e01fSmrg */
115005b261ecSmrgvoid
115105b261ecSmrgEnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
115205b261ecSmrg{
11534642e01fSmrg    QdEventPtr	tail = *syncEvents.pendtail;
11544642e01fSmrg    QdEventPtr	qe;
11554642e01fSmrg    SpritePtr	pSprite = device->spriteInfo->sprite;
11564642e01fSmrg    int		eventlen;
11574642e01fSmrg
115805b261ecSmrg
115905b261ecSmrg    NoticeTime(xE);
116005b261ecSmrg
116105b261ecSmrg#ifdef XKB
116205b261ecSmrg    /* Fix for key repeating bug. */
11634642e01fSmrg    if (device->key != NULL && device->key->xkbInfo != NULL &&
116405b261ecSmrg	xE->u.u.type == KeyRelease)
116505b261ecSmrg	AccessXCancelRepeatKey(device->key->xkbInfo, xE->u.u.detail);
116605b261ecSmrg#endif
116705b261ecSmrg
116805b261ecSmrg    if (DeviceEventCallback)
116905b261ecSmrg    {
117005b261ecSmrg	DeviceEventInfoRec eventinfo;
117105b261ecSmrg	/*  The RECORD spec says that the root window field of motion events
117205b261ecSmrg	 *  must be valid.  At this point, it hasn't been filled in yet, so
117305b261ecSmrg	 *  we do it here.  The long expression below is necessary to get
117405b261ecSmrg	 *  the current root window; the apparently reasonable alternative
117505b261ecSmrg	 *  GetCurrentRootWindow()->drawable.id doesn't give you the right
117605b261ecSmrg	 *  answer on the first motion event after a screen change because
117705b261ecSmrg	 *  the data that GetCurrentRootWindow relies on hasn't been
117805b261ecSmrg	 *  updated yet.
117905b261ecSmrg	 */
11804642e01fSmrg	if (xE->u.u.type == DeviceMotionNotify)
118105b261ecSmrg	    XE_KBPTR.root =
11824642e01fSmrg		WindowTable[pSprite->hotPhys.pScreen->myNum]->drawable.id;
118305b261ecSmrg	eventinfo.events = xE;
118405b261ecSmrg	eventinfo.count = count;
118505b261ecSmrg	CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
118605b261ecSmrg    }
11874642e01fSmrg    if (xE->u.u.type == DeviceMotionNotify)
118805b261ecSmrg    {
118905b261ecSmrg#ifdef PANORAMIX
119005b261ecSmrg	if(!noPanoramiXExtension) {
11914642e01fSmrg	    XE_KBPTR.rootX += panoramiXdataPtr[pSprite->screen->myNum].x -
119205b261ecSmrg			      panoramiXdataPtr[0].x;
11934642e01fSmrg	    XE_KBPTR.rootY += panoramiXdataPtr[pSprite->screen->myNum].y -
119405b261ecSmrg			      panoramiXdataPtr[0].y;
119505b261ecSmrg	}
119605b261ecSmrg#endif
11974642e01fSmrg	pSprite->hotPhys.x = XE_KBPTR.rootX;
11984642e01fSmrg	pSprite->hotPhys.y = XE_KBPTR.rootY;
119905b261ecSmrg	/* do motion compression, but not if from different devices */
120005b261ecSmrg	if (tail &&
12014642e01fSmrg	    (tail->event->u.u.type == DeviceMotionNotify) &&
120205b261ecSmrg            (tail->device == device) &&
12034642e01fSmrg	    (tail->pScreen == pSprite->hotPhys.pScreen))
120405b261ecSmrg	{
12054642e01fSmrg	    tail->event->u.keyButtonPointer.rootX = pSprite->hotPhys.x;
12064642e01fSmrg	    tail->event->u.keyButtonPointer.rootY = pSprite->hotPhys.y;
120705b261ecSmrg	    tail->event->u.keyButtonPointer.time = XE_KBPTR.time;
120805b261ecSmrg	    tail->months = currentTime.months;
120905b261ecSmrg	    return;
121005b261ecSmrg	}
121105b261ecSmrg    }
12124642e01fSmrg
12134642e01fSmrg    eventlen = count * sizeof(xEvent);
12144642e01fSmrg    if (xE->u.u.type == GenericEvent) /* count is 1 for GenericEvents */
12154642e01fSmrg	eventlen += ((xGenericEvent*)xE)->length * 4;
12164642e01fSmrg
12174642e01fSmrg    qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + eventlen);
121805b261ecSmrg    if (!qe)
121905b261ecSmrg	return;
122005b261ecSmrg    qe->next = (QdEventPtr)NULL;
122105b261ecSmrg    qe->device = device;
12224642e01fSmrg    qe->pScreen = pSprite->hotPhys.pScreen;
122305b261ecSmrg    qe->months = currentTime.months;
122405b261ecSmrg    qe->event = (xEvent *)(qe + 1);
122505b261ecSmrg    qe->evcount = count;
12264642e01fSmrg    if (xE->u.u.type == GenericEvent)
12274642e01fSmrg    {
12284642e01fSmrg	memcpy(qe->event, xE, eventlen);
12294642e01fSmrg    } else
12304642e01fSmrg    {
12314642e01fSmrg	xEvent	*qxE;
12324642e01fSmrg	for (qxE = qe->event; --count >= 0; qxE++, xE++)
12334642e01fSmrg	{
12344642e01fSmrg	    *qxE = *xE;
12354642e01fSmrg	}
12364642e01fSmrg    }
123705b261ecSmrg    if (tail)
123805b261ecSmrg	syncEvents.pendtail = &tail->next;
123905b261ecSmrg    *syncEvents.pendtail = qe;
124005b261ecSmrg}
124105b261ecSmrg
12424642e01fSmrg/**
12434642e01fSmrg * Run through the list of events queued up in syncEvents.
12444642e01fSmrg * For each event do:
12454642e01fSmrg * If the device for this event is not frozen anymore, take it and process it
12464642e01fSmrg * as usually.
12474642e01fSmrg * After that, check if there's any devices in the list that are not frozen.
12484642e01fSmrg * If there is none, we're done. If there is at least one device that is not
12494642e01fSmrg * frozen, then re-run from the beginning of the event queue.
12504642e01fSmrg */
125105b261ecSmrgstatic void
125205b261ecSmrgPlayReleasedEvents(void)
125305b261ecSmrg{
125405b261ecSmrg    QdEventPtr *prev, qe;
125505b261ecSmrg    DeviceIntPtr dev;
12564642e01fSmrg    DeviceIntPtr pDev;
12574642e01fSmrg    static CARD32 lastKnownMillis = 0; /* Hack, see comment below */
125805b261ecSmrg
125905b261ecSmrg    prev = &syncEvents.pending;
126005b261ecSmrg    while ( (qe = *prev) )
126105b261ecSmrg    {
12624642e01fSmrg	if (!qe->device->deviceGrab.sync.frozen)
126305b261ecSmrg	{
126405b261ecSmrg	    *prev = qe->next;
12654642e01fSmrg            pDev = qe->device;
126605b261ecSmrg	    if (*syncEvents.pendtail == *prev)
126705b261ecSmrg		syncEvents.pendtail = prev;
12684642e01fSmrg	    if (qe->event->u.u.type == DeviceMotionNotify)
12694642e01fSmrg		CheckVirtualMotion(pDev, qe, NullWindow);
127005b261ecSmrg	    syncEvents.time.months = qe->months;
12714642e01fSmrg            /* XXX: Hack! We can't reliably get the time from GenericEvents,
12724642e01fSmrg               since we don't know which struct it may be. So we store the time
12734642e01fSmrg               when we know it, and re-use it when we can't get it. */
12744642e01fSmrg            if (qe->event->u.u.type == GenericEvent)
12754642e01fSmrg            {
12764642e01fSmrg                syncEvents.time.milliseconds = lastKnownMillis;
12774642e01fSmrg            } else
12784642e01fSmrg            {
12794642e01fSmrg                syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time;
12804642e01fSmrg                lastKnownMillis = syncEvents.time.milliseconds;
12814642e01fSmrg            }
128205b261ecSmrg#ifdef PANORAMIX
128305b261ecSmrg	   /* Translate back to the sprite screen since processInputProc
128405b261ecSmrg	      will translate from sprite screen to screen 0 upon reentry
128505b261ecSmrg	      to the DIX layer */
12864642e01fSmrg            /* XXX: we can't do that for generic events */
128705b261ecSmrg	    if(!noPanoramiXExtension) {
12884642e01fSmrg		qe->event->u.keyButtonPointer.rootX +=
12894642e01fSmrg			panoramiXdataPtr[0].x -
12904642e01fSmrg			panoramiXdataPtr[pDev->spriteInfo->sprite->screen->myNum].x;
12914642e01fSmrg		qe->event->u.keyButtonPointer.rootY +=
12924642e01fSmrg			panoramiXdataPtr[0].y -
12934642e01fSmrg			panoramiXdataPtr[pDev->spriteInfo->sprite->screen->myNum].y;
129405b261ecSmrg	    }
129505b261ecSmrg#endif
129605b261ecSmrg	    (*qe->device->public.processInputProc)(qe->event, qe->device,
129705b261ecSmrg						   qe->evcount);
129805b261ecSmrg	    xfree(qe);
12994642e01fSmrg	    for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; dev = dev->next)
130005b261ecSmrg		;
130105b261ecSmrg	    if (!dev)
130205b261ecSmrg		break;
130305b261ecSmrg	    /* Playing the event may have unfrozen another device. */
130405b261ecSmrg	    /* So to play it safe, restart at the head of the queue */
130505b261ecSmrg	    prev = &syncEvents.pending;
130605b261ecSmrg	}
130705b261ecSmrg	else
130805b261ecSmrg	    prev = &qe->next;
13094642e01fSmrg    }
131005b261ecSmrg}
131105b261ecSmrg
13124642e01fSmrg/**
13134642e01fSmrg * Freeze or thaw the given devices. The device's processing proc is
13144642e01fSmrg * switched to either the real processing proc (in case of thawing) or an
13154642e01fSmrg * enqueuing processing proc (usually EnqueueEvent()).
13164642e01fSmrg *
13174642e01fSmrg * @param dev The device to freeze/thaw
13184642e01fSmrg * @param frozen True to freeze or false to thaw.
13194642e01fSmrg */
132005b261ecSmrgstatic void
132105b261ecSmrgFreezeThaw(DeviceIntPtr dev, Bool frozen)
132205b261ecSmrg{
13234642e01fSmrg    dev->deviceGrab.sync.frozen = frozen;
132405b261ecSmrg    if (frozen)
132505b261ecSmrg	dev->public.processInputProc = dev->public.enqueueInputProc;
132605b261ecSmrg    else
132705b261ecSmrg	dev->public.processInputProc = dev->public.realInputProc;
132805b261ecSmrg}
132905b261ecSmrg
13304642e01fSmrg/**
13314642e01fSmrg * Unfreeze devices and replay all events to the respective clients.
13324642e01fSmrg *
13334642e01fSmrg * ComputeFreezes takes the first event in the device's frozen event queue. It
13344642e01fSmrg * runs up the sprite tree (spriteTrace) and searches for the window to replay
13354642e01fSmrg * the events from. If it is found, it checks for passive grabs one down from
13364642e01fSmrg * the window or delivers the events.
13374642e01fSmrg *
13384642e01fSmrg * Since the events in the EQ are always XI events, we need to emulate core
13394642e01fSmrg * events here.
13404642e01fSmrg */
13414642e01fSmrgstatic void
134205b261ecSmrgComputeFreezes(void)
134305b261ecSmrg{
134405b261ecSmrg    DeviceIntPtr replayDev = syncEvents.replayDev;
134505b261ecSmrg    int i;
134605b261ecSmrg    WindowPtr w;
134705b261ecSmrg    xEvent *xE;
134805b261ecSmrg    int count;
134905b261ecSmrg    GrabPtr grab;
135005b261ecSmrg    DeviceIntPtr dev;
135105b261ecSmrg
135205b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
13534642e01fSmrg	FreezeThaw(dev, dev->deviceGrab.sync.other ||
13544642e01fSmrg                (dev->deviceGrab.sync.state >= FROZEN));
135505b261ecSmrg    if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
135605b261ecSmrg	return;
135705b261ecSmrg    syncEvents.playingEvents = TRUE;
135805b261ecSmrg    if (replayDev)
135905b261ecSmrg    {
13604642e01fSmrg	xE = replayDev->deviceGrab.sync.event;
13614642e01fSmrg	count = replayDev->deviceGrab.sync.evcount;
136205b261ecSmrg	syncEvents.replayDev = (DeviceIntPtr)NULL;
136305b261ecSmrg
13644642e01fSmrg        w = XYToWindow(replayDev, XE_KBPTR.rootX, XE_KBPTR.rootY);
13654642e01fSmrg	for (i = 0; i < replayDev->spriteInfo->sprite->spriteTraceGood; i++)
136605b261ecSmrg	{
13674642e01fSmrg	    if (syncEvents.replayWin ==
13684642e01fSmrg		replayDev->spriteInfo->sprite->spriteTrace[i])
136905b261ecSmrg	    {
137005b261ecSmrg		if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) {
13714642e01fSmrg		    if (replayDev->focus && !IsPointerEvent(xE))
137205b261ecSmrg			DeliverFocusedEvent(replayDev, xE, w, count);
137305b261ecSmrg		    else
137405b261ecSmrg			DeliverDeviceEvents(w, xE, NullGrab, NullWindow,
137505b261ecSmrg					        replayDev, count);
137605b261ecSmrg		}
137705b261ecSmrg		goto playmore;
137805b261ecSmrg	    }
137905b261ecSmrg	}
138005b261ecSmrg	/* must not still be in the same stack */
13814642e01fSmrg	if (replayDev->focus && !IsPointerEvent(xE))
138205b261ecSmrg	    DeliverFocusedEvent(replayDev, xE, w, count);
138305b261ecSmrg	else
138405b261ecSmrg	    DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count);
138505b261ecSmrg    }
138605b261ecSmrgplaymore:
138705b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
138805b261ecSmrg    {
13894642e01fSmrg	if (!dev->deviceGrab.sync.frozen)
139005b261ecSmrg	{
139105b261ecSmrg	    PlayReleasedEvents();
139205b261ecSmrg	    break;
139305b261ecSmrg	}
139405b261ecSmrg    }
139505b261ecSmrg    syncEvents.playingEvents = FALSE;
13964642e01fSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
139705b261ecSmrg    {
13984642e01fSmrg        if (DevHasCursor(dev))
13994642e01fSmrg        {
14004642e01fSmrg            /* the following may have been skipped during replay,
14014642e01fSmrg              so do it now */
14024642e01fSmrg            if ((grab = dev->deviceGrab.grab) && grab->confineTo)
14034642e01fSmrg            {
14044642e01fSmrg                if (grab->confineTo->drawable.pScreen !=
14054642e01fSmrg                        dev->spriteInfo->sprite->hotPhys.pScreen)
14064642e01fSmrg                    dev->spriteInfo->sprite->hotPhys.x =
14074642e01fSmrg                        dev->spriteInfo->sprite->hotPhys.y = 0;
14084642e01fSmrg                ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE);
14094642e01fSmrg            }
14104642e01fSmrg            else
14114642e01fSmrg                ConfineCursorToWindow(dev,
14124642e01fSmrg                        WindowTable[dev->spriteInfo->sprite->hotPhys.pScreen->myNum],
14134642e01fSmrg                        TRUE, FALSE);
14144642e01fSmrg            PostNewCursor(dev);
14154642e01fSmrg        }
141605b261ecSmrg    }
141705b261ecSmrg}
141805b261ecSmrg
141905b261ecSmrg#ifdef RANDR
142005b261ecSmrgvoid
142105b261ecSmrgScreenRestructured (ScreenPtr pScreen)
142205b261ecSmrg{
142305b261ecSmrg    GrabPtr grab;
14244642e01fSmrg    DeviceIntPtr pDev;
142505b261ecSmrg
14264642e01fSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
142705b261ecSmrg    {
14284642e01fSmrg        if (!DevHasCursor(pDev))
14294642e01fSmrg            continue;
14304642e01fSmrg
14314642e01fSmrg        /* GrabDevice doesn't have a confineTo field, so we don't need to
14324642e01fSmrg         * worry about it. */
14334642e01fSmrg        if ((grab = pDev->deviceGrab.grab) && grab->confineTo)
14344642e01fSmrg        {
14354642e01fSmrg            if (grab->confineTo->drawable.pScreen
14364642e01fSmrg                    != pDev->spriteInfo->sprite->hotPhys.pScreen)
14374642e01fSmrg                pDev->spriteInfo->sprite->hotPhys.x = pDev->spriteInfo->sprite->hotPhys.y = 0;
14384642e01fSmrg            ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
14394642e01fSmrg        }
14404642e01fSmrg        else
14414642e01fSmrg            ConfineCursorToWindow(pDev,
14424642e01fSmrg                    WindowTable[pDev->spriteInfo->sprite->hotPhys.pScreen->myNum],
14434642e01fSmrg                    TRUE, FALSE);
144405b261ecSmrg    }
144505b261ecSmrg}
144605b261ecSmrg#endif
144705b261ecSmrg
14484642e01fSmrgstatic void
144905b261ecSmrgCheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
145005b261ecSmrg{
14514642e01fSmrg    GrabPtr grab = thisDev->deviceGrab.grab;
145205b261ecSmrg    DeviceIntPtr dev;
145305b261ecSmrg
145405b261ecSmrg    if (thisMode == GrabModeSync)
14554642e01fSmrg	thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT;
145605b261ecSmrg    else
145705b261ecSmrg    {	/* free both if same client owns both */
14584642e01fSmrg	thisDev->deviceGrab.sync.state = THAWED;
14594642e01fSmrg	if (thisDev->deviceGrab.sync.other &&
14604642e01fSmrg	    (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) ==
146105b261ecSmrg	     CLIENT_BITS(grab->resource)))
14624642e01fSmrg	    thisDev->deviceGrab.sync.other = NullGrab;
146305b261ecSmrg    }
14644642e01fSmrg
14654642e01fSmrg    /*
14664642e01fSmrg        XXX: Direct slave grab won't freeze the paired master device.
14674642e01fSmrg        The correct thing to do would be to freeze all SDs attached to the
14684642e01fSmrg        paired master device.
14694642e01fSmrg     */
14704642e01fSmrg    if (thisDev->isMaster)
14714642e01fSmrg    {
14724642e01fSmrg        dev = GetPairedDevice(thisDev);
14734642e01fSmrg        if (otherMode == GrabModeSync)
14744642e01fSmrg            dev->deviceGrab.sync.other = grab;
14754642e01fSmrg        else
14764642e01fSmrg        {	/* free both if same client owns both */
14774642e01fSmrg            if (dev->deviceGrab.sync.other &&
14784642e01fSmrg                    (CLIENT_BITS(dev->deviceGrab.sync.other->resource) ==
14794642e01fSmrg                     CLIENT_BITS(grab->resource)))
14804642e01fSmrg                dev->deviceGrab.sync.other = NullGrab;
14814642e01fSmrg        }
148205b261ecSmrg    }
148305b261ecSmrg    ComputeFreezes();
148405b261ecSmrg}
148505b261ecSmrg
148605b261ecSmrg/**
148705b261ecSmrg * Activate a pointer grab on the given device. A pointer grab will cause all
14884642e01fSmrg * core pointer events of this device to be delivered to the grabbing client only.
14894642e01fSmrg * No other device will send core events to the grab client while the grab is
14904642e01fSmrg * on, but core events will be sent to other clients.
14914642e01fSmrg * Can cause the cursor to change if a grab cursor is set.
14924642e01fSmrg *
14934642e01fSmrg * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab
14944642e01fSmrg * is an implicit grab caused by a ButtonPress event.
14954642e01fSmrg *
149605b261ecSmrg * @param mouse The device to grab.
149705b261ecSmrg * @param grab The grab structure, needs to be setup.
149805b261ecSmrg * @param autoGrab True if the grab was caused by a button down event and not
14994642e01fSmrg * explicitely by a client.
150005b261ecSmrg */
150105b261ecSmrgvoid
15024642e01fSmrgActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
150305b261ecSmrg                    TimeStamp time, Bool autoGrab)
150405b261ecSmrg{
15054642e01fSmrg    GrabInfoPtr grabinfo = &mouse->deviceGrab;
15064642e01fSmrg    WindowPtr oldWin = (grabinfo->grab) ?
15074642e01fSmrg                        grabinfo->grab->window
15084642e01fSmrg                        : mouse->spriteInfo->sprite->win;
15094642e01fSmrg    Bool isPassive = autoGrab & ~ImplicitGrabMask;
151005b261ecSmrg
151105b261ecSmrg    if (grab->confineTo)
151205b261ecSmrg    {
15134642e01fSmrg	if (grab->confineTo->drawable.pScreen
15144642e01fSmrg                != mouse->spriteInfo->sprite->hotPhys.pScreen)
15154642e01fSmrg	    mouse->spriteInfo->sprite->hotPhys.x =
15164642e01fSmrg                mouse->spriteInfo->sprite->hotPhys.y = 0;
15174642e01fSmrg	ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE);
151805b261ecSmrg    }
15194642e01fSmrg    DoEnterLeaveEvents(mouse, oldWin, grab->window, NotifyGrab);
152005b261ecSmrg    mouse->valuator->motionHintWindow = NullWindow;
152105b261ecSmrg    if (syncEvents.playingEvents)
15224642e01fSmrg        grabinfo->grabTime = syncEvents.time;
152305b261ecSmrg    else
15244642e01fSmrg	grabinfo->grabTime = time;
152505b261ecSmrg    if (grab->cursor)
152605b261ecSmrg	grab->cursor->refcnt++;
15274642e01fSmrg    grabinfo->activeGrab = *grab;
15284642e01fSmrg    grabinfo->grab = &grabinfo->activeGrab;
15294642e01fSmrg    grabinfo->fromPassiveGrab = isPassive;
15304642e01fSmrg    grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
15314642e01fSmrg    PostNewCursor(mouse);
153205b261ecSmrg    CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
153305b261ecSmrg}
153405b261ecSmrg
153505b261ecSmrg/**
153605b261ecSmrg * Delete grab on given device, update the sprite.
153705b261ecSmrg *
15384642e01fSmrg * Extension devices are set up for ActivateKeyboardGrab().
153905b261ecSmrg */
154005b261ecSmrgvoid
154105b261ecSmrgDeactivatePointerGrab(DeviceIntPtr mouse)
154205b261ecSmrg{
15434642e01fSmrg    GrabPtr grab = mouse->deviceGrab.grab;
154405b261ecSmrg    DeviceIntPtr dev;
154505b261ecSmrg
154605b261ecSmrg    mouse->valuator->motionHintWindow = NullWindow;
15474642e01fSmrg    mouse->deviceGrab.grab = NullGrab;
15484642e01fSmrg    mouse->deviceGrab.sync.state = NOT_GRABBED;
15494642e01fSmrg    mouse->deviceGrab.fromPassiveGrab = FALSE;
15504642e01fSmrg
15514642e01fSmrg    /* make sure the potential XGE event mask is freed too*/
15524642e01fSmrg    if (grab->genericMasks)
15534642e01fSmrg    {
15544642e01fSmrg        xfree(grab->genericMasks);
15554642e01fSmrg        grab->genericMasks = NULL;
15564642e01fSmrg    }
15574642e01fSmrg
155805b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
155905b261ecSmrg    {
15604642e01fSmrg	if (dev->deviceGrab.sync.other == grab)
15614642e01fSmrg	    dev->deviceGrab.sync.other = NullGrab;
156205b261ecSmrg    }
15634642e01fSmrg    DoEnterLeaveEvents(mouse, grab->window,
15644642e01fSmrg                       mouse->spriteInfo->sprite->win, NotifyUngrab);
156505b261ecSmrg    if (grab->confineTo)
15664642e01fSmrg	ConfineCursorToWindow(mouse, RootWindow(mouse), FALSE, FALSE);
15674642e01fSmrg    PostNewCursor(mouse);
156805b261ecSmrg    if (grab->cursor)
156905b261ecSmrg	FreeCursor(grab->cursor, (Cursor)0);
15704642e01fSmrg
157105b261ecSmrg    ComputeFreezes();
157205b261ecSmrg}
157305b261ecSmrg
157405b261ecSmrg/**
15754642e01fSmrg * Activate a keyboard grab on the given device.
157605b261ecSmrg *
157705b261ecSmrg * Extension devices have ActivateKeyboardGrab() set as their grabbing proc.
157805b261ecSmrg */
157905b261ecSmrgvoid
158005b261ecSmrgActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive)
158105b261ecSmrg{
15824642e01fSmrg    GrabInfoPtr grabinfo = &keybd->deviceGrab;
158305b261ecSmrg    WindowPtr oldWin;
158405b261ecSmrg
15854642e01fSmrg    if (grabinfo->grab)
15864642e01fSmrg	oldWin = grabinfo->grab->window;
158705b261ecSmrg    else if (keybd->focus)
158805b261ecSmrg	oldWin = keybd->focus->win;
158905b261ecSmrg    else
15904642e01fSmrg	oldWin = keybd->spriteInfo->sprite->win;
159105b261ecSmrg    if (oldWin == FollowKeyboardWin)
159205b261ecSmrg	oldWin = inputInfo.keyboard->focus->win;
159305b261ecSmrg    if (keybd->valuator)
159405b261ecSmrg	keybd->valuator->motionHintWindow = NullWindow;
159505b261ecSmrg    DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
159605b261ecSmrg    if (syncEvents.playingEvents)
15974642e01fSmrg	grabinfo->grabTime = syncEvents.time;
159805b261ecSmrg    else
15994642e01fSmrg	grabinfo->grabTime = time;
16004642e01fSmrg    grabinfo->activeGrab = *grab;
16014642e01fSmrg    grabinfo->grab = &grabinfo->activeGrab;
16024642e01fSmrg    grabinfo->fromPassiveGrab = passive;
160305b261ecSmrg    CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
160405b261ecSmrg}
160505b261ecSmrg
160605b261ecSmrg/**
16074642e01fSmrg * Delete keyboard grab for the given device.
160805b261ecSmrg */
160905b261ecSmrgvoid
161005b261ecSmrgDeactivateKeyboardGrab(DeviceIntPtr keybd)
161105b261ecSmrg{
16124642e01fSmrg    GrabPtr grab = keybd->deviceGrab.grab;
161305b261ecSmrg    DeviceIntPtr dev;
161405b261ecSmrg    WindowPtr focusWin = keybd->focus ? keybd->focus->win
16154642e01fSmrg                                           : keybd->spriteInfo->sprite->win;
161605b261ecSmrg
161705b261ecSmrg    if (focusWin == FollowKeyboardWin)
161805b261ecSmrg	focusWin = inputInfo.keyboard->focus->win;
161905b261ecSmrg    if (keybd->valuator)
162005b261ecSmrg	keybd->valuator->motionHintWindow = NullWindow;
16214642e01fSmrg    keybd->deviceGrab.grab = NullGrab;
16224642e01fSmrg    keybd->deviceGrab.sync.state = NOT_GRABBED;
16234642e01fSmrg    keybd->deviceGrab.fromPassiveGrab = FALSE;
16244642e01fSmrg    if (grab->genericMasks)
16254642e01fSmrg    {
16264642e01fSmrg        xfree(grab->genericMasks);
16274642e01fSmrg        grab->genericMasks = NULL;
16284642e01fSmrg    }
16294642e01fSmrg
163005b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
163105b261ecSmrg    {
16324642e01fSmrg	if (dev->deviceGrab.sync.other == grab)
16334642e01fSmrg	    dev->deviceGrab.sync.other = NullGrab;
163405b261ecSmrg    }
163505b261ecSmrg    DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
16364642e01fSmrg
163705b261ecSmrg    ComputeFreezes();
163805b261ecSmrg}
163905b261ecSmrg
164005b261ecSmrgvoid
16414642e01fSmrgAllowSome(ClientPtr client,
16424642e01fSmrg          TimeStamp time,
16434642e01fSmrg          DeviceIntPtr thisDev,
16444642e01fSmrg          int newState,
16454642e01fSmrg          Bool core)
164605b261ecSmrg{
164705b261ecSmrg    Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
164805b261ecSmrg    TimeStamp grabTime;
164905b261ecSmrg    DeviceIntPtr dev;
16504642e01fSmrg    GrabInfoPtr devgrabinfo,
16514642e01fSmrg                grabinfo = &thisDev->deviceGrab;
165205b261ecSmrg
16534642e01fSmrg    thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
165405b261ecSmrg    thisSynced = FALSE;
165505b261ecSmrg    otherGrabbed = FALSE;
165605b261ecSmrg    othersFrozen = TRUE;
16574642e01fSmrg    grabTime = grabinfo->grabTime;
165805b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
165905b261ecSmrg    {
16604642e01fSmrg        devgrabinfo = &dev->deviceGrab;
16614642e01fSmrg
166205b261ecSmrg	if (dev == thisDev)
166305b261ecSmrg	    continue;
16644642e01fSmrg	if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
166505b261ecSmrg	{
166605b261ecSmrg	    if (!(thisGrabbed || otherGrabbed) ||
16674642e01fSmrg		(CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER))
16684642e01fSmrg		grabTime = devgrabinfo->grabTime;
166905b261ecSmrg	    otherGrabbed = TRUE;
16704642e01fSmrg	    if (grabinfo->sync.other == devgrabinfo->grab)
167105b261ecSmrg		thisSynced = TRUE;
16724642e01fSmrg	    if (devgrabinfo->sync.state < FROZEN)
167305b261ecSmrg		othersFrozen = FALSE;
167405b261ecSmrg	}
16754642e01fSmrg	else if (!devgrabinfo->sync.other || !SameClient(devgrabinfo->sync.other, client))
167605b261ecSmrg	    othersFrozen = FALSE;
167705b261ecSmrg    }
16784642e01fSmrg    if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced))
167905b261ecSmrg	return;
168005b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
168105b261ecSmrg	(CompareTimeStamps(time, grabTime) == EARLIER))
168205b261ecSmrg	return;
168305b261ecSmrg    switch (newState)
168405b261ecSmrg    {
16854642e01fSmrg	case THAWED:		       /* Async */
168605b261ecSmrg	    if (thisGrabbed)
16874642e01fSmrg		grabinfo->sync.state = THAWED;
168805b261ecSmrg	    if (thisSynced)
16894642e01fSmrg		grabinfo->sync.other = NullGrab;
169005b261ecSmrg	    ComputeFreezes();
169105b261ecSmrg	    break;
169205b261ecSmrg	case FREEZE_NEXT_EVENT:		/* Sync */
169305b261ecSmrg	    if (thisGrabbed)
169405b261ecSmrg	    {
16954642e01fSmrg		grabinfo->sync.state = FREEZE_NEXT_EVENT;
169605b261ecSmrg		if (thisSynced)
16974642e01fSmrg		    grabinfo->sync.other = NullGrab;
169805b261ecSmrg		ComputeFreezes();
169905b261ecSmrg	    }
170005b261ecSmrg	    break;
170105b261ecSmrg	case THAWED_BOTH:		/* AsyncBoth */
170205b261ecSmrg	    if (othersFrozen)
170305b261ecSmrg	    {
170405b261ecSmrg		for (dev = inputInfo.devices; dev; dev = dev->next)
170505b261ecSmrg		{
17064642e01fSmrg                    devgrabinfo = &dev->deviceGrab;
17074642e01fSmrg		    if (devgrabinfo->grab
17084642e01fSmrg                            && SameClient(devgrabinfo->grab, client))
17094642e01fSmrg			devgrabinfo->sync.state = THAWED;
17104642e01fSmrg		    if (devgrabinfo->sync.other &&
17114642e01fSmrg                            SameClient(devgrabinfo->sync.other, client))
17124642e01fSmrg			devgrabinfo->sync.other = NullGrab;
171305b261ecSmrg		}
171405b261ecSmrg		ComputeFreezes();
171505b261ecSmrg	    }
171605b261ecSmrg	    break;
171705b261ecSmrg	case FREEZE_BOTH_NEXT_EVENT:	/* SyncBoth */
171805b261ecSmrg	    if (othersFrozen)
171905b261ecSmrg	    {
172005b261ecSmrg		for (dev = inputInfo.devices; dev; dev = dev->next)
172105b261ecSmrg		{
17224642e01fSmrg                    devgrabinfo = &dev->deviceGrab;
17234642e01fSmrg		    if (devgrabinfo->grab
17244642e01fSmrg                            && SameClient(devgrabinfo->grab, client))
17254642e01fSmrg			devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT;
17264642e01fSmrg		    if (devgrabinfo->sync.other
17274642e01fSmrg                            && SameClient(devgrabinfo->sync.other, client))
17284642e01fSmrg			devgrabinfo->sync.other = NullGrab;
172905b261ecSmrg		}
173005b261ecSmrg		ComputeFreezes();
173105b261ecSmrg	    }
173205b261ecSmrg	    break;
173305b261ecSmrg	case NOT_GRABBED:		/* Replay */
17344642e01fSmrg	    if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT)
173505b261ecSmrg	    {
173605b261ecSmrg		if (thisSynced)
17374642e01fSmrg		    grabinfo->sync.other = NullGrab;
173805b261ecSmrg		syncEvents.replayDev = thisDev;
17394642e01fSmrg		syncEvents.replayWin = grabinfo->grab->window;
17404642e01fSmrg		(*grabinfo->DeactivateGrab)(thisDev);
174105b261ecSmrg		syncEvents.replayDev = (DeviceIntPtr)NULL;
174205b261ecSmrg	    }
174305b261ecSmrg	    break;
174405b261ecSmrg	case THAW_OTHERS:		/* AsyncOthers */
174505b261ecSmrg	    if (othersFrozen)
174605b261ecSmrg	    {
174705b261ecSmrg		for (dev = inputInfo.devices; dev; dev = dev->next)
174805b261ecSmrg		{
174905b261ecSmrg		    if (dev == thisDev)
175005b261ecSmrg			continue;
17514642e01fSmrg                    devgrabinfo = (core) ? &dev->deviceGrab : &dev->deviceGrab;
17524642e01fSmrg		    if (devgrabinfo->grab
17534642e01fSmrg                            && SameClient(devgrabinfo->grab, client))
17544642e01fSmrg			devgrabinfo->sync.state = THAWED;
17554642e01fSmrg		    if (devgrabinfo->sync.other
17564642e01fSmrg                            && SameClient(devgrabinfo->sync.other, client))
17574642e01fSmrg			devgrabinfo->sync.other = NullGrab;
175805b261ecSmrg		}
175905b261ecSmrg		ComputeFreezes();
176005b261ecSmrg	    }
176105b261ecSmrg	    break;
176205b261ecSmrg    }
176305b261ecSmrg}
176405b261ecSmrg
176505b261ecSmrg/**
176605b261ecSmrg * Server-side protocol handling for AllowEvents request.
176705b261ecSmrg *
17684642e01fSmrg * Release some events from a frozen device.
176905b261ecSmrg */
177005b261ecSmrgint
177105b261ecSmrgProcAllowEvents(ClientPtr client)
177205b261ecSmrg{
177305b261ecSmrg    TimeStamp		time;
17744642e01fSmrg    DeviceIntPtr	mouse = NULL;
17754642e01fSmrg    DeviceIntPtr	keybd = NULL;
177605b261ecSmrg    REQUEST(xAllowEventsReq);
177705b261ecSmrg
177805b261ecSmrg    REQUEST_SIZE_MATCH(xAllowEventsReq);
177905b261ecSmrg    time = ClientTimeToServerTime(stuff->time);
17804642e01fSmrg
17814642e01fSmrg    mouse = PickPointer(client);
17824642e01fSmrg    keybd = PickKeyboard(client);
17834642e01fSmrg
178405b261ecSmrg    switch (stuff->mode)
178505b261ecSmrg    {
178605b261ecSmrg	case ReplayPointer:
17874642e01fSmrg	    AllowSome(client, time, mouse, NOT_GRABBED, True);
178805b261ecSmrg	    break;
17894642e01fSmrg	case SyncPointer:
17904642e01fSmrg	    AllowSome(client, time, mouse, FREEZE_NEXT_EVENT, True);
179105b261ecSmrg	    break;
17924642e01fSmrg	case AsyncPointer:
17934642e01fSmrg	    AllowSome(client, time, mouse, THAWED, True);
179405b261ecSmrg	    break;
17954642e01fSmrg	case ReplayKeyboard:
17964642e01fSmrg	    AllowSome(client, time, keybd, NOT_GRABBED, True);
179705b261ecSmrg	    break;
17984642e01fSmrg	case SyncKeyboard:
17994642e01fSmrg	    AllowSome(client, time, keybd, FREEZE_NEXT_EVENT, True);
180005b261ecSmrg	    break;
18014642e01fSmrg	case AsyncKeyboard:
18024642e01fSmrg	    AllowSome(client, time, keybd, THAWED, True);
180305b261ecSmrg	    break;
180405b261ecSmrg	case SyncBoth:
18054642e01fSmrg	    AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT, True);
180605b261ecSmrg	    break;
180705b261ecSmrg	case AsyncBoth:
18084642e01fSmrg	    AllowSome(client, time, keybd, THAWED_BOTH, True);
180905b261ecSmrg	    break;
18104642e01fSmrg	default:
181105b261ecSmrg	    client->errorValue = stuff->mode;
181205b261ecSmrg	    return BadValue;
181305b261ecSmrg    }
181405b261ecSmrg    return Success;
181505b261ecSmrg}
181605b261ecSmrg
181705b261ecSmrg/**
181805b261ecSmrg * Deactivate grabs from any device that has been grabbed by the client.
181905b261ecSmrg */
182005b261ecSmrgvoid
182105b261ecSmrgReleaseActiveGrabs(ClientPtr client)
182205b261ecSmrg{
182305b261ecSmrg    DeviceIntPtr dev;
182405b261ecSmrg    Bool    done;
182505b261ecSmrg
182605b261ecSmrg    /* XXX CloseDownClient should remove passive grabs before
182705b261ecSmrg     * releasing active grabs.
182805b261ecSmrg     */
182905b261ecSmrg    do {
18304642e01fSmrg	done = TRUE;
18314642e01fSmrg	for (dev = inputInfo.devices; dev; dev = dev->next)
18324642e01fSmrg	{
18334642e01fSmrg	    if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
183405b261ecSmrg	    {
18354642e01fSmrg		(*dev->deviceGrab.DeactivateGrab)(dev);
18364642e01fSmrg		done = FALSE;
183705b261ecSmrg	    }
18384642e01fSmrg	}
183905b261ecSmrg    } while (!done);
184005b261ecSmrg}
184105b261ecSmrg
184205b261ecSmrg/**************************************************************************
184305b261ecSmrg *            The following procedures deal with delivering events        *
184405b261ecSmrg **************************************************************************/
184505b261ecSmrg
184605b261ecSmrg/**
184705b261ecSmrg * Deliver the given events to the given client.
184805b261ecSmrg *
184905b261ecSmrg * More than one event may be delivered at a time. This is the case with
185005b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events.
185105b261ecSmrg *
185205b261ecSmrg * TryClientEvents() is the last station before actually writing the events to
185305b261ecSmrg * the socket. Anything that is not filtered here, will get delivered to the
18544642e01fSmrg * client.
18554642e01fSmrg * An event is only delivered if
185605b261ecSmrg *   - mask and filter match up.
185705b261ecSmrg *   - no other client has a grab on the device that caused the event.
18584642e01fSmrg *
185905b261ecSmrg *
186005b261ecSmrg * @param client The target client to deliver to.
18614642e01fSmrg * @param dev The device the event came from. May be NULL.
186205b261ecSmrg * @param pEvents The events to be delivered.
186305b261ecSmrg * @param count Number of elements in pEvents.
186405b261ecSmrg * @param mask Event mask as set by the window.
186505b261ecSmrg * @param filter Mask based on event type.
18664642e01fSmrg * @param grab Possible grab on the device that caused the event.
186705b261ecSmrg *
186805b261ecSmrg * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
186905b261ecSmrg * client.
187005b261ecSmrg */
187105b261ecSmrg_X_EXPORT int
18724642e01fSmrgTryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
18734642e01fSmrg                 int count, Mask mask, Mask filter, GrabPtr grab)
187405b261ecSmrg{
187505b261ecSmrg    int i;
187605b261ecSmrg    int type;
187705b261ecSmrg
187805b261ecSmrg#ifdef DEBUG_EVENTS
18794642e01fSmrg    ErrorF("[dix] Event([%d, %d], mask=0x%x), client=%d",
188005b261ecSmrg	pEvents->u.u.type, pEvents->u.u.detail, mask, client->index);
188105b261ecSmrg#endif
188205b261ecSmrg    if ((client) && (client != serverClient) && (!client->clientGone) &&
188305b261ecSmrg	((filter == CantBeFiltered) || (mask & filter)))
188405b261ecSmrg    {
188505b261ecSmrg	if (grab && !SameClient(grab, client))
188605b261ecSmrg	    return -1; /* don't send, but notify caller */
188705b261ecSmrg	type = pEvents->u.u.type;
188805b261ecSmrg	if (type == MotionNotify)
188905b261ecSmrg	{
189005b261ecSmrg	    if (mask & PointerMotionHintMask)
189105b261ecSmrg	    {
18924642e01fSmrg		if (WID(dev->valuator->motionHintWindow) ==
189305b261ecSmrg		    pEvents->u.keyButtonPointer.event)
189405b261ecSmrg		{
189505b261ecSmrg#ifdef DEBUG_EVENTS
18964642e01fSmrg		    ErrorF("[dix] \n");
18974642e01fSmrg	    ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
189805b261ecSmrg#endif
189905b261ecSmrg		    return 1; /* don't send, but pretend we did */
190005b261ecSmrg		}
190105b261ecSmrg		pEvents->u.u.detail = NotifyHint;
190205b261ecSmrg	    }
190305b261ecSmrg	    else
190405b261ecSmrg	    {
190505b261ecSmrg		pEvents->u.u.detail = NotifyNormal;
190605b261ecSmrg	    }
190705b261ecSmrg	}
190805b261ecSmrg	else
190905b261ecSmrg	{
191005b261ecSmrg	    if ((type == DeviceMotionNotify) &&
191105b261ecSmrg		MaybeSendDeviceMotionNotifyHint
191205b261ecSmrg			((deviceKeyButtonPointer*)pEvents, mask) != 0)
191305b261ecSmrg		return 1;
191405b261ecSmrg	}
191505b261ecSmrg	type &= 0177;
191605b261ecSmrg	if (type != KeymapNotify)
191705b261ecSmrg	{
191805b261ecSmrg	    /* all extension events must have a sequence number */
191905b261ecSmrg	    for (i = 0; i < count; i++)
192005b261ecSmrg		pEvents[i].u.u.sequenceNumber = client->sequence;
192105b261ecSmrg	}
192205b261ecSmrg
192305b261ecSmrg	if (BitIsOn(criticalEvents, type))
192405b261ecSmrg	{
192505b261ecSmrg	    if (client->smart_priority < SMART_MAX_PRIORITY)
192605b261ecSmrg		client->smart_priority++;
192705b261ecSmrg	    SetCriticalOutputPending();
192805b261ecSmrg	}
192905b261ecSmrg
193005b261ecSmrg	WriteEventsToClient(client, count, pEvents);
193105b261ecSmrg#ifdef DEBUG_EVENTS
19324642e01fSmrg	ErrorF("[dix]  delivered\n");
193305b261ecSmrg#endif
193405b261ecSmrg	return 1;
193505b261ecSmrg    }
193605b261ecSmrg    else
193705b261ecSmrg    {
193805b261ecSmrg#ifdef DEBUG_EVENTS
19394642e01fSmrg	ErrorF("[dix] \n");
194005b261ecSmrg#endif
194105b261ecSmrg	return 0;
194205b261ecSmrg    }
194305b261ecSmrg}
194405b261ecSmrg
194505b261ecSmrg/**
194605b261ecSmrg * Deliver events to a window. At this point, we do not yet know if the event
194705b261ecSmrg * actually needs to be delivered. May activate a grab if the event is a
194805b261ecSmrg * button press.
194905b261ecSmrg *
19504642e01fSmrg * Core events are always delivered to the window owner. If the filter is
19514642e01fSmrg * something other than CantBeFiltered, the event is also delivered to other
19524642e01fSmrg * clients with the matching mask on the window.
19534642e01fSmrg *
195405b261ecSmrg * More than one event may be delivered at a time. This is the case with
195505b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events.
19564642e01fSmrg *
195705b261ecSmrg * @param pWin The window that would get the event.
195805b261ecSmrg * @param pEvents The events to be delivered.
195905b261ecSmrg * @param count Number of elements in pEvents.
196005b261ecSmrg * @param filter Mask based on event type.
19614642e01fSmrg * @param grab Possible grab on the device that caused the event.
196205b261ecSmrg * @param mskidx Mask index, depending on device that caused event.
196305b261ecSmrg *
196405b261ecSmrg * @return Number of events delivered to various clients.
196505b261ecSmrg */
196605b261ecSmrgint
19674642e01fSmrgDeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
19684642e01fSmrg        *pEvents, int count, Mask filter, GrabPtr grab, int mskidx)
196905b261ecSmrg{
197005b261ecSmrg    int deliveries = 0, nondeliveries = 0;
197105b261ecSmrg    int attempt;
197205b261ecSmrg    InputClients *other;
197305b261ecSmrg    ClientPtr client = NullClient;
197405b261ecSmrg    Mask deliveryMask = 0; /* If a grab occurs due to a button press, then
197505b261ecSmrg		              this mask is the mask of the grab. */
197605b261ecSmrg    int type = pEvents->u.u.type;
197705b261ecSmrg
197805b261ecSmrg    /* CantBeFiltered means only window owner gets the event */
19794642e01fSmrg    if ((filter == CantBeFiltered) ||
19804642e01fSmrg            (!(type & EXTENSION_EVENT_BASE) && type != GenericEvent))
198105b261ecSmrg    {
198205b261ecSmrg	/* if nobody ever wants to see this event, skip some work */
198305b261ecSmrg	if (filter != CantBeFiltered &&
198405b261ecSmrg	    !((wOtherEventMasks(pWin)|pWin->eventMask) & filter))
198505b261ecSmrg	    return 0;
19864642e01fSmrg
19874642e01fSmrg        if (!(type & EXTENSION_EVENT_BASE) &&
19884642e01fSmrg            IsInterferingGrab(wClient(pWin), pDev, pEvents))
19894642e01fSmrg                return 0;
19904642e01fSmrg
19914642e01fSmrg	if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
19924642e01fSmrg	    /* do nothing */;
19934642e01fSmrg        else if ( (attempt = TryClientEvents(wClient(pWin), pDev, pEvents,
19944642e01fSmrg                                             count, pWin->eventMask,
19954642e01fSmrg                                             filter, grab)) )
199605b261ecSmrg	{
199705b261ecSmrg	    if (attempt > 0)
199805b261ecSmrg	    {
199905b261ecSmrg		deliveries++;
200005b261ecSmrg		client = wClient(pWin);
200105b261ecSmrg		deliveryMask = pWin->eventMask;
200205b261ecSmrg	    } else
200305b261ecSmrg		nondeliveries--;
200405b261ecSmrg	}
200505b261ecSmrg    }
200605b261ecSmrg    if (filter != CantBeFiltered)
200705b261ecSmrg    {
20084642e01fSmrg        /* Handle generic events */
20094642e01fSmrg        if (type == GenericEvent)
20104642e01fSmrg        {
20114642e01fSmrg            GenericMaskPtr gmask;
20124642e01fSmrg            /* We don't do more than one GenericEvent at a time. */
20134642e01fSmrg            if (count > 1)
20144642e01fSmrg            {
20154642e01fSmrg                ErrorF("[dix] Do not send more than one GenericEvent at a time!\n");
20164642e01fSmrg                return 0;
20174642e01fSmrg            }
201805b261ecSmrg
20194642e01fSmrg            /* if we get here, filter should be set to the GE specific mask.
20204642e01fSmrg               check if any client wants it */
20214642e01fSmrg            if (!GEDeviceMaskIsSet(pWin, pDev, GEEXT(pEvents), filter))
20224642e01fSmrg                return 0;
20234642e01fSmrg
20244642e01fSmrg            /* run through all clients, deliver event */
20254642e01fSmrg            for (gmask = GECLIENT(pWin); gmask; gmask = gmask->next)
20264642e01fSmrg            {
20274642e01fSmrg                if (gmask->eventMask[GEEXTIDX(pEvents)] & filter)
20284642e01fSmrg                {
20294642e01fSmrg                    if (XaceHook(XACE_RECEIVE_ACCESS, rClient(gmask), pWin,
20304642e01fSmrg                                pEvents, count))
20314642e01fSmrg                        /* do nothing */;
20324642e01fSmrg                    else if (TryClientEvents(rClient(gmask), pDev,
20334642e01fSmrg                             pEvents, count,
20344642e01fSmrg                             gmask->eventMask[GEEXTIDX(pEvents)],
20354642e01fSmrg                             filter, grab) > 0)
20364642e01fSmrg                    {
20374642e01fSmrg                        deliveries++;
20384642e01fSmrg                    } else
20394642e01fSmrg                        nondeliveries--;
20404642e01fSmrg                }
20414642e01fSmrg            }
20424642e01fSmrg        }
20434642e01fSmrg        else {
20444642e01fSmrg            /* Traditional event */
20454642e01fSmrg            if (type & EXTENSION_EVENT_BASE)
20464642e01fSmrg            {
20474642e01fSmrg                OtherInputMasks *inputMasks;
20484642e01fSmrg
20494642e01fSmrg                inputMasks = wOtherInputMasks(pWin);
20504642e01fSmrg                if (!inputMasks ||
20514642e01fSmrg                        !(inputMasks->inputEvents[mskidx] & filter))
20524642e01fSmrg                    return 0;
20534642e01fSmrg                other = inputMasks->inputClients;
20544642e01fSmrg            }
20554642e01fSmrg            else
20564642e01fSmrg                other = (InputClients *)wOtherClients(pWin);
20574642e01fSmrg            for (; other; other = other->next)
20584642e01fSmrg            {
20594642e01fSmrg                /* core event? check for grab interference */
20604642e01fSmrg                if (!(type & EXTENSION_EVENT_BASE) &&
20614642e01fSmrg                        IsInterferingGrab(rClient(other), pDev, pEvents))
20624642e01fSmrg                    continue;
20634642e01fSmrg
20644642e01fSmrg                if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin,
20654642e01fSmrg                             pEvents, count))
20664642e01fSmrg                    /* do nothing */;
20674642e01fSmrg                else if ( (attempt = TryClientEvents(rClient(other), pDev,
20684642e01fSmrg                                                     pEvents, count,
20694642e01fSmrg                                                     other->mask[mskidx],
20704642e01fSmrg                                                     filter, grab)) )
20714642e01fSmrg                {
20724642e01fSmrg                    if (attempt > 0)
20734642e01fSmrg                    {
20744642e01fSmrg                        deliveries++;
20754642e01fSmrg                        client = rClient(other);
20764642e01fSmrg                        deliveryMask = other->mask[mskidx];
20774642e01fSmrg                    } else
20784642e01fSmrg                        nondeliveries--;
20794642e01fSmrg                }
20804642e01fSmrg            }
20814642e01fSmrg        }
208205b261ecSmrg    }
20834642e01fSmrg    /*
20844642e01fSmrg     * Note that since core events are delivered first, an implicit grab may
20854642e01fSmrg     * be activated on a core grab, stopping the XI events.
20864642e01fSmrg     */
20874642e01fSmrg    if ((type == DeviceButtonPress || type == ButtonPress)
20884642e01fSmrg            && deliveries
20894642e01fSmrg            && (!grab))
209005b261ecSmrg    {
209105b261ecSmrg	GrabRec tempGrab;
20924642e01fSmrg        OtherInputMasks *inputMasks;
209305b261ecSmrg
20944642e01fSmrg        tempGrab.next = NULL;
20954642e01fSmrg	tempGrab.device = pDev;
209605b261ecSmrg	tempGrab.resource = client->clientAsMask;
209705b261ecSmrg	tempGrab.window = pWin;
209805b261ecSmrg	tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
209905b261ecSmrg	tempGrab.eventMask = deliveryMask;
210005b261ecSmrg	tempGrab.keyboardMode = GrabModeAsync;
210105b261ecSmrg	tempGrab.pointerMode = GrabModeAsync;
210205b261ecSmrg	tempGrab.confineTo = NullWindow;
210305b261ecSmrg	tempGrab.cursor = NullCursor;
21044642e01fSmrg        tempGrab.coreGrab = (type == ButtonPress);
21054642e01fSmrg
21064642e01fSmrg        /* get the XI device mask */
21074642e01fSmrg        inputMasks = wOtherInputMasks(pWin);
21084642e01fSmrg        tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[pDev->id]: 0;
21094642e01fSmrg
21104642e01fSmrg        /* get the XGE event mask. */
21114642e01fSmrg        tempGrab.genericMasks = NULL;
21124642e01fSmrg        if (pWin->optional && pWin->optional->geMasks)
21134642e01fSmrg        {
21144642e01fSmrg            GenericClientMasksPtr gemasks = pWin->optional->geMasks;
21154642e01fSmrg            GenericMaskPtr geclient = gemasks->geClients;
21164642e01fSmrg            while(geclient && rClient(geclient) != client)
21174642e01fSmrg                geclient = geclient->next;
21184642e01fSmrg            if (geclient)
21194642e01fSmrg            {
21204642e01fSmrg                tempGrab.genericMasks = xcalloc(1, sizeof(GenericMaskRec));
21214642e01fSmrg                *tempGrab.genericMasks = *geclient;
21224642e01fSmrg                tempGrab.genericMasks->next = NULL;
21234642e01fSmrg            }
21244642e01fSmrg        }
21254642e01fSmrg	(*pDev->deviceGrab.ActivateGrab)(pDev, &tempGrab,
21264642e01fSmrg                                        currentTime, TRUE | ImplicitGrabMask);
212705b261ecSmrg    }
212805b261ecSmrg    else if ((type == MotionNotify) && deliveries)
21294642e01fSmrg	pDev->valuator->motionHintWindow = pWin;
213005b261ecSmrg    else
213105b261ecSmrg    {
213205b261ecSmrg	if (((type == DeviceMotionNotify)
213305b261ecSmrg#ifdef XKB
213405b261ecSmrg	     || (type == DeviceButtonPress)
213505b261ecSmrg#endif
213605b261ecSmrg	    ) && deliveries)
213705b261ecSmrg	    CheckDeviceGrabAndHintWindow (pWin, type,
213805b261ecSmrg					  (deviceKeyButtonPointer*) pEvents,
213905b261ecSmrg					  grab, client, deliveryMask);
214005b261ecSmrg    }
214105b261ecSmrg    if (deliveries)
214205b261ecSmrg	return deliveries;
214305b261ecSmrg    return nondeliveries;
214405b261ecSmrg}
214505b261ecSmrg
214605b261ecSmrg/* If the event goes to dontClient, don't send it and return 0.  if
214705b261ecSmrg   send works,  return 1 or if send didn't work, return 2.
214805b261ecSmrg   Only works for core events.
214905b261ecSmrg*/
215005b261ecSmrg
215105b261ecSmrg#ifdef PANORAMIX
21524642e01fSmrgstatic int
215305b261ecSmrgXineramaTryClientEventsResult(
215405b261ecSmrg    ClientPtr client,
215505b261ecSmrg    GrabPtr grab,
21564642e01fSmrg    Mask mask,
215705b261ecSmrg    Mask filter
215805b261ecSmrg){
215905b261ecSmrg    if ((client) && (client != serverClient) && (!client->clientGone) &&
216005b261ecSmrg        ((filter == CantBeFiltered) || (mask & filter)))
216105b261ecSmrg    {
216205b261ecSmrg        if (grab && !SameClient(grab, client)) return -1;
216305b261ecSmrg	else return 1;
216405b261ecSmrg    }
216505b261ecSmrg    return 0;
216605b261ecSmrg}
216705b261ecSmrg#endif
216805b261ecSmrg
216905b261ecSmrg/**
217005b261ecSmrg * Try to deliver events to the interested parties.
217105b261ecSmrg *
217205b261ecSmrg * @param pWin The window that would get the event.
217305b261ecSmrg * @param pEvents The events to be delivered.
217405b261ecSmrg * @param count Number of elements in pEvents.
217505b261ecSmrg * @param filter Mask based on event type.
217605b261ecSmrg * @param dontClient Don't deliver to the dontClient.
217705b261ecSmrg */
217805b261ecSmrgint
21794642e01fSmrgMaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
218005b261ecSmrg                           int count, Mask filter, ClientPtr dontClient)
218105b261ecSmrg{
218205b261ecSmrg    OtherClients *other;
218305b261ecSmrg
218405b261ecSmrg
218505b261ecSmrg    if (pWin->eventMask & filter)
218605b261ecSmrg    {
218705b261ecSmrg        if (wClient(pWin) == dontClient)
218805b261ecSmrg	    return 0;
218905b261ecSmrg#ifdef PANORAMIX
21904642e01fSmrg	if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
219105b261ecSmrg	    return XineramaTryClientEventsResult(
219205b261ecSmrg			wClient(pWin), NullGrab, pWin->eventMask, filter);
219305b261ecSmrg#endif
21944642e01fSmrg	if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
21954642e01fSmrg	    return 1; /* don't send, but pretend we did */
21964642e01fSmrg	return TryClientEvents(wClient(pWin), NULL, pEvents, count,
219705b261ecSmrg			       pWin->eventMask, filter, NullGrab);
219805b261ecSmrg    }
219905b261ecSmrg    for (other = wOtherClients(pWin); other; other = other->next)
220005b261ecSmrg    {
220105b261ecSmrg	if (other->mask & filter)
220205b261ecSmrg	{
220305b261ecSmrg            if (SameClient(other, dontClient))
220405b261ecSmrg		return 0;
220505b261ecSmrg#ifdef PANORAMIX
22064642e01fSmrg	    if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
220705b261ecSmrg	      return XineramaTryClientEventsResult(
220805b261ecSmrg			rClient(other), NullGrab, other->mask, filter);
220905b261ecSmrg#endif
22104642e01fSmrg	    if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents,
22114642e01fSmrg			 count))
22124642e01fSmrg		return 1; /* don't send, but pretend we did */
22134642e01fSmrg	    return TryClientEvents(rClient(other), NULL, pEvents, count,
221405b261ecSmrg				   other->mask, filter, NullGrab);
221505b261ecSmrg	}
221605b261ecSmrg    }
221705b261ecSmrg    return 2;
221805b261ecSmrg}
221905b261ecSmrg
222005b261ecSmrg/**
222105b261ecSmrg * Adjust event fields to comply with the window properties.
222205b261ecSmrg *
222305b261ecSmrg * @param xE Event to be modified in place
222405b261ecSmrg * @param pWin The window to get the information from.
222505b261ecSmrg * @param child Child window setting for event (if applicable)
222605b261ecSmrg * @param calcChild If True, calculate the child window.
222705b261ecSmrg */
222805b261ecSmrgstatic void
222905b261ecSmrgFixUpEventFromWindow(
22304642e01fSmrg    DeviceIntPtr pDev,
223105b261ecSmrg    xEvent *xE,
223205b261ecSmrg    WindowPtr pWin,
223305b261ecSmrg    Window child,
223405b261ecSmrg    Bool calcChild)
223505b261ecSmrg{
22364642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
22374642e01fSmrg
22384642e01fSmrg    if (xE->u.u.type == GenericEvent) /* just a safety barrier */
22394642e01fSmrg        return;
22404642e01fSmrg
224105b261ecSmrg    if (calcChild)
224205b261ecSmrg    {
22434642e01fSmrg        WindowPtr w= pSprite->spriteTrace[pSprite->spriteTraceGood-1];
22444642e01fSmrg	/* If the search ends up past the root should the child field be
22454642e01fSmrg		set to none or should the value in the argument be passed
22464642e01fSmrg		through. It probably doesn't matter since everyone calls
224705b261ecSmrg		this function with child == None anyway. */
224805b261ecSmrg
22494642e01fSmrg        while (w)
225005b261ecSmrg        {
225105b261ecSmrg            /* If the source window is same as event window, child should be
225205b261ecSmrg		none.  Don't bother going all all the way back to the root. */
225305b261ecSmrg
22544642e01fSmrg	    if (w == pWin)
22554642e01fSmrg	    {
22564642e01fSmrg		child = None;
22574642e01fSmrg		break;
225805b261ecSmrg	    }
22594642e01fSmrg
226005b261ecSmrg	    if (w->parent == pWin)
226105b261ecSmrg	    {
226205b261ecSmrg		child = w->drawable.id;
226305b261ecSmrg		break;
226405b261ecSmrg            }
22654642e01fSmrg	    w = w->parent;
22664642e01fSmrg        }
226705b261ecSmrg    }
22684642e01fSmrg    XE_KBPTR.root = RootWindow(pDev)->drawable.id;
226905b261ecSmrg    XE_KBPTR.event = pWin->drawable.id;
22704642e01fSmrg    if (pSprite->hot.pScreen == pWin->drawable.pScreen)
227105b261ecSmrg    {
227205b261ecSmrg	XE_KBPTR.sameScreen = xTrue;
227305b261ecSmrg	XE_KBPTR.child = child;
227405b261ecSmrg	XE_KBPTR.eventX =
227505b261ecSmrg	XE_KBPTR.rootX - pWin->drawable.x;
227605b261ecSmrg	XE_KBPTR.eventY =
227705b261ecSmrg	XE_KBPTR.rootY - pWin->drawable.y;
227805b261ecSmrg    }
227905b261ecSmrg    else
228005b261ecSmrg    {
228105b261ecSmrg	XE_KBPTR.sameScreen = xFalse;
228205b261ecSmrg	XE_KBPTR.child = None;
228305b261ecSmrg	XE_KBPTR.eventX = 0;
228405b261ecSmrg	XE_KBPTR.eventY = 0;
228505b261ecSmrg    }
228605b261ecSmrg}
228705b261ecSmrg
228805b261ecSmrg/**
22894642e01fSmrg * Deliver events caused by input devices. Called for both core input events
22904642e01fSmrg * and XI events.
22914642e01fSmrg * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is
22924642e01fSmrg * called directly from the processInputProc.
22934642e01fSmrg * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call
22944642e01fSmrg * DeliverDeviceEvents.
22954642e01fSmrg * For focused events, DeliverFocusedEvent is called first, and _may_ call
22964642e01fSmrg * DeliverDeviceEvents.
229705b261ecSmrg *
229805b261ecSmrg * @param pWin Window to deliver event to.
229905b261ecSmrg * @param xE Events to deliver.
230005b261ecSmrg * @param grab Possible grab on a device.
230105b261ecSmrg * @param stopAt Don't recurse up to the root window.
230205b261ecSmrg * @param dev The device that is responsible for the event.
230305b261ecSmrg * @param count number of events in xE.
230405b261ecSmrg *
23054642e01fSmrg * @see DeliverGrabbedEvent
23064642e01fSmrg * @see DeliverFocusedEvent
230705b261ecSmrg */
230805b261ecSmrgint
23094642e01fSmrgDeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab,
231005b261ecSmrg                    WindowPtr stopAt, DeviceIntPtr dev, int count)
231105b261ecSmrg{
231205b261ecSmrg    Window child = None;
231305b261ecSmrg    int type = xE->u.u.type;
23144642e01fSmrg    Mask filter = filters[dev->id][type];
231505b261ecSmrg    int deliveries = 0;
23164642e01fSmrg    OtherInputMasks *inputMasks;
23174642e01fSmrg    int mskidx = dev->id;
23184642e01fSmrg    xEvent core;
23194642e01fSmrg
23204642e01fSmrg    if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count))
23214642e01fSmrg	return 0;
232205b261ecSmrg
23234642e01fSmrg    /* handle generic events */
23244642e01fSmrg    /* XXX: Generic events aren't quite handled correctly yet. They should
23254642e01fSmrg     * eventually fit in with the rest of the stuff
23264642e01fSmrg     */
23274642e01fSmrg    if (type == GenericEvent)
232805b261ecSmrg    {
23294642e01fSmrg        WindowPtr win = pWin;
23304642e01fSmrg        xGenericEvent* ge = (xGenericEvent*)xE;
233105b261ecSmrg
23324642e01fSmrg        if (count > 1)
23334642e01fSmrg        {
23344642e01fSmrg            ErrorF("[dix] Do not send more than one GenericEvent at a time!\n");
23354642e01fSmrg            return 0;
23364642e01fSmrg        }
23374642e01fSmrg        filter = generic_filters[GEEXTIDX(xE)][ge->evtype];
23384642e01fSmrg
23394642e01fSmrg        while(win)
23404642e01fSmrg        {
23414642e01fSmrg            if (GEDeviceMaskIsSet(win, dev, GEEXT(xE), filter))
23424642e01fSmrg            {
23434642e01fSmrg                if (GEExtensions[GEEXTIDX(xE)].evfill)
23444642e01fSmrg                    GEExtensions[GEEXTIDX(xE)].evfill(ge, dev, win, grab);
23454642e01fSmrg                deliveries = DeliverEventsToWindow(dev, win, xE, count,
23464642e01fSmrg                        filter, grab, 0);
23474642e01fSmrg                if (deliveries > 0)
23484642e01fSmrg                    return deliveries;
23494642e01fSmrg            }
23504642e01fSmrg
23514642e01fSmrg            win = win->parent;
23524642e01fSmrg        }
235305b261ecSmrg    }
23544642e01fSmrg
23554642e01fSmrg    while (pWin && type != GenericEvent)
235605b261ecSmrg    {
23574642e01fSmrg        if (!dev->isMaster)
23584642e01fSmrg        {
23594642e01fSmrg            inputMasks = wOtherInputMasks(pWin);
23604642e01fSmrg            if (inputMasks && (filter & inputMasks->deliverableEvents[mskidx]))
23614642e01fSmrg            {
23624642e01fSmrg
23634642e01fSmrg                if (inputMasks && (inputMasks->inputEvents[mskidx] & filter))
23644642e01fSmrg                {
23654642e01fSmrg                    FixUpEventFromWindow(dev, xE, pWin, child, FALSE);
23664642e01fSmrg                    deliveries = DeliverEventsToWindow(dev, pWin, xE, count,
23674642e01fSmrg                            filter, grab, mskidx);
23684642e01fSmrg                    if (deliveries > 0)
23694642e01fSmrg                        return deliveries;
23704642e01fSmrg                }
23714642e01fSmrg            }
23724642e01fSmrg
23734642e01fSmrg            if ((deliveries < 0) || (pWin == stopAt) ||
23744642e01fSmrg                    (inputMasks && (filter & inputMasks->dontPropagateMask[mskidx])))
23754642e01fSmrg                return 0;
23764642e01fSmrg        } else
23774642e01fSmrg        {
23784642e01fSmrg            core = *xE;
23794642e01fSmrg            core.u.u.type = XItoCoreType(xE->u.u.type);
23804642e01fSmrg
23814642e01fSmrg            if (core.u.u.type && filter & pWin->deliverableEvents)
23824642e01fSmrg            {
23834642e01fSmrg                if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter)
23844642e01fSmrg                {
23854642e01fSmrg                    FixUpEventFromWindow(dev, &core, pWin, child, FALSE);
23864642e01fSmrg                    deliveries = DeliverEventsToWindow(dev, pWin, &core, 1,
23874642e01fSmrg                            filter, grab, 0);
23884642e01fSmrg                    if (deliveries > 0)
23894642e01fSmrg                        return deliveries;
23904642e01fSmrg                }
23914642e01fSmrg            }
23924642e01fSmrg
23934642e01fSmrg            if ((deliveries < 0) || (pWin == stopAt) ||
23944642e01fSmrg                (filter & wDontPropagateMask(pWin)))
23954642e01fSmrg                return 0;
23964642e01fSmrg        }
23974642e01fSmrg
23984642e01fSmrg        child = pWin->drawable.id;
23994642e01fSmrg        pWin = pWin->parent;
240005b261ecSmrg    }
24014642e01fSmrg
240205b261ecSmrg    return 0;
240305b261ecSmrg}
240405b261ecSmrg
240505b261ecSmrg/**
240605b261ecSmrg * Deliver event to a window and it's immediate parent. Used for most window
240705b261ecSmrg * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
24084642e01fSmrg * propagate up the tree or extension events
240905b261ecSmrg *
241005b261ecSmrg * In case of a ReparentNotify event, the event will be delivered to the
241105b261ecSmrg * otherParent as well.
241205b261ecSmrg *
241305b261ecSmrg * @param pWin Window to deliver events to.
241405b261ecSmrg * @param xE Events to deliver.
241505b261ecSmrg * @param count number of events in xE.
241605b261ecSmrg * @param otherParent Used for ReparentNotify events.
241705b261ecSmrg */
241805b261ecSmrg_X_EXPORT int
24194642e01fSmrgDeliverEvents(WindowPtr pWin, xEvent *xE, int count,
242005b261ecSmrg              WindowPtr otherParent)
242105b261ecSmrg{
242205b261ecSmrg    Mask filter;
242305b261ecSmrg    int     deliveries;
242405b261ecSmrg
242505b261ecSmrg#ifdef PANORAMIX
242605b261ecSmrg    if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
242705b261ecSmrg	return count;
242805b261ecSmrg#endif
242905b261ecSmrg
243005b261ecSmrg    if (!count)
243105b261ecSmrg	return 0;
24324642e01fSmrg    /* We don't know a device here. However, this should only ever be called
24334642e01fSmrg       for a non-device event so we are safe to use 0*/
24344642e01fSmrg    filter = filters[0][xE->u.u.type];
243505b261ecSmrg    if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify))
243605b261ecSmrg	xE->u.destroyNotify.event = pWin->drawable.id;
243705b261ecSmrg    if (filter != StructureAndSubMask)
24384642e01fSmrg	return DeliverEventsToWindow(inputInfo.pointer, pWin, xE, count, filter, NullGrab, 0);
24394642e01fSmrg    deliveries = DeliverEventsToWindow(inputInfo.pointer, pWin, xE, count, StructureNotifyMask,
244005b261ecSmrg				       NullGrab, 0);
244105b261ecSmrg    if (pWin->parent)
244205b261ecSmrg    {
244305b261ecSmrg	xE->u.destroyNotify.event = pWin->parent->drawable.id;
24444642e01fSmrg	deliveries += DeliverEventsToWindow(inputInfo.pointer, pWin->parent, xE, count,
244505b261ecSmrg					    SubstructureNotifyMask, NullGrab,
244605b261ecSmrg					    0);
244705b261ecSmrg	if (xE->u.u.type == ReparentNotify)
244805b261ecSmrg	{
244905b261ecSmrg	    xE->u.destroyNotify.event = otherParent->drawable.id;
24504642e01fSmrg            deliveries += DeliverEventsToWindow(inputInfo.pointer,
24514642e01fSmrg                    otherParent, xE, count, SubstructureNotifyMask,
245205b261ecSmrg						NullGrab, 0);
245305b261ecSmrg	}
245405b261ecSmrg    }
245505b261ecSmrg    return deliveries;
245605b261ecSmrg}
245705b261ecSmrg
245805b261ecSmrg
24594642e01fSmrgstatic Bool
246005b261ecSmrgPointInBorderSize(WindowPtr pWin, int x, int y)
246105b261ecSmrg{
246205b261ecSmrg    BoxRec box;
24634642e01fSmrg    SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
246405b261ecSmrg
246505b261ecSmrg    if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box))
246605b261ecSmrg	return TRUE;
246705b261ecSmrg
246805b261ecSmrg#ifdef PANORAMIX
24694642e01fSmrg    if(!noPanoramiXExtension &&
24704642e01fSmrg            XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
247105b261ecSmrg	int i;
247205b261ecSmrg
247305b261ecSmrg	for(i = 1; i < PanoramiXNumScreens; i++) {
24744642e01fSmrg	   if(POINT_IN_REGION(pSprite->screen,
24754642e01fSmrg			&pSprite->windows[i]->borderSize,
24764642e01fSmrg			x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x,
24774642e01fSmrg			y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y,
247805b261ecSmrg			&box))
247905b261ecSmrg		return TRUE;
248005b261ecSmrg	}
248105b261ecSmrg    }
248205b261ecSmrg#endif
248305b261ecSmrg    return FALSE;
248405b261ecSmrg}
248505b261ecSmrg
248605b261ecSmrg/**
248705b261ecSmrg * Traversed from the root window to the window at the position x/y. While
248805b261ecSmrg * traversing, it sets up the traversal history in the spriteTrace array.
248905b261ecSmrg * After completing, the spriteTrace history is set in the following way:
249005b261ecSmrg *   spriteTrace[0] ... root window
249105b261ecSmrg *   spriteTrace[1] ... top level window that encloses x/y
249205b261ecSmrg *       ...
249305b261ecSmrg *   spriteTrace[spriteTraceGood - 1] ... window at x/y
249405b261ecSmrg *
249505b261ecSmrg * @returns the window at the given coordinates.
249605b261ecSmrg */
24974642e01fSmrgstatic WindowPtr
24984642e01fSmrgXYToWindow(DeviceIntPtr pDev, int x, int y)
249905b261ecSmrg{
250005b261ecSmrg    WindowPtr  pWin;
250105b261ecSmrg    BoxRec		box;
25024642e01fSmrg    SpritePtr pSprite;
250305b261ecSmrg
25044642e01fSmrg    pSprite = pDev->spriteInfo->sprite;
25054642e01fSmrg    pSprite->spriteTraceGood = 1;	/* root window still there */
25064642e01fSmrg    pWin = RootWindow(pDev)->firstChild;
250705b261ecSmrg    while (pWin)
250805b261ecSmrg    {
250905b261ecSmrg	if ((pWin->mapped) &&
251005b261ecSmrg	    (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
251105b261ecSmrg	    (x < pWin->drawable.x + (int)pWin->drawable.width +
251205b261ecSmrg	     wBorderWidth(pWin)) &&
251305b261ecSmrg	    (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
251405b261ecSmrg	    (y < pWin->drawable.y + (int)pWin->drawable.height +
251505b261ecSmrg	     wBorderWidth (pWin))
251605b261ecSmrg	    /* When a window is shaped, a further check
251705b261ecSmrg	     * is made to see if the point is inside
251805b261ecSmrg	     * borderSize
251905b261ecSmrg	     */
252005b261ecSmrg	    && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
252105b261ecSmrg	    && (!wInputShape(pWin) ||
252205b261ecSmrg		POINT_IN_REGION(pWin->drawable.pScreen,
252305b261ecSmrg				wInputShape(pWin),
252405b261ecSmrg				x - pWin->drawable.x,
252505b261ecSmrg				y - pWin->drawable.y, &box))
25264642e01fSmrg#ifdef ROOTLESS
25274642e01fSmrg    /* In rootless mode windows may be offscreen, even when
25284642e01fSmrg     * they're in X's stack. (E.g. if the native window system
25294642e01fSmrg     * implements some form of virtual desktop system).
25304642e01fSmrg     */
25314642e01fSmrg		&& !pWin->rootlessUnhittable
253205b261ecSmrg#endif
253305b261ecSmrg	    )
253405b261ecSmrg	{
25354642e01fSmrg	    if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize)
253605b261ecSmrg	    {
25374642e01fSmrg		pSprite->spriteTraceSize += 10;
25384642e01fSmrg		pSprite->spriteTrace = xrealloc(pSprite->spriteTrace,
25394642e01fSmrg		                    pSprite->spriteTraceSize*sizeof(WindowPtr));
254005b261ecSmrg	    }
25414642e01fSmrg	    pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
254205b261ecSmrg	    pWin = pWin->firstChild;
254305b261ecSmrg	}
254405b261ecSmrg	else
254505b261ecSmrg	    pWin = pWin->nextSib;
254605b261ecSmrg    }
25474642e01fSmrg    return pSprite->spriteTrace[pSprite->spriteTraceGood-1];
254805b261ecSmrg}
254905b261ecSmrg
255005b261ecSmrg/**
255105b261ecSmrg * Update the sprite coordinates based on the event. Update the cursor
255205b261ecSmrg * position, then update the event with the new coordinates that may have been
255305b261ecSmrg * changed. If the window underneath the sprite has changed, change to new
255405b261ecSmrg * cursor and send enter/leave events.
25554642e01fSmrg *
25564642e01fSmrg * CheckMotion() will not do anything and return FALSE if the event is not a
25574642e01fSmrg * pointer event.
25584642e01fSmrg *
25594642e01fSmrg * @return TRUE if the sprite has moved or FALSE otherwise.
256005b261ecSmrg */
25614642e01fSmrgBool
25624642e01fSmrgCheckMotion(xEvent *xE, DeviceIntPtr pDev)
256305b261ecSmrg{
25644642e01fSmrg    INT16     *rootX, *rootY;
25654642e01fSmrg    WindowPtr prevSpriteWin;
25664642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
25674642e01fSmrg
25684642e01fSmrg    prevSpriteWin = pSprite->win;
256905b261ecSmrg
257005b261ecSmrg#ifdef PANORAMIX
257105b261ecSmrg    if(!noPanoramiXExtension)
25724642e01fSmrg	return XineramaCheckMotion(xE, pDev);
257305b261ecSmrg#endif
257405b261ecSmrg
257505b261ecSmrg    if (xE && !syncEvents.playingEvents)
257605b261ecSmrg    {
25774642e01fSmrg        /* GetPointerEvents() guarantees that pointer events have the correct
25784642e01fSmrg           rootX/Y set already. */
25794642e01fSmrg        switch(xE->u.u.type)
25804642e01fSmrg        {
25814642e01fSmrg            case ButtonPress:
25824642e01fSmrg            case ButtonRelease:
25834642e01fSmrg            case MotionNotify:
25844642e01fSmrg                rootX = &XE_KBPTR.rootX;
25854642e01fSmrg                rootY = &XE_KBPTR.rootY;
25864642e01fSmrg                break;
25874642e01fSmrg            default:
25884642e01fSmrg                if (xE->u.u.type == DeviceButtonPress ||
25894642e01fSmrg                        xE->u.u.type == DeviceButtonRelease ||
25904642e01fSmrg                        xE->u.u.type == DeviceMotionNotify)
25914642e01fSmrg                {
25924642e01fSmrg                    rootX = &((deviceKeyButtonPointer*)xE)->root_x;
25934642e01fSmrg                    rootY = &((deviceKeyButtonPointer*)xE)->root_y;
25944642e01fSmrg                    break;
25954642e01fSmrg                }
25964642e01fSmrg                /* all other events return FALSE */
25974642e01fSmrg                return FALSE;
25984642e01fSmrg        }
25994642e01fSmrg
26004642e01fSmrg        if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen)
26014642e01fSmrg        {
26024642e01fSmrg            pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
26034642e01fSmrg            RootWindow(pDev) = WindowTable[pSprite->hot.pScreen->myNum];
26044642e01fSmrg        }
26054642e01fSmrg        pSprite->hot.x = *rootX;
26064642e01fSmrg        pSprite->hot.y = *rootY;
26074642e01fSmrg        if (pSprite->hot.x < pSprite->physLimits.x1)
26084642e01fSmrg            pSprite->hot.x = pSprite->physLimits.x1;
26094642e01fSmrg        else if (pSprite->hot.x >= pSprite->physLimits.x2)
26104642e01fSmrg            pSprite->hot.x = pSprite->physLimits.x2 - 1;
26114642e01fSmrg        if (pSprite->hot.y < pSprite->physLimits.y1)
26124642e01fSmrg            pSprite->hot.y = pSprite->physLimits.y1;
26134642e01fSmrg        else if (pSprite->hot.y >= pSprite->physLimits.y2)
26144642e01fSmrg            pSprite->hot.y = pSprite->physLimits.y2 - 1;
26154642e01fSmrg	if (pSprite->hotShape)
26164642e01fSmrg	    ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y);
26174642e01fSmrg	pSprite->hotPhys = pSprite->hot;
26184642e01fSmrg
26194642e01fSmrg	if ((pSprite->hotPhys.x != *rootX) ||
26204642e01fSmrg	    (pSprite->hotPhys.y != *rootY))
262105b261ecSmrg	{
26224642e01fSmrg	    (*pSprite->hotPhys.pScreen->SetCursorPosition)(
26234642e01fSmrg                pDev, pSprite->hotPhys.pScreen,
26244642e01fSmrg		pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
262505b261ecSmrg	}
26264642e01fSmrg
26274642e01fSmrg	*rootX = pSprite->hot.x;
26284642e01fSmrg	*rootY = pSprite->hot.y;
262905b261ecSmrg    }
263005b261ecSmrg
26314642e01fSmrg    pSprite->win = XYToWindow(pDev, pSprite->hot.x, pSprite->hot.y);
263205b261ecSmrg#ifdef notyet
26334642e01fSmrg    if (!(pSprite->win->deliverableEvents &
26344642e01fSmrg	  Motion_Filter(pDev->button))
263505b261ecSmrg	!syncEvents.playingEvents)
263605b261ecSmrg    {
263705b261ecSmrg	/* XXX Do PointerNonInterestBox here */
263805b261ecSmrg    }
263905b261ecSmrg#endif
26404642e01fSmrg    if (pSprite->win != prevSpriteWin)
264105b261ecSmrg    {
264205b261ecSmrg	if (prevSpriteWin != NullWindow) {
264305b261ecSmrg	    if (!xE)
264405b261ecSmrg		UpdateCurrentTimeIf();
26454642e01fSmrg            DoEnterLeaveEvents(pDev, prevSpriteWin, pSprite->win,
26464642e01fSmrg                               NotifyNormal);
26474642e01fSmrg        }
26484642e01fSmrg	PostNewCursor(pDev);
264905b261ecSmrg        return FALSE;
265005b261ecSmrg    }
265105b261ecSmrg    return TRUE;
265205b261ecSmrg}
265305b261ecSmrg
265405b261ecSmrg/**
265505b261ecSmrg * Windows have restructured, we need to update the sprite position and the
265605b261ecSmrg * sprite's cursor.
265705b261ecSmrg */
26584642e01fSmrgvoid
265905b261ecSmrgWindowsRestructured(void)
266005b261ecSmrg{
26614642e01fSmrg    DeviceIntPtr pDev = inputInfo.devices;
26624642e01fSmrg    while(pDev)
26634642e01fSmrg    {
26644642e01fSmrg        if (DevHasCursor(pDev))
26654642e01fSmrg            CheckMotion((xEvent *)NULL, pDev);
26664642e01fSmrg        pDev = pDev->next;
26674642e01fSmrg    }
266805b261ecSmrg}
266905b261ecSmrg
267005b261ecSmrg#ifdef PANORAMIX
267105b261ecSmrg/* This was added to support reconfiguration under Xdmx.  The problem is
267205b261ecSmrg * that if the 0th screen (i.e., WindowTable[0]) is moved to an origin
267305b261ecSmrg * other than 0,0, the information in the private sprite structure must
267405b261ecSmrg * be updated accordingly, or XYToWindow (and other routines) will not
267505b261ecSmrg * compute correctly. */
267605b261ecSmrgvoid ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
267705b261ecSmrg{
267805b261ecSmrg    GrabPtr   grab;
26794642e01fSmrg    DeviceIntPtr pDev;
26804642e01fSmrg    SpritePtr pSprite;
268105b261ecSmrg
268205b261ecSmrg    if (noPanoramiXExtension) return;
268305b261ecSmrg
26844642e01fSmrg    pDev = inputInfo.devices;
26854642e01fSmrg    while(pDev)
26864642e01fSmrg    {
26874642e01fSmrg        if (DevHasCursor(pDev))
26884642e01fSmrg        {
26894642e01fSmrg            pSprite = pDev->spriteInfo->sprite;
26904642e01fSmrg            pSprite->hot.x        -= xoff;
26914642e01fSmrg            pSprite->hot.y        -= yoff;
26924642e01fSmrg
26934642e01fSmrg            pSprite->hotPhys.x    -= xoff;
26944642e01fSmrg            pSprite->hotPhys.y    -= yoff;
26954642e01fSmrg
26964642e01fSmrg            pSprite->hotLimits.x1 -= xoff;
26974642e01fSmrg            pSprite->hotLimits.y1 -= yoff;
26984642e01fSmrg            pSprite->hotLimits.x2 -= xoff;
26994642e01fSmrg            pSprite->hotLimits.y2 -= yoff;
27004642e01fSmrg
27014642e01fSmrg            if (REGION_NOTEMPTY(pSprite->screen, &pSprite->Reg1))
27024642e01fSmrg                REGION_TRANSLATE(pSprite->screen, &pSprite->Reg1,    xoff, yoff);
27034642e01fSmrg            if (REGION_NOTEMPTY(pSprite->screen, &pSprite->Reg2))
27044642e01fSmrg                REGION_TRANSLATE(pSprite->screen, &pSprite->Reg2,    xoff, yoff);
27054642e01fSmrg
27064642e01fSmrg            /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
27074642e01fSmrg            if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
27084642e01fSmrg                if (grab->confineTo->drawable.pScreen
27094642e01fSmrg                        != pSprite->hotPhys.pScreen)
27104642e01fSmrg                    pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
27114642e01fSmrg                ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
27124642e01fSmrg            } else
27134642e01fSmrg                ConfineCursorToWindow(
27144642e01fSmrg                        pDev,
27154642e01fSmrg                        WindowTable[pSprite->hotPhys.pScreen->myNum],
27164642e01fSmrg                        TRUE, FALSE);
27174642e01fSmrg
27184642e01fSmrg        }
27194642e01fSmrg        pDev = pDev->next;
27204642e01fSmrg    }
27214642e01fSmrg}
27224642e01fSmrg#endif
27234642e01fSmrg
27244642e01fSmrg/**
27254642e01fSmrg * Called from main() with the root window on the first screen. Used to do a
27264642e01fSmrg * lot more when MPX wasn't around yet. Things change.
27274642e01fSmrg *
27284642e01fSmrg * Should delete this now? -ds
27294642e01fSmrg */
27304642e01fSmrgvoid
273105b261ecSmrgDefineInitialRootWindow(WindowPtr win)
273205b261ecSmrg{
27334642e01fSmrg}
27344642e01fSmrg
27354642e01fSmrg/**
27364642e01fSmrg * Initialize a sprite for the given device and set it to some sane values. If
27374642e01fSmrg * the device already has a sprite alloc'd, don't realloc but just reset to
27384642e01fSmrg * default values.
27394642e01fSmrg * If a window is supplied, the sprite will be initialized with the window's
27404642e01fSmrg * cursor and positioned in the center of the window's screen. The root window
27414642e01fSmrg * is a good choice to pass in here.
27424642e01fSmrg *
27434642e01fSmrg * It's a good idea to call it only for pointer devices, unless you have a
27444642e01fSmrg * really talented keyboard.
27454642e01fSmrg *
27464642e01fSmrg * @param pDev The device to initialize.
27474642e01fSmrg * @param pWin The window where to generate the sprite in.
27484642e01fSmrg *
27494642e01fSmrg */
27504642e01fSmrgvoid
27514642e01fSmrgInitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
27524642e01fSmrg{
27534642e01fSmrg    SpritePtr pSprite;
27544642e01fSmrg    ScreenPtr pScreen;
27554642e01fSmrg
27564642e01fSmrg    if (!pDev->spriteInfo->sprite)
27574642e01fSmrg    {
27584642e01fSmrg        DeviceIntPtr it;
27594642e01fSmrg
27604642e01fSmrg        pDev->spriteInfo->sprite = (SpritePtr)xcalloc(1, sizeof(SpriteRec));
27614642e01fSmrg        if (!pDev->spriteInfo->sprite)
27624642e01fSmrg            FatalError("InitializeSprite: failed to allocate sprite struct");
27634642e01fSmrg
27644642e01fSmrg        /* We may have paired another device with this device before our
27654642e01fSmrg         * device had a actual sprite. We need to check for this and reset the
27664642e01fSmrg         * sprite field for all paired devices.
27674642e01fSmrg         *
27684642e01fSmrg         * The VCK is always paired with the VCP before the VCP has a sprite.
27694642e01fSmrg         */
27704642e01fSmrg        for (it = inputInfo.devices; it; it = it->next)
27714642e01fSmrg        {
27724642e01fSmrg            if (it->spriteInfo->paired == pDev)
27734642e01fSmrg                it->spriteInfo->sprite = pDev->spriteInfo->sprite;
27744642e01fSmrg        }
27754642e01fSmrg        if (inputInfo.keyboard->spriteInfo->paired == pDev)
27764642e01fSmrg            inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite;
27774642e01fSmrg    }
27784642e01fSmrg
27794642e01fSmrg    pSprite = pDev->spriteInfo->sprite;
27804642e01fSmrg    pDev->spriteInfo->spriteOwner = TRUE;
278105b261ecSmrg
27824642e01fSmrg    pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr)NULL;
27834642e01fSmrg    pSprite->hot.pScreen = pScreen;
27844642e01fSmrg    pSprite->hotPhys.pScreen = pScreen;
27854642e01fSmrg    if (pScreen)
27864642e01fSmrg    {
27874642e01fSmrg        pSprite->hotPhys.x = pScreen->width / 2;
27884642e01fSmrg        pSprite->hotPhys.y = pScreen->height / 2;
27894642e01fSmrg        pSprite->hotLimits.x2 = pScreen->width;
27904642e01fSmrg        pSprite->hotLimits.y2 = pScreen->height;
27914642e01fSmrg    }
27924642e01fSmrg
27934642e01fSmrg    pSprite->hot = pSprite->hotPhys;
27944642e01fSmrg    pSprite->win = pWin;
27954642e01fSmrg
27964642e01fSmrg    if (pWin)
27974642e01fSmrg    {
27984642e01fSmrg        pSprite->current = wCursor(pWin);
27994642e01fSmrg        pSprite->current->refcnt++;
28004642e01fSmrg	pSprite->spriteTrace = (WindowPtr *)xcalloc(1, 32*sizeof(WindowPtr));
28014642e01fSmrg	if (!pSprite->spriteTrace)
28024642e01fSmrg	    FatalError("Failed to allocate spriteTrace");
28034642e01fSmrg	pSprite->spriteTraceSize = 32;
28044642e01fSmrg
28054642e01fSmrg	RootWindow(pDev) = pWin;
28064642e01fSmrg	pSprite->spriteTraceGood = 1;
28074642e01fSmrg
28084642e01fSmrg	pSprite->pEnqueueScreen = pScreen;
28094642e01fSmrg	pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
28104642e01fSmrg
28114642e01fSmrg    } else {
28124642e01fSmrg        pSprite->current = NullCursor;
28134642e01fSmrg	pSprite->spriteTrace = NULL;
28144642e01fSmrg	pSprite->spriteTraceSize = 0;
28154642e01fSmrg	pSprite->spriteTraceGood = 0;
28164642e01fSmrg	pSprite->pEnqueueScreen = screenInfo.screens[0];
28174642e01fSmrg	pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
28184642e01fSmrg    }
28194642e01fSmrg
28204642e01fSmrg    if (pScreen)
28214642e01fSmrg    {
28224642e01fSmrg        (*pScreen->RealizeCursor) ( pDev, pScreen, pSprite->current);
28234642e01fSmrg        (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current,
28244642e01fSmrg                                   &pSprite->hotLimits, &pSprite->physLimits);
28254642e01fSmrg        pSprite->confined = FALSE;
28264642e01fSmrg
28274642e01fSmrg        (*pScreen->ConstrainCursor) (pDev, pScreen,
28284642e01fSmrg                                     &pSprite->physLimits);
28294642e01fSmrg        (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
28304642e01fSmrg                                       pSprite->hot.y,
28314642e01fSmrg                                       FALSE);
28324642e01fSmrg        (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
28334642e01fSmrg    }
283405b261ecSmrg#ifdef PANORAMIX
283505b261ecSmrg    if(!noPanoramiXExtension) {
28364642e01fSmrg        pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x;
28374642e01fSmrg        pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y;
28384642e01fSmrg        pSprite->hotLimits.x2 = PanoramiXPixWidth  - panoramiXdataPtr[0].x;
28394642e01fSmrg        pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
28404642e01fSmrg        pSprite->physLimits = pSprite->hotLimits;
28414642e01fSmrg        pSprite->confineWin = NullWindow;
28424642e01fSmrg        pSprite->hotShape = NullRegion;
28434642e01fSmrg        pSprite->screen = pScreen;
28444642e01fSmrg        /* gotta UNINIT these someplace */
28454642e01fSmrg        REGION_NULL(pScreen, &pSprite->Reg1);
28464642e01fSmrg        REGION_NULL(pScreen, &pSprite->Reg2);
28474642e01fSmrg    }
284805b261ecSmrg#endif
28494642e01fSmrg}
28504642e01fSmrg
28514642e01fSmrg/**
28524642e01fSmrg * Update the mouse sprite info when the server switches from a pScreen to another.
28534642e01fSmrg * Otherwise, the pScreen of the mouse sprite is never updated when we switch
28544642e01fSmrg * from a pScreen to another. Never updating the pScreen of the mouse sprite
28554642e01fSmrg * implies that windows that are in pScreen whose pScreen->myNum >0 will never
28564642e01fSmrg * get pointer events. This is  because in CheckMotion(), sprite.hotPhys.pScreen
28574642e01fSmrg * always points to the first pScreen it has been set by
28584642e01fSmrg * DefineInitialRootWindow().
28594642e01fSmrg *
28604642e01fSmrg * Calling this function is useful for use cases where the server
28614642e01fSmrg * has more than one pScreen.
28624642e01fSmrg * This function is similar to DefineInitialRootWindow() but it does not
28634642e01fSmrg * reset the mouse pointer position.
28644642e01fSmrg * @param win must be the new pScreen we are switching to.
28654642e01fSmrg */
28664642e01fSmrgvoid
28674642e01fSmrgUpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
28684642e01fSmrg{
28694642e01fSmrg    SpritePtr pSprite = NULL;
28704642e01fSmrg    WindowPtr win = NULL;
28714642e01fSmrg    if (!pScreen)
28724642e01fSmrg        return ;
28734642e01fSmrg
28744642e01fSmrg    if (!pDev->spriteInfo->sprite)
28754642e01fSmrg        return;
28764642e01fSmrg
28774642e01fSmrg    pSprite = pDev->spriteInfo->sprite;
28784642e01fSmrg
28794642e01fSmrg    win = WindowTable[pScreen->myNum];
28804642e01fSmrg
28814642e01fSmrg    pSprite->hotPhys.pScreen = pScreen;
28824642e01fSmrg    pSprite->hot = pSprite->hotPhys;
28834642e01fSmrg    pSprite->hotLimits.x2 = pScreen->width;
28844642e01fSmrg    pSprite->hotLimits.y2 = pScreen->height;
28854642e01fSmrg    pSprite->win = win;
28864642e01fSmrg    pSprite->current = wCursor (win);
28874642e01fSmrg    pSprite->current->refcnt++;
28884642e01fSmrg    pSprite->spriteTraceGood = 1;
28894642e01fSmrg    pSprite->spriteTrace[0] = win;
28904642e01fSmrg    (*pScreen->CursorLimits) (pDev,
28914642e01fSmrg                              pScreen,
28924642e01fSmrg                              pSprite->current,
28934642e01fSmrg                              &pSprite->hotLimits,
28944642e01fSmrg                              &pSprite->physLimits);
28954642e01fSmrg    pSprite->confined = FALSE;
28964642e01fSmrg    (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
28974642e01fSmrg    (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
28984642e01fSmrg
28994642e01fSmrg#ifdef PANORAMIX
29004642e01fSmrg    if(!noPanoramiXExtension) {
29014642e01fSmrg        pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x;
29024642e01fSmrg        pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y;
29034642e01fSmrg        pSprite->hotLimits.x2 = PanoramiXPixWidth  - panoramiXdataPtr[0].x;
29044642e01fSmrg        pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
29054642e01fSmrg        pSprite->physLimits = pSprite->hotLimits;
29064642e01fSmrg        pSprite->screen = pScreen;
290705b261ecSmrg    }
290805b261ecSmrg#endif
290905b261ecSmrg}
291005b261ecSmrg
291105b261ecSmrg/*
291205b261ecSmrg * This does not take any shortcuts, and even ignores its argument, since
291305b261ecSmrg * it does not happen very often, and one has to walk up the tree since
291405b261ecSmrg * this might be a newly instantiated cursor for an intermediate window
291505b261ecSmrg * between the one the pointer is in and the one that the last cursor was
291605b261ecSmrg * instantiated from.
291705b261ecSmrg */
291805b261ecSmrgvoid
291905b261ecSmrgWindowHasNewCursor(WindowPtr pWin)
292005b261ecSmrg{
29214642e01fSmrg    DeviceIntPtr pDev;
29224642e01fSmrg
29234642e01fSmrg    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
29244642e01fSmrg        if (DevHasCursor(pDev))
29254642e01fSmrg            PostNewCursor(pDev);
292605b261ecSmrg}
292705b261ecSmrg
292805b261ecSmrg_X_EXPORT void
29294642e01fSmrgNewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
293005b261ecSmrg{
29314642e01fSmrg    SpritePtr pSprite = pDev->spriteInfo->sprite;
29324642e01fSmrg
29334642e01fSmrg    pSprite->hotPhys.x = x;
29344642e01fSmrg    pSprite->hotPhys.y = y;
293505b261ecSmrg#ifdef PANORAMIX
293605b261ecSmrg    if(!noPanoramiXExtension) {
29374642e01fSmrg	pSprite->hotPhys.x += panoramiXdataPtr[newScreen->myNum].x -
293805b261ecSmrg			    panoramiXdataPtr[0].x;
29394642e01fSmrg	pSprite->hotPhys.y += panoramiXdataPtr[newScreen->myNum].y -
294005b261ecSmrg			    panoramiXdataPtr[0].y;
29414642e01fSmrg	if (newScreen != pSprite->screen) {
29424642e01fSmrg	    pSprite->screen = newScreen;
294305b261ecSmrg	    /* Make sure we tell the DDX to update its copy of the screen */
29444642e01fSmrg	    if(pSprite->confineWin)
29454642e01fSmrg		XineramaConfineCursorToWindow(pDev,
29464642e01fSmrg                        pSprite->confineWin, TRUE);
294705b261ecSmrg	    else
29484642e01fSmrg		XineramaConfineCursorToWindow(pDev, WindowTable[0], TRUE);
29494642e01fSmrg	    /* if the pointer wasn't confined, the DDX won't get
295005b261ecSmrg	       told of the pointer warp so we reposition it here */
295105b261ecSmrg	    if(!syncEvents.playingEvents)
29524642e01fSmrg		(*pSprite->screen->SetCursorPosition)(
29534642e01fSmrg                                                      pDev,
29544642e01fSmrg                                                      pSprite->screen,
29554642e01fSmrg		    pSprite->hotPhys.x + panoramiXdataPtr[0].x -
29564642e01fSmrg			panoramiXdataPtr[pSprite->screen->myNum].x,
29574642e01fSmrg		    pSprite->hotPhys.y + panoramiXdataPtr[0].y -
29584642e01fSmrg			panoramiXdataPtr[pSprite->screen->myNum].y, FALSE);
295905b261ecSmrg	}
29604642e01fSmrg    } else
296105b261ecSmrg#endif
29624642e01fSmrg    if (newScreen != pSprite->hotPhys.pScreen)
29634642e01fSmrg	ConfineCursorToWindow(pDev, WindowTable[newScreen->myNum],
29644642e01fSmrg                TRUE, FALSE);
296505b261ecSmrg}
296605b261ecSmrg
296705b261ecSmrg#ifdef PANORAMIX
296805b261ecSmrg
296905b261ecSmrgstatic Bool
297005b261ecSmrgXineramaPointInWindowIsVisible(
297105b261ecSmrg    WindowPtr pWin,
297205b261ecSmrg    int x,
297305b261ecSmrg    int y
297405b261ecSmrg)
297505b261ecSmrg{
297605b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
297705b261ecSmrg    BoxRec box;
297805b261ecSmrg    int i, xoff, yoff;
297905b261ecSmrg
298005b261ecSmrg    if (!pWin->realized) return FALSE;
298105b261ecSmrg
298205b261ecSmrg    if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box))
298305b261ecSmrg        return TRUE;
298405b261ecSmrg
29854642e01fSmrg    if(!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) return FALSE;
29864642e01fSmrg
29874642e01fSmrg    xoff = x + panoramiXdataPtr[0].x;
29884642e01fSmrg    yoff = y + panoramiXdataPtr[0].y;
298905b261ecSmrg
299005b261ecSmrg    for(i = 1; i < PanoramiXNumScreens; i++) {
29914642e01fSmrg	pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
299205b261ecSmrg	pScreen = pWin->drawable.pScreen;
299305b261ecSmrg	x = xoff - panoramiXdataPtr[i].x;
299405b261ecSmrg	y = yoff - panoramiXdataPtr[i].y;
299505b261ecSmrg
299605b261ecSmrg	if(POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)
299705b261ecSmrg	   && (!wInputShape(pWin) ||
299805b261ecSmrg	       POINT_IN_REGION(pWin->drawable.pScreen,
299905b261ecSmrg			       wInputShape(pWin),
30004642e01fSmrg			       x - pWin->drawable.x,
300105b261ecSmrg			       y - pWin->drawable.y, &box)))
300205b261ecSmrg            return TRUE;
300305b261ecSmrg
300405b261ecSmrg    }
300505b261ecSmrg
300605b261ecSmrg    return FALSE;
300705b261ecSmrg}
300805b261ecSmrg
300905b261ecSmrgstatic int
301005b261ecSmrgXineramaWarpPointer(ClientPtr client)
301105b261ecSmrg{
301205b261ecSmrg    WindowPtr	dest = NULL;
301305b261ecSmrg    int		x, y, rc;
30144642e01fSmrg    SpritePtr   pSprite = PickPointer(client)->spriteInfo->sprite;
301505b261ecSmrg
301605b261ecSmrg    REQUEST(xWarpPointerReq);
301705b261ecSmrg
301805b261ecSmrg
301905b261ecSmrg    if (stuff->dstWid != None) {
302005b261ecSmrg	rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
302105b261ecSmrg	if (rc != Success)
302205b261ecSmrg	    return rc;
302305b261ecSmrg    }
30244642e01fSmrg    x = pSprite->hotPhys.x;
30254642e01fSmrg    y = pSprite->hotPhys.y;
302605b261ecSmrg
302705b261ecSmrg    if (stuff->srcWid != None)
302805b261ecSmrg    {
302905b261ecSmrg	int     winX, winY;
30304642e01fSmrg	XID	winID = stuff->srcWid;
303105b261ecSmrg        WindowPtr source;
30324642e01fSmrg
303305b261ecSmrg	rc = dixLookupWindow(&source, winID, client, DixReadAccess);
303405b261ecSmrg	if (rc != Success)
303505b261ecSmrg	    return rc;
303605b261ecSmrg
303705b261ecSmrg	winX = source->drawable.x;
303805b261ecSmrg	winY = source->drawable.y;
303905b261ecSmrg	if(source == WindowTable[0]) {
304005b261ecSmrg	    winX -= panoramiXdataPtr[0].x;
304105b261ecSmrg	    winY -= panoramiXdataPtr[0].y;
304205b261ecSmrg	}
304305b261ecSmrg	if (x < winX + stuff->srcX ||
304405b261ecSmrg	    y < winY + stuff->srcY ||
304505b261ecSmrg	    (stuff->srcWidth != 0 &&
304605b261ecSmrg	     winX + stuff->srcX + (int)stuff->srcWidth < x) ||
304705b261ecSmrg	    (stuff->srcHeight != 0 &&
304805b261ecSmrg	     winY + stuff->srcY + (int)stuff->srcHeight < y) ||
304905b261ecSmrg	    !XineramaPointInWindowIsVisible(source, x, y))
305005b261ecSmrg	    return Success;
305105b261ecSmrg    }
305205b261ecSmrg    if (dest) {
305305b261ecSmrg	x = dest->drawable.x;
305405b261ecSmrg	y = dest->drawable.y;
305505b261ecSmrg	if(dest == WindowTable[0]) {
305605b261ecSmrg	    x -= panoramiXdataPtr[0].x;
305705b261ecSmrg	    y -= panoramiXdataPtr[0].y;
305805b261ecSmrg	}
30594642e01fSmrg    }
306005b261ecSmrg
306105b261ecSmrg    x += stuff->dstX;
306205b261ecSmrg    y += stuff->dstY;
306305b261ecSmrg
30644642e01fSmrg    if (x < pSprite->physLimits.x1)
30654642e01fSmrg	x = pSprite->physLimits.x1;
30664642e01fSmrg    else if (x >= pSprite->physLimits.x2)
30674642e01fSmrg	x = pSprite->physLimits.x2 - 1;
30684642e01fSmrg    if (y < pSprite->physLimits.y1)
30694642e01fSmrg	y = pSprite->physLimits.y1;
30704642e01fSmrg    else if (y >= pSprite->physLimits.y2)
30714642e01fSmrg	y = pSprite->physLimits.y2 - 1;
30724642e01fSmrg    if (pSprite->hotShape)
30734642e01fSmrg	ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
307405b261ecSmrg
30754642e01fSmrg    XineramaSetCursorPosition(PickPointer(client), x, y, TRUE);
307605b261ecSmrg
307705b261ecSmrg    return Success;
307805b261ecSmrg}
307905b261ecSmrg
308005b261ecSmrg#endif
308105b261ecSmrg
308205b261ecSmrg
308305b261ecSmrg/**
308405b261ecSmrg * Server-side protocol handling for WarpPointer request.
308505b261ecSmrg * Warps the cursor position to the coordinates given in the request.
308605b261ecSmrg */
308705b261ecSmrgint
308805b261ecSmrgProcWarpPointer(ClientPtr client)
308905b261ecSmrg{
309005b261ecSmrg    WindowPtr	dest = NULL;
309105b261ecSmrg    int		x, y, rc;
309205b261ecSmrg    ScreenPtr	newScreen;
30934642e01fSmrg    DeviceIntPtr dev;
30944642e01fSmrg    SpritePtr   pSprite;
309505b261ecSmrg
309605b261ecSmrg    REQUEST(xWarpPointerReq);
309705b261ecSmrg    REQUEST_SIZE_MATCH(xWarpPointerReq);
309805b261ecSmrg
30994642e01fSmrg    /* XXX XACE ??*/
31004642e01fSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
31014642e01fSmrg        if ((dev->coreEvents || dev == inputInfo.pointer) && dev->button) {
31024642e01fSmrg	    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
31034642e01fSmrg	    if (rc != Success)
31044642e01fSmrg		return rc;
31054642e01fSmrg	}
31064642e01fSmrg    }
31074642e01fSmrg
31084642e01fSmrg    dev = PickPointer(client);
31094642e01fSmrg    if (dev->u.lastSlave)
31104642e01fSmrg        dev = dev->u.lastSlave;
31114642e01fSmrg    pSprite = dev->spriteInfo->sprite;
31124642e01fSmrg
311305b261ecSmrg#ifdef PANORAMIX
311405b261ecSmrg    if(!noPanoramiXExtension)
311505b261ecSmrg	return XineramaWarpPointer(client);
311605b261ecSmrg#endif
311705b261ecSmrg
311805b261ecSmrg    if (stuff->dstWid != None) {
31194642e01fSmrg	rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess);
312005b261ecSmrg	if (rc != Success)
312105b261ecSmrg	    return rc;
312205b261ecSmrg    }
31234642e01fSmrg    x = pSprite->hotPhys.x;
31244642e01fSmrg    y = pSprite->hotPhys.y;
312505b261ecSmrg
312605b261ecSmrg    if (stuff->srcWid != None)
312705b261ecSmrg    {
312805b261ecSmrg	int     winX, winY;
31294642e01fSmrg	XID	winID = stuff->srcWid;
313005b261ecSmrg        WindowPtr source;
31314642e01fSmrg
31324642e01fSmrg	rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess);
313305b261ecSmrg	if (rc != Success)
313405b261ecSmrg	    return rc;
313505b261ecSmrg
313605b261ecSmrg	winX = source->drawable.x;
313705b261ecSmrg	winY = source->drawable.y;
31384642e01fSmrg	if (source->drawable.pScreen != pSprite->hotPhys.pScreen ||
313905b261ecSmrg	    x < winX + stuff->srcX ||
314005b261ecSmrg	    y < winY + stuff->srcY ||
314105b261ecSmrg	    (stuff->srcWidth != 0 &&
314205b261ecSmrg	     winX + stuff->srcX + (int)stuff->srcWidth < x) ||
314305b261ecSmrg	    (stuff->srcHeight != 0 &&
314405b261ecSmrg	     winY + stuff->srcY + (int)stuff->srcHeight < y) ||
314505b261ecSmrg	    !PointInWindowIsVisible(source, x, y))
314605b261ecSmrg	    return Success;
314705b261ecSmrg    }
31484642e01fSmrg    if (dest)
314905b261ecSmrg    {
315005b261ecSmrg	x = dest->drawable.x;
315105b261ecSmrg	y = dest->drawable.y;
315205b261ecSmrg	newScreen = dest->drawable.pScreen;
31534642e01fSmrg    } else
31544642e01fSmrg	newScreen = pSprite->hotPhys.pScreen;
315505b261ecSmrg
315605b261ecSmrg    x += stuff->dstX;
315705b261ecSmrg    y += stuff->dstY;
315805b261ecSmrg
315905b261ecSmrg    if (x < 0)
316005b261ecSmrg	x = 0;
316105b261ecSmrg    else if (x >= newScreen->width)
316205b261ecSmrg	x = newScreen->width - 1;
316305b261ecSmrg    if (y < 0)
316405b261ecSmrg	y = 0;
316505b261ecSmrg    else if (y >= newScreen->height)
316605b261ecSmrg	y = newScreen->height - 1;
316705b261ecSmrg
31684642e01fSmrg    if (newScreen == pSprite->hotPhys.pScreen)
31694642e01fSmrg    {
31704642e01fSmrg	if (x < pSprite->physLimits.x1)
31714642e01fSmrg	    x = pSprite->physLimits.x1;
31724642e01fSmrg	else if (x >= pSprite->physLimits.x2)
31734642e01fSmrg	    x = pSprite->physLimits.x2 - 1;
31744642e01fSmrg	if (y < pSprite->physLimits.y1)
31754642e01fSmrg	    y = pSprite->physLimits.y1;
31764642e01fSmrg	else if (y >= pSprite->physLimits.y2)
31774642e01fSmrg	    y = pSprite->physLimits.y2 - 1;
31784642e01fSmrg	if (pSprite->hotShape)
31794642e01fSmrg	    ConfineToShape(dev, pSprite->hotShape, &x, &y);
31804642e01fSmrg        (*newScreen->SetCursorPosition)(dev, newScreen, x, y, TRUE);
318105b261ecSmrg    }
31824642e01fSmrg    else if (!PointerConfinedToScreen(dev))
318305b261ecSmrg    {
31844642e01fSmrg	NewCurrentScreen(dev, newScreen, x, y);
318505b261ecSmrg    }
318605b261ecSmrg    return Success;
318705b261ecSmrg}
318805b261ecSmrg
31894642e01fSmrgstatic Bool
31904642e01fSmrgBorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
319105b261ecSmrg{
31924642e01fSmrg     if(REGION_NOTEMPTY(pDev->spriteInfo->sprite->hotPhys.pScreen, &pWin->borderSize))
319305b261ecSmrg	return TRUE;
319405b261ecSmrg
319505b261ecSmrg#ifdef PANORAMIX
31964642e01fSmrg     if(!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) {
319705b261ecSmrg	int i;
319805b261ecSmrg
319905b261ecSmrg	for(i = 1; i < PanoramiXNumScreens; i++) {
32004642e01fSmrg	    if(REGION_NOTEMPTY(pDev->spriteInfo->sprite->screen,
32014642e01fSmrg                        &pDev->spriteInfo->sprite->windows[i]->borderSize))
320205b261ecSmrg		return TRUE;
320305b261ecSmrg	}
320405b261ecSmrg     }
320505b261ecSmrg#endif
320605b261ecSmrg     return FALSE;
320705b261ecSmrg}
320805b261ecSmrg
32094642e01fSmrg/**
321005b261ecSmrg * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
32114642e01fSmrg * passive grab set on the window to be activated.
321205b261ecSmrg * If a passive grab is activated, the event will be delivered to the client.
32134642e01fSmrg *
321405b261ecSmrg * @param pWin The window that may be subject to a passive grab.
321505b261ecSmrg * @param device Device that caused the event.
321605b261ecSmrg * @param xE List of events (multiple ones for DeviceMotionNotify)
32174642e01fSmrg * @param count number of elements in xE.
32184642e01fSmrg * @param store The event that will be stored on the device (always XI)
32194642e01fSmrg * @param scount number of elements in store.
322005b261ecSmrg */
322105b261ecSmrg
322205b261ecSmrgstatic Bool
322305b261ecSmrgCheckPassiveGrabsOnWindow(
322405b261ecSmrg    WindowPtr pWin,
322505b261ecSmrg    DeviceIntPtr device,
322605b261ecSmrg    xEvent *xE,
32274642e01fSmrg    int count,
32284642e01fSmrg    xEvent *store,
32294642e01fSmrg    int scount)
323005b261ecSmrg{
323105b261ecSmrg    GrabPtr grab = wPassiveGrabs(pWin);
323205b261ecSmrg    GrabRec tempGrab;
32334642e01fSmrg    GrabInfoPtr grabinfo;
323405b261ecSmrg    xEvent *dxE;
323505b261ecSmrg
323605b261ecSmrg    if (!grab)
323705b261ecSmrg	return FALSE;
323805b261ecSmrg    tempGrab.window = pWin;
323905b261ecSmrg    tempGrab.device = device;
324005b261ecSmrg    tempGrab.type = xE->u.u.type;
324105b261ecSmrg    tempGrab.detail.exact = xE->u.u.detail;
324205b261ecSmrg    tempGrab.detail.pMask = NULL;
324305b261ecSmrg    tempGrab.modifiersDetail.pMask = NULL;
32444642e01fSmrg    tempGrab.next = NULL;
324505b261ecSmrg    for (; grab; grab = grab->next)
324605b261ecSmrg    {
324705b261ecSmrg#ifdef XKB
324805b261ecSmrg	DeviceIntPtr	gdev;
32494642e01fSmrg	XkbSrvInfoPtr	xkbi = NULL;
325005b261ecSmrg
325105b261ecSmrg	gdev= grab->modifierDevice;
32524642e01fSmrg        if (grab->coreGrab)
32534642e01fSmrg        {
32544642e01fSmrg            if (IsPointerDevice(device))
32554642e01fSmrg                gdev = GetPairedDevice(device);
32564642e01fSmrg            else
32574642e01fSmrg                gdev = device;
32584642e01fSmrg        }
32594642e01fSmrg        if (gdev && gdev->key)
32604642e01fSmrg            xkbi= gdev->key->xkbInfo;
326105b261ecSmrg#endif
326205b261ecSmrg	tempGrab.modifierDevice = grab->modifierDevice;
326305b261ecSmrg	if ((device == grab->modifierDevice) &&
32644642e01fSmrg	    ((xE->u.u.type == KeyPress) || (xE->u.u.type == DeviceKeyPress)))
326505b261ecSmrg	    tempGrab.modifiersDetail.exact =
326605b261ecSmrg#ifdef XKB
32674642e01fSmrg                (noXkbExtension) ?
32684642e01fSmrg                        ((gdev) ? gdev->key->prev_state : 0) :
32694642e01fSmrg                        ((xkbi) ?  xkbi->state.grab_mods : 0);
327005b261ecSmrg#else
32714642e01fSmrg                (gdev) ? gdev->key->prev_state : 0;
327205b261ecSmrg#endif
327305b261ecSmrg	else
327405b261ecSmrg	    tempGrab.modifiersDetail.exact =
327505b261ecSmrg#ifdef XKB
32764642e01fSmrg                (noXkbExtension) ?
32774642e01fSmrg                        ((gdev) ? gdev->key->state : 0) :
32784642e01fSmrg                        ((xkbi) ? xkbi->state.grab_mods : 0);
327905b261ecSmrg#else
32804642e01fSmrg                (gdev) ? gdev->key->state : 0;
328105b261ecSmrg#endif
32824642e01fSmrg            /* ignore the device for core events when comparing grabs */
32834642e01fSmrg	if (GrabMatchesSecond(&tempGrab, grab, (xE->u.u.type < LASTEvent)) &&
328405b261ecSmrg	    (!grab->confineTo ||
32854642e01fSmrg	     (grab->confineTo->realized &&
32864642e01fSmrg				BorderSizeNotEmpty(device, grab->confineTo))))
328705b261ecSmrg	{
328805b261ecSmrg#ifdef XKB
328905b261ecSmrg	    if (!noXkbExtension) {
329005b261ecSmrg		XE_KBPTR.state &= 0x1f00;
329105b261ecSmrg		XE_KBPTR.state |=
329205b261ecSmrg				tempGrab.modifiersDetail.exact&(~0x1f00);
329305b261ecSmrg	    }
329405b261ecSmrg#endif
32954642e01fSmrg            grabinfo = &device->deviceGrab;
32964642e01fSmrg            /* A passive grab may have been created for a different device
32974642e01fSmrg               than it is assigned to at this point in time.
32984642e01fSmrg               Update the grab's device and modifier device to reflect the
32994642e01fSmrg               current state.
33004642e01fSmrg               Since XGrabDeviceButton requires to specify the
33014642e01fSmrg               modifierDevice explicitly, we don't override this choice.
33024642e01fSmrg             */
33034642e01fSmrg            if (xE->u.u.type < LASTEvent)
33044642e01fSmrg            {
33054642e01fSmrg                grab->device = device;
33064642e01fSmrg                grab->modifierDevice = GetPairedDevice(device);
33074642e01fSmrg            }
33084642e01fSmrg
33094642e01fSmrg            /* In some cases a passive core grab may exist, but the client
33104642e01fSmrg             * already has a core grab on some other device. In this case we
33114642e01fSmrg             * must not get the grab, otherwise we may never ungrab the
33124642e01fSmrg             * device.
33134642e01fSmrg             */
33144642e01fSmrg
33154642e01fSmrg            if (grab->coreGrab)
33164642e01fSmrg            {
33174642e01fSmrg                DeviceIntPtr other;
33184642e01fSmrg                BOOL interfering = FALSE;
33194642e01fSmrg                for (other = inputInfo.devices; other; other = other->next)
33204642e01fSmrg                {
33214642e01fSmrg                    GrabPtr othergrab = other->deviceGrab.grab;
33224642e01fSmrg                    if (othergrab && othergrab->coreGrab &&
33234642e01fSmrg                        SameClient(grab, rClient(othergrab)) &&
33244642e01fSmrg                        ((IsPointerDevice(grab->device) &&
33254642e01fSmrg                         IsPointerDevice(othergrab->device)) ||
33264642e01fSmrg                         (IsKeyboardDevice(grab->device) &&
33274642e01fSmrg                          IsKeyboardDevice(othergrab->device))))
33284642e01fSmrg                    {
33294642e01fSmrg                        interfering = TRUE;
33304642e01fSmrg                        break;
33314642e01fSmrg                    }
33324642e01fSmrg                }
33334642e01fSmrg                if (interfering)
33344642e01fSmrg                    continue;
33354642e01fSmrg            }
33364642e01fSmrg
33374642e01fSmrg
33384642e01fSmrg	    (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
33394642e01fSmrg
33404642e01fSmrg	    FixUpEventFromWindow(device, xE, grab->window, None, TRUE);
334105b261ecSmrg
33424642e01fSmrg	    (void) TryClientEvents(rClient(grab), device, xE, count,
33434642e01fSmrg				   filters[device->id][xE->u.u.type],
33444642e01fSmrg				   filters[device->id][xE->u.u.type],  grab);
334505b261ecSmrg
33464642e01fSmrg	    if (grabinfo->sync.state == FROZEN_NO_EVENT)
334705b261ecSmrg	    {
33484642e01fSmrg		if (grabinfo->sync.evcount < scount)
334905b261ecSmrg		{
33504642e01fSmrg		    grabinfo->sync.event = xrealloc(grabinfo->sync.event,
33514642e01fSmrg						    scount * sizeof(xEvent));
335205b261ecSmrg		}
33534642e01fSmrg		grabinfo->sync.evcount = scount;
33544642e01fSmrg                /* we always store the XI event, never the core event */
33554642e01fSmrg		for (dxE = grabinfo->sync.event; --scount >= 0; dxE++, store++)
33564642e01fSmrg		    *dxE = *store;
33574642e01fSmrg		grabinfo->sync.state = FROZEN_WITH_EVENT;
33584642e01fSmrg            }
335905b261ecSmrg	    return TRUE;
336005b261ecSmrg	}
336105b261ecSmrg    }
336205b261ecSmrg    return FALSE;
336305b261ecSmrg}
336405b261ecSmrg
336505b261ecSmrg/**
336605b261ecSmrg * CheckDeviceGrabs handles both keyboard and pointer events that may cause
33674642e01fSmrg * a passive grab to be activated.
336805b261ecSmrg *
336905b261ecSmrg * If the event is a keyboard event, the ancestors of the focus window are
337005b261ecSmrg * traced down and tried to see if they have any passive grabs to be
337105b261ecSmrg * activated.  If the focus window itself is reached and it's descendants
337205b261ecSmrg * contain the pointer, the ancestors of the window that the pointer is in
337305b261ecSmrg * are then traced down starting at the focus window, otherwise no grabs are
33744642e01fSmrg * activated.
337505b261ecSmrg * If the event is a pointer event, the ancestors of the window that the
337605b261ecSmrg * pointer is in are traced down starting at the root until CheckPassiveGrabs
337705b261ecSmrg * causes a passive grab to activate or all the windows are
337805b261ecSmrg * tried. PRH
337905b261ecSmrg *
338005b261ecSmrg * If a grab is activated, the event has been sent to the client already!
338105b261ecSmrg *
33824642e01fSmrg * The event we pass in must always be an XI event. From this, we then emulate
33834642e01fSmrg * the core event and then check for grabs.
33844642e01fSmrg *
338505b261ecSmrg * @param device The device that caused the event.
33864642e01fSmrg * @param xE The event to handle (Device{Button|Key}Press).
338705b261ecSmrg * @param count Number of events in list.
338805b261ecSmrg * @return TRUE if a grab has been activated or false otherwise.
338905b261ecSmrg*/
339005b261ecSmrg
339105b261ecSmrgBool
33924642e01fSmrgCheckDeviceGrabs(DeviceIntPtr device, xEvent *xE,
339305b261ecSmrg                 int checkFirst, int count)
339405b261ecSmrg{
339505b261ecSmrg    int i;
339605b261ecSmrg    WindowPtr pWin = NULL;
33974642e01fSmrg    FocusClassPtr focus = IsPointerEvent(xE) ? NULL : device->focus;
33984642e01fSmrg    xEvent core;
33994642e01fSmrg    BOOL sendCore = (device->isMaster && device->coreEvents);
340005b261ecSmrg
34014642e01fSmrg    if ((xE->u.u.type == DeviceButtonPress)
34024642e01fSmrg            && (device->button->buttonsDown != 1))
340305b261ecSmrg	return FALSE;
340405b261ecSmrg
34054642e01fSmrg    if (xE->u.u.type < EXTENSION_EVENT_BASE)
34064642e01fSmrg    {
34074642e01fSmrg        ErrorF("[dix] Core event passed into CheckDeviceGrabs.\n");
34084642e01fSmrg        return FALSE;
34094642e01fSmrg    }
34104642e01fSmrg
34114642e01fSmrg
34124642e01fSmrg    if (sendCore)
34134642e01fSmrg    {
34144642e01fSmrg        core = *xE;
34154642e01fSmrg        core.u.u.type = XItoCoreType(xE->u.u.type);
34164642e01fSmrg        if(!core.u.u.type) /* probably a Proximity event, can't grab for those */
34174642e01fSmrg            return FALSE;
34184642e01fSmrg    }
34194642e01fSmrg
342005b261ecSmrg    i = checkFirst;
342105b261ecSmrg
342205b261ecSmrg    if (focus)
342305b261ecSmrg    {
342405b261ecSmrg	for (; i < focus->traceGood; i++)
342505b261ecSmrg	{
342605b261ecSmrg	    pWin = focus->trace[i];
34274642e01fSmrg            /* XI grabs have precendence */
342805b261ecSmrg	    if (pWin->optional &&
34294642e01fSmrg	       (CheckPassiveGrabsOnWindow(pWin, device, xE, count, xE, count)
34304642e01fSmrg                || (sendCore && CheckPassiveGrabsOnWindow(pWin, device, &core,
34314642e01fSmrg                        1, xE, count))))
343205b261ecSmrg		return TRUE;
343305b261ecSmrg	}
34344642e01fSmrg
343505b261ecSmrg	if ((focus->win == NoneWin) ||
34364642e01fSmrg	    (i >= device->spriteInfo->sprite->spriteTraceGood) ||
34374642e01fSmrg	    ((i > checkFirst) &&
34384642e01fSmrg             (pWin != device->spriteInfo->sprite->spriteTrace[i-1])))
343905b261ecSmrg	    return FALSE;
344005b261ecSmrg    }
344105b261ecSmrg
34424642e01fSmrg    for (; i < device->spriteInfo->sprite->spriteTraceGood; i++)
344305b261ecSmrg    {
34444642e01fSmrg	pWin = device->spriteInfo->sprite->spriteTrace[i];
344505b261ecSmrg	if (pWin->optional &&
34464642e01fSmrg	    (CheckPassiveGrabsOnWindow(pWin, device, xE, count, xE, count) ||
34474642e01fSmrg             (sendCore && CheckPassiveGrabsOnWindow(pWin, device, &core, 1,
34484642e01fSmrg                                                    xE, count))))
344905b261ecSmrg	    return TRUE;
345005b261ecSmrg    }
345105b261ecSmrg
345205b261ecSmrg    return FALSE;
345305b261ecSmrg}
345405b261ecSmrg
345505b261ecSmrg/**
345605b261ecSmrg * Called for keyboard events to deliver event to whatever client owns the
345705b261ecSmrg * focus. Event is delivered to the keyboard's focus window, the root window
345805b261ecSmrg * or to the window owning the input focus.
345905b261ecSmrg *
346005b261ecSmrg * @param keybd The keyboard originating the event.
346105b261ecSmrg * @param xE The event list.
346205b261ecSmrg * @param window Window underneath the sprite.
346305b261ecSmrg * @param count number of events in xE.
346405b261ecSmrg */
346505b261ecSmrgvoid
346605b261ecSmrgDeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
346705b261ecSmrg{
34684642e01fSmrg    DeviceIntPtr pointer;
346905b261ecSmrg    WindowPtr focus = keybd->focus->win;
34704642e01fSmrg    BOOL sendCore = (keybd->isMaster && keybd->coreEvents);
34714642e01fSmrg    xEvent core;
34724642e01fSmrg    int deliveries = 0;
347305b261ecSmrg
347405b261ecSmrg    if (focus == FollowKeyboardWin)
347505b261ecSmrg	focus = inputInfo.keyboard->focus->win;
347605b261ecSmrg    if (!focus)
347705b261ecSmrg	return;
347805b261ecSmrg    if (focus == PointerRootWin)
347905b261ecSmrg    {
348005b261ecSmrg	DeliverDeviceEvents(window, xE, NullGrab, NullWindow, keybd, count);
348105b261ecSmrg	return;
348205b261ecSmrg    }
348305b261ecSmrg    if ((focus == window) || IsParent(focus, window))
348405b261ecSmrg    {
348505b261ecSmrg	if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count))
348605b261ecSmrg	    return;
348705b261ecSmrg    }
34884642e01fSmrg    pointer = GetPairedDevice(keybd);
34894642e01fSmrg    if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count))
34904642e01fSmrg	return;
34914642e01fSmrg
34924642e01fSmrg    if (sendCore)
34934642e01fSmrg    {
34944642e01fSmrg        core = *xE;
34954642e01fSmrg        core.u.u.type = XItoCoreType(xE->u.u.type);
34964642e01fSmrg    }
34974642e01fSmrg
349805b261ecSmrg    /* just deliver it to the focus window */
34994642e01fSmrg    FixUpEventFromWindow(pointer, xE, focus, None, FALSE);
35004642e01fSmrg    deliveries = DeliverEventsToWindow(keybd, focus, xE, count,
35014642e01fSmrg                                       filters[keybd->id][xE->u.u.type],
35024642e01fSmrg                                       NullGrab, keybd->id);
35034642e01fSmrg
35044642e01fSmrg    if (deliveries > 0)
35054642e01fSmrg        return;
35064642e01fSmrg
35074642e01fSmrg    if (sendCore && core.u.u.type)
35084642e01fSmrg    {
35094642e01fSmrg        FixUpEventFromWindow(keybd, &core, focus, None, FALSE);
35104642e01fSmrg        deliveries = DeliverEventsToWindow(keybd, focus, &core, 1,
35114642e01fSmrg                                           filters[keybd->id][xE->u.u.type],
35124642e01fSmrg                                           NullGrab, 0);
35134642e01fSmrg    }
351405b261ecSmrg}
351505b261ecSmrg
351605b261ecSmrg/**
351705b261ecSmrg * Deliver an event from a device that is currently grabbed. Uses
351805b261ecSmrg * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the
351905b261ecSmrg * grab. If not, TryClientEvents() is used.
352005b261ecSmrg *
352105b261ecSmrg * @param deactivateGrab True if the device's grab should be deactivated.
352205b261ecSmrg */
352305b261ecSmrgvoid
35244642e01fSmrgDeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
352505b261ecSmrg                    Bool deactivateGrab, int count)
352605b261ecSmrg{
35274642e01fSmrg    GrabPtr grab;
35284642e01fSmrg    GrabInfoPtr grabinfo;
352905b261ecSmrg    int deliveries = 0;
353005b261ecSmrg    DeviceIntPtr dev;
35314642e01fSmrg    xEvent *dxE, core;
35324642e01fSmrg    SpritePtr pSprite = thisDev->spriteInfo->sprite;
35334642e01fSmrg    BOOL sendCore = FALSE;
35344642e01fSmrg
35354642e01fSmrg    grabinfo = &thisDev->deviceGrab;
35364642e01fSmrg    grab = grabinfo->grab;
353705b261ecSmrg
353805b261ecSmrg    if (grab->ownerEvents)
353905b261ecSmrg    {
354005b261ecSmrg	WindowPtr focus;
354105b261ecSmrg
35424642e01fSmrg        /* Hack: Some pointer device have a focus class. So we need to check
35434642e01fSmrg         * for the type of event, to see if we really want to deliver it to
35444642e01fSmrg         * the focus window. For pointer events, the answer is no.
35454642e01fSmrg         */
35464642e01fSmrg        if (xE->u.u.type == DeviceButtonPress ||
35474642e01fSmrg                xE->u.u.type == DeviceButtonRelease ||
35484642e01fSmrg                xE->u.u.type == DeviceMotionNotify ||
35494642e01fSmrg                xE->u.u.type == ProximityIn ||
35504642e01fSmrg                xE->u.u.type == ProximityOut)
35514642e01fSmrg        {
35524642e01fSmrg            focus = PointerRootWin;
35534642e01fSmrg        } else if (thisDev->focus)
355405b261ecSmrg	{
355505b261ecSmrg	    focus = thisDev->focus->win;
355605b261ecSmrg	    if (focus == FollowKeyboardWin)
355705b261ecSmrg		focus = inputInfo.keyboard->focus->win;
355805b261ecSmrg	}
355905b261ecSmrg	else
356005b261ecSmrg	    focus = PointerRootWin;
356105b261ecSmrg	if (focus == PointerRootWin)
35624642e01fSmrg	    deliveries = DeliverDeviceEvents(pSprite->win, xE, grab,
35634642e01fSmrg                                             NullWindow, thisDev, count);
35644642e01fSmrg	else if (focus && (focus == pSprite->win ||
35654642e01fSmrg                    IsParent(focus, pSprite->win)))
35664642e01fSmrg	    deliveries = DeliverDeviceEvents(pSprite->win, xE, grab, focus,
356705b261ecSmrg					     thisDev, count);
356805b261ecSmrg	else if (focus)
356905b261ecSmrg	    deliveries = DeliverDeviceEvents(focus, xE, grab, focus,
357005b261ecSmrg					     thisDev, count);
357105b261ecSmrg    }
357205b261ecSmrg    if (!deliveries)
357305b261ecSmrg    {
35744642e01fSmrg        {
35754642e01fSmrg            Mask mask = grab->eventMask;
35764642e01fSmrg
35774642e01fSmrg            if (thisDev->isMaster)
35784642e01fSmrg            {
35794642e01fSmrg                core = *xE;
35804642e01fSmrg                core.u.u.type = XItoCoreType(xE->u.u.type);
35814642e01fSmrg                if(core.u.u.type) {
35824642e01fSmrg                    FixUpEventFromWindow(thisDev, &core, grab->window,
35834642e01fSmrg                            None, TRUE);
35844642e01fSmrg                    if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
35854642e01fSmrg                                grab->window, &core, 1) ||
35864642e01fSmrg                            XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
35874642e01fSmrg                                grab->window, &core, 1))
35884642e01fSmrg                        deliveries = 1; /* don't send, but pretend we did */
35894642e01fSmrg                    else if (!IsInterferingGrab(rClient(grab), thisDev,
35904642e01fSmrg                                &core))
35914642e01fSmrg                    {
35924642e01fSmrg                        deliveries = TryClientEvents(rClient(grab), thisDev,
35934642e01fSmrg                                &core, 1, mask,
35944642e01fSmrg                                filters[thisDev->id][core.u.u.type],
35954642e01fSmrg                                grab);
35964642e01fSmrg                    }
35974642e01fSmrg                }
35984642e01fSmrg            } else
35994642e01fSmrg            {
36004642e01fSmrg                /* try XI event */
36014642e01fSmrg                if (grabinfo->fromPassiveGrab  &&
36024642e01fSmrg                        grabinfo->implicitGrab &&
36034642e01fSmrg                        (xE->u.u.type & EXTENSION_EVENT_BASE))
36044642e01fSmrg                    mask = grab->deviceMask;
36054642e01fSmrg                FixUpEventFromWindow(thisDev, xE, grab->window,
36064642e01fSmrg                        None, TRUE);
36074642e01fSmrg
36084642e01fSmrg                if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
36094642e01fSmrg                            grab->window, xE, count) ||
36104642e01fSmrg                        XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
36114642e01fSmrg                            grab->window, xE, count))
36124642e01fSmrg                    deliveries = 1; /* don't send, but pretend we did */
36134642e01fSmrg                else
36144642e01fSmrg                {
36154642e01fSmrg                    deliveries =
36164642e01fSmrg                        TryClientEvents(rClient(grab), thisDev,
36174642e01fSmrg                                xE, count,
36184642e01fSmrg                                mask,
36194642e01fSmrg                                filters[thisDev->id][xE->u.u.type],
36204642e01fSmrg                                grab);
36214642e01fSmrg                }
36224642e01fSmrg
36234642e01fSmrg            }
36244642e01fSmrg        }
36254642e01fSmrg        if (deliveries && (xE->u.u.type == MotionNotify
36264642e01fSmrg                    || xE->u.u.type == DeviceMotionNotify))
36274642e01fSmrg            thisDev->valuator->motionHintWindow = grab->window;
362805b261ecSmrg    }
36294642e01fSmrg    if (deliveries && !deactivateGrab &&
36304642e01fSmrg       (xE->u.u.type != MotionNotify && xE->u.u.type != DeviceMotionNotify))
36314642e01fSmrg    {
36324642e01fSmrg	switch (grabinfo->sync.state)
363305b261ecSmrg	{
363405b261ecSmrg	case FREEZE_BOTH_NEXT_EVENT:
363505b261ecSmrg	    for (dev = inputInfo.devices; dev; dev = dev->next)
363605b261ecSmrg	    {
363705b261ecSmrg		if (dev == thisDev)
363805b261ecSmrg		    continue;
363905b261ecSmrg		FreezeThaw(dev, TRUE);
36404642e01fSmrg		if ((grabinfo->sync.state == FREEZE_BOTH_NEXT_EVENT) &&
36414642e01fSmrg		    (CLIENT_BITS(grab->resource) ==
36424642e01fSmrg		     CLIENT_BITS(grab->resource)))
36434642e01fSmrg		    grabinfo->sync.state = FROZEN_NO_EVENT;
364405b261ecSmrg		else
36454642e01fSmrg		    grabinfo->sync.other = grab;
364605b261ecSmrg	    }
364705b261ecSmrg	    /* fall through */
364805b261ecSmrg	case FREEZE_NEXT_EVENT:
36494642e01fSmrg	    grabinfo->sync.state = FROZEN_WITH_EVENT;
365005b261ecSmrg	    FreezeThaw(thisDev, TRUE);
36514642e01fSmrg	    if (grabinfo->sync.evcount < count)
365205b261ecSmrg	    {
36534642e01fSmrg		grabinfo->sync.event = xrealloc(grabinfo->sync.event,
36544642e01fSmrg						count * sizeof(xEvent));
365505b261ecSmrg	    }
36564642e01fSmrg	    grabinfo->sync.evcount = count;
36574642e01fSmrg	    for (dxE = grabinfo->sync.event; --count >= 0; dxE++, xE++)
365805b261ecSmrg		*dxE = *xE;
365905b261ecSmrg	    break;
366005b261ecSmrg	}
36614642e01fSmrg    }
366205b261ecSmrg}
366305b261ecSmrg
366405b261ecSmrg/**
36654642e01fSmrg * Main keyboard event processing function for core keyboard events.
366605b261ecSmrg * Updates the events fields from the current pointer state and delivers the
366705b261ecSmrg * event.
366805b261ecSmrg *
366905b261ecSmrg * For key events, xE will always be a single event.
367005b261ecSmrg *
367105b261ecSmrg * @param xE Event list
367205b261ecSmrg * @param keybd The device that caused an event.
367305b261ecSmrg * @param count Number of elements in xE.
367405b261ecSmrg */
367505b261ecSmrgvoid
367605b261ecSmrg#ifdef XKB
367705b261ecSmrgCoreProcessKeyboardEvent (xEvent *xE, DeviceIntPtr keybd, int count)
367805b261ecSmrg#else
367905b261ecSmrgProcessKeyboardEvent (xEvent *xE, DeviceIntPtr keybd, int count)
368005b261ecSmrg#endif
368105b261ecSmrg{
368205b261ecSmrg    int             key, bit;
36834642e01fSmrg    BYTE            *kptr;
36844642e01fSmrg    CARD8           modifiers;
36854642e01fSmrg    GrabPtr         grab;
36864642e01fSmrg    GrabInfoPtr     grabinfo;
368705b261ecSmrg    Bool            deactivateGrab = FALSE;
36884642e01fSmrg    KeyClassPtr     keyc = keybd->key;
36894642e01fSmrg
36904642e01fSmrg    grabinfo = &keybd->deviceGrab;
36914642e01fSmrg    grab = grabinfo->grab;
369205b261ecSmrg
369305b261ecSmrg    if (!syncEvents.playingEvents)
369405b261ecSmrg    {
369505b261ecSmrg	NoticeTime(xE);
369605b261ecSmrg	if (DeviceEventCallback)
369705b261ecSmrg	{
369805b261ecSmrg	    DeviceEventInfoRec eventinfo;
369905b261ecSmrg	    eventinfo.events = xE;
370005b261ecSmrg	    eventinfo.count = count;
370105b261ecSmrg	    CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
370205b261ecSmrg	}
370305b261ecSmrg    }
37044642e01fSmrg    /* ProcessOtherEvent already updated the keyboard's state, so we need to
37054642e01fSmrg     * access prev_state here! */
37064642e01fSmrg    XE_KBPTR.state = (keyc->prev_state | GetPairedDevice(keybd)->button->state);
37074642e01fSmrg    XE_KBPTR.rootX = keybd->spriteInfo->sprite->hot.x;
37084642e01fSmrg    XE_KBPTR.rootY = keybd->spriteInfo->sprite->hot.y;
370905b261ecSmrg    key = xE->u.u.detail;
371005b261ecSmrg    kptr = &keyc->down[key >> 3];
371105b261ecSmrg    bit = 1 << (key & 7);
371205b261ecSmrg    modifiers = keyc->modifierMap[key];
371305b261ecSmrg
371405b261ecSmrg    switch (xE->u.u.type)
371505b261ecSmrg    {
37164642e01fSmrg	case KeyPress:
37174642e01fSmrg            /* We MUST NOT change the device itself here.  All device state
37184642e01fSmrg             * changes must be performed in ProcessOtherEvents. We're dealing
37194642e01fSmrg             * with the same device struct, so if we change it in POE and
37204642e01fSmrg             * here, we've just screwed up the state by setting it twice.
37214642e01fSmrg             *
37224642e01fSmrg             * Devices may not send core events but always send XI events, so
37234642e01fSmrg             * the state must be changed in POE, not here.
37244642e01fSmrg             */
372505b261ecSmrg	    if (!grab && CheckDeviceGrabs(keybd, xE, 0, count))
372605b261ecSmrg	    {
37274642e01fSmrg		grabinfo->activatingKey = key;
372805b261ecSmrg		return;
372905b261ecSmrg	    }
373005b261ecSmrg	    break;
37314642e01fSmrg	case KeyRelease:
373205b261ecSmrg	    if (!(*kptr & bit)) /* guard against duplicates */
373305b261ecSmrg		return;
37344642e01fSmrg            /* No device state changes, see comment for KeyPress */
37354642e01fSmrg	    if (grabinfo->fromPassiveGrab && (key == grabinfo->activatingKey))
373605b261ecSmrg		deactivateGrab = TRUE;
373705b261ecSmrg	    break;
37384642e01fSmrg	default:
373905b261ecSmrg	    FatalError("Impossible keyboard event");
374005b261ecSmrg    }
374105b261ecSmrg    if (grab)
374205b261ecSmrg	DeliverGrabbedEvent(xE, keybd, deactivateGrab, count);
374305b261ecSmrg    else
37444642e01fSmrg	DeliverFocusedEvent(keybd, xE, keybd->spriteInfo->sprite->win, count);
374505b261ecSmrg    if (deactivateGrab)
37464642e01fSmrg        (*grabinfo->DeactivateGrab)(keybd);
374705b261ecSmrg
374805b261ecSmrg    XaceHook(XACE_KEY_AVAIL, xE, keybd, count);
374905b261ecSmrg}
375005b261ecSmrg
375105b261ecSmrg#ifdef XKB
375205b261ecSmrg/* This function is used to set the key pressed or key released state -
37534642e01fSmrg   this is only used when the pressing of keys does not cause
375405b261ecSmrg   the device's processInputProc to be called, as in for example Mouse Keys.
375505b261ecSmrg*/
375605b261ecSmrgvoid
375705b261ecSmrgFixKeyState (xEvent *xE, DeviceIntPtr keybd)
375805b261ecSmrg{
375905b261ecSmrg    int             key, bit;
376005b261ecSmrg    BYTE   *kptr;
376105b261ecSmrg    KeyClassPtr keyc = keybd->key;
376205b261ecSmrg
376305b261ecSmrg    key = xE->u.u.detail;
376405b261ecSmrg    kptr = &keyc->down[key >> 3];
376505b261ecSmrg    bit = 1 << (key & 7);
376605b261ecSmrg
376705b261ecSmrg    if (((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease)||
376805b261ecSmrg         (xE->u.u.type==DeviceKeyPress)||(xE->u.u.type==DeviceKeyRelease))
376905b261ecSmrg            ) {
377005b261ecSmrg	DebugF("FixKeyState: Key %d %s\n",key,
377105b261ecSmrg               (((xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress))?"down":"up"));
377205b261ecSmrg    }
377305b261ecSmrg
377405b261ecSmrg    if (xE->u.u.type == KeyPress || xE->u.u.type == DeviceKeyPress)
377505b261ecSmrg	    *kptr |= bit;
377605b261ecSmrg    else if (xE->u.u.type == KeyRelease || xE->u.u.type == DeviceKeyRelease)
377705b261ecSmrg	    *kptr &= ~bit;
377805b261ecSmrg    else
377905b261ecSmrg        FatalError("Impossible keyboard event");
378005b261ecSmrg}
378105b261ecSmrg#endif
378205b261ecSmrg
37834642e01fSmrg/**
37844642e01fSmrg * Main pointer event processing function for core pointer events.
378505b261ecSmrg * For motion events: update the sprite.
378605b261ecSmrg * For all other events: Update the event fields based on the current sprite
378705b261ecSmrg * state.
378805b261ecSmrg *
378905b261ecSmrg * For core pointer events, xE will always be a single event.
379005b261ecSmrg *
379105b261ecSmrg * @param xE Event list
379205b261ecSmrg * @param mouse The device that caused an event.
379305b261ecSmrg * @param count Number of elements in xE.
379405b261ecSmrg */
379505b261ecSmrgvoid
379605b261ecSmrg#ifdef XKB
379705b261ecSmrgCoreProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
379805b261ecSmrg#else
379905b261ecSmrgProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
380005b261ecSmrg#endif
380105b261ecSmrg{
38024642e01fSmrg    GrabPtr	        grab = mouse->deviceGrab.grab;
380305b261ecSmrg    Bool                deactivateGrab = FALSE;
38044642e01fSmrg    ButtonClassPtr      butc = mouse->button;
38054642e01fSmrg    SpritePtr           pSprite = mouse->spriteInfo->sprite;
38064642e01fSmrg
380705b261ecSmrg#ifdef XKB
38084642e01fSmrg    XkbSrvInfoPtr xkbi= GetPairedDevice(mouse)->key->xkbInfo;
380905b261ecSmrg#endif
381005b261ecSmrg
381105b261ecSmrg    if (!syncEvents.playingEvents)
381205b261ecSmrg	NoticeTime(xE)
381305b261ecSmrg    XE_KBPTR.state = (butc->state | (
381405b261ecSmrg#ifdef XKB
381505b261ecSmrg			(noXkbExtension ?
381605b261ecSmrg				inputInfo.keyboard->key->state :
381705b261ecSmrg				xkbi->state.grab_mods)
381805b261ecSmrg#else
381905b261ecSmrg			inputInfo.keyboard->key->state
382005b261ecSmrg#endif
382105b261ecSmrg				    ));
382205b261ecSmrg    {
382305b261ecSmrg	NoticeTime(xE);
382405b261ecSmrg	if (DeviceEventCallback)
382505b261ecSmrg	{
382605b261ecSmrg	    DeviceEventInfoRec eventinfo;
382705b261ecSmrg	    /* see comment in EnqueueEvents regarding the next three lines */
382805b261ecSmrg	    if (xE->u.u.type == MotionNotify)
382905b261ecSmrg		XE_KBPTR.root =
38304642e01fSmrg		    WindowTable[pSprite->hotPhys.pScreen->myNum]->drawable.id;
383105b261ecSmrg	    eventinfo.events = xE;
383205b261ecSmrg	    eventinfo.count = count;
383305b261ecSmrg	    CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
383405b261ecSmrg	}
383505b261ecSmrg    }
38364642e01fSmrg    /* We need to call CheckMotion for each event. It doesn't really give us
38374642e01fSmrg       any benefit for relative devices, but absolute devices may not send
38384642e01fSmrg       button events to the right position otherwise. */
38394642e01fSmrg    if (!CheckMotion(xE, mouse) && xE->u.u.type == MotionNotify)
38404642e01fSmrg            return;
384105b261ecSmrg    if (xE->u.u.type != MotionNotify)
384205b261ecSmrg    {
384305b261ecSmrg	int  key;
384405b261ecSmrg
38454642e01fSmrg	XE_KBPTR.rootX = pSprite->hot.x;
38464642e01fSmrg	XE_KBPTR.rootY = pSprite->hot.y;
384705b261ecSmrg
384805b261ecSmrg	key = xE->u.u.detail;
384905b261ecSmrg	switch (xE->u.u.type)
385005b261ecSmrg	{
38514642e01fSmrg	case ButtonPress:
38524642e01fSmrg            /*
38534642e01fSmrg             * We rely on the fact that ButtonMotionMask is the same as
38544642e01fSmrg             * DeviceButtonMotionMask, so setting the motionMask
38554642e01fSmrg             * to this value ensures correctness for both XI and core events.
38564642e01fSmrg             */
385705b261ecSmrg	    if (xE->u.u.detail == 0)
385805b261ecSmrg		return;
38594642e01fSmrg            filters[mouse->id][Motion_Filter(butc)] = MotionNotify;
386005b261ecSmrg	    if (!grab)
386105b261ecSmrg		if (CheckDeviceGrabs(mouse, xE, 0, count))
386205b261ecSmrg		    return;
386305b261ecSmrg	    break;
38644642e01fSmrg	case ButtonRelease:
386505b261ecSmrg	    if (xE->u.u.detail == 0)
386605b261ecSmrg		return;
38674642e01fSmrg            filters[mouse->id][Motion_Filter(butc)] = MotionNotify;
38684642e01fSmrg	    if (!butc->buttonsDown && mouse->deviceGrab.fromPassiveGrab)
386905b261ecSmrg		deactivateGrab = TRUE;
387005b261ecSmrg	    break;
38714642e01fSmrg	default:
38724642e01fSmrg	    FatalError("bogus pointer event from ddx. Type %d\n", xE->u.u.type);
387305b261ecSmrg	}
387405b261ecSmrg    }
38754642e01fSmrg
387605b261ecSmrg    if (grab)
387705b261ecSmrg	DeliverGrabbedEvent(xE, mouse, deactivateGrab, count);
387805b261ecSmrg    else
38794642e01fSmrg	DeliverDeviceEvents(pSprite->win, xE, NullGrab, NullWindow,
388005b261ecSmrg			    mouse, count);
388105b261ecSmrg    if (deactivateGrab)
38824642e01fSmrg        (*mouse->deviceGrab.DeactivateGrab)(mouse);
388305b261ecSmrg}
388405b261ecSmrg
388505b261ecSmrg#define AtMostOneClient \
388605b261ecSmrg	(SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
38874642e01fSmrg#define ManagerMask \
38884642e01fSmrg	(SubstructureRedirectMask | ResizeRedirectMask)
388905b261ecSmrg
389005b261ecSmrg/**
389105b261ecSmrg * Recalculate which events may be deliverable for the given window.
389205b261ecSmrg * Recalculated mask is used for quicker determination which events may be
389305b261ecSmrg * delivered to a window.
389405b261ecSmrg *
389505b261ecSmrg * The otherEventMasks on a WindowOptional is the combination of all event
389605b261ecSmrg * masks set by all clients on the window.
389705b261ecSmrg * deliverableEventMask is the combination of the eventMask and the
389805b261ecSmrg * otherEventMask.
389905b261ecSmrg *
390005b261ecSmrg * Traverses to siblings and parents of the window.
390105b261ecSmrg */
390205b261ecSmrgvoid
390305b261ecSmrgRecalculateDeliverableEvents(pWin)
390405b261ecSmrg    WindowPtr pWin;
390505b261ecSmrg{
390605b261ecSmrg    OtherClients *others;
390705b261ecSmrg    WindowPtr pChild;
390805b261ecSmrg
390905b261ecSmrg    pChild = pWin;
391005b261ecSmrg    while (1)
391105b261ecSmrg    {
391205b261ecSmrg	if (pChild->optional)
391305b261ecSmrg	{
391405b261ecSmrg	    pChild->optional->otherEventMasks = 0;
391505b261ecSmrg	    for (others = wOtherClients(pChild); others; others = others->next)
391605b261ecSmrg	    {
391705b261ecSmrg		pChild->optional->otherEventMasks |= others->mask;
391805b261ecSmrg	    }
391905b261ecSmrg	}
392005b261ecSmrg	pChild->deliverableEvents = pChild->eventMask|
392105b261ecSmrg				    wOtherEventMasks(pChild);
392205b261ecSmrg	if (pChild->parent)
392305b261ecSmrg	    pChild->deliverableEvents |=
392405b261ecSmrg		(pChild->parent->deliverableEvents &
392505b261ecSmrg		 ~wDontPropagateMask(pChild) & PropagateMask);
392605b261ecSmrg	if (pChild->firstChild)
392705b261ecSmrg	{
392805b261ecSmrg	    pChild = pChild->firstChild;
392905b261ecSmrg	    continue;
393005b261ecSmrg	}
393105b261ecSmrg	while (!pChild->nextSib && (pChild != pWin))
393205b261ecSmrg	    pChild = pChild->parent;
393305b261ecSmrg	if (pChild == pWin)
393405b261ecSmrg	    break;
393505b261ecSmrg	pChild = pChild->nextSib;
393605b261ecSmrg    }
393705b261ecSmrg}
393805b261ecSmrg
393905b261ecSmrg/**
394005b261ecSmrg *
394105b261ecSmrg *  \param value must conform to DeleteType
394205b261ecSmrg */
394305b261ecSmrgint
394405b261ecSmrgOtherClientGone(pointer value, XID id)
394505b261ecSmrg{
394605b261ecSmrg    OtherClientsPtr other, prev;
394705b261ecSmrg    WindowPtr pWin = (WindowPtr)value;
394805b261ecSmrg
394905b261ecSmrg    prev = 0;
395005b261ecSmrg    for (other = wOtherClients(pWin); other; other = other->next)
395105b261ecSmrg    {
395205b261ecSmrg	if (other->resource == id)
395305b261ecSmrg	{
395405b261ecSmrg	    if (prev)
395505b261ecSmrg		prev->next = other->next;
395605b261ecSmrg	    else
395705b261ecSmrg	    {
395805b261ecSmrg		if (!(pWin->optional->otherClients = other->next))
395905b261ecSmrg		    CheckWindowOptionalNeed (pWin);
396005b261ecSmrg	    }
396105b261ecSmrg	    xfree(other);
396205b261ecSmrg	    RecalculateDeliverableEvents(pWin);
396305b261ecSmrg	    return(Success);
396405b261ecSmrg	}
396505b261ecSmrg	prev = other;
396605b261ecSmrg    }
396705b261ecSmrg    FatalError("client not on event list");
396805b261ecSmrg    /*NOTREACHED*/
396905b261ecSmrg    return -1; /* make compiler happy */
397005b261ecSmrg}
397105b261ecSmrg
397205b261ecSmrgint
397305b261ecSmrgEventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
397405b261ecSmrg{
397505b261ecSmrg    Mask check;
397605b261ecSmrg    OtherClients * others;
39774642e01fSmrg    DeviceIntPtr dev;
39784642e01fSmrg    int rc;
397905b261ecSmrg
398005b261ecSmrg    if (mask & ~AllEventMasks)
398105b261ecSmrg    {
398205b261ecSmrg	client->errorValue = mask;
398305b261ecSmrg	return BadValue;
398405b261ecSmrg    }
39854642e01fSmrg    check = (mask & ManagerMask);
39864642e01fSmrg    if (check) {
39874642e01fSmrg	rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id,
39884642e01fSmrg		      RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess);
39894642e01fSmrg	if (rc != Success)
39904642e01fSmrg	    return rc;
39914642e01fSmrg    }
399205b261ecSmrg    check = (mask & AtMostOneClient);
399305b261ecSmrg    if (check & (pWin->eventMask|wOtherEventMasks(pWin)))
399405b261ecSmrg    {				       /* It is illegal for two different
399505b261ecSmrg				          clients to select on any of the
399605b261ecSmrg				          events for AtMostOneClient. However,
399705b261ecSmrg				          it is OK, for some client to
399805b261ecSmrg				          continue selecting on one of those
399905b261ecSmrg				          events.  */
400005b261ecSmrg	if ((wClient(pWin) != client) && (check & pWin->eventMask))
400105b261ecSmrg	    return BadAccess;
400205b261ecSmrg	for (others = wOtherClients (pWin); others; others = others->next)
400305b261ecSmrg	{
400405b261ecSmrg	    if (!SameClient(others, client) && (check & others->mask))
400505b261ecSmrg		return BadAccess;
400605b261ecSmrg	}
400705b261ecSmrg    }
400805b261ecSmrg    if (wClient (pWin) == client)
400905b261ecSmrg    {
401005b261ecSmrg	check = pWin->eventMask;
401105b261ecSmrg	pWin->eventMask = mask;
401205b261ecSmrg    }
401305b261ecSmrg    else
401405b261ecSmrg    {
401505b261ecSmrg	for (others = wOtherClients (pWin); others; others = others->next)
401605b261ecSmrg	{
401705b261ecSmrg	    if (SameClient(others, client))
401805b261ecSmrg	    {
401905b261ecSmrg		check = others->mask;
402005b261ecSmrg		if (mask == 0)
402105b261ecSmrg		{
402205b261ecSmrg		    FreeResource(others->resource, RT_NONE);
402305b261ecSmrg		    return Success;
402405b261ecSmrg		}
402505b261ecSmrg		else
402605b261ecSmrg		    others->mask = mask;
402705b261ecSmrg		goto maskSet;
402805b261ecSmrg	    }
402905b261ecSmrg	}
403005b261ecSmrg	check = 0;
403105b261ecSmrg	if (!pWin->optional && !MakeWindowOptional (pWin))
403205b261ecSmrg	    return BadAlloc;
403305b261ecSmrg	others = (OtherClients *) xalloc(sizeof(OtherClients));
403405b261ecSmrg	if (!others)
403505b261ecSmrg	    return BadAlloc;
403605b261ecSmrg	others->mask = mask;
403705b261ecSmrg	others->resource = FakeClientID(client->index);
403805b261ecSmrg	others->next = pWin->optional->otherClients;
403905b261ecSmrg	pWin->optional->otherClients = others;
404005b261ecSmrg	if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin))
404105b261ecSmrg	    return BadAlloc;
404205b261ecSmrg    }
40434642e01fSmrgmaskSet:
40444642e01fSmrg    if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask))
40454642e01fSmrg    {
40464642e01fSmrg        for (dev = inputInfo.devices; dev; dev = dev->next)
40474642e01fSmrg        {
40484642e01fSmrg            if (dev->valuator && dev->valuator->motionHintWindow == pWin)
40494642e01fSmrg                dev->valuator->motionHintWindow = NullWindow;
40504642e01fSmrg        }
40514642e01fSmrg    }
405205b261ecSmrg    RecalculateDeliverableEvents(pWin);
405305b261ecSmrg    return Success;
405405b261ecSmrg}
405505b261ecSmrg
405605b261ecSmrgint
40574642e01fSmrgEventSuppressForWindow(WindowPtr pWin, ClientPtr client,
405805b261ecSmrg                       Mask mask, Bool *checkOptional)
405905b261ecSmrg{
406005b261ecSmrg    int i, free;
406105b261ecSmrg
406205b261ecSmrg    if (mask & ~PropagateMask)
406305b261ecSmrg    {
406405b261ecSmrg	client->errorValue = mask;
406505b261ecSmrg	return BadValue;
406605b261ecSmrg    }
406705b261ecSmrg    if (pWin->dontPropagate)
406805b261ecSmrg	DontPropagateRefCnts[pWin->dontPropagate]--;
406905b261ecSmrg    if (!mask)
407005b261ecSmrg	i = 0;
407105b261ecSmrg    else
407205b261ecSmrg    {
407305b261ecSmrg	for (i = DNPMCOUNT, free = 0; --i > 0; )
407405b261ecSmrg	{
407505b261ecSmrg	    if (!DontPropagateRefCnts[i])
407605b261ecSmrg		free = i;
407705b261ecSmrg	    else if (mask == DontPropagateMasks[i])
407805b261ecSmrg		break;
407905b261ecSmrg	}
408005b261ecSmrg	if (!i && free)
408105b261ecSmrg	{
408205b261ecSmrg	    i = free;
408305b261ecSmrg	    DontPropagateMasks[i] = mask;
408405b261ecSmrg	}
408505b261ecSmrg    }
408605b261ecSmrg    if (i || !mask)
408705b261ecSmrg    {
408805b261ecSmrg	pWin->dontPropagate = i;
408905b261ecSmrg	if (i)
409005b261ecSmrg	    DontPropagateRefCnts[i]++;
409105b261ecSmrg	if (pWin->optional)
409205b261ecSmrg	{
409305b261ecSmrg	    pWin->optional->dontPropagateMask = mask;
409405b261ecSmrg	    *checkOptional = TRUE;
409505b261ecSmrg	}
409605b261ecSmrg    }
409705b261ecSmrg    else
409805b261ecSmrg    {
409905b261ecSmrg	if (!pWin->optional && !MakeWindowOptional (pWin))
410005b261ecSmrg	{
410105b261ecSmrg	    if (pWin->dontPropagate)
410205b261ecSmrg		DontPropagateRefCnts[pWin->dontPropagate]++;
410305b261ecSmrg	    return BadAlloc;
410405b261ecSmrg	}
410505b261ecSmrg	pWin->dontPropagate = 0;
410605b261ecSmrg        pWin->optional->dontPropagateMask = mask;
410705b261ecSmrg    }
410805b261ecSmrg    RecalculateDeliverableEvents(pWin);
410905b261ecSmrg    return Success;
411005b261ecSmrg}
411105b261ecSmrg
411205b261ecSmrg/**
41134642e01fSmrg * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
41144642e01fSmrg * Uses the paired keyboard to get some additional information.
411505b261ecSmrg */
41164642e01fSmrgvoid
41174642e01fSmrgCoreEnterLeaveEvent(
41184642e01fSmrg    DeviceIntPtr mouse,
411905b261ecSmrg    int type,
412005b261ecSmrg    int mode,
412105b261ecSmrg    int detail,
412205b261ecSmrg    WindowPtr pWin,
412305b261ecSmrg    Window child)
412405b261ecSmrg{
41254642e01fSmrg    xEvent              event;
412605b261ecSmrg    WindowPtr		focus;
41274642e01fSmrg    DeviceIntPtr        keybd;
41284642e01fSmrg    GrabPtr	        grab = mouse->deviceGrab.grab;
412905b261ecSmrg    Mask		mask;
413005b261ecSmrg
41314642e01fSmrg    keybd = GetPairedDevice(mouse);
41324642e01fSmrg
413305b261ecSmrg    if ((pWin == mouse->valuator->motionHintWindow) &&
413405b261ecSmrg	(detail != NotifyInferior))
413505b261ecSmrg	mouse->valuator->motionHintWindow = NullWindow;
413605b261ecSmrg    if (grab)
413705b261ecSmrg    {
413805b261ecSmrg	mask = (pWin == grab->window) ? grab->eventMask : 0;
413905b261ecSmrg	if (grab->ownerEvents)
414005b261ecSmrg	    mask |= EventMaskForClient(pWin, rClient(grab));
414105b261ecSmrg    }
414205b261ecSmrg    else
414305b261ecSmrg    {
414405b261ecSmrg	mask = pWin->eventMask | wOtherEventMasks(pWin);
414505b261ecSmrg    }
41464642e01fSmrg
41474642e01fSmrg    event.u.u.type = type;
41484642e01fSmrg    event.u.u.detail = detail;
41494642e01fSmrg    event.u.enterLeave.time = currentTime.milliseconds;
41504642e01fSmrg    event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x;
41514642e01fSmrg    event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y;
41524642e01fSmrg    /* Counts on the same initial structure of crossing & button events! */
41534642e01fSmrg    FixUpEventFromWindow(mouse, &event, pWin, None, FALSE);
41544642e01fSmrg    /* Enter/Leave events always set child */
41554642e01fSmrg    event.u.enterLeave.child = child;
41564642e01fSmrg    event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
41574642e01fSmrg        ELFlagSameScreen : 0;
415805b261ecSmrg#ifdef XKB
41594642e01fSmrg    if (!noXkbExtension) {
41604642e01fSmrg        event.u.enterLeave.state = mouse->button->state & 0x1f00;
41614642e01fSmrg        if (keybd)
41624642e01fSmrg            event.u.enterLeave.state |=
41634642e01fSmrg                XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
41644642e01fSmrg    } else
416505b261ecSmrg#endif
416605b261ecSmrg    {
41674642e01fSmrg        event.u.enterLeave.state = (keybd) ? keybd->key->state : 0;
41684642e01fSmrg        event.u.enterLeave.state |= mouse->button->state;
416905b261ecSmrg    }
41704642e01fSmrg    event.u.enterLeave.mode = mode;
41714642e01fSmrg    focus = (keybd) ? keybd->focus->win : None;
41724642e01fSmrg    if ((focus != NoneWin) &&
41734642e01fSmrg            ((pWin == focus) || (focus == PointerRootWin) ||
41744642e01fSmrg             IsParent(focus, pWin)))
41754642e01fSmrg        event.u.enterLeave.flags |= ELFlagFocus;
417605b261ecSmrg
41774642e01fSmrg    if ((mask & filters[mouse->id][type]))
417805b261ecSmrg    {
41794642e01fSmrg        if (grab)
41804642e01fSmrg            TryClientEvents(rClient(grab), mouse, &event, 1, mask,
41814642e01fSmrg                                  filters[mouse->id][type], grab);
41824642e01fSmrg        else
41834642e01fSmrg            DeliverEventsToWindow(mouse, pWin, &event, 1,
41844642e01fSmrg                                  filters[mouse->id][type], NullGrab, 0);
418505b261ecSmrg    }
418605b261ecSmrg
41874642e01fSmrg    if ((type == EnterNotify) && (mask & KeymapStateMask))
418805b261ecSmrg    {
41894642e01fSmrg        xKeymapEvent ke;
41904642e01fSmrg        ClientPtr client = grab ? rClient(grab)
41914642e01fSmrg            : clients[CLIENT_ID(pWin->drawable.id)];
41924642e01fSmrg        if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess))
41934642e01fSmrg            bzero((char *)&ke.map[0], 31);
41944642e01fSmrg        else
41954642e01fSmrg            memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31);
41964642e01fSmrg
41974642e01fSmrg        ke.type = KeymapNotify;
41984642e01fSmrg        if (grab)
41994642e01fSmrg            TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1,
42004642e01fSmrg                            mask, KeymapStateMask, grab);
42014642e01fSmrg        else
42024642e01fSmrg            DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1,
42034642e01fSmrg                                  KeymapStateMask, NullGrab, 0);
420405b261ecSmrg    }
420505b261ecSmrg}
420605b261ecSmrg
42074642e01fSmrgvoid
42084642e01fSmrgCoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
420905b261ecSmrg{
421005b261ecSmrg    xEvent event;
421105b261ecSmrg
421205b261ecSmrg    event.u.focus.mode = mode;
421305b261ecSmrg    event.u.u.type = type;
421405b261ecSmrg    event.u.u.detail = detail;
421505b261ecSmrg    event.u.focus.window = pWin->drawable.id;
42164642e01fSmrg    (void)DeliverEventsToWindow(dev, pWin, &event, 1,
42174642e01fSmrg            filters[dev->id][type], NullGrab, 0);
421805b261ecSmrg    if ((type == FocusIn) &&
42194642e01fSmrg            ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
422005b261ecSmrg    {
42214642e01fSmrg        xKeymapEvent ke;
42224642e01fSmrg        ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)];
42234642e01fSmrg        if (XaceHook(XACE_DEVICE_ACCESS, client, dev, FALSE))
42244642e01fSmrg            memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
42254642e01fSmrg        else
42264642e01fSmrg            bzero((char *)&ke.map[0], 31);
422705b261ecSmrg
42284642e01fSmrg        ke.type = KeymapNotify;
42294642e01fSmrg        (void)DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1,
42304642e01fSmrg                KeymapStateMask, NullGrab, 0);
423105b261ecSmrg    }
423205b261ecSmrg}
423305b261ecSmrg
423405b261ecSmrg/**
423505b261ecSmrg * Set the input focus to the given window. Subsequent keyboard events will be
423605b261ecSmrg * delivered to the given window.
42374642e01fSmrg *
423805b261ecSmrg * Usually called from ProcSetInputFocus as result of a client request. If so,
423905b261ecSmrg * the device is the inputInfo.keyboard.
424005b261ecSmrg * If called from ProcXSetInputFocus as result of a client xinput request, the
424105b261ecSmrg * device is set to the device specified by the client.
424205b261ecSmrg *
424305b261ecSmrg * @param client Client that requested input focus change.
42444642e01fSmrg * @param dev Focus device.
424505b261ecSmrg * @param focusID The window to obtain the focus. Can be PointerRoot or None.
424605b261ecSmrg * @param revertTo Specifies where the focus reverts to when window becomes
424705b261ecSmrg * unviewable.
424805b261ecSmrg * @param ctime Specifies the time.
424905b261ecSmrg * @param followOK True if pointer is allowed to follow the keyboard.
425005b261ecSmrg */
425105b261ecSmrgint
425205b261ecSmrgSetInputFocus(
425305b261ecSmrg    ClientPtr client,
425405b261ecSmrg    DeviceIntPtr dev,
425505b261ecSmrg    Window focusID,
425605b261ecSmrg    CARD8 revertTo,
425705b261ecSmrg    Time ctime,
425805b261ecSmrg    Bool followOK)
425905b261ecSmrg{
426005b261ecSmrg    FocusClassPtr focus;
426105b261ecSmrg    WindowPtr focusWin;
426205b261ecSmrg    int mode, rc;
426305b261ecSmrg    TimeStamp time;
42644642e01fSmrg    DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */
42654642e01fSmrg
426605b261ecSmrg
426705b261ecSmrg    UpdateCurrentTime();
426805b261ecSmrg    if ((revertTo != RevertToParent) &&
426905b261ecSmrg	(revertTo != RevertToPointerRoot) &&
427005b261ecSmrg	(revertTo != RevertToNone) &&
427105b261ecSmrg	((revertTo != RevertToFollowKeyboard) || !followOK))
427205b261ecSmrg    {
427305b261ecSmrg	client->errorValue = revertTo;
427405b261ecSmrg	return BadValue;
427505b261ecSmrg    }
427605b261ecSmrg    time = ClientTimeToServerTime(ctime);
42774642e01fSmrg
42784642e01fSmrg    if (IsKeyboardDevice(dev))
42794642e01fSmrg        keybd = dev;
42804642e01fSmrg    else
42814642e01fSmrg        keybd = GetPairedDevice(dev);
42824642e01fSmrg
428305b261ecSmrg    if ((focusID == None) || (focusID == PointerRoot))
428405b261ecSmrg	focusWin = (WindowPtr)(long)focusID;
428505b261ecSmrg    else if ((focusID == FollowKeyboard) && followOK)
42864642e01fSmrg    {
42874642e01fSmrg	focusWin = keybd->focus->win;
42884642e01fSmrg    }
428905b261ecSmrg    else {
42904642e01fSmrg	rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess);
429105b261ecSmrg	if (rc != Success)
429205b261ecSmrg	    return rc;
42934642e01fSmrg	/* It is a match error to try to set the input focus to an
429405b261ecSmrg	unviewable window. */
429505b261ecSmrg	if(!focusWin->realized)
429605b261ecSmrg	    return(BadMatch);
429705b261ecSmrg    }
42984642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess);
42994642e01fSmrg    if (rc != Success)
43004642e01fSmrg	return Success;
43014642e01fSmrg
430205b261ecSmrg    focus = dev->focus;
430305b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
430405b261ecSmrg	(CompareTimeStamps(time, focus->time) == EARLIER))
430505b261ecSmrg	return Success;
43064642e01fSmrg    mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal;
430705b261ecSmrg    if (focus->win == FollowKeyboardWin)
43084642e01fSmrg	DoFocusEvents(dev, keybd->focus->win, focusWin, mode);
430905b261ecSmrg    else
431005b261ecSmrg	DoFocusEvents(dev, focus->win, focusWin, mode);
431105b261ecSmrg    focus->time = time;
431205b261ecSmrg    focus->revert = revertTo;
431305b261ecSmrg    if (focusID == FollowKeyboard)
431405b261ecSmrg	focus->win = FollowKeyboardWin;
431505b261ecSmrg    else
431605b261ecSmrg	focus->win = focusWin;
431705b261ecSmrg    if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
431805b261ecSmrg	focus->traceGood = 0;
431905b261ecSmrg    else
432005b261ecSmrg    {
432105b261ecSmrg        int depth = 0;
432205b261ecSmrg	WindowPtr pWin;
432305b261ecSmrg
432405b261ecSmrg        for (pWin = focusWin; pWin; pWin = pWin->parent) depth++;
432505b261ecSmrg        if (depth > focus->traceSize)
432605b261ecSmrg        {
432705b261ecSmrg	    focus->traceSize = depth+1;
43284642e01fSmrg	    focus->trace = xrealloc(focus->trace,
43294642e01fSmrg				    focus->traceSize * sizeof(WindowPtr));
433005b261ecSmrg	}
433105b261ecSmrg	focus->traceGood = depth;
43324642e01fSmrg        for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
433305b261ecSmrg	    focus->trace[depth] = pWin;
433405b261ecSmrg    }
433505b261ecSmrg    return Success;
433605b261ecSmrg}
433705b261ecSmrg
433805b261ecSmrg/**
433905b261ecSmrg * Server-side protocol handling for SetInputFocus request.
434005b261ecSmrg *
434105b261ecSmrg * Sets the input focus for the virtual core keyboard.
434205b261ecSmrg */
434305b261ecSmrgint
434405b261ecSmrgProcSetInputFocus(client)
434505b261ecSmrg    ClientPtr client;
434605b261ecSmrg{
43474642e01fSmrg    DeviceIntPtr kbd = PickKeyboard(client);
434805b261ecSmrg    REQUEST(xSetInputFocusReq);
434905b261ecSmrg
435005b261ecSmrg    REQUEST_SIZE_MATCH(xSetInputFocusReq);
435105b261ecSmrg
43524642e01fSmrg    return SetInputFocus(client, kbd, stuff->focus,
435305b261ecSmrg			 stuff->revertTo, stuff->time, FALSE);
435405b261ecSmrg}
435505b261ecSmrg
435605b261ecSmrg/**
435705b261ecSmrg * Server-side protocol handling for GetInputFocus request.
43584642e01fSmrg *
43594642e01fSmrg * Sends the current input focus for the client's keyboard back to the
436005b261ecSmrg * client.
436105b261ecSmrg */
436205b261ecSmrgint
436305b261ecSmrgProcGetInputFocus(ClientPtr client)
436405b261ecSmrg{
43654642e01fSmrg    DeviceIntPtr kbd = PickKeyboard(client);
436605b261ecSmrg    xGetInputFocusReply rep;
43674642e01fSmrg    FocusClassPtr focus = kbd->focus;
43684642e01fSmrg    int rc;
436905b261ecSmrg    /* REQUEST(xReq); */
437005b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
43714642e01fSmrg
43724642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess);
43734642e01fSmrg    if (rc != Success)
43744642e01fSmrg	return rc;
43754642e01fSmrg
437605b261ecSmrg    rep.type = X_Reply;
437705b261ecSmrg    rep.length = 0;
437805b261ecSmrg    rep.sequenceNumber = client->sequence;
437905b261ecSmrg    if (focus->win == NoneWin)
438005b261ecSmrg	rep.focus = None;
438105b261ecSmrg    else if (focus->win == PointerRootWin)
438205b261ecSmrg	rep.focus = PointerRoot;
438305b261ecSmrg    else rep.focus = focus->win->drawable.id;
438405b261ecSmrg    rep.revertTo = focus->revert;
438505b261ecSmrg    WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
438605b261ecSmrg    return Success;
438705b261ecSmrg}
438805b261ecSmrg
438905b261ecSmrg/**
43904642e01fSmrg * Server-side protocol handling for GrabPointer request.
439105b261ecSmrg *
43924642e01fSmrg * Sets an active grab on the client's ClientPointer and returns success
43934642e01fSmrg * status to client.
439405b261ecSmrg */
439505b261ecSmrgint
439605b261ecSmrgProcGrabPointer(ClientPtr client)
439705b261ecSmrg{
439805b261ecSmrg    xGrabPointerReply rep;
43994642e01fSmrg    DeviceIntPtr device = PickPointer(client);
440005b261ecSmrg    GrabPtr grab;
440105b261ecSmrg    WindowPtr pWin, confineTo;
440205b261ecSmrg    CursorPtr cursor, oldCursor;
440305b261ecSmrg    REQUEST(xGrabPointerReq);
440405b261ecSmrg    TimeStamp time;
44054642e01fSmrg    Mask access_mode = DixGrabAccess;
440605b261ecSmrg    int rc;
440705b261ecSmrg
440805b261ecSmrg    REQUEST_SIZE_MATCH(xGrabPointerReq);
440905b261ecSmrg    UpdateCurrentTime();
441005b261ecSmrg    if ((stuff->pointerMode != GrabModeSync) &&
441105b261ecSmrg	(stuff->pointerMode != GrabModeAsync))
441205b261ecSmrg    {
441305b261ecSmrg	client->errorValue = stuff->pointerMode;
441405b261ecSmrg        return BadValue;
441505b261ecSmrg    }
441605b261ecSmrg    if ((stuff->keyboardMode != GrabModeSync) &&
441705b261ecSmrg	(stuff->keyboardMode != GrabModeAsync))
441805b261ecSmrg    {
441905b261ecSmrg	client->errorValue = stuff->keyboardMode;
442005b261ecSmrg        return BadValue;
442105b261ecSmrg    }
442205b261ecSmrg    if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
442305b261ecSmrg    {
442405b261ecSmrg	client->errorValue = stuff->ownerEvents;
442505b261ecSmrg        return BadValue;
442605b261ecSmrg    }
442705b261ecSmrg    if (stuff->eventMask & ~PointerGrabMask)
442805b261ecSmrg    {
442905b261ecSmrg	client->errorValue = stuff->eventMask;
443005b261ecSmrg        return BadValue;
443105b261ecSmrg    }
44324642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
443305b261ecSmrg    if (rc != Success)
443405b261ecSmrg	return rc;
443505b261ecSmrg    if (stuff->confineTo == None)
443605b261ecSmrg	confineTo = NullWindow;
44374642e01fSmrg    else
443805b261ecSmrg    {
443905b261ecSmrg	rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
44404642e01fSmrg			     DixSetAttrAccess);
444105b261ecSmrg	if (rc != Success)
444205b261ecSmrg	    return rc;
444305b261ecSmrg    }
444405b261ecSmrg    if (stuff->cursor == None)
444505b261ecSmrg	cursor = NullCursor;
444605b261ecSmrg    else
444705b261ecSmrg    {
44484642e01fSmrg	rc = dixLookupResource((pointer *)&cursor, stuff->cursor, RT_CURSOR,
44494642e01fSmrg			       client, DixUseAccess);
44504642e01fSmrg	if (rc != Success)
445105b261ecSmrg	{
445205b261ecSmrg	    client->errorValue = stuff->cursor;
44534642e01fSmrg	    return (rc == BadValue) ? BadCursor : rc;
445405b261ecSmrg	}
44554642e01fSmrg	access_mode |= DixForceAccess;
445605b261ecSmrg    }
44574642e01fSmrg    if (stuff->pointerMode == GrabModeSync ||
44584642e01fSmrg	stuff->keyboardMode == GrabModeSync)
44594642e01fSmrg	access_mode |= DixFreezeAccess;
44604642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, device, access_mode);
44614642e01fSmrg    if (rc != Success)
44624642e01fSmrg	return rc;
44634642e01fSmrg
446405b261ecSmrg	/* at this point, some sort of reply is guaranteed. */
446505b261ecSmrg    time = ClientTimeToServerTime(stuff->time);
446605b261ecSmrg    rep.type = X_Reply;
446705b261ecSmrg    rep.sequenceNumber = client->sequence;
446805b261ecSmrg    rep.length = 0;
44694642e01fSmrg
44704642e01fSmrg    grab = device->deviceGrab.grab;
44714642e01fSmrg    /* check for
44724642e01fSmrg       1. other client has a grab on the device already.
44734642e01fSmrg       2. window is viewable
44744642e01fSmrg       3. other client has this device as frozen "other" device
44754642e01fSmrg       4. times are screwed.
44764642e01fSmrg     */
447705b261ecSmrg    if ((grab) && !SameClient(grab, client))
447805b261ecSmrg	rep.status = AlreadyGrabbed;
447905b261ecSmrg    else if ((!pWin->realized) ||
448005b261ecSmrg             (confineTo &&
44814642e01fSmrg                !(confineTo->realized
44824642e01fSmrg                    && BorderSizeNotEmpty(device, confineTo))))
448305b261ecSmrg	rep.status = GrabNotViewable;
44844642e01fSmrg    else if (device->deviceGrab.sync.frozen &&
44854642e01fSmrg	     device->deviceGrab.sync.other &&
44864642e01fSmrg             !SameClient(device->deviceGrab.sync.other, client))
448705b261ecSmrg	rep.status = GrabFrozen;
448805b261ecSmrg    else if ((CompareTimeStamps(time, currentTime) == LATER) ||
44894642e01fSmrg	     (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
449005b261ecSmrg	rep.status = GrabInvalidTime;
449105b261ecSmrg    else
449205b261ecSmrg    {
449305b261ecSmrg	GrabRec tempGrab;
449405b261ecSmrg
449505b261ecSmrg	oldCursor = NullCursor;
449605b261ecSmrg	if (grab)
44974642e01fSmrg	{
449805b261ecSmrg	    if (grab->confineTo && !confineTo)
44994642e01fSmrg		ConfineCursorToWindow(device, RootWindow(device), FALSE, FALSE);
450005b261ecSmrg	    oldCursor = grab->cursor;
450105b261ecSmrg	}
45024642e01fSmrg        tempGrab.next = NULL;
450305b261ecSmrg	tempGrab.cursor = cursor;
450405b261ecSmrg	tempGrab.resource = client->clientAsMask;
450505b261ecSmrg	tempGrab.ownerEvents = stuff->ownerEvents;
450605b261ecSmrg	tempGrab.eventMask = stuff->eventMask;
450705b261ecSmrg	tempGrab.confineTo = confineTo;
450805b261ecSmrg	tempGrab.window = pWin;
450905b261ecSmrg	tempGrab.keyboardMode = stuff->keyboardMode;
451005b261ecSmrg	tempGrab.pointerMode = stuff->pointerMode;
451105b261ecSmrg	tempGrab.device = device;
45124642e01fSmrg        tempGrab.coreGrab = True;
45134642e01fSmrg        tempGrab.genericMasks = NULL;
45144642e01fSmrg	(*device->deviceGrab.ActivateGrab)(device, &tempGrab, time, FALSE);
451505b261ecSmrg	if (oldCursor)
451605b261ecSmrg	    FreeCursor (oldCursor, (Cursor)0);
451705b261ecSmrg	rep.status = GrabSuccess;
451805b261ecSmrg    }
451905b261ecSmrg    WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
452005b261ecSmrg    return Success;
452105b261ecSmrg}
452205b261ecSmrg
452305b261ecSmrg/**
452405b261ecSmrg * Server-side protocol handling for ChangeActivePointerGrab request.
452505b261ecSmrg *
452605b261ecSmrg * Changes properties of the grab hold by the client. If the client does not
45274642e01fSmrg * hold an active grab on the device, nothing happens.
452805b261ecSmrg */
452905b261ecSmrgint
453005b261ecSmrgProcChangeActivePointerGrab(ClientPtr client)
453105b261ecSmrg{
45324642e01fSmrg    DeviceIntPtr device;
45334642e01fSmrg    GrabPtr      grab;
453405b261ecSmrg    CursorPtr newCursor, oldCursor;
453505b261ecSmrg    REQUEST(xChangeActivePointerGrabReq);
453605b261ecSmrg    TimeStamp time;
453705b261ecSmrg
453805b261ecSmrg    REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
453905b261ecSmrg    if (stuff->eventMask & ~PointerGrabMask)
454005b261ecSmrg    {
454105b261ecSmrg	client->errorValue = stuff->eventMask;
454205b261ecSmrg        return BadValue;
454305b261ecSmrg    }
454405b261ecSmrg    if (stuff->cursor == None)
454505b261ecSmrg	newCursor = NullCursor;
454605b261ecSmrg    else
454705b261ecSmrg    {
45484642e01fSmrg	int rc = dixLookupResource((pointer *)&newCursor, stuff->cursor,
45494642e01fSmrg				   RT_CURSOR, client, DixUseAccess);
45504642e01fSmrg	if (rc != Success)
455105b261ecSmrg	{
455205b261ecSmrg	    client->errorValue = stuff->cursor;
45534642e01fSmrg	    return (rc == BadValue) ? BadCursor : rc;
455405b261ecSmrg	}
455505b261ecSmrg    }
45564642e01fSmrg
45574642e01fSmrg    device = PickPointer(client);
45584642e01fSmrg    grab = device->deviceGrab.grab;
45594642e01fSmrg
456005b261ecSmrg    if (!grab)
456105b261ecSmrg	return Success;
456205b261ecSmrg    if (!SameClient(grab, client))
456305b261ecSmrg	return Success;
456405b261ecSmrg    time = ClientTimeToServerTime(stuff->time);
456505b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
45664642e01fSmrg	     (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
456705b261ecSmrg	return Success;
456805b261ecSmrg    oldCursor = grab->cursor;
456905b261ecSmrg    grab->cursor = newCursor;
457005b261ecSmrg    if (newCursor)
457105b261ecSmrg	newCursor->refcnt++;
45724642e01fSmrg    PostNewCursor(device);
457305b261ecSmrg    if (oldCursor)
457405b261ecSmrg	FreeCursor(oldCursor, (Cursor)0);
457505b261ecSmrg    grab->eventMask = stuff->eventMask;
457605b261ecSmrg    return Success;
457705b261ecSmrg}
457805b261ecSmrg
457905b261ecSmrg/**
458005b261ecSmrg * Server-side protocol handling for UngrabPointer request.
458105b261ecSmrg *
45824642e01fSmrg * Deletes a pointer grab on a device the client has grabbed.
458305b261ecSmrg */
458405b261ecSmrgint
458505b261ecSmrgProcUngrabPointer(ClientPtr client)
458605b261ecSmrg{
45874642e01fSmrg    DeviceIntPtr device = PickPointer(client);
458805b261ecSmrg    GrabPtr grab;
458905b261ecSmrg    TimeStamp time;
459005b261ecSmrg    REQUEST(xResourceReq);
459105b261ecSmrg
459205b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
459305b261ecSmrg    UpdateCurrentTime();
45944642e01fSmrg    grab = device->deviceGrab.grab;
45954642e01fSmrg
459605b261ecSmrg    time = ClientTimeToServerTime(stuff->id);
459705b261ecSmrg    if ((CompareTimeStamps(time, currentTime) != LATER) &&
45984642e01fSmrg	    (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
459905b261ecSmrg	    (grab) && SameClient(grab, client))
46004642e01fSmrg	(*device->deviceGrab.DeactivateGrab)(device);
460105b261ecSmrg    return Success;
460205b261ecSmrg}
460305b261ecSmrg
460405b261ecSmrg/**
460505b261ecSmrg * Sets a grab on the given device.
46064642e01fSmrg *
46074642e01fSmrg * Called from ProcGrabKeyboard to work on the client's keyboard.
460805b261ecSmrg * Called from ProcXGrabDevice to work on the device specified by the client.
46094642e01fSmrg *
461005b261ecSmrg * The parameters this_mode and other_mode represent the keyboard_mode and
46114642e01fSmrg * pointer_mode parameters of XGrabKeyboard().
461205b261ecSmrg * See man page for details on all the parameters
46134642e01fSmrg *
461405b261ecSmrg * @param client Client that owns the grab.
46154642e01fSmrg * @param dev The device to grab.
461605b261ecSmrg * @param this_mode GrabModeSync or GrabModeAsync
461705b261ecSmrg * @param other_mode GrabModeSync or GrabModeAsync
461805b261ecSmrg * @param status Return code to be returned to the caller.
46194642e01fSmrg *
462005b261ecSmrg * @returns Success or BadValue.
462105b261ecSmrg */
462205b261ecSmrgint
46234642e01fSmrgGrabDevice(ClientPtr client, DeviceIntPtr dev,
46244642e01fSmrg           unsigned this_mode, unsigned other_mode, Window grabWindow,
46254642e01fSmrg           unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status,
46264642e01fSmrg           Bool coreGrab)
462705b261ecSmrg{
462805b261ecSmrg    WindowPtr pWin;
462905b261ecSmrg    GrabPtr grab;
463005b261ecSmrg    TimeStamp time;
46314642e01fSmrg    Mask access_mode = DixGrabAccess;
463205b261ecSmrg    int rc;
46334642e01fSmrg    GrabInfoPtr grabInfo = &dev->deviceGrab;
463405b261ecSmrg
463505b261ecSmrg    UpdateCurrentTime();
463605b261ecSmrg    if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync))
463705b261ecSmrg    {
463805b261ecSmrg	client->errorValue = this_mode;
463905b261ecSmrg        return BadValue;
464005b261ecSmrg    }
464105b261ecSmrg    if ((other_mode != GrabModeSync) && (other_mode != GrabModeAsync))
464205b261ecSmrg    {
464305b261ecSmrg	client->errorValue = other_mode;
464405b261ecSmrg        return BadValue;
464505b261ecSmrg    }
464605b261ecSmrg    if ((ownerEvents != xFalse) && (ownerEvents != xTrue))
464705b261ecSmrg    {
464805b261ecSmrg	client->errorValue = ownerEvents;
464905b261ecSmrg        return BadValue;
465005b261ecSmrg    }
46514642e01fSmrg
46524642e01fSmrg    rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
465305b261ecSmrg    if (rc != Success)
465405b261ecSmrg	return rc;
46554642e01fSmrg    if (this_mode == GrabModeSync || other_mode == GrabModeSync)
46564642e01fSmrg	access_mode |= DixFreezeAccess;
46574642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
46584642e01fSmrg    if (rc != Success)
46594642e01fSmrg	return rc;
46604642e01fSmrg
466105b261ecSmrg    time = ClientTimeToServerTime(ctime);
46624642e01fSmrg    grab = grabInfo->grab;
466305b261ecSmrg    if (grab && !SameClient(grab, client))
466405b261ecSmrg	*status = AlreadyGrabbed;
466505b261ecSmrg    else if (!pWin->realized)
466605b261ecSmrg	*status = GrabNotViewable;
466705b261ecSmrg    else if ((CompareTimeStamps(time, currentTime) == LATER) ||
46684642e01fSmrg	     (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER))
466905b261ecSmrg	*status = GrabInvalidTime;
46704642e01fSmrg    else if (grabInfo->sync.frozen &&
46714642e01fSmrg	     grabInfo->sync.other && !SameClient(grabInfo->sync.other, client))
467205b261ecSmrg	*status = GrabFrozen;
467305b261ecSmrg    else
467405b261ecSmrg    {
467505b261ecSmrg	GrabRec tempGrab;
467605b261ecSmrg
46774642e01fSmrg        /* Otherwise segfaults happen on grabbed MPX devices */
46784642e01fSmrg        memset(&tempGrab, 0, sizeof(GrabRec));
46794642e01fSmrg
46804642e01fSmrg        tempGrab.next = NULL;
468105b261ecSmrg	tempGrab.window = pWin;
468205b261ecSmrg	tempGrab.resource = client->clientAsMask;
468305b261ecSmrg	tempGrab.ownerEvents = ownerEvents;
468405b261ecSmrg	tempGrab.keyboardMode = this_mode;
468505b261ecSmrg	tempGrab.pointerMode = other_mode;
468605b261ecSmrg	tempGrab.eventMask = mask;
468705b261ecSmrg	tempGrab.device = dev;
46884642e01fSmrg        tempGrab.cursor = NULL;
46894642e01fSmrg        tempGrab.coreGrab = coreGrab;
46904642e01fSmrg        tempGrab.genericMasks = NULL;
46914642e01fSmrg
46924642e01fSmrg	(*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE);
469305b261ecSmrg	*status = GrabSuccess;
469405b261ecSmrg    }
469505b261ecSmrg    return Success;
469605b261ecSmrg}
469705b261ecSmrg
469805b261ecSmrg/**
469905b261ecSmrg * Server-side protocol handling for GrabKeyboard request.
470005b261ecSmrg *
47014642e01fSmrg * Grabs the client's keyboard and returns success status to client.
470205b261ecSmrg */
470305b261ecSmrgint
470405b261ecSmrgProcGrabKeyboard(ClientPtr client)
470505b261ecSmrg{
470605b261ecSmrg    xGrabKeyboardReply rep;
470705b261ecSmrg    REQUEST(xGrabKeyboardReq);
470805b261ecSmrg    int result;
47094642e01fSmrg    DeviceIntPtr keyboard = PickKeyboard(client);
471005b261ecSmrg
471105b261ecSmrg    REQUEST_SIZE_MATCH(xGrabKeyboardReq);
471205b261ecSmrg
47134642e01fSmrg    result = GrabDevice(client, keyboard, stuff->keyboardMode,
47144642e01fSmrg            stuff->pointerMode, stuff->grabWindow,
47154642e01fSmrg            stuff->ownerEvents, stuff->time,
47164642e01fSmrg            KeyPressMask | KeyReleaseMask, &rep.status, TRUE);
471705b261ecSmrg
471805b261ecSmrg    if (result != Success)
471905b261ecSmrg	return result;
472005b261ecSmrg    rep.type = X_Reply;
472105b261ecSmrg    rep.sequenceNumber = client->sequence;
472205b261ecSmrg    rep.length = 0;
472305b261ecSmrg    WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
472405b261ecSmrg    return Success;
472505b261ecSmrg}
472605b261ecSmrg
472705b261ecSmrg/**
472805b261ecSmrg * Server-side protocol handling for UngrabKeyboard request.
472905b261ecSmrg *
47304642e01fSmrg * Deletes a possible grab on the client's keyboard.
473105b261ecSmrg */
473205b261ecSmrgint
473305b261ecSmrgProcUngrabKeyboard(ClientPtr client)
473405b261ecSmrg{
47354642e01fSmrg    DeviceIntPtr device = PickKeyboard(client);
473605b261ecSmrg    GrabPtr grab;
473705b261ecSmrg    TimeStamp time;
473805b261ecSmrg    REQUEST(xResourceReq);
473905b261ecSmrg
474005b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
474105b261ecSmrg    UpdateCurrentTime();
47424642e01fSmrg
47434642e01fSmrg    grab = device->deviceGrab.grab;
47444642e01fSmrg
474505b261ecSmrg    time = ClientTimeToServerTime(stuff->id);
474605b261ecSmrg    if ((CompareTimeStamps(time, currentTime) != LATER) &&
47474642e01fSmrg	(CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
47484642e01fSmrg	(grab) && SameClient(grab, client) && grab->coreGrab)
47494642e01fSmrg	(*device->deviceGrab.DeactivateGrab)(device);
475005b261ecSmrg    return Success;
475105b261ecSmrg}
475205b261ecSmrg
475305b261ecSmrg/**
475405b261ecSmrg * Server-side protocol handling for QueryPointer request.
475505b261ecSmrg *
47564642e01fSmrg * Returns the current state and position of the client's ClientPointer to the
47574642e01fSmrg * client.
475805b261ecSmrg */
475905b261ecSmrgint
476005b261ecSmrgProcQueryPointer(ClientPtr client)
476105b261ecSmrg{
476205b261ecSmrg    xQueryPointerReply rep;
476305b261ecSmrg    WindowPtr pWin, t;
47644642e01fSmrg    DeviceIntPtr mouse = PickPointer(client);
47654642e01fSmrg    SpritePtr pSprite;
476605b261ecSmrg    int rc;
47674642e01fSmrg    REQUEST(xResourceReq);
476805b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
47694642e01fSmrg
47704642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
47714642e01fSmrg    if (rc != Success)
47724642e01fSmrg	return rc;
47734642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
477405b261ecSmrg    if (rc != Success)
477505b261ecSmrg	return rc;
47764642e01fSmrg
47774642e01fSmrg    pSprite = mouse->spriteInfo->sprite;
477805b261ecSmrg    if (mouse->valuator->motionHintWindow)
477905b261ecSmrg	MaybeStopHint(mouse, client);
478005b261ecSmrg    rep.type = X_Reply;
478105b261ecSmrg    rep.sequenceNumber = client->sequence;
478205b261ecSmrg    rep.mask = mouse->button->state | inputInfo.keyboard->key->state;
478305b261ecSmrg    rep.length = 0;
47844642e01fSmrg    rep.root = (RootWindow(mouse))->drawable.id;
47854642e01fSmrg    rep.rootX = pSprite->hot.x;
47864642e01fSmrg    rep.rootY = pSprite->hot.y;
478705b261ecSmrg    rep.child = None;
47884642e01fSmrg    if (pSprite->hot.pScreen == pWin->drawable.pScreen)
478905b261ecSmrg    {
479005b261ecSmrg	rep.sameScreen = xTrue;
47914642e01fSmrg	rep.winX = pSprite->hot.x - pWin->drawable.x;
47924642e01fSmrg	rep.winY = pSprite->hot.y - pWin->drawable.y;
47934642e01fSmrg	for (t = pSprite->win; t; t = t->parent)
479405b261ecSmrg	    if (t->parent == pWin)
479505b261ecSmrg	    {
479605b261ecSmrg		rep.child = t->drawable.id;
479705b261ecSmrg		break;
479805b261ecSmrg	    }
479905b261ecSmrg    }
480005b261ecSmrg    else
480105b261ecSmrg    {
480205b261ecSmrg	rep.sameScreen = xFalse;
480305b261ecSmrg	rep.winX = 0;
480405b261ecSmrg	rep.winY = 0;
480505b261ecSmrg    }
480605b261ecSmrg
480705b261ecSmrg#ifdef PANORAMIX
480805b261ecSmrg    if(!noPanoramiXExtension) {
480905b261ecSmrg	rep.rootX += panoramiXdataPtr[0].x;
481005b261ecSmrg	rep.rootY += panoramiXdataPtr[0].y;
481105b261ecSmrg	if(stuff->id == rep.root) {
481205b261ecSmrg	    rep.winX += panoramiXdataPtr[0].x;
481305b261ecSmrg	    rep.winY += panoramiXdataPtr[0].y;
481405b261ecSmrg	}
481505b261ecSmrg    }
481605b261ecSmrg#endif
481705b261ecSmrg
481805b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
481905b261ecSmrg
48204642e01fSmrg    return(Success);
482105b261ecSmrg}
482205b261ecSmrg
482305b261ecSmrg/**
482405b261ecSmrg * Initializes the device list and the DIX sprite to sane values. Allocates
482505b261ecSmrg * trace memory used for quick window traversal.
482605b261ecSmrg */
482705b261ecSmrgvoid
482805b261ecSmrgInitEvents(void)
482905b261ecSmrg{
483005b261ecSmrg    int i;
483105b261ecSmrg
483205b261ecSmrg    inputInfo.numDevices = 0;
483305b261ecSmrg    inputInfo.devices = (DeviceIntPtr)NULL;
483405b261ecSmrg    inputInfo.off_devices = (DeviceIntPtr)NULL;
483505b261ecSmrg    inputInfo.keyboard = (DeviceIntPtr)NULL;
483605b261ecSmrg    inputInfo.pointer = (DeviceIntPtr)NULL;
48374642e01fSmrg    lastEventMask = OwnerGrabButtonMask;
48384642e01fSmrg    filters[0][PointerMotionMask] = MotionNotify;
48394642e01fSmrg    for (i = 1; i < MAXDEVICES; i++)
484005b261ecSmrg    {
48414642e01fSmrg        memcpy(&filters[i], filters[0], sizeof(filters[0]));
484205b261ecSmrg    }
48434642e01fSmrg
484405b261ecSmrg    syncEvents.replayDev = (DeviceIntPtr)NULL;
484505b261ecSmrg    syncEvents.replayWin = NullWindow;
484605b261ecSmrg    while (syncEvents.pending)
484705b261ecSmrg    {
484805b261ecSmrg	QdEventPtr next = syncEvents.pending->next;
484905b261ecSmrg	xfree(syncEvents.pending);
485005b261ecSmrg	syncEvents.pending = next;
485105b261ecSmrg    }
485205b261ecSmrg    syncEvents.pendtail = &syncEvents.pending;
485305b261ecSmrg    syncEvents.playingEvents = FALSE;
485405b261ecSmrg    syncEvents.time.months = 0;
485505b261ecSmrg    syncEvents.time.milliseconds = 0;	/* hardly matters */
485605b261ecSmrg    currentTime.months = 0;
485705b261ecSmrg    currentTime.milliseconds = GetTimeInMillis();
485805b261ecSmrg    lastDeviceEventTime = currentTime;
485905b261ecSmrg    for (i = 0; i < DNPMCOUNT; i++)
486005b261ecSmrg    {
486105b261ecSmrg	DontPropagateMasks[i] = 0;
486205b261ecSmrg	DontPropagateRefCnts[i] = 0;
486305b261ecSmrg    }
48644642e01fSmrg
48654642e01fSmrg    InputEventListLen = GetMaximumEventsNum();
48664642e01fSmrg    InputEventList = InitEventList(InputEventListLen);
48674642e01fSmrg    if (!InputEventList)
48684642e01fSmrg        FatalError("[dix] Failed to allocate input event list.\n");
486905b261ecSmrg}
487005b261ecSmrg
487105b261ecSmrgvoid
487205b261ecSmrgCloseDownEvents(void)
487305b261ecSmrg{
48744642e01fSmrg    int len;
48754642e01fSmrg    EventListPtr list;
48764642e01fSmrg
48774642e01fSmrg    len = GetEventList(&list);
48784642e01fSmrg    while(len--)
48794642e01fSmrg        xfree(list[len].event);
488005b261ecSmrg}
488105b261ecSmrg
488205b261ecSmrg/**
488305b261ecSmrg * Server-side protocol handling for SendEvent request.
488405b261ecSmrg *
48854642e01fSmrg * Locates the window to send the event to and forwards the event.
488605b261ecSmrg */
488705b261ecSmrgint
488805b261ecSmrgProcSendEvent(ClientPtr client)
488905b261ecSmrg{
489005b261ecSmrg    WindowPtr pWin;
489105b261ecSmrg    WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
48924642e01fSmrg    SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
489305b261ecSmrg    REQUEST(xSendEventReq);
489405b261ecSmrg
489505b261ecSmrg    REQUEST_SIZE_MATCH(xSendEventReq);
489605b261ecSmrg
489705b261ecSmrg    /* The client's event type must be a core event type or one defined by an
489805b261ecSmrg	extension. */
489905b261ecSmrg
490005b261ecSmrg    if ( ! ((stuff->event.u.u.type > X_Reply &&
49014642e01fSmrg	     stuff->event.u.u.type < LASTEvent) ||
490205b261ecSmrg	    (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
490305b261ecSmrg	     stuff->event.u.u.type < (unsigned)lastEvent)))
490405b261ecSmrg    {
490505b261ecSmrg	client->errorValue = stuff->event.u.u.type;
490605b261ecSmrg	return BadValue;
490705b261ecSmrg    }
490805b261ecSmrg    if (stuff->event.u.u.type == ClientMessage &&
490905b261ecSmrg	stuff->event.u.u.detail != 8 &&
491005b261ecSmrg	stuff->event.u.u.detail != 16 &&
491105b261ecSmrg	stuff->event.u.u.detail != 32)
491205b261ecSmrg    {
491305b261ecSmrg	client->errorValue = stuff->event.u.u.detail;
491405b261ecSmrg	return BadValue;
491505b261ecSmrg    }
491605b261ecSmrg    if (stuff->eventMask & ~AllEventMasks)
491705b261ecSmrg    {
491805b261ecSmrg	client->errorValue = stuff->eventMask;
491905b261ecSmrg	return BadValue;
492005b261ecSmrg    }
492105b261ecSmrg
492205b261ecSmrg    if (stuff->destination == PointerWindow)
49234642e01fSmrg	pWin = pSprite->win;
492405b261ecSmrg    else if (stuff->destination == InputFocus)
492505b261ecSmrg    {
492605b261ecSmrg	WindowPtr inputFocus = inputInfo.keyboard->focus->win;
492705b261ecSmrg
492805b261ecSmrg	if (inputFocus == NoneWin)
492905b261ecSmrg	    return Success;
493005b261ecSmrg
493105b261ecSmrg	/* If the input focus is PointerRootWin, send the event to where
493205b261ecSmrg	the pointer is if possible, then perhaps propogate up to root. */
49334642e01fSmrg	if (inputFocus == PointerRootWin)
49344642e01fSmrg	    inputFocus = pSprite->spriteTrace[0]; /* Root window! */
493505b261ecSmrg
49364642e01fSmrg	if (IsParent(inputFocus, pSprite->win))
493705b261ecSmrg	{
493805b261ecSmrg	    effectiveFocus = inputFocus;
49394642e01fSmrg	    pWin = pSprite->win;
494005b261ecSmrg	}
494105b261ecSmrg	else
494205b261ecSmrg	    effectiveFocus = pWin = inputFocus;
494305b261ecSmrg    }
494405b261ecSmrg    else
49454642e01fSmrg	dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess);
494605b261ecSmrg
494705b261ecSmrg    if (!pWin)
494805b261ecSmrg	return BadWindow;
494905b261ecSmrg    if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue))
495005b261ecSmrg    {
495105b261ecSmrg	client->errorValue = stuff->propagate;
495205b261ecSmrg	return BadValue;
495305b261ecSmrg    }
495405b261ecSmrg    stuff->event.u.u.type |= 0x80;
495505b261ecSmrg    if (stuff->propagate)
495605b261ecSmrg    {
495705b261ecSmrg	for (;pWin; pWin = pWin->parent)
495805b261ecSmrg	{
49594642e01fSmrg	    if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin,
49604642e01fSmrg			 &stuff->event, 1))
49614642e01fSmrg		return Success;
49624642e01fSmrg            if (DeliverEventsToWindow(PickPointer(client), pWin,
49634642e01fSmrg                        &stuff->event, 1, stuff->eventMask, NullGrab, 0))
496405b261ecSmrg		return Success;
496505b261ecSmrg	    if (pWin == effectiveFocus)
496605b261ecSmrg		return Success;
496705b261ecSmrg	    stuff->eventMask &= ~wDontPropagateMask(pWin);
496805b261ecSmrg	    if (!stuff->eventMask)
496905b261ecSmrg		break;
497005b261ecSmrg	}
497105b261ecSmrg    }
49724642e01fSmrg    else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1))
49734642e01fSmrg        (void)DeliverEventsToWindow(PickPointer(client), pWin, &stuff->event,
49744642e01fSmrg                                    1, stuff->eventMask, NullGrab, 0);
497505b261ecSmrg    return Success;
497605b261ecSmrg}
497705b261ecSmrg
497805b261ecSmrg/**
497905b261ecSmrg * Server-side protocol handling for UngrabKey request.
498005b261ecSmrg *
49814642e01fSmrg * Deletes a passive grab for the given key. Works on the
49824642e01fSmrg * client's keyboard.
498305b261ecSmrg */
498405b261ecSmrgint
498505b261ecSmrgProcUngrabKey(ClientPtr client)
498605b261ecSmrg{
498705b261ecSmrg    REQUEST(xUngrabKeyReq);
498805b261ecSmrg    WindowPtr pWin;
498905b261ecSmrg    GrabRec tempGrab;
49904642e01fSmrg    DeviceIntPtr keybd = PickKeyboard(client);
499105b261ecSmrg    int rc;
499205b261ecSmrg
499305b261ecSmrg    REQUEST_SIZE_MATCH(xUngrabKeyReq);
499405b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
499505b261ecSmrg    if (rc != Success)
499605b261ecSmrg	return rc;
499705b261ecSmrg
499805b261ecSmrg    if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) ||
499905b261ecSmrg	 (stuff->key < keybd->key->curKeySyms.minKeyCode))
500005b261ecSmrg	&& (stuff->key != AnyKey))
500105b261ecSmrg    {
500205b261ecSmrg	client->errorValue = stuff->key;
500305b261ecSmrg        return BadValue;
500405b261ecSmrg    }
500505b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
500605b261ecSmrg	(stuff->modifiers & ~AllModifiersMask))
500705b261ecSmrg    {
500805b261ecSmrg	client->errorValue = stuff->modifiers;
500905b261ecSmrg	return BadValue;
501005b261ecSmrg    }
501105b261ecSmrg    tempGrab.resource = client->clientAsMask;
501205b261ecSmrg    tempGrab.device = keybd;
501305b261ecSmrg    tempGrab.window = pWin;
501405b261ecSmrg    tempGrab.modifiersDetail.exact = stuff->modifiers;
501505b261ecSmrg    tempGrab.modifiersDetail.pMask = NULL;
501605b261ecSmrg    tempGrab.modifierDevice = inputInfo.keyboard;
501705b261ecSmrg    tempGrab.type = KeyPress;
501805b261ecSmrg    tempGrab.detail.exact = stuff->key;
501905b261ecSmrg    tempGrab.detail.pMask = NULL;
50204642e01fSmrg    tempGrab.next = NULL;
502105b261ecSmrg
502205b261ecSmrg    if (!DeletePassiveGrabFromList(&tempGrab))
502305b261ecSmrg	return(BadAlloc);
502405b261ecSmrg    return(Success);
502505b261ecSmrg}
502605b261ecSmrg
502705b261ecSmrg/**
502805b261ecSmrg * Server-side protocol handling for GrabKey request.
502905b261ecSmrg *
50304642e01fSmrg * Creates a grab for the client's keyboard and adds it to the list of passive
50314642e01fSmrg * grabs.
503205b261ecSmrg */
503305b261ecSmrgint
503405b261ecSmrgProcGrabKey(ClientPtr client)
503505b261ecSmrg{
503605b261ecSmrg    WindowPtr pWin;
503705b261ecSmrg    REQUEST(xGrabKeyReq);
503805b261ecSmrg    GrabPtr grab;
50394642e01fSmrg    DeviceIntPtr keybd = PickKeyboard(client);
504005b261ecSmrg    int rc;
504105b261ecSmrg
504205b261ecSmrg    REQUEST_SIZE_MATCH(xGrabKeyReq);
504305b261ecSmrg    if ((stuff->ownerEvents != xTrue) && (stuff->ownerEvents != xFalse))
504405b261ecSmrg    {
504505b261ecSmrg	client->errorValue = stuff->ownerEvents;
504605b261ecSmrg	return(BadValue);
504705b261ecSmrg    }
504805b261ecSmrg    if ((stuff->pointerMode != GrabModeSync) &&
504905b261ecSmrg	(stuff->pointerMode != GrabModeAsync))
505005b261ecSmrg    {
505105b261ecSmrg	client->errorValue = stuff->pointerMode;
505205b261ecSmrg        return BadValue;
505305b261ecSmrg    }
505405b261ecSmrg    if ((stuff->keyboardMode != GrabModeSync) &&
505505b261ecSmrg	(stuff->keyboardMode != GrabModeAsync))
505605b261ecSmrg    {
505705b261ecSmrg	client->errorValue = stuff->keyboardMode;
505805b261ecSmrg        return BadValue;
505905b261ecSmrg    }
506005b261ecSmrg    if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) ||
506105b261ecSmrg	 (stuff->key < keybd->key->curKeySyms.minKeyCode))
506205b261ecSmrg	&& (stuff->key != AnyKey))
506305b261ecSmrg    {
506405b261ecSmrg	client->errorValue = stuff->key;
506505b261ecSmrg        return BadValue;
506605b261ecSmrg    }
506705b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
506805b261ecSmrg	(stuff->modifiers & ~AllModifiersMask))
506905b261ecSmrg    {
507005b261ecSmrg	client->errorValue = stuff->modifiers;
507105b261ecSmrg	return BadValue;
507205b261ecSmrg    }
50734642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
507405b261ecSmrg    if (rc != Success)
507505b261ecSmrg	return rc;
507605b261ecSmrg
50774642e01fSmrg    grab = CreateGrab(client->index, keybd, pWin,
507805b261ecSmrg	(Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents,
507905b261ecSmrg	(Bool)stuff->keyboardMode, (Bool)stuff->pointerMode,
50804642e01fSmrg	keybd, stuff->modifiers, KeyPress, stuff->key,
508105b261ecSmrg	NullWindow, NullCursor);
508205b261ecSmrg    if (!grab)
508305b261ecSmrg	return BadAlloc;
50844642e01fSmrg    return AddPassiveGrabToList(client, grab);
508505b261ecSmrg}
508605b261ecSmrg
508705b261ecSmrg
508805b261ecSmrg/**
508905b261ecSmrg * Server-side protocol handling for GrabButton request.
509005b261ecSmrg *
50914642e01fSmrg * Creates a grab for the client's ClientPointer and adds it as a passive grab
50924642e01fSmrg * to the list.
509305b261ecSmrg */
509405b261ecSmrgint
509505b261ecSmrgProcGrabButton(ClientPtr client)
509605b261ecSmrg{
509705b261ecSmrg    WindowPtr pWin, confineTo;
509805b261ecSmrg    REQUEST(xGrabButtonReq);
509905b261ecSmrg    CursorPtr cursor;
510005b261ecSmrg    GrabPtr grab;
51014642e01fSmrg    DeviceIntPtr ptr, modifierDevice;
51024642e01fSmrg    Mask access_mode = DixGrabAccess;
510305b261ecSmrg    int rc;
510405b261ecSmrg
510505b261ecSmrg    REQUEST_SIZE_MATCH(xGrabButtonReq);
510605b261ecSmrg    if ((stuff->pointerMode != GrabModeSync) &&
510705b261ecSmrg	(stuff->pointerMode != GrabModeAsync))
510805b261ecSmrg    {
510905b261ecSmrg	client->errorValue = stuff->pointerMode;
511005b261ecSmrg        return BadValue;
511105b261ecSmrg    }
511205b261ecSmrg    if ((stuff->keyboardMode != GrabModeSync) &&
511305b261ecSmrg	(stuff->keyboardMode != GrabModeAsync))
511405b261ecSmrg    {
511505b261ecSmrg	client->errorValue = stuff->keyboardMode;
511605b261ecSmrg        return BadValue;
511705b261ecSmrg    }
511805b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
511905b261ecSmrg	(stuff->modifiers & ~AllModifiersMask))
512005b261ecSmrg    {
512105b261ecSmrg	client->errorValue = stuff->modifiers;
512205b261ecSmrg	return BadValue;
512305b261ecSmrg    }
512405b261ecSmrg    if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
512505b261ecSmrg    {
512605b261ecSmrg	client->errorValue = stuff->ownerEvents;
512705b261ecSmrg	return BadValue;
512805b261ecSmrg    }
512905b261ecSmrg    if (stuff->eventMask & ~PointerGrabMask)
513005b261ecSmrg    {
513105b261ecSmrg	client->errorValue = stuff->eventMask;
513205b261ecSmrg        return BadValue;
513305b261ecSmrg    }
51344642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
513505b261ecSmrg    if (rc != Success)
513605b261ecSmrg	return rc;
513705b261ecSmrg    if (stuff->confineTo == None)
513805b261ecSmrg       confineTo = NullWindow;
513905b261ecSmrg    else {
514005b261ecSmrg	rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
51414642e01fSmrg			     DixSetAttrAccess);
514205b261ecSmrg	if (rc != Success)
514305b261ecSmrg	    return rc;
514405b261ecSmrg    }
514505b261ecSmrg    if (stuff->cursor == None)
514605b261ecSmrg	cursor = NullCursor;
514705b261ecSmrg    else
514805b261ecSmrg    {
51494642e01fSmrg	rc = dixLookupResource((pointer *)&cursor, stuff->cursor, RT_CURSOR,
51504642e01fSmrg			       client, DixUseAccess);
51514642e01fSmrg	if (rc != Success)
515205b261ecSmrg	if (!cursor)
515305b261ecSmrg	{
515405b261ecSmrg	    client->errorValue = stuff->cursor;
51554642e01fSmrg	    return (rc == BadValue) ? BadCursor : rc;
515605b261ecSmrg	}
51574642e01fSmrg	access_mode |= DixForceAccess;
515805b261ecSmrg    }
515905b261ecSmrg
51604642e01fSmrg    ptr = PickPointer(client);
51614642e01fSmrg    modifierDevice = GetPairedDevice(ptr);
51624642e01fSmrg    if (stuff->pointerMode == GrabModeSync ||
51634642e01fSmrg	stuff->keyboardMode == GrabModeSync)
51644642e01fSmrg	access_mode |= DixFreezeAccess;
51654642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode);
51664642e01fSmrg    if (rc != Success)
51674642e01fSmrg	return rc;
516805b261ecSmrg
51694642e01fSmrg    grab = CreateGrab(client->index, ptr, pWin,
517005b261ecSmrg        (Mask)stuff->eventMask, (Bool)stuff->ownerEvents,
517105b261ecSmrg        (Bool) stuff->keyboardMode, (Bool)stuff->pointerMode,
51724642e01fSmrg        modifierDevice, stuff->modifiers, ButtonPress,
517305b261ecSmrg        stuff->button, confineTo, cursor);
517405b261ecSmrg    if (!grab)
517505b261ecSmrg	return BadAlloc;
51764642e01fSmrg    return AddPassiveGrabToList(client, grab);
517705b261ecSmrg}
517805b261ecSmrg
517905b261ecSmrg/**
518005b261ecSmrg * Server-side protocol handling for UngrabButton request.
518105b261ecSmrg *
51824642e01fSmrg * Deletes a passive grab on the client's ClientPointer from the list.
518305b261ecSmrg */
518405b261ecSmrgint
518505b261ecSmrgProcUngrabButton(ClientPtr client)
518605b261ecSmrg{
518705b261ecSmrg    REQUEST(xUngrabButtonReq);
518805b261ecSmrg    WindowPtr pWin;
518905b261ecSmrg    GrabRec tempGrab;
519005b261ecSmrg    int rc;
519105b261ecSmrg
519205b261ecSmrg    REQUEST_SIZE_MATCH(xUngrabButtonReq);
519305b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
519405b261ecSmrg	(stuff->modifiers & ~AllModifiersMask))
519505b261ecSmrg    {
519605b261ecSmrg	client->errorValue = stuff->modifiers;
519705b261ecSmrg	return BadValue;
519805b261ecSmrg    }
519905b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
520005b261ecSmrg    if (rc != Success)
520105b261ecSmrg	return rc;
520205b261ecSmrg    tempGrab.resource = client->clientAsMask;
52034642e01fSmrg    tempGrab.device = PickPointer(client);
520405b261ecSmrg    tempGrab.window = pWin;
520505b261ecSmrg    tempGrab.modifiersDetail.exact = stuff->modifiers;
520605b261ecSmrg    tempGrab.modifiersDetail.pMask = NULL;
520705b261ecSmrg    tempGrab.modifierDevice = inputInfo.keyboard;
520805b261ecSmrg    tempGrab.type = ButtonPress;
520905b261ecSmrg    tempGrab.detail.exact = stuff->button;
521005b261ecSmrg    tempGrab.detail.pMask = NULL;
52114642e01fSmrg    tempGrab.next = NULL;
521205b261ecSmrg
521305b261ecSmrg    if (!DeletePassiveGrabFromList(&tempGrab))
521405b261ecSmrg	return(BadAlloc);
521505b261ecSmrg    return(Success);
521605b261ecSmrg}
521705b261ecSmrg
521805b261ecSmrg/**
521905b261ecSmrg * Deactivate any grab that may be on the window, remove the focus.
522005b261ecSmrg * Delete any XInput extension events from the window too. Does not change the
522105b261ecSmrg * window mask. Use just before the window is deleted.
522205b261ecSmrg *
522305b261ecSmrg * If freeResources is set, passive grabs on the window are deleted.
522405b261ecSmrg *
522505b261ecSmrg * @param pWin The window to delete events from.
522605b261ecSmrg * @param freeResources True if resources associated with the window should be
522705b261ecSmrg * deleted.
522805b261ecSmrg */
522905b261ecSmrgvoid
523005b261ecSmrgDeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
523105b261ecSmrg{
523205b261ecSmrg    WindowPtr		parent;
523305b261ecSmrg    DeviceIntPtr	mouse = inputInfo.pointer;
523405b261ecSmrg    DeviceIntPtr	keybd = inputInfo.keyboard;
52354642e01fSmrg    FocusClassPtr	focus;
523605b261ecSmrg    OtherClientsPtr	oc;
523705b261ecSmrg    GrabPtr		passive;
52384642e01fSmrg    GrabPtr             grab;
523905b261ecSmrg
524005b261ecSmrg
524105b261ecSmrg    /* Deactivate any grabs performed on this window, before making any
524205b261ecSmrg	input focus changes. */
52434642e01fSmrg    grab = mouse->deviceGrab.grab;
52444642e01fSmrg    if (grab &&
52454642e01fSmrg	((grab->window == pWin) || (grab->confineTo == pWin)))
52464642e01fSmrg	(*mouse->deviceGrab.DeactivateGrab)(mouse);
524705b261ecSmrg
524805b261ecSmrg
524905b261ecSmrg    /* Deactivating a keyboard grab should cause focus events. */
52504642e01fSmrg    grab = keybd->deviceGrab.grab;
52514642e01fSmrg    if (grab && (grab->window == pWin))
52524642e01fSmrg	(*keybd->deviceGrab.DeactivateGrab)(keybd);
525305b261ecSmrg
52544642e01fSmrg    /* And now the real devices */
52554642e01fSmrg    for (mouse = inputInfo.devices; mouse; mouse = mouse->next)
525605b261ecSmrg    {
52574642e01fSmrg        grab = mouse->deviceGrab.grab;
52584642e01fSmrg        if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
52594642e01fSmrg            (*mouse->deviceGrab.DeactivateGrab)(mouse);
52604642e01fSmrg    }
526105b261ecSmrg
526205b261ecSmrg
52634642e01fSmrg    for (keybd = inputInfo.devices; keybd; keybd = keybd->next)
52644642e01fSmrg    {
52654642e01fSmrg        if (IsKeyboardDevice(keybd))
52664642e01fSmrg        {
52674642e01fSmrg            focus = keybd->focus;
52684642e01fSmrg
52694642e01fSmrg            /* If the focus window is a root window (ie. has no parent) then don't
52704642e01fSmrg               delete the focus from it. */
52714642e01fSmrg
52724642e01fSmrg            if ((pWin == focus->win) && (pWin->parent != NullWindow))
52734642e01fSmrg            {
52744642e01fSmrg                int focusEventMode = NotifyNormal;
52754642e01fSmrg
52764642e01fSmrg                /* If a grab is in progress, then alter the mode of focus events. */
52774642e01fSmrg
52784642e01fSmrg                if (keybd->deviceGrab.grab)
52794642e01fSmrg                    focusEventMode = NotifyWhileGrabbed;
52804642e01fSmrg
52814642e01fSmrg                switch (focus->revert)
52824642e01fSmrg                {
52834642e01fSmrg                    case RevertToNone:
52844642e01fSmrg                        DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
52854642e01fSmrg                        focus->win = NoneWin;
52864642e01fSmrg                        focus->traceGood = 0;
52874642e01fSmrg                        break;
52884642e01fSmrg                    case RevertToParent:
52894642e01fSmrg                        parent = pWin;
52904642e01fSmrg                        do
52914642e01fSmrg                        {
52924642e01fSmrg                            parent = parent->parent;
52934642e01fSmrg                            focus->traceGood--;
52944642e01fSmrg                        } while (!parent->realized
52954642e01fSmrg                                /* This would be a good protocol change -- windows being reparented
52964642e01fSmrg                                   during SaveSet processing would cause the focus to revert to the
52974642e01fSmrg                                   nearest enclosing window which will survive the death of the exiting
52984642e01fSmrg                                   client, instead of ending up reverting to a dying window and thence
52994642e01fSmrg                                   to None
53004642e01fSmrg                                 */
530105b261ecSmrg#ifdef NOTDEF
53024642e01fSmrg                                || clients[CLIENT_ID(parent->drawable.id)]->clientGone
530305b261ecSmrg#endif
53044642e01fSmrg                                );
53054642e01fSmrg                        DoFocusEvents(keybd, pWin, parent, focusEventMode);
53064642e01fSmrg                        focus->win = parent;
53074642e01fSmrg                        focus->revert = RevertToNone;
53084642e01fSmrg                        break;
53094642e01fSmrg                    case RevertToPointerRoot:
53104642e01fSmrg                        DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode);
53114642e01fSmrg                        focus->win = PointerRootWin;
53124642e01fSmrg                        focus->traceGood = 0;
53134642e01fSmrg                        break;
53144642e01fSmrg                }
53154642e01fSmrg            }
53164642e01fSmrg        }
531705b261ecSmrg
53184642e01fSmrg        if (IsPointerDevice(keybd))
53194642e01fSmrg        {
53204642e01fSmrg            if (keybd->valuator->motionHintWindow == pWin)
53214642e01fSmrg                keybd->valuator->motionHintWindow = NullWindow;
53224642e01fSmrg        }
53234642e01fSmrg    }
532405b261ecSmrg
532505b261ecSmrg    if (freeResources)
532605b261ecSmrg    {
532705b261ecSmrg	if (pWin->dontPropagate)
532805b261ecSmrg	    DontPropagateRefCnts[pWin->dontPropagate]--;
532905b261ecSmrg	while ( (oc = wOtherClients(pWin)) )
533005b261ecSmrg	    FreeResource(oc->resource, RT_NONE);
533105b261ecSmrg	while ( (passive = wPassiveGrabs(pWin)) )
533205b261ecSmrg	    FreeResource(passive->resource, RT_NONE);
533305b261ecSmrg     }
53344642e01fSmrg
533505b261ecSmrg    DeleteWindowFromAnyExtEvents(pWin, freeResources);
533605b261ecSmrg}
533705b261ecSmrg
533805b261ecSmrg/**
533905b261ecSmrg * Call this whenever some window at or below pWin has changed geometry. If
534005b261ecSmrg * there is a grab on the window, the cursor will be re-confined into the
534105b261ecSmrg * window.
534205b261ecSmrg */
534305b261ecSmrg_X_EXPORT void
534405b261ecSmrgCheckCursorConfinement(WindowPtr pWin)
534505b261ecSmrg{
53464642e01fSmrg    GrabPtr grab;
534705b261ecSmrg    WindowPtr confineTo;
53484642e01fSmrg    DeviceIntPtr pDev;
534905b261ecSmrg
535005b261ecSmrg#ifdef PANORAMIX
535105b261ecSmrg    if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return;
535205b261ecSmrg#endif
535305b261ecSmrg
53544642e01fSmrg    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
535505b261ecSmrg    {
53564642e01fSmrg        if (DevHasCursor(pDev))
53574642e01fSmrg        {
53584642e01fSmrg            grab = pDev->deviceGrab.grab;
53594642e01fSmrg            if (grab && (confineTo = grab->confineTo))
53604642e01fSmrg            {
53614642e01fSmrg                if (!BorderSizeNotEmpty(pDev, confineTo))
53624642e01fSmrg                    (*inputInfo.pointer->deviceGrab.DeactivateGrab)(pDev);
53634642e01fSmrg                else if ((pWin == confineTo) || IsParent(pWin, confineTo))
53644642e01fSmrg                    ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
53654642e01fSmrg            }
53664642e01fSmrg        }
536705b261ecSmrg    }
536805b261ecSmrg}
536905b261ecSmrg
537005b261ecSmrgMask
537105b261ecSmrgEventMaskForClient(WindowPtr pWin, ClientPtr client)
537205b261ecSmrg{
537305b261ecSmrg    OtherClientsPtr	other;
537405b261ecSmrg
537505b261ecSmrg    if (wClient (pWin) == client)
537605b261ecSmrg	return pWin->eventMask;
537705b261ecSmrg    for (other = wOtherClients(pWin); other; other = other->next)
537805b261ecSmrg    {
537905b261ecSmrg	if (SameClient(other, client))
538005b261ecSmrg	    return other->mask;
538105b261ecSmrg    }
538205b261ecSmrg    return 0;
538305b261ecSmrg}
538405b261ecSmrg
538505b261ecSmrg/**
538605b261ecSmrg * Server-side protocol handling for RecolorCursor request.
538705b261ecSmrg */
538805b261ecSmrgint
538905b261ecSmrgProcRecolorCursor(ClientPtr client)
539005b261ecSmrg{
539105b261ecSmrg    CursorPtr pCursor;
53924642e01fSmrg    int		rc, nscr;
539305b261ecSmrg    ScreenPtr	pscr;
53944642e01fSmrg    Bool	displayed;
53954642e01fSmrg    SpritePtr   pSprite = PickPointer(client)->spriteInfo->sprite;
539605b261ecSmrg    REQUEST(xRecolorCursorReq);
539705b261ecSmrg
539805b261ecSmrg    REQUEST_SIZE_MATCH(xRecolorCursorReq);
53994642e01fSmrg    rc = dixLookupResource((pointer *)&pCursor, stuff->cursor, RT_CURSOR,
54004642e01fSmrg			   client, DixWriteAccess);
54014642e01fSmrg    if (rc != Success)
540205b261ecSmrg    {
540305b261ecSmrg	client->errorValue = stuff->cursor;
54044642e01fSmrg	return (rc == BadValue) ? BadCursor : rc;
540505b261ecSmrg    }
540605b261ecSmrg
540705b261ecSmrg    pCursor->foreRed = stuff->foreRed;
540805b261ecSmrg    pCursor->foreGreen = stuff->foreGreen;
540905b261ecSmrg    pCursor->foreBlue = stuff->foreBlue;
541005b261ecSmrg
541105b261ecSmrg    pCursor->backRed = stuff->backRed;
541205b261ecSmrg    pCursor->backGreen = stuff->backGreen;
541305b261ecSmrg    pCursor->backBlue = stuff->backBlue;
541405b261ecSmrg
541505b261ecSmrg    for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
541605b261ecSmrg    {
541705b261ecSmrg	pscr = screenInfo.screens[nscr];
541805b261ecSmrg#ifdef PANORAMIX
541905b261ecSmrg	if(!noPanoramiXExtension)
54204642e01fSmrg	    displayed = (pscr == pSprite->screen);
542105b261ecSmrg	else
542205b261ecSmrg#endif
54234642e01fSmrg	    displayed = (pscr == pSprite->hotPhys.pScreen);
54244642e01fSmrg	( *pscr->RecolorCursor)(PickPointer(client), pscr, pCursor,
54254642e01fSmrg				(pCursor == pSprite->current) && displayed);
542605b261ecSmrg    }
542705b261ecSmrg    return (Success);
542805b261ecSmrg}
542905b261ecSmrg
543005b261ecSmrg/**
543105b261ecSmrg * Write the given events to a client, swapping the byte order if necessary.
543205b261ecSmrg * To swap the byte ordering, a callback is called that has to be set up for
543305b261ecSmrg * the given event type.
543405b261ecSmrg *
543505b261ecSmrg * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
54364642e01fSmrg * can be more than one. Usually it's just one event.
543705b261ecSmrg *
543805b261ecSmrg * Do not modify the event structure passed in. See comment below.
54394642e01fSmrg *
544005b261ecSmrg * @param pClient Client to send events to.
544105b261ecSmrg * @param count Number of events.
544205b261ecSmrg * @param events The event list.
544305b261ecSmrg */
544405b261ecSmrg_X_EXPORT void
544505b261ecSmrgWriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
544605b261ecSmrg{
544705b261ecSmrg#ifdef PANORAMIX
544805b261ecSmrg    xEvent    eventCopy;
544905b261ecSmrg#endif
54504642e01fSmrg    xEvent    *eventTo, *eventFrom;
54514642e01fSmrg    int       i,
54524642e01fSmrg              eventlength = sizeof(xEvent);
545305b261ecSmrg
545405b261ecSmrg#ifdef XKB
545505b261ecSmrg    if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events)))
545605b261ecSmrg	return;
545705b261ecSmrg#endif
545805b261ecSmrg
545905b261ecSmrg#ifdef PANORAMIX
54604642e01fSmrg    if(!noPanoramiXExtension &&
54614642e01fSmrg       (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y))
546205b261ecSmrg    {
546305b261ecSmrg	switch(events->u.u.type) {
546405b261ecSmrg	case MotionNotify:
546505b261ecSmrg	case ButtonPress:
546605b261ecSmrg	case ButtonRelease:
546705b261ecSmrg	case KeyPress:
546805b261ecSmrg	case KeyRelease:
546905b261ecSmrg	case EnterNotify:
547005b261ecSmrg	case LeaveNotify:
54714642e01fSmrg	/*
547205b261ecSmrg	   When multiple clients want the same event DeliverEventsToWindow
54734642e01fSmrg	   passes the same event structure multiple times so we can't
54744642e01fSmrg	   modify the one passed to us
547505b261ecSmrg        */
547605b261ecSmrg	    count = 1;  /* should always be 1 */
547705b261ecSmrg	    memcpy(&eventCopy, events, sizeof(xEvent));
547805b261ecSmrg	    eventCopy.u.keyButtonPointer.rootX += panoramiXdataPtr[0].x;
547905b261ecSmrg	    eventCopy.u.keyButtonPointer.rootY += panoramiXdataPtr[0].y;
54804642e01fSmrg	    if(eventCopy.u.keyButtonPointer.event ==
54814642e01fSmrg	       eventCopy.u.keyButtonPointer.root)
548205b261ecSmrg	    {
548305b261ecSmrg		eventCopy.u.keyButtonPointer.eventX += panoramiXdataPtr[0].x;
548405b261ecSmrg		eventCopy.u.keyButtonPointer.eventY += panoramiXdataPtr[0].y;
548505b261ecSmrg	    }
548605b261ecSmrg	    events = &eventCopy;
548705b261ecSmrg	    break;
548805b261ecSmrg	default: break;
548905b261ecSmrg	}
549005b261ecSmrg    }
549105b261ecSmrg#endif
549205b261ecSmrg
549305b261ecSmrg    if (EventCallback)
549405b261ecSmrg    {
549505b261ecSmrg	EventInfoRec eventinfo;
549605b261ecSmrg	eventinfo.client = pClient;
549705b261ecSmrg	eventinfo.events = events;
549805b261ecSmrg	eventinfo.count = count;
549905b261ecSmrg	CallCallbacks(&EventCallback, (pointer)&eventinfo);
550005b261ecSmrg    }
550105b261ecSmrg#ifdef XSERVER_DTRACE
550205b261ecSmrg    if (XSERVER_SEND_EVENT_ENABLED()) {
550305b261ecSmrg	for (i = 0; i < count; i++)
550405b261ecSmrg	{
550505b261ecSmrg	    XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]);
550605b261ecSmrg	}
550705b261ecSmrg    }
55084642e01fSmrg#endif
55094642e01fSmrg    /* Just a safety check to make sure we only have one GenericEvent, it just
55104642e01fSmrg     * makes things easier for me right now. (whot) */
55114642e01fSmrg    for (i = 1; i < count; i++)
55124642e01fSmrg    {
55134642e01fSmrg        if (events[i].u.u.type == GenericEvent)
55144642e01fSmrg        {
55154642e01fSmrg            ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n");
55164642e01fSmrg            return;
55174642e01fSmrg        }
55184642e01fSmrg    }
55194642e01fSmrg
55204642e01fSmrg    if (events->u.u.type == GenericEvent)
55214642e01fSmrg    {
55224642e01fSmrg        eventlength += ((xGenericEvent*)events)->length * 4;
55234642e01fSmrg    }
55244642e01fSmrg
552505b261ecSmrg    if(pClient->swapped)
552605b261ecSmrg    {
55274642e01fSmrg        if (eventlength > swapEventLen)
55284642e01fSmrg        {
55294642e01fSmrg            swapEventLen = eventlength;
55304642e01fSmrg            swapEvent = Xrealloc(swapEvent, swapEventLen);
55314642e01fSmrg            if (!swapEvent)
55324642e01fSmrg            {
55334642e01fSmrg                FatalError("WriteEventsToClient: Out of memory.\n");
55344642e01fSmrg                return;
55354642e01fSmrg            }
55364642e01fSmrg        }
55374642e01fSmrg
553805b261ecSmrg	for(i = 0; i < count; i++)
553905b261ecSmrg	{
554005b261ecSmrg	    eventFrom = &events[i];
55414642e01fSmrg            eventTo = swapEvent;
55424642e01fSmrg
554305b261ecSmrg	    /* Remember to strip off the leading bit of type in case
554405b261ecSmrg	       this event was sent with "SendEvent." */
554505b261ecSmrg	    (*EventSwapVector[eventFrom->u.u.type & 0177])
55464642e01fSmrg		(eventFrom, eventTo);
55474642e01fSmrg
55484642e01fSmrg	    (void)WriteToClient(pClient, eventlength, (char *)eventTo);
554905b261ecSmrg	}
555005b261ecSmrg    }
555105b261ecSmrg    else
555205b261ecSmrg    {
55534642e01fSmrg        /* only one GenericEvent, remember? that means either count is 1 and
55544642e01fSmrg         * eventlength is arbitrary or eventlength is 32 and count doesn't
55554642e01fSmrg         * matter. And we're all set. Woohoo. */
55564642e01fSmrg	(void)WriteToClient(pClient, count * eventlength, (char *) events);
555705b261ecSmrg    }
555805b261ecSmrg}
55594642e01fSmrg
55604642e01fSmrg/*
55614642e01fSmrg * Set the client pointer for the given client. Second parameter setter could
55624642e01fSmrg * be used in the future to determine access rights. Unused for now.
55634642e01fSmrg *
55644642e01fSmrg * A client can have exactly one ClientPointer. Each time a
55654642e01fSmrg * request/reply/event is processed and the choice of devices is ambiguous
55664642e01fSmrg * (e.g. QueryPointer request), the server will pick the ClientPointer (see
55674642e01fSmrg * PickPointer()).
55684642e01fSmrg * If a keyboard is needed, the first keyboard paired with the CP is used.
55694642e01fSmrg */
55704642e01fSmrg_X_EXPORT Bool
55714642e01fSmrgSetClientPointer(ClientPtr client, ClientPtr setter, DeviceIntPtr device)
55724642e01fSmrg{
55734642e01fSmrg    if (!device->isMaster)
55744642e01fSmrg    {
55754642e01fSmrg        ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n");
55764642e01fSmrg        return FALSE;
55774642e01fSmrg    } else if (!device->spriteInfo->spriteOwner)
55784642e01fSmrg    {
55794642e01fSmrg        ErrorF("[dix] Device %d does not have a sprite. "
55804642e01fSmrg                "Cannot be ClientPointer\n", device->id);
55814642e01fSmrg        return FALSE;
55824642e01fSmrg    }
55834642e01fSmrg    client->clientPtr = device;
55844642e01fSmrg    return TRUE;
55854642e01fSmrg}
55864642e01fSmrg
55874642e01fSmrg/* PickPointer will pick an appropriate pointer for the given client.
55884642e01fSmrg *
55894642e01fSmrg * An "appropriate device" is (in order of priority):
55904642e01fSmrg *  1) A device the given client has a core grab on.
55914642e01fSmrg *  2) A device set as ClientPointer for the given client.
55924642e01fSmrg *  3) The first master device.
55934642e01fSmrg */
55944642e01fSmrg_X_EXPORT DeviceIntPtr
55954642e01fSmrgPickPointer(ClientPtr client)
55964642e01fSmrg{
55974642e01fSmrg    DeviceIntPtr it = inputInfo.devices;
55984642e01fSmrg
55994642e01fSmrg    /* First, check if the client currently has a grab on a device. Even
56004642e01fSmrg     * keyboards count. */
56014642e01fSmrg    for(it = inputInfo.devices; it; it = it->next)
56024642e01fSmrg    {
56034642e01fSmrg        GrabPtr grab = it->deviceGrab.grab;
56044642e01fSmrg        if (grab && grab->coreGrab && SameClient(grab, client))
56054642e01fSmrg        {
56064642e01fSmrg            if (!IsPointerDevice(it))
56074642e01fSmrg                it = GetPairedDevice(it);
56084642e01fSmrg            return it; /* Always return a core grabbed device */
56094642e01fSmrg        }
56104642e01fSmrg    }
56114642e01fSmrg
56124642e01fSmrg    if (!client->clientPtr)
56134642e01fSmrg    {
56144642e01fSmrg        DeviceIntPtr it = inputInfo.devices;
56154642e01fSmrg        while (it)
56164642e01fSmrg        {
56174642e01fSmrg            if (it->isMaster && it->spriteInfo->spriteOwner)
56184642e01fSmrg            {
56194642e01fSmrg                client->clientPtr = it;
56204642e01fSmrg                break;
56214642e01fSmrg            }
56224642e01fSmrg            it = it->next;
56234642e01fSmrg        }
56244642e01fSmrg    }
56254642e01fSmrg    return client->clientPtr;
56264642e01fSmrg}
56274642e01fSmrg
56284642e01fSmrg/* PickKeyboard will pick an appropriate keyboard for the given client by
56294642e01fSmrg * searching the list of devices for the keyboard device that is paired with
56304642e01fSmrg * the client's pointer.
56314642e01fSmrg */
56324642e01fSmrg_X_EXPORT DeviceIntPtr
56334642e01fSmrgPickKeyboard(ClientPtr client)
56344642e01fSmrg{
56354642e01fSmrg    DeviceIntPtr ptr = PickPointer(client);
56364642e01fSmrg    DeviceIntPtr kbd = ptr->spriteInfo->paired;
56374642e01fSmrg
56384642e01fSmrg    if (!kbd)
56394642e01fSmrg    {
56404642e01fSmrg        ErrorF("[dix] ClientPointer not paired with a keyboard. This "
56414642e01fSmrg                "is a bug.\n");
56424642e01fSmrg    }
56434642e01fSmrg
56444642e01fSmrg    return kbd;
56454642e01fSmrg}
56464642e01fSmrg
56474642e01fSmrg/* A client that has one or more core grabs does not get core events from
56484642e01fSmrg * devices it does not have a grab on. Legacy applications behave bad
56494642e01fSmrg * otherwise because they are not used to it and the events interfere.
56504642e01fSmrg * Only applies for core events.
56514642e01fSmrg *
56524642e01fSmrg * Return true if a core event from the device would interfere and should not
56534642e01fSmrg * be delivered.
56544642e01fSmrg */
56554642e01fSmrgBool
56564642e01fSmrgIsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event)
56574642e01fSmrg{
56584642e01fSmrg    DeviceIntPtr it = inputInfo.devices;
56594642e01fSmrg
56604642e01fSmrg    if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
56614642e01fSmrg        return FALSE;
56624642e01fSmrg
56634642e01fSmrg    switch(event->u.u.type)
56644642e01fSmrg    {
56654642e01fSmrg        case KeyPress:
56664642e01fSmrg        case KeyRelease:
56674642e01fSmrg        case ButtonPress:
56684642e01fSmrg        case ButtonRelease:
56694642e01fSmrg        case MotionNotify:
56704642e01fSmrg        case EnterNotify:
56714642e01fSmrg        case LeaveNotify:
56724642e01fSmrg            break;
56734642e01fSmrg        default:
56744642e01fSmrg            return FALSE;
56754642e01fSmrg    }
56764642e01fSmrg
56774642e01fSmrg    while(it)
56784642e01fSmrg    {
56794642e01fSmrg        if (it != dev)
56804642e01fSmrg        {
56814642e01fSmrg            if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client)
56824642e01fSmrg                        && !it->deviceGrab.fromPassiveGrab)
56834642e01fSmrg            {
56844642e01fSmrg                if ((IsPointerDevice(it) && IsPointerDevice(dev)) ||
56854642e01fSmrg                        (IsKeyboardDevice(it) && IsKeyboardDevice(dev)))
56864642e01fSmrg                    return TRUE;
56874642e01fSmrg            }
56884642e01fSmrg        }
56894642e01fSmrg        it = it->next;
56904642e01fSmrg    }
56914642e01fSmrg
56924642e01fSmrg    return FALSE;
56934642e01fSmrg}
56944642e01fSmrg
56954642e01fSmrg/**
56964642e01fSmrg * Set the filters for a extension.
56974642e01fSmrg * The filters array needs to contain the Masks that are applicable for each
56984642e01fSmrg * event type for the given extension.
56994642e01fSmrg * e.g. if generic event type 2 should be let through for windows with
57004642e01fSmrg * MyExampleMask set, make sure that filters[2] == MyExampleMask.
57014642e01fSmrg */
57024642e01fSmrg_X_EXPORT void
57034642e01fSmrgSetGenericFilter(int extension, Mask* filters)
57044642e01fSmrg{
57054642e01fSmrg    generic_filters[extension & 0x7f] = filters;
57064642e01fSmrg}
57074642e01fSmrg
57084642e01fSmrg
57094642e01fSmrg/**
57104642e01fSmrg * Grab a device for XI events and XGE events.
57114642e01fSmrg * grabmode is used to ungrab a device.
57124642e01fSmrg */
57134642e01fSmrg_X_EXPORT int
57144642e01fSmrgExtGrabDevice(ClientPtr client,
57154642e01fSmrg              DeviceIntPtr dev,
57164642e01fSmrg              int device_mode,
57174642e01fSmrg              WindowPtr grabWindow,
57184642e01fSmrg              WindowPtr confineTo,
57194642e01fSmrg              TimeStamp ctime,
57204642e01fSmrg              Bool ownerEvents,
57214642e01fSmrg              CursorPtr cursor,
57224642e01fSmrg              Mask xi_mask,
57234642e01fSmrg              GenericMaskPtr ge_masks)
57244642e01fSmrg{
57254642e01fSmrg    GrabInfoPtr grabinfo;
57264642e01fSmrg    GrabRec     newGrab;
57274642e01fSmrg
57284642e01fSmrg    UpdateCurrentTime();
57294642e01fSmrg
57304642e01fSmrg    grabinfo = &dev->deviceGrab;
57314642e01fSmrg
57324642e01fSmrg    if (grabinfo->grab && !SameClient(grabinfo->grab, client))
57334642e01fSmrg        return AlreadyGrabbed;
57344642e01fSmrg
57354642e01fSmrg    if (!grabWindow->realized)
57364642e01fSmrg        return GrabNotViewable;
57374642e01fSmrg
57384642e01fSmrg    if ((CompareTimeStamps(ctime, currentTime) == LATER) ||
57394642e01fSmrg            (CompareTimeStamps(ctime, grabinfo->grabTime) == EARLIER))
57404642e01fSmrg        return GrabInvalidTime;
57414642e01fSmrg
57424642e01fSmrg    if (grabinfo->sync.frozen && grabinfo->sync.other &&
57434642e01fSmrg            !SameClient(grabinfo->sync.other, client))
57444642e01fSmrg        return GrabFrozen;
57454642e01fSmrg
57464642e01fSmrg    memset(&newGrab, 0, sizeof(GrabRec));
57474642e01fSmrg    newGrab.window         = grabWindow;
57484642e01fSmrg    newGrab.resource       = client->clientAsMask;
57494642e01fSmrg    newGrab.ownerEvents    = ownerEvents;
57504642e01fSmrg    newGrab.device         = dev;
57514642e01fSmrg    newGrab.cursor         = cursor;
57524642e01fSmrg    newGrab.confineTo      = confineTo;
57534642e01fSmrg    newGrab.eventMask      = xi_mask;
57544642e01fSmrg    newGrab.genericMasks   = NULL;
57554642e01fSmrg    newGrab.next           = NULL;
57564642e01fSmrg
57574642e01fSmrg    if (ge_masks)
57584642e01fSmrg    {
57594642e01fSmrg        newGrab.genericMasks  = xcalloc(1, sizeof(GenericMaskRec));
57604642e01fSmrg        *newGrab.genericMasks = *ge_masks;
57614642e01fSmrg        newGrab.genericMasks->next = NULL;
57624642e01fSmrg    }
57634642e01fSmrg
57644642e01fSmrg    if (IsPointerDevice(dev))
57654642e01fSmrg    {
57664642e01fSmrg        newGrab.keyboardMode = GrabModeAsync;
57674642e01fSmrg        newGrab.pointerMode  = device_mode;
57684642e01fSmrg    } else
57694642e01fSmrg    {
57704642e01fSmrg        newGrab.keyboardMode = device_mode;
57714642e01fSmrg        newGrab.pointerMode  = GrabModeAsync;
57724642e01fSmrg    }
57734642e01fSmrg
57744642e01fSmrg    (*grabinfo->ActivateGrab)(dev, &newGrab, ctime, FALSE);
57754642e01fSmrg    return GrabSuccess;
57764642e01fSmrg}
57774642e01fSmrg
5778