events.c revision 05b261ec
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
3005b261ecSmrgPermission to use, copy, modify, and distribute this software and its
3105b261ecSmrgdocumentation for any purpose and without fee is hereby granted,
3205b261ecSmrgprovided that the above copyright notice appear in all copies and that
3305b261ecSmrgboth 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
3605b261ecSmrgsoftware 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#ifdef XEVIE
15305b261ecSmrgextern WindowPtr *WindowTable;
15405b261ecSmrgextern int       xevieFlag;
15505b261ecSmrgextern int       xevieClientIndex;
15605b261ecSmrgextern DeviceIntPtr     xeviemouse;
15705b261ecSmrgextern DeviceIntPtr     xeviekb;
15805b261ecSmrgextern Mask      xevieMask;
15905b261ecSmrgextern Mask      xevieFilters[128];
16005b261ecSmrgextern int       xevieEventSent;
16105b261ecSmrgextern int       xevieKBEventSent;
16205b261ecSmrgint    xeviegrabState = 0;
16305b261ecSmrg#endif
16405b261ecSmrg
16505b261ecSmrg#include <X11/extensions/XIproto.h>
16605b261ecSmrg#include "exglobals.h"
16705b261ecSmrg#include "exevents.h"
16805b261ecSmrg#include "exglobals.h"
16905b261ecSmrg#include "extnsionst.h"
17005b261ecSmrg
17105b261ecSmrg#include "dixevents.h"
17205b261ecSmrg#include "dixgrabs.h"
17305b261ecSmrg#include "dispatch.h"
17405b261ecSmrg/**
17505b261ecSmrg * Extension events type numbering starts at EXTENSION_EVENT_BASE.
17605b261ecSmrg */
17705b261ecSmrg#define EXTENSION_EVENT_BASE  64
17805b261ecSmrg
17905b261ecSmrg#define NoSuchEvent 0x80000000	/* so doesn't match NoEventMask */
18005b261ecSmrg#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
18105b261ecSmrg#define AllButtonsMask ( \
18205b261ecSmrg	Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
18305b261ecSmrg#define MotionMask ( \
18405b261ecSmrg	PointerMotionMask | Button1MotionMask | \
18505b261ecSmrg	Button2MotionMask | Button3MotionMask | Button4MotionMask | \
18605b261ecSmrg	Button5MotionMask | ButtonMotionMask )
18705b261ecSmrg#define PropagateMask ( \
18805b261ecSmrg	KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
18905b261ecSmrg	MotionMask )
19005b261ecSmrg#define PointerGrabMask ( \
19105b261ecSmrg	ButtonPressMask | ButtonReleaseMask | \
19205b261ecSmrg	EnterWindowMask | LeaveWindowMask | \
19305b261ecSmrg	PointerMotionHintMask | KeymapStateMask | \
19405b261ecSmrg	MotionMask )
19505b261ecSmrg#define AllModifiersMask ( \
19605b261ecSmrg	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
19705b261ecSmrg	Mod3Mask | Mod4Mask | Mod5Mask )
19805b261ecSmrg#define AllEventMasks (lastEventMask|(lastEventMask-1))
19905b261ecSmrg/*
20005b261ecSmrg * The following relies on the fact that the Button<n>MotionMasks are equal
20105b261ecSmrg * to the corresponding Button<n>Masks from the current modifier/button state.
20205b261ecSmrg */
20305b261ecSmrg#define Motion_Filter(class) (PointerMotionMask | \
20405b261ecSmrg			      (class)->state | (class)->motionMask)
20505b261ecSmrg
20605b261ecSmrg
20705b261ecSmrg#define WID(w) ((w) ? ((w)->drawable.id) : 0)
20805b261ecSmrg
20905b261ecSmrg#define XE_KBPTR (xE->u.keyButtonPointer)
21005b261ecSmrg
21105b261ecSmrg
21205b261ecSmrg#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
21305b261ecSmrg
21405b261ecSmrg_X_EXPORT CallbackListPtr EventCallback;
21505b261ecSmrg_X_EXPORT CallbackListPtr DeviceEventCallback;
21605b261ecSmrg
21705b261ecSmrg#define DNPMCOUNT 8
21805b261ecSmrg
21905b261ecSmrgMask DontPropagateMasks[DNPMCOUNT];
22005b261ecSmrgstatic int DontPropagateRefCnts[DNPMCOUNT];
22105b261ecSmrg
22205b261ecSmrg/**
22305b261ecSmrg * Main input device struct.
22405b261ecSmrg *     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,
22705b261ecSmrg *     but multiple devices may send core events. If a device generates core
22805b261ecSmrg *     events, those events will appear to originate from the core pointer.
22905b261ecSmrg *
23005b261ecSmrg *     inputInfo.keyboard
23105b261ecSmrg *     is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
23205b261ecSmrg *     See inputInfo.pointer.
23305b261ecSmrg *
23405b261ecSmrg *     inputInfo.devices
23505b261ecSmrg *     linked list containing all devices including VCK and VCP. The VCK will
23605b261ecSmrg *     always be the first entry, the VCP the second entry in the device list.
23705b261ecSmrg *
23805b261ecSmrg *     inputInfo.off_devices
23905b261ecSmrg *     Devices that have not been initialized and are thus turned off.
24005b261ecSmrg *
24105b261ecSmrg *     inputInfo.numDevices
24205b261ecSmrg *     Total number of devices.
24305b261ecSmrg */
24405b261ecSmrg_X_EXPORT InputInfo inputInfo;
24505b261ecSmrg
24605b261ecSmrgstatic struct {
24705b261ecSmrg    QdEventPtr		pending, *pendtail;
24805b261ecSmrg    DeviceIntPtr	replayDev;	/* kludgy rock to put flag for */
24905b261ecSmrg    WindowPtr		replayWin;	/*   ComputeFreezes            */
25005b261ecSmrg    Bool		playingEvents;
25105b261ecSmrg    TimeStamp		time;
25205b261ecSmrg} syncEvents;
25305b261ecSmrg
25405b261ecSmrg/*
25505b261ecSmrg * The window trace information is used to avoid having to compute all the
25605b261ecSmrg * windows between the root and the current pointer window each time a button
25705b261ecSmrg * or key goes down. The grabs on each of those windows must be checked.
25805b261ecSmrg *
25905b261ecSmrg * @see XYToWindow() for a documentation on how the array is set up.
26005b261ecSmrg */
26105b261ecSmrgstatic WindowPtr *spriteTrace = (WindowPtr *)NULL;
26205b261ecSmrg#define ROOT spriteTrace[0]
26305b261ecSmrgstatic int spriteTraceSize = 0;
26405b261ecSmrgstatic int spriteTraceGood;
26505b261ecSmrg
26605b261ecSmrg/**
26705b261ecSmrg * DIX sprite information. This is the sprite as seen from the DIX. It does
26805b261ecSmrg * not represent the actual sprite rendered to the screen.
26905b261ecSmrg *
27005b261ecSmrg */
27105b261ecSmrgstatic  struct {
27205b261ecSmrg    CursorPtr	current;
27305b261ecSmrg    BoxRec	hotLimits;	/* logical constraints of hot spot */
27405b261ecSmrg    Bool	confined;	/* confined to screen */
27505b261ecSmrg#if defined(SHAPE) || defined(PANORAMIX)
27605b261ecSmrg    RegionPtr	hotShape;	/* additional logical shape constraint */
27705b261ecSmrg#endif
27805b261ecSmrg    BoxRec	physLimits;	/* physical constraints of hot spot */
27905b261ecSmrg    WindowPtr	win;		/* window of logical position */
28005b261ecSmrg    HotSpot	hot;		/* logical pointer position */
28105b261ecSmrg    HotSpot	hotPhys;	/* physical pointer position */
28205b261ecSmrg#ifdef PANORAMIX
28305b261ecSmrg    ScreenPtr	screen;		/* all others are in Screen 0 coordinates */
28405b261ecSmrg    RegionRec   Reg1;	        /* Region 1 for confining motion */
28505b261ecSmrg    RegionRec   Reg2;		/* Region 2 for confining virtual motion */
28605b261ecSmrg    WindowPtr   windows[MAXSCREENS];
28705b261ecSmrg    WindowPtr	confineWin;	/* confine window */
28805b261ecSmrg#endif
28905b261ecSmrg} sprite;			/* info about the cursor sprite */
29005b261ecSmrg
29105b261ecSmrg#ifdef XEVIE
29205b261ecSmrg_X_EXPORT WindowPtr xeviewin;
29305b261ecSmrg_X_EXPORT HotSpot xeviehot;
29405b261ecSmrg#endif
29505b261ecSmrg
29605b261ecSmrgstatic void DoEnterLeaveEvents(
29705b261ecSmrg    WindowPtr fromWin,
29805b261ecSmrg    WindowPtr toWin,
29905b261ecSmrg    int mode
30005b261ecSmrg);
30105b261ecSmrg
30205b261ecSmrgstatic WindowPtr XYToWindow(
30305b261ecSmrg    int x,
30405b261ecSmrg    int y
30505b261ecSmrg);
30605b261ecSmrg
30705b261ecSmrg/**
30805b261ecSmrg * Max event opcode.
30905b261ecSmrg */
31005b261ecSmrgextern int lastEvent;
31105b261ecSmrg
31205b261ecSmrgstatic Mask lastEventMask;
31305b261ecSmrg
31405b261ecSmrg#ifdef XINPUT
31505b261ecSmrgextern int DeviceMotionNotify;
31605b261ecSmrg#endif
31705b261ecSmrg
31805b261ecSmrg#define CantBeFiltered NoEventMask
31905b261ecSmrgstatic Mask filters[128] =
32005b261ecSmrg{
32105b261ecSmrg	NoSuchEvent,		       /* 0 */
32205b261ecSmrg	NoSuchEvent,		       /* 1 */
32305b261ecSmrg	KeyPressMask,		       /* KeyPress */
32405b261ecSmrg	KeyReleaseMask,		       /* KeyRelease */
32505b261ecSmrg	ButtonPressMask,	       /* ButtonPress */
32605b261ecSmrg	ButtonReleaseMask,	       /* ButtonRelease */
32705b261ecSmrg	PointerMotionMask,	       /* MotionNotify (initial state) */
32805b261ecSmrg	EnterWindowMask,	       /* EnterNotify */
32905b261ecSmrg	LeaveWindowMask,	       /* LeaveNotify */
33005b261ecSmrg	FocusChangeMask,	       /* FocusIn */
33105b261ecSmrg	FocusChangeMask,	       /* FocusOut */
33205b261ecSmrg	KeymapStateMask,	       /* KeymapNotify */
33305b261ecSmrg	ExposureMask,		       /* Expose */
33405b261ecSmrg	CantBeFiltered,		       /* GraphicsExpose */
33505b261ecSmrg	CantBeFiltered,		       /* NoExpose */
33605b261ecSmrg	VisibilityChangeMask,	       /* VisibilityNotify */
33705b261ecSmrg	SubstructureNotifyMask,	       /* CreateNotify */
33805b261ecSmrg	StructureAndSubMask,	       /* DestroyNotify */
33905b261ecSmrg	StructureAndSubMask,	       /* UnmapNotify */
34005b261ecSmrg	StructureAndSubMask,	       /* MapNotify */
34105b261ecSmrg	SubstructureRedirectMask,      /* MapRequest */
34205b261ecSmrg	StructureAndSubMask,	       /* ReparentNotify */
34305b261ecSmrg	StructureAndSubMask,	       /* ConfigureNotify */
34405b261ecSmrg	SubstructureRedirectMask,      /* ConfigureRequest */
34505b261ecSmrg	StructureAndSubMask,	       /* GravityNotify */
34605b261ecSmrg	ResizeRedirectMask,	       /* ResizeRequest */
34705b261ecSmrg	StructureAndSubMask,	       /* CirculateNotify */
34805b261ecSmrg	SubstructureRedirectMask,      /* CirculateRequest */
34905b261ecSmrg	PropertyChangeMask,	       /* PropertyNotify */
35005b261ecSmrg	CantBeFiltered,		       /* SelectionClear */
35105b261ecSmrg	CantBeFiltered,		       /* SelectionRequest */
35205b261ecSmrg	CantBeFiltered,		       /* SelectionNotify */
35305b261ecSmrg	ColormapChangeMask,	       /* ColormapNotify */
35405b261ecSmrg	CantBeFiltered,		       /* ClientMessage */
35505b261ecSmrg	CantBeFiltered		       /* MappingNotify */
35605b261ecSmrg};
35705b261ecSmrg
35805b261ecSmrgstatic CARD8 criticalEvents[32] =
35905b261ecSmrg{
36005b261ecSmrg    0x7c				/* key and button events */
36105b261ecSmrg};
36205b261ecSmrg
36305b261ecSmrg#ifdef PANORAMIX
36405b261ecSmrgstatic void ConfineToShape(RegionPtr shape, int *px, int *py);
36505b261ecSmrgstatic void PostNewCursor(void);
36605b261ecSmrg
36705b261ecSmrg#define SyntheticMotion(x, y) \
36805b261ecSmrg    PostSyntheticMotion(x, y, noPanoramiXExtension ? 0 : \
36905b261ecSmrg                              sprite.screen->myNum, \
37005b261ecSmrg                        syncEvents.playingEvents ? \
37105b261ecSmrg                          syncEvents.time.milliseconds : \
37205b261ecSmrg                          currentTime.milliseconds);
37305b261ecSmrg
37405b261ecSmrgstatic Bool
37505b261ecSmrgXineramaSetCursorPosition(
37605b261ecSmrg    int x,
37705b261ecSmrg    int y,
37805b261ecSmrg    Bool generateEvent
37905b261ecSmrg){
38005b261ecSmrg    ScreenPtr pScreen;
38105b261ecSmrg    BoxRec box;
38205b261ecSmrg    int i;
38305b261ecSmrg
38405b261ecSmrg    /* x,y are in Screen 0 coordinates.  We need to decide what Screen
38505b261ecSmrg       to send the message too and what the coordinates relative to
38605b261ecSmrg       that screen are. */
38705b261ecSmrg
38805b261ecSmrg    pScreen = sprite.screen;
38905b261ecSmrg    x += panoramiXdataPtr[0].x;
39005b261ecSmrg    y += panoramiXdataPtr[0].y;
39105b261ecSmrg
39205b261ecSmrg    if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum],
39305b261ecSmrg								x, y, &box))
39405b261ecSmrg    {
39505b261ecSmrg	FOR_NSCREENS(i)
39605b261ecSmrg	{
39705b261ecSmrg	    if(i == pScreen->myNum)
39805b261ecSmrg		continue;
39905b261ecSmrg	    if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box))
40005b261ecSmrg	    {
40105b261ecSmrg		pScreen = screenInfo.screens[i];
40205b261ecSmrg		break;
40305b261ecSmrg	    }
40405b261ecSmrg	}
40505b261ecSmrg    }
40605b261ecSmrg
40705b261ecSmrg    sprite.screen = pScreen;
40805b261ecSmrg    sprite.hotPhys.x = x - panoramiXdataPtr[0].x;
40905b261ecSmrg    sprite.hotPhys.y = y - panoramiXdataPtr[0].y;
41005b261ecSmrg    x -= panoramiXdataPtr[pScreen->myNum].x;
41105b261ecSmrg    y -= panoramiXdataPtr[pScreen->myNum].y;
41205b261ecSmrg
41305b261ecSmrg    return (*pScreen->SetCursorPosition)(pScreen, x, y, generateEvent);
41405b261ecSmrg}
41505b261ecSmrg
41605b261ecSmrg
41705b261ecSmrgstatic void
41805b261ecSmrgXineramaConstrainCursor(void)
41905b261ecSmrg{
42005b261ecSmrg    ScreenPtr pScreen = sprite.screen;
42105b261ecSmrg    BoxRec newBox = sprite.physLimits;
42205b261ecSmrg
42305b261ecSmrg    /* Translate the constraining box to the screen
42405b261ecSmrg       the sprite is actually on */
42505b261ecSmrg    newBox.x1 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x;
42605b261ecSmrg    newBox.x2 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x;
42705b261ecSmrg    newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
42805b261ecSmrg    newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
42905b261ecSmrg
43005b261ecSmrg    (* pScreen->ConstrainCursor)(pScreen, &newBox);
43105b261ecSmrg}
43205b261ecSmrg
43305b261ecSmrgstatic void
43405b261ecSmrgXineramaCheckPhysLimits(
43505b261ecSmrg    CursorPtr cursor,
43605b261ecSmrg    Bool generateEvents
43705b261ecSmrg){
43805b261ecSmrg    HotSpot new;
43905b261ecSmrg
44005b261ecSmrg    if (!cursor)
44105b261ecSmrg	return;
44205b261ecSmrg
44305b261ecSmrg    new = sprite.hotPhys;
44405b261ecSmrg
44505b261ecSmrg    /* I don't care what the DDX has to say about it */
44605b261ecSmrg    sprite.physLimits = sprite.hotLimits;
44705b261ecSmrg
44805b261ecSmrg    /* constrain the pointer to those limits */
44905b261ecSmrg    if (new.x < sprite.physLimits.x1)
45005b261ecSmrg	new.x = sprite.physLimits.x1;
45105b261ecSmrg    else
45205b261ecSmrg	if (new.x >= sprite.physLimits.x2)
45305b261ecSmrg	    new.x = sprite.physLimits.x2 - 1;
45405b261ecSmrg    if (new.y < sprite.physLimits.y1)
45505b261ecSmrg	new.y = sprite.physLimits.y1;
45605b261ecSmrg    else
45705b261ecSmrg	if (new.y >= sprite.physLimits.y2)
45805b261ecSmrg	    new.y = sprite.physLimits.y2 - 1;
45905b261ecSmrg
46005b261ecSmrg    if (sprite.hotShape)  /* more work if the shape is a mess */
46105b261ecSmrg	ConfineToShape(sprite.hotShape, &new.x, &new.y);
46205b261ecSmrg
46305b261ecSmrg    if((new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y))
46405b261ecSmrg    {
46505b261ecSmrg	XineramaSetCursorPosition (new.x, new.y, generateEvents);
46605b261ecSmrg	if (!generateEvents)
46705b261ecSmrg	    SyntheticMotion(new.x, new.y);
46805b261ecSmrg    }
46905b261ecSmrg
47005b261ecSmrg    /* Tell DDX what the limits are */
47105b261ecSmrg    XineramaConstrainCursor();
47205b261ecSmrg}
47305b261ecSmrg
47405b261ecSmrg
47505b261ecSmrgstatic Bool
47605b261ecSmrgXineramaSetWindowPntrs(WindowPtr pWin)
47705b261ecSmrg{
47805b261ecSmrg    if(pWin == WindowTable[0]) {
47905b261ecSmrg	    memcpy(sprite.windows, WindowTable,
48005b261ecSmrg				PanoramiXNumScreens*sizeof(WindowPtr));
48105b261ecSmrg    } else {
48205b261ecSmrg	PanoramiXRes *win;
48305b261ecSmrg	int i;
48405b261ecSmrg
48505b261ecSmrg	win = (PanoramiXRes*)LookupIDByType(pWin->drawable.id, XRT_WINDOW);
48605b261ecSmrg
48705b261ecSmrg	if(!win)
48805b261ecSmrg	    return FALSE;
48905b261ecSmrg
49005b261ecSmrg	for(i = 0; i < PanoramiXNumScreens; i++) {
49105b261ecSmrg	   sprite.windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW);
49205b261ecSmrg	   if(!sprite.windows[i])  /* window is being unmapped */
49305b261ecSmrg		return FALSE;
49405b261ecSmrg	}
49505b261ecSmrg    }
49605b261ecSmrg    return TRUE;
49705b261ecSmrg}
49805b261ecSmrg
49905b261ecSmrgstatic void
50005b261ecSmrgXineramaCheckVirtualMotion(
50105b261ecSmrg   QdEventPtr qe,
50205b261ecSmrg   WindowPtr pWin
50305b261ecSmrg){
50405b261ecSmrg
50505b261ecSmrg    if (qe)
50605b261ecSmrg    {
50705b261ecSmrg	sprite.hot.pScreen = qe->pScreen;  /* should always be Screen 0 */
50805b261ecSmrg	sprite.hot.x = qe->event->u.keyButtonPointer.rootX;
50905b261ecSmrg	sprite.hot.y = qe->event->u.keyButtonPointer.rootY;
51005b261ecSmrg	pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo :
51105b261ecSmrg					 NullWindow;
51205b261ecSmrg    }
51305b261ecSmrg    if (pWin)
51405b261ecSmrg    {
51505b261ecSmrg	int x, y, off_x, off_y, i;
51605b261ecSmrg	BoxRec lims;
51705b261ecSmrg
51805b261ecSmrg	if(!XineramaSetWindowPntrs(pWin))
51905b261ecSmrg	    return;
52005b261ecSmrg
52105b261ecSmrg	i = PanoramiXNumScreens - 1;
52205b261ecSmrg
52305b261ecSmrg	REGION_COPY(sprite.screen, &sprite.Reg2,
52405b261ecSmrg					&sprite.windows[i]->borderSize);
52505b261ecSmrg	off_x = panoramiXdataPtr[i].x;
52605b261ecSmrg	off_y = panoramiXdataPtr[i].y;
52705b261ecSmrg
52805b261ecSmrg	while(i--) {
52905b261ecSmrg	    x = off_x - panoramiXdataPtr[i].x;
53005b261ecSmrg	    y = off_y - panoramiXdataPtr[i].y;
53105b261ecSmrg
53205b261ecSmrg	    if(x || y)
53305b261ecSmrg		REGION_TRANSLATE(sprite.screen, &sprite.Reg2, x, y);
53405b261ecSmrg
53505b261ecSmrg	    REGION_UNION(sprite.screen, &sprite.Reg2, &sprite.Reg2,
53605b261ecSmrg					&sprite.windows[i]->borderSize);
53705b261ecSmrg
53805b261ecSmrg	    off_x = panoramiXdataPtr[i].x;
53905b261ecSmrg	    off_y = panoramiXdataPtr[i].y;
54005b261ecSmrg	}
54105b261ecSmrg
54205b261ecSmrg	lims = *REGION_EXTENTS(sprite.screen, &sprite.Reg2);
54305b261ecSmrg
54405b261ecSmrg        if (sprite.hot.x < lims.x1)
54505b261ecSmrg            sprite.hot.x = lims.x1;
54605b261ecSmrg        else if (sprite.hot.x >= lims.x2)
54705b261ecSmrg            sprite.hot.x = lims.x2 - 1;
54805b261ecSmrg        if (sprite.hot.y < lims.y1)
54905b261ecSmrg            sprite.hot.y = lims.y1;
55005b261ecSmrg        else if (sprite.hot.y >= lims.y2)
55105b261ecSmrg            sprite.hot.y = lims.y2 - 1;
55205b261ecSmrg
55305b261ecSmrg	if (REGION_NUM_RECTS(&sprite.Reg2) > 1)
55405b261ecSmrg	    ConfineToShape(&sprite.Reg2, &sprite.hot.x, &sprite.hot.y);
55505b261ecSmrg
55605b261ecSmrg	if (qe)
55705b261ecSmrg	{
55805b261ecSmrg	    qe->pScreen = sprite.hot.pScreen;
55905b261ecSmrg	    qe->event->u.keyButtonPointer.rootX = sprite.hot.x;
56005b261ecSmrg	    qe->event->u.keyButtonPointer.rootY = sprite.hot.y;
56105b261ecSmrg	}
56205b261ecSmrg    }
56305b261ecSmrg#ifdef XEVIE
56405b261ecSmrg    xeviehot.x = sprite.hot.x;
56505b261ecSmrg    xeviehot.y = sprite.hot.y;
56605b261ecSmrg#endif
56705b261ecSmrg}
56805b261ecSmrg
56905b261ecSmrg
57005b261ecSmrgstatic Bool
57105b261ecSmrgXineramaCheckMotion(xEvent *xE)
57205b261ecSmrg{
57305b261ecSmrg    WindowPtr prevSpriteWin = sprite.win;
57405b261ecSmrg
57505b261ecSmrg    if (xE && !syncEvents.playingEvents)
57605b261ecSmrg    {
57705b261ecSmrg	/* Motion events entering DIX get translated to Screen 0
57805b261ecSmrg	   coordinates.  Replayed events have already been
57905b261ecSmrg	   translated since they've entered DIX before */
58005b261ecSmrg	XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x -
58105b261ecSmrg			  panoramiXdataPtr[0].x;
58205b261ecSmrg	XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y -
58305b261ecSmrg			  panoramiXdataPtr[0].y;
58405b261ecSmrg	sprite.hot.x = XE_KBPTR.rootX;
58505b261ecSmrg	sprite.hot.y = XE_KBPTR.rootY;
58605b261ecSmrg	if (sprite.hot.x < sprite.physLimits.x1)
58705b261ecSmrg	    sprite.hot.x = sprite.physLimits.x1;
58805b261ecSmrg	else if (sprite.hot.x >= sprite.physLimits.x2)
58905b261ecSmrg	    sprite.hot.x = sprite.physLimits.x2 - 1;
59005b261ecSmrg	if (sprite.hot.y < sprite.physLimits.y1)
59105b261ecSmrg	    sprite.hot.y = sprite.physLimits.y1;
59205b261ecSmrg	else if (sprite.hot.y >= sprite.physLimits.y2)
59305b261ecSmrg	    sprite.hot.y = sprite.physLimits.y2 - 1;
59405b261ecSmrg
59505b261ecSmrg	if (sprite.hotShape)
59605b261ecSmrg	    ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y);
59705b261ecSmrg
59805b261ecSmrg	sprite.hotPhys = sprite.hot;
59905b261ecSmrg	if ((sprite.hotPhys.x != XE_KBPTR.rootX) ||
60005b261ecSmrg	    (sprite.hotPhys.y != XE_KBPTR.rootY))
60105b261ecSmrg	{
60205b261ecSmrg	    XineramaSetCursorPosition(
60305b261ecSmrg			sprite.hotPhys.x, sprite.hotPhys.y, FALSE);
60405b261ecSmrg	}
60505b261ecSmrg	XE_KBPTR.rootX = sprite.hot.x;
60605b261ecSmrg	XE_KBPTR.rootY = sprite.hot.y;
60705b261ecSmrg    }
60805b261ecSmrg
60905b261ecSmrg#ifdef XEVIE
61005b261ecSmrg    xeviehot.x = sprite.hot.x;
61105b261ecSmrg    xeviehot.y = sprite.hot.y;
61205b261ecSmrg    xeviewin =
61305b261ecSmrg#endif
61405b261ecSmrg    sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y);
61505b261ecSmrg
61605b261ecSmrg    if (sprite.win != prevSpriteWin)
61705b261ecSmrg    {
61805b261ecSmrg	if (prevSpriteWin != NullWindow) {
61905b261ecSmrg	    if (!xE)
62005b261ecSmrg		UpdateCurrentTimeIf();
62105b261ecSmrg	    DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal);
62205b261ecSmrg	}
62305b261ecSmrg	PostNewCursor();
62405b261ecSmrg        return FALSE;
62505b261ecSmrg    }
62605b261ecSmrg    return TRUE;
62705b261ecSmrg}
62805b261ecSmrg
62905b261ecSmrg
63005b261ecSmrgstatic void
63105b261ecSmrgXineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents)
63205b261ecSmrg{
63305b261ecSmrg
63405b261ecSmrg    if (syncEvents.playingEvents)
63505b261ecSmrg    {
63605b261ecSmrg	XineramaCheckVirtualMotion((QdEventPtr)NULL, pWin);
63705b261ecSmrg	SyntheticMotion(sprite.hot.x, sprite.hot.y);
63805b261ecSmrg    }
63905b261ecSmrg    else
64005b261ecSmrg    {
64105b261ecSmrg	int x, y, off_x, off_y, i;
64205b261ecSmrg
64305b261ecSmrg	if(!XineramaSetWindowPntrs(pWin))
64405b261ecSmrg	    return;
64505b261ecSmrg
64605b261ecSmrg	i = PanoramiXNumScreens - 1;
64705b261ecSmrg
64805b261ecSmrg	REGION_COPY(sprite.screen, &sprite.Reg1,
64905b261ecSmrg					&sprite.windows[i]->borderSize);
65005b261ecSmrg	off_x = panoramiXdataPtr[i].x;
65105b261ecSmrg	off_y = panoramiXdataPtr[i].y;
65205b261ecSmrg
65305b261ecSmrg	while(i--) {
65405b261ecSmrg	    x = off_x - panoramiXdataPtr[i].x;
65505b261ecSmrg	    y = off_y - panoramiXdataPtr[i].y;
65605b261ecSmrg
65705b261ecSmrg	    if(x || y)
65805b261ecSmrg		REGION_TRANSLATE(sprite.screen, &sprite.Reg1, x, y);
65905b261ecSmrg
66005b261ecSmrg	    REGION_UNION(sprite.screen, &sprite.Reg1, &sprite.Reg1,
66105b261ecSmrg					&sprite.windows[i]->borderSize);
66205b261ecSmrg
66305b261ecSmrg	    off_x = panoramiXdataPtr[i].x;
66405b261ecSmrg	    off_y = panoramiXdataPtr[i].y;
66505b261ecSmrg	}
66605b261ecSmrg
66705b261ecSmrg	sprite.hotLimits = *REGION_EXTENTS(sprite.screen, &sprite.Reg1);
66805b261ecSmrg
66905b261ecSmrg	if(REGION_NUM_RECTS(&sprite.Reg1) > 1)
67005b261ecSmrg	   sprite.hotShape = &sprite.Reg1;
67105b261ecSmrg	else
67205b261ecSmrg	   sprite.hotShape = NullRegion;
67305b261ecSmrg
67405b261ecSmrg	sprite.confined = FALSE;
67505b261ecSmrg	sprite.confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin;
67605b261ecSmrg
67705b261ecSmrg	XineramaCheckPhysLimits(sprite.current, generateEvents);
67805b261ecSmrg    }
67905b261ecSmrg}
68005b261ecSmrg
68105b261ecSmrg
68205b261ecSmrgstatic void
68305b261ecSmrgXineramaChangeToCursor(CursorPtr cursor)
68405b261ecSmrg{
68505b261ecSmrg    if (cursor != sprite.current)
68605b261ecSmrg    {
68705b261ecSmrg	if ((sprite.current->bits->xhot != cursor->bits->xhot) ||
68805b261ecSmrg		(sprite.current->bits->yhot != cursor->bits->yhot))
68905b261ecSmrg	    XineramaCheckPhysLimits(cursor, FALSE);
69005b261ecSmrg    	(*sprite.screen->DisplayCursor)(sprite.screen, cursor);
69105b261ecSmrg	FreeCursor(sprite.current, (Cursor)0);
69205b261ecSmrg	sprite.current = cursor;
69305b261ecSmrg	sprite.current->refcnt++;
69405b261ecSmrg    }
69505b261ecSmrg}
69605b261ecSmrg
69705b261ecSmrg#else
69805b261ecSmrg#define SyntheticMotion(x, y) \
69905b261ecSmrg     PostSyntheticMotion(x, y, \
70005b261ecSmrg                         0, \
70105b261ecSmrg                         syncEvents.playingEvents ? \
70205b261ecSmrg                           syncEvents.time.milliseconds : \
70305b261ecSmrg                           currentTime.milliseconds);
70405b261ecSmrg
70505b261ecSmrg#endif  /* PANORAMIX */
70605b261ecSmrg
70705b261ecSmrgvoid
70805b261ecSmrgSetMaskForEvent(Mask mask, int event)
70905b261ecSmrg{
71005b261ecSmrg    if ((event < LASTEvent) || (event >= 128))
71105b261ecSmrg	FatalError("SetMaskForEvent: bogus event number");
71205b261ecSmrg    filters[event] = mask;
71305b261ecSmrg}
71405b261ecSmrg
71505b261ecSmrg_X_EXPORT void
71605b261ecSmrgSetCriticalEvent(int event)
71705b261ecSmrg{
71805b261ecSmrg    if (event >= 128)
71905b261ecSmrg	FatalError("SetCriticalEvent: bogus event number");
72005b261ecSmrg    criticalEvents[event >> 3] |= 1 << (event & 7);
72105b261ecSmrg}
72205b261ecSmrg
72305b261ecSmrg#ifdef SHAPE
72405b261ecSmrgstatic void
72505b261ecSmrgConfineToShape(RegionPtr shape, int *px, int *py)
72605b261ecSmrg{
72705b261ecSmrg    BoxRec box;
72805b261ecSmrg    int x = *px, y = *py;
72905b261ecSmrg    int incx = 1, incy = 1;
73005b261ecSmrg
73105b261ecSmrg    if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box))
73205b261ecSmrg	return;
73305b261ecSmrg    box = *REGION_EXTENTS(sprite.hot.pScreen, shape);
73405b261ecSmrg    /* this is rather crude */
73505b261ecSmrg    do {
73605b261ecSmrg	x += incx;
73705b261ecSmrg	if (x >= box.x2)
73805b261ecSmrg	{
73905b261ecSmrg	    incx = -1;
74005b261ecSmrg	    x = *px - 1;
74105b261ecSmrg	}
74205b261ecSmrg	else if (x < box.x1)
74305b261ecSmrg	{
74405b261ecSmrg	    incx = 1;
74505b261ecSmrg	    x = *px;
74605b261ecSmrg	    y += incy;
74705b261ecSmrg	    if (y >= box.y2)
74805b261ecSmrg	    {
74905b261ecSmrg		incy = -1;
75005b261ecSmrg		y = *py - 1;
75105b261ecSmrg	    }
75205b261ecSmrg	    else if (y < box.y1)
75305b261ecSmrg		return; /* should never get here! */
75405b261ecSmrg	}
75505b261ecSmrg    } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box));
75605b261ecSmrg    *px = x;
75705b261ecSmrg    *py = y;
75805b261ecSmrg}
75905b261ecSmrg#endif
76005b261ecSmrg
76105b261ecSmrgstatic void
76205b261ecSmrgCheckPhysLimits(
76305b261ecSmrg    CursorPtr cursor,
76405b261ecSmrg    Bool generateEvents,
76505b261ecSmrg    Bool confineToScreen,
76605b261ecSmrg    ScreenPtr pScreen)
76705b261ecSmrg{
76805b261ecSmrg    HotSpot new;
76905b261ecSmrg
77005b261ecSmrg    if (!cursor)
77105b261ecSmrg	return;
77205b261ecSmrg    new = sprite.hotPhys;
77305b261ecSmrg    if (pScreen)
77405b261ecSmrg	new.pScreen = pScreen;
77505b261ecSmrg    else
77605b261ecSmrg	pScreen = new.pScreen;
77705b261ecSmrg    (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits,
77805b261ecSmrg			      &sprite.physLimits);
77905b261ecSmrg    sprite.confined = confineToScreen;
78005b261ecSmrg    (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits);
78105b261ecSmrg    if (new.x < sprite.physLimits.x1)
78205b261ecSmrg	new.x = sprite.physLimits.x1;
78305b261ecSmrg    else
78405b261ecSmrg	if (new.x >= sprite.physLimits.x2)
78505b261ecSmrg	    new.x = sprite.physLimits.x2 - 1;
78605b261ecSmrg    if (new.y < sprite.physLimits.y1)
78705b261ecSmrg	new.y = sprite.physLimits.y1;
78805b261ecSmrg    else
78905b261ecSmrg	if (new.y >= sprite.physLimits.y2)
79005b261ecSmrg	    new.y = sprite.physLimits.y2 - 1;
79105b261ecSmrg#ifdef SHAPE
79205b261ecSmrg    if (sprite.hotShape)
79305b261ecSmrg	ConfineToShape(sprite.hotShape, &new.x, &new.y);
79405b261ecSmrg#endif
79505b261ecSmrg    if ((pScreen != sprite.hotPhys.pScreen) ||
79605b261ecSmrg	(new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y))
79705b261ecSmrg    {
79805b261ecSmrg	if (pScreen != sprite.hotPhys.pScreen)
79905b261ecSmrg	    sprite.hotPhys = new;
80005b261ecSmrg	(*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents);
80105b261ecSmrg	if (!generateEvents)
80205b261ecSmrg	    SyntheticMotion(new.x, new.y);
80305b261ecSmrg    }
80405b261ecSmrg}
80505b261ecSmrg
80605b261ecSmrgstatic void
80705b261ecSmrgCheckVirtualMotion(
80805b261ecSmrg    QdEventPtr qe,
80905b261ecSmrg    WindowPtr pWin)
81005b261ecSmrg{
81105b261ecSmrg#ifdef PANORAMIX
81205b261ecSmrg    if(!noPanoramiXExtension) {
81305b261ecSmrg	XineramaCheckVirtualMotion(qe, pWin);
81405b261ecSmrg	return;
81505b261ecSmrg    }
81605b261ecSmrg#endif
81705b261ecSmrg    if (qe)
81805b261ecSmrg    {
81905b261ecSmrg	sprite.hot.pScreen = qe->pScreen;
82005b261ecSmrg	sprite.hot.x = qe->event->u.keyButtonPointer.rootX;
82105b261ecSmrg	sprite.hot.y = qe->event->u.keyButtonPointer.rootY;
82205b261ecSmrg	pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo :
82305b261ecSmrg					 NullWindow;
82405b261ecSmrg    }
82505b261ecSmrg    if (pWin)
82605b261ecSmrg    {
82705b261ecSmrg	BoxRec lims;
82805b261ecSmrg
82905b261ecSmrg	if (sprite.hot.pScreen != pWin->drawable.pScreen)
83005b261ecSmrg	{
83105b261ecSmrg	    sprite.hot.pScreen = pWin->drawable.pScreen;
83205b261ecSmrg	    sprite.hot.x = sprite.hot.y = 0;
83305b261ecSmrg	}
83405b261ecSmrg	lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize);
83505b261ecSmrg	if (sprite.hot.x < lims.x1)
83605b261ecSmrg	    sprite.hot.x = lims.x1;
83705b261ecSmrg	else if (sprite.hot.x >= lims.x2)
83805b261ecSmrg	    sprite.hot.x = lims.x2 - 1;
83905b261ecSmrg	if (sprite.hot.y < lims.y1)
84005b261ecSmrg	    sprite.hot.y = lims.y1;
84105b261ecSmrg	else if (sprite.hot.y >= lims.y2)
84205b261ecSmrg	    sprite.hot.y = lims.y2 - 1;
84305b261ecSmrg#ifdef SHAPE
84405b261ecSmrg	if (wBoundingShape(pWin))
84505b261ecSmrg	    ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y);
84605b261ecSmrg#endif
84705b261ecSmrg	if (qe)
84805b261ecSmrg	{
84905b261ecSmrg	    qe->pScreen = sprite.hot.pScreen;
85005b261ecSmrg	    qe->event->u.keyButtonPointer.rootX = sprite.hot.x;
85105b261ecSmrg	    qe->event->u.keyButtonPointer.rootY = sprite.hot.y;
85205b261ecSmrg	}
85305b261ecSmrg    }
85405b261ecSmrg#ifdef XEVIE
85505b261ecSmrg    xeviehot.x = sprite.hot.x;
85605b261ecSmrg    xeviehot.y = sprite.hot.y;
85705b261ecSmrg#endif
85805b261ecSmrg    ROOT = WindowTable[sprite.hot.pScreen->myNum];
85905b261ecSmrg}
86005b261ecSmrg
86105b261ecSmrgstatic void
86205b261ecSmrgConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
86305b261ecSmrg{
86405b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
86505b261ecSmrg
86605b261ecSmrg#ifdef PANORAMIX
86705b261ecSmrg    if(!noPanoramiXExtension) {
86805b261ecSmrg	XineramaConfineCursorToWindow(pWin, generateEvents);
86905b261ecSmrg	return;
87005b261ecSmrg    }
87105b261ecSmrg#endif
87205b261ecSmrg
87305b261ecSmrg    if (syncEvents.playingEvents)
87405b261ecSmrg    {
87505b261ecSmrg	CheckVirtualMotion((QdEventPtr)NULL, pWin);
87605b261ecSmrg	SyntheticMotion(sprite.hot.x, sprite.hot.y);
87705b261ecSmrg    }
87805b261ecSmrg    else
87905b261ecSmrg    {
88005b261ecSmrg	sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize);
88105b261ecSmrg#ifdef SHAPE
88205b261ecSmrg	sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize
88305b261ecSmrg					       : NullRegion;
88405b261ecSmrg#endif
88505b261ecSmrg	CheckPhysLimits(sprite.current, generateEvents, confineToScreen,
88605b261ecSmrg			pScreen);
88705b261ecSmrg    }
88805b261ecSmrg}
88905b261ecSmrg
89005b261ecSmrg_X_EXPORT Bool
89105b261ecSmrgPointerConfinedToScreen(void)
89205b261ecSmrg{
89305b261ecSmrg    return sprite.confined;
89405b261ecSmrg}
89505b261ecSmrg
89605b261ecSmrg/**
89705b261ecSmrg * Update the sprite cursor to the given cursor.
89805b261ecSmrg *
89905b261ecSmrg * ChangeToCursor() will display the new cursor and free the old cursor (if
90005b261ecSmrg * applicable). If the provided cursor is already the updated cursor, nothing
90105b261ecSmrg * happens.
90205b261ecSmrg */
90305b261ecSmrgstatic void
90405b261ecSmrgChangeToCursor(CursorPtr cursor)
90505b261ecSmrg{
90605b261ecSmrg#ifdef PANORAMIX
90705b261ecSmrg    if(!noPanoramiXExtension) {
90805b261ecSmrg	XineramaChangeToCursor(cursor);
90905b261ecSmrg	return;
91005b261ecSmrg    }
91105b261ecSmrg#endif
91205b261ecSmrg
91305b261ecSmrg    if (cursor != sprite.current)
91405b261ecSmrg    {
91505b261ecSmrg	if ((sprite.current->bits->xhot != cursor->bits->xhot) ||
91605b261ecSmrg		(sprite.current->bits->yhot != cursor->bits->yhot))
91705b261ecSmrg	    CheckPhysLimits(cursor, FALSE, sprite.confined,
91805b261ecSmrg			    (ScreenPtr)NULL);
91905b261ecSmrg	(*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen,
92005b261ecSmrg						  cursor);
92105b261ecSmrg	FreeCursor(sprite.current, (Cursor)0);
92205b261ecSmrg	sprite.current = cursor;
92305b261ecSmrg	sprite.current->refcnt++;
92405b261ecSmrg    }
92505b261ecSmrg}
92605b261ecSmrg
92705b261ecSmrg/**
92805b261ecSmrg * @returns true if b is a descendent of a
92905b261ecSmrg */
93005b261ecSmrgBool
93105b261ecSmrgIsParent(WindowPtr a, WindowPtr b)
93205b261ecSmrg{
93305b261ecSmrg    for (b = b->parent; b; b = b->parent)
93405b261ecSmrg	if (b == a) return TRUE;
93505b261ecSmrg    return FALSE;
93605b261ecSmrg}
93705b261ecSmrg
93805b261ecSmrg/**
93905b261ecSmrg * Update the cursor displayed on the screen.
94005b261ecSmrg *
94105b261ecSmrg * Called whenever a cursor may have changed shape or position.
94205b261ecSmrg */
94305b261ecSmrgstatic void
94405b261ecSmrgPostNewCursor(void)
94505b261ecSmrg{
94605b261ecSmrg    WindowPtr win;
94705b261ecSmrg    GrabPtr grab = inputInfo.pointer->grab;
94805b261ecSmrg
94905b261ecSmrg    if (syncEvents.playingEvents)
95005b261ecSmrg	return;
95105b261ecSmrg    if (grab)
95205b261ecSmrg    {
95305b261ecSmrg	if (grab->cursor)
95405b261ecSmrg	{
95505b261ecSmrg	    ChangeToCursor(grab->cursor);
95605b261ecSmrg	    return;
95705b261ecSmrg	}
95805b261ecSmrg	if (IsParent(grab->window, sprite.win))
95905b261ecSmrg	    win = sprite.win;
96005b261ecSmrg	else
96105b261ecSmrg	    win = grab->window;
96205b261ecSmrg    }
96305b261ecSmrg    else
96405b261ecSmrg	win = sprite.win;
96505b261ecSmrg    for (; win; win = win->parent)
96605b261ecSmrg	if (win->optional && win->optional->cursor != NullCursor)
96705b261ecSmrg	{
96805b261ecSmrg	    ChangeToCursor(win->optional->cursor);
96905b261ecSmrg	    return;
97005b261ecSmrg	}
97105b261ecSmrg}
97205b261ecSmrg
97305b261ecSmrg/**
97405b261ecSmrg * @return root window of current active screen.
97505b261ecSmrg */
97605b261ecSmrg_X_EXPORT WindowPtr
97705b261ecSmrgGetCurrentRootWindow(void)
97805b261ecSmrg{
97905b261ecSmrg    return ROOT;
98005b261ecSmrg}
98105b261ecSmrg
98205b261ecSmrg/**
98305b261ecSmrg * @return window underneath the cursor sprite.
98405b261ecSmrg */
98505b261ecSmrg_X_EXPORT WindowPtr
98605b261ecSmrgGetSpriteWindow(void)
98705b261ecSmrg{
98805b261ecSmrg    return sprite.win;
98905b261ecSmrg}
99005b261ecSmrg
99105b261ecSmrg/**
99205b261ecSmrg * @return current sprite cursor.
99305b261ecSmrg */
99405b261ecSmrg_X_EXPORT CursorPtr
99505b261ecSmrgGetSpriteCursor(void)
99605b261ecSmrg{
99705b261ecSmrg    return sprite.current;
99805b261ecSmrg}
99905b261ecSmrg
100005b261ecSmrg/**
100105b261ecSmrg * Set x/y current sprite position in screen coordinates.
100205b261ecSmrg */
100305b261ecSmrg_X_EXPORT void
100405b261ecSmrgGetSpritePosition(int *px, int *py)
100505b261ecSmrg{
100605b261ecSmrg    *px = sprite.hotPhys.x;
100705b261ecSmrg    *py = sprite.hotPhys.y;
100805b261ecSmrg}
100905b261ecSmrg
101005b261ecSmrg#ifdef PANORAMIX
101105b261ecSmrg_X_EXPORT int
101205b261ecSmrgXineramaGetCursorScreen(void)
101305b261ecSmrg{
101405b261ecSmrg    if(!noPanoramiXExtension) {
101505b261ecSmrg	return sprite.screen->myNum;
101605b261ecSmrg    } else {
101705b261ecSmrg	return 0;
101805b261ecSmrg    }
101905b261ecSmrg}
102005b261ecSmrg#endif /* PANORAMIX */
102105b261ecSmrg
102205b261ecSmrg#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */
102305b261ecSmrg
102405b261ecSmrgstatic void
102505b261ecSmrgMonthChangedOrBadTime(xEvent *xE)
102605b261ecSmrg{
102705b261ecSmrg    /* If the ddx/OS is careless about not processing timestamped events from
102805b261ecSmrg     * different sources in sorted order, then it's possible for time to go
102905b261ecSmrg     * backwards when it should not.  Here we ensure a decent time.
103005b261ecSmrg     */
103105b261ecSmrg    if ((currentTime.milliseconds - XE_KBPTR.time) > TIMESLOP)
103205b261ecSmrg	currentTime.months++;
103305b261ecSmrg    else
103405b261ecSmrg	XE_KBPTR.time = currentTime.milliseconds;
103505b261ecSmrg}
103605b261ecSmrg
103705b261ecSmrg#define NoticeTime(xE) { \
103805b261ecSmrg    if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \
103905b261ecSmrg	MonthChangedOrBadTime(xE); \
104005b261ecSmrg    currentTime.milliseconds = (xE)->u.keyButtonPointer.time; \
104105b261ecSmrg    lastDeviceEventTime = currentTime; }
104205b261ecSmrg
104305b261ecSmrgvoid
104405b261ecSmrgNoticeEventTime(xEvent *xE)
104505b261ecSmrg{
104605b261ecSmrg    if (!syncEvents.playingEvents)
104705b261ecSmrg	NoticeTime(xE);
104805b261ecSmrg}
104905b261ecSmrg
105005b261ecSmrg/**************************************************************************
105105b261ecSmrg *            The following procedures deal with synchronous events       *
105205b261ecSmrg **************************************************************************/
105305b261ecSmrg
105405b261ecSmrgvoid
105505b261ecSmrgEnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
105605b261ecSmrg{
105705b261ecSmrg    QdEventPtr tail = *syncEvents.pendtail;
105805b261ecSmrg    QdEventPtr qe;
105905b261ecSmrg    xEvent		*qxE;
106005b261ecSmrg
106105b261ecSmrg    NoticeTime(xE);
106205b261ecSmrg
106305b261ecSmrg#ifdef XKB
106405b261ecSmrg    /* Fix for key repeating bug. */
106505b261ecSmrg    if (device->key != NULL && device->key->xkbInfo != NULL &&
106605b261ecSmrg	xE->u.u.type == KeyRelease)
106705b261ecSmrg	AccessXCancelRepeatKey(device->key->xkbInfo, xE->u.u.detail);
106805b261ecSmrg#endif
106905b261ecSmrg
107005b261ecSmrg    if (DeviceEventCallback)
107105b261ecSmrg    {
107205b261ecSmrg	DeviceEventInfoRec eventinfo;
107305b261ecSmrg	/*  The RECORD spec says that the root window field of motion events
107405b261ecSmrg	 *  must be valid.  At this point, it hasn't been filled in yet, so
107505b261ecSmrg	 *  we do it here.  The long expression below is necessary to get
107605b261ecSmrg	 *  the current root window; the apparently reasonable alternative
107705b261ecSmrg	 *  GetCurrentRootWindow()->drawable.id doesn't give you the right
107805b261ecSmrg	 *  answer on the first motion event after a screen change because
107905b261ecSmrg	 *  the data that GetCurrentRootWindow relies on hasn't been
108005b261ecSmrg	 *  updated yet.
108105b261ecSmrg	 */
108205b261ecSmrg	if (xE->u.u.type == MotionNotify)
108305b261ecSmrg	    XE_KBPTR.root =
108405b261ecSmrg		WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id;
108505b261ecSmrg	eventinfo.events = xE;
108605b261ecSmrg	eventinfo.count = count;
108705b261ecSmrg	CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
108805b261ecSmrg    }
108905b261ecSmrg    if (xE->u.u.type == MotionNotify)
109005b261ecSmrg    {
109105b261ecSmrg#ifdef PANORAMIX
109205b261ecSmrg	if(!noPanoramiXExtension) {
109305b261ecSmrg	    XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x -
109405b261ecSmrg			      panoramiXdataPtr[0].x;
109505b261ecSmrg	    XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y -
109605b261ecSmrg			      panoramiXdataPtr[0].y;
109705b261ecSmrg	}
109805b261ecSmrg#endif
109905b261ecSmrg	sprite.hotPhys.x = XE_KBPTR.rootX;
110005b261ecSmrg	sprite.hotPhys.y = XE_KBPTR.rootY;
110105b261ecSmrg	/* do motion compression, but not if from different devices */
110205b261ecSmrg	if (tail &&
110305b261ecSmrg	    (tail->event->u.u.type == MotionNotify) &&
110405b261ecSmrg            (tail->device == device) &&
110505b261ecSmrg	    (tail->pScreen == sprite.hotPhys.pScreen))
110605b261ecSmrg	{
110705b261ecSmrg	    tail->event->u.keyButtonPointer.rootX = sprite.hotPhys.x;
110805b261ecSmrg	    tail->event->u.keyButtonPointer.rootY = sprite.hotPhys.y;
110905b261ecSmrg	    tail->event->u.keyButtonPointer.time = XE_KBPTR.time;
111005b261ecSmrg	    tail->months = currentTime.months;
111105b261ecSmrg	    return;
111205b261ecSmrg	}
111305b261ecSmrg    }
111405b261ecSmrg    qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent)));
111505b261ecSmrg    if (!qe)
111605b261ecSmrg	return;
111705b261ecSmrg    qe->next = (QdEventPtr)NULL;
111805b261ecSmrg    qe->device = device;
111905b261ecSmrg    qe->pScreen = sprite.hotPhys.pScreen;
112005b261ecSmrg    qe->months = currentTime.months;
112105b261ecSmrg    qe->event = (xEvent *)(qe + 1);
112205b261ecSmrg    qe->evcount = count;
112305b261ecSmrg    for (qxE = qe->event; --count >= 0; qxE++, xE++)
112405b261ecSmrg	*qxE = *xE;
112505b261ecSmrg    if (tail)
112605b261ecSmrg	syncEvents.pendtail = &tail->next;
112705b261ecSmrg    *syncEvents.pendtail = qe;
112805b261ecSmrg}
112905b261ecSmrg
113005b261ecSmrgstatic void
113105b261ecSmrgPlayReleasedEvents(void)
113205b261ecSmrg{
113305b261ecSmrg    QdEventPtr *prev, qe;
113405b261ecSmrg    DeviceIntPtr dev;
113505b261ecSmrg
113605b261ecSmrg    prev = &syncEvents.pending;
113705b261ecSmrg    while ( (qe = *prev) )
113805b261ecSmrg    {
113905b261ecSmrg	if (!qe->device->sync.frozen)
114005b261ecSmrg	{
114105b261ecSmrg	    *prev = qe->next;
114205b261ecSmrg	    if (*syncEvents.pendtail == *prev)
114305b261ecSmrg		syncEvents.pendtail = prev;
114405b261ecSmrg	    if (qe->event->u.u.type == MotionNotify)
114505b261ecSmrg		CheckVirtualMotion(qe, NullWindow);
114605b261ecSmrg	    syncEvents.time.months = qe->months;
114705b261ecSmrg	    syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time;
114805b261ecSmrg#ifdef PANORAMIX
114905b261ecSmrg	   /* Translate back to the sprite screen since processInputProc
115005b261ecSmrg	      will translate from sprite screen to screen 0 upon reentry
115105b261ecSmrg	      to the DIX layer */
115205b261ecSmrg	    if(!noPanoramiXExtension) {
115305b261ecSmrg		qe->event->u.keyButtonPointer.rootX +=
115405b261ecSmrg			panoramiXdataPtr[0].x -
115505b261ecSmrg			panoramiXdataPtr[sprite.screen->myNum].x;
115605b261ecSmrg		qe->event->u.keyButtonPointer.rootY +=
115705b261ecSmrg			panoramiXdataPtr[0].y -
115805b261ecSmrg			panoramiXdataPtr[sprite.screen->myNum].y;
115905b261ecSmrg	    }
116005b261ecSmrg#endif
116105b261ecSmrg	    (*qe->device->public.processInputProc)(qe->event, qe->device,
116205b261ecSmrg						   qe->evcount);
116305b261ecSmrg	    xfree(qe);
116405b261ecSmrg	    for (dev = inputInfo.devices; dev && dev->sync.frozen; dev = dev->next)
116505b261ecSmrg		;
116605b261ecSmrg	    if (!dev)
116705b261ecSmrg		break;
116805b261ecSmrg	    /* Playing the event may have unfrozen another device. */
116905b261ecSmrg	    /* So to play it safe, restart at the head of the queue */
117005b261ecSmrg	    prev = &syncEvents.pending;
117105b261ecSmrg	}
117205b261ecSmrg	else
117305b261ecSmrg	    prev = &qe->next;
117405b261ecSmrg    }
117505b261ecSmrg}
117605b261ecSmrg
117705b261ecSmrgstatic void
117805b261ecSmrgFreezeThaw(DeviceIntPtr dev, Bool frozen)
117905b261ecSmrg{
118005b261ecSmrg    dev->sync.frozen = frozen;
118105b261ecSmrg    if (frozen)
118205b261ecSmrg	dev->public.processInputProc = dev->public.enqueueInputProc;
118305b261ecSmrg    else
118405b261ecSmrg	dev->public.processInputProc = dev->public.realInputProc;
118505b261ecSmrg}
118605b261ecSmrg
118705b261ecSmrgvoid
118805b261ecSmrgComputeFreezes(void)
118905b261ecSmrg{
119005b261ecSmrg    DeviceIntPtr replayDev = syncEvents.replayDev;
119105b261ecSmrg    int i;
119205b261ecSmrg    WindowPtr w;
119305b261ecSmrg    xEvent *xE;
119405b261ecSmrg    int count;
119505b261ecSmrg    GrabPtr grab;
119605b261ecSmrg    DeviceIntPtr dev;
119705b261ecSmrg
119805b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
119905b261ecSmrg	FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN));
120005b261ecSmrg    if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
120105b261ecSmrg	return;
120205b261ecSmrg    syncEvents.playingEvents = TRUE;
120305b261ecSmrg    if (replayDev)
120405b261ecSmrg    {
120505b261ecSmrg	xE = replayDev->sync.event;
120605b261ecSmrg	count = replayDev->sync.evcount;
120705b261ecSmrg	syncEvents.replayDev = (DeviceIntPtr)NULL;
120805b261ecSmrg
120905b261ecSmrg        w = XYToWindow( XE_KBPTR.rootX, XE_KBPTR.rootY);
121005b261ecSmrg	for (i = 0; i < spriteTraceGood; i++)
121105b261ecSmrg	{
121205b261ecSmrg	    if (syncEvents.replayWin == spriteTrace[i])
121305b261ecSmrg	    {
121405b261ecSmrg		if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) {
121505b261ecSmrg		    if (replayDev->focus)
121605b261ecSmrg			DeliverFocusedEvent(replayDev, xE, w, count);
121705b261ecSmrg		    else
121805b261ecSmrg			DeliverDeviceEvents(w, xE, NullGrab, NullWindow,
121905b261ecSmrg					        replayDev, count);
122005b261ecSmrg		}
122105b261ecSmrg		goto playmore;
122205b261ecSmrg	    }
122305b261ecSmrg	}
122405b261ecSmrg	/* must not still be in the same stack */
122505b261ecSmrg	if (replayDev->focus)
122605b261ecSmrg	    DeliverFocusedEvent(replayDev, xE, w, count);
122705b261ecSmrg	else
122805b261ecSmrg	    DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count);
122905b261ecSmrg    }
123005b261ecSmrgplaymore:
123105b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
123205b261ecSmrg    {
123305b261ecSmrg	if (!dev->sync.frozen)
123405b261ecSmrg	{
123505b261ecSmrg	    PlayReleasedEvents();
123605b261ecSmrg	    break;
123705b261ecSmrg	}
123805b261ecSmrg    }
123905b261ecSmrg    syncEvents.playingEvents = FALSE;
124005b261ecSmrg    /* the following may have been skipped during replay, so do it now */
124105b261ecSmrg    if ((grab = inputInfo.pointer->grab) && grab->confineTo)
124205b261ecSmrg    {
124305b261ecSmrg	if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
124405b261ecSmrg	    sprite.hotPhys.x = sprite.hotPhys.y = 0;
124505b261ecSmrg	ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
124605b261ecSmrg    }
124705b261ecSmrg    else
124805b261ecSmrg	ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum],
124905b261ecSmrg			      TRUE, FALSE);
125005b261ecSmrg    PostNewCursor();
125105b261ecSmrg}
125205b261ecSmrg
125305b261ecSmrg#ifdef RANDR
125405b261ecSmrgvoid
125505b261ecSmrgScreenRestructured (ScreenPtr pScreen)
125605b261ecSmrg{
125705b261ecSmrg    GrabPtr grab;
125805b261ecSmrg
125905b261ecSmrg    if ((grab = inputInfo.pointer->grab) && grab->confineTo)
126005b261ecSmrg    {
126105b261ecSmrg	if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
126205b261ecSmrg	    sprite.hotPhys.x = sprite.hotPhys.y = 0;
126305b261ecSmrg	ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
126405b261ecSmrg    }
126505b261ecSmrg    else
126605b261ecSmrg	ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum],
126705b261ecSmrg			      TRUE, FALSE);
126805b261ecSmrg}
126905b261ecSmrg#endif
127005b261ecSmrg
127105b261ecSmrgvoid
127205b261ecSmrgCheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
127305b261ecSmrg{
127405b261ecSmrg    GrabPtr grab = thisDev->grab;
127505b261ecSmrg    DeviceIntPtr dev;
127605b261ecSmrg
127705b261ecSmrg    if (thisMode == GrabModeSync)
127805b261ecSmrg	thisDev->sync.state = FROZEN_NO_EVENT;
127905b261ecSmrg    else
128005b261ecSmrg    {	/* free both if same client owns both */
128105b261ecSmrg	thisDev->sync.state = THAWED;
128205b261ecSmrg	if (thisDev->sync.other &&
128305b261ecSmrg	    (CLIENT_BITS(thisDev->sync.other->resource) ==
128405b261ecSmrg	     CLIENT_BITS(grab->resource)))
128505b261ecSmrg	    thisDev->sync.other = NullGrab;
128605b261ecSmrg    }
128705b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
128805b261ecSmrg    {
128905b261ecSmrg	if (dev != thisDev)
129005b261ecSmrg	{
129105b261ecSmrg	    if (otherMode == GrabModeSync)
129205b261ecSmrg		dev->sync.other = grab;
129305b261ecSmrg	    else
129405b261ecSmrg	    {	/* free both if same client owns both */
129505b261ecSmrg		if (dev->sync.other &&
129605b261ecSmrg		    (CLIENT_BITS(dev->sync.other->resource) ==
129705b261ecSmrg		     CLIENT_BITS(grab->resource)))
129805b261ecSmrg		    dev->sync.other = NullGrab;
129905b261ecSmrg	    }
130005b261ecSmrg	}
130105b261ecSmrg    }
130205b261ecSmrg    ComputeFreezes();
130305b261ecSmrg}
130405b261ecSmrg
130505b261ecSmrg/**
130605b261ecSmrg * Activate a pointer grab on the given device. A pointer grab will cause all
130705b261ecSmrg * core pointer events to be delivered to the grabbing client only. Can cause
130805b261ecSmrg * the cursor to change if a grab cursor is set.
130905b261ecSmrg *
131005b261ecSmrg * As a pointer grab can only be issued on the core devices, mouse is always
131105b261ecSmrg * inputInfo.pointer. Extension devices are set up for ActivateKeyboardGrab().
131205b261ecSmrg *
131305b261ecSmrg * @param mouse The device to grab.
131405b261ecSmrg * @param grab The grab structure, needs to be setup.
131505b261ecSmrg * @param autoGrab True if the grab was caused by a button down event and not
131605b261ecSmrg * explicitely by a client.
131705b261ecSmrg */
131805b261ecSmrgvoid
131905b261ecSmrgActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
132005b261ecSmrg                    TimeStamp time, Bool autoGrab)
132105b261ecSmrg{
132205b261ecSmrg    WindowPtr oldWin = (mouse->grab) ? mouse->grab->window
132305b261ecSmrg				     : sprite.win;
132405b261ecSmrg
132505b261ecSmrg    if (grab->confineTo)
132605b261ecSmrg    {
132705b261ecSmrg	if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
132805b261ecSmrg	    sprite.hotPhys.x = sprite.hotPhys.y = 0;
132905b261ecSmrg	ConfineCursorToWindow(grab->confineTo, FALSE, TRUE);
133005b261ecSmrg    }
133105b261ecSmrg    DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab);
133205b261ecSmrg    mouse->valuator->motionHintWindow = NullWindow;
133305b261ecSmrg    if (syncEvents.playingEvents)
133405b261ecSmrg	mouse->grabTime = syncEvents.time;
133505b261ecSmrg    else
133605b261ecSmrg	mouse->grabTime = time;
133705b261ecSmrg    if (grab->cursor)
133805b261ecSmrg	grab->cursor->refcnt++;
133905b261ecSmrg    mouse->activeGrab = *grab;
134005b261ecSmrg    mouse->grab = &mouse->activeGrab;
134105b261ecSmrg    mouse->fromPassiveGrab = autoGrab;
134205b261ecSmrg    PostNewCursor();
134305b261ecSmrg    CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
134405b261ecSmrg}
134505b261ecSmrg
134605b261ecSmrg/**
134705b261ecSmrg * Delete grab on given device, update the sprite.
134805b261ecSmrg *
134905b261ecSmrg * As a pointer grab can only be issued on the core devices, mouse is always
135005b261ecSmrg * inputInfo.pointer. Extension devices are set up for ActivateKeyboardGrab().
135105b261ecSmrg */
135205b261ecSmrgvoid
135305b261ecSmrgDeactivatePointerGrab(DeviceIntPtr mouse)
135405b261ecSmrg{
135505b261ecSmrg    GrabPtr grab = mouse->grab;
135605b261ecSmrg    DeviceIntPtr dev;
135705b261ecSmrg
135805b261ecSmrg    mouse->valuator->motionHintWindow = NullWindow;
135905b261ecSmrg    mouse->grab = NullGrab;
136005b261ecSmrg    mouse->sync.state = NOT_GRABBED;
136105b261ecSmrg    mouse->fromPassiveGrab = FALSE;
136205b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
136305b261ecSmrg    {
136405b261ecSmrg	if (dev->sync.other == grab)
136505b261ecSmrg	    dev->sync.other = NullGrab;
136605b261ecSmrg    }
136705b261ecSmrg    DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab);
136805b261ecSmrg    if (grab->confineTo)
136905b261ecSmrg	ConfineCursorToWindow(ROOT, FALSE, FALSE);
137005b261ecSmrg    PostNewCursor();
137105b261ecSmrg    if (grab->cursor)
137205b261ecSmrg	FreeCursor(grab->cursor, (Cursor)0);
137305b261ecSmrg    ComputeFreezes();
137405b261ecSmrg}
137505b261ecSmrg
137605b261ecSmrg/**
137705b261ecSmrg * Activate a keyboard grab on the given device.
137805b261ecSmrg *
137905b261ecSmrg * Extension devices have ActivateKeyboardGrab() set as their grabbing proc.
138005b261ecSmrg */
138105b261ecSmrgvoid
138205b261ecSmrgActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive)
138305b261ecSmrg{
138405b261ecSmrg    WindowPtr oldWin;
138505b261ecSmrg
138605b261ecSmrg    if (keybd->grab)
138705b261ecSmrg	oldWin = keybd->grab->window;
138805b261ecSmrg    else if (keybd->focus)
138905b261ecSmrg	oldWin = keybd->focus->win;
139005b261ecSmrg    else
139105b261ecSmrg	oldWin = sprite.win;
139205b261ecSmrg    if (oldWin == FollowKeyboardWin)
139305b261ecSmrg	oldWin = inputInfo.keyboard->focus->win;
139405b261ecSmrg    if (keybd->valuator)
139505b261ecSmrg	keybd->valuator->motionHintWindow = NullWindow;
139605b261ecSmrg    DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
139705b261ecSmrg    if (syncEvents.playingEvents)
139805b261ecSmrg	keybd->grabTime = syncEvents.time;
139905b261ecSmrg    else
140005b261ecSmrg	keybd->grabTime = time;
140105b261ecSmrg    keybd->activeGrab = *grab;
140205b261ecSmrg    keybd->grab = &keybd->activeGrab;
140305b261ecSmrg    keybd->fromPassiveGrab = passive;
140405b261ecSmrg    CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
140505b261ecSmrg}
140605b261ecSmrg
140705b261ecSmrg/**
140805b261ecSmrg * Delete keyboard grab for the given device.
140905b261ecSmrg */
141005b261ecSmrgvoid
141105b261ecSmrgDeactivateKeyboardGrab(DeviceIntPtr keybd)
141205b261ecSmrg{
141305b261ecSmrg    GrabPtr grab = keybd->grab;
141405b261ecSmrg    DeviceIntPtr dev;
141505b261ecSmrg    WindowPtr focusWin = keybd->focus ? keybd->focus->win
141605b261ecSmrg					       : sprite.win;
141705b261ecSmrg
141805b261ecSmrg    if (focusWin == FollowKeyboardWin)
141905b261ecSmrg	focusWin = inputInfo.keyboard->focus->win;
142005b261ecSmrg    if (keybd->valuator)
142105b261ecSmrg	keybd->valuator->motionHintWindow = NullWindow;
142205b261ecSmrg    keybd->grab = NullGrab;
142305b261ecSmrg    keybd->sync.state = NOT_GRABBED;
142405b261ecSmrg    keybd->fromPassiveGrab = FALSE;
142505b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
142605b261ecSmrg    {
142705b261ecSmrg	if (dev->sync.other == grab)
142805b261ecSmrg	    dev->sync.other = NullGrab;
142905b261ecSmrg    }
143005b261ecSmrg    DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
143105b261ecSmrg    ComputeFreezes();
143205b261ecSmrg}
143305b261ecSmrg
143405b261ecSmrgvoid
143505b261ecSmrgAllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState)
143605b261ecSmrg{
143705b261ecSmrg    Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
143805b261ecSmrg    TimeStamp grabTime;
143905b261ecSmrg    DeviceIntPtr dev;
144005b261ecSmrg
144105b261ecSmrg    thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client);
144205b261ecSmrg    thisSynced = FALSE;
144305b261ecSmrg    otherGrabbed = FALSE;
144405b261ecSmrg    othersFrozen = TRUE;
144505b261ecSmrg    grabTime = thisDev->grabTime;
144605b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next)
144705b261ecSmrg    {
144805b261ecSmrg	if (dev == thisDev)
144905b261ecSmrg	    continue;
145005b261ecSmrg	if (dev->grab && SameClient(dev->grab, client))
145105b261ecSmrg	{
145205b261ecSmrg	    if (!(thisGrabbed || otherGrabbed) ||
145305b261ecSmrg		(CompareTimeStamps(dev->grabTime, grabTime) == LATER))
145405b261ecSmrg		grabTime = dev->grabTime;
145505b261ecSmrg	    otherGrabbed = TRUE;
145605b261ecSmrg	    if (thisDev->sync.other == dev->grab)
145705b261ecSmrg		thisSynced = TRUE;
145805b261ecSmrg	    if (dev->sync.state < FROZEN)
145905b261ecSmrg		othersFrozen = FALSE;
146005b261ecSmrg	}
146105b261ecSmrg	else if (!dev->sync.other || !SameClient(dev->sync.other, client))
146205b261ecSmrg	    othersFrozen = FALSE;
146305b261ecSmrg    }
146405b261ecSmrg    if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced))
146505b261ecSmrg	return;
146605b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
146705b261ecSmrg	(CompareTimeStamps(time, grabTime) == EARLIER))
146805b261ecSmrg	return;
146905b261ecSmrg    switch (newState)
147005b261ecSmrg    {
147105b261ecSmrg	case THAWED:	 	       /* Async */
147205b261ecSmrg	    if (thisGrabbed)
147305b261ecSmrg		thisDev->sync.state = THAWED;
147405b261ecSmrg	    if (thisSynced)
147505b261ecSmrg		thisDev->sync.other = NullGrab;
147605b261ecSmrg	    ComputeFreezes();
147705b261ecSmrg	    break;
147805b261ecSmrg	case FREEZE_NEXT_EVENT:		/* Sync */
147905b261ecSmrg	    if (thisGrabbed)
148005b261ecSmrg	    {
148105b261ecSmrg		thisDev->sync.state = FREEZE_NEXT_EVENT;
148205b261ecSmrg		if (thisSynced)
148305b261ecSmrg		    thisDev->sync.other = NullGrab;
148405b261ecSmrg		ComputeFreezes();
148505b261ecSmrg	    }
148605b261ecSmrg	    break;
148705b261ecSmrg	case THAWED_BOTH:		/* AsyncBoth */
148805b261ecSmrg	    if (othersFrozen)
148905b261ecSmrg	    {
149005b261ecSmrg		for (dev = inputInfo.devices; dev; dev = dev->next)
149105b261ecSmrg		{
149205b261ecSmrg		    if (dev->grab && SameClient(dev->grab, client))
149305b261ecSmrg			dev->sync.state = THAWED;
149405b261ecSmrg		    if (dev->sync.other && SameClient(dev->sync.other, client))
149505b261ecSmrg			dev->sync.other = NullGrab;
149605b261ecSmrg		}
149705b261ecSmrg		ComputeFreezes();
149805b261ecSmrg	    }
149905b261ecSmrg	    break;
150005b261ecSmrg	case FREEZE_BOTH_NEXT_EVENT:	/* SyncBoth */
150105b261ecSmrg	    if (othersFrozen)
150205b261ecSmrg	    {
150305b261ecSmrg		for (dev = inputInfo.devices; dev; dev = dev->next)
150405b261ecSmrg		{
150505b261ecSmrg		    if (dev->grab && SameClient(dev->grab, client))
150605b261ecSmrg			dev->sync.state = FREEZE_BOTH_NEXT_EVENT;
150705b261ecSmrg		    if (dev->sync.other && SameClient(dev->sync.other, client))
150805b261ecSmrg			dev->sync.other = NullGrab;
150905b261ecSmrg		}
151005b261ecSmrg		ComputeFreezes();
151105b261ecSmrg	    }
151205b261ecSmrg	    break;
151305b261ecSmrg	case NOT_GRABBED:		/* Replay */
151405b261ecSmrg	    if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT)
151505b261ecSmrg	    {
151605b261ecSmrg		if (thisSynced)
151705b261ecSmrg		    thisDev->sync.other = NullGrab;
151805b261ecSmrg		syncEvents.replayDev = thisDev;
151905b261ecSmrg		syncEvents.replayWin = thisDev->grab->window;
152005b261ecSmrg		(*thisDev->DeactivateGrab)(thisDev);
152105b261ecSmrg		syncEvents.replayDev = (DeviceIntPtr)NULL;
152205b261ecSmrg	    }
152305b261ecSmrg	    break;
152405b261ecSmrg	case THAW_OTHERS:		/* AsyncOthers */
152505b261ecSmrg	    if (othersFrozen)
152605b261ecSmrg	    {
152705b261ecSmrg		for (dev = inputInfo.devices; dev; dev = dev->next)
152805b261ecSmrg		{
152905b261ecSmrg		    if (dev == thisDev)
153005b261ecSmrg			continue;
153105b261ecSmrg		    if (dev->grab && SameClient(dev->grab, client))
153205b261ecSmrg			dev->sync.state = THAWED;
153305b261ecSmrg		    if (dev->sync.other && SameClient(dev->sync.other, client))
153405b261ecSmrg			dev->sync.other = NullGrab;
153505b261ecSmrg		}
153605b261ecSmrg		ComputeFreezes();
153705b261ecSmrg	    }
153805b261ecSmrg	    break;
153905b261ecSmrg    }
154005b261ecSmrg}
154105b261ecSmrg
154205b261ecSmrg/**
154305b261ecSmrg * Server-side protocol handling for AllowEvents request.
154405b261ecSmrg *
154505b261ecSmrg * Release some events from a frozen device. Only applicable for core devices.
154605b261ecSmrg */
154705b261ecSmrgint
154805b261ecSmrgProcAllowEvents(ClientPtr client)
154905b261ecSmrg{
155005b261ecSmrg    TimeStamp		time;
155105b261ecSmrg    DeviceIntPtr	mouse = inputInfo.pointer;
155205b261ecSmrg    DeviceIntPtr	keybd = inputInfo.keyboard;
155305b261ecSmrg    REQUEST(xAllowEventsReq);
155405b261ecSmrg
155505b261ecSmrg    REQUEST_SIZE_MATCH(xAllowEventsReq);
155605b261ecSmrg    time = ClientTimeToServerTime(stuff->time);
155705b261ecSmrg    switch (stuff->mode)
155805b261ecSmrg    {
155905b261ecSmrg	case ReplayPointer:
156005b261ecSmrg	    AllowSome(client, time, mouse, NOT_GRABBED);
156105b261ecSmrg	    break;
156205b261ecSmrg	case SyncPointer:
156305b261ecSmrg	    AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
156405b261ecSmrg	    break;
156505b261ecSmrg	case AsyncPointer:
156605b261ecSmrg	    AllowSome(client, time, mouse, THAWED);
156705b261ecSmrg	    break;
156805b261ecSmrg	case ReplayKeyboard:
156905b261ecSmrg	    AllowSome(client, time, keybd, NOT_GRABBED);
157005b261ecSmrg	    break;
157105b261ecSmrg	case SyncKeyboard:
157205b261ecSmrg	    AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
157305b261ecSmrg	    break;
157405b261ecSmrg	case AsyncKeyboard:
157505b261ecSmrg	    AllowSome(client, time, keybd, THAWED);
157605b261ecSmrg	    break;
157705b261ecSmrg	case SyncBoth:
157805b261ecSmrg	    AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
157905b261ecSmrg	    break;
158005b261ecSmrg	case AsyncBoth:
158105b261ecSmrg	    AllowSome(client, time, keybd, THAWED_BOTH);
158205b261ecSmrg	    break;
158305b261ecSmrg	default:
158405b261ecSmrg	    client->errorValue = stuff->mode;
158505b261ecSmrg	    return BadValue;
158605b261ecSmrg    }
158705b261ecSmrg    return Success;
158805b261ecSmrg}
158905b261ecSmrg
159005b261ecSmrg/**
159105b261ecSmrg * Deactivate grabs from any device that has been grabbed by the client.
159205b261ecSmrg */
159305b261ecSmrgvoid
159405b261ecSmrgReleaseActiveGrabs(ClientPtr client)
159505b261ecSmrg{
159605b261ecSmrg    DeviceIntPtr dev;
159705b261ecSmrg    Bool    done;
159805b261ecSmrg
159905b261ecSmrg    /* XXX CloseDownClient should remove passive grabs before
160005b261ecSmrg     * releasing active grabs.
160105b261ecSmrg     */
160205b261ecSmrg    do {
160305b261ecSmrg    	done = TRUE;
160405b261ecSmrg    	for (dev = inputInfo.devices; dev; dev = dev->next)
160505b261ecSmrg    	{
160605b261ecSmrg	    if (dev->grab && SameClient(dev->grab, client))
160705b261ecSmrg	    {
160805b261ecSmrg	    	(*dev->DeactivateGrab)(dev);
160905b261ecSmrg	    	done = FALSE;
161005b261ecSmrg	    }
161105b261ecSmrg    	}
161205b261ecSmrg    } while (!done);
161305b261ecSmrg}
161405b261ecSmrg
161505b261ecSmrg/**************************************************************************
161605b261ecSmrg *            The following procedures deal with delivering events        *
161705b261ecSmrg **************************************************************************/
161805b261ecSmrg
161905b261ecSmrg/**
162005b261ecSmrg * Deliver the given events to the given client.
162105b261ecSmrg *
162205b261ecSmrg * More than one event may be delivered at a time. This is the case with
162305b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events.
162405b261ecSmrg *
162505b261ecSmrg * TryClientEvents() is the last station before actually writing the events to
162605b261ecSmrg * the socket. Anything that is not filtered here, will get delivered to the
162705b261ecSmrg * client.
162805b261ecSmrg * An event is only delivered if
162905b261ecSmrg *   - mask and filter match up.
163005b261ecSmrg *   - no other client has a grab on the device that caused the event.
163105b261ecSmrg *
163205b261ecSmrg *
163305b261ecSmrg * @param client The target client to deliver to.
163405b261ecSmrg * @param pEvents The events to be delivered.
163505b261ecSmrg * @param count Number of elements in pEvents.
163605b261ecSmrg * @param mask Event mask as set by the window.
163705b261ecSmrg * @param filter Mask based on event type.
163805b261ecSmrg * @param grab Possible grab on the device that caused the event.
163905b261ecSmrg *
164005b261ecSmrg * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
164105b261ecSmrg * client.
164205b261ecSmrg */
164305b261ecSmrg_X_EXPORT int
164405b261ecSmrgTryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask,
164505b261ecSmrg                 Mask filter, GrabPtr grab)
164605b261ecSmrg{
164705b261ecSmrg    int i;
164805b261ecSmrg    int type;
164905b261ecSmrg
165005b261ecSmrg#ifdef DEBUG_EVENTS
165105b261ecSmrg    ErrorF("Event([%d, %d], mask=0x%x), client=%d",
165205b261ecSmrg	pEvents->u.u.type, pEvents->u.u.detail, mask, client->index);
165305b261ecSmrg#endif
165405b261ecSmrg    if ((client) && (client != serverClient) && (!client->clientGone) &&
165505b261ecSmrg	((filter == CantBeFiltered) || (mask & filter)))
165605b261ecSmrg    {
165705b261ecSmrg	if (grab && !SameClient(grab, client))
165805b261ecSmrg	    return -1; /* don't send, but notify caller */
165905b261ecSmrg	type = pEvents->u.u.type;
166005b261ecSmrg	if (type == MotionNotify)
166105b261ecSmrg	{
166205b261ecSmrg	    if (mask & PointerMotionHintMask)
166305b261ecSmrg	    {
166405b261ecSmrg		if (WID(inputInfo.pointer->valuator->motionHintWindow) ==
166505b261ecSmrg		    pEvents->u.keyButtonPointer.event)
166605b261ecSmrg		{
166705b261ecSmrg#ifdef DEBUG_EVENTS
166805b261ecSmrg		    ErrorF("\n");
166905b261ecSmrg	    ErrorF("motionHintWindow == keyButtonPointer.event\n");
167005b261ecSmrg#endif
167105b261ecSmrg		    return 1; /* don't send, but pretend we did */
167205b261ecSmrg		}
167305b261ecSmrg		pEvents->u.u.detail = NotifyHint;
167405b261ecSmrg	    }
167505b261ecSmrg	    else
167605b261ecSmrg	    {
167705b261ecSmrg		pEvents->u.u.detail = NotifyNormal;
167805b261ecSmrg	    }
167905b261ecSmrg	}
168005b261ecSmrg#ifdef XINPUT
168105b261ecSmrg	else
168205b261ecSmrg	{
168305b261ecSmrg	    if ((type == DeviceMotionNotify) &&
168405b261ecSmrg		MaybeSendDeviceMotionNotifyHint
168505b261ecSmrg			((deviceKeyButtonPointer*)pEvents, mask) != 0)
168605b261ecSmrg		return 1;
168705b261ecSmrg	}
168805b261ecSmrg#endif
168905b261ecSmrg	type &= 0177;
169005b261ecSmrg	if (type != KeymapNotify)
169105b261ecSmrg	{
169205b261ecSmrg	    /* all extension events must have a sequence number */
169305b261ecSmrg	    for (i = 0; i < count; i++)
169405b261ecSmrg		pEvents[i].u.u.sequenceNumber = client->sequence;
169505b261ecSmrg	}
169605b261ecSmrg
169705b261ecSmrg	if (BitIsOn(criticalEvents, type))
169805b261ecSmrg	{
169905b261ecSmrg#ifdef SMART_SCHEDULE
170005b261ecSmrg	    if (client->smart_priority < SMART_MAX_PRIORITY)
170105b261ecSmrg		client->smart_priority++;
170205b261ecSmrg#endif
170305b261ecSmrg	    SetCriticalOutputPending();
170405b261ecSmrg	}
170505b261ecSmrg
170605b261ecSmrg	WriteEventsToClient(client, count, pEvents);
170705b261ecSmrg#ifdef DEBUG_EVENTS
170805b261ecSmrg	ErrorF(  " delivered\n");
170905b261ecSmrg#endif
171005b261ecSmrg	return 1;
171105b261ecSmrg    }
171205b261ecSmrg    else
171305b261ecSmrg    {
171405b261ecSmrg#ifdef DEBUG_EVENTS
171505b261ecSmrg	ErrorF("\n");
171605b261ecSmrg#endif
171705b261ecSmrg	return 0;
171805b261ecSmrg    }
171905b261ecSmrg}
172005b261ecSmrg
172105b261ecSmrg/**
172205b261ecSmrg * Deliver events to a window. At this point, we do not yet know if the event
172305b261ecSmrg * actually needs to be delivered. May activate a grab if the event is a
172405b261ecSmrg * button press.
172505b261ecSmrg *
172605b261ecSmrg * More than one event may be delivered at a time. This is the case with
172705b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events.
172805b261ecSmrg *
172905b261ecSmrg * @param pWin The window that would get the event.
173005b261ecSmrg * @param pEvents The events to be delivered.
173105b261ecSmrg * @param count Number of elements in pEvents.
173205b261ecSmrg * @param filter Mask based on event type.
173305b261ecSmrg * @param grab Possible grab on the device that caused the event.
173405b261ecSmrg * @param mskidx Mask index, depending on device that caused event.
173505b261ecSmrg *
173605b261ecSmrg * @return Number of events delivered to various clients.
173705b261ecSmrg */
173805b261ecSmrgint
173905b261ecSmrgDeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count,
174005b261ecSmrg                      Mask filter, GrabPtr grab, int mskidx)
174105b261ecSmrg{
174205b261ecSmrg    int deliveries = 0, nondeliveries = 0;
174305b261ecSmrg    int attempt;
174405b261ecSmrg    InputClients *other;
174505b261ecSmrg    ClientPtr client = NullClient;
174605b261ecSmrg    Mask deliveryMask = 0; /* If a grab occurs due to a button press, then
174705b261ecSmrg		              this mask is the mask of the grab. */
174805b261ecSmrg    int type = pEvents->u.u.type;
174905b261ecSmrg
175005b261ecSmrg    /* CantBeFiltered means only window owner gets the event */
175105b261ecSmrg    if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE))
175205b261ecSmrg    {
175305b261ecSmrg	/* if nobody ever wants to see this event, skip some work */
175405b261ecSmrg	if (filter != CantBeFiltered &&
175505b261ecSmrg	    !((wOtherEventMasks(pWin)|pWin->eventMask) & filter))
175605b261ecSmrg	    return 0;
175705b261ecSmrg	if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count,
175805b261ecSmrg				      pWin->eventMask, filter, grab)) )
175905b261ecSmrg	{
176005b261ecSmrg	    if (attempt > 0)
176105b261ecSmrg	    {
176205b261ecSmrg		deliveries++;
176305b261ecSmrg		client = wClient(pWin);
176405b261ecSmrg		deliveryMask = pWin->eventMask;
176505b261ecSmrg	    } else
176605b261ecSmrg		nondeliveries--;
176705b261ecSmrg	}
176805b261ecSmrg    }
176905b261ecSmrg    if (filter != CantBeFiltered)
177005b261ecSmrg    {
177105b261ecSmrg	if (type & EXTENSION_EVENT_BASE)
177205b261ecSmrg	{
177305b261ecSmrg	    OtherInputMasks *inputMasks;
177405b261ecSmrg
177505b261ecSmrg	    inputMasks = wOtherInputMasks(pWin);
177605b261ecSmrg	    if (!inputMasks ||
177705b261ecSmrg		!(inputMasks->inputEvents[mskidx] & filter))
177805b261ecSmrg		return 0;
177905b261ecSmrg	    other = inputMasks->inputClients;
178005b261ecSmrg	}
178105b261ecSmrg	else
178205b261ecSmrg	    other = (InputClients *)wOtherClients(pWin);
178305b261ecSmrg	for (; other; other = other->next)
178405b261ecSmrg	{
178505b261ecSmrg	    if ( (attempt = TryClientEvents(rClient(other), pEvents, count,
178605b261ecSmrg					  other->mask[mskidx], filter, grab)) )
178705b261ecSmrg	    {
178805b261ecSmrg		if (attempt > 0)
178905b261ecSmrg		{
179005b261ecSmrg		    deliveries++;
179105b261ecSmrg		    client = rClient(other);
179205b261ecSmrg		    deliveryMask = other->mask[mskidx];
179305b261ecSmrg		} else
179405b261ecSmrg		    nondeliveries--;
179505b261ecSmrg	    }
179605b261ecSmrg	}
179705b261ecSmrg    }
179805b261ecSmrg    if ((type == ButtonPress) && deliveries && (!grab))
179905b261ecSmrg    {
180005b261ecSmrg	GrabRec tempGrab;
180105b261ecSmrg
180205b261ecSmrg	tempGrab.device = inputInfo.pointer;
180305b261ecSmrg	tempGrab.resource = client->clientAsMask;
180405b261ecSmrg	tempGrab.window = pWin;
180505b261ecSmrg	tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
180605b261ecSmrg	tempGrab.eventMask = deliveryMask;
180705b261ecSmrg	tempGrab.keyboardMode = GrabModeAsync;
180805b261ecSmrg	tempGrab.pointerMode = GrabModeAsync;
180905b261ecSmrg	tempGrab.confineTo = NullWindow;
181005b261ecSmrg	tempGrab.cursor = NullCursor;
181105b261ecSmrg	(*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab,
181205b261ecSmrg					   currentTime, TRUE);
181305b261ecSmrg    }
181405b261ecSmrg    else if ((type == MotionNotify) && deliveries)
181505b261ecSmrg	inputInfo.pointer->valuator->motionHintWindow = pWin;
181605b261ecSmrg#ifdef XINPUT
181705b261ecSmrg    else
181805b261ecSmrg    {
181905b261ecSmrg	if (((type == DeviceMotionNotify)
182005b261ecSmrg#ifdef XKB
182105b261ecSmrg	     || (type == DeviceButtonPress)
182205b261ecSmrg#endif
182305b261ecSmrg	    ) && deliveries)
182405b261ecSmrg	    CheckDeviceGrabAndHintWindow (pWin, type,
182505b261ecSmrg					  (deviceKeyButtonPointer*) pEvents,
182605b261ecSmrg					  grab, client, deliveryMask);
182705b261ecSmrg    }
182805b261ecSmrg#endif
182905b261ecSmrg    if (deliveries)
183005b261ecSmrg	return deliveries;
183105b261ecSmrg    return nondeliveries;
183205b261ecSmrg}
183305b261ecSmrg
183405b261ecSmrg/* If the event goes to dontClient, don't send it and return 0.  if
183505b261ecSmrg   send works,  return 1 or if send didn't work, return 2.
183605b261ecSmrg   Only works for core events.
183705b261ecSmrg*/
183805b261ecSmrg
183905b261ecSmrg#ifdef PANORAMIX
184005b261ecSmrgstatic int
184105b261ecSmrgXineramaTryClientEventsResult(
184205b261ecSmrg    ClientPtr client,
184305b261ecSmrg    GrabPtr grab,
184405b261ecSmrg    Mask mask,
184505b261ecSmrg    Mask filter
184605b261ecSmrg){
184705b261ecSmrg    if ((client) && (client != serverClient) && (!client->clientGone) &&
184805b261ecSmrg        ((filter == CantBeFiltered) || (mask & filter)))
184905b261ecSmrg    {
185005b261ecSmrg        if (grab && !SameClient(grab, client)) return -1;
185105b261ecSmrg	else return 1;
185205b261ecSmrg    }
185305b261ecSmrg    return 0;
185405b261ecSmrg}
185505b261ecSmrg#endif
185605b261ecSmrg
185705b261ecSmrg/**
185805b261ecSmrg * Try to deliver events to the interested parties.
185905b261ecSmrg *
186005b261ecSmrg * @param pWin The window that would get the event.
186105b261ecSmrg * @param pEvents The events to be delivered.
186205b261ecSmrg * @param count Number of elements in pEvents.
186305b261ecSmrg * @param filter Mask based on event type.
186405b261ecSmrg * @param dontClient Don't deliver to the dontClient.
186505b261ecSmrg */
186605b261ecSmrgint
186705b261ecSmrgMaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
186805b261ecSmrg                           int count, Mask filter, ClientPtr dontClient)
186905b261ecSmrg{
187005b261ecSmrg    OtherClients *other;
187105b261ecSmrg
187205b261ecSmrg
187305b261ecSmrg    if (pWin->eventMask & filter)
187405b261ecSmrg    {
187505b261ecSmrg        if (wClient(pWin) == dontClient)
187605b261ecSmrg	    return 0;
187705b261ecSmrg#ifdef PANORAMIX
187805b261ecSmrg	if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
187905b261ecSmrg	    return XineramaTryClientEventsResult(
188005b261ecSmrg			wClient(pWin), NullGrab, pWin->eventMask, filter);
188105b261ecSmrg#endif
188205b261ecSmrg	return TryClientEvents(wClient(pWin), pEvents, count,
188305b261ecSmrg			       pWin->eventMask, filter, NullGrab);
188405b261ecSmrg    }
188505b261ecSmrg    for (other = wOtherClients(pWin); other; other = other->next)
188605b261ecSmrg    {
188705b261ecSmrg	if (other->mask & filter)
188805b261ecSmrg	{
188905b261ecSmrg            if (SameClient(other, dontClient))
189005b261ecSmrg		return 0;
189105b261ecSmrg#ifdef PANORAMIX
189205b261ecSmrg	    if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
189305b261ecSmrg	      return XineramaTryClientEventsResult(
189405b261ecSmrg			rClient(other), NullGrab, other->mask, filter);
189505b261ecSmrg#endif
189605b261ecSmrg	    return TryClientEvents(rClient(other), pEvents, count,
189705b261ecSmrg				   other->mask, filter, NullGrab);
189805b261ecSmrg	}
189905b261ecSmrg    }
190005b261ecSmrg    return 2;
190105b261ecSmrg}
190205b261ecSmrg
190305b261ecSmrg/**
190405b261ecSmrg * Adjust event fields to comply with the window properties.
190505b261ecSmrg *
190605b261ecSmrg * @param xE Event to be modified in place
190705b261ecSmrg * @param pWin The window to get the information from.
190805b261ecSmrg * @param child Child window setting for event (if applicable)
190905b261ecSmrg * @param calcChild If True, calculate the child window.
191005b261ecSmrg */
191105b261ecSmrgstatic void
191205b261ecSmrgFixUpEventFromWindow(
191305b261ecSmrg    xEvent *xE,
191405b261ecSmrg    WindowPtr pWin,
191505b261ecSmrg    Window child,
191605b261ecSmrg    Bool calcChild)
191705b261ecSmrg{
191805b261ecSmrg    if (calcChild)
191905b261ecSmrg    {
192005b261ecSmrg        WindowPtr w=spriteTrace[spriteTraceGood-1];
192105b261ecSmrg	/* If the search ends up past the root should the child field be
192205b261ecSmrg	 	set to none or should the value in the argument be passed
192305b261ecSmrg		through. It probably doesn't matter since everyone calls
192405b261ecSmrg		this function with child == None anyway. */
192505b261ecSmrg
192605b261ecSmrg        while (w)
192705b261ecSmrg        {
192805b261ecSmrg            /* If the source window is same as event window, child should be
192905b261ecSmrg		none.  Don't bother going all all the way back to the root. */
193005b261ecSmrg
193105b261ecSmrg 	    if (w == pWin)
193205b261ecSmrg	    {
193305b261ecSmrg   		child = None;
193405b261ecSmrg 		break;
193505b261ecSmrg	    }
193605b261ecSmrg
193705b261ecSmrg	    if (w->parent == pWin)
193805b261ecSmrg	    {
193905b261ecSmrg		child = w->drawable.id;
194005b261ecSmrg		break;
194105b261ecSmrg            }
194205b261ecSmrg 	    w = w->parent;
194305b261ecSmrg        }
194405b261ecSmrg    }
194505b261ecSmrg    XE_KBPTR.root = ROOT->drawable.id;
194605b261ecSmrg    XE_KBPTR.event = pWin->drawable.id;
194705b261ecSmrg    if (sprite.hot.pScreen == pWin->drawable.pScreen)
194805b261ecSmrg    {
194905b261ecSmrg	XE_KBPTR.sameScreen = xTrue;
195005b261ecSmrg	XE_KBPTR.child = child;
195105b261ecSmrg	XE_KBPTR.eventX =
195205b261ecSmrg	XE_KBPTR.rootX - pWin->drawable.x;
195305b261ecSmrg	XE_KBPTR.eventY =
195405b261ecSmrg	XE_KBPTR.rootY - pWin->drawable.y;
195505b261ecSmrg    }
195605b261ecSmrg    else
195705b261ecSmrg    {
195805b261ecSmrg	XE_KBPTR.sameScreen = xFalse;
195905b261ecSmrg	XE_KBPTR.child = None;
196005b261ecSmrg	XE_KBPTR.eventX = 0;
196105b261ecSmrg	XE_KBPTR.eventY = 0;
196205b261ecSmrg    }
196305b261ecSmrg}
196405b261ecSmrg
196505b261ecSmrg/**
196605b261ecSmrg * Deliver events caused by input devices. Called for all core input events
196705b261ecSmrg * and XI events. No filtering of events happens before DeliverDeviceEvents(),
196805b261ecSmrg * it will be called for any event that comes out of the event queue.
196905b261ecSmrg *
197005b261ecSmrg * For all core events, dev is either inputInfo.pointer or inputInfo.keyboard.
197105b261ecSmrg * For all extension events, dev is the device that caused the event.
197205b261ecSmrg *
197305b261ecSmrg * @param pWin Window to deliver event to.
197405b261ecSmrg * @param xE Events to deliver.
197505b261ecSmrg * @param grab Possible grab on a device.
197605b261ecSmrg * @param stopAt Don't recurse up to the root window.
197705b261ecSmrg * @param dev The device that is responsible for the event.
197805b261ecSmrg * @param count number of events in xE.
197905b261ecSmrg *
198005b261ecSmrg */
198105b261ecSmrgint
198205b261ecSmrgDeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab,
198305b261ecSmrg                    WindowPtr stopAt, DeviceIntPtr dev, int count)
198405b261ecSmrg{
198505b261ecSmrg    Window child = None;
198605b261ecSmrg    int type = xE->u.u.type;
198705b261ecSmrg    Mask filter = filters[type];
198805b261ecSmrg    int deliveries = 0;
198905b261ecSmrg
199005b261ecSmrg    if (type & EXTENSION_EVENT_BASE)
199105b261ecSmrg    {
199205b261ecSmrg	OtherInputMasks *inputMasks;
199305b261ecSmrg	int mskidx = dev->id;
199405b261ecSmrg
199505b261ecSmrg	inputMasks = wOtherInputMasks(pWin);
199605b261ecSmrg	if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx]))
199705b261ecSmrg	    return 0;
199805b261ecSmrg	while (pWin)
199905b261ecSmrg	{
200005b261ecSmrg	    if (inputMasks && (inputMasks->inputEvents[mskidx] & filter))
200105b261ecSmrg	    {
200205b261ecSmrg		FixUpEventFromWindow(xE, pWin, child, FALSE);
200305b261ecSmrg		deliveries = DeliverEventsToWindow(pWin, xE, count, filter,
200405b261ecSmrg						   grab, mskidx);
200505b261ecSmrg		if (deliveries > 0)
200605b261ecSmrg		    return deliveries;
200705b261ecSmrg	    }
200805b261ecSmrg	    if ((deliveries < 0) ||
200905b261ecSmrg		(pWin == stopAt) ||
201005b261ecSmrg		(inputMasks &&
201105b261ecSmrg		 (filter & inputMasks->dontPropagateMask[mskidx])))
201205b261ecSmrg		return 0;
201305b261ecSmrg	    child = pWin->drawable.id;
201405b261ecSmrg	    pWin = pWin->parent;
201505b261ecSmrg	    if (pWin)
201605b261ecSmrg		inputMasks = wOtherInputMasks(pWin);
201705b261ecSmrg	}
201805b261ecSmrg    }
201905b261ecSmrg    else
202005b261ecSmrg    {
202105b261ecSmrg	if (!(filter & pWin->deliverableEvents))
202205b261ecSmrg	    return 0;
202305b261ecSmrg	while (pWin)
202405b261ecSmrg	{
202505b261ecSmrg	    if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter)
202605b261ecSmrg	    {
202705b261ecSmrg		FixUpEventFromWindow(xE, pWin, child, FALSE);
202805b261ecSmrg		deliveries = DeliverEventsToWindow(pWin, xE, count, filter,
202905b261ecSmrg						   grab, 0);
203005b261ecSmrg		if (deliveries > 0)
203105b261ecSmrg		    return deliveries;
203205b261ecSmrg	    }
203305b261ecSmrg	    if ((deliveries < 0) ||
203405b261ecSmrg		(pWin == stopAt) ||
203505b261ecSmrg		(filter & wDontPropagateMask(pWin)))
203605b261ecSmrg		return 0;
203705b261ecSmrg	    child = pWin->drawable.id;
203805b261ecSmrg	    pWin = pWin->parent;
203905b261ecSmrg	}
204005b261ecSmrg    }
204105b261ecSmrg    return 0;
204205b261ecSmrg}
204305b261ecSmrg
204405b261ecSmrg/**
204505b261ecSmrg * Deliver event to a window and it's immediate parent. Used for most window
204605b261ecSmrg * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
204705b261ecSmrg * propagate up the tree or extension events
204805b261ecSmrg *
204905b261ecSmrg * In case of a ReparentNotify event, the event will be delivered to the
205005b261ecSmrg * otherParent as well.
205105b261ecSmrg *
205205b261ecSmrg * @param pWin Window to deliver events to.
205305b261ecSmrg * @param xE Events to deliver.
205405b261ecSmrg * @param count number of events in xE.
205505b261ecSmrg * @param otherParent Used for ReparentNotify events.
205605b261ecSmrg */
205705b261ecSmrg_X_EXPORT int
205805b261ecSmrgDeliverEvents(WindowPtr pWin, xEvent *xE, int count,
205905b261ecSmrg              WindowPtr otherParent)
206005b261ecSmrg{
206105b261ecSmrg    Mask filter;
206205b261ecSmrg    int     deliveries;
206305b261ecSmrg
206405b261ecSmrg#ifdef PANORAMIX
206505b261ecSmrg    if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
206605b261ecSmrg	return count;
206705b261ecSmrg#endif
206805b261ecSmrg
206905b261ecSmrg    if (!count)
207005b261ecSmrg	return 0;
207105b261ecSmrg    filter = filters[xE->u.u.type];
207205b261ecSmrg    if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify))
207305b261ecSmrg	xE->u.destroyNotify.event = pWin->drawable.id;
207405b261ecSmrg    if (filter != StructureAndSubMask)
207505b261ecSmrg	return DeliverEventsToWindow(pWin, xE, count, filter, NullGrab, 0);
207605b261ecSmrg    deliveries = DeliverEventsToWindow(pWin, xE, count, StructureNotifyMask,
207705b261ecSmrg				       NullGrab, 0);
207805b261ecSmrg    if (pWin->parent)
207905b261ecSmrg    {
208005b261ecSmrg	xE->u.destroyNotify.event = pWin->parent->drawable.id;
208105b261ecSmrg	deliveries += DeliverEventsToWindow(pWin->parent, xE, count,
208205b261ecSmrg					    SubstructureNotifyMask, NullGrab,
208305b261ecSmrg					    0);
208405b261ecSmrg	if (xE->u.u.type == ReparentNotify)
208505b261ecSmrg	{
208605b261ecSmrg	    xE->u.destroyNotify.event = otherParent->drawable.id;
208705b261ecSmrg	    deliveries += DeliverEventsToWindow(otherParent, xE, count,
208805b261ecSmrg						SubstructureNotifyMask,
208905b261ecSmrg						NullGrab, 0);
209005b261ecSmrg	}
209105b261ecSmrg    }
209205b261ecSmrg    return deliveries;
209305b261ecSmrg}
209405b261ecSmrg
209505b261ecSmrg
209605b261ecSmrgstatic Bool
209705b261ecSmrgPointInBorderSize(WindowPtr pWin, int x, int y)
209805b261ecSmrg{
209905b261ecSmrg    BoxRec box;
210005b261ecSmrg
210105b261ecSmrg    if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box))
210205b261ecSmrg	return TRUE;
210305b261ecSmrg
210405b261ecSmrg#ifdef PANORAMIX
210505b261ecSmrg    if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) {
210605b261ecSmrg	int i;
210705b261ecSmrg
210805b261ecSmrg	for(i = 1; i < PanoramiXNumScreens; i++) {
210905b261ecSmrg	   if(POINT_IN_REGION(sprite.screen,
211005b261ecSmrg			&sprite.windows[i]->borderSize,
211105b261ecSmrg			x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x,
211205b261ecSmrg			y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y,
211305b261ecSmrg			&box))
211405b261ecSmrg		return TRUE;
211505b261ecSmrg	}
211605b261ecSmrg    }
211705b261ecSmrg#endif
211805b261ecSmrg    return FALSE;
211905b261ecSmrg}
212005b261ecSmrg
212105b261ecSmrg/**
212205b261ecSmrg * Traversed from the root window to the window at the position x/y. While
212305b261ecSmrg * traversing, it sets up the traversal history in the spriteTrace array.
212405b261ecSmrg * After completing, the spriteTrace history is set in the following way:
212505b261ecSmrg *   spriteTrace[0] ... root window
212605b261ecSmrg *   spriteTrace[1] ... top level window that encloses x/y
212705b261ecSmrg *       ...
212805b261ecSmrg *   spriteTrace[spriteTraceGood - 1] ... window at x/y
212905b261ecSmrg *
213005b261ecSmrg * @returns the window at the given coordinates.
213105b261ecSmrg */
213205b261ecSmrgstatic WindowPtr
213305b261ecSmrgXYToWindow(int x, int y)
213405b261ecSmrg{
213505b261ecSmrg    WindowPtr  pWin;
213605b261ecSmrg    BoxRec		box;
213705b261ecSmrg
213805b261ecSmrg    spriteTraceGood = 1;	/* root window still there */
213905b261ecSmrg    pWin = ROOT->firstChild;
214005b261ecSmrg    while (pWin)
214105b261ecSmrg    {
214205b261ecSmrg	if ((pWin->mapped) &&
214305b261ecSmrg	    (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
214405b261ecSmrg	    (x < pWin->drawable.x + (int)pWin->drawable.width +
214505b261ecSmrg	     wBorderWidth(pWin)) &&
214605b261ecSmrg	    (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
214705b261ecSmrg	    (y < pWin->drawable.y + (int)pWin->drawable.height +
214805b261ecSmrg	     wBorderWidth (pWin))
214905b261ecSmrg#ifdef SHAPE
215005b261ecSmrg	    /* When a window is shaped, a further check
215105b261ecSmrg	     * is made to see if the point is inside
215205b261ecSmrg	     * borderSize
215305b261ecSmrg	     */
215405b261ecSmrg	    && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
215505b261ecSmrg	    && (!wInputShape(pWin) ||
215605b261ecSmrg		POINT_IN_REGION(pWin->drawable.pScreen,
215705b261ecSmrg				wInputShape(pWin),
215805b261ecSmrg				x - pWin->drawable.x,
215905b261ecSmrg				y - pWin->drawable.y, &box))
216005b261ecSmrg#endif
216105b261ecSmrg	    )
216205b261ecSmrg	{
216305b261ecSmrg	    if (spriteTraceGood >= spriteTraceSize)
216405b261ecSmrg	    {
216505b261ecSmrg		spriteTraceSize += 10;
216605b261ecSmrg		Must_have_memory = TRUE; /* XXX */
216705b261ecSmrg		spriteTrace = (WindowPtr *)xrealloc(
216805b261ecSmrg		    spriteTrace, spriteTraceSize*sizeof(WindowPtr));
216905b261ecSmrg		Must_have_memory = FALSE; /* XXX */
217005b261ecSmrg	    }
217105b261ecSmrg	    spriteTrace[spriteTraceGood++] = pWin;
217205b261ecSmrg	    pWin = pWin->firstChild;
217305b261ecSmrg	}
217405b261ecSmrg	else
217505b261ecSmrg	    pWin = pWin->nextSib;
217605b261ecSmrg    }
217705b261ecSmrg    return spriteTrace[spriteTraceGood-1];
217805b261ecSmrg}
217905b261ecSmrg
218005b261ecSmrg/**
218105b261ecSmrg * Update the sprite coordinates based on the event. Update the cursor
218205b261ecSmrg * position, then update the event with the new coordinates that may have been
218305b261ecSmrg * changed. If the window underneath the sprite has changed, change to new
218405b261ecSmrg * cursor and send enter/leave events.
218505b261ecSmrg */
218605b261ecSmrgstatic Bool
218705b261ecSmrgCheckMotion(xEvent *xE)
218805b261ecSmrg{
218905b261ecSmrg    WindowPtr prevSpriteWin = sprite.win;
219005b261ecSmrg
219105b261ecSmrg#ifdef PANORAMIX
219205b261ecSmrg    if(!noPanoramiXExtension)
219305b261ecSmrg	return XineramaCheckMotion(xE);
219405b261ecSmrg#endif
219505b261ecSmrg
219605b261ecSmrg    if (xE && !syncEvents.playingEvents)
219705b261ecSmrg    {
219805b261ecSmrg	if (sprite.hot.pScreen != sprite.hotPhys.pScreen)
219905b261ecSmrg	{
220005b261ecSmrg	    sprite.hot.pScreen = sprite.hotPhys.pScreen;
220105b261ecSmrg	    ROOT = WindowTable[sprite.hot.pScreen->myNum];
220205b261ecSmrg	}
220305b261ecSmrg	sprite.hot.x = XE_KBPTR.rootX;
220405b261ecSmrg	sprite.hot.y = XE_KBPTR.rootY;
220505b261ecSmrg	if (sprite.hot.x < sprite.physLimits.x1)
220605b261ecSmrg	    sprite.hot.x = sprite.physLimits.x1;
220705b261ecSmrg	else if (sprite.hot.x >= sprite.physLimits.x2)
220805b261ecSmrg	    sprite.hot.x = sprite.physLimits.x2 - 1;
220905b261ecSmrg	if (sprite.hot.y < sprite.physLimits.y1)
221005b261ecSmrg	    sprite.hot.y = sprite.physLimits.y1;
221105b261ecSmrg	else if (sprite.hot.y >= sprite.physLimits.y2)
221205b261ecSmrg	    sprite.hot.y = sprite.physLimits.y2 - 1;
221305b261ecSmrg#ifdef SHAPE
221405b261ecSmrg	if (sprite.hotShape)
221505b261ecSmrg	    ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y);
221605b261ecSmrg#endif
221705b261ecSmrg#ifdef XEVIE
221805b261ecSmrg        xeviehot.x = sprite.hot.x;
221905b261ecSmrg        xeviehot.y = sprite.hot.y;
222005b261ecSmrg#endif
222105b261ecSmrg	sprite.hotPhys = sprite.hot;
222205b261ecSmrg	if ((sprite.hotPhys.x != XE_KBPTR.rootX) ||
222305b261ecSmrg	    (sprite.hotPhys.y != XE_KBPTR.rootY))
222405b261ecSmrg	{
222505b261ecSmrg	    (*sprite.hotPhys.pScreen->SetCursorPosition)(
222605b261ecSmrg		sprite.hotPhys.pScreen,
222705b261ecSmrg		sprite.hotPhys.x, sprite.hotPhys.y, FALSE);
222805b261ecSmrg	}
222905b261ecSmrg	XE_KBPTR.rootX = sprite.hot.x;
223005b261ecSmrg	XE_KBPTR.rootY = sprite.hot.y;
223105b261ecSmrg    }
223205b261ecSmrg
223305b261ecSmrg#ifdef XEVIE
223405b261ecSmrg    xeviewin =
223505b261ecSmrg#endif
223605b261ecSmrg    sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y);
223705b261ecSmrg#ifdef notyet
223805b261ecSmrg    if (!(sprite.win->deliverableEvents &
223905b261ecSmrg	  Motion_Filter(inputInfo.pointer->button))
224005b261ecSmrg	!syncEvents.playingEvents)
224105b261ecSmrg    {
224205b261ecSmrg	/* XXX Do PointerNonInterestBox here */
224305b261ecSmrg    }
224405b261ecSmrg#endif
224505b261ecSmrg    if (sprite.win != prevSpriteWin)
224605b261ecSmrg    {
224705b261ecSmrg	if (prevSpriteWin != NullWindow) {
224805b261ecSmrg	    if (!xE)
224905b261ecSmrg		UpdateCurrentTimeIf();
225005b261ecSmrg	    DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal);
225105b261ecSmrg	}
225205b261ecSmrg	PostNewCursor();
225305b261ecSmrg        return FALSE;
225405b261ecSmrg    }
225505b261ecSmrg    return TRUE;
225605b261ecSmrg}
225705b261ecSmrg
225805b261ecSmrg/**
225905b261ecSmrg * Windows have restructured, we need to update the sprite position and the
226005b261ecSmrg * sprite's cursor.
226105b261ecSmrg */
226205b261ecSmrg_X_EXPORT void
226305b261ecSmrgWindowsRestructured(void)
226405b261ecSmrg{
226505b261ecSmrg    (void) CheckMotion((xEvent *)NULL);
226605b261ecSmrg}
226705b261ecSmrg
226805b261ecSmrg#ifdef PANORAMIX
226905b261ecSmrg/* This was added to support reconfiguration under Xdmx.  The problem is
227005b261ecSmrg * that if the 0th screen (i.e., WindowTable[0]) is moved to an origin
227105b261ecSmrg * other than 0,0, the information in the private sprite structure must
227205b261ecSmrg * be updated accordingly, or XYToWindow (and other routines) will not
227305b261ecSmrg * compute correctly. */
227405b261ecSmrgvoid ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
227505b261ecSmrg{
227605b261ecSmrg    GrabPtr   grab;
227705b261ecSmrg
227805b261ecSmrg    if (noPanoramiXExtension) return;
227905b261ecSmrg
228005b261ecSmrg    sprite.hot.x        -= xoff;
228105b261ecSmrg    sprite.hot.y        -= yoff;
228205b261ecSmrg
228305b261ecSmrg    sprite.hotPhys.x    -= xoff;
228405b261ecSmrg    sprite.hotPhys.y    -= yoff;
228505b261ecSmrg
228605b261ecSmrg    sprite.hotLimits.x1 -= xoff;
228705b261ecSmrg    sprite.hotLimits.y1 -= yoff;
228805b261ecSmrg    sprite.hotLimits.x2 -= xoff;
228905b261ecSmrg    sprite.hotLimits.y2 -= yoff;
229005b261ecSmrg
229105b261ecSmrg    if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg1))
229205b261ecSmrg        REGION_TRANSLATE(sprite.screen, &sprite.Reg1,    xoff, yoff);
229305b261ecSmrg    if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg2))
229405b261ecSmrg        REGION_TRANSLATE(sprite.screen, &sprite.Reg2,    xoff, yoff);
229505b261ecSmrg
229605b261ecSmrg    /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
229705b261ecSmrg    if ((grab = inputInfo.pointer->grab) && grab->confineTo) {
229805b261ecSmrg	if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
229905b261ecSmrg	    sprite.hotPhys.x = sprite.hotPhys.y = 0;
230005b261ecSmrg	ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
230105b261ecSmrg    } else
230205b261ecSmrg	ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum],
230305b261ecSmrg			      TRUE, FALSE);
230405b261ecSmrg}
230505b261ecSmrg#endif
230605b261ecSmrg
230705b261ecSmrg/**
230805b261ecSmrg * Set the given window to sane values, display the cursor in the center of
230905b261ecSmrg * the screen. Called from main() with the root window on the first screen.
231005b261ecSmrg */
231105b261ecSmrgvoid
231205b261ecSmrgDefineInitialRootWindow(WindowPtr win)
231305b261ecSmrg{
231405b261ecSmrg    ScreenPtr pScreen = win->drawable.pScreen;
231505b261ecSmrg
231605b261ecSmrg    sprite.hotPhys.pScreen = pScreen;
231705b261ecSmrg    sprite.hotPhys.x = pScreen->width / 2;
231805b261ecSmrg    sprite.hotPhys.y = pScreen->height / 2;
231905b261ecSmrg    sprite.hot = sprite.hotPhys;
232005b261ecSmrg    sprite.hotLimits.x2 = pScreen->width;
232105b261ecSmrg    sprite.hotLimits.y2 = pScreen->height;
232205b261ecSmrg#ifdef XEVIE
232305b261ecSmrg    xeviewin =
232405b261ecSmrg#endif
232505b261ecSmrg    sprite.win = win;
232605b261ecSmrg    sprite.current = wCursor (win);
232705b261ecSmrg    sprite.current->refcnt++;
232805b261ecSmrg    spriteTraceGood = 1;
232905b261ecSmrg    ROOT = win;
233005b261ecSmrg    (*pScreen->CursorLimits) (
233105b261ecSmrg	pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits);
233205b261ecSmrg    sprite.confined = FALSE;
233305b261ecSmrg    (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits);
233405b261ecSmrg    (*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE);
233505b261ecSmrg    (*pScreen->DisplayCursor) (pScreen, sprite.current);
233605b261ecSmrg
233705b261ecSmrg#ifdef PANORAMIX
233805b261ecSmrg    if(!noPanoramiXExtension) {
233905b261ecSmrg	sprite.hotLimits.x1 = -panoramiXdataPtr[0].x;
234005b261ecSmrg	sprite.hotLimits.y1 = -panoramiXdataPtr[0].y;
234105b261ecSmrg	sprite.hotLimits.x2 = PanoramiXPixWidth  - panoramiXdataPtr[0].x;
234205b261ecSmrg	sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
234305b261ecSmrg	sprite.physLimits = sprite.hotLimits;
234405b261ecSmrg	sprite.confineWin = NullWindow;
234505b261ecSmrg#ifdef SHAPE
234605b261ecSmrg        sprite.hotShape = NullRegion;
234705b261ecSmrg#endif
234805b261ecSmrg	sprite.screen = pScreen;
234905b261ecSmrg	/* gotta UNINIT these someplace */
235005b261ecSmrg	REGION_NULL(pScreen, &sprite.Reg1);
235105b261ecSmrg	REGION_NULL(pScreen, &sprite.Reg2);
235205b261ecSmrg    }
235305b261ecSmrg#endif
235405b261ecSmrg}
235505b261ecSmrg
235605b261ecSmrg/*
235705b261ecSmrg * This does not take any shortcuts, and even ignores its argument, since
235805b261ecSmrg * it does not happen very often, and one has to walk up the tree since
235905b261ecSmrg * this might be a newly instantiated cursor for an intermediate window
236005b261ecSmrg * between the one the pointer is in and the one that the last cursor was
236105b261ecSmrg * instantiated from.
236205b261ecSmrg */
236305b261ecSmrgvoid
236405b261ecSmrgWindowHasNewCursor(WindowPtr pWin)
236505b261ecSmrg{
236605b261ecSmrg    PostNewCursor();
236705b261ecSmrg}
236805b261ecSmrg
236905b261ecSmrg_X_EXPORT void
237005b261ecSmrgNewCurrentScreen(ScreenPtr newScreen, int x, int y)
237105b261ecSmrg{
237205b261ecSmrg    sprite.hotPhys.x = x;
237305b261ecSmrg    sprite.hotPhys.y = y;
237405b261ecSmrg#ifdef PANORAMIX
237505b261ecSmrg    if(!noPanoramiXExtension) {
237605b261ecSmrg	sprite.hotPhys.x += panoramiXdataPtr[newScreen->myNum].x -
237705b261ecSmrg			    panoramiXdataPtr[0].x;
237805b261ecSmrg	sprite.hotPhys.y += panoramiXdataPtr[newScreen->myNum].y -
237905b261ecSmrg			    panoramiXdataPtr[0].y;
238005b261ecSmrg	if (newScreen != sprite.screen) {
238105b261ecSmrg	    sprite.screen = newScreen;
238205b261ecSmrg	    /* Make sure we tell the DDX to update its copy of the screen */
238305b261ecSmrg	    if(sprite.confineWin)
238405b261ecSmrg		XineramaConfineCursorToWindow(sprite.confineWin, TRUE);
238505b261ecSmrg	    else
238605b261ecSmrg		XineramaConfineCursorToWindow(WindowTable[0], TRUE);
238705b261ecSmrg	    /* if the pointer wasn't confined, the DDX won't get
238805b261ecSmrg	       told of the pointer warp so we reposition it here */
238905b261ecSmrg	    if(!syncEvents.playingEvents)
239005b261ecSmrg		(*sprite.screen->SetCursorPosition)(sprite.screen,
239105b261ecSmrg		    sprite.hotPhys.x + panoramiXdataPtr[0].x -
239205b261ecSmrg			panoramiXdataPtr[sprite.screen->myNum].x,
239305b261ecSmrg		    sprite.hotPhys.y + panoramiXdataPtr[0].y -
239405b261ecSmrg			panoramiXdataPtr[sprite.screen->myNum].y, FALSE);
239505b261ecSmrg	}
239605b261ecSmrg    } else
239705b261ecSmrg#endif
239805b261ecSmrg    if (newScreen != sprite.hotPhys.pScreen)
239905b261ecSmrg	ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE);
240005b261ecSmrg}
240105b261ecSmrg
240205b261ecSmrg#ifdef PANORAMIX
240305b261ecSmrg
240405b261ecSmrgstatic Bool
240505b261ecSmrgXineramaPointInWindowIsVisible(
240605b261ecSmrg    WindowPtr pWin,
240705b261ecSmrg    int x,
240805b261ecSmrg    int y
240905b261ecSmrg)
241005b261ecSmrg{
241105b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
241205b261ecSmrg    BoxRec box;
241305b261ecSmrg    int i, xoff, yoff;
241405b261ecSmrg
241505b261ecSmrg    if (!pWin->realized) return FALSE;
241605b261ecSmrg
241705b261ecSmrg    if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box))
241805b261ecSmrg        return TRUE;
241905b261ecSmrg
242005b261ecSmrg    if(!XineramaSetWindowPntrs(pWin)) return FALSE;
242105b261ecSmrg
242205b261ecSmrg    xoff = x + panoramiXdataPtr[0].x;
242305b261ecSmrg    yoff = y + panoramiXdataPtr[0].y;
242405b261ecSmrg
242505b261ecSmrg    for(i = 1; i < PanoramiXNumScreens; i++) {
242605b261ecSmrg	pWin = sprite.windows[i];
242705b261ecSmrg	pScreen = pWin->drawable.pScreen;
242805b261ecSmrg	x = xoff - panoramiXdataPtr[i].x;
242905b261ecSmrg	y = yoff - panoramiXdataPtr[i].y;
243005b261ecSmrg
243105b261ecSmrg	if(POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)
243205b261ecSmrg	   && (!wInputShape(pWin) ||
243305b261ecSmrg	       POINT_IN_REGION(pWin->drawable.pScreen,
243405b261ecSmrg			       wInputShape(pWin),
243505b261ecSmrg			       x - pWin->drawable.x,
243605b261ecSmrg			       y - pWin->drawable.y, &box)))
243705b261ecSmrg            return TRUE;
243805b261ecSmrg
243905b261ecSmrg    }
244005b261ecSmrg
244105b261ecSmrg    return FALSE;
244205b261ecSmrg}
244305b261ecSmrg
244405b261ecSmrgstatic int
244505b261ecSmrgXineramaWarpPointer(ClientPtr client)
244605b261ecSmrg{
244705b261ecSmrg    WindowPtr	dest = NULL;
244805b261ecSmrg    int		x, y, rc;
244905b261ecSmrg
245005b261ecSmrg    REQUEST(xWarpPointerReq);
245105b261ecSmrg
245205b261ecSmrg
245305b261ecSmrg    if (stuff->dstWid != None) {
245405b261ecSmrg	rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
245505b261ecSmrg	if (rc != Success)
245605b261ecSmrg	    return rc;
245705b261ecSmrg    }
245805b261ecSmrg    x = sprite.hotPhys.x;
245905b261ecSmrg    y = sprite.hotPhys.y;
246005b261ecSmrg
246105b261ecSmrg    if (stuff->srcWid != None)
246205b261ecSmrg    {
246305b261ecSmrg	int     winX, winY;
246405b261ecSmrg 	XID 	winID = stuff->srcWid;
246505b261ecSmrg        WindowPtr source;
246605b261ecSmrg
246705b261ecSmrg	rc = dixLookupWindow(&source, winID, client, DixReadAccess);
246805b261ecSmrg	if (rc != Success)
246905b261ecSmrg	    return rc;
247005b261ecSmrg
247105b261ecSmrg	winX = source->drawable.x;
247205b261ecSmrg	winY = source->drawable.y;
247305b261ecSmrg	if(source == WindowTable[0]) {
247405b261ecSmrg	    winX -= panoramiXdataPtr[0].x;
247505b261ecSmrg	    winY -= panoramiXdataPtr[0].y;
247605b261ecSmrg	}
247705b261ecSmrg	if (x < winX + stuff->srcX ||
247805b261ecSmrg	    y < winY + stuff->srcY ||
247905b261ecSmrg	    (stuff->srcWidth != 0 &&
248005b261ecSmrg	     winX + stuff->srcX + (int)stuff->srcWidth < x) ||
248105b261ecSmrg	    (stuff->srcHeight != 0 &&
248205b261ecSmrg	     winY + stuff->srcY + (int)stuff->srcHeight < y) ||
248305b261ecSmrg	    !XineramaPointInWindowIsVisible(source, x, y))
248405b261ecSmrg	    return Success;
248505b261ecSmrg    }
248605b261ecSmrg    if (dest) {
248705b261ecSmrg	x = dest->drawable.x;
248805b261ecSmrg	y = dest->drawable.y;
248905b261ecSmrg	if(dest == WindowTable[0]) {
249005b261ecSmrg	    x -= panoramiXdataPtr[0].x;
249105b261ecSmrg	    y -= panoramiXdataPtr[0].y;
249205b261ecSmrg	}
249305b261ecSmrg    }
249405b261ecSmrg
249505b261ecSmrg    x += stuff->dstX;
249605b261ecSmrg    y += stuff->dstY;
249705b261ecSmrg
249805b261ecSmrg    if (x < sprite.physLimits.x1)
249905b261ecSmrg	x = sprite.physLimits.x1;
250005b261ecSmrg    else if (x >= sprite.physLimits.x2)
250105b261ecSmrg	x = sprite.physLimits.x2 - 1;
250205b261ecSmrg    if (y < sprite.physLimits.y1)
250305b261ecSmrg	y = sprite.physLimits.y1;
250405b261ecSmrg    else if (y >= sprite.physLimits.y2)
250505b261ecSmrg	y = sprite.physLimits.y2 - 1;
250605b261ecSmrg    if (sprite.hotShape)
250705b261ecSmrg	ConfineToShape(sprite.hotShape, &x, &y);
250805b261ecSmrg
250905b261ecSmrg    XineramaSetCursorPosition(x, y, TRUE);
251005b261ecSmrg
251105b261ecSmrg    return Success;
251205b261ecSmrg}
251305b261ecSmrg
251405b261ecSmrg#endif
251505b261ecSmrg
251605b261ecSmrg
251705b261ecSmrg/**
251805b261ecSmrg * Server-side protocol handling for WarpPointer request.
251905b261ecSmrg * Warps the cursor position to the coordinates given in the request.
252005b261ecSmrg */
252105b261ecSmrgint
252205b261ecSmrgProcWarpPointer(ClientPtr client)
252305b261ecSmrg{
252405b261ecSmrg    WindowPtr	dest = NULL;
252505b261ecSmrg    int		x, y, rc;
252605b261ecSmrg    ScreenPtr	newScreen;
252705b261ecSmrg
252805b261ecSmrg    REQUEST(xWarpPointerReq);
252905b261ecSmrg
253005b261ecSmrg    REQUEST_SIZE_MATCH(xWarpPointerReq);
253105b261ecSmrg
253205b261ecSmrg#ifdef PANORAMIX
253305b261ecSmrg    if(!noPanoramiXExtension)
253405b261ecSmrg	return XineramaWarpPointer(client);
253505b261ecSmrg#endif
253605b261ecSmrg
253705b261ecSmrg    if (stuff->dstWid != None) {
253805b261ecSmrg	rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
253905b261ecSmrg	if (rc != Success)
254005b261ecSmrg	    return rc;
254105b261ecSmrg    }
254205b261ecSmrg    x = sprite.hotPhys.x;
254305b261ecSmrg    y = sprite.hotPhys.y;
254405b261ecSmrg
254505b261ecSmrg    if (stuff->srcWid != None)
254605b261ecSmrg    {
254705b261ecSmrg	int     winX, winY;
254805b261ecSmrg 	XID 	winID = stuff->srcWid;
254905b261ecSmrg        WindowPtr source;
255005b261ecSmrg
255105b261ecSmrg	rc = dixLookupWindow(&source, winID, client, DixReadAccess);
255205b261ecSmrg	if (rc != Success)
255305b261ecSmrg	    return rc;
255405b261ecSmrg
255505b261ecSmrg	winX = source->drawable.x;
255605b261ecSmrg	winY = source->drawable.y;
255705b261ecSmrg	if (source->drawable.pScreen != sprite.hotPhys.pScreen ||
255805b261ecSmrg	    x < winX + stuff->srcX ||
255905b261ecSmrg	    y < winY + stuff->srcY ||
256005b261ecSmrg	    (stuff->srcWidth != 0 &&
256105b261ecSmrg	     winX + stuff->srcX + (int)stuff->srcWidth < x) ||
256205b261ecSmrg	    (stuff->srcHeight != 0 &&
256305b261ecSmrg	     winY + stuff->srcY + (int)stuff->srcHeight < y) ||
256405b261ecSmrg	    !PointInWindowIsVisible(source, x, y))
256505b261ecSmrg	    return Success;
256605b261ecSmrg    }
256705b261ecSmrg    if (dest)
256805b261ecSmrg    {
256905b261ecSmrg	x = dest->drawable.x;
257005b261ecSmrg	y = dest->drawable.y;
257105b261ecSmrg	newScreen = dest->drawable.pScreen;
257205b261ecSmrg    } else
257305b261ecSmrg	newScreen = sprite.hotPhys.pScreen;
257405b261ecSmrg
257505b261ecSmrg    x += stuff->dstX;
257605b261ecSmrg    y += stuff->dstY;
257705b261ecSmrg
257805b261ecSmrg    if (x < 0)
257905b261ecSmrg	x = 0;
258005b261ecSmrg    else if (x >= newScreen->width)
258105b261ecSmrg	x = newScreen->width - 1;
258205b261ecSmrg    if (y < 0)
258305b261ecSmrg	y = 0;
258405b261ecSmrg    else if (y >= newScreen->height)
258505b261ecSmrg	y = newScreen->height - 1;
258605b261ecSmrg
258705b261ecSmrg    if (newScreen == sprite.hotPhys.pScreen)
258805b261ecSmrg    {
258905b261ecSmrg	if (x < sprite.physLimits.x1)
259005b261ecSmrg	    x = sprite.physLimits.x1;
259105b261ecSmrg	else if (x >= sprite.physLimits.x2)
259205b261ecSmrg	    x = sprite.physLimits.x2 - 1;
259305b261ecSmrg	if (y < sprite.physLimits.y1)
259405b261ecSmrg	    y = sprite.physLimits.y1;
259505b261ecSmrg	else if (y >= sprite.physLimits.y2)
259605b261ecSmrg	    y = sprite.physLimits.y2 - 1;
259705b261ecSmrg#if defined(SHAPE)
259805b261ecSmrg	if (sprite.hotShape)
259905b261ecSmrg	    ConfineToShape(sprite.hotShape, &x, &y);
260005b261ecSmrg#endif
260105b261ecSmrg	(*newScreen->SetCursorPosition)(newScreen, x, y, TRUE);
260205b261ecSmrg    }
260305b261ecSmrg    else if (!PointerConfinedToScreen())
260405b261ecSmrg    {
260505b261ecSmrg	NewCurrentScreen(newScreen, x, y);
260605b261ecSmrg    }
260705b261ecSmrg    return Success;
260805b261ecSmrg}
260905b261ecSmrg
261005b261ecSmrgstatic Bool
261105b261ecSmrgBorderSizeNotEmpty(WindowPtr pWin)
261205b261ecSmrg{
261305b261ecSmrg     if(REGION_NOTEMPTY(sprite.hotPhys.pScreen, &pWin->borderSize))
261405b261ecSmrg	return TRUE;
261505b261ecSmrg
261605b261ecSmrg#ifdef PANORAMIX
261705b261ecSmrg     if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) {
261805b261ecSmrg	int i;
261905b261ecSmrg
262005b261ecSmrg	for(i = 1; i < PanoramiXNumScreens; i++) {
262105b261ecSmrg	    if(REGION_NOTEMPTY(sprite.screen, &sprite.windows[i]->borderSize))
262205b261ecSmrg		return TRUE;
262305b261ecSmrg	}
262405b261ecSmrg     }
262505b261ecSmrg#endif
262605b261ecSmrg     return FALSE;
262705b261ecSmrg}
262805b261ecSmrg
262905b261ecSmrg/**
263005b261ecSmrg * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
263105b261ecSmrg * passive grab set on the window to be activated.
263205b261ecSmrg * If a passive grab is activated, the event will be delivered to the client.
263305b261ecSmrg *
263405b261ecSmrg * @param pWin The window that may be subject to a passive grab.
263505b261ecSmrg * @param device Device that caused the event.
263605b261ecSmrg * @param xE List of events (multiple ones for DeviceMotionNotify)
263705b261ecSmrg * @count number of elements in xE.
263805b261ecSmrg */
263905b261ecSmrg
264005b261ecSmrgstatic Bool
264105b261ecSmrgCheckPassiveGrabsOnWindow(
264205b261ecSmrg    WindowPtr pWin,
264305b261ecSmrg    DeviceIntPtr device,
264405b261ecSmrg    xEvent *xE,
264505b261ecSmrg    int count)
264605b261ecSmrg{
264705b261ecSmrg    GrabPtr grab = wPassiveGrabs(pWin);
264805b261ecSmrg    GrabRec tempGrab;
264905b261ecSmrg    xEvent *dxE;
265005b261ecSmrg
265105b261ecSmrg    if (!grab)
265205b261ecSmrg	return FALSE;
265305b261ecSmrg    tempGrab.window = pWin;
265405b261ecSmrg    tempGrab.device = device;
265505b261ecSmrg    tempGrab.type = xE->u.u.type;
265605b261ecSmrg    tempGrab.detail.exact = xE->u.u.detail;
265705b261ecSmrg    tempGrab.detail.pMask = NULL;
265805b261ecSmrg    tempGrab.modifiersDetail.pMask = NULL;
265905b261ecSmrg    for (; grab; grab = grab->next)
266005b261ecSmrg    {
266105b261ecSmrg#ifdef XKB
266205b261ecSmrg	DeviceIntPtr	gdev;
266305b261ecSmrg	XkbSrvInfoPtr	xkbi;
266405b261ecSmrg
266505b261ecSmrg	gdev= grab->modifierDevice;
266605b261ecSmrg	xkbi= gdev->key->xkbInfo;
266705b261ecSmrg#endif
266805b261ecSmrg	tempGrab.modifierDevice = grab->modifierDevice;
266905b261ecSmrg	if ((device == grab->modifierDevice) &&
267005b261ecSmrg	    ((xE->u.u.type == KeyPress)
267105b261ecSmrg#if defined(XINPUT) && defined(XKB)
267205b261ecSmrg	     || (xE->u.u.type == DeviceKeyPress)
267305b261ecSmrg#endif
267405b261ecSmrg	     ))
267505b261ecSmrg	    tempGrab.modifiersDetail.exact =
267605b261ecSmrg#ifdef XKB
267705b261ecSmrg		(noXkbExtension?gdev->key->prev_state:xkbi->state.grab_mods);
267805b261ecSmrg#else
267905b261ecSmrg		grab->modifierDevice->key->prev_state;
268005b261ecSmrg#endif
268105b261ecSmrg	else
268205b261ecSmrg	    tempGrab.modifiersDetail.exact =
268305b261ecSmrg#ifdef XKB
268405b261ecSmrg		(noXkbExtension ? gdev->key->state : xkbi->state.grab_mods);
268505b261ecSmrg#else
268605b261ecSmrg		grab->modifierDevice->key->state;
268705b261ecSmrg#endif
268805b261ecSmrg	if (GrabMatchesSecond(&tempGrab, grab) &&
268905b261ecSmrg	    (!grab->confineTo ||
269005b261ecSmrg	     (grab->confineTo->realized &&
269105b261ecSmrg				BorderSizeNotEmpty(grab->confineTo))))
269205b261ecSmrg	{
269305b261ecSmrg	    if (!XaceHook(XACE_DEVICE_ACCESS, wClient(pWin), device, FALSE))
269405b261ecSmrg		return FALSE;
269505b261ecSmrg#ifdef XKB
269605b261ecSmrg	    if (!noXkbExtension) {
269705b261ecSmrg		XE_KBPTR.state &= 0x1f00;
269805b261ecSmrg		XE_KBPTR.state |=
269905b261ecSmrg				tempGrab.modifiersDetail.exact&(~0x1f00);
270005b261ecSmrg	    }
270105b261ecSmrg#endif
270205b261ecSmrg	    (*device->ActivateGrab)(device, grab, currentTime, TRUE);
270305b261ecSmrg
270405b261ecSmrg	    FixUpEventFromWindow(xE, grab->window, None, TRUE);
270505b261ecSmrg
270605b261ecSmrg	    (void) TryClientEvents(rClient(grab), xE, count,
270705b261ecSmrg				   filters[xE->u.u.type],
270805b261ecSmrg				   filters[xE->u.u.type],  grab);
270905b261ecSmrg
271005b261ecSmrg	    if (device->sync.state == FROZEN_NO_EVENT)
271105b261ecSmrg	    {
271205b261ecSmrg		if (device->sync.evcount < count)
271305b261ecSmrg		{
271405b261ecSmrg		    Must_have_memory = TRUE; /* XXX */
271505b261ecSmrg		    device->sync.event = (xEvent *)xrealloc(device->sync.event,
271605b261ecSmrg							    count*
271705b261ecSmrg							    sizeof(xEvent));
271805b261ecSmrg		    Must_have_memory = FALSE; /* XXX */
271905b261ecSmrg		}
272005b261ecSmrg		device->sync.evcount = count;
272105b261ecSmrg		for (dxE = device->sync.event; --count >= 0; dxE++, xE++)
272205b261ecSmrg		    *dxE = *xE;
272305b261ecSmrg	    	device->sync.state = FROZEN_WITH_EVENT;
272405b261ecSmrg            }
272505b261ecSmrg	    return TRUE;
272605b261ecSmrg	}
272705b261ecSmrg    }
272805b261ecSmrg    return FALSE;
272905b261ecSmrg}
273005b261ecSmrg
273105b261ecSmrg/**
273205b261ecSmrg * CheckDeviceGrabs handles both keyboard and pointer events that may cause
273305b261ecSmrg * a passive grab to be activated.
273405b261ecSmrg *
273505b261ecSmrg * If the event is a keyboard event, the ancestors of the focus window are
273605b261ecSmrg * traced down and tried to see if they have any passive grabs to be
273705b261ecSmrg * activated.  If the focus window itself is reached and it's descendants
273805b261ecSmrg * contain the pointer, the ancestors of the window that the pointer is in
273905b261ecSmrg * are then traced down starting at the focus window, otherwise no grabs are
274005b261ecSmrg * activated.
274105b261ecSmrg * If the event is a pointer event, the ancestors of the window that the
274205b261ecSmrg * pointer is in are traced down starting at the root until CheckPassiveGrabs
274305b261ecSmrg * causes a passive grab to activate or all the windows are
274405b261ecSmrg * tried. PRH
274505b261ecSmrg *
274605b261ecSmrg * If a grab is activated, the event has been sent to the client already!
274705b261ecSmrg *
274805b261ecSmrg * @param device The device that caused the event.
274905b261ecSmrg * @param xE The event to handle (most likely {Device}ButtonPress).
275005b261ecSmrg * @param count Number of events in list.
275105b261ecSmrg * @return TRUE if a grab has been activated or false otherwise.
275205b261ecSmrg*/
275305b261ecSmrg
275405b261ecSmrgBool
275505b261ecSmrgCheckDeviceGrabs(DeviceIntPtr device, xEvent *xE,
275605b261ecSmrg                 int checkFirst, int count)
275705b261ecSmrg{
275805b261ecSmrg    int i;
275905b261ecSmrg    WindowPtr pWin = NULL;
276005b261ecSmrg    FocusClassPtr focus = device->focus;
276105b261ecSmrg
276205b261ecSmrg    if (((xE->u.u.type == ButtonPress)
276305b261ecSmrg#if defined(XINPUT) && defined(XKB)
276405b261ecSmrg	 || (xE->u.u.type == DeviceButtonPress)
276505b261ecSmrg#endif
276605b261ecSmrg	 ) && (device->button->buttonsDown != 1))
276705b261ecSmrg	return FALSE;
276805b261ecSmrg
276905b261ecSmrg    i = checkFirst;
277005b261ecSmrg
277105b261ecSmrg    if (focus)
277205b261ecSmrg    {
277305b261ecSmrg	for (; i < focus->traceGood; i++)
277405b261ecSmrg	{
277505b261ecSmrg	    pWin = focus->trace[i];
277605b261ecSmrg	    if (pWin->optional &&
277705b261ecSmrg		CheckPassiveGrabsOnWindow(pWin, device, xE, count))
277805b261ecSmrg		return TRUE;
277905b261ecSmrg	}
278005b261ecSmrg
278105b261ecSmrg	if ((focus->win == NoneWin) ||
278205b261ecSmrg	    (i >= spriteTraceGood) ||
278305b261ecSmrg	    ((i > checkFirst) && (pWin != spriteTrace[i-1])))
278405b261ecSmrg	    return FALSE;
278505b261ecSmrg    }
278605b261ecSmrg
278705b261ecSmrg    for (; i < spriteTraceGood; i++)
278805b261ecSmrg    {
278905b261ecSmrg	pWin = spriteTrace[i];
279005b261ecSmrg	if (pWin->optional &&
279105b261ecSmrg	    CheckPassiveGrabsOnWindow(pWin, device, xE, count))
279205b261ecSmrg	    return TRUE;
279305b261ecSmrg    }
279405b261ecSmrg
279505b261ecSmrg    return FALSE;
279605b261ecSmrg}
279705b261ecSmrg
279805b261ecSmrg/**
279905b261ecSmrg * Called for keyboard events to deliver event to whatever client owns the
280005b261ecSmrg * focus. Event is delivered to the keyboard's focus window, the root window
280105b261ecSmrg * or to the window owning the input focus.
280205b261ecSmrg *
280305b261ecSmrg * @param keybd The keyboard originating the event.
280405b261ecSmrg * @param xE The event list.
280505b261ecSmrg * @param window Window underneath the sprite.
280605b261ecSmrg * @param count number of events in xE.
280705b261ecSmrg */
280805b261ecSmrgvoid
280905b261ecSmrgDeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
281005b261ecSmrg{
281105b261ecSmrg    WindowPtr focus = keybd->focus->win;
281205b261ecSmrg    int mskidx = 0;
281305b261ecSmrg
281405b261ecSmrg    if (focus == FollowKeyboardWin)
281505b261ecSmrg	focus = inputInfo.keyboard->focus->win;
281605b261ecSmrg    if (!focus)
281705b261ecSmrg	return;
281805b261ecSmrg    if (focus == PointerRootWin)
281905b261ecSmrg    {
282005b261ecSmrg	DeliverDeviceEvents(window, xE, NullGrab, NullWindow, keybd, count);
282105b261ecSmrg	return;
282205b261ecSmrg    }
282305b261ecSmrg    if ((focus == window) || IsParent(focus, window))
282405b261ecSmrg    {
282505b261ecSmrg	if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count))
282605b261ecSmrg	    return;
282705b261ecSmrg    }
282805b261ecSmrg    /* just deliver it to the focus window */
282905b261ecSmrg    FixUpEventFromWindow(xE, focus, None, FALSE);
283005b261ecSmrg    if (xE->u.u.type & EXTENSION_EVENT_BASE)
283105b261ecSmrg	mskidx = keybd->id;
283205b261ecSmrg    (void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type],
283305b261ecSmrg				NullGrab, mskidx);
283405b261ecSmrg}
283505b261ecSmrg
283605b261ecSmrg/**
283705b261ecSmrg * Deliver an event from a device that is currently grabbed. Uses
283805b261ecSmrg * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the
283905b261ecSmrg * grab. If not, TryClientEvents() is used.
284005b261ecSmrg *
284105b261ecSmrg * @param deactivateGrab True if the device's grab should be deactivated.
284205b261ecSmrg */
284305b261ecSmrgvoid
284405b261ecSmrgDeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
284505b261ecSmrg                    Bool deactivateGrab, int count)
284605b261ecSmrg{
284705b261ecSmrg    GrabPtr grab = thisDev->grab;
284805b261ecSmrg    int deliveries = 0;
284905b261ecSmrg    DeviceIntPtr dev;
285005b261ecSmrg    xEvent *dxE;
285105b261ecSmrg
285205b261ecSmrg    if (grab->ownerEvents)
285305b261ecSmrg    {
285405b261ecSmrg	WindowPtr focus;
285505b261ecSmrg
285605b261ecSmrg	if (thisDev->focus)
285705b261ecSmrg	{
285805b261ecSmrg	    focus = thisDev->focus->win;
285905b261ecSmrg	    if (focus == FollowKeyboardWin)
286005b261ecSmrg		focus = inputInfo.keyboard->focus->win;
286105b261ecSmrg	}
286205b261ecSmrg	else
286305b261ecSmrg	    focus = PointerRootWin;
286405b261ecSmrg	if (focus == PointerRootWin)
286505b261ecSmrg	    deliveries = DeliverDeviceEvents(sprite.win, xE, grab, NullWindow,
286605b261ecSmrg					     thisDev, count);
286705b261ecSmrg	else if (focus && (focus == sprite.win || IsParent(focus, sprite.win)))
286805b261ecSmrg	    deliveries = DeliverDeviceEvents(sprite.win, xE, grab, focus,
286905b261ecSmrg					     thisDev, count);
287005b261ecSmrg	else if (focus)
287105b261ecSmrg	    deliveries = DeliverDeviceEvents(focus, xE, grab, focus,
287205b261ecSmrg					     thisDev, count);
287305b261ecSmrg    }
287405b261ecSmrg    if (!deliveries)
287505b261ecSmrg    {
287605b261ecSmrg	FixUpEventFromWindow(xE, grab->window, None, TRUE);
287705b261ecSmrg	deliveries = TryClientEvents(rClient(grab), xE, count,
287805b261ecSmrg				     (Mask)grab->eventMask,
287905b261ecSmrg				     filters[xE->u.u.type], grab);
288005b261ecSmrg	if (deliveries && (xE->u.u.type == MotionNotify
288105b261ecSmrg#ifdef XINPUT
288205b261ecSmrg			   || xE->u.u.type == DeviceMotionNotify
288305b261ecSmrg#endif
288405b261ecSmrg			   ))
288505b261ecSmrg	    thisDev->valuator->motionHintWindow = grab->window;
288605b261ecSmrg    }
288705b261ecSmrg    if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify
288805b261ecSmrg#ifdef XINPUT
288905b261ecSmrg					  && xE->u.u.type != DeviceMotionNotify
289005b261ecSmrg#endif
289105b261ecSmrg					  ))
289205b261ecSmrg	switch (thisDev->sync.state)
289305b261ecSmrg	{
289405b261ecSmrg	case FREEZE_BOTH_NEXT_EVENT:
289505b261ecSmrg	    for (dev = inputInfo.devices; dev; dev = dev->next)
289605b261ecSmrg	    {
289705b261ecSmrg		if (dev == thisDev)
289805b261ecSmrg		    continue;
289905b261ecSmrg		FreezeThaw(dev, TRUE);
290005b261ecSmrg		if ((dev->sync.state == FREEZE_BOTH_NEXT_EVENT) &&
290105b261ecSmrg		    (CLIENT_BITS(dev->grab->resource) ==
290205b261ecSmrg		     CLIENT_BITS(thisDev->grab->resource)))
290305b261ecSmrg		    dev->sync.state = FROZEN_NO_EVENT;
290405b261ecSmrg		else
290505b261ecSmrg		    dev->sync.other = thisDev->grab;
290605b261ecSmrg	    }
290705b261ecSmrg	    /* fall through */
290805b261ecSmrg	case FREEZE_NEXT_EVENT:
290905b261ecSmrg	    thisDev->sync.state = FROZEN_WITH_EVENT;
291005b261ecSmrg	    FreezeThaw(thisDev, TRUE);
291105b261ecSmrg	    if (thisDev->sync.evcount < count)
291205b261ecSmrg	    {
291305b261ecSmrg		Must_have_memory = TRUE; /* XXX */
291405b261ecSmrg		thisDev->sync.event = (xEvent *)xrealloc(thisDev->sync.event,
291505b261ecSmrg							 count*sizeof(xEvent));
291605b261ecSmrg		Must_have_memory = FALSE; /* XXX */
291705b261ecSmrg	    }
291805b261ecSmrg	    thisDev->sync.evcount = count;
291905b261ecSmrg	    for (dxE = thisDev->sync.event; --count >= 0; dxE++, xE++)
292005b261ecSmrg		*dxE = *xE;
292105b261ecSmrg	    break;
292205b261ecSmrg	}
292305b261ecSmrg}
292405b261ecSmrg
292505b261ecSmrg/**
292605b261ecSmrg * Main keyboard event processing function for core keyboard events.
292705b261ecSmrg * Updates the events fields from the current pointer state and delivers the
292805b261ecSmrg * event.
292905b261ecSmrg *
293005b261ecSmrg * For key events, xE will always be a single event.
293105b261ecSmrg *
293205b261ecSmrg * @param xE Event list
293305b261ecSmrg * @param keybd The device that caused an event.
293405b261ecSmrg * @param count Number of elements in xE.
293505b261ecSmrg */
293605b261ecSmrgvoid
293705b261ecSmrg#ifdef XKB
293805b261ecSmrgCoreProcessKeyboardEvent (xEvent *xE, DeviceIntPtr keybd, int count)
293905b261ecSmrg#else
294005b261ecSmrgProcessKeyboardEvent (xEvent *xE, DeviceIntPtr keybd, int count)
294105b261ecSmrg#endif
294205b261ecSmrg{
294305b261ecSmrg    int             key, bit;
294405b261ecSmrg    BYTE   *kptr;
294505b261ecSmrg    int    i;
294605b261ecSmrg    CARD8  modifiers;
294705b261ecSmrg    CARD16 mask;
294805b261ecSmrg    GrabPtr         grab = keybd->grab;
294905b261ecSmrg    Bool            deactivateGrab = FALSE;
295005b261ecSmrg    KeyClassPtr keyc = keybd->key;
295105b261ecSmrg#ifdef XEVIE
295205b261ecSmrg    static Window           rootWin = 0;
295305b261ecSmrg
295405b261ecSmrg    if(!xeviegrabState && xevieFlag && clients[xevieClientIndex] &&
295505b261ecSmrg          (xevieMask & xevieFilters[xE->u.u.type])) {
295605b261ecSmrg      key = xE->u.u.detail;
295705b261ecSmrg      kptr = &keyc->down[key >> 3];
295805b261ecSmrg      bit = 1 << (key & 7);
295905b261ecSmrg      if((xE->u.u.type == KeyPress &&  (*kptr & bit)) ||
296005b261ecSmrg         (xE->u.u.type == KeyRelease && !(*kptr & bit)))
296105b261ecSmrg      {} else {
296205b261ecSmrg#ifdef XKB
296305b261ecSmrg        if(!noXkbExtension)
296405b261ecSmrg	    xevieKBEventSent = 1;
296505b261ecSmrg#endif
296605b261ecSmrg        if(!xevieKBEventSent)
296705b261ecSmrg        {
296805b261ecSmrg          xeviekb = keybd;
296905b261ecSmrg          if(!rootWin) {
297005b261ecSmrg	      rootWin = GetCurrentRootWindow()->drawable.id;
297105b261ecSmrg          }
297205b261ecSmrg          xE->u.keyButtonPointer.event = xeviewin->drawable.id;
297305b261ecSmrg          xE->u.keyButtonPointer.root = rootWin;
297405b261ecSmrg          xE->u.keyButtonPointer.child = (xeviewin->firstChild) ? xeviewin->firstChild->
297505b261ecSmrgdrawable.id:0;
297605b261ecSmrg          xE->u.keyButtonPointer.rootX = xeviehot.x;
297705b261ecSmrg          xE->u.keyButtonPointer.rootY = xeviehot.y;
297805b261ecSmrg          xE->u.keyButtonPointer.state = keyc->state;
297905b261ecSmrg          WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE);
298005b261ecSmrg#ifdef XKB
298105b261ecSmrg          if(noXkbExtension)
298205b261ecSmrg#endif
298305b261ecSmrg            return;
298405b261ecSmrg        } else {
298505b261ecSmrg	    xevieKBEventSent = 0;
298605b261ecSmrg        }
298705b261ecSmrg      }
298805b261ecSmrg    }
298905b261ecSmrg#endif
299005b261ecSmrg
299105b261ecSmrg    if (!syncEvents.playingEvents)
299205b261ecSmrg    {
299305b261ecSmrg	NoticeTime(xE);
299405b261ecSmrg	if (DeviceEventCallback)
299505b261ecSmrg	{
299605b261ecSmrg	    DeviceEventInfoRec eventinfo;
299705b261ecSmrg	    eventinfo.events = xE;
299805b261ecSmrg	    eventinfo.count = count;
299905b261ecSmrg	    CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
300005b261ecSmrg	}
300105b261ecSmrg    }
300205b261ecSmrg#ifdef XEVIE
300305b261ecSmrg    /* fix for bug5094030: don't change the state bit if the event is from XEvIE client */
300405b261ecSmrg    if(!(!xeviegrabState && xevieFlag && clients[xevieClientIndex] &&
300505b261ecSmrg	 (xevieMask & xevieFilters[xE->u.u.type]
300605b261ecSmrg#ifdef XKB
300705b261ecSmrg	  && !noXkbExtension
300805b261ecSmrg#endif
300905b261ecSmrg    )))
301005b261ecSmrg#endif
301105b261ecSmrg    XE_KBPTR.state = (keyc->state | inputInfo.pointer->button->state);
301205b261ecSmrg    XE_KBPTR.rootX = sprite.hot.x;
301305b261ecSmrg    XE_KBPTR.rootY = sprite.hot.y;
301405b261ecSmrg    key = xE->u.u.detail;
301505b261ecSmrg    kptr = &keyc->down[key >> 3];
301605b261ecSmrg    bit = 1 << (key & 7);
301705b261ecSmrg    modifiers = keyc->modifierMap[key];
301805b261ecSmrg#if defined(XKB) && defined(XEVIE)
301905b261ecSmrg    if(!noXkbExtension && !xeviegrabState &&
302005b261ecSmrg       xevieFlag && clients[xevieClientIndex] &&
302105b261ecSmrg       (xevieMask & xevieFilters[xE->u.u.type])) {
302205b261ecSmrg	switch(xE->u.u.type) {
302305b261ecSmrg	  case KeyPress: *kptr &= ~bit; break;
302405b261ecSmrg	  case KeyRelease: *kptr |= bit; break;
302505b261ecSmrg	}
302605b261ecSmrg    }
302705b261ecSmrg#endif
302805b261ecSmrg
302905b261ecSmrg    switch (xE->u.u.type)
303005b261ecSmrg    {
303105b261ecSmrg	case KeyPress:
303205b261ecSmrg	    if (*kptr & bit) /* allow ddx to generate multiple downs */
303305b261ecSmrg	    {
303405b261ecSmrg		if (!modifiers)
303505b261ecSmrg		{
303605b261ecSmrg		    xE->u.u.type = KeyRelease;
303705b261ecSmrg		    (*keybd->public.processInputProc)(xE, keybd, count);
303805b261ecSmrg		    xE->u.u.type = KeyPress;
303905b261ecSmrg		    /* release can have side effects, don't fall through */
304005b261ecSmrg		    (*keybd->public.processInputProc)(xE, keybd, count);
304105b261ecSmrg		}
304205b261ecSmrg		return;
304305b261ecSmrg	    }
304405b261ecSmrg	    inputInfo.pointer->valuator->motionHintWindow = NullWindow;
304505b261ecSmrg	    *kptr |= bit;
304605b261ecSmrg	    keyc->prev_state = keyc->state;
304705b261ecSmrg	    for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
304805b261ecSmrg	    {
304905b261ecSmrg		if (mask & modifiers)
305005b261ecSmrg		{
305105b261ecSmrg		    /* This key affects modifier "i" */
305205b261ecSmrg		    keyc->modifierKeyCount[i]++;
305305b261ecSmrg		    keyc->state |= mask;
305405b261ecSmrg		    modifiers &= ~mask;
305505b261ecSmrg		}
305605b261ecSmrg	    }
305705b261ecSmrg	    if (!grab && CheckDeviceGrabs(keybd, xE, 0, count))
305805b261ecSmrg	    {
305905b261ecSmrg		keybd->activatingKey = key;
306005b261ecSmrg		return;
306105b261ecSmrg	    }
306205b261ecSmrg	    break;
306305b261ecSmrg	case KeyRelease:
306405b261ecSmrg	    if (!(*kptr & bit)) /* guard against duplicates */
306505b261ecSmrg		return;
306605b261ecSmrg	    inputInfo.pointer->valuator->motionHintWindow = NullWindow;
306705b261ecSmrg	    *kptr &= ~bit;
306805b261ecSmrg	    keyc->prev_state = keyc->state;
306905b261ecSmrg	    for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
307005b261ecSmrg	    {
307105b261ecSmrg		if (mask & modifiers) {
307205b261ecSmrg		    /* This key affects modifier "i" */
307305b261ecSmrg		    if (--keyc->modifierKeyCount[i] <= 0) {
307405b261ecSmrg			keyc->state &= ~mask;
307505b261ecSmrg			keyc->modifierKeyCount[i] = 0;
307605b261ecSmrg		    }
307705b261ecSmrg		    modifiers &= ~mask;
307805b261ecSmrg		}
307905b261ecSmrg	    }
308005b261ecSmrg	    if (keybd->fromPassiveGrab && (key == keybd->activatingKey))
308105b261ecSmrg		deactivateGrab = TRUE;
308205b261ecSmrg	    break;
308305b261ecSmrg	default:
308405b261ecSmrg	    FatalError("Impossible keyboard event");
308505b261ecSmrg    }
308605b261ecSmrg    if (grab)
308705b261ecSmrg	DeliverGrabbedEvent(xE, keybd, deactivateGrab, count);
308805b261ecSmrg    else
308905b261ecSmrg	DeliverFocusedEvent(keybd, xE, sprite.win, count);
309005b261ecSmrg    if (deactivateGrab)
309105b261ecSmrg        (*keybd->DeactivateGrab)(keybd);
309205b261ecSmrg
309305b261ecSmrg    XaceHook(XACE_KEY_AVAIL, xE, keybd, count);
309405b261ecSmrg}
309505b261ecSmrg
309605b261ecSmrg#ifdef XKB
309705b261ecSmrg/* This function is used to set the key pressed or key released state -
309805b261ecSmrg   this is only used when the pressing of keys does not cause
309905b261ecSmrg   the device's processInputProc to be called, as in for example Mouse Keys.
310005b261ecSmrg*/
310105b261ecSmrgvoid
310205b261ecSmrgFixKeyState (xEvent *xE, DeviceIntPtr keybd)
310305b261ecSmrg{
310405b261ecSmrg    int             key, bit;
310505b261ecSmrg    BYTE   *kptr;
310605b261ecSmrg    KeyClassPtr keyc = keybd->key;
310705b261ecSmrg
310805b261ecSmrg    key = xE->u.u.detail;
310905b261ecSmrg    kptr = &keyc->down[key >> 3];
311005b261ecSmrg    bit = 1 << (key & 7);
311105b261ecSmrg
311205b261ecSmrg    if (((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease)||
311305b261ecSmrg         (xE->u.u.type==DeviceKeyPress)||(xE->u.u.type==DeviceKeyRelease))
311405b261ecSmrg            ) {
311505b261ecSmrg	DebugF("FixKeyState: Key %d %s\n",key,
311605b261ecSmrg               (((xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress))?"down":"up"));
311705b261ecSmrg    }
311805b261ecSmrg
311905b261ecSmrg    if (xE->u.u.type == KeyPress || xE->u.u.type == DeviceKeyPress)
312005b261ecSmrg	    *kptr |= bit;
312105b261ecSmrg    else if (xE->u.u.type == KeyRelease || xE->u.u.type == DeviceKeyRelease)
312205b261ecSmrg	    *kptr &= ~bit;
312305b261ecSmrg    else
312405b261ecSmrg        FatalError("Impossible keyboard event");
312505b261ecSmrg}
312605b261ecSmrg#endif
312705b261ecSmrg
312805b261ecSmrg/**
312905b261ecSmrg * Main pointer event processing function for core pointer events.
313005b261ecSmrg * For motion events: update the sprite.
313105b261ecSmrg * For all other events: Update the event fields based on the current sprite
313205b261ecSmrg * state.
313305b261ecSmrg *
313405b261ecSmrg * For core pointer events, xE will always be a single event.
313505b261ecSmrg *
313605b261ecSmrg * @param xE Event list
313705b261ecSmrg * @param mouse The device that caused an event.
313805b261ecSmrg * @param count Number of elements in xE.
313905b261ecSmrg */
314005b261ecSmrgvoid
314105b261ecSmrg#ifdef XKB
314205b261ecSmrgCoreProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
314305b261ecSmrg#else
314405b261ecSmrgProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
314505b261ecSmrg#endif
314605b261ecSmrg{
314705b261ecSmrg    GrabPtr	grab = mouse->grab;
314805b261ecSmrg    Bool                deactivateGrab = FALSE;
314905b261ecSmrg    ButtonClassPtr butc = mouse->button;
315005b261ecSmrg#ifdef XKB
315105b261ecSmrg    XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo;
315205b261ecSmrg#endif
315305b261ecSmrg#ifdef XEVIE
315405b261ecSmrg    if(xevieFlag && clients[xevieClientIndex] && !xeviegrabState &&
315505b261ecSmrg       (xevieMask & xevieFilters[xE->u.u.type])) {
315605b261ecSmrg      if(xevieEventSent)
315705b261ecSmrg        xevieEventSent = 0;
315805b261ecSmrg      else {
315905b261ecSmrg        xeviemouse = mouse;
316005b261ecSmrg        WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE);
316105b261ecSmrg        return;
316205b261ecSmrg      }
316305b261ecSmrg    }
316405b261ecSmrg#endif
316505b261ecSmrg
316605b261ecSmrg    if (!syncEvents.playingEvents)
316705b261ecSmrg	NoticeTime(xE)
316805b261ecSmrg    XE_KBPTR.state = (butc->state | (
316905b261ecSmrg#ifdef XKB
317005b261ecSmrg			(noXkbExtension ?
317105b261ecSmrg				inputInfo.keyboard->key->state :
317205b261ecSmrg				xkbi->state.grab_mods)
317305b261ecSmrg#else
317405b261ecSmrg			inputInfo.keyboard->key->state
317505b261ecSmrg#endif
317605b261ecSmrg				    ));
317705b261ecSmrg    {
317805b261ecSmrg	NoticeTime(xE);
317905b261ecSmrg	if (DeviceEventCallback)
318005b261ecSmrg	{
318105b261ecSmrg	    DeviceEventInfoRec eventinfo;
318205b261ecSmrg	    /* see comment in EnqueueEvents regarding the next three lines */
318305b261ecSmrg	    if (xE->u.u.type == MotionNotify)
318405b261ecSmrg		XE_KBPTR.root =
318505b261ecSmrg		    WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id;
318605b261ecSmrg	    eventinfo.events = xE;
318705b261ecSmrg	    eventinfo.count = count;
318805b261ecSmrg	    CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
318905b261ecSmrg	}
319005b261ecSmrg    }
319105b261ecSmrg    if (xE->u.u.type != MotionNotify)
319205b261ecSmrg    {
319305b261ecSmrg	int  key;
319405b261ecSmrg	BYTE *kptr;
319505b261ecSmrg	int           bit;
319605b261ecSmrg
319705b261ecSmrg	XE_KBPTR.rootX = sprite.hot.x;
319805b261ecSmrg	XE_KBPTR.rootY = sprite.hot.y;
319905b261ecSmrg
320005b261ecSmrg	key = xE->u.u.detail;
320105b261ecSmrg	kptr = &butc->down[key >> 3];
320205b261ecSmrg	bit = 1 << (key & 7);
320305b261ecSmrg	switch (xE->u.u.type)
320405b261ecSmrg	{
320505b261ecSmrg	case ButtonPress:
320605b261ecSmrg	    mouse->valuator->motionHintWindow = NullWindow;
320705b261ecSmrg	    if (!(*kptr & bit))
320805b261ecSmrg		butc->buttonsDown++;
320905b261ecSmrg	    butc->motionMask = ButtonMotionMask;
321005b261ecSmrg	    *kptr |= bit;
321105b261ecSmrg	    if (xE->u.u.detail == 0)
321205b261ecSmrg		return;
321305b261ecSmrg	    if (xE->u.u.detail <= 5)
321405b261ecSmrg		butc->state |= (Button1Mask >> 1) << xE->u.u.detail;
321505b261ecSmrg	    filters[MotionNotify] = Motion_Filter(butc);
321605b261ecSmrg	    if (!grab)
321705b261ecSmrg		if (CheckDeviceGrabs(mouse, xE, 0, count))
321805b261ecSmrg		    return;
321905b261ecSmrg	    break;
322005b261ecSmrg	case ButtonRelease:
322105b261ecSmrg	    mouse->valuator->motionHintWindow = NullWindow;
322205b261ecSmrg	    if (*kptr & bit)
322305b261ecSmrg		--butc->buttonsDown;
322405b261ecSmrg	    if (!butc->buttonsDown)
322505b261ecSmrg		butc->motionMask = 0;
322605b261ecSmrg	    *kptr &= ~bit;
322705b261ecSmrg	    if (xE->u.u.detail == 0)
322805b261ecSmrg		return;
322905b261ecSmrg	    if (xE->u.u.detail <= 5)
323005b261ecSmrg		butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
323105b261ecSmrg	    filters[MotionNotify] = Motion_Filter(butc);
323205b261ecSmrg	    if (!butc->state && mouse->fromPassiveGrab)
323305b261ecSmrg		deactivateGrab = TRUE;
323405b261ecSmrg	    break;
323505b261ecSmrg	default:
323605b261ecSmrg	    FatalError("bogus pointer event from ddx");
323705b261ecSmrg	}
323805b261ecSmrg    }
323905b261ecSmrg    else if (!CheckMotion(xE))
324005b261ecSmrg	return;
324105b261ecSmrg    if (grab)
324205b261ecSmrg	DeliverGrabbedEvent(xE, mouse, deactivateGrab, count);
324305b261ecSmrg    else
324405b261ecSmrg	DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow,
324505b261ecSmrg			    mouse, count);
324605b261ecSmrg    if (deactivateGrab)
324705b261ecSmrg        (*mouse->DeactivateGrab)(mouse);
324805b261ecSmrg}
324905b261ecSmrg
325005b261ecSmrg#define AtMostOneClient \
325105b261ecSmrg	(SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
325205b261ecSmrg
325305b261ecSmrg/**
325405b261ecSmrg * Recalculate which events may be deliverable for the given window.
325505b261ecSmrg * Recalculated mask is used for quicker determination which events may be
325605b261ecSmrg * delivered to a window.
325705b261ecSmrg *
325805b261ecSmrg * The otherEventMasks on a WindowOptional is the combination of all event
325905b261ecSmrg * masks set by all clients on the window.
326005b261ecSmrg * deliverableEventMask is the combination of the eventMask and the
326105b261ecSmrg * otherEventMask.
326205b261ecSmrg *
326305b261ecSmrg * Traverses to siblings and parents of the window.
326405b261ecSmrg */
326505b261ecSmrgvoid
326605b261ecSmrgRecalculateDeliverableEvents(pWin)
326705b261ecSmrg    WindowPtr pWin;
326805b261ecSmrg{
326905b261ecSmrg    OtherClients *others;
327005b261ecSmrg    WindowPtr pChild;
327105b261ecSmrg
327205b261ecSmrg    pChild = pWin;
327305b261ecSmrg    while (1)
327405b261ecSmrg    {
327505b261ecSmrg	if (pChild->optional)
327605b261ecSmrg	{
327705b261ecSmrg	    pChild->optional->otherEventMasks = 0;
327805b261ecSmrg	    for (others = wOtherClients(pChild); others; others = others->next)
327905b261ecSmrg	    {
328005b261ecSmrg		pChild->optional->otherEventMasks |= others->mask;
328105b261ecSmrg	    }
328205b261ecSmrg	}
328305b261ecSmrg	pChild->deliverableEvents = pChild->eventMask|
328405b261ecSmrg				    wOtherEventMasks(pChild);
328505b261ecSmrg	if (pChild->parent)
328605b261ecSmrg	    pChild->deliverableEvents |=
328705b261ecSmrg		(pChild->parent->deliverableEvents &
328805b261ecSmrg		 ~wDontPropagateMask(pChild) & PropagateMask);
328905b261ecSmrg	if (pChild->firstChild)
329005b261ecSmrg	{
329105b261ecSmrg	    pChild = pChild->firstChild;
329205b261ecSmrg	    continue;
329305b261ecSmrg	}
329405b261ecSmrg	while (!pChild->nextSib && (pChild != pWin))
329505b261ecSmrg	    pChild = pChild->parent;
329605b261ecSmrg	if (pChild == pWin)
329705b261ecSmrg	    break;
329805b261ecSmrg	pChild = pChild->nextSib;
329905b261ecSmrg    }
330005b261ecSmrg}
330105b261ecSmrg
330205b261ecSmrg/**
330305b261ecSmrg *
330405b261ecSmrg *  \param value must conform to DeleteType
330505b261ecSmrg */
330605b261ecSmrgint
330705b261ecSmrgOtherClientGone(pointer value, XID id)
330805b261ecSmrg{
330905b261ecSmrg    OtherClientsPtr other, prev;
331005b261ecSmrg    WindowPtr pWin = (WindowPtr)value;
331105b261ecSmrg
331205b261ecSmrg    prev = 0;
331305b261ecSmrg    for (other = wOtherClients(pWin); other; other = other->next)
331405b261ecSmrg    {
331505b261ecSmrg	if (other->resource == id)
331605b261ecSmrg	{
331705b261ecSmrg	    if (prev)
331805b261ecSmrg		prev->next = other->next;
331905b261ecSmrg	    else
332005b261ecSmrg	    {
332105b261ecSmrg		if (!(pWin->optional->otherClients = other->next))
332205b261ecSmrg		    CheckWindowOptionalNeed (pWin);
332305b261ecSmrg	    }
332405b261ecSmrg	    xfree(other);
332505b261ecSmrg	    RecalculateDeliverableEvents(pWin);
332605b261ecSmrg	    return(Success);
332705b261ecSmrg	}
332805b261ecSmrg	prev = other;
332905b261ecSmrg    }
333005b261ecSmrg    FatalError("client not on event list");
333105b261ecSmrg    /*NOTREACHED*/
333205b261ecSmrg    return -1; /* make compiler happy */
333305b261ecSmrg}
333405b261ecSmrg
333505b261ecSmrgint
333605b261ecSmrgEventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
333705b261ecSmrg{
333805b261ecSmrg    Mask check;
333905b261ecSmrg    OtherClients * others;
334005b261ecSmrg
334105b261ecSmrg    if (mask & ~AllEventMasks)
334205b261ecSmrg    {
334305b261ecSmrg	client->errorValue = mask;
334405b261ecSmrg	return BadValue;
334505b261ecSmrg    }
334605b261ecSmrg    check = (mask & AtMostOneClient);
334705b261ecSmrg    if (check & (pWin->eventMask|wOtherEventMasks(pWin)))
334805b261ecSmrg    {				       /* It is illegal for two different
334905b261ecSmrg				          clients to select on any of the
335005b261ecSmrg				          events for AtMostOneClient. However,
335105b261ecSmrg				          it is OK, for some client to
335205b261ecSmrg				          continue selecting on one of those
335305b261ecSmrg				          events.  */
335405b261ecSmrg	if ((wClient(pWin) != client) && (check & pWin->eventMask))
335505b261ecSmrg	    return BadAccess;
335605b261ecSmrg	for (others = wOtherClients (pWin); others; others = others->next)
335705b261ecSmrg	{
335805b261ecSmrg	    if (!SameClient(others, client) && (check & others->mask))
335905b261ecSmrg		return BadAccess;
336005b261ecSmrg	}
336105b261ecSmrg    }
336205b261ecSmrg    if (wClient (pWin) == client)
336305b261ecSmrg    {
336405b261ecSmrg	check = pWin->eventMask;
336505b261ecSmrg	pWin->eventMask = mask;
336605b261ecSmrg    }
336705b261ecSmrg    else
336805b261ecSmrg    {
336905b261ecSmrg	for (others = wOtherClients (pWin); others; others = others->next)
337005b261ecSmrg	{
337105b261ecSmrg	    if (SameClient(others, client))
337205b261ecSmrg	    {
337305b261ecSmrg		check = others->mask;
337405b261ecSmrg		if (mask == 0)
337505b261ecSmrg		{
337605b261ecSmrg		    FreeResource(others->resource, RT_NONE);
337705b261ecSmrg		    return Success;
337805b261ecSmrg		}
337905b261ecSmrg		else
338005b261ecSmrg		    others->mask = mask;
338105b261ecSmrg		goto maskSet;
338205b261ecSmrg	    }
338305b261ecSmrg	}
338405b261ecSmrg	check = 0;
338505b261ecSmrg	if (!pWin->optional && !MakeWindowOptional (pWin))
338605b261ecSmrg	    return BadAlloc;
338705b261ecSmrg	others = (OtherClients *) xalloc(sizeof(OtherClients));
338805b261ecSmrg	if (!others)
338905b261ecSmrg	    return BadAlloc;
339005b261ecSmrg	others->mask = mask;
339105b261ecSmrg	others->resource = FakeClientID(client->index);
339205b261ecSmrg	others->next = pWin->optional->otherClients;
339305b261ecSmrg	pWin->optional->otherClients = others;
339405b261ecSmrg	if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin))
339505b261ecSmrg	    return BadAlloc;
339605b261ecSmrg    }
339705b261ecSmrgmaskSet:
339805b261ecSmrg    if ((inputInfo.pointer->valuator->motionHintWindow == pWin) &&
339905b261ecSmrg	(mask & PointerMotionHintMask) &&
340005b261ecSmrg	!(check & PointerMotionHintMask) &&
340105b261ecSmrg	!inputInfo.pointer->grab)
340205b261ecSmrg	inputInfo.pointer->valuator->motionHintWindow = NullWindow;
340305b261ecSmrg    RecalculateDeliverableEvents(pWin);
340405b261ecSmrg    return Success;
340505b261ecSmrg}
340605b261ecSmrg
340705b261ecSmrgint
340805b261ecSmrgEventSuppressForWindow(WindowPtr pWin, ClientPtr client,
340905b261ecSmrg                       Mask mask, Bool *checkOptional)
341005b261ecSmrg{
341105b261ecSmrg    int i, free;
341205b261ecSmrg
341305b261ecSmrg    if (mask & ~PropagateMask)
341405b261ecSmrg    {
341505b261ecSmrg	client->errorValue = mask;
341605b261ecSmrg	return BadValue;
341705b261ecSmrg    }
341805b261ecSmrg    if (pWin->dontPropagate)
341905b261ecSmrg	DontPropagateRefCnts[pWin->dontPropagate]--;
342005b261ecSmrg    if (!mask)
342105b261ecSmrg	i = 0;
342205b261ecSmrg    else
342305b261ecSmrg    {
342405b261ecSmrg	for (i = DNPMCOUNT, free = 0; --i > 0; )
342505b261ecSmrg	{
342605b261ecSmrg	    if (!DontPropagateRefCnts[i])
342705b261ecSmrg		free = i;
342805b261ecSmrg	    else if (mask == DontPropagateMasks[i])
342905b261ecSmrg		break;
343005b261ecSmrg	}
343105b261ecSmrg	if (!i && free)
343205b261ecSmrg	{
343305b261ecSmrg	    i = free;
343405b261ecSmrg	    DontPropagateMasks[i] = mask;
343505b261ecSmrg	}
343605b261ecSmrg    }
343705b261ecSmrg    if (i || !mask)
343805b261ecSmrg    {
343905b261ecSmrg	pWin->dontPropagate = i;
344005b261ecSmrg	if (i)
344105b261ecSmrg	    DontPropagateRefCnts[i]++;
344205b261ecSmrg	if (pWin->optional)
344305b261ecSmrg	{
344405b261ecSmrg	    pWin->optional->dontPropagateMask = mask;
344505b261ecSmrg	    *checkOptional = TRUE;
344605b261ecSmrg	}
344705b261ecSmrg    }
344805b261ecSmrg    else
344905b261ecSmrg    {
345005b261ecSmrg	if (!pWin->optional && !MakeWindowOptional (pWin))
345105b261ecSmrg	{
345205b261ecSmrg	    if (pWin->dontPropagate)
345305b261ecSmrg		DontPropagateRefCnts[pWin->dontPropagate]++;
345405b261ecSmrg	    return BadAlloc;
345505b261ecSmrg	}
345605b261ecSmrg	pWin->dontPropagate = 0;
345705b261ecSmrg        pWin->optional->dontPropagateMask = mask;
345805b261ecSmrg    }
345905b261ecSmrg    RecalculateDeliverableEvents(pWin);
346005b261ecSmrg    return Success;
346105b261ecSmrg}
346205b261ecSmrg
346305b261ecSmrg/**
346405b261ecSmrg * @return The window that is the first ancestor of both a and b.
346505b261ecSmrg */
346605b261ecSmrgstatic WindowPtr
346705b261ecSmrgCommonAncestor(
346805b261ecSmrg    WindowPtr a,
346905b261ecSmrg    WindowPtr b)
347005b261ecSmrg{
347105b261ecSmrg    for (b = b->parent; b; b = b->parent)
347205b261ecSmrg	if (IsParent(b, a)) return b;
347305b261ecSmrg    return NullWindow;
347405b261ecSmrg}
347505b261ecSmrg
347605b261ecSmrg/**
347705b261ecSmrg * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
347805b261ecSmrg * The core devices are used to fill in the event fields.
347905b261ecSmrg */
348005b261ecSmrgstatic void
348105b261ecSmrgEnterLeaveEvent(
348205b261ecSmrg    int type,
348305b261ecSmrg    int mode,
348405b261ecSmrg    int detail,
348505b261ecSmrg    WindowPtr pWin,
348605b261ecSmrg    Window child)
348705b261ecSmrg{
348805b261ecSmrg    xEvent		event;
348905b261ecSmrg    DeviceIntPtr keybd = inputInfo.keyboard;
349005b261ecSmrg    WindowPtr		focus;
349105b261ecSmrg    DeviceIntPtr mouse = inputInfo.pointer;
349205b261ecSmrg    GrabPtr	grab = mouse->grab;
349305b261ecSmrg    Mask		mask;
349405b261ecSmrg
349505b261ecSmrg    if ((pWin == mouse->valuator->motionHintWindow) &&
349605b261ecSmrg	(detail != NotifyInferior))
349705b261ecSmrg	mouse->valuator->motionHintWindow = NullWindow;
349805b261ecSmrg    if (grab)
349905b261ecSmrg    {
350005b261ecSmrg	mask = (pWin == grab->window) ? grab->eventMask : 0;
350105b261ecSmrg	if (grab->ownerEvents)
350205b261ecSmrg	    mask |= EventMaskForClient(pWin, rClient(grab));
350305b261ecSmrg    }
350405b261ecSmrg    else
350505b261ecSmrg    {
350605b261ecSmrg	mask = pWin->eventMask | wOtherEventMasks(pWin);
350705b261ecSmrg    }
350805b261ecSmrg    if (mask & filters[type])
350905b261ecSmrg    {
351005b261ecSmrg	event.u.u.type = type;
351105b261ecSmrg	event.u.u.detail = detail;
351205b261ecSmrg	event.u.enterLeave.time = currentTime.milliseconds;
351305b261ecSmrg	event.u.enterLeave.rootX = sprite.hot.x;
351405b261ecSmrg	event.u.enterLeave.rootY = sprite.hot.y;
351505b261ecSmrg	/* Counts on the same initial structure of crossing & button events! */
351605b261ecSmrg	FixUpEventFromWindow(&event, pWin, None, FALSE);
351705b261ecSmrg	/* Enter/Leave events always set child */
351805b261ecSmrg	event.u.enterLeave.child = child;
351905b261ecSmrg	event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
352005b261ecSmrg					    ELFlagSameScreen : 0;
352105b261ecSmrg#ifdef XKB
352205b261ecSmrg	if (!noXkbExtension) {
352305b261ecSmrg	    event.u.enterLeave.state = mouse->button->state & 0x1f00;
352405b261ecSmrg	    event.u.enterLeave.state |=
352505b261ecSmrg			XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
352605b261ecSmrg	} else
352705b261ecSmrg#endif
352805b261ecSmrg	event.u.enterLeave.state = keybd->key->state | mouse->button->state;
352905b261ecSmrg	event.u.enterLeave.mode = mode;
353005b261ecSmrg	focus = keybd->focus->win;
353105b261ecSmrg	if ((focus != NoneWin) &&
353205b261ecSmrg	    ((pWin == focus) || (focus == PointerRootWin) ||
353305b261ecSmrg	     IsParent(focus, pWin)))
353405b261ecSmrg	    event.u.enterLeave.flags |= ELFlagFocus;
353505b261ecSmrg	if (grab)
353605b261ecSmrg	    (void)TryClientEvents(rClient(grab), &event, 1, mask,
353705b261ecSmrg				  filters[type], grab);
353805b261ecSmrg	else
353905b261ecSmrg	    (void)DeliverEventsToWindow(pWin, &event, 1, filters[type],
354005b261ecSmrg					NullGrab, 0);
354105b261ecSmrg    }
354205b261ecSmrg    if ((type == EnterNotify) && (mask & KeymapStateMask))
354305b261ecSmrg    {
354405b261ecSmrg	xKeymapEvent ke;
354505b261ecSmrg	ClientPtr client = grab ? rClient(grab)
354605b261ecSmrg				: clients[CLIENT_ID(pWin->drawable.id)];
354705b261ecSmrg	if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, FALSE))
354805b261ecSmrg	    memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31);
354905b261ecSmrg	else
355005b261ecSmrg	    bzero((char *)&ke.map[0], 31);
355105b261ecSmrg
355205b261ecSmrg	ke.type = KeymapNotify;
355305b261ecSmrg	if (grab)
355405b261ecSmrg	    (void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask,
355505b261ecSmrg				  KeymapStateMask, grab);
355605b261ecSmrg	else
355705b261ecSmrg	    (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1,
355805b261ecSmrg					KeymapStateMask, NullGrab, 0);
355905b261ecSmrg    }
356005b261ecSmrg}
356105b261ecSmrg
356205b261ecSmrg/**
356305b261ecSmrg * Send enter notifies to all parent windows up to ancestor.
356405b261ecSmrg * This function recurses.
356505b261ecSmrg */
356605b261ecSmrgstatic void
356705b261ecSmrgEnterNotifies(WindowPtr ancestor, WindowPtr child, int mode, int detail)
356805b261ecSmrg{
356905b261ecSmrg    WindowPtr	parent = child->parent;
357005b261ecSmrg
357105b261ecSmrg    if (ancestor == parent)
357205b261ecSmrg	return;
357305b261ecSmrg    EnterNotifies(ancestor, parent, mode, detail);
357405b261ecSmrg    EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id);
357505b261ecSmrg}
357605b261ecSmrg
357705b261ecSmrg
357805b261ecSmrg/**
357905b261ecSmrg * Send leave notifies to all parent windows up to ancestor.
358005b261ecSmrg * This function recurses.
358105b261ecSmrg */
358205b261ecSmrgstatic void
358305b261ecSmrgLeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail)
358405b261ecSmrg{
358505b261ecSmrg    WindowPtr  pWin;
358605b261ecSmrg
358705b261ecSmrg    if (ancestor == child)
358805b261ecSmrg	return;
358905b261ecSmrg    for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent)
359005b261ecSmrg    {
359105b261ecSmrg	EnterLeaveEvent(LeaveNotify, mode, detail, pWin, child->drawable.id);
359205b261ecSmrg	child = pWin;
359305b261ecSmrg    }
359405b261ecSmrg}
359505b261ecSmrg
359605b261ecSmrg/**
359705b261ecSmrg * Figure out if enter/leave events are necessary and send them to the
359805b261ecSmrg * appropriate windows.
359905b261ecSmrg *
360005b261ecSmrg * @param fromWin Window the sprite moved out of.
360105b261ecSmrg * @param toWin Window the sprite moved into.
360205b261ecSmrg */
360305b261ecSmrgstatic void
360405b261ecSmrgDoEnterLeaveEvents(WindowPtr fromWin, WindowPtr toWin, int mode)
360505b261ecSmrg{
360605b261ecSmrg    if (fromWin == toWin)
360705b261ecSmrg	return;
360805b261ecSmrg    if (IsParent(fromWin, toWin))
360905b261ecSmrg    {
361005b261ecSmrg	EnterLeaveEvent(LeaveNotify, mode, NotifyInferior, fromWin, None);
361105b261ecSmrg	EnterNotifies(fromWin, toWin, mode, NotifyVirtual);
361205b261ecSmrg	EnterLeaveEvent(EnterNotify, mode, NotifyAncestor, toWin, None);
361305b261ecSmrg    }
361405b261ecSmrg    else if (IsParent(toWin, fromWin))
361505b261ecSmrg    {
361605b261ecSmrg	EnterLeaveEvent(LeaveNotify, mode, NotifyAncestor, fromWin, None);
361705b261ecSmrg	LeaveNotifies(fromWin, toWin, mode, NotifyVirtual);
361805b261ecSmrg	EnterLeaveEvent(EnterNotify, mode, NotifyInferior, toWin, None);
361905b261ecSmrg    }
362005b261ecSmrg    else
362105b261ecSmrg    { /* neither fromWin nor toWin is descendent of the other */
362205b261ecSmrg	WindowPtr common = CommonAncestor(toWin, fromWin);
362305b261ecSmrg	/* common == NullWindow ==> different screens */
362405b261ecSmrg	EnterLeaveEvent(LeaveNotify, mode, NotifyNonlinear, fromWin, None);
362505b261ecSmrg	LeaveNotifies(fromWin, common, mode, NotifyNonlinearVirtual);
362605b261ecSmrg	EnterNotifies(common, toWin, mode, NotifyNonlinearVirtual);
362705b261ecSmrg	EnterLeaveEvent(EnterNotify, mode, NotifyNonlinear, toWin, None);
362805b261ecSmrg    }
362905b261ecSmrg}
363005b261ecSmrg
363105b261ecSmrgstatic void
363205b261ecSmrgFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
363305b261ecSmrg{
363405b261ecSmrg    xEvent event;
363505b261ecSmrg
363605b261ecSmrg#ifdef XINPUT
363705b261ecSmrg    if (dev != inputInfo.keyboard)
363805b261ecSmrg    {
363905b261ecSmrg	DeviceFocusEvent(dev, type, mode, detail, pWin);
364005b261ecSmrg	return;
364105b261ecSmrg    }
364205b261ecSmrg#endif
364305b261ecSmrg    event.u.focus.mode = mode;
364405b261ecSmrg    event.u.u.type = type;
364505b261ecSmrg    event.u.u.detail = detail;
364605b261ecSmrg    event.u.focus.window = pWin->drawable.id;
364705b261ecSmrg    (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], NullGrab,
364805b261ecSmrg				0);
364905b261ecSmrg    if ((type == FocusIn) &&
365005b261ecSmrg	((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
365105b261ecSmrg    {
365205b261ecSmrg	xKeymapEvent ke;
365305b261ecSmrg	ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)];
365405b261ecSmrg	if (XaceHook(XACE_DEVICE_ACCESS, client, dev, FALSE))
365505b261ecSmrg	    memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
365605b261ecSmrg	else
365705b261ecSmrg	    bzero((char *)&ke.map[0], 31);
365805b261ecSmrg
365905b261ecSmrg	ke.type = KeymapNotify;
366005b261ecSmrg	(void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1,
366105b261ecSmrg				    KeymapStateMask, NullGrab, 0);
366205b261ecSmrg    }
366305b261ecSmrg}
366405b261ecSmrg
366505b261ecSmrg /*
366605b261ecSmrg  * recursive because it is easier
366705b261ecSmrg  * no-op if child not descended from ancestor
366805b261ecSmrg  */
366905b261ecSmrgstatic Bool
367005b261ecSmrgFocusInEvents(
367105b261ecSmrg    DeviceIntPtr dev,
367205b261ecSmrg    WindowPtr ancestor, WindowPtr child, WindowPtr skipChild,
367305b261ecSmrg    int mode, int detail,
367405b261ecSmrg    Bool doAncestor)
367505b261ecSmrg{
367605b261ecSmrg    if (child == NullWindow)
367705b261ecSmrg	return ancestor == NullWindow;
367805b261ecSmrg    if (ancestor == child)
367905b261ecSmrg    {
368005b261ecSmrg	if (doAncestor)
368105b261ecSmrg	    FocusEvent(dev, FocusIn, mode, detail, child);
368205b261ecSmrg	return TRUE;
368305b261ecSmrg    }
368405b261ecSmrg    if (FocusInEvents(dev, ancestor, child->parent, skipChild, mode, detail,
368505b261ecSmrg		      doAncestor))
368605b261ecSmrg    {
368705b261ecSmrg	if (child != skipChild)
368805b261ecSmrg	    FocusEvent(dev, FocusIn, mode, detail, child);
368905b261ecSmrg	return TRUE;
369005b261ecSmrg    }
369105b261ecSmrg    return FALSE;
369205b261ecSmrg}
369305b261ecSmrg
369405b261ecSmrg/* dies horribly if ancestor is not an ancestor of child */
369505b261ecSmrgstatic void
369605b261ecSmrgFocusOutEvents(
369705b261ecSmrg    DeviceIntPtr dev,
369805b261ecSmrg    WindowPtr child, WindowPtr ancestor,
369905b261ecSmrg    int mode, int detail,
370005b261ecSmrg    Bool doAncestor)
370105b261ecSmrg{
370205b261ecSmrg    WindowPtr  pWin;
370305b261ecSmrg
370405b261ecSmrg    for (pWin = child; pWin != ancestor; pWin = pWin->parent)
370505b261ecSmrg	FocusEvent(dev, FocusOut, mode, detail, pWin);
370605b261ecSmrg    if (doAncestor)
370705b261ecSmrg	FocusEvent(dev, FocusOut, mode, detail, ancestor);
370805b261ecSmrg}
370905b261ecSmrg
371005b261ecSmrgvoid
371105b261ecSmrgDoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
371205b261ecSmrg{
371305b261ecSmrg    int     out, in;		       /* for holding details for to/from
371405b261ecSmrg				          PointerRoot/None */
371505b261ecSmrg    int     i;
371605b261ecSmrg
371705b261ecSmrg    if (fromWin == toWin)
371805b261ecSmrg	return;
371905b261ecSmrg    out = (fromWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot;
372005b261ecSmrg    in = (toWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot;
372105b261ecSmrg /* wrong values if neither, but then not referenced */
372205b261ecSmrg
372305b261ecSmrg    if ((toWin == NullWindow) || (toWin == PointerRootWin))
372405b261ecSmrg    {
372505b261ecSmrg	if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
372605b261ecSmrg   	{
372705b261ecSmrg	    if (fromWin == PointerRootWin)
372805b261ecSmrg		FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
372905b261ecSmrg			       TRUE);
373005b261ecSmrg	    /* Notify all the roots */
373105b261ecSmrg#ifdef PANORAMIX
373205b261ecSmrg 	    if ( !noPanoramiXExtension )
373305b261ecSmrg	        FocusEvent(dev, FocusOut, mode, out, WindowTable[0]);
373405b261ecSmrg	    else
373505b261ecSmrg#endif
373605b261ecSmrg	        for (i=0; i<screenInfo.numScreens; i++)
373705b261ecSmrg	            FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
373805b261ecSmrg	}
373905b261ecSmrg	else
374005b261ecSmrg	{
374105b261ecSmrg	    if (IsParent(fromWin, sprite.win))
374205b261ecSmrg	      FocusOutEvents(dev, sprite.win, fromWin, mode, NotifyPointer,
374305b261ecSmrg			     FALSE);
374405b261ecSmrg	    FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
374505b261ecSmrg	    /* next call catches the root too, if the screen changed */
374605b261ecSmrg	    FocusOutEvents(dev, fromWin->parent, NullWindow, mode,
374705b261ecSmrg			   NotifyNonlinearVirtual, FALSE);
374805b261ecSmrg	}
374905b261ecSmrg	/* Notify all the roots */
375005b261ecSmrg#ifdef PANORAMIX
375105b261ecSmrg	if ( !noPanoramiXExtension )
375205b261ecSmrg	    FocusEvent(dev, FocusIn, mode, in, WindowTable[0]);
375305b261ecSmrg	else
375405b261ecSmrg#endif
375505b261ecSmrg	    for (i=0; i<screenInfo.numScreens; i++)
375605b261ecSmrg	        FocusEvent(dev, FocusIn, mode, in, WindowTable[i]);
375705b261ecSmrg	if (toWin == PointerRootWin)
375805b261ecSmrg	    (void)FocusInEvents(dev, ROOT, sprite.win, NullWindow, mode,
375905b261ecSmrg				NotifyPointer, TRUE);
376005b261ecSmrg    }
376105b261ecSmrg    else
376205b261ecSmrg    {
376305b261ecSmrg	if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
376405b261ecSmrg	{
376505b261ecSmrg	    if (fromWin == PointerRootWin)
376605b261ecSmrg		FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
376705b261ecSmrg			       TRUE);
376805b261ecSmrg#ifdef PANORAMIX
376905b261ecSmrg 	    if ( !noPanoramiXExtension )
377005b261ecSmrg	        FocusEvent(dev, FocusOut, mode, out, WindowTable[0]);
377105b261ecSmrg	    else
377205b261ecSmrg#endif
377305b261ecSmrg	        for (i=0; i<screenInfo.numScreens; i++)
377405b261ecSmrg	            FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
377505b261ecSmrg	    if (toWin->parent != NullWindow)
377605b261ecSmrg	      (void)FocusInEvents(dev, ROOT, toWin, toWin, mode,
377705b261ecSmrg				  NotifyNonlinearVirtual, TRUE);
377805b261ecSmrg	    FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
377905b261ecSmrg	    if (IsParent(toWin, sprite.win))
378005b261ecSmrg    	       (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode,
378105b261ecSmrg				   NotifyPointer, FALSE);
378205b261ecSmrg	}
378305b261ecSmrg	else
378405b261ecSmrg	{
378505b261ecSmrg	    if (IsParent(toWin, fromWin))
378605b261ecSmrg	    {
378705b261ecSmrg		FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin);
378805b261ecSmrg		FocusOutEvents(dev, fromWin->parent, toWin, mode,
378905b261ecSmrg			       NotifyVirtual, FALSE);
379005b261ecSmrg		FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin);
379105b261ecSmrg		if ((IsParent(toWin, sprite.win)) &&
379205b261ecSmrg			(sprite.win != fromWin) &&
379305b261ecSmrg			(!IsParent(fromWin, sprite.win)) &&
379405b261ecSmrg			(!IsParent(sprite.win, fromWin)))
379505b261ecSmrg		    (void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
379605b261ecSmrg					mode, NotifyPointer, FALSE);
379705b261ecSmrg	    }
379805b261ecSmrg	    else
379905b261ecSmrg		if (IsParent(fromWin, toWin))
380005b261ecSmrg		{
380105b261ecSmrg		    if ((IsParent(fromWin, sprite.win)) &&
380205b261ecSmrg			    (sprite.win != fromWin) &&
380305b261ecSmrg			    (!IsParent(toWin, sprite.win)) &&
380405b261ecSmrg			    (!IsParent(sprite.win, toWin)))
380505b261ecSmrg			FocusOutEvents(dev, sprite.win, fromWin, mode,
380605b261ecSmrg				       NotifyPointer, FALSE);
380705b261ecSmrg		    FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin);
380805b261ecSmrg		    (void)FocusInEvents(dev, fromWin, toWin, toWin, mode,
380905b261ecSmrg					NotifyVirtual, FALSE);
381005b261ecSmrg		    FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin);
381105b261ecSmrg		}
381205b261ecSmrg		else
381305b261ecSmrg		{
381405b261ecSmrg		/* neither fromWin or toWin is child of other */
381505b261ecSmrg		    WindowPtr common = CommonAncestor(toWin, fromWin);
381605b261ecSmrg		/* common == NullWindow ==> different screens */
381705b261ecSmrg		    if (IsParent(fromWin, sprite.win))
381805b261ecSmrg			FocusOutEvents(dev, sprite.win, fromWin, mode,
381905b261ecSmrg				       NotifyPointer, FALSE);
382005b261ecSmrg		    FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
382105b261ecSmrg		    if (fromWin->parent != NullWindow)
382205b261ecSmrg		      FocusOutEvents(dev, fromWin->parent, common, mode,
382305b261ecSmrg				     NotifyNonlinearVirtual, FALSE);
382405b261ecSmrg		    if (toWin->parent != NullWindow)
382505b261ecSmrg		      (void)FocusInEvents(dev, common, toWin, toWin, mode,
382605b261ecSmrg					  NotifyNonlinearVirtual, FALSE);
382705b261ecSmrg		    FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
382805b261ecSmrg		    if (IsParent(toWin, sprite.win))
382905b261ecSmrg			(void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
383005b261ecSmrg					    mode, NotifyPointer, FALSE);
383105b261ecSmrg		}
383205b261ecSmrg	}
383305b261ecSmrg    }
383405b261ecSmrg}
383505b261ecSmrg
383605b261ecSmrg/**
383705b261ecSmrg * Set the input focus to the given window. Subsequent keyboard events will be
383805b261ecSmrg * delivered to the given window.
383905b261ecSmrg *
384005b261ecSmrg * Usually called from ProcSetInputFocus as result of a client request. If so,
384105b261ecSmrg * the device is the inputInfo.keyboard.
384205b261ecSmrg * If called from ProcXSetInputFocus as result of a client xinput request, the
384305b261ecSmrg * device is set to the device specified by the client.
384405b261ecSmrg *
384505b261ecSmrg * @param client Client that requested input focus change.
384605b261ecSmrg * @param dev Focus device.
384705b261ecSmrg * @param focusID The window to obtain the focus. Can be PointerRoot or None.
384805b261ecSmrg * @param revertTo Specifies where the focus reverts to when window becomes
384905b261ecSmrg * unviewable.
385005b261ecSmrg * @param ctime Specifies the time.
385105b261ecSmrg * @param followOK True if pointer is allowed to follow the keyboard.
385205b261ecSmrg */
385305b261ecSmrgint
385405b261ecSmrgSetInputFocus(
385505b261ecSmrg    ClientPtr client,
385605b261ecSmrg    DeviceIntPtr dev,
385705b261ecSmrg    Window focusID,
385805b261ecSmrg    CARD8 revertTo,
385905b261ecSmrg    Time ctime,
386005b261ecSmrg    Bool followOK)
386105b261ecSmrg{
386205b261ecSmrg    FocusClassPtr focus;
386305b261ecSmrg    WindowPtr focusWin;
386405b261ecSmrg    int mode, rc;
386505b261ecSmrg    TimeStamp time;
386605b261ecSmrg
386705b261ecSmrg    UpdateCurrentTime();
386805b261ecSmrg    if ((revertTo != RevertToParent) &&
386905b261ecSmrg	(revertTo != RevertToPointerRoot) &&
387005b261ecSmrg	(revertTo != RevertToNone) &&
387105b261ecSmrg	((revertTo != RevertToFollowKeyboard) || !followOK))
387205b261ecSmrg    {
387305b261ecSmrg	client->errorValue = revertTo;
387405b261ecSmrg	return BadValue;
387505b261ecSmrg    }
387605b261ecSmrg    time = ClientTimeToServerTime(ctime);
387705b261ecSmrg    if ((focusID == None) || (focusID == PointerRoot))
387805b261ecSmrg	focusWin = (WindowPtr)(long)focusID;
387905b261ecSmrg    else if ((focusID == FollowKeyboard) && followOK)
388005b261ecSmrg	focusWin = inputInfo.keyboard->focus->win;
388105b261ecSmrg    else {
388205b261ecSmrg	rc = dixLookupWindow(&focusWin, focusID, client, DixReadAccess);
388305b261ecSmrg	if (rc != Success)
388405b261ecSmrg	    return rc;
388505b261ecSmrg 	/* It is a match error to try to set the input focus to an
388605b261ecSmrg	unviewable window. */
388705b261ecSmrg	if(!focusWin->realized)
388805b261ecSmrg	    return(BadMatch);
388905b261ecSmrg    }
389005b261ecSmrg    focus = dev->focus;
389105b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
389205b261ecSmrg	(CompareTimeStamps(time, focus->time) == EARLIER))
389305b261ecSmrg	return Success;
389405b261ecSmrg    mode = (dev->grab) ? NotifyWhileGrabbed : NotifyNormal;
389505b261ecSmrg    if (focus->win == FollowKeyboardWin)
389605b261ecSmrg	DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode);
389705b261ecSmrg    else
389805b261ecSmrg	DoFocusEvents(dev, focus->win, focusWin, mode);
389905b261ecSmrg    focus->time = time;
390005b261ecSmrg    focus->revert = revertTo;
390105b261ecSmrg    if (focusID == FollowKeyboard)
390205b261ecSmrg	focus->win = FollowKeyboardWin;
390305b261ecSmrg    else
390405b261ecSmrg	focus->win = focusWin;
390505b261ecSmrg    if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
390605b261ecSmrg	focus->traceGood = 0;
390705b261ecSmrg    else
390805b261ecSmrg    {
390905b261ecSmrg        int depth = 0;
391005b261ecSmrg	WindowPtr pWin;
391105b261ecSmrg
391205b261ecSmrg        for (pWin = focusWin; pWin; pWin = pWin->parent) depth++;
391305b261ecSmrg        if (depth > focus->traceSize)
391405b261ecSmrg        {
391505b261ecSmrg	    focus->traceSize = depth+1;
391605b261ecSmrg	    Must_have_memory = TRUE; /* XXX */
391705b261ecSmrg	    focus->trace = (WindowPtr *)xrealloc(focus->trace,
391805b261ecSmrg						 focus->traceSize *
391905b261ecSmrg						 sizeof(WindowPtr));
392005b261ecSmrg	    Must_have_memory = FALSE; /* XXX */
392105b261ecSmrg	}
392205b261ecSmrg	focus->traceGood = depth;
392305b261ecSmrg        for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
392405b261ecSmrg	    focus->trace[depth] = pWin;
392505b261ecSmrg    }
392605b261ecSmrg    return Success;
392705b261ecSmrg}
392805b261ecSmrg
392905b261ecSmrg/**
393005b261ecSmrg * Server-side protocol handling for SetInputFocus request.
393105b261ecSmrg *
393205b261ecSmrg * Sets the input focus for the virtual core keyboard.
393305b261ecSmrg */
393405b261ecSmrgint
393505b261ecSmrgProcSetInputFocus(client)
393605b261ecSmrg    ClientPtr client;
393705b261ecSmrg{
393805b261ecSmrg    REQUEST(xSetInputFocusReq);
393905b261ecSmrg
394005b261ecSmrg    REQUEST_SIZE_MATCH(xSetInputFocusReq);
394105b261ecSmrg
394205b261ecSmrg    if (!XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, TRUE))
394305b261ecSmrg	return Success;
394405b261ecSmrg
394505b261ecSmrg    return SetInputFocus(client, inputInfo.keyboard, stuff->focus,
394605b261ecSmrg			 stuff->revertTo, stuff->time, FALSE);
394705b261ecSmrg}
394805b261ecSmrg
394905b261ecSmrg/**
395005b261ecSmrg * Server-side protocol handling for GetInputFocus request.
395105b261ecSmrg *
395205b261ecSmrg * Sends the current input focus for the virtual core keyboard back to the
395305b261ecSmrg * client.
395405b261ecSmrg */
395505b261ecSmrgint
395605b261ecSmrgProcGetInputFocus(ClientPtr client)
395705b261ecSmrg{
395805b261ecSmrg    xGetInputFocusReply rep;
395905b261ecSmrg    /* REQUEST(xReq); */
396005b261ecSmrg    FocusClassPtr focus = inputInfo.keyboard->focus;
396105b261ecSmrg
396205b261ecSmrg    REQUEST_SIZE_MATCH(xReq);
396305b261ecSmrg    rep.type = X_Reply;
396405b261ecSmrg    rep.length = 0;
396505b261ecSmrg    rep.sequenceNumber = client->sequence;
396605b261ecSmrg    if (focus->win == NoneWin)
396705b261ecSmrg	rep.focus = None;
396805b261ecSmrg    else if (focus->win == PointerRootWin)
396905b261ecSmrg	rep.focus = PointerRoot;
397005b261ecSmrg    else rep.focus = focus->win->drawable.id;
397105b261ecSmrg    rep.revertTo = focus->revert;
397205b261ecSmrg    WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
397305b261ecSmrg    return Success;
397405b261ecSmrg}
397505b261ecSmrg
397605b261ecSmrg/**
397705b261ecSmrg * Server-side protocol handling for Grabpointer request.
397805b261ecSmrg *
397905b261ecSmrg * Sets an active grab on the inputInfo.pointer and returns success status to
398005b261ecSmrg * client.
398105b261ecSmrg */
398205b261ecSmrgint
398305b261ecSmrgProcGrabPointer(ClientPtr client)
398405b261ecSmrg{
398505b261ecSmrg    xGrabPointerReply rep;
398605b261ecSmrg    DeviceIntPtr device = inputInfo.pointer;
398705b261ecSmrg    GrabPtr grab;
398805b261ecSmrg    WindowPtr pWin, confineTo;
398905b261ecSmrg    CursorPtr cursor, oldCursor;
399005b261ecSmrg    REQUEST(xGrabPointerReq);
399105b261ecSmrg    TimeStamp time;
399205b261ecSmrg    int rc;
399305b261ecSmrg
399405b261ecSmrg    REQUEST_SIZE_MATCH(xGrabPointerReq);
399505b261ecSmrg    UpdateCurrentTime();
399605b261ecSmrg    if ((stuff->pointerMode != GrabModeSync) &&
399705b261ecSmrg	(stuff->pointerMode != GrabModeAsync))
399805b261ecSmrg    {
399905b261ecSmrg	client->errorValue = stuff->pointerMode;
400005b261ecSmrg        return BadValue;
400105b261ecSmrg    }
400205b261ecSmrg    if ((stuff->keyboardMode != GrabModeSync) &&
400305b261ecSmrg	(stuff->keyboardMode != GrabModeAsync))
400405b261ecSmrg    {
400505b261ecSmrg	client->errorValue = stuff->keyboardMode;
400605b261ecSmrg        return BadValue;
400705b261ecSmrg    }
400805b261ecSmrg    if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
400905b261ecSmrg    {
401005b261ecSmrg	client->errorValue = stuff->ownerEvents;
401105b261ecSmrg        return BadValue;
401205b261ecSmrg    }
401305b261ecSmrg    if (stuff->eventMask & ~PointerGrabMask)
401405b261ecSmrg    {
401505b261ecSmrg	client->errorValue = stuff->eventMask;
401605b261ecSmrg        return BadValue;
401705b261ecSmrg    }
401805b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
401905b261ecSmrg    if (rc != Success)
402005b261ecSmrg	return rc;
402105b261ecSmrg    if (stuff->confineTo == None)
402205b261ecSmrg	confineTo = NullWindow;
402305b261ecSmrg    else
402405b261ecSmrg    {
402505b261ecSmrg	rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
402605b261ecSmrg			     DixReadAccess);
402705b261ecSmrg	if (rc != Success)
402805b261ecSmrg	    return rc;
402905b261ecSmrg    }
403005b261ecSmrg    if (stuff->cursor == None)
403105b261ecSmrg	cursor = NullCursor;
403205b261ecSmrg    else
403305b261ecSmrg    {
403405b261ecSmrg	cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
403505b261ecSmrg						RT_CURSOR, DixReadAccess);
403605b261ecSmrg	if (!cursor)
403705b261ecSmrg	{
403805b261ecSmrg	    client->errorValue = stuff->cursor;
403905b261ecSmrg	    return BadCursor;
404005b261ecSmrg	}
404105b261ecSmrg    }
404205b261ecSmrg	/* at this point, some sort of reply is guaranteed. */
404305b261ecSmrg    time = ClientTimeToServerTime(stuff->time);
404405b261ecSmrg    rep.type = X_Reply;
404505b261ecSmrg    rep.sequenceNumber = client->sequence;
404605b261ecSmrg    rep.length = 0;
404705b261ecSmrg    grab = device->grab;
404805b261ecSmrg    if ((grab) && !SameClient(grab, client))
404905b261ecSmrg	rep.status = AlreadyGrabbed;
405005b261ecSmrg    else if ((!pWin->realized) ||
405105b261ecSmrg             (confineTo &&
405205b261ecSmrg                !(confineTo->realized && BorderSizeNotEmpty(confineTo))))
405305b261ecSmrg	rep.status = GrabNotViewable;
405405b261ecSmrg    else if (device->sync.frozen &&
405505b261ecSmrg	     device->sync.other && !SameClient(device->sync.other, client))
405605b261ecSmrg	rep.status = GrabFrozen;
405705b261ecSmrg    else if ((CompareTimeStamps(time, currentTime) == LATER) ||
405805b261ecSmrg	     (CompareTimeStamps(time, device->grabTime) == EARLIER))
405905b261ecSmrg	rep.status = GrabInvalidTime;
406005b261ecSmrg    else
406105b261ecSmrg    {
406205b261ecSmrg	GrabRec tempGrab;
406305b261ecSmrg
406405b261ecSmrg	oldCursor = NullCursor;
406505b261ecSmrg	if (grab)
406605b261ecSmrg 	{
406705b261ecSmrg	    if (grab->confineTo && !confineTo)
406805b261ecSmrg		ConfineCursorToWindow(ROOT, FALSE, FALSE);
406905b261ecSmrg	    oldCursor = grab->cursor;
407005b261ecSmrg	}
407105b261ecSmrg	tempGrab.cursor = cursor;
407205b261ecSmrg	tempGrab.resource = client->clientAsMask;
407305b261ecSmrg	tempGrab.ownerEvents = stuff->ownerEvents;
407405b261ecSmrg	tempGrab.eventMask = stuff->eventMask;
407505b261ecSmrg	tempGrab.confineTo = confineTo;
407605b261ecSmrg	tempGrab.window = pWin;
407705b261ecSmrg	tempGrab.keyboardMode = stuff->keyboardMode;
407805b261ecSmrg	tempGrab.pointerMode = stuff->pointerMode;
407905b261ecSmrg	tempGrab.device = device;
408005b261ecSmrg	(*device->ActivateGrab)(device, &tempGrab, time, FALSE);
408105b261ecSmrg	if (oldCursor)
408205b261ecSmrg	    FreeCursor (oldCursor, (Cursor)0);
408305b261ecSmrg	rep.status = GrabSuccess;
408405b261ecSmrg    }
408505b261ecSmrg    WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
408605b261ecSmrg    return Success;
408705b261ecSmrg}
408805b261ecSmrg
408905b261ecSmrg/**
409005b261ecSmrg * Server-side protocol handling for ChangeActivePointerGrab request.
409105b261ecSmrg *
409205b261ecSmrg * Changes properties of the grab hold by the client. If the client does not
409305b261ecSmrg * hold an active grab on the device, nothing happens.
409405b261ecSmrg *
409505b261ecSmrg * Works on the core pointer only.
409605b261ecSmrg */
409705b261ecSmrgint
409805b261ecSmrgProcChangeActivePointerGrab(ClientPtr client)
409905b261ecSmrg{
410005b261ecSmrg    DeviceIntPtr device = inputInfo.pointer;
410105b261ecSmrg    GrabPtr grab = device->grab;
410205b261ecSmrg    CursorPtr newCursor, oldCursor;
410305b261ecSmrg    REQUEST(xChangeActivePointerGrabReq);
410405b261ecSmrg    TimeStamp time;
410505b261ecSmrg
410605b261ecSmrg    REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
410705b261ecSmrg    if (stuff->eventMask & ~PointerGrabMask)
410805b261ecSmrg    {
410905b261ecSmrg	client->errorValue = stuff->eventMask;
411005b261ecSmrg        return BadValue;
411105b261ecSmrg    }
411205b261ecSmrg    if (stuff->cursor == None)
411305b261ecSmrg	newCursor = NullCursor;
411405b261ecSmrg    else
411505b261ecSmrg    {
411605b261ecSmrg	newCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
411705b261ecSmrg						RT_CURSOR, DixReadAccess);
411805b261ecSmrg	if (!newCursor)
411905b261ecSmrg	{
412005b261ecSmrg	    client->errorValue = stuff->cursor;
412105b261ecSmrg	    return BadCursor;
412205b261ecSmrg	}
412305b261ecSmrg    }
412405b261ecSmrg    if (!grab)
412505b261ecSmrg	return Success;
412605b261ecSmrg    if (!SameClient(grab, client))
412705b261ecSmrg	return Success;
412805b261ecSmrg    time = ClientTimeToServerTime(stuff->time);
412905b261ecSmrg    if ((CompareTimeStamps(time, currentTime) == LATER) ||
413005b261ecSmrg	     (CompareTimeStamps(time, device->grabTime) == EARLIER))
413105b261ecSmrg	return Success;
413205b261ecSmrg    oldCursor = grab->cursor;
413305b261ecSmrg    grab->cursor = newCursor;
413405b261ecSmrg    if (newCursor)
413505b261ecSmrg	newCursor->refcnt++;
413605b261ecSmrg    PostNewCursor();
413705b261ecSmrg    if (oldCursor)
413805b261ecSmrg	FreeCursor(oldCursor, (Cursor)0);
413905b261ecSmrg    grab->eventMask = stuff->eventMask;
414005b261ecSmrg    return Success;
414105b261ecSmrg}
414205b261ecSmrg
414305b261ecSmrg/**
414405b261ecSmrg * Server-side protocol handling for UngrabPointer request.
414505b261ecSmrg *
414605b261ecSmrg * Deletes the pointer grab on the core pointer device.
414705b261ecSmrg */
414805b261ecSmrgint
414905b261ecSmrgProcUngrabPointer(ClientPtr client)
415005b261ecSmrg{
415105b261ecSmrg    DeviceIntPtr device = inputInfo.pointer;
415205b261ecSmrg    GrabPtr grab;
415305b261ecSmrg    TimeStamp time;
415405b261ecSmrg    REQUEST(xResourceReq);
415505b261ecSmrg
415605b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
415705b261ecSmrg    UpdateCurrentTime();
415805b261ecSmrg    grab = device->grab;
415905b261ecSmrg    time = ClientTimeToServerTime(stuff->id);
416005b261ecSmrg    if ((CompareTimeStamps(time, currentTime) != LATER) &&
416105b261ecSmrg	    (CompareTimeStamps(time, device->grabTime) != EARLIER) &&
416205b261ecSmrg	    (grab) && SameClient(grab, client))
416305b261ecSmrg	(*device->DeactivateGrab)(device);
416405b261ecSmrg    return Success;
416505b261ecSmrg}
416605b261ecSmrg
416705b261ecSmrg/**
416805b261ecSmrg * Sets a grab on the given device.
416905b261ecSmrg *
417005b261ecSmrg * Called from ProcGrabKeyboard to work on the inputInfo.keyboard.
417105b261ecSmrg * Called from ProcXGrabDevice to work on the device specified by the client.
417205b261ecSmrg *
417305b261ecSmrg * The parameters this_mode and other_mode represent the keyboard_mode and
417405b261ecSmrg * pointer_mode parameters of XGrabKeyboard().
417505b261ecSmrg * See man page for details on all the parameters
417605b261ecSmrg *
417705b261ecSmrg * @param client Client that owns the grab.
417805b261ecSmrg * @param dev The device to grab.
417905b261ecSmrg * @param this_mode GrabModeSync or GrabModeAsync
418005b261ecSmrg * @param other_mode GrabModeSync or GrabModeAsync
418105b261ecSmrg * @param status Return code to be returned to the caller.
418205b261ecSmrg *
418305b261ecSmrg * @returns Success or BadValue.
418405b261ecSmrg */
418505b261ecSmrgint
418605b261ecSmrgGrabDevice(ClientPtr client, DeviceIntPtr dev,
418705b261ecSmrg           unsigned this_mode, unsigned other_mode, Window grabWindow,
418805b261ecSmrg           unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status)
418905b261ecSmrg{
419005b261ecSmrg    WindowPtr pWin;
419105b261ecSmrg    GrabPtr grab;
419205b261ecSmrg    TimeStamp time;
419305b261ecSmrg    int rc;
419405b261ecSmrg
419505b261ecSmrg    UpdateCurrentTime();
419605b261ecSmrg    if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync))
419705b261ecSmrg    {
419805b261ecSmrg	client->errorValue = this_mode;
419905b261ecSmrg        return BadValue;
420005b261ecSmrg    }
420105b261ecSmrg    if ((other_mode != GrabModeSync) && (other_mode != GrabModeAsync))
420205b261ecSmrg    {
420305b261ecSmrg	client->errorValue = other_mode;
420405b261ecSmrg        return BadValue;
420505b261ecSmrg    }
420605b261ecSmrg    if ((ownerEvents != xFalse) && (ownerEvents != xTrue))
420705b261ecSmrg    {
420805b261ecSmrg	client->errorValue = ownerEvents;
420905b261ecSmrg        return BadValue;
421005b261ecSmrg    }
421105b261ecSmrg    rc = dixLookupWindow(&pWin, grabWindow, client, DixReadAccess);
421205b261ecSmrg    if (rc != Success)
421305b261ecSmrg	return rc;
421405b261ecSmrg    time = ClientTimeToServerTime(ctime);
421505b261ecSmrg    grab = dev->grab;
421605b261ecSmrg    if (grab && !SameClient(grab, client))
421705b261ecSmrg	*status = AlreadyGrabbed;
421805b261ecSmrg    else if (!pWin->realized)
421905b261ecSmrg	*status = GrabNotViewable;
422005b261ecSmrg    else if ((CompareTimeStamps(time, currentTime) == LATER) ||
422105b261ecSmrg	     (CompareTimeStamps(time, dev->grabTime) == EARLIER))
422205b261ecSmrg	*status = GrabInvalidTime;
422305b261ecSmrg    else if (dev->sync.frozen &&
422405b261ecSmrg	     dev->sync.other && !SameClient(dev->sync.other, client))
422505b261ecSmrg	*status = GrabFrozen;
422605b261ecSmrg    else
422705b261ecSmrg    {
422805b261ecSmrg	GrabRec tempGrab;
422905b261ecSmrg
423005b261ecSmrg	tempGrab.window = pWin;
423105b261ecSmrg	tempGrab.resource = client->clientAsMask;
423205b261ecSmrg	tempGrab.ownerEvents = ownerEvents;
423305b261ecSmrg	tempGrab.keyboardMode = this_mode;
423405b261ecSmrg	tempGrab.pointerMode = other_mode;
423505b261ecSmrg	tempGrab.eventMask = mask;
423605b261ecSmrg	tempGrab.device = dev;
423705b261ecSmrg	(*dev->ActivateGrab)(dev, &tempGrab, time, FALSE);
423805b261ecSmrg	*status = GrabSuccess;
423905b261ecSmrg    }
424005b261ecSmrg    return Success;
424105b261ecSmrg}
424205b261ecSmrg
424305b261ecSmrg/**
424405b261ecSmrg * Server-side protocol handling for GrabKeyboard request.
424505b261ecSmrg *
424605b261ecSmrg * Grabs the inputInfo.keyboad and returns success status to client.
424705b261ecSmrg */
424805b261ecSmrgint
424905b261ecSmrgProcGrabKeyboard(ClientPtr client)
425005b261ecSmrg{
425105b261ecSmrg    xGrabKeyboardReply rep;
425205b261ecSmrg    REQUEST(xGrabKeyboardReq);
425305b261ecSmrg    int result;
425405b261ecSmrg
425505b261ecSmrg    REQUEST_SIZE_MATCH(xGrabKeyboardReq);
425605b261ecSmrg
425705b261ecSmrg    if (XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, TRUE))
425805b261ecSmrg	result = GrabDevice(client, inputInfo.keyboard, stuff->keyboardMode,
425905b261ecSmrg			    stuff->pointerMode, stuff->grabWindow,
426005b261ecSmrg			    stuff->ownerEvents, stuff->time,
426105b261ecSmrg			    KeyPressMask | KeyReleaseMask, &rep.status);
426205b261ecSmrg    else {
426305b261ecSmrg	result = Success;
426405b261ecSmrg	rep.status = AlreadyGrabbed;
426505b261ecSmrg    }
426605b261ecSmrg
426705b261ecSmrg    if (result != Success)
426805b261ecSmrg	return result;
426905b261ecSmrg    rep.type = X_Reply;
427005b261ecSmrg    rep.sequenceNumber = client->sequence;
427105b261ecSmrg    rep.length = 0;
427205b261ecSmrg    WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
427305b261ecSmrg    return Success;
427405b261ecSmrg}
427505b261ecSmrg
427605b261ecSmrg/**
427705b261ecSmrg * Server-side protocol handling for UngrabKeyboard request.
427805b261ecSmrg *
427905b261ecSmrg * Deletes a possible grab on the inputInfo.keyboard.
428005b261ecSmrg */
428105b261ecSmrgint
428205b261ecSmrgProcUngrabKeyboard(ClientPtr client)
428305b261ecSmrg{
428405b261ecSmrg    DeviceIntPtr device = inputInfo.keyboard;
428505b261ecSmrg    GrabPtr grab;
428605b261ecSmrg    TimeStamp time;
428705b261ecSmrg    REQUEST(xResourceReq);
428805b261ecSmrg
428905b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
429005b261ecSmrg    UpdateCurrentTime();
429105b261ecSmrg    grab = device->grab;
429205b261ecSmrg    time = ClientTimeToServerTime(stuff->id);
429305b261ecSmrg    if ((CompareTimeStamps(time, currentTime) != LATER) &&
429405b261ecSmrg	(CompareTimeStamps(time, device->grabTime) != EARLIER) &&
429505b261ecSmrg	(grab) && SameClient(grab, client))
429605b261ecSmrg	(*device->DeactivateGrab)(device);
429705b261ecSmrg    return Success;
429805b261ecSmrg}
429905b261ecSmrg
430005b261ecSmrg/**
430105b261ecSmrg * Server-side protocol handling for QueryPointer request.
430205b261ecSmrg *
430305b261ecSmrg * Returns the current state and position of the core pointer to the client.
430405b261ecSmrg */
430505b261ecSmrgint
430605b261ecSmrgProcQueryPointer(ClientPtr client)
430705b261ecSmrg{
430805b261ecSmrg    xQueryPointerReply rep;
430905b261ecSmrg    WindowPtr pWin, t;
431005b261ecSmrg    REQUEST(xResourceReq);
431105b261ecSmrg    DeviceIntPtr mouse = inputInfo.pointer;
431205b261ecSmrg    int rc;
431305b261ecSmrg
431405b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
431505b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess);
431605b261ecSmrg    if (rc != Success)
431705b261ecSmrg	return rc;
431805b261ecSmrg    if (mouse->valuator->motionHintWindow)
431905b261ecSmrg	MaybeStopHint(mouse, client);
432005b261ecSmrg    rep.type = X_Reply;
432105b261ecSmrg    rep.sequenceNumber = client->sequence;
432205b261ecSmrg    rep.mask = mouse->button->state | inputInfo.keyboard->key->state;
432305b261ecSmrg    rep.length = 0;
432405b261ecSmrg    rep.root = (ROOT)->drawable.id;
432505b261ecSmrg    rep.rootX = sprite.hot.x;
432605b261ecSmrg    rep.rootY = sprite.hot.y;
432705b261ecSmrg    rep.child = None;
432805b261ecSmrg    if (sprite.hot.pScreen == pWin->drawable.pScreen)
432905b261ecSmrg    {
433005b261ecSmrg	rep.sameScreen = xTrue;
433105b261ecSmrg	rep.winX = sprite.hot.x - pWin->drawable.x;
433205b261ecSmrg	rep.winY = sprite.hot.y - pWin->drawable.y;
433305b261ecSmrg	for (t = sprite.win; t; t = t->parent)
433405b261ecSmrg	    if (t->parent == pWin)
433505b261ecSmrg	    {
433605b261ecSmrg		rep.child = t->drawable.id;
433705b261ecSmrg		break;
433805b261ecSmrg	    }
433905b261ecSmrg    }
434005b261ecSmrg    else
434105b261ecSmrg    {
434205b261ecSmrg	rep.sameScreen = xFalse;
434305b261ecSmrg	rep.winX = 0;
434405b261ecSmrg	rep.winY = 0;
434505b261ecSmrg    }
434605b261ecSmrg
434705b261ecSmrg#ifdef PANORAMIX
434805b261ecSmrg    if(!noPanoramiXExtension) {
434905b261ecSmrg	rep.rootX += panoramiXdataPtr[0].x;
435005b261ecSmrg	rep.rootY += panoramiXdataPtr[0].y;
435105b261ecSmrg	if(stuff->id == rep.root) {
435205b261ecSmrg	    rep.winX += panoramiXdataPtr[0].x;
435305b261ecSmrg	    rep.winY += panoramiXdataPtr[0].y;
435405b261ecSmrg	}
435505b261ecSmrg    }
435605b261ecSmrg#endif
435705b261ecSmrg
435805b261ecSmrg    WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
435905b261ecSmrg
436005b261ecSmrg    return(Success);
436105b261ecSmrg}
436205b261ecSmrg
436305b261ecSmrg/**
436405b261ecSmrg * Initializes the device list and the DIX sprite to sane values. Allocates
436505b261ecSmrg * trace memory used for quick window traversal.
436605b261ecSmrg */
436705b261ecSmrgvoid
436805b261ecSmrgInitEvents(void)
436905b261ecSmrg{
437005b261ecSmrg    int i;
437105b261ecSmrg
437205b261ecSmrg    sprite.hot.pScreen = sprite.hotPhys.pScreen = (ScreenPtr)NULL;
437305b261ecSmrg    inputInfo.numDevices = 0;
437405b261ecSmrg    inputInfo.devices = (DeviceIntPtr)NULL;
437505b261ecSmrg    inputInfo.off_devices = (DeviceIntPtr)NULL;
437605b261ecSmrg    inputInfo.keyboard = (DeviceIntPtr)NULL;
437705b261ecSmrg    inputInfo.pointer = (DeviceIntPtr)NULL;
437805b261ecSmrg    if (spriteTraceSize == 0)
437905b261ecSmrg    {
438005b261ecSmrg	spriteTraceSize = 32;
438105b261ecSmrg	spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr));
438205b261ecSmrg	if (!spriteTrace)
438305b261ecSmrg	    FatalError("failed to allocate spriteTrace");
438405b261ecSmrg    }
438505b261ecSmrg    spriteTraceGood = 0;
438605b261ecSmrg    lastEventMask = OwnerGrabButtonMask;
438705b261ecSmrg    filters[MotionNotify] = PointerMotionMask;
438805b261ecSmrg#ifdef XEVIE
438905b261ecSmrg    xeviewin =
439005b261ecSmrg#endif
439105b261ecSmrg    sprite.win = NullWindow;
439205b261ecSmrg    sprite.current = NullCursor;
439305b261ecSmrg    sprite.hotLimits.x1 = 0;
439405b261ecSmrg    sprite.hotLimits.y1 = 0;
439505b261ecSmrg    sprite.hotLimits.x2 = 0;
439605b261ecSmrg    sprite.hotLimits.y2 = 0;
439705b261ecSmrg    sprite.confined = FALSE;
439805b261ecSmrg    syncEvents.replayDev = (DeviceIntPtr)NULL;
439905b261ecSmrg    syncEvents.replayWin = NullWindow;
440005b261ecSmrg    while (syncEvents.pending)
440105b261ecSmrg    {
440205b261ecSmrg	QdEventPtr next = syncEvents.pending->next;
440305b261ecSmrg	xfree(syncEvents.pending);
440405b261ecSmrg	syncEvents.pending = next;
440505b261ecSmrg    }
440605b261ecSmrg    syncEvents.pendtail = &syncEvents.pending;
440705b261ecSmrg    syncEvents.playingEvents = FALSE;
440805b261ecSmrg    syncEvents.time.months = 0;
440905b261ecSmrg    syncEvents.time.milliseconds = 0;	/* hardly matters */
441005b261ecSmrg    currentTime.months = 0;
441105b261ecSmrg    currentTime.milliseconds = GetTimeInMillis();
441205b261ecSmrg    lastDeviceEventTime = currentTime;
441305b261ecSmrg    for (i = 0; i < DNPMCOUNT; i++)
441405b261ecSmrg    {
441505b261ecSmrg	DontPropagateMasks[i] = 0;
441605b261ecSmrg	DontPropagateRefCnts[i] = 0;
441705b261ecSmrg    }
441805b261ecSmrg}
441905b261ecSmrg
442005b261ecSmrgvoid
442105b261ecSmrgCloseDownEvents(void)
442205b261ecSmrg{
442305b261ecSmrg  xfree(spriteTrace);
442405b261ecSmrg  spriteTrace = NULL;
442505b261ecSmrg  spriteTraceSize = 0;
442605b261ecSmrg}
442705b261ecSmrg
442805b261ecSmrg/**
442905b261ecSmrg * Server-side protocol handling for SendEvent request.
443005b261ecSmrg *
443105b261ecSmrg * Locates the window to send the event to and forwards the event.
443205b261ecSmrg */
443305b261ecSmrgint
443405b261ecSmrgProcSendEvent(ClientPtr client)
443505b261ecSmrg{
443605b261ecSmrg    WindowPtr pWin;
443705b261ecSmrg    WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
443805b261ecSmrg    REQUEST(xSendEventReq);
443905b261ecSmrg
444005b261ecSmrg    REQUEST_SIZE_MATCH(xSendEventReq);
444105b261ecSmrg
444205b261ecSmrg    /* The client's event type must be a core event type or one defined by an
444305b261ecSmrg	extension. */
444405b261ecSmrg
444505b261ecSmrg    if ( ! ((stuff->event.u.u.type > X_Reply &&
444605b261ecSmrg	     stuff->event.u.u.type < LASTEvent) ||
444705b261ecSmrg	    (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
444805b261ecSmrg	     stuff->event.u.u.type < (unsigned)lastEvent)))
444905b261ecSmrg    {
445005b261ecSmrg	client->errorValue = stuff->event.u.u.type;
445105b261ecSmrg	return BadValue;
445205b261ecSmrg    }
445305b261ecSmrg    if (stuff->event.u.u.type == ClientMessage &&
445405b261ecSmrg	stuff->event.u.u.detail != 8 &&
445505b261ecSmrg	stuff->event.u.u.detail != 16 &&
445605b261ecSmrg	stuff->event.u.u.detail != 32)
445705b261ecSmrg    {
445805b261ecSmrg	client->errorValue = stuff->event.u.u.detail;
445905b261ecSmrg	return BadValue;
446005b261ecSmrg    }
446105b261ecSmrg    if (stuff->eventMask & ~AllEventMasks)
446205b261ecSmrg    {
446305b261ecSmrg	client->errorValue = stuff->eventMask;
446405b261ecSmrg	return BadValue;
446505b261ecSmrg    }
446605b261ecSmrg
446705b261ecSmrg    if (stuff->destination == PointerWindow)
446805b261ecSmrg	pWin = sprite.win;
446905b261ecSmrg    else if (stuff->destination == InputFocus)
447005b261ecSmrg    {
447105b261ecSmrg	WindowPtr inputFocus = inputInfo.keyboard->focus->win;
447205b261ecSmrg
447305b261ecSmrg	if (inputFocus == NoneWin)
447405b261ecSmrg	    return Success;
447505b261ecSmrg
447605b261ecSmrg	/* If the input focus is PointerRootWin, send the event to where
447705b261ecSmrg	the pointer is if possible, then perhaps propogate up to root. */
447805b261ecSmrg   	if (inputFocus == PointerRootWin)
447905b261ecSmrg	    inputFocus = ROOT;
448005b261ecSmrg
448105b261ecSmrg	if (IsParent(inputFocus, sprite.win))
448205b261ecSmrg	{
448305b261ecSmrg	    effectiveFocus = inputFocus;
448405b261ecSmrg	    pWin = sprite.win;
448505b261ecSmrg	}
448605b261ecSmrg	else
448705b261ecSmrg	    effectiveFocus = pWin = inputFocus;
448805b261ecSmrg    }
448905b261ecSmrg    else
449005b261ecSmrg	dixLookupWindow(&pWin, stuff->destination, client, DixReadAccess);
449105b261ecSmrg
449205b261ecSmrg    if (!pWin)
449305b261ecSmrg	return BadWindow;
449405b261ecSmrg    if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue))
449505b261ecSmrg    {
449605b261ecSmrg	client->errorValue = stuff->propagate;
449705b261ecSmrg	return BadValue;
449805b261ecSmrg    }
449905b261ecSmrg    stuff->event.u.u.type |= 0x80;
450005b261ecSmrg    if (stuff->propagate)
450105b261ecSmrg    {
450205b261ecSmrg	for (;pWin; pWin = pWin->parent)
450305b261ecSmrg	{
450405b261ecSmrg	    if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask,
450505b261ecSmrg				      NullGrab, 0))
450605b261ecSmrg		return Success;
450705b261ecSmrg	    if (pWin == effectiveFocus)
450805b261ecSmrg		return Success;
450905b261ecSmrg	    stuff->eventMask &= ~wDontPropagateMask(pWin);
451005b261ecSmrg	    if (!stuff->eventMask)
451105b261ecSmrg		break;
451205b261ecSmrg	}
451305b261ecSmrg    }
451405b261ecSmrg    else
451505b261ecSmrg	(void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask,
451605b261ecSmrg				    NullGrab, 0);
451705b261ecSmrg    return Success;
451805b261ecSmrg}
451905b261ecSmrg
452005b261ecSmrg/**
452105b261ecSmrg * Server-side protocol handling for UngrabKey request.
452205b261ecSmrg *
452305b261ecSmrg * Deletes a passive grab for the given key. Only works on the
452405b261ecSmrg * inputInfo.keyboard.
452505b261ecSmrg */
452605b261ecSmrgint
452705b261ecSmrgProcUngrabKey(ClientPtr client)
452805b261ecSmrg{
452905b261ecSmrg    REQUEST(xUngrabKeyReq);
453005b261ecSmrg    WindowPtr pWin;
453105b261ecSmrg    GrabRec tempGrab;
453205b261ecSmrg    DeviceIntPtr keybd = inputInfo.keyboard;
453305b261ecSmrg    int rc;
453405b261ecSmrg
453505b261ecSmrg    REQUEST_SIZE_MATCH(xUngrabKeyReq);
453605b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
453705b261ecSmrg    if (rc != Success)
453805b261ecSmrg	return rc;
453905b261ecSmrg
454005b261ecSmrg    if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) ||
454105b261ecSmrg	 (stuff->key < keybd->key->curKeySyms.minKeyCode))
454205b261ecSmrg	&& (stuff->key != AnyKey))
454305b261ecSmrg    {
454405b261ecSmrg	client->errorValue = stuff->key;
454505b261ecSmrg        return BadValue;
454605b261ecSmrg    }
454705b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
454805b261ecSmrg	(stuff->modifiers & ~AllModifiersMask))
454905b261ecSmrg    {
455005b261ecSmrg	client->errorValue = stuff->modifiers;
455105b261ecSmrg	return BadValue;
455205b261ecSmrg    }
455305b261ecSmrg    tempGrab.resource = client->clientAsMask;
455405b261ecSmrg    tempGrab.device = keybd;
455505b261ecSmrg    tempGrab.window = pWin;
455605b261ecSmrg    tempGrab.modifiersDetail.exact = stuff->modifiers;
455705b261ecSmrg    tempGrab.modifiersDetail.pMask = NULL;
455805b261ecSmrg    tempGrab.modifierDevice = inputInfo.keyboard;
455905b261ecSmrg    tempGrab.type = KeyPress;
456005b261ecSmrg    tempGrab.detail.exact = stuff->key;
456105b261ecSmrg    tempGrab.detail.pMask = NULL;
456205b261ecSmrg
456305b261ecSmrg    if (!DeletePassiveGrabFromList(&tempGrab))
456405b261ecSmrg	return(BadAlloc);
456505b261ecSmrg    return(Success);
456605b261ecSmrg}
456705b261ecSmrg
456805b261ecSmrg/**
456905b261ecSmrg * Server-side protocol handling for GrabKey request.
457005b261ecSmrg *
457105b261ecSmrg * Creates a grab for the inputInfo.keyboard and adds it to the list of
457205b261ecSmrg * passive grabs.
457305b261ecSmrg */
457405b261ecSmrgint
457505b261ecSmrgProcGrabKey(ClientPtr client)
457605b261ecSmrg{
457705b261ecSmrg    WindowPtr pWin;
457805b261ecSmrg    REQUEST(xGrabKeyReq);
457905b261ecSmrg    GrabPtr grab;
458005b261ecSmrg    DeviceIntPtr keybd = inputInfo.keyboard;
458105b261ecSmrg    int rc;
458205b261ecSmrg
458305b261ecSmrg    REQUEST_SIZE_MATCH(xGrabKeyReq);
458405b261ecSmrg    if ((stuff->ownerEvents != xTrue) && (stuff->ownerEvents != xFalse))
458505b261ecSmrg    {
458605b261ecSmrg	client->errorValue = stuff->ownerEvents;
458705b261ecSmrg	return(BadValue);
458805b261ecSmrg    }
458905b261ecSmrg    if ((stuff->pointerMode != GrabModeSync) &&
459005b261ecSmrg	(stuff->pointerMode != GrabModeAsync))
459105b261ecSmrg    {
459205b261ecSmrg	client->errorValue = stuff->pointerMode;
459305b261ecSmrg        return BadValue;
459405b261ecSmrg    }
459505b261ecSmrg    if ((stuff->keyboardMode != GrabModeSync) &&
459605b261ecSmrg	(stuff->keyboardMode != GrabModeAsync))
459705b261ecSmrg    {
459805b261ecSmrg	client->errorValue = stuff->keyboardMode;
459905b261ecSmrg        return BadValue;
460005b261ecSmrg    }
460105b261ecSmrg    if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) ||
460205b261ecSmrg	 (stuff->key < keybd->key->curKeySyms.minKeyCode))
460305b261ecSmrg	&& (stuff->key != AnyKey))
460405b261ecSmrg    {
460505b261ecSmrg	client->errorValue = stuff->key;
460605b261ecSmrg        return BadValue;
460705b261ecSmrg    }
460805b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
460905b261ecSmrg	(stuff->modifiers & ~AllModifiersMask))
461005b261ecSmrg    {
461105b261ecSmrg	client->errorValue = stuff->modifiers;
461205b261ecSmrg	return BadValue;
461305b261ecSmrg    }
461405b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
461505b261ecSmrg    if (rc != Success)
461605b261ecSmrg	return rc;
461705b261ecSmrg
461805b261ecSmrg    grab = CreateGrab(client->index, keybd, pWin,
461905b261ecSmrg	(Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents,
462005b261ecSmrg	(Bool)stuff->keyboardMode, (Bool)stuff->pointerMode,
462105b261ecSmrg	keybd, stuff->modifiers, KeyPress, stuff->key,
462205b261ecSmrg	NullWindow, NullCursor);
462305b261ecSmrg    if (!grab)
462405b261ecSmrg	return BadAlloc;
462505b261ecSmrg    return AddPassiveGrabToList(grab);
462605b261ecSmrg}
462705b261ecSmrg
462805b261ecSmrg
462905b261ecSmrg/**
463005b261ecSmrg * Server-side protocol handling for GrabButton request.
463105b261ecSmrg *
463205b261ecSmrg * Creates a grab for the inputInfo.pointer and adds it as a passive grab to
463305b261ecSmrg * the list.
463405b261ecSmrg */
463505b261ecSmrgint
463605b261ecSmrgProcGrabButton(ClientPtr client)
463705b261ecSmrg{
463805b261ecSmrg    WindowPtr pWin, confineTo;
463905b261ecSmrg    REQUEST(xGrabButtonReq);
464005b261ecSmrg    CursorPtr cursor;
464105b261ecSmrg    GrabPtr grab;
464205b261ecSmrg    int rc;
464305b261ecSmrg
464405b261ecSmrg    REQUEST_SIZE_MATCH(xGrabButtonReq);
464505b261ecSmrg    if ((stuff->pointerMode != GrabModeSync) &&
464605b261ecSmrg	(stuff->pointerMode != GrabModeAsync))
464705b261ecSmrg    {
464805b261ecSmrg	client->errorValue = stuff->pointerMode;
464905b261ecSmrg        return BadValue;
465005b261ecSmrg    }
465105b261ecSmrg    if ((stuff->keyboardMode != GrabModeSync) &&
465205b261ecSmrg	(stuff->keyboardMode != GrabModeAsync))
465305b261ecSmrg    {
465405b261ecSmrg	client->errorValue = stuff->keyboardMode;
465505b261ecSmrg        return BadValue;
465605b261ecSmrg    }
465705b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
465805b261ecSmrg	(stuff->modifiers & ~AllModifiersMask))
465905b261ecSmrg    {
466005b261ecSmrg	client->errorValue = stuff->modifiers;
466105b261ecSmrg	return BadValue;
466205b261ecSmrg    }
466305b261ecSmrg    if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
466405b261ecSmrg    {
466505b261ecSmrg	client->errorValue = stuff->ownerEvents;
466605b261ecSmrg	return BadValue;
466705b261ecSmrg    }
466805b261ecSmrg    if (stuff->eventMask & ~PointerGrabMask)
466905b261ecSmrg    {
467005b261ecSmrg	client->errorValue = stuff->eventMask;
467105b261ecSmrg        return BadValue;
467205b261ecSmrg    }
467305b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
467405b261ecSmrg    if (rc != Success)
467505b261ecSmrg	return rc;
467605b261ecSmrg    if (stuff->confineTo == None)
467705b261ecSmrg       confineTo = NullWindow;
467805b261ecSmrg    else {
467905b261ecSmrg	rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
468005b261ecSmrg			     DixReadAccess);
468105b261ecSmrg	if (rc != Success)
468205b261ecSmrg	    return rc;
468305b261ecSmrg    }
468405b261ecSmrg    if (stuff->cursor == None)
468505b261ecSmrg	cursor = NullCursor;
468605b261ecSmrg    else
468705b261ecSmrg    {
468805b261ecSmrg	cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
468905b261ecSmrg						RT_CURSOR, DixReadAccess);
469005b261ecSmrg	if (!cursor)
469105b261ecSmrg	{
469205b261ecSmrg	    client->errorValue = stuff->cursor;
469305b261ecSmrg	    return BadCursor;
469405b261ecSmrg	}
469505b261ecSmrg    }
469605b261ecSmrg
469705b261ecSmrg
469805b261ecSmrg    grab = CreateGrab(client->index, inputInfo.pointer, pWin,
469905b261ecSmrg        (Mask)stuff->eventMask, (Bool)stuff->ownerEvents,
470005b261ecSmrg        (Bool) stuff->keyboardMode, (Bool)stuff->pointerMode,
470105b261ecSmrg        inputInfo.keyboard, stuff->modifiers, ButtonPress,
470205b261ecSmrg        stuff->button, confineTo, cursor);
470305b261ecSmrg    if (!grab)
470405b261ecSmrg	return BadAlloc;
470505b261ecSmrg    return AddPassiveGrabToList(grab);
470605b261ecSmrg}
470705b261ecSmrg
470805b261ecSmrg/**
470905b261ecSmrg * Server-side protocol handling for UngrabButton request.
471005b261ecSmrg *
471105b261ecSmrg * Deletes a passive grab on the inputInfo.pointer from the list.
471205b261ecSmrg */
471305b261ecSmrgint
471405b261ecSmrgProcUngrabButton(ClientPtr client)
471505b261ecSmrg{
471605b261ecSmrg    REQUEST(xUngrabButtonReq);
471705b261ecSmrg    WindowPtr pWin;
471805b261ecSmrg    GrabRec tempGrab;
471905b261ecSmrg    int rc;
472005b261ecSmrg
472105b261ecSmrg    REQUEST_SIZE_MATCH(xUngrabButtonReq);
472205b261ecSmrg    if ((stuff->modifiers != AnyModifier) &&
472305b261ecSmrg	(stuff->modifiers & ~AllModifiersMask))
472405b261ecSmrg    {
472505b261ecSmrg	client->errorValue = stuff->modifiers;
472605b261ecSmrg	return BadValue;
472705b261ecSmrg    }
472805b261ecSmrg    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
472905b261ecSmrg    if (rc != Success)
473005b261ecSmrg	return rc;
473105b261ecSmrg    tempGrab.resource = client->clientAsMask;
473205b261ecSmrg    tempGrab.device = inputInfo.pointer;
473305b261ecSmrg    tempGrab.window = pWin;
473405b261ecSmrg    tempGrab.modifiersDetail.exact = stuff->modifiers;
473505b261ecSmrg    tempGrab.modifiersDetail.pMask = NULL;
473605b261ecSmrg    tempGrab.modifierDevice = inputInfo.keyboard;
473705b261ecSmrg    tempGrab.type = ButtonPress;
473805b261ecSmrg    tempGrab.detail.exact = stuff->button;
473905b261ecSmrg    tempGrab.detail.pMask = NULL;
474005b261ecSmrg
474105b261ecSmrg    if (!DeletePassiveGrabFromList(&tempGrab))
474205b261ecSmrg	return(BadAlloc);
474305b261ecSmrg    return(Success);
474405b261ecSmrg}
474505b261ecSmrg
474605b261ecSmrg/**
474705b261ecSmrg * Deactivate any grab that may be on the window, remove the focus.
474805b261ecSmrg * Delete any XInput extension events from the window too. Does not change the
474905b261ecSmrg * window mask. Use just before the window is deleted.
475005b261ecSmrg *
475105b261ecSmrg * If freeResources is set, passive grabs on the window are deleted.
475205b261ecSmrg *
475305b261ecSmrg * @param pWin The window to delete events from.
475405b261ecSmrg * @param freeResources True if resources associated with the window should be
475505b261ecSmrg * deleted.
475605b261ecSmrg */
475705b261ecSmrgvoid
475805b261ecSmrgDeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
475905b261ecSmrg{
476005b261ecSmrg    WindowPtr		parent;
476105b261ecSmrg    DeviceIntPtr	mouse = inputInfo.pointer;
476205b261ecSmrg    DeviceIntPtr	keybd = inputInfo.keyboard;
476305b261ecSmrg    FocusClassPtr	focus = keybd->focus;
476405b261ecSmrg    OtherClientsPtr	oc;
476505b261ecSmrg    GrabPtr		passive;
476605b261ecSmrg
476705b261ecSmrg
476805b261ecSmrg    /* Deactivate any grabs performed on this window, before making any
476905b261ecSmrg	input focus changes. */
477005b261ecSmrg
477105b261ecSmrg    if (mouse->grab &&
477205b261ecSmrg	((mouse->grab->window == pWin) || (mouse->grab->confineTo == pWin)))
477305b261ecSmrg	(*mouse->DeactivateGrab)(mouse);
477405b261ecSmrg
477505b261ecSmrg    /* Deactivating a keyboard grab should cause focus events. */
477605b261ecSmrg
477705b261ecSmrg    if (keybd->grab && (keybd->grab->window == pWin))
477805b261ecSmrg	(*keybd->DeactivateGrab)(keybd);
477905b261ecSmrg
478005b261ecSmrg    /* If the focus window is a root window (ie. has no parent) then don't
478105b261ecSmrg	delete the focus from it. */
478205b261ecSmrg
478305b261ecSmrg    if ((pWin == focus->win) && (pWin->parent != NullWindow))
478405b261ecSmrg    {
478505b261ecSmrg	int focusEventMode = NotifyNormal;
478605b261ecSmrg
478705b261ecSmrg 	/* If a grab is in progress, then alter the mode of focus events. */
478805b261ecSmrg
478905b261ecSmrg	if (keybd->grab)
479005b261ecSmrg	    focusEventMode = NotifyWhileGrabbed;
479105b261ecSmrg
479205b261ecSmrg	switch (focus->revert)
479305b261ecSmrg	{
479405b261ecSmrg	case RevertToNone:
479505b261ecSmrg	    DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
479605b261ecSmrg	    focus->win = NoneWin;
479705b261ecSmrg	    focus->traceGood = 0;
479805b261ecSmrg	    break;
479905b261ecSmrg	case RevertToParent:
480005b261ecSmrg	    parent = pWin;
480105b261ecSmrg	    do
480205b261ecSmrg	    {
480305b261ecSmrg		parent = parent->parent;
480405b261ecSmrg		focus->traceGood--;
480505b261ecSmrg	    } while (!parent->realized
480605b261ecSmrg/* This would be a good protocol change -- windows being reparented
480705b261ecSmrg   during SaveSet processing would cause the focus to revert to the
480805b261ecSmrg   nearest enclosing window which will survive the death of the exiting
480905b261ecSmrg   client, instead of ending up reverting to a dying window and thence
481005b261ecSmrg   to None
481105b261ecSmrg */
481205b261ecSmrg#ifdef NOTDEF
481305b261ecSmrg 	      || clients[CLIENT_ID(parent->drawable.id)]->clientGone
481405b261ecSmrg#endif
481505b261ecSmrg		);
481605b261ecSmrg	    DoFocusEvents(keybd, pWin, parent, focusEventMode);
481705b261ecSmrg	    focus->win = parent;
481805b261ecSmrg	    focus->revert = RevertToNone;
481905b261ecSmrg	    break;
482005b261ecSmrg	case RevertToPointerRoot:
482105b261ecSmrg	    DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode);
482205b261ecSmrg	    focus->win = PointerRootWin;
482305b261ecSmrg	    focus->traceGood = 0;
482405b261ecSmrg	    break;
482505b261ecSmrg	}
482605b261ecSmrg    }
482705b261ecSmrg
482805b261ecSmrg    if (mouse->valuator->motionHintWindow == pWin)
482905b261ecSmrg	mouse->valuator->motionHintWindow = NullWindow;
483005b261ecSmrg
483105b261ecSmrg    if (freeResources)
483205b261ecSmrg    {
483305b261ecSmrg	if (pWin->dontPropagate)
483405b261ecSmrg	    DontPropagateRefCnts[pWin->dontPropagate]--;
483505b261ecSmrg	while ( (oc = wOtherClients(pWin)) )
483605b261ecSmrg	    FreeResource(oc->resource, RT_NONE);
483705b261ecSmrg	while ( (passive = wPassiveGrabs(pWin)) )
483805b261ecSmrg	    FreeResource(passive->resource, RT_NONE);
483905b261ecSmrg     }
484005b261ecSmrg#ifdef XINPUT
484105b261ecSmrg    DeleteWindowFromAnyExtEvents(pWin, freeResources);
484205b261ecSmrg#endif
484305b261ecSmrg}
484405b261ecSmrg
484505b261ecSmrg/**
484605b261ecSmrg * Call this whenever some window at or below pWin has changed geometry. If
484705b261ecSmrg * there is a grab on the window, the cursor will be re-confined into the
484805b261ecSmrg * window.
484905b261ecSmrg */
485005b261ecSmrg_X_EXPORT void
485105b261ecSmrgCheckCursorConfinement(WindowPtr pWin)
485205b261ecSmrg{
485305b261ecSmrg    GrabPtr grab = inputInfo.pointer->grab;
485405b261ecSmrg    WindowPtr confineTo;
485505b261ecSmrg
485605b261ecSmrg#ifdef PANORAMIX
485705b261ecSmrg    if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return;
485805b261ecSmrg#endif
485905b261ecSmrg
486005b261ecSmrg    if (grab && (confineTo = grab->confineTo))
486105b261ecSmrg    {
486205b261ecSmrg	if (!BorderSizeNotEmpty(confineTo))
486305b261ecSmrg	    (*inputInfo.pointer->DeactivateGrab)(inputInfo.pointer);
486405b261ecSmrg	else if ((pWin == confineTo) || IsParent(pWin, confineTo))
486505b261ecSmrg	    ConfineCursorToWindow(confineTo, TRUE, TRUE);
486605b261ecSmrg    }
486705b261ecSmrg}
486805b261ecSmrg
486905b261ecSmrgMask
487005b261ecSmrgEventMaskForClient(WindowPtr pWin, ClientPtr client)
487105b261ecSmrg{
487205b261ecSmrg    OtherClientsPtr	other;
487305b261ecSmrg
487405b261ecSmrg    if (wClient (pWin) == client)
487505b261ecSmrg	return pWin->eventMask;
487605b261ecSmrg    for (other = wOtherClients(pWin); other; other = other->next)
487705b261ecSmrg    {
487805b261ecSmrg	if (SameClient(other, client))
487905b261ecSmrg	    return other->mask;
488005b261ecSmrg    }
488105b261ecSmrg    return 0;
488205b261ecSmrg}
488305b261ecSmrg
488405b261ecSmrg/**
488505b261ecSmrg * Server-side protocol handling for RecolorCursor request.
488605b261ecSmrg */
488705b261ecSmrgint
488805b261ecSmrgProcRecolorCursor(ClientPtr client)
488905b261ecSmrg{
489005b261ecSmrg    CursorPtr pCursor;
489105b261ecSmrg    int		nscr;
489205b261ecSmrg    ScreenPtr	pscr;
489305b261ecSmrg    Bool 	displayed;
489405b261ecSmrg    REQUEST(xRecolorCursorReq);
489505b261ecSmrg
489605b261ecSmrg    REQUEST_SIZE_MATCH(xRecolorCursorReq);
489705b261ecSmrg    pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
489805b261ecSmrg					RT_CURSOR, DixWriteAccess);
489905b261ecSmrg    if ( !pCursor)
490005b261ecSmrg    {
490105b261ecSmrg	client->errorValue = stuff->cursor;
490205b261ecSmrg	return (BadCursor);
490305b261ecSmrg    }
490405b261ecSmrg
490505b261ecSmrg    pCursor->foreRed = stuff->foreRed;
490605b261ecSmrg    pCursor->foreGreen = stuff->foreGreen;
490705b261ecSmrg    pCursor->foreBlue = stuff->foreBlue;
490805b261ecSmrg
490905b261ecSmrg    pCursor->backRed = stuff->backRed;
491005b261ecSmrg    pCursor->backGreen = stuff->backGreen;
491105b261ecSmrg    pCursor->backBlue = stuff->backBlue;
491205b261ecSmrg
491305b261ecSmrg    for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
491405b261ecSmrg    {
491505b261ecSmrg	pscr = screenInfo.screens[nscr];
491605b261ecSmrg#ifdef PANORAMIX
491705b261ecSmrg	if(!noPanoramiXExtension)
491805b261ecSmrg	    displayed = (pscr == sprite.screen);
491905b261ecSmrg	else
492005b261ecSmrg#endif
492105b261ecSmrg	    displayed = (pscr == sprite.hotPhys.pScreen);
492205b261ecSmrg	( *pscr->RecolorCursor)(pscr, pCursor,
492305b261ecSmrg				(pCursor == sprite.current) && displayed);
492405b261ecSmrg    }
492505b261ecSmrg    return (Success);
492605b261ecSmrg}
492705b261ecSmrg
492805b261ecSmrg/**
492905b261ecSmrg * Write the given events to a client, swapping the byte order if necessary.
493005b261ecSmrg * To swap the byte ordering, a callback is called that has to be set up for
493105b261ecSmrg * the given event type.
493205b261ecSmrg *
493305b261ecSmrg * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
493405b261ecSmrg * can be more than one. Usually it's just one event.
493505b261ecSmrg *
493605b261ecSmrg * Do not modify the event structure passed in. See comment below.
493705b261ecSmrg *
493805b261ecSmrg * @param pClient Client to send events to.
493905b261ecSmrg * @param count Number of events.
494005b261ecSmrg * @param events The event list.
494105b261ecSmrg */
494205b261ecSmrg_X_EXPORT void
494305b261ecSmrgWriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
494405b261ecSmrg{
494505b261ecSmrg#ifdef PANORAMIX
494605b261ecSmrg    xEvent    eventCopy;
494705b261ecSmrg#endif
494805b261ecSmrg    xEvent    eventTo, *eventFrom;
494905b261ecSmrg    int       i;
495005b261ecSmrg
495105b261ecSmrg#ifdef XKB
495205b261ecSmrg    if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events)))
495305b261ecSmrg	return;
495405b261ecSmrg#endif
495505b261ecSmrg
495605b261ecSmrg#ifdef PANORAMIX
495705b261ecSmrg    if(!noPanoramiXExtension &&
495805b261ecSmrg       (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y))
495905b261ecSmrg    {
496005b261ecSmrg	switch(events->u.u.type) {
496105b261ecSmrg	case MotionNotify:
496205b261ecSmrg	case ButtonPress:
496305b261ecSmrg	case ButtonRelease:
496405b261ecSmrg	case KeyPress:
496505b261ecSmrg	case KeyRelease:
496605b261ecSmrg	case EnterNotify:
496705b261ecSmrg	case LeaveNotify:
496805b261ecSmrg	/*
496905b261ecSmrg	   When multiple clients want the same event DeliverEventsToWindow
497005b261ecSmrg	   passes the same event structure multiple times so we can't
497105b261ecSmrg	   modify the one passed to us
497205b261ecSmrg        */
497305b261ecSmrg	    count = 1;  /* should always be 1 */
497405b261ecSmrg	    memcpy(&eventCopy, events, sizeof(xEvent));
497505b261ecSmrg	    eventCopy.u.keyButtonPointer.rootX += panoramiXdataPtr[0].x;
497605b261ecSmrg	    eventCopy.u.keyButtonPointer.rootY += panoramiXdataPtr[0].y;
497705b261ecSmrg	    if(eventCopy.u.keyButtonPointer.event ==
497805b261ecSmrg	       eventCopy.u.keyButtonPointer.root)
497905b261ecSmrg	    {
498005b261ecSmrg		eventCopy.u.keyButtonPointer.eventX += panoramiXdataPtr[0].x;
498105b261ecSmrg		eventCopy.u.keyButtonPointer.eventY += panoramiXdataPtr[0].y;
498205b261ecSmrg	    }
498305b261ecSmrg	    events = &eventCopy;
498405b261ecSmrg	    break;
498505b261ecSmrg	default: break;
498605b261ecSmrg	}
498705b261ecSmrg    }
498805b261ecSmrg#endif
498905b261ecSmrg
499005b261ecSmrg    if (EventCallback)
499105b261ecSmrg    {
499205b261ecSmrg	EventInfoRec eventinfo;
499305b261ecSmrg	eventinfo.client = pClient;
499405b261ecSmrg	eventinfo.events = events;
499505b261ecSmrg	eventinfo.count = count;
499605b261ecSmrg	CallCallbacks(&EventCallback, (pointer)&eventinfo);
499705b261ecSmrg    }
499805b261ecSmrg#ifdef XSERVER_DTRACE
499905b261ecSmrg    if (XSERVER_SEND_EVENT_ENABLED()) {
500005b261ecSmrg	for (i = 0; i < count; i++)
500105b261ecSmrg	{
500205b261ecSmrg	    XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]);
500305b261ecSmrg	}
500405b261ecSmrg    }
500505b261ecSmrg#endif
500605b261ecSmrg    if(pClient->swapped)
500705b261ecSmrg    {
500805b261ecSmrg	for(i = 0; i < count; i++)
500905b261ecSmrg	{
501005b261ecSmrg	    eventFrom = &events[i];
501105b261ecSmrg	    /* Remember to strip off the leading bit of type in case
501205b261ecSmrg	       this event was sent with "SendEvent." */
501305b261ecSmrg	    (*EventSwapVector[eventFrom->u.u.type & 0177])
501405b261ecSmrg		(eventFrom, &eventTo);
501505b261ecSmrg	    (void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo);
501605b261ecSmrg	}
501705b261ecSmrg    }
501805b261ecSmrg    else
501905b261ecSmrg    {
502005b261ecSmrg	(void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events);
502105b261ecSmrg    }
502205b261ecSmrg}
5023