events.c revision 4642e01f
1/************************************************************
2
3Copyright 1987, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25
26Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
27
28                        All Rights Reserved
29
30Permission to use, copy, modify, and distribute this software and its
31documentation for any purpose and without fee is hereby granted,
32provided that the above copyright notice appear in all copies and that
33both that copyright notice and this permission notice appear in
34supporting documentation, and that the name of Digital not be
35used in advertising or publicity pertaining to distribution of the
36software without specific, written prior permission.
37
38DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44SOFTWARE.
45
46********************************************************/
47
48/* The panoramix components contained the following notice */
49/*****************************************************************
50
51Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
52
53Permission is hereby granted, free of charge, to any person obtaining a copy
54of this software and associated documentation files (the "Software"), to deal
55in the Software without restriction, including without limitation the rights
56to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
57copies of the Software.
58
59The above copyright notice and this permission notice shall be included in
60all copies or substantial portions of the Software.
61
62THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
65DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
66BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
67WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
68IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
69
70Except as contained in this notice, the name of Digital Equipment Corporation
71shall not be used in advertising or otherwise to promote the sale, use or other
72dealings in this Software without prior written authorization from Digital
73Equipment Corporation.
74
75******************************************************************/
76
77/*****************************************************************
78
79Copyright 2003-2005 Sun Microsystems, Inc.
80
81All rights reserved.
82
83Permission is hereby granted, free of charge, to any person obtaining a
84copy of this software and associated documentation files (the
85"Software"), to deal in the Software without restriction, including
86without limitation the rights to use, copy, modify, merge, publish,
87distribute, and/or sell copies of the Software, and to permit persons
88to whom the Software is furnished to do so, provided that the above
89copyright notice(s) and this permission notice appear in all copies of
90the Software and that both the above copyright notice(s) and this
91permission notice appear in supporting documentation.
92
93THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
94OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
95MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
96OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
97HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
98INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
99FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
100NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
101WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
102
103Except as contained in this notice, the name of a copyright holder
104shall not be used in advertising or otherwise to promote the sale, use
105or other dealings in this Software without prior written authorization
106of the copyright holder.
107
108******************************************************************/
109
110/** @file
111 * This file handles event delivery and a big part of the server-side protocol
112 * handling (the parts for input devices).
113 */
114
115#ifdef HAVE_DIX_CONFIG_H
116#include <dix-config.h>
117#endif
118
119#include <X11/X.h>
120#include <X11/keysym.h>
121#include "misc.h"
122#include "resource.h"
123#define NEED_EVENTS
124#define NEED_REPLIES
125#include <X11/Xproto.h>
126#include "windowstr.h"
127#include "inputstr.h"
128#include "scrnintstr.h"
129#include "cursorstr.h"
130
131#include "dixstruct.h"
132#ifdef PANORAMIX
133#include "panoramiX.h"
134#include "panoramiXsrv.h"
135#endif
136#include "globals.h"
137
138#ifdef XKB
139#include <X11/extensions/XKBproto.h>
140#include <xkbsrv.h>
141extern Bool XkbFilterEvents(ClientPtr, int, xEvent *);
142#endif
143
144#include "xace.h"
145
146#ifdef XSERVER_DTRACE
147#include <sys/types.h>
148typedef const char *string;
149#include "Xserver-dtrace.h"
150#endif
151
152#include <X11/extensions/XIproto.h>
153#include <X11/extensions/XI.h>
154#include "exglobals.h"
155#include "exevents.h"
156#include "exglobals.h"
157#include "extnsionst.h"
158
159#include "dixevents.h"
160#include "dixgrabs.h"
161#include "dispatch.h"
162
163#include <X11/extensions/ge.h>
164#include "geext.h"
165#include "geint.h"
166
167#include "enterleave.h"
168
169/**
170 * Extension events type numbering starts at EXTENSION_EVENT_BASE.
171 */
172#define NoSuchEvent 0x80000000	/* so doesn't match NoEventMask */
173#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
174#define AllButtonsMask ( \
175	Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
176#define MotionMask ( \
177	PointerMotionMask | Button1MotionMask | \
178	Button2MotionMask | Button3MotionMask | Button4MotionMask | \
179	Button5MotionMask | ButtonMotionMask )
180#define PropagateMask ( \
181	KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
182	MotionMask )
183#define PointerGrabMask ( \
184	ButtonPressMask | ButtonReleaseMask | \
185	EnterWindowMask | LeaveWindowMask | \
186	PointerMotionHintMask | KeymapStateMask | \
187	MotionMask )
188#define AllModifiersMask ( \
189	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
190	Mod3Mask | Mod4Mask | Mod5Mask )
191#define AllEventMasks (lastEventMask|(lastEventMask-1))
192
193/**
194 * Used to indicate a implicit passive grab created by a ButtonPress event.
195 * See DeliverEventsToWindow().
196 */
197#define ImplicitGrabMask (1 << 7)
198/*
199 * The following relies on the fact that the Button<n>MotionMasks are equal
200 * to the corresponding Button<n>Masks from the current modifier/button state.
201 */
202#define Motion_Filter(class) (PointerMotionMask | \
203			      (class)->state | (class)->motionMask)
204
205
206#define WID(w) ((w) ? ((w)->drawable.id) : 0)
207
208#define XE_KBPTR (xE->u.keyButtonPointer)
209
210
211#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
212
213_X_EXPORT CallbackListPtr EventCallback;
214_X_EXPORT CallbackListPtr DeviceEventCallback;
215
216#define DNPMCOUNT 8
217
218Mask DontPropagateMasks[DNPMCOUNT];
219static int DontPropagateRefCnts[DNPMCOUNT];
220
221
222/**
223 * Main input device struct.
224 *     inputInfo.pointer
225 *     is the core pointer. Referred to as "virtual core pointer", "VCP",
226 *     "core pointer" or inputInfo.pointer. There is exactly one core pointer,
227 *     but multiple devices may send core events. The VCP is the first master
228 *     pointer device and cannot be deleted.
229 *
230 *     inputInfo.keyboard
231 *     is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
232 *     See inputInfo.pointer.
233 *
234 *     inputInfo.devices
235 *     linked list containing all devices including VCP and VCK.
236 *
237 *     inputInfo.off_devices
238 *     Devices that have not been initialized and are thus turned off.
239 *
240 *     inputInfo.numDevices
241 *     Total number of devices.
242 */
243_X_EXPORT InputInfo inputInfo;
244
245/**
246 * syncEvents is the global structure for queued events.
247 * Devices can be frozen through GrabModeSync pointer grabs. If this is the
248 * case, events from these devices are added to "pending" instead of being
249 * processed normally. When the device is unfrozen, events in "pending" are
250 * replayed and processed as if they would come from the device directly.
251 *
252 * pending ... list of queued events
253 * pendtail ... last event in list
254 * replayDev ... The device to replay events for. Only set in AllowEvents, in
255 *               which case it is set to the device specified in the request.
256 * replayWin ... the window the events are supposed to be replayed on. This
257 *               window may be set to the grab's window (but only when
258 *               Replay{Pointer|Keyboard} is given in the XAllowEvents
259 *               request.
260 * playingEvents ... flag to indicate whether we're in the process of
261 *                   replaying events. Only set in ComputeFreezes().
262 */
263static struct {
264    QdEventPtr		pending, *pendtail;
265    DeviceIntPtr	replayDev;	/* kludgy rock to put flag for */
266    WindowPtr		replayWin;	/*   ComputeFreezes            */
267    Bool		playingEvents;
268    TimeStamp		time;
269} syncEvents;
270
271#define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0]
272
273static xEvent* swapEvent = NULL;
274static int swapEventLen = 0;
275
276/**
277 * Convert the given event type from an XI event to a core event.
278 * @return The matching core event type or 0 if there is none.
279 */
280_X_EXPORT int
281XItoCoreType(int xitype)
282{
283    int coretype = 0;
284    if (xitype == DeviceMotionNotify)
285        coretype = MotionNotify;
286    else if (xitype == DeviceButtonPress)
287        coretype = ButtonPress;
288    else if (xitype == DeviceButtonRelease)
289        coretype = ButtonRelease;
290    else if (xitype == DeviceKeyPress)
291        coretype = KeyPress;
292    else if (xitype == DeviceKeyRelease)
293        coretype = KeyRelease;
294
295    return coretype;
296}
297
298/**
299 * True if device owns a cursor, false if device shares a cursor sprite with
300 * another device.
301 */
302_X_EXPORT Bool
303DevHasCursor(DeviceIntPtr pDev)
304{
305    return pDev->spriteInfo->spriteOwner;
306}
307
308/*
309 * Return true if a device is a pointer, check is the same as used by XI to
310 * fill the 'use' field.
311 */
312_X_EXPORT Bool
313IsPointerDevice(DeviceIntPtr dev)
314{
315    return (dev->valuator && dev->button);
316}
317
318/*
319 * Return true if a device is a keyboard, check is the same as used by XI to
320 * fill the 'use' field.
321 *
322 * Some pointer devices have keys as well (e.g. multimedia keys). Try to not
323 * count them as keyboard devices.
324 */
325_X_EXPORT Bool
326IsKeyboardDevice(DeviceIntPtr dev)
327{
328    return (dev->key && dev->kbdfeed) && !IsPointerDevice(dev);
329}
330
331static WindowPtr XYToWindow(
332    DeviceIntPtr pDev,
333    int x,
334    int y
335);
336
337/**
338 * Max event opcode.
339 */
340extern int lastEvent;
341
342static Mask lastEventMask;
343
344extern int DeviceMotionNotify;
345
346/**
347 * Event filters. One set of filters for each device, but only the first layer
348 * is initialized. The rest is memcpy'd in InitEvents.
349 */
350#define CantBeFiltered NoEventMask
351static Mask filters[MAXDEVICES][128] = {
352{
353	NoSuchEvent,		       /* 0 */
354	NoSuchEvent,		       /* 1 */
355	KeyPressMask,		       /* KeyPress */
356	KeyReleaseMask,		       /* KeyRelease */
357	ButtonPressMask,	       /* ButtonPress */
358	ButtonReleaseMask,	       /* ButtonRelease */
359	PointerMotionMask,	       /* MotionNotify (initial state) */
360	EnterWindowMask,	       /* EnterNotify */
361	LeaveWindowMask,	       /* LeaveNotify */
362	FocusChangeMask,	       /* FocusIn */
363	FocusChangeMask,	       /* FocusOut */
364	KeymapStateMask,	       /* KeymapNotify */
365	ExposureMask,		       /* Expose */
366	CantBeFiltered,		       /* GraphicsExpose */
367	CantBeFiltered,		       /* NoExpose */
368	VisibilityChangeMask,	       /* VisibilityNotify */
369	SubstructureNotifyMask,	       /* CreateNotify */
370	StructureAndSubMask,	       /* DestroyNotify */
371	StructureAndSubMask,	       /* UnmapNotify */
372	StructureAndSubMask,	       /* MapNotify */
373	SubstructureRedirectMask,      /* MapRequest */
374	StructureAndSubMask,	       /* ReparentNotify */
375	StructureAndSubMask,	       /* ConfigureNotify */
376	SubstructureRedirectMask,      /* ConfigureRequest */
377	StructureAndSubMask,	       /* GravityNotify */
378	ResizeRedirectMask,	       /* ResizeRequest */
379	StructureAndSubMask,	       /* CirculateNotify */
380	SubstructureRedirectMask,      /* CirculateRequest */
381	PropertyChangeMask,	       /* PropertyNotify */
382	CantBeFiltered,		       /* SelectionClear */
383	CantBeFiltered,		       /* SelectionRequest */
384	CantBeFiltered,		       /* SelectionNotify */
385	ColormapChangeMask,	       /* ColormapNotify */
386	CantBeFiltered,		       /* ClientMessage */
387	CantBeFiltered		       /* MappingNotify */
388}};
389
390
391/**
392 * same principle as filters, but one set of filters for each extension.
393 * The extension is responsible for setting the filters by calling
394 * SetGenericFilter().
395 */
396static Mask* generic_filters[MAXEXTENSIONS];
397
398static CARD8 criticalEvents[32] =
399{
400    0x7c, 0x30, 0x40			/* key, button, expose, and configure events */
401};
402
403#ifdef PANORAMIX
404static void PostNewCursor(DeviceIntPtr pDev);
405
406#define SyntheticMotion(dev, x, y) \
407    PostSyntheticMotion(dev, x, y, noPanoramiXExtension ? 0 : \
408                              dev->spriteInfo->sprite->screen->myNum, \
409                        syncEvents.playingEvents ? \
410                          syncEvents.time.milliseconds : \
411                          currentTime.milliseconds);
412
413static Bool
414XineramaSetCursorPosition(
415    DeviceIntPtr pDev,
416    int x,
417    int y,
418    Bool generateEvent
419){
420    ScreenPtr pScreen;
421    BoxRec box;
422    int i;
423    SpritePtr pSprite = pDev->spriteInfo->sprite;
424
425    /* x,y are in Screen 0 coordinates.  We need to decide what Screen
426       to send the message too and what the coordinates relative to
427       that screen are. */
428
429    pScreen = pSprite->screen;
430    x += panoramiXdataPtr[0].x;
431    y += panoramiXdataPtr[0].y;
432
433    if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum],
434								x, y, &box))
435    {
436	FOR_NSCREENS(i)
437	{
438	    if(i == pScreen->myNum)
439		continue;
440	    if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box))
441	    {
442		pScreen = screenInfo.screens[i];
443		break;
444	    }
445	}
446    }
447
448    pSprite->screen = pScreen;
449    pSprite->hotPhys.x = x - panoramiXdataPtr[0].x;
450    pSprite->hotPhys.y = y - panoramiXdataPtr[0].y;
451    x -= panoramiXdataPtr[pScreen->myNum].x;
452    y -= panoramiXdataPtr[pScreen->myNum].y;
453
454    return (*pScreen->SetCursorPosition)(pDev, pScreen, x, y, generateEvent);
455}
456
457
458static void
459XineramaConstrainCursor(DeviceIntPtr pDev)
460{
461    SpritePtr pSprite = pDev->spriteInfo->sprite;
462    ScreenPtr pScreen;
463    BoxRec newBox;
464
465    pScreen = pSprite->screen;
466    newBox = pSprite->physLimits;
467
468    /* Translate the constraining box to the screen
469       the sprite is actually on */
470    newBox.x1 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x;
471    newBox.x2 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x;
472    newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
473    newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
474
475    (* pScreen->ConstrainCursor)(pDev, pScreen, &newBox);
476}
477
478static void
479XineramaCheckPhysLimits(
480    DeviceIntPtr pDev,
481    CursorPtr cursor,
482    Bool generateEvents
483){
484    HotSpot new;
485    SpritePtr pSprite = pDev->spriteInfo->sprite;
486
487    if (!cursor)
488	return;
489
490    new = pSprite->hotPhys;
491
492    /* I don't care what the DDX has to say about it */
493    pSprite->physLimits = pSprite->hotLimits;
494
495    /* constrain the pointer to those limits */
496    if (new.x < pSprite->physLimits.x1)
497	new.x = pSprite->physLimits.x1;
498    else
499	if (new.x >= pSprite->physLimits.x2)
500	    new.x = pSprite->physLimits.x2 - 1;
501    if (new.y < pSprite->physLimits.y1)
502	new.y = pSprite->physLimits.y1;
503    else
504	if (new.y >= pSprite->physLimits.y2)
505	    new.y = pSprite->physLimits.y2 - 1;
506
507    if (pSprite->hotShape)  /* more work if the shape is a mess */
508	ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y);
509
510    if((new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y))
511    {
512	XineramaSetCursorPosition (pDev, new.x, new.y, generateEvents);
513	if (!generateEvents)
514	    SyntheticMotion(pDev, new.x, new.y);
515    }
516
517    /* Tell DDX what the limits are */
518    XineramaConstrainCursor(pDev);
519}
520
521
522static Bool
523XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
524{
525    SpritePtr pSprite = pDev->spriteInfo->sprite;
526
527    if(pWin == WindowTable[0]) {
528	    memcpy(pSprite->windows, WindowTable,
529				PanoramiXNumScreens*sizeof(WindowPtr));
530    } else {
531	PanoramiXRes *win;
532	int i;
533
534	win = (PanoramiXRes*)LookupIDByType(pWin->drawable.id, XRT_WINDOW);
535
536	if(!win)
537	    return FALSE;
538
539	for(i = 0; i < PanoramiXNumScreens; i++) {
540	   pSprite->windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW);
541	   if(!pSprite->windows[i])  /* window is being unmapped */
542		return FALSE;
543	}
544    }
545    return TRUE;
546}
547
548static void
549XineramaCheckVirtualMotion(
550   DeviceIntPtr pDev,
551   QdEventPtr qe,
552   WindowPtr pWin)
553{
554    SpritePtr pSprite = pDev->spriteInfo->sprite;
555
556    if (qe)
557    {
558	pSprite->hot.pScreen = qe->pScreen;  /* should always be Screen 0 */
559	pSprite->hot.x = qe->event->u.keyButtonPointer.rootX;
560	pSprite->hot.y = qe->event->u.keyButtonPointer.rootY;
561	pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo :
562					 NullWindow;
563    }
564    if (pWin)
565    {
566	int x, y, off_x, off_y, i;
567	BoxRec lims;
568
569	if(!XineramaSetWindowPntrs(pDev, pWin))
570	    return;
571
572	i = PanoramiXNumScreens - 1;
573
574	REGION_COPY(pSprite->screen, &pSprite->Reg2,
575					&pSprite->windows[i]->borderSize);
576	off_x = panoramiXdataPtr[i].x;
577	off_y = panoramiXdataPtr[i].y;
578
579	while(i--) {
580	    x = off_x - panoramiXdataPtr[i].x;
581	    y = off_y - panoramiXdataPtr[i].y;
582
583	    if(x || y)
584		REGION_TRANSLATE(pSprite->screen, &pSprite->Reg2, x, y);
585
586	    REGION_UNION(pSprite->screen, &pSprite->Reg2, &pSprite->Reg2,
587					&pSprite->windows[i]->borderSize);
588
589	    off_x = panoramiXdataPtr[i].x;
590	    off_y = panoramiXdataPtr[i].y;
591	}
592
593	lims = *REGION_EXTENTS(pSprite->screen, &pSprite->Reg2);
594
595        if (pSprite->hot.x < lims.x1)
596            pSprite->hot.x = lims.x1;
597        else if (pSprite->hot.x >= lims.x2)
598            pSprite->hot.x = lims.x2 - 1;
599        if (pSprite->hot.y < lims.y1)
600            pSprite->hot.y = lims.y1;
601        else if (pSprite->hot.y >= lims.y2)
602            pSprite->hot.y = lims.y2 - 1;
603
604	if (REGION_NUM_RECTS(&pSprite->Reg2) > 1)
605	    ConfineToShape(pDev, &pSprite->Reg2,
606                    &pSprite->hot.x, &pSprite->hot.y);
607
608	if (qe)
609	{
610	    qe->pScreen = pSprite->hot.pScreen;
611	    qe->event->u.keyButtonPointer.rootX = pSprite->hot.x;
612	    qe->event->u.keyButtonPointer.rootY = pSprite->hot.y;
613	}
614    }
615}
616
617
618static Bool
619XineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev)
620{
621    WindowPtr prevSpriteWin;
622    SpritePtr pSprite = pDev->spriteInfo->sprite;
623
624    prevSpriteWin = pSprite->win;
625
626    if (xE && !syncEvents.playingEvents)
627    {
628        /* GetPointerEvents() guarantees that pointer events have the correct
629           rootX/Y set already. */
630        switch(xE->u.u.type)
631        {
632            case ButtonPress:
633            case ButtonRelease:
634            case MotionNotify:
635                break;
636            default:
637                if (xE->u.u.type == DeviceButtonPress ||
638                        xE->u.u.type == DeviceButtonRelease ||
639                        xE->u.u.type == DeviceMotionNotify)
640                    break;
641                /* all other events return FALSE */
642                return FALSE;
643        }
644
645	/* Motion events entering DIX get translated to Screen 0
646	   coordinates.  Replayed events have already been
647	   translated since they've entered DIX before */
648	XE_KBPTR.rootX += panoramiXdataPtr[pSprite->screen->myNum].x -
649			  panoramiXdataPtr[0].x;
650	XE_KBPTR.rootY += panoramiXdataPtr[pSprite->screen->myNum].y -
651			  panoramiXdataPtr[0].y;
652	pSprite->hot.x = XE_KBPTR.rootX;
653	pSprite->hot.y = XE_KBPTR.rootY;
654	if (pSprite->hot.x < pSprite->physLimits.x1)
655	    pSprite->hot.x = pSprite->physLimits.x1;
656	else if (pSprite->hot.x >= pSprite->physLimits.x2)
657	    pSprite->hot.x = pSprite->physLimits.x2 - 1;
658	if (pSprite->hot.y < pSprite->physLimits.y1)
659	    pSprite->hot.y = pSprite->physLimits.y1;
660	else if (pSprite->hot.y >= pSprite->physLimits.y2)
661	    pSprite->hot.y = pSprite->physLimits.y2 - 1;
662
663	if (pSprite->hotShape)
664	    ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y);
665
666	pSprite->hotPhys = pSprite->hot;
667	if ((pSprite->hotPhys.x != XE_KBPTR.rootX) ||
668	    (pSprite->hotPhys.y != XE_KBPTR.rootY))
669	{
670	    XineramaSetCursorPosition(
671			pDev, pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
672	}
673	XE_KBPTR.rootX = pSprite->hot.x;
674	XE_KBPTR.rootY = pSprite->hot.y;
675    }
676
677    pSprite->win = XYToWindow(pDev, pSprite->hot.x, pSprite->hot.y);
678
679    if (pSprite->win != prevSpriteWin)
680    {
681	if (prevSpriteWin != NullWindow) {
682	    if (!xE)
683		UpdateCurrentTimeIf();
684            DoEnterLeaveEvents(pDev, prevSpriteWin, pSprite->win,
685                               NotifyNormal);
686        }
687	PostNewCursor(pDev);
688        return FALSE;
689    }
690    return TRUE;
691}
692
693
694static void
695XineramaConfineCursorToWindow(DeviceIntPtr pDev,
696                              WindowPtr pWin,
697                              Bool generateEvents)
698{
699    SpritePtr pSprite = pDev->spriteInfo->sprite;
700
701    if (syncEvents.playingEvents)
702    {
703	XineramaCheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin);
704	SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y);
705    }
706    else
707    {
708	int x, y, off_x, off_y, i;
709
710	if(!XineramaSetWindowPntrs(pDev, pWin))
711	    return;
712
713	i = PanoramiXNumScreens - 1;
714
715	REGION_COPY(pSprite->screen, &pSprite->Reg1,
716					&pSprite->windows[i]->borderSize);
717	off_x = panoramiXdataPtr[i].x;
718	off_y = panoramiXdataPtr[i].y;
719
720	while(i--) {
721	    x = off_x - panoramiXdataPtr[i].x;
722	    y = off_y - panoramiXdataPtr[i].y;
723
724	    if(x || y)
725		REGION_TRANSLATE(pSprite->screen, &pSprite->Reg1, x, y);
726
727	    REGION_UNION(pSprite->screen, &pSprite->Reg1, &pSprite->Reg1,
728					&pSprite->windows[i]->borderSize);
729
730	    off_x = panoramiXdataPtr[i].x;
731	    off_y = panoramiXdataPtr[i].y;
732	}
733
734	pSprite->hotLimits = *REGION_EXTENTS(pSprite->screen, &pSprite->Reg1);
735
736	if(REGION_NUM_RECTS(&pSprite->Reg1) > 1)
737	   pSprite->hotShape = &pSprite->Reg1;
738	else
739	   pSprite->hotShape = NullRegion;
740
741	pSprite->confined = FALSE;
742	pSprite->confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin;
743
744        XineramaCheckPhysLimits(pDev, pSprite->current,
745                                generateEvents);
746    }
747}
748
749
750static void
751XineramaChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
752{
753    SpritePtr pSprite = pDev->spriteInfo->sprite;
754
755    if (cursor != pSprite->current)
756    {
757	if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
758		(pSprite->current->bits->yhot != cursor->bits->yhot))
759	    XineramaCheckPhysLimits(pDev, cursor, FALSE);
760	(*pSprite->screen->DisplayCursor)(pDev, pSprite->screen, cursor);
761	FreeCursor(pSprite->current, (Cursor)0);
762	pSprite->current = cursor;
763	pSprite->current->refcnt++;
764    }
765}
766
767#else
768#define SyntheticMotion(dev, x, y) \
769     PostSyntheticMotion(dev, x, y, \
770                         0, \
771                         syncEvents.playingEvents ? \
772                           syncEvents.time.milliseconds : \
773                           currentTime.milliseconds);
774
775#endif  /* PANORAMIX */
776
777void
778SetMaskForEvent(int deviceid, Mask mask, int event)
779{
780    int coretype;
781    if (deviceid < 0 || deviceid > MAXDEVICES)
782        FatalError("SetMaskForEvent: bogus device id");
783    if ((event < LASTEvent) || (event >= 128))
784	FatalError("SetMaskForEvent: bogus event number");
785    filters[deviceid][event] = mask;
786
787    /* Need to change the mask for the core events too */
788    coretype = XItoCoreType(event);
789    if (coretype)
790        filters[deviceid][coretype] = mask;
791}
792
793_X_EXPORT void
794SetCriticalEvent(int event)
795{
796    if (event >= 128)
797	FatalError("SetCriticalEvent: bogus event number");
798    criticalEvents[event >> 3] |= 1 << (event & 7);
799}
800
801void
802ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
803{
804    BoxRec box;
805    int x = *px, y = *py;
806    int incx = 1, incy = 1;
807    SpritePtr pSprite;
808
809    pSprite = pDev->spriteInfo->sprite;
810    if (POINT_IN_REGION(pSprite->hot.pScreen, shape, x, y, &box))
811	return;
812    box = *REGION_EXTENTS(pSprite->hot.pScreen, shape);
813    /* this is rather crude */
814    do {
815	x += incx;
816	if (x >= box.x2)
817	{
818	    incx = -1;
819	    x = *px - 1;
820	}
821	else if (x < box.x1)
822	{
823	    incx = 1;
824	    x = *px;
825	    y += incy;
826	    if (y >= box.y2)
827	    {
828		incy = -1;
829		y = *py - 1;
830	    }
831	    else if (y < box.y1)
832		return; /* should never get here! */
833	}
834    } while (!POINT_IN_REGION(pSprite->hot.pScreen, shape, x, y, &box));
835    *px = x;
836    *py = y;
837}
838
839static void
840CheckPhysLimits(
841    DeviceIntPtr pDev,
842    CursorPtr cursor,
843    Bool generateEvents,
844    Bool confineToScreen,
845    ScreenPtr pScreen)
846{
847    HotSpot new;
848    SpritePtr pSprite = pDev->spriteInfo->sprite;
849
850    if (!cursor)
851	return;
852    new = pSprite->hotPhys;
853    if (pScreen)
854	new.pScreen = pScreen;
855    else
856	pScreen = new.pScreen;
857    (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits,
858			      &pSprite->physLimits);
859    pSprite->confined = confineToScreen;
860    (* pScreen->ConstrainCursor)(pDev, pScreen, &pSprite->physLimits);
861    if (new.x < pSprite->physLimits.x1)
862	new.x = pSprite->physLimits.x1;
863    else
864	if (new.x >= pSprite->physLimits.x2)
865	    new.x = pSprite->physLimits.x2 - 1;
866    if (new.y < pSprite->physLimits.y1)
867	new.y = pSprite->physLimits.y1;
868    else
869	if (new.y >= pSprite->physLimits.y2)
870	    new.y = pSprite->physLimits.y2 - 1;
871    if (pSprite->hotShape)
872	ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y);
873    if ((pScreen != pSprite->hotPhys.pScreen) ||
874	(new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y))
875    {
876	if (pScreen != pSprite->hotPhys.pScreen)
877	    pSprite->hotPhys = new;
878        (*pScreen->SetCursorPosition)
879            (pDev, pScreen, new.x, new.y, generateEvents);
880        if (!generateEvents)
881	    SyntheticMotion(pDev, new.x, new.y);
882    }
883}
884
885static void
886CheckVirtualMotion(
887    DeviceIntPtr pDev,
888    QdEventPtr qe,
889    WindowPtr pWin)
890{
891    SpritePtr pSprite = pDev->spriteInfo->sprite;
892
893#ifdef PANORAMIX
894    if(!noPanoramiXExtension) {
895	XineramaCheckVirtualMotion(pDev, qe, pWin);
896	return;
897    }
898#endif
899    if (qe)
900    {
901	pSprite->hot.pScreen = qe->pScreen;
902	pSprite->hot.x = qe->event->u.keyButtonPointer.rootX;
903	pSprite->hot.y = qe->event->u.keyButtonPointer.rootY;
904	pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo : NullWindow;
905    }
906    if (pWin)
907    {
908	BoxRec lims;
909
910	if (pSprite->hot.pScreen != pWin->drawable.pScreen)
911	{
912	    pSprite->hot.pScreen = pWin->drawable.pScreen;
913	    pSprite->hot.x = pSprite->hot.y = 0;
914	}
915	lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize);
916	if (pSprite->hot.x < lims.x1)
917	    pSprite->hot.x = lims.x1;
918	else if (pSprite->hot.x >= lims.x2)
919	    pSprite->hot.x = lims.x2 - 1;
920	if (pSprite->hot.y < lims.y1)
921	    pSprite->hot.y = lims.y1;
922	else if (pSprite->hot.y >= lims.y2)
923	    pSprite->hot.y = lims.y2 - 1;
924	if (wBoundingShape(pWin))
925	    ConfineToShape(pDev, &pWin->borderSize,
926                    &pSprite->hot.x, &pSprite->hot.y);
927	if (qe)
928	{
929	    qe->pScreen = pSprite->hot.pScreen;
930	    qe->event->u.keyButtonPointer.rootX = pSprite->hot.x;
931	    qe->event->u.keyButtonPointer.rootY = pSprite->hot.y;
932	}
933    }
934    RootWindow(pDev) = WindowTable[pSprite->hot.pScreen->myNum];
935}
936
937static void
938ConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
939{
940    ScreenPtr pScreen = pWin->drawable.pScreen;
941    SpritePtr pSprite = pDev->spriteInfo->sprite;
942
943#ifdef PANORAMIX
944    if(!noPanoramiXExtension) {
945	XineramaConfineCursorToWindow(pDev, pWin, generateEvents);
946	return;
947    }
948#endif
949
950    if (syncEvents.playingEvents)
951    {
952	CheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin);
953	SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y);
954    }
955    else
956    {
957	pSprite->hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize);
958	pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize
959					       : NullRegion;
960        CheckPhysLimits(pDev, pSprite->current, generateEvents,
961                        confineToScreen, pScreen);
962    }
963}
964
965_X_EXPORT Bool
966PointerConfinedToScreen(DeviceIntPtr pDev)
967{
968    return pDev->spriteInfo->sprite->confined;
969}
970
971/**
972 * Update the sprite cursor to the given cursor.
973 *
974 * ChangeToCursor() will display the new cursor and free the old cursor (if
975 * applicable). If the provided cursor is already the updated cursor, nothing
976 * happens.
977 */
978static void
979ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
980{
981    SpritePtr pSprite = pDev->spriteInfo->sprite;
982
983#ifdef PANORAMIX
984    if(!noPanoramiXExtension) {
985	XineramaChangeToCursor(pDev, cursor);
986	return;
987    }
988#endif
989
990    if (cursor != pSprite->current)
991    {
992	if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
993		(pSprite->current->bits->yhot != cursor->bits->yhot))
994	    CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined,
995			    (ScreenPtr)NULL);
996        (*pSprite->hotPhys.pScreen->DisplayCursor) (pDev,
997                                                   pSprite->hotPhys.pScreen,
998                                                   cursor);
999	FreeCursor(pSprite->current, (Cursor)0);
1000	pSprite->current = cursor;
1001	pSprite->current->refcnt++;
1002    }
1003}
1004
1005/**
1006 * @returns true if b is a descendent of a
1007 */
1008Bool
1009IsParent(WindowPtr a, WindowPtr b)
1010{
1011    for (b = b->parent; b; b = b->parent)
1012	if (b == a) return TRUE;
1013    return FALSE;
1014}
1015
1016/**
1017 * Update the cursor displayed on the screen.
1018 *
1019 * Called whenever a cursor may have changed shape or position.
1020 */
1021static void
1022PostNewCursor(DeviceIntPtr pDev)
1023{
1024    WindowPtr win;
1025    GrabPtr grab = pDev->deviceGrab.grab;
1026    SpritePtr   pSprite = pDev->spriteInfo->sprite;
1027    CursorPtr   pCursor;
1028
1029    if (syncEvents.playingEvents)
1030	return;
1031    if (grab)
1032    {
1033	if (grab->cursor)
1034	{
1035	    ChangeToCursor(pDev, grab->cursor);
1036	    return;
1037	}
1038	if (IsParent(grab->window, pSprite->win))
1039	    win = pSprite->win;
1040	else
1041	    win = grab->window;
1042    }
1043    else
1044	win = pSprite->win;
1045    for (; win; win = win->parent)
1046    {
1047	if (win->optional)
1048        {
1049            pCursor = WindowGetDeviceCursor(win, pDev);
1050            if (!pCursor && win->optional->cursor != NullCursor)
1051                pCursor = win->optional->cursor;
1052            if (pCursor)
1053            {
1054                ChangeToCursor(pDev, pCursor);
1055                return;
1056            }
1057	}
1058    }
1059}
1060
1061
1062/**
1063 * @param dev device which you want to know its current root window
1064 * @return root window where dev's sprite is located
1065 */
1066_X_EXPORT WindowPtr
1067GetCurrentRootWindow(DeviceIntPtr dev)
1068{
1069    return RootWindow(dev);
1070}
1071
1072/**
1073 * @return window underneath the cursor sprite.
1074 */
1075_X_EXPORT WindowPtr
1076GetSpriteWindow(DeviceIntPtr pDev)
1077{
1078    return pDev->spriteInfo->sprite->win;
1079}
1080
1081/**
1082 * @return current sprite cursor.
1083 */
1084_X_EXPORT CursorPtr
1085GetSpriteCursor(DeviceIntPtr pDev)
1086{
1087    return pDev->spriteInfo->sprite->current;
1088}
1089
1090/**
1091 * Set x/y current sprite position in screen coordinates.
1092 */
1093_X_EXPORT void
1094GetSpritePosition(DeviceIntPtr pDev, int *px, int *py)
1095{
1096    SpritePtr pSprite = pDev->spriteInfo->sprite;
1097    *px = pSprite->hotPhys.x;
1098    *py = pSprite->hotPhys.y;
1099}
1100
1101#ifdef PANORAMIX
1102_X_EXPORT int
1103XineramaGetCursorScreen(DeviceIntPtr pDev)
1104{
1105    if(!noPanoramiXExtension) {
1106	return pDev->spriteInfo->sprite->screen->myNum;
1107    } else {
1108	return 0;
1109    }
1110}
1111#endif /* PANORAMIX */
1112
1113#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */
1114
1115static void
1116MonthChangedOrBadTime(xEvent *xE)
1117{
1118    /* If the ddx/OS is careless about not processing timestamped events from
1119     * different sources in sorted order, then it's possible for time to go
1120     * backwards when it should not.  Here we ensure a decent time.
1121     */
1122    if ((currentTime.milliseconds - XE_KBPTR.time) > TIMESLOP)
1123	currentTime.months++;
1124    else
1125	XE_KBPTR.time = currentTime.milliseconds;
1126}
1127
1128#define NoticeTime(xE) { \
1129    if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \
1130	MonthChangedOrBadTime(xE); \
1131    currentTime.milliseconds = (xE)->u.keyButtonPointer.time; \
1132    lastDeviceEventTime = currentTime; }
1133
1134void
1135NoticeEventTime(xEvent *xE)
1136{
1137    if (!syncEvents.playingEvents)
1138	NoticeTime(xE);
1139}
1140
1141/**************************************************************************
1142 *            The following procedures deal with synchronous events       *
1143 **************************************************************************/
1144
1145/**
1146 * EnqueueEvent is a device's processInputProc if a device is frozen.
1147 * Instead of delivering the events to the client, the event is tacked onto a
1148 * linked list for later delivery.
1149 */
1150void
1151EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
1152{
1153    QdEventPtr	tail = *syncEvents.pendtail;
1154    QdEventPtr	qe;
1155    SpritePtr	pSprite = device->spriteInfo->sprite;
1156    int		eventlen;
1157
1158
1159    NoticeTime(xE);
1160
1161#ifdef XKB
1162    /* Fix for key repeating bug. */
1163    if (device->key != NULL && device->key->xkbInfo != NULL &&
1164	xE->u.u.type == KeyRelease)
1165	AccessXCancelRepeatKey(device->key->xkbInfo, xE->u.u.detail);
1166#endif
1167
1168    if (DeviceEventCallback)
1169    {
1170	DeviceEventInfoRec eventinfo;
1171	/*  The RECORD spec says that the root window field of motion events
1172	 *  must be valid.  At this point, it hasn't been filled in yet, so
1173	 *  we do it here.  The long expression below is necessary to get
1174	 *  the current root window; the apparently reasonable alternative
1175	 *  GetCurrentRootWindow()->drawable.id doesn't give you the right
1176	 *  answer on the first motion event after a screen change because
1177	 *  the data that GetCurrentRootWindow relies on hasn't been
1178	 *  updated yet.
1179	 */
1180	if (xE->u.u.type == DeviceMotionNotify)
1181	    XE_KBPTR.root =
1182		WindowTable[pSprite->hotPhys.pScreen->myNum]->drawable.id;
1183	eventinfo.events = xE;
1184	eventinfo.count = count;
1185	CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
1186    }
1187    if (xE->u.u.type == DeviceMotionNotify)
1188    {
1189#ifdef PANORAMIX
1190	if(!noPanoramiXExtension) {
1191	    XE_KBPTR.rootX += panoramiXdataPtr[pSprite->screen->myNum].x -
1192			      panoramiXdataPtr[0].x;
1193	    XE_KBPTR.rootY += panoramiXdataPtr[pSprite->screen->myNum].y -
1194			      panoramiXdataPtr[0].y;
1195	}
1196#endif
1197	pSprite->hotPhys.x = XE_KBPTR.rootX;
1198	pSprite->hotPhys.y = XE_KBPTR.rootY;
1199	/* do motion compression, but not if from different devices */
1200	if (tail &&
1201	    (tail->event->u.u.type == DeviceMotionNotify) &&
1202            (tail->device == device) &&
1203	    (tail->pScreen == pSprite->hotPhys.pScreen))
1204	{
1205	    tail->event->u.keyButtonPointer.rootX = pSprite->hotPhys.x;
1206	    tail->event->u.keyButtonPointer.rootY = pSprite->hotPhys.y;
1207	    tail->event->u.keyButtonPointer.time = XE_KBPTR.time;
1208	    tail->months = currentTime.months;
1209	    return;
1210	}
1211    }
1212
1213    eventlen = count * sizeof(xEvent);
1214    if (xE->u.u.type == GenericEvent) /* count is 1 for GenericEvents */
1215	eventlen += ((xGenericEvent*)xE)->length * 4;
1216
1217    qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + eventlen);
1218    if (!qe)
1219	return;
1220    qe->next = (QdEventPtr)NULL;
1221    qe->device = device;
1222    qe->pScreen = pSprite->hotPhys.pScreen;
1223    qe->months = currentTime.months;
1224    qe->event = (xEvent *)(qe + 1);
1225    qe->evcount = count;
1226    if (xE->u.u.type == GenericEvent)
1227    {
1228	memcpy(qe->event, xE, eventlen);
1229    } else
1230    {
1231	xEvent	*qxE;
1232	for (qxE = qe->event; --count >= 0; qxE++, xE++)
1233	{
1234	    *qxE = *xE;
1235	}
1236    }
1237    if (tail)
1238	syncEvents.pendtail = &tail->next;
1239    *syncEvents.pendtail = qe;
1240}
1241
1242/**
1243 * Run through the list of events queued up in syncEvents.
1244 * For each event do:
1245 * If the device for this event is not frozen anymore, take it and process it
1246 * as usually.
1247 * After that, check if there's any devices in the list that are not frozen.
1248 * If there is none, we're done. If there is at least one device that is not
1249 * frozen, then re-run from the beginning of the event queue.
1250 */
1251static void
1252PlayReleasedEvents(void)
1253{
1254    QdEventPtr *prev, qe;
1255    DeviceIntPtr dev;
1256    DeviceIntPtr pDev;
1257    static CARD32 lastKnownMillis = 0; /* Hack, see comment below */
1258
1259    prev = &syncEvents.pending;
1260    while ( (qe = *prev) )
1261    {
1262	if (!qe->device->deviceGrab.sync.frozen)
1263	{
1264	    *prev = qe->next;
1265            pDev = qe->device;
1266	    if (*syncEvents.pendtail == *prev)
1267		syncEvents.pendtail = prev;
1268	    if (qe->event->u.u.type == DeviceMotionNotify)
1269		CheckVirtualMotion(pDev, qe, NullWindow);
1270	    syncEvents.time.months = qe->months;
1271            /* XXX: Hack! We can't reliably get the time from GenericEvents,
1272               since we don't know which struct it may be. So we store the time
1273               when we know it, and re-use it when we can't get it. */
1274            if (qe->event->u.u.type == GenericEvent)
1275            {
1276                syncEvents.time.milliseconds = lastKnownMillis;
1277            } else
1278            {
1279                syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time;
1280                lastKnownMillis = syncEvents.time.milliseconds;
1281            }
1282#ifdef PANORAMIX
1283	   /* Translate back to the sprite screen since processInputProc
1284	      will translate from sprite screen to screen 0 upon reentry
1285	      to the DIX layer */
1286            /* XXX: we can't do that for generic events */
1287	    if(!noPanoramiXExtension) {
1288		qe->event->u.keyButtonPointer.rootX +=
1289			panoramiXdataPtr[0].x -
1290			panoramiXdataPtr[pDev->spriteInfo->sprite->screen->myNum].x;
1291		qe->event->u.keyButtonPointer.rootY +=
1292			panoramiXdataPtr[0].y -
1293			panoramiXdataPtr[pDev->spriteInfo->sprite->screen->myNum].y;
1294	    }
1295#endif
1296	    (*qe->device->public.processInputProc)(qe->event, qe->device,
1297						   qe->evcount);
1298	    xfree(qe);
1299	    for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; dev = dev->next)
1300		;
1301	    if (!dev)
1302		break;
1303	    /* Playing the event may have unfrozen another device. */
1304	    /* So to play it safe, restart at the head of the queue */
1305	    prev = &syncEvents.pending;
1306	}
1307	else
1308	    prev = &qe->next;
1309    }
1310}
1311
1312/**
1313 * Freeze or thaw the given devices. The device's processing proc is
1314 * switched to either the real processing proc (in case of thawing) or an
1315 * enqueuing processing proc (usually EnqueueEvent()).
1316 *
1317 * @param dev The device to freeze/thaw
1318 * @param frozen True to freeze or false to thaw.
1319 */
1320static void
1321FreezeThaw(DeviceIntPtr dev, Bool frozen)
1322{
1323    dev->deviceGrab.sync.frozen = frozen;
1324    if (frozen)
1325	dev->public.processInputProc = dev->public.enqueueInputProc;
1326    else
1327	dev->public.processInputProc = dev->public.realInputProc;
1328}
1329
1330/**
1331 * Unfreeze devices and replay all events to the respective clients.
1332 *
1333 * ComputeFreezes takes the first event in the device's frozen event queue. It
1334 * runs up the sprite tree (spriteTrace) and searches for the window to replay
1335 * the events from. If it is found, it checks for passive grabs one down from
1336 * the window or delivers the events.
1337 *
1338 * Since the events in the EQ are always XI events, we need to emulate core
1339 * events here.
1340 */
1341static void
1342ComputeFreezes(void)
1343{
1344    DeviceIntPtr replayDev = syncEvents.replayDev;
1345    int i;
1346    WindowPtr w;
1347    xEvent *xE;
1348    int count;
1349    GrabPtr grab;
1350    DeviceIntPtr dev;
1351
1352    for (dev = inputInfo.devices; dev; dev = dev->next)
1353	FreezeThaw(dev, dev->deviceGrab.sync.other ||
1354                (dev->deviceGrab.sync.state >= FROZEN));
1355    if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
1356	return;
1357    syncEvents.playingEvents = TRUE;
1358    if (replayDev)
1359    {
1360	xE = replayDev->deviceGrab.sync.event;
1361	count = replayDev->deviceGrab.sync.evcount;
1362	syncEvents.replayDev = (DeviceIntPtr)NULL;
1363
1364        w = XYToWindow(replayDev, XE_KBPTR.rootX, XE_KBPTR.rootY);
1365	for (i = 0; i < replayDev->spriteInfo->sprite->spriteTraceGood; i++)
1366	{
1367	    if (syncEvents.replayWin ==
1368		replayDev->spriteInfo->sprite->spriteTrace[i])
1369	    {
1370		if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) {
1371		    if (replayDev->focus && !IsPointerEvent(xE))
1372			DeliverFocusedEvent(replayDev, xE, w, count);
1373		    else
1374			DeliverDeviceEvents(w, xE, NullGrab, NullWindow,
1375					        replayDev, count);
1376		}
1377		goto playmore;
1378	    }
1379	}
1380	/* must not still be in the same stack */
1381	if (replayDev->focus && !IsPointerEvent(xE))
1382	    DeliverFocusedEvent(replayDev, xE, w, count);
1383	else
1384	    DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count);
1385    }
1386playmore:
1387    for (dev = inputInfo.devices; dev; dev = dev->next)
1388    {
1389	if (!dev->deviceGrab.sync.frozen)
1390	{
1391	    PlayReleasedEvents();
1392	    break;
1393	}
1394    }
1395    syncEvents.playingEvents = FALSE;
1396    for (dev = inputInfo.devices; dev; dev = dev->next)
1397    {
1398        if (DevHasCursor(dev))
1399        {
1400            /* the following may have been skipped during replay,
1401              so do it now */
1402            if ((grab = dev->deviceGrab.grab) && grab->confineTo)
1403            {
1404                if (grab->confineTo->drawable.pScreen !=
1405                        dev->spriteInfo->sprite->hotPhys.pScreen)
1406                    dev->spriteInfo->sprite->hotPhys.x =
1407                        dev->spriteInfo->sprite->hotPhys.y = 0;
1408                ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE);
1409            }
1410            else
1411                ConfineCursorToWindow(dev,
1412                        WindowTable[dev->spriteInfo->sprite->hotPhys.pScreen->myNum],
1413                        TRUE, FALSE);
1414            PostNewCursor(dev);
1415        }
1416    }
1417}
1418
1419#ifdef RANDR
1420void
1421ScreenRestructured (ScreenPtr pScreen)
1422{
1423    GrabPtr grab;
1424    DeviceIntPtr pDev;
1425
1426    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
1427    {
1428        if (!DevHasCursor(pDev))
1429            continue;
1430
1431        /* GrabDevice doesn't have a confineTo field, so we don't need to
1432         * worry about it. */
1433        if ((grab = pDev->deviceGrab.grab) && grab->confineTo)
1434        {
1435            if (grab->confineTo->drawable.pScreen
1436                    != pDev->spriteInfo->sprite->hotPhys.pScreen)
1437                pDev->spriteInfo->sprite->hotPhys.x = pDev->spriteInfo->sprite->hotPhys.y = 0;
1438            ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
1439        }
1440        else
1441            ConfineCursorToWindow(pDev,
1442                    WindowTable[pDev->spriteInfo->sprite->hotPhys.pScreen->myNum],
1443                    TRUE, FALSE);
1444    }
1445}
1446#endif
1447
1448static void
1449CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
1450{
1451    GrabPtr grab = thisDev->deviceGrab.grab;
1452    DeviceIntPtr dev;
1453
1454    if (thisMode == GrabModeSync)
1455	thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT;
1456    else
1457    {	/* free both if same client owns both */
1458	thisDev->deviceGrab.sync.state = THAWED;
1459	if (thisDev->deviceGrab.sync.other &&
1460	    (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) ==
1461	     CLIENT_BITS(grab->resource)))
1462	    thisDev->deviceGrab.sync.other = NullGrab;
1463    }
1464
1465    /*
1466        XXX: Direct slave grab won't freeze the paired master device.
1467        The correct thing to do would be to freeze all SDs attached to the
1468        paired master device.
1469     */
1470    if (thisDev->isMaster)
1471    {
1472        dev = GetPairedDevice(thisDev);
1473        if (otherMode == GrabModeSync)
1474            dev->deviceGrab.sync.other = grab;
1475        else
1476        {	/* free both if same client owns both */
1477            if (dev->deviceGrab.sync.other &&
1478                    (CLIENT_BITS(dev->deviceGrab.sync.other->resource) ==
1479                     CLIENT_BITS(grab->resource)))
1480                dev->deviceGrab.sync.other = NullGrab;
1481        }
1482    }
1483    ComputeFreezes();
1484}
1485
1486/**
1487 * Activate a pointer grab on the given device. A pointer grab will cause all
1488 * core pointer events of this device to be delivered to the grabbing client only.
1489 * No other device will send core events to the grab client while the grab is
1490 * on, but core events will be sent to other clients.
1491 * Can cause the cursor to change if a grab cursor is set.
1492 *
1493 * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab
1494 * is an implicit grab caused by a ButtonPress event.
1495 *
1496 * @param mouse The device to grab.
1497 * @param grab The grab structure, needs to be setup.
1498 * @param autoGrab True if the grab was caused by a button down event and not
1499 * explicitely by a client.
1500 */
1501void
1502ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
1503                    TimeStamp time, Bool autoGrab)
1504{
1505    GrabInfoPtr grabinfo = &mouse->deviceGrab;
1506    WindowPtr oldWin = (grabinfo->grab) ?
1507                        grabinfo->grab->window
1508                        : mouse->spriteInfo->sprite->win;
1509    Bool isPassive = autoGrab & ~ImplicitGrabMask;
1510
1511    if (grab->confineTo)
1512    {
1513	if (grab->confineTo->drawable.pScreen
1514                != mouse->spriteInfo->sprite->hotPhys.pScreen)
1515	    mouse->spriteInfo->sprite->hotPhys.x =
1516                mouse->spriteInfo->sprite->hotPhys.y = 0;
1517	ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE);
1518    }
1519    DoEnterLeaveEvents(mouse, oldWin, grab->window, NotifyGrab);
1520    mouse->valuator->motionHintWindow = NullWindow;
1521    if (syncEvents.playingEvents)
1522        grabinfo->grabTime = syncEvents.time;
1523    else
1524	grabinfo->grabTime = time;
1525    if (grab->cursor)
1526	grab->cursor->refcnt++;
1527    grabinfo->activeGrab = *grab;
1528    grabinfo->grab = &grabinfo->activeGrab;
1529    grabinfo->fromPassiveGrab = isPassive;
1530    grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
1531    PostNewCursor(mouse);
1532    CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
1533}
1534
1535/**
1536 * Delete grab on given device, update the sprite.
1537 *
1538 * Extension devices are set up for ActivateKeyboardGrab().
1539 */
1540void
1541DeactivatePointerGrab(DeviceIntPtr mouse)
1542{
1543    GrabPtr grab = mouse->deviceGrab.grab;
1544    DeviceIntPtr dev;
1545
1546    mouse->valuator->motionHintWindow = NullWindow;
1547    mouse->deviceGrab.grab = NullGrab;
1548    mouse->deviceGrab.sync.state = NOT_GRABBED;
1549    mouse->deviceGrab.fromPassiveGrab = FALSE;
1550
1551    /* make sure the potential XGE event mask is freed too*/
1552    if (grab->genericMasks)
1553    {
1554        xfree(grab->genericMasks);
1555        grab->genericMasks = NULL;
1556    }
1557
1558    for (dev = inputInfo.devices; dev; dev = dev->next)
1559    {
1560	if (dev->deviceGrab.sync.other == grab)
1561	    dev->deviceGrab.sync.other = NullGrab;
1562    }
1563    DoEnterLeaveEvents(mouse, grab->window,
1564                       mouse->spriteInfo->sprite->win, NotifyUngrab);
1565    if (grab->confineTo)
1566	ConfineCursorToWindow(mouse, RootWindow(mouse), FALSE, FALSE);
1567    PostNewCursor(mouse);
1568    if (grab->cursor)
1569	FreeCursor(grab->cursor, (Cursor)0);
1570
1571    ComputeFreezes();
1572}
1573
1574/**
1575 * Activate a keyboard grab on the given device.
1576 *
1577 * Extension devices have ActivateKeyboardGrab() set as their grabbing proc.
1578 */
1579void
1580ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive)
1581{
1582    GrabInfoPtr grabinfo = &keybd->deviceGrab;
1583    WindowPtr oldWin;
1584
1585    if (grabinfo->grab)
1586	oldWin = grabinfo->grab->window;
1587    else if (keybd->focus)
1588	oldWin = keybd->focus->win;
1589    else
1590	oldWin = keybd->spriteInfo->sprite->win;
1591    if (oldWin == FollowKeyboardWin)
1592	oldWin = inputInfo.keyboard->focus->win;
1593    if (keybd->valuator)
1594	keybd->valuator->motionHintWindow = NullWindow;
1595    DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
1596    if (syncEvents.playingEvents)
1597	grabinfo->grabTime = syncEvents.time;
1598    else
1599	grabinfo->grabTime = time;
1600    grabinfo->activeGrab = *grab;
1601    grabinfo->grab = &grabinfo->activeGrab;
1602    grabinfo->fromPassiveGrab = passive;
1603    CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
1604}
1605
1606/**
1607 * Delete keyboard grab for the given device.
1608 */
1609void
1610DeactivateKeyboardGrab(DeviceIntPtr keybd)
1611{
1612    GrabPtr grab = keybd->deviceGrab.grab;
1613    DeviceIntPtr dev;
1614    WindowPtr focusWin = keybd->focus ? keybd->focus->win
1615                                           : keybd->spriteInfo->sprite->win;
1616
1617    if (focusWin == FollowKeyboardWin)
1618	focusWin = inputInfo.keyboard->focus->win;
1619    if (keybd->valuator)
1620	keybd->valuator->motionHintWindow = NullWindow;
1621    keybd->deviceGrab.grab = NullGrab;
1622    keybd->deviceGrab.sync.state = NOT_GRABBED;
1623    keybd->deviceGrab.fromPassiveGrab = FALSE;
1624    if (grab->genericMasks)
1625    {
1626        xfree(grab->genericMasks);
1627        grab->genericMasks = NULL;
1628    }
1629
1630    for (dev = inputInfo.devices; dev; dev = dev->next)
1631    {
1632	if (dev->deviceGrab.sync.other == grab)
1633	    dev->deviceGrab.sync.other = NullGrab;
1634    }
1635    DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
1636
1637    ComputeFreezes();
1638}
1639
1640void
1641AllowSome(ClientPtr client,
1642          TimeStamp time,
1643          DeviceIntPtr thisDev,
1644          int newState,
1645          Bool core)
1646{
1647    Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
1648    TimeStamp grabTime;
1649    DeviceIntPtr dev;
1650    GrabInfoPtr devgrabinfo,
1651                grabinfo = &thisDev->deviceGrab;
1652
1653    thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
1654    thisSynced = FALSE;
1655    otherGrabbed = FALSE;
1656    othersFrozen = TRUE;
1657    grabTime = grabinfo->grabTime;
1658    for (dev = inputInfo.devices; dev; dev = dev->next)
1659    {
1660        devgrabinfo = &dev->deviceGrab;
1661
1662	if (dev == thisDev)
1663	    continue;
1664	if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
1665	{
1666	    if (!(thisGrabbed || otherGrabbed) ||
1667		(CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER))
1668		grabTime = devgrabinfo->grabTime;
1669	    otherGrabbed = TRUE;
1670	    if (grabinfo->sync.other == devgrabinfo->grab)
1671		thisSynced = TRUE;
1672	    if (devgrabinfo->sync.state < FROZEN)
1673		othersFrozen = FALSE;
1674	}
1675	else if (!devgrabinfo->sync.other || !SameClient(devgrabinfo->sync.other, client))
1676	    othersFrozen = FALSE;
1677    }
1678    if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced))
1679	return;
1680    if ((CompareTimeStamps(time, currentTime) == LATER) ||
1681	(CompareTimeStamps(time, grabTime) == EARLIER))
1682	return;
1683    switch (newState)
1684    {
1685	case THAWED:		       /* Async */
1686	    if (thisGrabbed)
1687		grabinfo->sync.state = THAWED;
1688	    if (thisSynced)
1689		grabinfo->sync.other = NullGrab;
1690	    ComputeFreezes();
1691	    break;
1692	case FREEZE_NEXT_EVENT:		/* Sync */
1693	    if (thisGrabbed)
1694	    {
1695		grabinfo->sync.state = FREEZE_NEXT_EVENT;
1696		if (thisSynced)
1697		    grabinfo->sync.other = NullGrab;
1698		ComputeFreezes();
1699	    }
1700	    break;
1701	case THAWED_BOTH:		/* AsyncBoth */
1702	    if (othersFrozen)
1703	    {
1704		for (dev = inputInfo.devices; dev; dev = dev->next)
1705		{
1706                    devgrabinfo = &dev->deviceGrab;
1707		    if (devgrabinfo->grab
1708                            && SameClient(devgrabinfo->grab, client))
1709			devgrabinfo->sync.state = THAWED;
1710		    if (devgrabinfo->sync.other &&
1711                            SameClient(devgrabinfo->sync.other, client))
1712			devgrabinfo->sync.other = NullGrab;
1713		}
1714		ComputeFreezes();
1715	    }
1716	    break;
1717	case FREEZE_BOTH_NEXT_EVENT:	/* SyncBoth */
1718	    if (othersFrozen)
1719	    {
1720		for (dev = inputInfo.devices; dev; dev = dev->next)
1721		{
1722                    devgrabinfo = &dev->deviceGrab;
1723		    if (devgrabinfo->grab
1724                            && SameClient(devgrabinfo->grab, client))
1725			devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT;
1726		    if (devgrabinfo->sync.other
1727                            && SameClient(devgrabinfo->sync.other, client))
1728			devgrabinfo->sync.other = NullGrab;
1729		}
1730		ComputeFreezes();
1731	    }
1732	    break;
1733	case NOT_GRABBED:		/* Replay */
1734	    if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT)
1735	    {
1736		if (thisSynced)
1737		    grabinfo->sync.other = NullGrab;
1738		syncEvents.replayDev = thisDev;
1739		syncEvents.replayWin = grabinfo->grab->window;
1740		(*grabinfo->DeactivateGrab)(thisDev);
1741		syncEvents.replayDev = (DeviceIntPtr)NULL;
1742	    }
1743	    break;
1744	case THAW_OTHERS:		/* AsyncOthers */
1745	    if (othersFrozen)
1746	    {
1747		for (dev = inputInfo.devices; dev; dev = dev->next)
1748		{
1749		    if (dev == thisDev)
1750			continue;
1751                    devgrabinfo = (core) ? &dev->deviceGrab : &dev->deviceGrab;
1752		    if (devgrabinfo->grab
1753                            && SameClient(devgrabinfo->grab, client))
1754			devgrabinfo->sync.state = THAWED;
1755		    if (devgrabinfo->sync.other
1756                            && SameClient(devgrabinfo->sync.other, client))
1757			devgrabinfo->sync.other = NullGrab;
1758		}
1759		ComputeFreezes();
1760	    }
1761	    break;
1762    }
1763}
1764
1765/**
1766 * Server-side protocol handling for AllowEvents request.
1767 *
1768 * Release some events from a frozen device.
1769 */
1770int
1771ProcAllowEvents(ClientPtr client)
1772{
1773    TimeStamp		time;
1774    DeviceIntPtr	mouse = NULL;
1775    DeviceIntPtr	keybd = NULL;
1776    REQUEST(xAllowEventsReq);
1777
1778    REQUEST_SIZE_MATCH(xAllowEventsReq);
1779    time = ClientTimeToServerTime(stuff->time);
1780
1781    mouse = PickPointer(client);
1782    keybd = PickKeyboard(client);
1783
1784    switch (stuff->mode)
1785    {
1786	case ReplayPointer:
1787	    AllowSome(client, time, mouse, NOT_GRABBED, True);
1788	    break;
1789	case SyncPointer:
1790	    AllowSome(client, time, mouse, FREEZE_NEXT_EVENT, True);
1791	    break;
1792	case AsyncPointer:
1793	    AllowSome(client, time, mouse, THAWED, True);
1794	    break;
1795	case ReplayKeyboard:
1796	    AllowSome(client, time, keybd, NOT_GRABBED, True);
1797	    break;
1798	case SyncKeyboard:
1799	    AllowSome(client, time, keybd, FREEZE_NEXT_EVENT, True);
1800	    break;
1801	case AsyncKeyboard:
1802	    AllowSome(client, time, keybd, THAWED, True);
1803	    break;
1804	case SyncBoth:
1805	    AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT, True);
1806	    break;
1807	case AsyncBoth:
1808	    AllowSome(client, time, keybd, THAWED_BOTH, True);
1809	    break;
1810	default:
1811	    client->errorValue = stuff->mode;
1812	    return BadValue;
1813    }
1814    return Success;
1815}
1816
1817/**
1818 * Deactivate grabs from any device that has been grabbed by the client.
1819 */
1820void
1821ReleaseActiveGrabs(ClientPtr client)
1822{
1823    DeviceIntPtr dev;
1824    Bool    done;
1825
1826    /* XXX CloseDownClient should remove passive grabs before
1827     * releasing active grabs.
1828     */
1829    do {
1830	done = TRUE;
1831	for (dev = inputInfo.devices; dev; dev = dev->next)
1832	{
1833	    if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
1834	    {
1835		(*dev->deviceGrab.DeactivateGrab)(dev);
1836		done = FALSE;
1837	    }
1838	}
1839    } while (!done);
1840}
1841
1842/**************************************************************************
1843 *            The following procedures deal with delivering events        *
1844 **************************************************************************/
1845
1846/**
1847 * Deliver the given events to the given client.
1848 *
1849 * More than one event may be delivered at a time. This is the case with
1850 * DeviceMotionNotifies which may be followed by DeviceValuator events.
1851 *
1852 * TryClientEvents() is the last station before actually writing the events to
1853 * the socket. Anything that is not filtered here, will get delivered to the
1854 * client.
1855 * An event is only delivered if
1856 *   - mask and filter match up.
1857 *   - no other client has a grab on the device that caused the event.
1858 *
1859 *
1860 * @param client The target client to deliver to.
1861 * @param dev The device the event came from. May be NULL.
1862 * @param pEvents The events to be delivered.
1863 * @param count Number of elements in pEvents.
1864 * @param mask Event mask as set by the window.
1865 * @param filter Mask based on event type.
1866 * @param grab Possible grab on the device that caused the event.
1867 *
1868 * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
1869 * client.
1870 */
1871_X_EXPORT int
1872TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
1873                 int count, Mask mask, Mask filter, GrabPtr grab)
1874{
1875    int i;
1876    int type;
1877
1878#ifdef DEBUG_EVENTS
1879    ErrorF("[dix] Event([%d, %d], mask=0x%x), client=%d",
1880	pEvents->u.u.type, pEvents->u.u.detail, mask, client->index);
1881#endif
1882    if ((client) && (client != serverClient) && (!client->clientGone) &&
1883	((filter == CantBeFiltered) || (mask & filter)))
1884    {
1885	if (grab && !SameClient(grab, client))
1886	    return -1; /* don't send, but notify caller */
1887	type = pEvents->u.u.type;
1888	if (type == MotionNotify)
1889	{
1890	    if (mask & PointerMotionHintMask)
1891	    {
1892		if (WID(dev->valuator->motionHintWindow) ==
1893		    pEvents->u.keyButtonPointer.event)
1894		{
1895#ifdef DEBUG_EVENTS
1896		    ErrorF("[dix] \n");
1897	    ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
1898#endif
1899		    return 1; /* don't send, but pretend we did */
1900		}
1901		pEvents->u.u.detail = NotifyHint;
1902	    }
1903	    else
1904	    {
1905		pEvents->u.u.detail = NotifyNormal;
1906	    }
1907	}
1908	else
1909	{
1910	    if ((type == DeviceMotionNotify) &&
1911		MaybeSendDeviceMotionNotifyHint
1912			((deviceKeyButtonPointer*)pEvents, mask) != 0)
1913		return 1;
1914	}
1915	type &= 0177;
1916	if (type != KeymapNotify)
1917	{
1918	    /* all extension events must have a sequence number */
1919	    for (i = 0; i < count; i++)
1920		pEvents[i].u.u.sequenceNumber = client->sequence;
1921	}
1922
1923	if (BitIsOn(criticalEvents, type))
1924	{
1925	    if (client->smart_priority < SMART_MAX_PRIORITY)
1926		client->smart_priority++;
1927	    SetCriticalOutputPending();
1928	}
1929
1930	WriteEventsToClient(client, count, pEvents);
1931#ifdef DEBUG_EVENTS
1932	ErrorF("[dix]  delivered\n");
1933#endif
1934	return 1;
1935    }
1936    else
1937    {
1938#ifdef DEBUG_EVENTS
1939	ErrorF("[dix] \n");
1940#endif
1941	return 0;
1942    }
1943}
1944
1945/**
1946 * Deliver events to a window. At this point, we do not yet know if the event
1947 * actually needs to be delivered. May activate a grab if the event is a
1948 * button press.
1949 *
1950 * Core events are always delivered to the window owner. If the filter is
1951 * something other than CantBeFiltered, the event is also delivered to other
1952 * clients with the matching mask on the window.
1953 *
1954 * More than one event may be delivered at a time. This is the case with
1955 * DeviceMotionNotifies which may be followed by DeviceValuator events.
1956 *
1957 * @param pWin The window that would get the event.
1958 * @param pEvents The events to be delivered.
1959 * @param count Number of elements in pEvents.
1960 * @param filter Mask based on event type.
1961 * @param grab Possible grab on the device that caused the event.
1962 * @param mskidx Mask index, depending on device that caused event.
1963 *
1964 * @return Number of events delivered to various clients.
1965 */
1966int
1967DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
1968        *pEvents, int count, Mask filter, GrabPtr grab, int mskidx)
1969{
1970    int deliveries = 0, nondeliveries = 0;
1971    int attempt;
1972    InputClients *other;
1973    ClientPtr client = NullClient;
1974    Mask deliveryMask = 0; /* If a grab occurs due to a button press, then
1975		              this mask is the mask of the grab. */
1976    int type = pEvents->u.u.type;
1977
1978    /* CantBeFiltered means only window owner gets the event */
1979    if ((filter == CantBeFiltered) ||
1980            (!(type & EXTENSION_EVENT_BASE) && type != GenericEvent))
1981    {
1982	/* if nobody ever wants to see this event, skip some work */
1983	if (filter != CantBeFiltered &&
1984	    !((wOtherEventMasks(pWin)|pWin->eventMask) & filter))
1985	    return 0;
1986
1987        if (!(type & EXTENSION_EVENT_BASE) &&
1988            IsInterferingGrab(wClient(pWin), pDev, pEvents))
1989                return 0;
1990
1991	if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
1992	    /* do nothing */;
1993        else if ( (attempt = TryClientEvents(wClient(pWin), pDev, pEvents,
1994                                             count, pWin->eventMask,
1995                                             filter, grab)) )
1996	{
1997	    if (attempt > 0)
1998	    {
1999		deliveries++;
2000		client = wClient(pWin);
2001		deliveryMask = pWin->eventMask;
2002	    } else
2003		nondeliveries--;
2004	}
2005    }
2006    if (filter != CantBeFiltered)
2007    {
2008        /* Handle generic events */
2009        if (type == GenericEvent)
2010        {
2011            GenericMaskPtr gmask;
2012            /* We don't do more than one GenericEvent at a time. */
2013            if (count > 1)
2014            {
2015                ErrorF("[dix] Do not send more than one GenericEvent at a time!\n");
2016                return 0;
2017            }
2018
2019            /* if we get here, filter should be set to the GE specific mask.
2020               check if any client wants it */
2021            if (!GEDeviceMaskIsSet(pWin, pDev, GEEXT(pEvents), filter))
2022                return 0;
2023
2024            /* run through all clients, deliver event */
2025            for (gmask = GECLIENT(pWin); gmask; gmask = gmask->next)
2026            {
2027                if (gmask->eventMask[GEEXTIDX(pEvents)] & filter)
2028                {
2029                    if (XaceHook(XACE_RECEIVE_ACCESS, rClient(gmask), pWin,
2030                                pEvents, count))
2031                        /* do nothing */;
2032                    else if (TryClientEvents(rClient(gmask), pDev,
2033                             pEvents, count,
2034                             gmask->eventMask[GEEXTIDX(pEvents)],
2035                             filter, grab) > 0)
2036                    {
2037                        deliveries++;
2038                    } else
2039                        nondeliveries--;
2040                }
2041            }
2042        }
2043        else {
2044            /* Traditional event */
2045            if (type & EXTENSION_EVENT_BASE)
2046            {
2047                OtherInputMasks *inputMasks;
2048
2049                inputMasks = wOtherInputMasks(pWin);
2050                if (!inputMasks ||
2051                        !(inputMasks->inputEvents[mskidx] & filter))
2052                    return 0;
2053                other = inputMasks->inputClients;
2054            }
2055            else
2056                other = (InputClients *)wOtherClients(pWin);
2057            for (; other; other = other->next)
2058            {
2059                /* core event? check for grab interference */
2060                if (!(type & EXTENSION_EVENT_BASE) &&
2061                        IsInterferingGrab(rClient(other), pDev, pEvents))
2062                    continue;
2063
2064                if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin,
2065                             pEvents, count))
2066                    /* do nothing */;
2067                else if ( (attempt = TryClientEvents(rClient(other), pDev,
2068                                                     pEvents, count,
2069                                                     other->mask[mskidx],
2070                                                     filter, grab)) )
2071                {
2072                    if (attempt > 0)
2073                    {
2074                        deliveries++;
2075                        client = rClient(other);
2076                        deliveryMask = other->mask[mskidx];
2077                    } else
2078                        nondeliveries--;
2079                }
2080            }
2081        }
2082    }
2083    /*
2084     * Note that since core events are delivered first, an implicit grab may
2085     * be activated on a core grab, stopping the XI events.
2086     */
2087    if ((type == DeviceButtonPress || type == ButtonPress)
2088            && deliveries
2089            && (!grab))
2090    {
2091	GrabRec tempGrab;
2092        OtherInputMasks *inputMasks;
2093
2094        tempGrab.next = NULL;
2095	tempGrab.device = pDev;
2096	tempGrab.resource = client->clientAsMask;
2097	tempGrab.window = pWin;
2098	tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
2099	tempGrab.eventMask = deliveryMask;
2100	tempGrab.keyboardMode = GrabModeAsync;
2101	tempGrab.pointerMode = GrabModeAsync;
2102	tempGrab.confineTo = NullWindow;
2103	tempGrab.cursor = NullCursor;
2104        tempGrab.coreGrab = (type == ButtonPress);
2105
2106        /* get the XI device mask */
2107        inputMasks = wOtherInputMasks(pWin);
2108        tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[pDev->id]: 0;
2109
2110        /* get the XGE event mask. */
2111        tempGrab.genericMasks = NULL;
2112        if (pWin->optional && pWin->optional->geMasks)
2113        {
2114            GenericClientMasksPtr gemasks = pWin->optional->geMasks;
2115            GenericMaskPtr geclient = gemasks->geClients;
2116            while(geclient && rClient(geclient) != client)
2117                geclient = geclient->next;
2118            if (geclient)
2119            {
2120                tempGrab.genericMasks = xcalloc(1, sizeof(GenericMaskRec));
2121                *tempGrab.genericMasks = *geclient;
2122                tempGrab.genericMasks->next = NULL;
2123            }
2124        }
2125	(*pDev->deviceGrab.ActivateGrab)(pDev, &tempGrab,
2126                                        currentTime, TRUE | ImplicitGrabMask);
2127    }
2128    else if ((type == MotionNotify) && deliveries)
2129	pDev->valuator->motionHintWindow = pWin;
2130    else
2131    {
2132	if (((type == DeviceMotionNotify)
2133#ifdef XKB
2134	     || (type == DeviceButtonPress)
2135#endif
2136	    ) && deliveries)
2137	    CheckDeviceGrabAndHintWindow (pWin, type,
2138					  (deviceKeyButtonPointer*) pEvents,
2139					  grab, client, deliveryMask);
2140    }
2141    if (deliveries)
2142	return deliveries;
2143    return nondeliveries;
2144}
2145
2146/* If the event goes to dontClient, don't send it and return 0.  if
2147   send works,  return 1 or if send didn't work, return 2.
2148   Only works for core events.
2149*/
2150
2151#ifdef PANORAMIX
2152static int
2153XineramaTryClientEventsResult(
2154    ClientPtr client,
2155    GrabPtr grab,
2156    Mask mask,
2157    Mask filter
2158){
2159    if ((client) && (client != serverClient) && (!client->clientGone) &&
2160        ((filter == CantBeFiltered) || (mask & filter)))
2161    {
2162        if (grab && !SameClient(grab, client)) return -1;
2163	else return 1;
2164    }
2165    return 0;
2166}
2167#endif
2168
2169/**
2170 * Try to deliver events to the interested parties.
2171 *
2172 * @param pWin The window that would get the event.
2173 * @param pEvents The events to be delivered.
2174 * @param count Number of elements in pEvents.
2175 * @param filter Mask based on event type.
2176 * @param dontClient Don't deliver to the dontClient.
2177 */
2178int
2179MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
2180                           int count, Mask filter, ClientPtr dontClient)
2181{
2182    OtherClients *other;
2183
2184
2185    if (pWin->eventMask & filter)
2186    {
2187        if (wClient(pWin) == dontClient)
2188	    return 0;
2189#ifdef PANORAMIX
2190	if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2191	    return XineramaTryClientEventsResult(
2192			wClient(pWin), NullGrab, pWin->eventMask, filter);
2193#endif
2194	if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
2195	    return 1; /* don't send, but pretend we did */
2196	return TryClientEvents(wClient(pWin), NULL, pEvents, count,
2197			       pWin->eventMask, filter, NullGrab);
2198    }
2199    for (other = wOtherClients(pWin); other; other = other->next)
2200    {
2201	if (other->mask & filter)
2202	{
2203            if (SameClient(other, dontClient))
2204		return 0;
2205#ifdef PANORAMIX
2206	    if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2207	      return XineramaTryClientEventsResult(
2208			rClient(other), NullGrab, other->mask, filter);
2209#endif
2210	    if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents,
2211			 count))
2212		return 1; /* don't send, but pretend we did */
2213	    return TryClientEvents(rClient(other), NULL, pEvents, count,
2214				   other->mask, filter, NullGrab);
2215	}
2216    }
2217    return 2;
2218}
2219
2220/**
2221 * Adjust event fields to comply with the window properties.
2222 *
2223 * @param xE Event to be modified in place
2224 * @param pWin The window to get the information from.
2225 * @param child Child window setting for event (if applicable)
2226 * @param calcChild If True, calculate the child window.
2227 */
2228static void
2229FixUpEventFromWindow(
2230    DeviceIntPtr pDev,
2231    xEvent *xE,
2232    WindowPtr pWin,
2233    Window child,
2234    Bool calcChild)
2235{
2236    SpritePtr pSprite = pDev->spriteInfo->sprite;
2237
2238    if (xE->u.u.type == GenericEvent) /* just a safety barrier */
2239        return;
2240
2241    if (calcChild)
2242    {
2243        WindowPtr w= pSprite->spriteTrace[pSprite->spriteTraceGood-1];
2244	/* If the search ends up past the root should the child field be
2245		set to none or should the value in the argument be passed
2246		through. It probably doesn't matter since everyone calls
2247		this function with child == None anyway. */
2248
2249        while (w)
2250        {
2251            /* If the source window is same as event window, child should be
2252		none.  Don't bother going all all the way back to the root. */
2253
2254	    if (w == pWin)
2255	    {
2256		child = None;
2257		break;
2258	    }
2259
2260	    if (w->parent == pWin)
2261	    {
2262		child = w->drawable.id;
2263		break;
2264            }
2265	    w = w->parent;
2266        }
2267    }
2268    XE_KBPTR.root = RootWindow(pDev)->drawable.id;
2269    XE_KBPTR.event = pWin->drawable.id;
2270    if (pSprite->hot.pScreen == pWin->drawable.pScreen)
2271    {
2272	XE_KBPTR.sameScreen = xTrue;
2273	XE_KBPTR.child = child;
2274	XE_KBPTR.eventX =
2275	XE_KBPTR.rootX - pWin->drawable.x;
2276	XE_KBPTR.eventY =
2277	XE_KBPTR.rootY - pWin->drawable.y;
2278    }
2279    else
2280    {
2281	XE_KBPTR.sameScreen = xFalse;
2282	XE_KBPTR.child = None;
2283	XE_KBPTR.eventX = 0;
2284	XE_KBPTR.eventY = 0;
2285    }
2286}
2287
2288/**
2289 * Deliver events caused by input devices. Called for both core input events
2290 * and XI events.
2291 * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is
2292 * called directly from the processInputProc.
2293 * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call
2294 * DeliverDeviceEvents.
2295 * For focused events, DeliverFocusedEvent is called first, and _may_ call
2296 * DeliverDeviceEvents.
2297 *
2298 * @param pWin Window to deliver event to.
2299 * @param xE Events to deliver.
2300 * @param grab Possible grab on a device.
2301 * @param stopAt Don't recurse up to the root window.
2302 * @param dev The device that is responsible for the event.
2303 * @param count number of events in xE.
2304 *
2305 * @see DeliverGrabbedEvent
2306 * @see DeliverFocusedEvent
2307 */
2308int
2309DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab,
2310                    WindowPtr stopAt, DeviceIntPtr dev, int count)
2311{
2312    Window child = None;
2313    int type = xE->u.u.type;
2314    Mask filter = filters[dev->id][type];
2315    int deliveries = 0;
2316    OtherInputMasks *inputMasks;
2317    int mskidx = dev->id;
2318    xEvent core;
2319
2320    if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count))
2321	return 0;
2322
2323    /* handle generic events */
2324    /* XXX: Generic events aren't quite handled correctly yet. They should
2325     * eventually fit in with the rest of the stuff
2326     */
2327    if (type == GenericEvent)
2328    {
2329        WindowPtr win = pWin;
2330        xGenericEvent* ge = (xGenericEvent*)xE;
2331
2332        if (count > 1)
2333        {
2334            ErrorF("[dix] Do not send more than one GenericEvent at a time!\n");
2335            return 0;
2336        }
2337        filter = generic_filters[GEEXTIDX(xE)][ge->evtype];
2338
2339        while(win)
2340        {
2341            if (GEDeviceMaskIsSet(win, dev, GEEXT(xE), filter))
2342            {
2343                if (GEExtensions[GEEXTIDX(xE)].evfill)
2344                    GEExtensions[GEEXTIDX(xE)].evfill(ge, dev, win, grab);
2345                deliveries = DeliverEventsToWindow(dev, win, xE, count,
2346                        filter, grab, 0);
2347                if (deliveries > 0)
2348                    return deliveries;
2349            }
2350
2351            win = win->parent;
2352        }
2353    }
2354
2355    while (pWin && type != GenericEvent)
2356    {
2357        if (!dev->isMaster)
2358        {
2359            inputMasks = wOtherInputMasks(pWin);
2360            if (inputMasks && (filter & inputMasks->deliverableEvents[mskidx]))
2361            {
2362
2363                if (inputMasks && (inputMasks->inputEvents[mskidx] & filter))
2364                {
2365                    FixUpEventFromWindow(dev, xE, pWin, child, FALSE);
2366                    deliveries = DeliverEventsToWindow(dev, pWin, xE, count,
2367                            filter, grab, mskidx);
2368                    if (deliveries > 0)
2369                        return deliveries;
2370                }
2371            }
2372
2373            if ((deliveries < 0) || (pWin == stopAt) ||
2374                    (inputMasks && (filter & inputMasks->dontPropagateMask[mskidx])))
2375                return 0;
2376        } else
2377        {
2378            core = *xE;
2379            core.u.u.type = XItoCoreType(xE->u.u.type);
2380
2381            if (core.u.u.type && filter & pWin->deliverableEvents)
2382            {
2383                if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter)
2384                {
2385                    FixUpEventFromWindow(dev, &core, pWin, child, FALSE);
2386                    deliveries = DeliverEventsToWindow(dev, pWin, &core, 1,
2387                            filter, grab, 0);
2388                    if (deliveries > 0)
2389                        return deliveries;
2390                }
2391            }
2392
2393            if ((deliveries < 0) || (pWin == stopAt) ||
2394                (filter & wDontPropagateMask(pWin)))
2395                return 0;
2396        }
2397
2398        child = pWin->drawable.id;
2399        pWin = pWin->parent;
2400    }
2401
2402    return 0;
2403}
2404
2405/**
2406 * Deliver event to a window and it's immediate parent. Used for most window
2407 * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
2408 * propagate up the tree or extension events
2409 *
2410 * In case of a ReparentNotify event, the event will be delivered to the
2411 * otherParent as well.
2412 *
2413 * @param pWin Window to deliver events to.
2414 * @param xE Events to deliver.
2415 * @param count number of events in xE.
2416 * @param otherParent Used for ReparentNotify events.
2417 */
2418_X_EXPORT int
2419DeliverEvents(WindowPtr pWin, xEvent *xE, int count,
2420              WindowPtr otherParent)
2421{
2422    Mask filter;
2423    int     deliveries;
2424
2425#ifdef PANORAMIX
2426    if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2427	return count;
2428#endif
2429
2430    if (!count)
2431	return 0;
2432    /* We don't know a device here. However, this should only ever be called
2433       for a non-device event so we are safe to use 0*/
2434    filter = filters[0][xE->u.u.type];
2435    if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify))
2436	xE->u.destroyNotify.event = pWin->drawable.id;
2437    if (filter != StructureAndSubMask)
2438	return DeliverEventsToWindow(inputInfo.pointer, pWin, xE, count, filter, NullGrab, 0);
2439    deliveries = DeliverEventsToWindow(inputInfo.pointer, pWin, xE, count, StructureNotifyMask,
2440				       NullGrab, 0);
2441    if (pWin->parent)
2442    {
2443	xE->u.destroyNotify.event = pWin->parent->drawable.id;
2444	deliveries += DeliverEventsToWindow(inputInfo.pointer, pWin->parent, xE, count,
2445					    SubstructureNotifyMask, NullGrab,
2446					    0);
2447	if (xE->u.u.type == ReparentNotify)
2448	{
2449	    xE->u.destroyNotify.event = otherParent->drawable.id;
2450            deliveries += DeliverEventsToWindow(inputInfo.pointer,
2451                    otherParent, xE, count, SubstructureNotifyMask,
2452						NullGrab, 0);
2453	}
2454    }
2455    return deliveries;
2456}
2457
2458
2459static Bool
2460PointInBorderSize(WindowPtr pWin, int x, int y)
2461{
2462    BoxRec box;
2463    SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
2464
2465    if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box))
2466	return TRUE;
2467
2468#ifdef PANORAMIX
2469    if(!noPanoramiXExtension &&
2470            XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
2471	int i;
2472
2473	for(i = 1; i < PanoramiXNumScreens; i++) {
2474	   if(POINT_IN_REGION(pSprite->screen,
2475			&pSprite->windows[i]->borderSize,
2476			x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x,
2477			y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y,
2478			&box))
2479		return TRUE;
2480	}
2481    }
2482#endif
2483    return FALSE;
2484}
2485
2486/**
2487 * Traversed from the root window to the window at the position x/y. While
2488 * traversing, it sets up the traversal history in the spriteTrace array.
2489 * After completing, the spriteTrace history is set in the following way:
2490 *   spriteTrace[0] ... root window
2491 *   spriteTrace[1] ... top level window that encloses x/y
2492 *       ...
2493 *   spriteTrace[spriteTraceGood - 1] ... window at x/y
2494 *
2495 * @returns the window at the given coordinates.
2496 */
2497static WindowPtr
2498XYToWindow(DeviceIntPtr pDev, int x, int y)
2499{
2500    WindowPtr  pWin;
2501    BoxRec		box;
2502    SpritePtr pSprite;
2503
2504    pSprite = pDev->spriteInfo->sprite;
2505    pSprite->spriteTraceGood = 1;	/* root window still there */
2506    pWin = RootWindow(pDev)->firstChild;
2507    while (pWin)
2508    {
2509	if ((pWin->mapped) &&
2510	    (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
2511	    (x < pWin->drawable.x + (int)pWin->drawable.width +
2512	     wBorderWidth(pWin)) &&
2513	    (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
2514	    (y < pWin->drawable.y + (int)pWin->drawable.height +
2515	     wBorderWidth (pWin))
2516	    /* When a window is shaped, a further check
2517	     * is made to see if the point is inside
2518	     * borderSize
2519	     */
2520	    && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
2521	    && (!wInputShape(pWin) ||
2522		POINT_IN_REGION(pWin->drawable.pScreen,
2523				wInputShape(pWin),
2524				x - pWin->drawable.x,
2525				y - pWin->drawable.y, &box))
2526#ifdef ROOTLESS
2527    /* In rootless mode windows may be offscreen, even when
2528     * they're in X's stack. (E.g. if the native window system
2529     * implements some form of virtual desktop system).
2530     */
2531		&& !pWin->rootlessUnhittable
2532#endif
2533	    )
2534	{
2535	    if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize)
2536	    {
2537		pSprite->spriteTraceSize += 10;
2538		pSprite->spriteTrace = xrealloc(pSprite->spriteTrace,
2539		                    pSprite->spriteTraceSize*sizeof(WindowPtr));
2540	    }
2541	    pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
2542	    pWin = pWin->firstChild;
2543	}
2544	else
2545	    pWin = pWin->nextSib;
2546    }
2547    return pSprite->spriteTrace[pSprite->spriteTraceGood-1];
2548}
2549
2550/**
2551 * Update the sprite coordinates based on the event. Update the cursor
2552 * position, then update the event with the new coordinates that may have been
2553 * changed. If the window underneath the sprite has changed, change to new
2554 * cursor and send enter/leave events.
2555 *
2556 * CheckMotion() will not do anything and return FALSE if the event is not a
2557 * pointer event.
2558 *
2559 * @return TRUE if the sprite has moved or FALSE otherwise.
2560 */
2561Bool
2562CheckMotion(xEvent *xE, DeviceIntPtr pDev)
2563{
2564    INT16     *rootX, *rootY;
2565    WindowPtr prevSpriteWin;
2566    SpritePtr pSprite = pDev->spriteInfo->sprite;
2567
2568    prevSpriteWin = pSprite->win;
2569
2570#ifdef PANORAMIX
2571    if(!noPanoramiXExtension)
2572	return XineramaCheckMotion(xE, pDev);
2573#endif
2574
2575    if (xE && !syncEvents.playingEvents)
2576    {
2577        /* GetPointerEvents() guarantees that pointer events have the correct
2578           rootX/Y set already. */
2579        switch(xE->u.u.type)
2580        {
2581            case ButtonPress:
2582            case ButtonRelease:
2583            case MotionNotify:
2584                rootX = &XE_KBPTR.rootX;
2585                rootY = &XE_KBPTR.rootY;
2586                break;
2587            default:
2588                if (xE->u.u.type == DeviceButtonPress ||
2589                        xE->u.u.type == DeviceButtonRelease ||
2590                        xE->u.u.type == DeviceMotionNotify)
2591                {
2592                    rootX = &((deviceKeyButtonPointer*)xE)->root_x;
2593                    rootY = &((deviceKeyButtonPointer*)xE)->root_y;
2594                    break;
2595                }
2596                /* all other events return FALSE */
2597                return FALSE;
2598        }
2599
2600        if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen)
2601        {
2602            pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
2603            RootWindow(pDev) = WindowTable[pSprite->hot.pScreen->myNum];
2604        }
2605        pSprite->hot.x = *rootX;
2606        pSprite->hot.y = *rootY;
2607        if (pSprite->hot.x < pSprite->physLimits.x1)
2608            pSprite->hot.x = pSprite->physLimits.x1;
2609        else if (pSprite->hot.x >= pSprite->physLimits.x2)
2610            pSprite->hot.x = pSprite->physLimits.x2 - 1;
2611        if (pSprite->hot.y < pSprite->physLimits.y1)
2612            pSprite->hot.y = pSprite->physLimits.y1;
2613        else if (pSprite->hot.y >= pSprite->physLimits.y2)
2614            pSprite->hot.y = pSprite->physLimits.y2 - 1;
2615	if (pSprite->hotShape)
2616	    ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y);
2617	pSprite->hotPhys = pSprite->hot;
2618
2619	if ((pSprite->hotPhys.x != *rootX) ||
2620	    (pSprite->hotPhys.y != *rootY))
2621	{
2622	    (*pSprite->hotPhys.pScreen->SetCursorPosition)(
2623                pDev, pSprite->hotPhys.pScreen,
2624		pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
2625	}
2626
2627	*rootX = pSprite->hot.x;
2628	*rootY = pSprite->hot.y;
2629    }
2630
2631    pSprite->win = XYToWindow(pDev, pSprite->hot.x, pSprite->hot.y);
2632#ifdef notyet
2633    if (!(pSprite->win->deliverableEvents &
2634	  Motion_Filter(pDev->button))
2635	!syncEvents.playingEvents)
2636    {
2637	/* XXX Do PointerNonInterestBox here */
2638    }
2639#endif
2640    if (pSprite->win != prevSpriteWin)
2641    {
2642	if (prevSpriteWin != NullWindow) {
2643	    if (!xE)
2644		UpdateCurrentTimeIf();
2645            DoEnterLeaveEvents(pDev, prevSpriteWin, pSprite->win,
2646                               NotifyNormal);
2647        }
2648	PostNewCursor(pDev);
2649        return FALSE;
2650    }
2651    return TRUE;
2652}
2653
2654/**
2655 * Windows have restructured, we need to update the sprite position and the
2656 * sprite's cursor.
2657 */
2658void
2659WindowsRestructured(void)
2660{
2661    DeviceIntPtr pDev = inputInfo.devices;
2662    while(pDev)
2663    {
2664        if (DevHasCursor(pDev))
2665            CheckMotion((xEvent *)NULL, pDev);
2666        pDev = pDev->next;
2667    }
2668}
2669
2670#ifdef PANORAMIX
2671/* This was added to support reconfiguration under Xdmx.  The problem is
2672 * that if the 0th screen (i.e., WindowTable[0]) is moved to an origin
2673 * other than 0,0, the information in the private sprite structure must
2674 * be updated accordingly, or XYToWindow (and other routines) will not
2675 * compute correctly. */
2676void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
2677{
2678    GrabPtr   grab;
2679    DeviceIntPtr pDev;
2680    SpritePtr pSprite;
2681
2682    if (noPanoramiXExtension) return;
2683
2684    pDev = inputInfo.devices;
2685    while(pDev)
2686    {
2687        if (DevHasCursor(pDev))
2688        {
2689            pSprite = pDev->spriteInfo->sprite;
2690            pSprite->hot.x        -= xoff;
2691            pSprite->hot.y        -= yoff;
2692
2693            pSprite->hotPhys.x    -= xoff;
2694            pSprite->hotPhys.y    -= yoff;
2695
2696            pSprite->hotLimits.x1 -= xoff;
2697            pSprite->hotLimits.y1 -= yoff;
2698            pSprite->hotLimits.x2 -= xoff;
2699            pSprite->hotLimits.y2 -= yoff;
2700
2701            if (REGION_NOTEMPTY(pSprite->screen, &pSprite->Reg1))
2702                REGION_TRANSLATE(pSprite->screen, &pSprite->Reg1,    xoff, yoff);
2703            if (REGION_NOTEMPTY(pSprite->screen, &pSprite->Reg2))
2704                REGION_TRANSLATE(pSprite->screen, &pSprite->Reg2,    xoff, yoff);
2705
2706            /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
2707            if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
2708                if (grab->confineTo->drawable.pScreen
2709                        != pSprite->hotPhys.pScreen)
2710                    pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
2711                ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
2712            } else
2713                ConfineCursorToWindow(
2714                        pDev,
2715                        WindowTable[pSprite->hotPhys.pScreen->myNum],
2716                        TRUE, FALSE);
2717
2718        }
2719        pDev = pDev->next;
2720    }
2721}
2722#endif
2723
2724/**
2725 * Called from main() with the root window on the first screen. Used to do a
2726 * lot more when MPX wasn't around yet. Things change.
2727 *
2728 * Should delete this now? -ds
2729 */
2730void
2731DefineInitialRootWindow(WindowPtr win)
2732{
2733}
2734
2735/**
2736 * Initialize a sprite for the given device and set it to some sane values. If
2737 * the device already has a sprite alloc'd, don't realloc but just reset to
2738 * default values.
2739 * If a window is supplied, the sprite will be initialized with the window's
2740 * cursor and positioned in the center of the window's screen. The root window
2741 * is a good choice to pass in here.
2742 *
2743 * It's a good idea to call it only for pointer devices, unless you have a
2744 * really talented keyboard.
2745 *
2746 * @param pDev The device to initialize.
2747 * @param pWin The window where to generate the sprite in.
2748 *
2749 */
2750void
2751InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
2752{
2753    SpritePtr pSprite;
2754    ScreenPtr pScreen;
2755
2756    if (!pDev->spriteInfo->sprite)
2757    {
2758        DeviceIntPtr it;
2759
2760        pDev->spriteInfo->sprite = (SpritePtr)xcalloc(1, sizeof(SpriteRec));
2761        if (!pDev->spriteInfo->sprite)
2762            FatalError("InitializeSprite: failed to allocate sprite struct");
2763
2764        /* We may have paired another device with this device before our
2765         * device had a actual sprite. We need to check for this and reset the
2766         * sprite field for all paired devices.
2767         *
2768         * The VCK is always paired with the VCP before the VCP has a sprite.
2769         */
2770        for (it = inputInfo.devices; it; it = it->next)
2771        {
2772            if (it->spriteInfo->paired == pDev)
2773                it->spriteInfo->sprite = pDev->spriteInfo->sprite;
2774        }
2775        if (inputInfo.keyboard->spriteInfo->paired == pDev)
2776            inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite;
2777    }
2778
2779    pSprite = pDev->spriteInfo->sprite;
2780    pDev->spriteInfo->spriteOwner = TRUE;
2781
2782    pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr)NULL;
2783    pSprite->hot.pScreen = pScreen;
2784    pSprite->hotPhys.pScreen = pScreen;
2785    if (pScreen)
2786    {
2787        pSprite->hotPhys.x = pScreen->width / 2;
2788        pSprite->hotPhys.y = pScreen->height / 2;
2789        pSprite->hotLimits.x2 = pScreen->width;
2790        pSprite->hotLimits.y2 = pScreen->height;
2791    }
2792
2793    pSprite->hot = pSprite->hotPhys;
2794    pSprite->win = pWin;
2795
2796    if (pWin)
2797    {
2798        pSprite->current = wCursor(pWin);
2799        pSprite->current->refcnt++;
2800	pSprite->spriteTrace = (WindowPtr *)xcalloc(1, 32*sizeof(WindowPtr));
2801	if (!pSprite->spriteTrace)
2802	    FatalError("Failed to allocate spriteTrace");
2803	pSprite->spriteTraceSize = 32;
2804
2805	RootWindow(pDev) = pWin;
2806	pSprite->spriteTraceGood = 1;
2807
2808	pSprite->pEnqueueScreen = pScreen;
2809	pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
2810
2811    } else {
2812        pSprite->current = NullCursor;
2813	pSprite->spriteTrace = NULL;
2814	pSprite->spriteTraceSize = 0;
2815	pSprite->spriteTraceGood = 0;
2816	pSprite->pEnqueueScreen = screenInfo.screens[0];
2817	pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
2818    }
2819
2820    if (pScreen)
2821    {
2822        (*pScreen->RealizeCursor) ( pDev, pScreen, pSprite->current);
2823        (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current,
2824                                   &pSprite->hotLimits, &pSprite->physLimits);
2825        pSprite->confined = FALSE;
2826
2827        (*pScreen->ConstrainCursor) (pDev, pScreen,
2828                                     &pSprite->physLimits);
2829        (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
2830                                       pSprite->hot.y,
2831                                       FALSE);
2832        (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
2833    }
2834#ifdef PANORAMIX
2835    if(!noPanoramiXExtension) {
2836        pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x;
2837        pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y;
2838        pSprite->hotLimits.x2 = PanoramiXPixWidth  - panoramiXdataPtr[0].x;
2839        pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
2840        pSprite->physLimits = pSprite->hotLimits;
2841        pSprite->confineWin = NullWindow;
2842        pSprite->hotShape = NullRegion;
2843        pSprite->screen = pScreen;
2844        /* gotta UNINIT these someplace */
2845        REGION_NULL(pScreen, &pSprite->Reg1);
2846        REGION_NULL(pScreen, &pSprite->Reg2);
2847    }
2848#endif
2849}
2850
2851/**
2852 * Update the mouse sprite info when the server switches from a pScreen to another.
2853 * Otherwise, the pScreen of the mouse sprite is never updated when we switch
2854 * from a pScreen to another. Never updating the pScreen of the mouse sprite
2855 * implies that windows that are in pScreen whose pScreen->myNum >0 will never
2856 * get pointer events. This is  because in CheckMotion(), sprite.hotPhys.pScreen
2857 * always points to the first pScreen it has been set by
2858 * DefineInitialRootWindow().
2859 *
2860 * Calling this function is useful for use cases where the server
2861 * has more than one pScreen.
2862 * This function is similar to DefineInitialRootWindow() but it does not
2863 * reset the mouse pointer position.
2864 * @param win must be the new pScreen we are switching to.
2865 */
2866void
2867UpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
2868{
2869    SpritePtr pSprite = NULL;
2870    WindowPtr win = NULL;
2871    if (!pScreen)
2872        return ;
2873
2874    if (!pDev->spriteInfo->sprite)
2875        return;
2876
2877    pSprite = pDev->spriteInfo->sprite;
2878
2879    win = WindowTable[pScreen->myNum];
2880
2881    pSprite->hotPhys.pScreen = pScreen;
2882    pSprite->hot = pSprite->hotPhys;
2883    pSprite->hotLimits.x2 = pScreen->width;
2884    pSprite->hotLimits.y2 = pScreen->height;
2885    pSprite->win = win;
2886    pSprite->current = wCursor (win);
2887    pSprite->current->refcnt++;
2888    pSprite->spriteTraceGood = 1;
2889    pSprite->spriteTrace[0] = win;
2890    (*pScreen->CursorLimits) (pDev,
2891                              pScreen,
2892                              pSprite->current,
2893                              &pSprite->hotLimits,
2894                              &pSprite->physLimits);
2895    pSprite->confined = FALSE;
2896    (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
2897    (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
2898
2899#ifdef PANORAMIX
2900    if(!noPanoramiXExtension) {
2901        pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x;
2902        pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y;
2903        pSprite->hotLimits.x2 = PanoramiXPixWidth  - panoramiXdataPtr[0].x;
2904        pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
2905        pSprite->physLimits = pSprite->hotLimits;
2906        pSprite->screen = pScreen;
2907    }
2908#endif
2909}
2910
2911/*
2912 * This does not take any shortcuts, and even ignores its argument, since
2913 * it does not happen very often, and one has to walk up the tree since
2914 * this might be a newly instantiated cursor for an intermediate window
2915 * between the one the pointer is in and the one that the last cursor was
2916 * instantiated from.
2917 */
2918void
2919WindowHasNewCursor(WindowPtr pWin)
2920{
2921    DeviceIntPtr pDev;
2922
2923    for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
2924        if (DevHasCursor(pDev))
2925            PostNewCursor(pDev);
2926}
2927
2928_X_EXPORT void
2929NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
2930{
2931    SpritePtr pSprite = pDev->spriteInfo->sprite;
2932
2933    pSprite->hotPhys.x = x;
2934    pSprite->hotPhys.y = y;
2935#ifdef PANORAMIX
2936    if(!noPanoramiXExtension) {
2937	pSprite->hotPhys.x += panoramiXdataPtr[newScreen->myNum].x -
2938			    panoramiXdataPtr[0].x;
2939	pSprite->hotPhys.y += panoramiXdataPtr[newScreen->myNum].y -
2940			    panoramiXdataPtr[0].y;
2941	if (newScreen != pSprite->screen) {
2942	    pSprite->screen = newScreen;
2943	    /* Make sure we tell the DDX to update its copy of the screen */
2944	    if(pSprite->confineWin)
2945		XineramaConfineCursorToWindow(pDev,
2946                        pSprite->confineWin, TRUE);
2947	    else
2948		XineramaConfineCursorToWindow(pDev, WindowTable[0], TRUE);
2949	    /* if the pointer wasn't confined, the DDX won't get
2950	       told of the pointer warp so we reposition it here */
2951	    if(!syncEvents.playingEvents)
2952		(*pSprite->screen->SetCursorPosition)(
2953                                                      pDev,
2954                                                      pSprite->screen,
2955		    pSprite->hotPhys.x + panoramiXdataPtr[0].x -
2956			panoramiXdataPtr[pSprite->screen->myNum].x,
2957		    pSprite->hotPhys.y + panoramiXdataPtr[0].y -
2958			panoramiXdataPtr[pSprite->screen->myNum].y, FALSE);
2959	}
2960    } else
2961#endif
2962    if (newScreen != pSprite->hotPhys.pScreen)
2963	ConfineCursorToWindow(pDev, WindowTable[newScreen->myNum],
2964                TRUE, FALSE);
2965}
2966
2967#ifdef PANORAMIX
2968
2969static Bool
2970XineramaPointInWindowIsVisible(
2971    WindowPtr pWin,
2972    int x,
2973    int y
2974)
2975{
2976    ScreenPtr pScreen = pWin->drawable.pScreen;
2977    BoxRec box;
2978    int i, xoff, yoff;
2979
2980    if (!pWin->realized) return FALSE;
2981
2982    if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box))
2983        return TRUE;
2984
2985    if(!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) return FALSE;
2986
2987    xoff = x + panoramiXdataPtr[0].x;
2988    yoff = y + panoramiXdataPtr[0].y;
2989
2990    for(i = 1; i < PanoramiXNumScreens; i++) {
2991	pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
2992	pScreen = pWin->drawable.pScreen;
2993	x = xoff - panoramiXdataPtr[i].x;
2994	y = yoff - panoramiXdataPtr[i].y;
2995
2996	if(POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)
2997	   && (!wInputShape(pWin) ||
2998	       POINT_IN_REGION(pWin->drawable.pScreen,
2999			       wInputShape(pWin),
3000			       x - pWin->drawable.x,
3001			       y - pWin->drawable.y, &box)))
3002            return TRUE;
3003
3004    }
3005
3006    return FALSE;
3007}
3008
3009static int
3010XineramaWarpPointer(ClientPtr client)
3011{
3012    WindowPtr	dest = NULL;
3013    int		x, y, rc;
3014    SpritePtr   pSprite = PickPointer(client)->spriteInfo->sprite;
3015
3016    REQUEST(xWarpPointerReq);
3017
3018
3019    if (stuff->dstWid != None) {
3020	rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
3021	if (rc != Success)
3022	    return rc;
3023    }
3024    x = pSprite->hotPhys.x;
3025    y = pSprite->hotPhys.y;
3026
3027    if (stuff->srcWid != None)
3028    {
3029	int     winX, winY;
3030	XID	winID = stuff->srcWid;
3031        WindowPtr source;
3032
3033	rc = dixLookupWindow(&source, winID, client, DixReadAccess);
3034	if (rc != Success)
3035	    return rc;
3036
3037	winX = source->drawable.x;
3038	winY = source->drawable.y;
3039	if(source == WindowTable[0]) {
3040	    winX -= panoramiXdataPtr[0].x;
3041	    winY -= panoramiXdataPtr[0].y;
3042	}
3043	if (x < winX + stuff->srcX ||
3044	    y < winY + stuff->srcY ||
3045	    (stuff->srcWidth != 0 &&
3046	     winX + stuff->srcX + (int)stuff->srcWidth < x) ||
3047	    (stuff->srcHeight != 0 &&
3048	     winY + stuff->srcY + (int)stuff->srcHeight < y) ||
3049	    !XineramaPointInWindowIsVisible(source, x, y))
3050	    return Success;
3051    }
3052    if (dest) {
3053	x = dest->drawable.x;
3054	y = dest->drawable.y;
3055	if(dest == WindowTable[0]) {
3056	    x -= panoramiXdataPtr[0].x;
3057	    y -= panoramiXdataPtr[0].y;
3058	}
3059    }
3060
3061    x += stuff->dstX;
3062    y += stuff->dstY;
3063
3064    if (x < pSprite->physLimits.x1)
3065	x = pSprite->physLimits.x1;
3066    else if (x >= pSprite->physLimits.x2)
3067	x = pSprite->physLimits.x2 - 1;
3068    if (y < pSprite->physLimits.y1)
3069	y = pSprite->physLimits.y1;
3070    else if (y >= pSprite->physLimits.y2)
3071	y = pSprite->physLimits.y2 - 1;
3072    if (pSprite->hotShape)
3073	ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
3074
3075    XineramaSetCursorPosition(PickPointer(client), x, y, TRUE);
3076
3077    return Success;
3078}
3079
3080#endif
3081
3082
3083/**
3084 * Server-side protocol handling for WarpPointer request.
3085 * Warps the cursor position to the coordinates given in the request.
3086 */
3087int
3088ProcWarpPointer(ClientPtr client)
3089{
3090    WindowPtr	dest = NULL;
3091    int		x, y, rc;
3092    ScreenPtr	newScreen;
3093    DeviceIntPtr dev;
3094    SpritePtr   pSprite;
3095
3096    REQUEST(xWarpPointerReq);
3097    REQUEST_SIZE_MATCH(xWarpPointerReq);
3098
3099    /* XXX XACE ??*/
3100    for (dev = inputInfo.devices; dev; dev = dev->next) {
3101        if ((dev->coreEvents || dev == inputInfo.pointer) && dev->button) {
3102	    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
3103	    if (rc != Success)
3104		return rc;
3105	}
3106    }
3107
3108    dev = PickPointer(client);
3109    if (dev->u.lastSlave)
3110        dev = dev->u.lastSlave;
3111    pSprite = dev->spriteInfo->sprite;
3112
3113#ifdef PANORAMIX
3114    if(!noPanoramiXExtension)
3115	return XineramaWarpPointer(client);
3116#endif
3117
3118    if (stuff->dstWid != None) {
3119	rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess);
3120	if (rc != Success)
3121	    return rc;
3122    }
3123    x = pSprite->hotPhys.x;
3124    y = pSprite->hotPhys.y;
3125
3126    if (stuff->srcWid != None)
3127    {
3128	int     winX, winY;
3129	XID	winID = stuff->srcWid;
3130        WindowPtr source;
3131
3132	rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess);
3133	if (rc != Success)
3134	    return rc;
3135
3136	winX = source->drawable.x;
3137	winY = source->drawable.y;
3138	if (source->drawable.pScreen != pSprite->hotPhys.pScreen ||
3139	    x < winX + stuff->srcX ||
3140	    y < winY + stuff->srcY ||
3141	    (stuff->srcWidth != 0 &&
3142	     winX + stuff->srcX + (int)stuff->srcWidth < x) ||
3143	    (stuff->srcHeight != 0 &&
3144	     winY + stuff->srcY + (int)stuff->srcHeight < y) ||
3145	    !PointInWindowIsVisible(source, x, y))
3146	    return Success;
3147    }
3148    if (dest)
3149    {
3150	x = dest->drawable.x;
3151	y = dest->drawable.y;
3152	newScreen = dest->drawable.pScreen;
3153    } else
3154	newScreen = pSprite->hotPhys.pScreen;
3155
3156    x += stuff->dstX;
3157    y += stuff->dstY;
3158
3159    if (x < 0)
3160	x = 0;
3161    else if (x >= newScreen->width)
3162	x = newScreen->width - 1;
3163    if (y < 0)
3164	y = 0;
3165    else if (y >= newScreen->height)
3166	y = newScreen->height - 1;
3167
3168    if (newScreen == pSprite->hotPhys.pScreen)
3169    {
3170	if (x < pSprite->physLimits.x1)
3171	    x = pSprite->physLimits.x1;
3172	else if (x >= pSprite->physLimits.x2)
3173	    x = pSprite->physLimits.x2 - 1;
3174	if (y < pSprite->physLimits.y1)
3175	    y = pSprite->physLimits.y1;
3176	else if (y >= pSprite->physLimits.y2)
3177	    y = pSprite->physLimits.y2 - 1;
3178	if (pSprite->hotShape)
3179	    ConfineToShape(dev, pSprite->hotShape, &x, &y);
3180        (*newScreen->SetCursorPosition)(dev, newScreen, x, y, TRUE);
3181    }
3182    else if (!PointerConfinedToScreen(dev))
3183    {
3184	NewCurrentScreen(dev, newScreen, x, y);
3185    }
3186    return Success;
3187}
3188
3189static Bool
3190BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
3191{
3192     if(REGION_NOTEMPTY(pDev->spriteInfo->sprite->hotPhys.pScreen, &pWin->borderSize))
3193	return TRUE;
3194
3195#ifdef PANORAMIX
3196     if(!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) {
3197	int i;
3198
3199	for(i = 1; i < PanoramiXNumScreens; i++) {
3200	    if(REGION_NOTEMPTY(pDev->spriteInfo->sprite->screen,
3201                        &pDev->spriteInfo->sprite->windows[i]->borderSize))
3202		return TRUE;
3203	}
3204     }
3205#endif
3206     return FALSE;
3207}
3208
3209/**
3210 * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
3211 * passive grab set on the window to be activated.
3212 * If a passive grab is activated, the event will be delivered to the client.
3213 *
3214 * @param pWin The window that may be subject to a passive grab.
3215 * @param device Device that caused the event.
3216 * @param xE List of events (multiple ones for DeviceMotionNotify)
3217 * @param count number of elements in xE.
3218 * @param store The event that will be stored on the device (always XI)
3219 * @param scount number of elements in store.
3220 */
3221
3222static Bool
3223CheckPassiveGrabsOnWindow(
3224    WindowPtr pWin,
3225    DeviceIntPtr device,
3226    xEvent *xE,
3227    int count,
3228    xEvent *store,
3229    int scount)
3230{
3231    GrabPtr grab = wPassiveGrabs(pWin);
3232    GrabRec tempGrab;
3233    GrabInfoPtr grabinfo;
3234    xEvent *dxE;
3235
3236    if (!grab)
3237	return FALSE;
3238    tempGrab.window = pWin;
3239    tempGrab.device = device;
3240    tempGrab.type = xE->u.u.type;
3241    tempGrab.detail.exact = xE->u.u.detail;
3242    tempGrab.detail.pMask = NULL;
3243    tempGrab.modifiersDetail.pMask = NULL;
3244    tempGrab.next = NULL;
3245    for (; grab; grab = grab->next)
3246    {
3247#ifdef XKB
3248	DeviceIntPtr	gdev;
3249	XkbSrvInfoPtr	xkbi = NULL;
3250
3251	gdev= grab->modifierDevice;
3252        if (grab->coreGrab)
3253        {
3254            if (IsPointerDevice(device))
3255                gdev = GetPairedDevice(device);
3256            else
3257                gdev = device;
3258        }
3259        if (gdev && gdev->key)
3260            xkbi= gdev->key->xkbInfo;
3261#endif
3262	tempGrab.modifierDevice = grab->modifierDevice;
3263	if ((device == grab->modifierDevice) &&
3264	    ((xE->u.u.type == KeyPress) || (xE->u.u.type == DeviceKeyPress)))
3265	    tempGrab.modifiersDetail.exact =
3266#ifdef XKB
3267                (noXkbExtension) ?
3268                        ((gdev) ? gdev->key->prev_state : 0) :
3269                        ((xkbi) ?  xkbi->state.grab_mods : 0);
3270#else
3271                (gdev) ? gdev->key->prev_state : 0;
3272#endif
3273	else
3274	    tempGrab.modifiersDetail.exact =
3275#ifdef XKB
3276                (noXkbExtension) ?
3277                        ((gdev) ? gdev->key->state : 0) :
3278                        ((xkbi) ? xkbi->state.grab_mods : 0);
3279#else
3280                (gdev) ? gdev->key->state : 0;
3281#endif
3282            /* ignore the device for core events when comparing grabs */
3283	if (GrabMatchesSecond(&tempGrab, grab, (xE->u.u.type < LASTEvent)) &&
3284	    (!grab->confineTo ||
3285	     (grab->confineTo->realized &&
3286				BorderSizeNotEmpty(device, grab->confineTo))))
3287	{
3288#ifdef XKB
3289	    if (!noXkbExtension) {
3290		XE_KBPTR.state &= 0x1f00;
3291		XE_KBPTR.state |=
3292				tempGrab.modifiersDetail.exact&(~0x1f00);
3293	    }
3294#endif
3295            grabinfo = &device->deviceGrab;
3296            /* A passive grab may have been created for a different device
3297               than it is assigned to at this point in time.
3298               Update the grab's device and modifier device to reflect the
3299               current state.
3300               Since XGrabDeviceButton requires to specify the
3301               modifierDevice explicitly, we don't override this choice.
3302             */
3303            if (xE->u.u.type < LASTEvent)
3304            {
3305                grab->device = device;
3306                grab->modifierDevice = GetPairedDevice(device);
3307            }
3308
3309            /* In some cases a passive core grab may exist, but the client
3310             * already has a core grab on some other device. In this case we
3311             * must not get the grab, otherwise we may never ungrab the
3312             * device.
3313             */
3314
3315            if (grab->coreGrab)
3316            {
3317                DeviceIntPtr other;
3318                BOOL interfering = FALSE;
3319                for (other = inputInfo.devices; other; other = other->next)
3320                {
3321                    GrabPtr othergrab = other->deviceGrab.grab;
3322                    if (othergrab && othergrab->coreGrab &&
3323                        SameClient(grab, rClient(othergrab)) &&
3324                        ((IsPointerDevice(grab->device) &&
3325                         IsPointerDevice(othergrab->device)) ||
3326                         (IsKeyboardDevice(grab->device) &&
3327                          IsKeyboardDevice(othergrab->device))))
3328                    {
3329                        interfering = TRUE;
3330                        break;
3331                    }
3332                }
3333                if (interfering)
3334                    continue;
3335            }
3336
3337
3338	    (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
3339
3340	    FixUpEventFromWindow(device, xE, grab->window, None, TRUE);
3341
3342	    (void) TryClientEvents(rClient(grab), device, xE, count,
3343				   filters[device->id][xE->u.u.type],
3344				   filters[device->id][xE->u.u.type],  grab);
3345
3346	    if (grabinfo->sync.state == FROZEN_NO_EVENT)
3347	    {
3348		if (grabinfo->sync.evcount < scount)
3349		{
3350		    grabinfo->sync.event = xrealloc(grabinfo->sync.event,
3351						    scount * sizeof(xEvent));
3352		}
3353		grabinfo->sync.evcount = scount;
3354                /* we always store the XI event, never the core event */
3355		for (dxE = grabinfo->sync.event; --scount >= 0; dxE++, store++)
3356		    *dxE = *store;
3357		grabinfo->sync.state = FROZEN_WITH_EVENT;
3358            }
3359	    return TRUE;
3360	}
3361    }
3362    return FALSE;
3363}
3364
3365/**
3366 * CheckDeviceGrabs handles both keyboard and pointer events that may cause
3367 * a passive grab to be activated.
3368 *
3369 * If the event is a keyboard event, the ancestors of the focus window are
3370 * traced down and tried to see if they have any passive grabs to be
3371 * activated.  If the focus window itself is reached and it's descendants
3372 * contain the pointer, the ancestors of the window that the pointer is in
3373 * are then traced down starting at the focus window, otherwise no grabs are
3374 * activated.
3375 * If the event is a pointer event, the ancestors of the window that the
3376 * pointer is in are traced down starting at the root until CheckPassiveGrabs
3377 * causes a passive grab to activate or all the windows are
3378 * tried. PRH
3379 *
3380 * If a grab is activated, the event has been sent to the client already!
3381 *
3382 * The event we pass in must always be an XI event. From this, we then emulate
3383 * the core event and then check for grabs.
3384 *
3385 * @param device The device that caused the event.
3386 * @param xE The event to handle (Device{Button|Key}Press).
3387 * @param count Number of events in list.
3388 * @return TRUE if a grab has been activated or false otherwise.
3389*/
3390
3391Bool
3392CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE,
3393                 int checkFirst, int count)
3394{
3395    int i;
3396    WindowPtr pWin = NULL;
3397    FocusClassPtr focus = IsPointerEvent(xE) ? NULL : device->focus;
3398    xEvent core;
3399    BOOL sendCore = (device->isMaster && device->coreEvents);
3400
3401    if ((xE->u.u.type == DeviceButtonPress)
3402            && (device->button->buttonsDown != 1))
3403	return FALSE;
3404
3405    if (xE->u.u.type < EXTENSION_EVENT_BASE)
3406    {
3407        ErrorF("[dix] Core event passed into CheckDeviceGrabs.\n");
3408        return FALSE;
3409    }
3410
3411
3412    if (sendCore)
3413    {
3414        core = *xE;
3415        core.u.u.type = XItoCoreType(xE->u.u.type);
3416        if(!core.u.u.type) /* probably a Proximity event, can't grab for those */
3417            return FALSE;
3418    }
3419
3420    i = checkFirst;
3421
3422    if (focus)
3423    {
3424	for (; i < focus->traceGood; i++)
3425	{
3426	    pWin = focus->trace[i];
3427            /* XI grabs have precendence */
3428	    if (pWin->optional &&
3429	       (CheckPassiveGrabsOnWindow(pWin, device, xE, count, xE, count)
3430                || (sendCore && CheckPassiveGrabsOnWindow(pWin, device, &core,
3431                        1, xE, count))))
3432		return TRUE;
3433	}
3434
3435	if ((focus->win == NoneWin) ||
3436	    (i >= device->spriteInfo->sprite->spriteTraceGood) ||
3437	    ((i > checkFirst) &&
3438             (pWin != device->spriteInfo->sprite->spriteTrace[i-1])))
3439	    return FALSE;
3440    }
3441
3442    for (; i < device->spriteInfo->sprite->spriteTraceGood; i++)
3443    {
3444	pWin = device->spriteInfo->sprite->spriteTrace[i];
3445	if (pWin->optional &&
3446	    (CheckPassiveGrabsOnWindow(pWin, device, xE, count, xE, count) ||
3447             (sendCore && CheckPassiveGrabsOnWindow(pWin, device, &core, 1,
3448                                                    xE, count))))
3449	    return TRUE;
3450    }
3451
3452    return FALSE;
3453}
3454
3455/**
3456 * Called for keyboard events to deliver event to whatever client owns the
3457 * focus. Event is delivered to the keyboard's focus window, the root window
3458 * or to the window owning the input focus.
3459 *
3460 * @param keybd The keyboard originating the event.
3461 * @param xE The event list.
3462 * @param window Window underneath the sprite.
3463 * @param count number of events in xE.
3464 */
3465void
3466DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
3467{
3468    DeviceIntPtr pointer;
3469    WindowPtr focus = keybd->focus->win;
3470    BOOL sendCore = (keybd->isMaster && keybd->coreEvents);
3471    xEvent core;
3472    int deliveries = 0;
3473
3474    if (focus == FollowKeyboardWin)
3475	focus = inputInfo.keyboard->focus->win;
3476    if (!focus)
3477	return;
3478    if (focus == PointerRootWin)
3479    {
3480	DeliverDeviceEvents(window, xE, NullGrab, NullWindow, keybd, count);
3481	return;
3482    }
3483    if ((focus == window) || IsParent(focus, window))
3484    {
3485	if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count))
3486	    return;
3487    }
3488    pointer = GetPairedDevice(keybd);
3489    if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count))
3490	return;
3491
3492    if (sendCore)
3493    {
3494        core = *xE;
3495        core.u.u.type = XItoCoreType(xE->u.u.type);
3496    }
3497
3498    /* just deliver it to the focus window */
3499    FixUpEventFromWindow(pointer, xE, focus, None, FALSE);
3500    deliveries = DeliverEventsToWindow(keybd, focus, xE, count,
3501                                       filters[keybd->id][xE->u.u.type],
3502                                       NullGrab, keybd->id);
3503
3504    if (deliveries > 0)
3505        return;
3506
3507    if (sendCore && core.u.u.type)
3508    {
3509        FixUpEventFromWindow(keybd, &core, focus, None, FALSE);
3510        deliveries = DeliverEventsToWindow(keybd, focus, &core, 1,
3511                                           filters[keybd->id][xE->u.u.type],
3512                                           NullGrab, 0);
3513    }
3514}
3515
3516/**
3517 * Deliver an event from a device that is currently grabbed. Uses
3518 * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the
3519 * grab. If not, TryClientEvents() is used.
3520 *
3521 * @param deactivateGrab True if the device's grab should be deactivated.
3522 */
3523void
3524DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
3525                    Bool deactivateGrab, int count)
3526{
3527    GrabPtr grab;
3528    GrabInfoPtr grabinfo;
3529    int deliveries = 0;
3530    DeviceIntPtr dev;
3531    xEvent *dxE, core;
3532    SpritePtr pSprite = thisDev->spriteInfo->sprite;
3533    BOOL sendCore = FALSE;
3534
3535    grabinfo = &thisDev->deviceGrab;
3536    grab = grabinfo->grab;
3537
3538    if (grab->ownerEvents)
3539    {
3540	WindowPtr focus;
3541
3542        /* Hack: Some pointer device have a focus class. So we need to check
3543         * for the type of event, to see if we really want to deliver it to
3544         * the focus window. For pointer events, the answer is no.
3545         */
3546        if (xE->u.u.type == DeviceButtonPress ||
3547                xE->u.u.type == DeviceButtonRelease ||
3548                xE->u.u.type == DeviceMotionNotify ||
3549                xE->u.u.type == ProximityIn ||
3550                xE->u.u.type == ProximityOut)
3551        {
3552            focus = PointerRootWin;
3553        } else if (thisDev->focus)
3554	{
3555	    focus = thisDev->focus->win;
3556	    if (focus == FollowKeyboardWin)
3557		focus = inputInfo.keyboard->focus->win;
3558	}
3559	else
3560	    focus = PointerRootWin;
3561	if (focus == PointerRootWin)
3562	    deliveries = DeliverDeviceEvents(pSprite->win, xE, grab,
3563                                             NullWindow, thisDev, count);
3564	else if (focus && (focus == pSprite->win ||
3565                    IsParent(focus, pSprite->win)))
3566	    deliveries = DeliverDeviceEvents(pSprite->win, xE, grab, focus,
3567					     thisDev, count);
3568	else if (focus)
3569	    deliveries = DeliverDeviceEvents(focus, xE, grab, focus,
3570					     thisDev, count);
3571    }
3572    if (!deliveries)
3573    {
3574        {
3575            Mask mask = grab->eventMask;
3576
3577            if (thisDev->isMaster)
3578            {
3579                core = *xE;
3580                core.u.u.type = XItoCoreType(xE->u.u.type);
3581                if(core.u.u.type) {
3582                    FixUpEventFromWindow(thisDev, &core, grab->window,
3583                            None, TRUE);
3584                    if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
3585                                grab->window, &core, 1) ||
3586                            XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
3587                                grab->window, &core, 1))
3588                        deliveries = 1; /* don't send, but pretend we did */
3589                    else if (!IsInterferingGrab(rClient(grab), thisDev,
3590                                &core))
3591                    {
3592                        deliveries = TryClientEvents(rClient(grab), thisDev,
3593                                &core, 1, mask,
3594                                filters[thisDev->id][core.u.u.type],
3595                                grab);
3596                    }
3597                }
3598            } else
3599            {
3600                /* try XI event */
3601                if (grabinfo->fromPassiveGrab  &&
3602                        grabinfo->implicitGrab &&
3603                        (xE->u.u.type & EXTENSION_EVENT_BASE))
3604                    mask = grab->deviceMask;
3605                FixUpEventFromWindow(thisDev, xE, grab->window,
3606                        None, TRUE);
3607
3608                if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
3609                            grab->window, xE, count) ||
3610                        XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
3611                            grab->window, xE, count))
3612                    deliveries = 1; /* don't send, but pretend we did */
3613                else
3614                {
3615                    deliveries =
3616                        TryClientEvents(rClient(grab), thisDev,
3617                                xE, count,
3618                                mask,
3619                                filters[thisDev->id][xE->u.u.type],
3620                                grab);
3621                }
3622
3623            }
3624        }
3625        if (deliveries && (xE->u.u.type == MotionNotify
3626                    || xE->u.u.type == DeviceMotionNotify))
3627            thisDev->valuator->motionHintWindow = grab->window;
3628    }
3629    if (deliveries && !deactivateGrab &&
3630       (xE->u.u.type != MotionNotify && xE->u.u.type != DeviceMotionNotify))
3631    {
3632	switch (grabinfo->sync.state)
3633	{
3634	case FREEZE_BOTH_NEXT_EVENT:
3635	    for (dev = inputInfo.devices; dev; dev = dev->next)
3636	    {
3637		if (dev == thisDev)
3638		    continue;
3639		FreezeThaw(dev, TRUE);
3640		if ((grabinfo->sync.state == FREEZE_BOTH_NEXT_EVENT) &&
3641		    (CLIENT_BITS(grab->resource) ==
3642		     CLIENT_BITS(grab->resource)))
3643		    grabinfo->sync.state = FROZEN_NO_EVENT;
3644		else
3645		    grabinfo->sync.other = grab;
3646	    }
3647	    /* fall through */
3648	case FREEZE_NEXT_EVENT:
3649	    grabinfo->sync.state = FROZEN_WITH_EVENT;
3650	    FreezeThaw(thisDev, TRUE);
3651	    if (grabinfo->sync.evcount < count)
3652	    {
3653		grabinfo->sync.event = xrealloc(grabinfo->sync.event,
3654						count * sizeof(xEvent));
3655	    }
3656	    grabinfo->sync.evcount = count;
3657	    for (dxE = grabinfo->sync.event; --count >= 0; dxE++, xE++)
3658		*dxE = *xE;
3659	    break;
3660	}
3661    }
3662}
3663
3664/**
3665 * Main keyboard event processing function for core keyboard events.
3666 * Updates the events fields from the current pointer state and delivers the
3667 * event.
3668 *
3669 * For key events, xE will always be a single event.
3670 *
3671 * @param xE Event list
3672 * @param keybd The device that caused an event.
3673 * @param count Number of elements in xE.
3674 */
3675void
3676#ifdef XKB
3677CoreProcessKeyboardEvent (xEvent *xE, DeviceIntPtr keybd, int count)
3678#else
3679ProcessKeyboardEvent (xEvent *xE, DeviceIntPtr keybd, int count)
3680#endif
3681{
3682    int             key, bit;
3683    BYTE            *kptr;
3684    CARD8           modifiers;
3685    GrabPtr         grab;
3686    GrabInfoPtr     grabinfo;
3687    Bool            deactivateGrab = FALSE;
3688    KeyClassPtr     keyc = keybd->key;
3689
3690    grabinfo = &keybd->deviceGrab;
3691    grab = grabinfo->grab;
3692
3693    if (!syncEvents.playingEvents)
3694    {
3695	NoticeTime(xE);
3696	if (DeviceEventCallback)
3697	{
3698	    DeviceEventInfoRec eventinfo;
3699	    eventinfo.events = xE;
3700	    eventinfo.count = count;
3701	    CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
3702	}
3703    }
3704    /* ProcessOtherEvent already updated the keyboard's state, so we need to
3705     * access prev_state here! */
3706    XE_KBPTR.state = (keyc->prev_state | GetPairedDevice(keybd)->button->state);
3707    XE_KBPTR.rootX = keybd->spriteInfo->sprite->hot.x;
3708    XE_KBPTR.rootY = keybd->spriteInfo->sprite->hot.y;
3709    key = xE->u.u.detail;
3710    kptr = &keyc->down[key >> 3];
3711    bit = 1 << (key & 7);
3712    modifiers = keyc->modifierMap[key];
3713
3714    switch (xE->u.u.type)
3715    {
3716	case KeyPress:
3717            /* We MUST NOT change the device itself here.  All device state
3718             * changes must be performed in ProcessOtherEvents. We're dealing
3719             * with the same device struct, so if we change it in POE and
3720             * here, we've just screwed up the state by setting it twice.
3721             *
3722             * Devices may not send core events but always send XI events, so
3723             * the state must be changed in POE, not here.
3724             */
3725	    if (!grab && CheckDeviceGrabs(keybd, xE, 0, count))
3726	    {
3727		grabinfo->activatingKey = key;
3728		return;
3729	    }
3730	    break;
3731	case KeyRelease:
3732	    if (!(*kptr & bit)) /* guard against duplicates */
3733		return;
3734            /* No device state changes, see comment for KeyPress */
3735	    if (grabinfo->fromPassiveGrab && (key == grabinfo->activatingKey))
3736		deactivateGrab = TRUE;
3737	    break;
3738	default:
3739	    FatalError("Impossible keyboard event");
3740    }
3741    if (grab)
3742	DeliverGrabbedEvent(xE, keybd, deactivateGrab, count);
3743    else
3744	DeliverFocusedEvent(keybd, xE, keybd->spriteInfo->sprite->win, count);
3745    if (deactivateGrab)
3746        (*grabinfo->DeactivateGrab)(keybd);
3747
3748    XaceHook(XACE_KEY_AVAIL, xE, keybd, count);
3749}
3750
3751#ifdef XKB
3752/* This function is used to set the key pressed or key released state -
3753   this is only used when the pressing of keys does not cause
3754   the device's processInputProc to be called, as in for example Mouse Keys.
3755*/
3756void
3757FixKeyState (xEvent *xE, DeviceIntPtr keybd)
3758{
3759    int             key, bit;
3760    BYTE   *kptr;
3761    KeyClassPtr keyc = keybd->key;
3762
3763    key = xE->u.u.detail;
3764    kptr = &keyc->down[key >> 3];
3765    bit = 1 << (key & 7);
3766
3767    if (((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease)||
3768         (xE->u.u.type==DeviceKeyPress)||(xE->u.u.type==DeviceKeyRelease))
3769            ) {
3770	DebugF("FixKeyState: Key %d %s\n",key,
3771               (((xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress))?"down":"up"));
3772    }
3773
3774    if (xE->u.u.type == KeyPress || xE->u.u.type == DeviceKeyPress)
3775	    *kptr |= bit;
3776    else if (xE->u.u.type == KeyRelease || xE->u.u.type == DeviceKeyRelease)
3777	    *kptr &= ~bit;
3778    else
3779        FatalError("Impossible keyboard event");
3780}
3781#endif
3782
3783/**
3784 * Main pointer event processing function for core pointer events.
3785 * For motion events: update the sprite.
3786 * For all other events: Update the event fields based on the current sprite
3787 * state.
3788 *
3789 * For core pointer events, xE will always be a single event.
3790 *
3791 * @param xE Event list
3792 * @param mouse The device that caused an event.
3793 * @param count Number of elements in xE.
3794 */
3795void
3796#ifdef XKB
3797CoreProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
3798#else
3799ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count)
3800#endif
3801{
3802    GrabPtr	        grab = mouse->deviceGrab.grab;
3803    Bool                deactivateGrab = FALSE;
3804    ButtonClassPtr      butc = mouse->button;
3805    SpritePtr           pSprite = mouse->spriteInfo->sprite;
3806
3807#ifdef XKB
3808    XkbSrvInfoPtr xkbi= GetPairedDevice(mouse)->key->xkbInfo;
3809#endif
3810
3811    if (!syncEvents.playingEvents)
3812	NoticeTime(xE)
3813    XE_KBPTR.state = (butc->state | (
3814#ifdef XKB
3815			(noXkbExtension ?
3816				inputInfo.keyboard->key->state :
3817				xkbi->state.grab_mods)
3818#else
3819			inputInfo.keyboard->key->state
3820#endif
3821				    ));
3822    {
3823	NoticeTime(xE);
3824	if (DeviceEventCallback)
3825	{
3826	    DeviceEventInfoRec eventinfo;
3827	    /* see comment in EnqueueEvents regarding the next three lines */
3828	    if (xE->u.u.type == MotionNotify)
3829		XE_KBPTR.root =
3830		    WindowTable[pSprite->hotPhys.pScreen->myNum]->drawable.id;
3831	    eventinfo.events = xE;
3832	    eventinfo.count = count;
3833	    CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
3834	}
3835    }
3836    /* We need to call CheckMotion for each event. It doesn't really give us
3837       any benefit for relative devices, but absolute devices may not send
3838       button events to the right position otherwise. */
3839    if (!CheckMotion(xE, mouse) && xE->u.u.type == MotionNotify)
3840            return;
3841    if (xE->u.u.type != MotionNotify)
3842    {
3843	int  key;
3844
3845	XE_KBPTR.rootX = pSprite->hot.x;
3846	XE_KBPTR.rootY = pSprite->hot.y;
3847
3848	key = xE->u.u.detail;
3849	switch (xE->u.u.type)
3850	{
3851	case ButtonPress:
3852            /*
3853             * We rely on the fact that ButtonMotionMask is the same as
3854             * DeviceButtonMotionMask, so setting the motionMask
3855             * to this value ensures correctness for both XI and core events.
3856             */
3857	    if (xE->u.u.detail == 0)
3858		return;
3859            filters[mouse->id][Motion_Filter(butc)] = MotionNotify;
3860	    if (!grab)
3861		if (CheckDeviceGrabs(mouse, xE, 0, count))
3862		    return;
3863	    break;
3864	case ButtonRelease:
3865	    if (xE->u.u.detail == 0)
3866		return;
3867            filters[mouse->id][Motion_Filter(butc)] = MotionNotify;
3868	    if (!butc->buttonsDown && mouse->deviceGrab.fromPassiveGrab)
3869		deactivateGrab = TRUE;
3870	    break;
3871	default:
3872	    FatalError("bogus pointer event from ddx. Type %d\n", xE->u.u.type);
3873	}
3874    }
3875
3876    if (grab)
3877	DeliverGrabbedEvent(xE, mouse, deactivateGrab, count);
3878    else
3879	DeliverDeviceEvents(pSprite->win, xE, NullGrab, NullWindow,
3880			    mouse, count);
3881    if (deactivateGrab)
3882        (*mouse->deviceGrab.DeactivateGrab)(mouse);
3883}
3884
3885#define AtMostOneClient \
3886	(SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
3887#define ManagerMask \
3888	(SubstructureRedirectMask | ResizeRedirectMask)
3889
3890/**
3891 * Recalculate which events may be deliverable for the given window.
3892 * Recalculated mask is used for quicker determination which events may be
3893 * delivered to a window.
3894 *
3895 * The otherEventMasks on a WindowOptional is the combination of all event
3896 * masks set by all clients on the window.
3897 * deliverableEventMask is the combination of the eventMask and the
3898 * otherEventMask.
3899 *
3900 * Traverses to siblings and parents of the window.
3901 */
3902void
3903RecalculateDeliverableEvents(pWin)
3904    WindowPtr pWin;
3905{
3906    OtherClients *others;
3907    WindowPtr pChild;
3908
3909    pChild = pWin;
3910    while (1)
3911    {
3912	if (pChild->optional)
3913	{
3914	    pChild->optional->otherEventMasks = 0;
3915	    for (others = wOtherClients(pChild); others; others = others->next)
3916	    {
3917		pChild->optional->otherEventMasks |= others->mask;
3918	    }
3919	}
3920	pChild->deliverableEvents = pChild->eventMask|
3921				    wOtherEventMasks(pChild);
3922	if (pChild->parent)
3923	    pChild->deliverableEvents |=
3924		(pChild->parent->deliverableEvents &
3925		 ~wDontPropagateMask(pChild) & PropagateMask);
3926	if (pChild->firstChild)
3927	{
3928	    pChild = pChild->firstChild;
3929	    continue;
3930	}
3931	while (!pChild->nextSib && (pChild != pWin))
3932	    pChild = pChild->parent;
3933	if (pChild == pWin)
3934	    break;
3935	pChild = pChild->nextSib;
3936    }
3937}
3938
3939/**
3940 *
3941 *  \param value must conform to DeleteType
3942 */
3943int
3944OtherClientGone(pointer value, XID id)
3945{
3946    OtherClientsPtr other, prev;
3947    WindowPtr pWin = (WindowPtr)value;
3948
3949    prev = 0;
3950    for (other = wOtherClients(pWin); other; other = other->next)
3951    {
3952	if (other->resource == id)
3953	{
3954	    if (prev)
3955		prev->next = other->next;
3956	    else
3957	    {
3958		if (!(pWin->optional->otherClients = other->next))
3959		    CheckWindowOptionalNeed (pWin);
3960	    }
3961	    xfree(other);
3962	    RecalculateDeliverableEvents(pWin);
3963	    return(Success);
3964	}
3965	prev = other;
3966    }
3967    FatalError("client not on event list");
3968    /*NOTREACHED*/
3969    return -1; /* make compiler happy */
3970}
3971
3972int
3973EventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
3974{
3975    Mask check;
3976    OtherClients * others;
3977    DeviceIntPtr dev;
3978    int rc;
3979
3980    if (mask & ~AllEventMasks)
3981    {
3982	client->errorValue = mask;
3983	return BadValue;
3984    }
3985    check = (mask & ManagerMask);
3986    if (check) {
3987	rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id,
3988		      RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess);
3989	if (rc != Success)
3990	    return rc;
3991    }
3992    check = (mask & AtMostOneClient);
3993    if (check & (pWin->eventMask|wOtherEventMasks(pWin)))
3994    {				       /* It is illegal for two different
3995				          clients to select on any of the
3996				          events for AtMostOneClient. However,
3997				          it is OK, for some client to
3998				          continue selecting on one of those
3999				          events.  */
4000	if ((wClient(pWin) != client) && (check & pWin->eventMask))
4001	    return BadAccess;
4002	for (others = wOtherClients (pWin); others; others = others->next)
4003	{
4004	    if (!SameClient(others, client) && (check & others->mask))
4005		return BadAccess;
4006	}
4007    }
4008    if (wClient (pWin) == client)
4009    {
4010	check = pWin->eventMask;
4011	pWin->eventMask = mask;
4012    }
4013    else
4014    {
4015	for (others = wOtherClients (pWin); others; others = others->next)
4016	{
4017	    if (SameClient(others, client))
4018	    {
4019		check = others->mask;
4020		if (mask == 0)
4021		{
4022		    FreeResource(others->resource, RT_NONE);
4023		    return Success;
4024		}
4025		else
4026		    others->mask = mask;
4027		goto maskSet;
4028	    }
4029	}
4030	check = 0;
4031	if (!pWin->optional && !MakeWindowOptional (pWin))
4032	    return BadAlloc;
4033	others = (OtherClients *) xalloc(sizeof(OtherClients));
4034	if (!others)
4035	    return BadAlloc;
4036	others->mask = mask;
4037	others->resource = FakeClientID(client->index);
4038	others->next = pWin->optional->otherClients;
4039	pWin->optional->otherClients = others;
4040	if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin))
4041	    return BadAlloc;
4042    }
4043maskSet:
4044    if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask))
4045    {
4046        for (dev = inputInfo.devices; dev; dev = dev->next)
4047        {
4048            if (dev->valuator && dev->valuator->motionHintWindow == pWin)
4049                dev->valuator->motionHintWindow = NullWindow;
4050        }
4051    }
4052    RecalculateDeliverableEvents(pWin);
4053    return Success;
4054}
4055
4056int
4057EventSuppressForWindow(WindowPtr pWin, ClientPtr client,
4058                       Mask mask, Bool *checkOptional)
4059{
4060    int i, free;
4061
4062    if (mask & ~PropagateMask)
4063    {
4064	client->errorValue = mask;
4065	return BadValue;
4066    }
4067    if (pWin->dontPropagate)
4068	DontPropagateRefCnts[pWin->dontPropagate]--;
4069    if (!mask)
4070	i = 0;
4071    else
4072    {
4073	for (i = DNPMCOUNT, free = 0; --i > 0; )
4074	{
4075	    if (!DontPropagateRefCnts[i])
4076		free = i;
4077	    else if (mask == DontPropagateMasks[i])
4078		break;
4079	}
4080	if (!i && free)
4081	{
4082	    i = free;
4083	    DontPropagateMasks[i] = mask;
4084	}
4085    }
4086    if (i || !mask)
4087    {
4088	pWin->dontPropagate = i;
4089	if (i)
4090	    DontPropagateRefCnts[i]++;
4091	if (pWin->optional)
4092	{
4093	    pWin->optional->dontPropagateMask = mask;
4094	    *checkOptional = TRUE;
4095	}
4096    }
4097    else
4098    {
4099	if (!pWin->optional && !MakeWindowOptional (pWin))
4100	{
4101	    if (pWin->dontPropagate)
4102		DontPropagateRefCnts[pWin->dontPropagate]++;
4103	    return BadAlloc;
4104	}
4105	pWin->dontPropagate = 0;
4106        pWin->optional->dontPropagateMask = mask;
4107    }
4108    RecalculateDeliverableEvents(pWin);
4109    return Success;
4110}
4111
4112/**
4113 * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
4114 * Uses the paired keyboard to get some additional information.
4115 */
4116void
4117CoreEnterLeaveEvent(
4118    DeviceIntPtr mouse,
4119    int type,
4120    int mode,
4121    int detail,
4122    WindowPtr pWin,
4123    Window child)
4124{
4125    xEvent              event;
4126    WindowPtr		focus;
4127    DeviceIntPtr        keybd;
4128    GrabPtr	        grab = mouse->deviceGrab.grab;
4129    Mask		mask;
4130
4131    keybd = GetPairedDevice(mouse);
4132
4133    if ((pWin == mouse->valuator->motionHintWindow) &&
4134	(detail != NotifyInferior))
4135	mouse->valuator->motionHintWindow = NullWindow;
4136    if (grab)
4137    {
4138	mask = (pWin == grab->window) ? grab->eventMask : 0;
4139	if (grab->ownerEvents)
4140	    mask |= EventMaskForClient(pWin, rClient(grab));
4141    }
4142    else
4143    {
4144	mask = pWin->eventMask | wOtherEventMasks(pWin);
4145    }
4146
4147    event.u.u.type = type;
4148    event.u.u.detail = detail;
4149    event.u.enterLeave.time = currentTime.milliseconds;
4150    event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x;
4151    event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y;
4152    /* Counts on the same initial structure of crossing & button events! */
4153    FixUpEventFromWindow(mouse, &event, pWin, None, FALSE);
4154    /* Enter/Leave events always set child */
4155    event.u.enterLeave.child = child;
4156    event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
4157        ELFlagSameScreen : 0;
4158#ifdef XKB
4159    if (!noXkbExtension) {
4160        event.u.enterLeave.state = mouse->button->state & 0x1f00;
4161        if (keybd)
4162            event.u.enterLeave.state |=
4163                XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
4164    } else
4165#endif
4166    {
4167        event.u.enterLeave.state = (keybd) ? keybd->key->state : 0;
4168        event.u.enterLeave.state |= mouse->button->state;
4169    }
4170    event.u.enterLeave.mode = mode;
4171    focus = (keybd) ? keybd->focus->win : None;
4172    if ((focus != NoneWin) &&
4173            ((pWin == focus) || (focus == PointerRootWin) ||
4174             IsParent(focus, pWin)))
4175        event.u.enterLeave.flags |= ELFlagFocus;
4176
4177    if ((mask & filters[mouse->id][type]))
4178    {
4179        if (grab)
4180            TryClientEvents(rClient(grab), mouse, &event, 1, mask,
4181                                  filters[mouse->id][type], grab);
4182        else
4183            DeliverEventsToWindow(mouse, pWin, &event, 1,
4184                                  filters[mouse->id][type], NullGrab, 0);
4185    }
4186
4187    if ((type == EnterNotify) && (mask & KeymapStateMask))
4188    {
4189        xKeymapEvent ke;
4190        ClientPtr client = grab ? rClient(grab)
4191            : clients[CLIENT_ID(pWin->drawable.id)];
4192        if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess))
4193            bzero((char *)&ke.map[0], 31);
4194        else
4195            memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31);
4196
4197        ke.type = KeymapNotify;
4198        if (grab)
4199            TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1,
4200                            mask, KeymapStateMask, grab);
4201        else
4202            DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1,
4203                                  KeymapStateMask, NullGrab, 0);
4204    }
4205}
4206
4207void
4208CoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
4209{
4210    xEvent event;
4211
4212    event.u.focus.mode = mode;
4213    event.u.u.type = type;
4214    event.u.u.detail = detail;
4215    event.u.focus.window = pWin->drawable.id;
4216    (void)DeliverEventsToWindow(dev, pWin, &event, 1,
4217            filters[dev->id][type], NullGrab, 0);
4218    if ((type == FocusIn) &&
4219            ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
4220    {
4221        xKeymapEvent ke;
4222        ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)];
4223        if (XaceHook(XACE_DEVICE_ACCESS, client, dev, FALSE))
4224            memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
4225        else
4226            bzero((char *)&ke.map[0], 31);
4227
4228        ke.type = KeymapNotify;
4229        (void)DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1,
4230                KeymapStateMask, NullGrab, 0);
4231    }
4232}
4233
4234/**
4235 * Set the input focus to the given window. Subsequent keyboard events will be
4236 * delivered to the given window.
4237 *
4238 * Usually called from ProcSetInputFocus as result of a client request. If so,
4239 * the device is the inputInfo.keyboard.
4240 * If called from ProcXSetInputFocus as result of a client xinput request, the
4241 * device is set to the device specified by the client.
4242 *
4243 * @param client Client that requested input focus change.
4244 * @param dev Focus device.
4245 * @param focusID The window to obtain the focus. Can be PointerRoot or None.
4246 * @param revertTo Specifies where the focus reverts to when window becomes
4247 * unviewable.
4248 * @param ctime Specifies the time.
4249 * @param followOK True if pointer is allowed to follow the keyboard.
4250 */
4251int
4252SetInputFocus(
4253    ClientPtr client,
4254    DeviceIntPtr dev,
4255    Window focusID,
4256    CARD8 revertTo,
4257    Time ctime,
4258    Bool followOK)
4259{
4260    FocusClassPtr focus;
4261    WindowPtr focusWin;
4262    int mode, rc;
4263    TimeStamp time;
4264    DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */
4265
4266
4267    UpdateCurrentTime();
4268    if ((revertTo != RevertToParent) &&
4269	(revertTo != RevertToPointerRoot) &&
4270	(revertTo != RevertToNone) &&
4271	((revertTo != RevertToFollowKeyboard) || !followOK))
4272    {
4273	client->errorValue = revertTo;
4274	return BadValue;
4275    }
4276    time = ClientTimeToServerTime(ctime);
4277
4278    if (IsKeyboardDevice(dev))
4279        keybd = dev;
4280    else
4281        keybd = GetPairedDevice(dev);
4282
4283    if ((focusID == None) || (focusID == PointerRoot))
4284	focusWin = (WindowPtr)(long)focusID;
4285    else if ((focusID == FollowKeyboard) && followOK)
4286    {
4287	focusWin = keybd->focus->win;
4288    }
4289    else {
4290	rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess);
4291	if (rc != Success)
4292	    return rc;
4293	/* It is a match error to try to set the input focus to an
4294	unviewable window. */
4295	if(!focusWin->realized)
4296	    return(BadMatch);
4297    }
4298    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess);
4299    if (rc != Success)
4300	return Success;
4301
4302    focus = dev->focus;
4303    if ((CompareTimeStamps(time, currentTime) == LATER) ||
4304	(CompareTimeStamps(time, focus->time) == EARLIER))
4305	return Success;
4306    mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal;
4307    if (focus->win == FollowKeyboardWin)
4308	DoFocusEvents(dev, keybd->focus->win, focusWin, mode);
4309    else
4310	DoFocusEvents(dev, focus->win, focusWin, mode);
4311    focus->time = time;
4312    focus->revert = revertTo;
4313    if (focusID == FollowKeyboard)
4314	focus->win = FollowKeyboardWin;
4315    else
4316	focus->win = focusWin;
4317    if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
4318	focus->traceGood = 0;
4319    else
4320    {
4321        int depth = 0;
4322	WindowPtr pWin;
4323
4324        for (pWin = focusWin; pWin; pWin = pWin->parent) depth++;
4325        if (depth > focus->traceSize)
4326        {
4327	    focus->traceSize = depth+1;
4328	    focus->trace = xrealloc(focus->trace,
4329				    focus->traceSize * sizeof(WindowPtr));
4330	}
4331	focus->traceGood = depth;
4332        for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
4333	    focus->trace[depth] = pWin;
4334    }
4335    return Success;
4336}
4337
4338/**
4339 * Server-side protocol handling for SetInputFocus request.
4340 *
4341 * Sets the input focus for the virtual core keyboard.
4342 */
4343int
4344ProcSetInputFocus(client)
4345    ClientPtr client;
4346{
4347    DeviceIntPtr kbd = PickKeyboard(client);
4348    REQUEST(xSetInputFocusReq);
4349
4350    REQUEST_SIZE_MATCH(xSetInputFocusReq);
4351
4352    return SetInputFocus(client, kbd, stuff->focus,
4353			 stuff->revertTo, stuff->time, FALSE);
4354}
4355
4356/**
4357 * Server-side protocol handling for GetInputFocus request.
4358 *
4359 * Sends the current input focus for the client's keyboard back to the
4360 * client.
4361 */
4362int
4363ProcGetInputFocus(ClientPtr client)
4364{
4365    DeviceIntPtr kbd = PickKeyboard(client);
4366    xGetInputFocusReply rep;
4367    FocusClassPtr focus = kbd->focus;
4368    int rc;
4369    /* REQUEST(xReq); */
4370    REQUEST_SIZE_MATCH(xReq);
4371
4372    rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess);
4373    if (rc != Success)
4374	return rc;
4375
4376    rep.type = X_Reply;
4377    rep.length = 0;
4378    rep.sequenceNumber = client->sequence;
4379    if (focus->win == NoneWin)
4380	rep.focus = None;
4381    else if (focus->win == PointerRootWin)
4382	rep.focus = PointerRoot;
4383    else rep.focus = focus->win->drawable.id;
4384    rep.revertTo = focus->revert;
4385    WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
4386    return Success;
4387}
4388
4389/**
4390 * Server-side protocol handling for GrabPointer request.
4391 *
4392 * Sets an active grab on the client's ClientPointer and returns success
4393 * status to client.
4394 */
4395int
4396ProcGrabPointer(ClientPtr client)
4397{
4398    xGrabPointerReply rep;
4399    DeviceIntPtr device = PickPointer(client);
4400    GrabPtr grab;
4401    WindowPtr pWin, confineTo;
4402    CursorPtr cursor, oldCursor;
4403    REQUEST(xGrabPointerReq);
4404    TimeStamp time;
4405    Mask access_mode = DixGrabAccess;
4406    int rc;
4407
4408    REQUEST_SIZE_MATCH(xGrabPointerReq);
4409    UpdateCurrentTime();
4410    if ((stuff->pointerMode != GrabModeSync) &&
4411	(stuff->pointerMode != GrabModeAsync))
4412    {
4413	client->errorValue = stuff->pointerMode;
4414        return BadValue;
4415    }
4416    if ((stuff->keyboardMode != GrabModeSync) &&
4417	(stuff->keyboardMode != GrabModeAsync))
4418    {
4419	client->errorValue = stuff->keyboardMode;
4420        return BadValue;
4421    }
4422    if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
4423    {
4424	client->errorValue = stuff->ownerEvents;
4425        return BadValue;
4426    }
4427    if (stuff->eventMask & ~PointerGrabMask)
4428    {
4429	client->errorValue = stuff->eventMask;
4430        return BadValue;
4431    }
4432    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
4433    if (rc != Success)
4434	return rc;
4435    if (stuff->confineTo == None)
4436	confineTo = NullWindow;
4437    else
4438    {
4439	rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
4440			     DixSetAttrAccess);
4441	if (rc != Success)
4442	    return rc;
4443    }
4444    if (stuff->cursor == None)
4445	cursor = NullCursor;
4446    else
4447    {
4448	rc = dixLookupResource((pointer *)&cursor, stuff->cursor, RT_CURSOR,
4449			       client, DixUseAccess);
4450	if (rc != Success)
4451	{
4452	    client->errorValue = stuff->cursor;
4453	    return (rc == BadValue) ? BadCursor : rc;
4454	}
4455	access_mode |= DixForceAccess;
4456    }
4457    if (stuff->pointerMode == GrabModeSync ||
4458	stuff->keyboardMode == GrabModeSync)
4459	access_mode |= DixFreezeAccess;
4460    rc = XaceHook(XACE_DEVICE_ACCESS, client, device, access_mode);
4461    if (rc != Success)
4462	return rc;
4463
4464	/* at this point, some sort of reply is guaranteed. */
4465    time = ClientTimeToServerTime(stuff->time);
4466    rep.type = X_Reply;
4467    rep.sequenceNumber = client->sequence;
4468    rep.length = 0;
4469
4470    grab = device->deviceGrab.grab;
4471    /* check for
4472       1. other client has a grab on the device already.
4473       2. window is viewable
4474       3. other client has this device as frozen "other" device
4475       4. times are screwed.
4476     */
4477    if ((grab) && !SameClient(grab, client))
4478	rep.status = AlreadyGrabbed;
4479    else if ((!pWin->realized) ||
4480             (confineTo &&
4481                !(confineTo->realized
4482                    && BorderSizeNotEmpty(device, confineTo))))
4483	rep.status = GrabNotViewable;
4484    else if (device->deviceGrab.sync.frozen &&
4485	     device->deviceGrab.sync.other &&
4486             !SameClient(device->deviceGrab.sync.other, client))
4487	rep.status = GrabFrozen;
4488    else if ((CompareTimeStamps(time, currentTime) == LATER) ||
4489	     (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
4490	rep.status = GrabInvalidTime;
4491    else
4492    {
4493	GrabRec tempGrab;
4494
4495	oldCursor = NullCursor;
4496	if (grab)
4497	{
4498	    if (grab->confineTo && !confineTo)
4499		ConfineCursorToWindow(device, RootWindow(device), FALSE, FALSE);
4500	    oldCursor = grab->cursor;
4501	}
4502        tempGrab.next = NULL;
4503	tempGrab.cursor = cursor;
4504	tempGrab.resource = client->clientAsMask;
4505	tempGrab.ownerEvents = stuff->ownerEvents;
4506	tempGrab.eventMask = stuff->eventMask;
4507	tempGrab.confineTo = confineTo;
4508	tempGrab.window = pWin;
4509	tempGrab.keyboardMode = stuff->keyboardMode;
4510	tempGrab.pointerMode = stuff->pointerMode;
4511	tempGrab.device = device;
4512        tempGrab.coreGrab = True;
4513        tempGrab.genericMasks = NULL;
4514	(*device->deviceGrab.ActivateGrab)(device, &tempGrab, time, FALSE);
4515	if (oldCursor)
4516	    FreeCursor (oldCursor, (Cursor)0);
4517	rep.status = GrabSuccess;
4518    }
4519    WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
4520    return Success;
4521}
4522
4523/**
4524 * Server-side protocol handling for ChangeActivePointerGrab request.
4525 *
4526 * Changes properties of the grab hold by the client. If the client does not
4527 * hold an active grab on the device, nothing happens.
4528 */
4529int
4530ProcChangeActivePointerGrab(ClientPtr client)
4531{
4532    DeviceIntPtr device;
4533    GrabPtr      grab;
4534    CursorPtr newCursor, oldCursor;
4535    REQUEST(xChangeActivePointerGrabReq);
4536    TimeStamp time;
4537
4538    REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
4539    if (stuff->eventMask & ~PointerGrabMask)
4540    {
4541	client->errorValue = stuff->eventMask;
4542        return BadValue;
4543    }
4544    if (stuff->cursor == None)
4545	newCursor = NullCursor;
4546    else
4547    {
4548	int rc = dixLookupResource((pointer *)&newCursor, stuff->cursor,
4549				   RT_CURSOR, client, DixUseAccess);
4550	if (rc != Success)
4551	{
4552	    client->errorValue = stuff->cursor;
4553	    return (rc == BadValue) ? BadCursor : rc;
4554	}
4555    }
4556
4557    device = PickPointer(client);
4558    grab = device->deviceGrab.grab;
4559
4560    if (!grab)
4561	return Success;
4562    if (!SameClient(grab, client))
4563	return Success;
4564    time = ClientTimeToServerTime(stuff->time);
4565    if ((CompareTimeStamps(time, currentTime) == LATER) ||
4566	     (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
4567	return Success;
4568    oldCursor = grab->cursor;
4569    grab->cursor = newCursor;
4570    if (newCursor)
4571	newCursor->refcnt++;
4572    PostNewCursor(device);
4573    if (oldCursor)
4574	FreeCursor(oldCursor, (Cursor)0);
4575    grab->eventMask = stuff->eventMask;
4576    return Success;
4577}
4578
4579/**
4580 * Server-side protocol handling for UngrabPointer request.
4581 *
4582 * Deletes a pointer grab on a device the client has grabbed.
4583 */
4584int
4585ProcUngrabPointer(ClientPtr client)
4586{
4587    DeviceIntPtr device = PickPointer(client);
4588    GrabPtr grab;
4589    TimeStamp time;
4590    REQUEST(xResourceReq);
4591
4592    REQUEST_SIZE_MATCH(xResourceReq);
4593    UpdateCurrentTime();
4594    grab = device->deviceGrab.grab;
4595
4596    time = ClientTimeToServerTime(stuff->id);
4597    if ((CompareTimeStamps(time, currentTime) != LATER) &&
4598	    (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
4599	    (grab) && SameClient(grab, client))
4600	(*device->deviceGrab.DeactivateGrab)(device);
4601    return Success;
4602}
4603
4604/**
4605 * Sets a grab on the given device.
4606 *
4607 * Called from ProcGrabKeyboard to work on the client's keyboard.
4608 * Called from ProcXGrabDevice to work on the device specified by the client.
4609 *
4610 * The parameters this_mode and other_mode represent the keyboard_mode and
4611 * pointer_mode parameters of XGrabKeyboard().
4612 * See man page for details on all the parameters
4613 *
4614 * @param client Client that owns the grab.
4615 * @param dev The device to grab.
4616 * @param this_mode GrabModeSync or GrabModeAsync
4617 * @param other_mode GrabModeSync or GrabModeAsync
4618 * @param status Return code to be returned to the caller.
4619 *
4620 * @returns Success or BadValue.
4621 */
4622int
4623GrabDevice(ClientPtr client, DeviceIntPtr dev,
4624           unsigned this_mode, unsigned other_mode, Window grabWindow,
4625           unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status,
4626           Bool coreGrab)
4627{
4628    WindowPtr pWin;
4629    GrabPtr grab;
4630    TimeStamp time;
4631    Mask access_mode = DixGrabAccess;
4632    int rc;
4633    GrabInfoPtr grabInfo = &dev->deviceGrab;
4634
4635    UpdateCurrentTime();
4636    if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync))
4637    {
4638	client->errorValue = this_mode;
4639        return BadValue;
4640    }
4641    if ((other_mode != GrabModeSync) && (other_mode != GrabModeAsync))
4642    {
4643	client->errorValue = other_mode;
4644        return BadValue;
4645    }
4646    if ((ownerEvents != xFalse) && (ownerEvents != xTrue))
4647    {
4648	client->errorValue = ownerEvents;
4649        return BadValue;
4650    }
4651
4652    rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
4653    if (rc != Success)
4654	return rc;
4655    if (this_mode == GrabModeSync || other_mode == GrabModeSync)
4656	access_mode |= DixFreezeAccess;
4657    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
4658    if (rc != Success)
4659	return rc;
4660
4661    time = ClientTimeToServerTime(ctime);
4662    grab = grabInfo->grab;
4663    if (grab && !SameClient(grab, client))
4664	*status = AlreadyGrabbed;
4665    else if (!pWin->realized)
4666	*status = GrabNotViewable;
4667    else if ((CompareTimeStamps(time, currentTime) == LATER) ||
4668	     (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER))
4669	*status = GrabInvalidTime;
4670    else if (grabInfo->sync.frozen &&
4671	     grabInfo->sync.other && !SameClient(grabInfo->sync.other, client))
4672	*status = GrabFrozen;
4673    else
4674    {
4675	GrabRec tempGrab;
4676
4677        /* Otherwise segfaults happen on grabbed MPX devices */
4678        memset(&tempGrab, 0, sizeof(GrabRec));
4679
4680        tempGrab.next = NULL;
4681	tempGrab.window = pWin;
4682	tempGrab.resource = client->clientAsMask;
4683	tempGrab.ownerEvents = ownerEvents;
4684	tempGrab.keyboardMode = this_mode;
4685	tempGrab.pointerMode = other_mode;
4686	tempGrab.eventMask = mask;
4687	tempGrab.device = dev;
4688        tempGrab.cursor = NULL;
4689        tempGrab.coreGrab = coreGrab;
4690        tempGrab.genericMasks = NULL;
4691
4692	(*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE);
4693	*status = GrabSuccess;
4694    }
4695    return Success;
4696}
4697
4698/**
4699 * Server-side protocol handling for GrabKeyboard request.
4700 *
4701 * Grabs the client's keyboard and returns success status to client.
4702 */
4703int
4704ProcGrabKeyboard(ClientPtr client)
4705{
4706    xGrabKeyboardReply rep;
4707    REQUEST(xGrabKeyboardReq);
4708    int result;
4709    DeviceIntPtr keyboard = PickKeyboard(client);
4710
4711    REQUEST_SIZE_MATCH(xGrabKeyboardReq);
4712
4713    result = GrabDevice(client, keyboard, stuff->keyboardMode,
4714            stuff->pointerMode, stuff->grabWindow,
4715            stuff->ownerEvents, stuff->time,
4716            KeyPressMask | KeyReleaseMask, &rep.status, TRUE);
4717
4718    if (result != Success)
4719	return result;
4720    rep.type = X_Reply;
4721    rep.sequenceNumber = client->sequence;
4722    rep.length = 0;
4723    WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
4724    return Success;
4725}
4726
4727/**
4728 * Server-side protocol handling for UngrabKeyboard request.
4729 *
4730 * Deletes a possible grab on the client's keyboard.
4731 */
4732int
4733ProcUngrabKeyboard(ClientPtr client)
4734{
4735    DeviceIntPtr device = PickKeyboard(client);
4736    GrabPtr grab;
4737    TimeStamp time;
4738    REQUEST(xResourceReq);
4739
4740    REQUEST_SIZE_MATCH(xResourceReq);
4741    UpdateCurrentTime();
4742
4743    grab = device->deviceGrab.grab;
4744
4745    time = ClientTimeToServerTime(stuff->id);
4746    if ((CompareTimeStamps(time, currentTime) != LATER) &&
4747	(CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
4748	(grab) && SameClient(grab, client) && grab->coreGrab)
4749	(*device->deviceGrab.DeactivateGrab)(device);
4750    return Success;
4751}
4752
4753/**
4754 * Server-side protocol handling for QueryPointer request.
4755 *
4756 * Returns the current state and position of the client's ClientPointer to the
4757 * client.
4758 */
4759int
4760ProcQueryPointer(ClientPtr client)
4761{
4762    xQueryPointerReply rep;
4763    WindowPtr pWin, t;
4764    DeviceIntPtr mouse = PickPointer(client);
4765    SpritePtr pSprite;
4766    int rc;
4767    REQUEST(xResourceReq);
4768    REQUEST_SIZE_MATCH(xResourceReq);
4769
4770    rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
4771    if (rc != Success)
4772	return rc;
4773    rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
4774    if (rc != Success)
4775	return rc;
4776
4777    pSprite = mouse->spriteInfo->sprite;
4778    if (mouse->valuator->motionHintWindow)
4779	MaybeStopHint(mouse, client);
4780    rep.type = X_Reply;
4781    rep.sequenceNumber = client->sequence;
4782    rep.mask = mouse->button->state | inputInfo.keyboard->key->state;
4783    rep.length = 0;
4784    rep.root = (RootWindow(mouse))->drawable.id;
4785    rep.rootX = pSprite->hot.x;
4786    rep.rootY = pSprite->hot.y;
4787    rep.child = None;
4788    if (pSprite->hot.pScreen == pWin->drawable.pScreen)
4789    {
4790	rep.sameScreen = xTrue;
4791	rep.winX = pSprite->hot.x - pWin->drawable.x;
4792	rep.winY = pSprite->hot.y - pWin->drawable.y;
4793	for (t = pSprite->win; t; t = t->parent)
4794	    if (t->parent == pWin)
4795	    {
4796		rep.child = t->drawable.id;
4797		break;
4798	    }
4799    }
4800    else
4801    {
4802	rep.sameScreen = xFalse;
4803	rep.winX = 0;
4804	rep.winY = 0;
4805    }
4806
4807#ifdef PANORAMIX
4808    if(!noPanoramiXExtension) {
4809	rep.rootX += panoramiXdataPtr[0].x;
4810	rep.rootY += panoramiXdataPtr[0].y;
4811	if(stuff->id == rep.root) {
4812	    rep.winX += panoramiXdataPtr[0].x;
4813	    rep.winY += panoramiXdataPtr[0].y;
4814	}
4815    }
4816#endif
4817
4818    WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
4819
4820    return(Success);
4821}
4822
4823/**
4824 * Initializes the device list and the DIX sprite to sane values. Allocates
4825 * trace memory used for quick window traversal.
4826 */
4827void
4828InitEvents(void)
4829{
4830    int i;
4831
4832    inputInfo.numDevices = 0;
4833    inputInfo.devices = (DeviceIntPtr)NULL;
4834    inputInfo.off_devices = (DeviceIntPtr)NULL;
4835    inputInfo.keyboard = (DeviceIntPtr)NULL;
4836    inputInfo.pointer = (DeviceIntPtr)NULL;
4837    lastEventMask = OwnerGrabButtonMask;
4838    filters[0][PointerMotionMask] = MotionNotify;
4839    for (i = 1; i < MAXDEVICES; i++)
4840    {
4841        memcpy(&filters[i], filters[0], sizeof(filters[0]));
4842    }
4843
4844    syncEvents.replayDev = (DeviceIntPtr)NULL;
4845    syncEvents.replayWin = NullWindow;
4846    while (syncEvents.pending)
4847    {
4848	QdEventPtr next = syncEvents.pending->next;
4849	xfree(syncEvents.pending);
4850	syncEvents.pending = next;
4851    }
4852    syncEvents.pendtail = &syncEvents.pending;
4853    syncEvents.playingEvents = FALSE;
4854    syncEvents.time.months = 0;
4855    syncEvents.time.milliseconds = 0;	/* hardly matters */
4856    currentTime.months = 0;
4857    currentTime.milliseconds = GetTimeInMillis();
4858    lastDeviceEventTime = currentTime;
4859    for (i = 0; i < DNPMCOUNT; i++)
4860    {
4861	DontPropagateMasks[i] = 0;
4862	DontPropagateRefCnts[i] = 0;
4863    }
4864
4865    InputEventListLen = GetMaximumEventsNum();
4866    InputEventList = InitEventList(InputEventListLen);
4867    if (!InputEventList)
4868        FatalError("[dix] Failed to allocate input event list.\n");
4869}
4870
4871void
4872CloseDownEvents(void)
4873{
4874    int len;
4875    EventListPtr list;
4876
4877    len = GetEventList(&list);
4878    while(len--)
4879        xfree(list[len].event);
4880}
4881
4882/**
4883 * Server-side protocol handling for SendEvent request.
4884 *
4885 * Locates the window to send the event to and forwards the event.
4886 */
4887int
4888ProcSendEvent(ClientPtr client)
4889{
4890    WindowPtr pWin;
4891    WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
4892    SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
4893    REQUEST(xSendEventReq);
4894
4895    REQUEST_SIZE_MATCH(xSendEventReq);
4896
4897    /* The client's event type must be a core event type or one defined by an
4898	extension. */
4899
4900    if ( ! ((stuff->event.u.u.type > X_Reply &&
4901	     stuff->event.u.u.type < LASTEvent) ||
4902	    (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
4903	     stuff->event.u.u.type < (unsigned)lastEvent)))
4904    {
4905	client->errorValue = stuff->event.u.u.type;
4906	return BadValue;
4907    }
4908    if (stuff->event.u.u.type == ClientMessage &&
4909	stuff->event.u.u.detail != 8 &&
4910	stuff->event.u.u.detail != 16 &&
4911	stuff->event.u.u.detail != 32)
4912    {
4913	client->errorValue = stuff->event.u.u.detail;
4914	return BadValue;
4915    }
4916    if (stuff->eventMask & ~AllEventMasks)
4917    {
4918	client->errorValue = stuff->eventMask;
4919	return BadValue;
4920    }
4921
4922    if (stuff->destination == PointerWindow)
4923	pWin = pSprite->win;
4924    else if (stuff->destination == InputFocus)
4925    {
4926	WindowPtr inputFocus = inputInfo.keyboard->focus->win;
4927
4928	if (inputFocus == NoneWin)
4929	    return Success;
4930
4931	/* If the input focus is PointerRootWin, send the event to where
4932	the pointer is if possible, then perhaps propogate up to root. */
4933	if (inputFocus == PointerRootWin)
4934	    inputFocus = pSprite->spriteTrace[0]; /* Root window! */
4935
4936	if (IsParent(inputFocus, pSprite->win))
4937	{
4938	    effectiveFocus = inputFocus;
4939	    pWin = pSprite->win;
4940	}
4941	else
4942	    effectiveFocus = pWin = inputFocus;
4943    }
4944    else
4945	dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess);
4946
4947    if (!pWin)
4948	return BadWindow;
4949    if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue))
4950    {
4951	client->errorValue = stuff->propagate;
4952	return BadValue;
4953    }
4954    stuff->event.u.u.type |= 0x80;
4955    if (stuff->propagate)
4956    {
4957	for (;pWin; pWin = pWin->parent)
4958	{
4959	    if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin,
4960			 &stuff->event, 1))
4961		return Success;
4962            if (DeliverEventsToWindow(PickPointer(client), pWin,
4963                        &stuff->event, 1, stuff->eventMask, NullGrab, 0))
4964		return Success;
4965	    if (pWin == effectiveFocus)
4966		return Success;
4967	    stuff->eventMask &= ~wDontPropagateMask(pWin);
4968	    if (!stuff->eventMask)
4969		break;
4970	}
4971    }
4972    else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1))
4973        (void)DeliverEventsToWindow(PickPointer(client), pWin, &stuff->event,
4974                                    1, stuff->eventMask, NullGrab, 0);
4975    return Success;
4976}
4977
4978/**
4979 * Server-side protocol handling for UngrabKey request.
4980 *
4981 * Deletes a passive grab for the given key. Works on the
4982 * client's keyboard.
4983 */
4984int
4985ProcUngrabKey(ClientPtr client)
4986{
4987    REQUEST(xUngrabKeyReq);
4988    WindowPtr pWin;
4989    GrabRec tempGrab;
4990    DeviceIntPtr keybd = PickKeyboard(client);
4991    int rc;
4992
4993    REQUEST_SIZE_MATCH(xUngrabKeyReq);
4994    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
4995    if (rc != Success)
4996	return rc;
4997
4998    if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) ||
4999	 (stuff->key < keybd->key->curKeySyms.minKeyCode))
5000	&& (stuff->key != AnyKey))
5001    {
5002	client->errorValue = stuff->key;
5003        return BadValue;
5004    }
5005    if ((stuff->modifiers != AnyModifier) &&
5006	(stuff->modifiers & ~AllModifiersMask))
5007    {
5008	client->errorValue = stuff->modifiers;
5009	return BadValue;
5010    }
5011    tempGrab.resource = client->clientAsMask;
5012    tempGrab.device = keybd;
5013    tempGrab.window = pWin;
5014    tempGrab.modifiersDetail.exact = stuff->modifiers;
5015    tempGrab.modifiersDetail.pMask = NULL;
5016    tempGrab.modifierDevice = inputInfo.keyboard;
5017    tempGrab.type = KeyPress;
5018    tempGrab.detail.exact = stuff->key;
5019    tempGrab.detail.pMask = NULL;
5020    tempGrab.next = NULL;
5021
5022    if (!DeletePassiveGrabFromList(&tempGrab))
5023	return(BadAlloc);
5024    return(Success);
5025}
5026
5027/**
5028 * Server-side protocol handling for GrabKey request.
5029 *
5030 * Creates a grab for the client's keyboard and adds it to the list of passive
5031 * grabs.
5032 */
5033int
5034ProcGrabKey(ClientPtr client)
5035{
5036    WindowPtr pWin;
5037    REQUEST(xGrabKeyReq);
5038    GrabPtr grab;
5039    DeviceIntPtr keybd = PickKeyboard(client);
5040    int rc;
5041
5042    REQUEST_SIZE_MATCH(xGrabKeyReq);
5043    if ((stuff->ownerEvents != xTrue) && (stuff->ownerEvents != xFalse))
5044    {
5045	client->errorValue = stuff->ownerEvents;
5046	return(BadValue);
5047    }
5048    if ((stuff->pointerMode != GrabModeSync) &&
5049	(stuff->pointerMode != GrabModeAsync))
5050    {
5051	client->errorValue = stuff->pointerMode;
5052        return BadValue;
5053    }
5054    if ((stuff->keyboardMode != GrabModeSync) &&
5055	(stuff->keyboardMode != GrabModeAsync))
5056    {
5057	client->errorValue = stuff->keyboardMode;
5058        return BadValue;
5059    }
5060    if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) ||
5061	 (stuff->key < keybd->key->curKeySyms.minKeyCode))
5062	&& (stuff->key != AnyKey))
5063    {
5064	client->errorValue = stuff->key;
5065        return BadValue;
5066    }
5067    if ((stuff->modifiers != AnyModifier) &&
5068	(stuff->modifiers & ~AllModifiersMask))
5069    {
5070	client->errorValue = stuff->modifiers;
5071	return BadValue;
5072    }
5073    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
5074    if (rc != Success)
5075	return rc;
5076
5077    grab = CreateGrab(client->index, keybd, pWin,
5078	(Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents,
5079	(Bool)stuff->keyboardMode, (Bool)stuff->pointerMode,
5080	keybd, stuff->modifiers, KeyPress, stuff->key,
5081	NullWindow, NullCursor);
5082    if (!grab)
5083	return BadAlloc;
5084    return AddPassiveGrabToList(client, grab);
5085}
5086
5087
5088/**
5089 * Server-side protocol handling for GrabButton request.
5090 *
5091 * Creates a grab for the client's ClientPointer and adds it as a passive grab
5092 * to the list.
5093 */
5094int
5095ProcGrabButton(ClientPtr client)
5096{
5097    WindowPtr pWin, confineTo;
5098    REQUEST(xGrabButtonReq);
5099    CursorPtr cursor;
5100    GrabPtr grab;
5101    DeviceIntPtr ptr, modifierDevice;
5102    Mask access_mode = DixGrabAccess;
5103    int rc;
5104
5105    REQUEST_SIZE_MATCH(xGrabButtonReq);
5106    if ((stuff->pointerMode != GrabModeSync) &&
5107	(stuff->pointerMode != GrabModeAsync))
5108    {
5109	client->errorValue = stuff->pointerMode;
5110        return BadValue;
5111    }
5112    if ((stuff->keyboardMode != GrabModeSync) &&
5113	(stuff->keyboardMode != GrabModeAsync))
5114    {
5115	client->errorValue = stuff->keyboardMode;
5116        return BadValue;
5117    }
5118    if ((stuff->modifiers != AnyModifier) &&
5119	(stuff->modifiers & ~AllModifiersMask))
5120    {
5121	client->errorValue = stuff->modifiers;
5122	return BadValue;
5123    }
5124    if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
5125    {
5126	client->errorValue = stuff->ownerEvents;
5127	return BadValue;
5128    }
5129    if (stuff->eventMask & ~PointerGrabMask)
5130    {
5131	client->errorValue = stuff->eventMask;
5132        return BadValue;
5133    }
5134    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
5135    if (rc != Success)
5136	return rc;
5137    if (stuff->confineTo == None)
5138       confineTo = NullWindow;
5139    else {
5140	rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
5141			     DixSetAttrAccess);
5142	if (rc != Success)
5143	    return rc;
5144    }
5145    if (stuff->cursor == None)
5146	cursor = NullCursor;
5147    else
5148    {
5149	rc = dixLookupResource((pointer *)&cursor, stuff->cursor, RT_CURSOR,
5150			       client, DixUseAccess);
5151	if (rc != Success)
5152	if (!cursor)
5153	{
5154	    client->errorValue = stuff->cursor;
5155	    return (rc == BadValue) ? BadCursor : rc;
5156	}
5157	access_mode |= DixForceAccess;
5158    }
5159
5160    ptr = PickPointer(client);
5161    modifierDevice = GetPairedDevice(ptr);
5162    if (stuff->pointerMode == GrabModeSync ||
5163	stuff->keyboardMode == GrabModeSync)
5164	access_mode |= DixFreezeAccess;
5165    rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode);
5166    if (rc != Success)
5167	return rc;
5168
5169    grab = CreateGrab(client->index, ptr, pWin,
5170        (Mask)stuff->eventMask, (Bool)stuff->ownerEvents,
5171        (Bool) stuff->keyboardMode, (Bool)stuff->pointerMode,
5172        modifierDevice, stuff->modifiers, ButtonPress,
5173        stuff->button, confineTo, cursor);
5174    if (!grab)
5175	return BadAlloc;
5176    return AddPassiveGrabToList(client, grab);
5177}
5178
5179/**
5180 * Server-side protocol handling for UngrabButton request.
5181 *
5182 * Deletes a passive grab on the client's ClientPointer from the list.
5183 */
5184int
5185ProcUngrabButton(ClientPtr client)
5186{
5187    REQUEST(xUngrabButtonReq);
5188    WindowPtr pWin;
5189    GrabRec tempGrab;
5190    int rc;
5191
5192    REQUEST_SIZE_MATCH(xUngrabButtonReq);
5193    if ((stuff->modifiers != AnyModifier) &&
5194	(stuff->modifiers & ~AllModifiersMask))
5195    {
5196	client->errorValue = stuff->modifiers;
5197	return BadValue;
5198    }
5199    rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
5200    if (rc != Success)
5201	return rc;
5202    tempGrab.resource = client->clientAsMask;
5203    tempGrab.device = PickPointer(client);
5204    tempGrab.window = pWin;
5205    tempGrab.modifiersDetail.exact = stuff->modifiers;
5206    tempGrab.modifiersDetail.pMask = NULL;
5207    tempGrab.modifierDevice = inputInfo.keyboard;
5208    tempGrab.type = ButtonPress;
5209    tempGrab.detail.exact = stuff->button;
5210    tempGrab.detail.pMask = NULL;
5211    tempGrab.next = NULL;
5212
5213    if (!DeletePassiveGrabFromList(&tempGrab))
5214	return(BadAlloc);
5215    return(Success);
5216}
5217
5218/**
5219 * Deactivate any grab that may be on the window, remove the focus.
5220 * Delete any XInput extension events from the window too. Does not change the
5221 * window mask. Use just before the window is deleted.
5222 *
5223 * If freeResources is set, passive grabs on the window are deleted.
5224 *
5225 * @param pWin The window to delete events from.
5226 * @param freeResources True if resources associated with the window should be
5227 * deleted.
5228 */
5229void
5230DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
5231{
5232    WindowPtr		parent;
5233    DeviceIntPtr	mouse = inputInfo.pointer;
5234    DeviceIntPtr	keybd = inputInfo.keyboard;
5235    FocusClassPtr	focus;
5236    OtherClientsPtr	oc;
5237    GrabPtr		passive;
5238    GrabPtr             grab;
5239
5240
5241    /* Deactivate any grabs performed on this window, before making any
5242	input focus changes. */
5243    grab = mouse->deviceGrab.grab;
5244    if (grab &&
5245	((grab->window == pWin) || (grab->confineTo == pWin)))
5246	(*mouse->deviceGrab.DeactivateGrab)(mouse);
5247
5248
5249    /* Deactivating a keyboard grab should cause focus events. */
5250    grab = keybd->deviceGrab.grab;
5251    if (grab && (grab->window == pWin))
5252	(*keybd->deviceGrab.DeactivateGrab)(keybd);
5253
5254    /* And now the real devices */
5255    for (mouse = inputInfo.devices; mouse; mouse = mouse->next)
5256    {
5257        grab = mouse->deviceGrab.grab;
5258        if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
5259            (*mouse->deviceGrab.DeactivateGrab)(mouse);
5260    }
5261
5262
5263    for (keybd = inputInfo.devices; keybd; keybd = keybd->next)
5264    {
5265        if (IsKeyboardDevice(keybd))
5266        {
5267            focus = keybd->focus;
5268
5269            /* If the focus window is a root window (ie. has no parent) then don't
5270               delete the focus from it. */
5271
5272            if ((pWin == focus->win) && (pWin->parent != NullWindow))
5273            {
5274                int focusEventMode = NotifyNormal;
5275
5276                /* If a grab is in progress, then alter the mode of focus events. */
5277
5278                if (keybd->deviceGrab.grab)
5279                    focusEventMode = NotifyWhileGrabbed;
5280
5281                switch (focus->revert)
5282                {
5283                    case RevertToNone:
5284                        DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
5285                        focus->win = NoneWin;
5286                        focus->traceGood = 0;
5287                        break;
5288                    case RevertToParent:
5289                        parent = pWin;
5290                        do
5291                        {
5292                            parent = parent->parent;
5293                            focus->traceGood--;
5294                        } while (!parent->realized
5295                                /* This would be a good protocol change -- windows being reparented
5296                                   during SaveSet processing would cause the focus to revert to the
5297                                   nearest enclosing window which will survive the death of the exiting
5298                                   client, instead of ending up reverting to a dying window and thence
5299                                   to None
5300                                 */
5301#ifdef NOTDEF
5302                                || clients[CLIENT_ID(parent->drawable.id)]->clientGone
5303#endif
5304                                );
5305                        DoFocusEvents(keybd, pWin, parent, focusEventMode);
5306                        focus->win = parent;
5307                        focus->revert = RevertToNone;
5308                        break;
5309                    case RevertToPointerRoot:
5310                        DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode);
5311                        focus->win = PointerRootWin;
5312                        focus->traceGood = 0;
5313                        break;
5314                }
5315            }
5316        }
5317
5318        if (IsPointerDevice(keybd))
5319        {
5320            if (keybd->valuator->motionHintWindow == pWin)
5321                keybd->valuator->motionHintWindow = NullWindow;
5322        }
5323    }
5324
5325    if (freeResources)
5326    {
5327	if (pWin->dontPropagate)
5328	    DontPropagateRefCnts[pWin->dontPropagate]--;
5329	while ( (oc = wOtherClients(pWin)) )
5330	    FreeResource(oc->resource, RT_NONE);
5331	while ( (passive = wPassiveGrabs(pWin)) )
5332	    FreeResource(passive->resource, RT_NONE);
5333     }
5334
5335    DeleteWindowFromAnyExtEvents(pWin, freeResources);
5336}
5337
5338/**
5339 * Call this whenever some window at or below pWin has changed geometry. If
5340 * there is a grab on the window, the cursor will be re-confined into the
5341 * window.
5342 */
5343_X_EXPORT void
5344CheckCursorConfinement(WindowPtr pWin)
5345{
5346    GrabPtr grab;
5347    WindowPtr confineTo;
5348    DeviceIntPtr pDev;
5349
5350#ifdef PANORAMIX
5351    if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return;
5352#endif
5353
5354    for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
5355    {
5356        if (DevHasCursor(pDev))
5357        {
5358            grab = pDev->deviceGrab.grab;
5359            if (grab && (confineTo = grab->confineTo))
5360            {
5361                if (!BorderSizeNotEmpty(pDev, confineTo))
5362                    (*inputInfo.pointer->deviceGrab.DeactivateGrab)(pDev);
5363                else if ((pWin == confineTo) || IsParent(pWin, confineTo))
5364                    ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
5365            }
5366        }
5367    }
5368}
5369
5370Mask
5371EventMaskForClient(WindowPtr pWin, ClientPtr client)
5372{
5373    OtherClientsPtr	other;
5374
5375    if (wClient (pWin) == client)
5376	return pWin->eventMask;
5377    for (other = wOtherClients(pWin); other; other = other->next)
5378    {
5379	if (SameClient(other, client))
5380	    return other->mask;
5381    }
5382    return 0;
5383}
5384
5385/**
5386 * Server-side protocol handling for RecolorCursor request.
5387 */
5388int
5389ProcRecolorCursor(ClientPtr client)
5390{
5391    CursorPtr pCursor;
5392    int		rc, nscr;
5393    ScreenPtr	pscr;
5394    Bool	displayed;
5395    SpritePtr   pSprite = PickPointer(client)->spriteInfo->sprite;
5396    REQUEST(xRecolorCursorReq);
5397
5398    REQUEST_SIZE_MATCH(xRecolorCursorReq);
5399    rc = dixLookupResource((pointer *)&pCursor, stuff->cursor, RT_CURSOR,
5400			   client, DixWriteAccess);
5401    if (rc != Success)
5402    {
5403	client->errorValue = stuff->cursor;
5404	return (rc == BadValue) ? BadCursor : rc;
5405    }
5406
5407    pCursor->foreRed = stuff->foreRed;
5408    pCursor->foreGreen = stuff->foreGreen;
5409    pCursor->foreBlue = stuff->foreBlue;
5410
5411    pCursor->backRed = stuff->backRed;
5412    pCursor->backGreen = stuff->backGreen;
5413    pCursor->backBlue = stuff->backBlue;
5414
5415    for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
5416    {
5417	pscr = screenInfo.screens[nscr];
5418#ifdef PANORAMIX
5419	if(!noPanoramiXExtension)
5420	    displayed = (pscr == pSprite->screen);
5421	else
5422#endif
5423	    displayed = (pscr == pSprite->hotPhys.pScreen);
5424	( *pscr->RecolorCursor)(PickPointer(client), pscr, pCursor,
5425				(pCursor == pSprite->current) && displayed);
5426    }
5427    return (Success);
5428}
5429
5430/**
5431 * Write the given events to a client, swapping the byte order if necessary.
5432 * To swap the byte ordering, a callback is called that has to be set up for
5433 * the given event type.
5434 *
5435 * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
5436 * can be more than one. Usually it's just one event.
5437 *
5438 * Do not modify the event structure passed in. See comment below.
5439 *
5440 * @param pClient Client to send events to.
5441 * @param count Number of events.
5442 * @param events The event list.
5443 */
5444_X_EXPORT void
5445WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
5446{
5447#ifdef PANORAMIX
5448    xEvent    eventCopy;
5449#endif
5450    xEvent    *eventTo, *eventFrom;
5451    int       i,
5452              eventlength = sizeof(xEvent);
5453
5454#ifdef XKB
5455    if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events)))
5456	return;
5457#endif
5458
5459#ifdef PANORAMIX
5460    if(!noPanoramiXExtension &&
5461       (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y))
5462    {
5463	switch(events->u.u.type) {
5464	case MotionNotify:
5465	case ButtonPress:
5466	case ButtonRelease:
5467	case KeyPress:
5468	case KeyRelease:
5469	case EnterNotify:
5470	case LeaveNotify:
5471	/*
5472	   When multiple clients want the same event DeliverEventsToWindow
5473	   passes the same event structure multiple times so we can't
5474	   modify the one passed to us
5475        */
5476	    count = 1;  /* should always be 1 */
5477	    memcpy(&eventCopy, events, sizeof(xEvent));
5478	    eventCopy.u.keyButtonPointer.rootX += panoramiXdataPtr[0].x;
5479	    eventCopy.u.keyButtonPointer.rootY += panoramiXdataPtr[0].y;
5480	    if(eventCopy.u.keyButtonPointer.event ==
5481	       eventCopy.u.keyButtonPointer.root)
5482	    {
5483		eventCopy.u.keyButtonPointer.eventX += panoramiXdataPtr[0].x;
5484		eventCopy.u.keyButtonPointer.eventY += panoramiXdataPtr[0].y;
5485	    }
5486	    events = &eventCopy;
5487	    break;
5488	default: break;
5489	}
5490    }
5491#endif
5492
5493    if (EventCallback)
5494    {
5495	EventInfoRec eventinfo;
5496	eventinfo.client = pClient;
5497	eventinfo.events = events;
5498	eventinfo.count = count;
5499	CallCallbacks(&EventCallback, (pointer)&eventinfo);
5500    }
5501#ifdef XSERVER_DTRACE
5502    if (XSERVER_SEND_EVENT_ENABLED()) {
5503	for (i = 0; i < count; i++)
5504	{
5505	    XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]);
5506	}
5507    }
5508#endif
5509    /* Just a safety check to make sure we only have one GenericEvent, it just
5510     * makes things easier for me right now. (whot) */
5511    for (i = 1; i < count; i++)
5512    {
5513        if (events[i].u.u.type == GenericEvent)
5514        {
5515            ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n");
5516            return;
5517        }
5518    }
5519
5520    if (events->u.u.type == GenericEvent)
5521    {
5522        eventlength += ((xGenericEvent*)events)->length * 4;
5523    }
5524
5525    if(pClient->swapped)
5526    {
5527        if (eventlength > swapEventLen)
5528        {
5529            swapEventLen = eventlength;
5530            swapEvent = Xrealloc(swapEvent, swapEventLen);
5531            if (!swapEvent)
5532            {
5533                FatalError("WriteEventsToClient: Out of memory.\n");
5534                return;
5535            }
5536        }
5537
5538	for(i = 0; i < count; i++)
5539	{
5540	    eventFrom = &events[i];
5541            eventTo = swapEvent;
5542
5543	    /* Remember to strip off the leading bit of type in case
5544	       this event was sent with "SendEvent." */
5545	    (*EventSwapVector[eventFrom->u.u.type & 0177])
5546		(eventFrom, eventTo);
5547
5548	    (void)WriteToClient(pClient, eventlength, (char *)eventTo);
5549	}
5550    }
5551    else
5552    {
5553        /* only one GenericEvent, remember? that means either count is 1 and
5554         * eventlength is arbitrary or eventlength is 32 and count doesn't
5555         * matter. And we're all set. Woohoo. */
5556	(void)WriteToClient(pClient, count * eventlength, (char *) events);
5557    }
5558}
5559
5560/*
5561 * Set the client pointer for the given client. Second parameter setter could
5562 * be used in the future to determine access rights. Unused for now.
5563 *
5564 * A client can have exactly one ClientPointer. Each time a
5565 * request/reply/event is processed and the choice of devices is ambiguous
5566 * (e.g. QueryPointer request), the server will pick the ClientPointer (see
5567 * PickPointer()).
5568 * If a keyboard is needed, the first keyboard paired with the CP is used.
5569 */
5570_X_EXPORT Bool
5571SetClientPointer(ClientPtr client, ClientPtr setter, DeviceIntPtr device)
5572{
5573    if (!device->isMaster)
5574    {
5575        ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n");
5576        return FALSE;
5577    } else if (!device->spriteInfo->spriteOwner)
5578    {
5579        ErrorF("[dix] Device %d does not have a sprite. "
5580                "Cannot be ClientPointer\n", device->id);
5581        return FALSE;
5582    }
5583    client->clientPtr = device;
5584    return TRUE;
5585}
5586
5587/* PickPointer will pick an appropriate pointer for the given client.
5588 *
5589 * An "appropriate device" is (in order of priority):
5590 *  1) A device the given client has a core grab on.
5591 *  2) A device set as ClientPointer for the given client.
5592 *  3) The first master device.
5593 */
5594_X_EXPORT DeviceIntPtr
5595PickPointer(ClientPtr client)
5596{
5597    DeviceIntPtr it = inputInfo.devices;
5598
5599    /* First, check if the client currently has a grab on a device. Even
5600     * keyboards count. */
5601    for(it = inputInfo.devices; it; it = it->next)
5602    {
5603        GrabPtr grab = it->deviceGrab.grab;
5604        if (grab && grab->coreGrab && SameClient(grab, client))
5605        {
5606            if (!IsPointerDevice(it))
5607                it = GetPairedDevice(it);
5608            return it; /* Always return a core grabbed device */
5609        }
5610    }
5611
5612    if (!client->clientPtr)
5613    {
5614        DeviceIntPtr it = inputInfo.devices;
5615        while (it)
5616        {
5617            if (it->isMaster && it->spriteInfo->spriteOwner)
5618            {
5619                client->clientPtr = it;
5620                break;
5621            }
5622            it = it->next;
5623        }
5624    }
5625    return client->clientPtr;
5626}
5627
5628/* PickKeyboard will pick an appropriate keyboard for the given client by
5629 * searching the list of devices for the keyboard device that is paired with
5630 * the client's pointer.
5631 */
5632_X_EXPORT DeviceIntPtr
5633PickKeyboard(ClientPtr client)
5634{
5635    DeviceIntPtr ptr = PickPointer(client);
5636    DeviceIntPtr kbd = ptr->spriteInfo->paired;
5637
5638    if (!kbd)
5639    {
5640        ErrorF("[dix] ClientPointer not paired with a keyboard. This "
5641                "is a bug.\n");
5642    }
5643
5644    return kbd;
5645}
5646
5647/* A client that has one or more core grabs does not get core events from
5648 * devices it does not have a grab on. Legacy applications behave bad
5649 * otherwise because they are not used to it and the events interfere.
5650 * Only applies for core events.
5651 *
5652 * Return true if a core event from the device would interfere and should not
5653 * be delivered.
5654 */
5655Bool
5656IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event)
5657{
5658    DeviceIntPtr it = inputInfo.devices;
5659
5660    if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
5661        return FALSE;
5662
5663    switch(event->u.u.type)
5664    {
5665        case KeyPress:
5666        case KeyRelease:
5667        case ButtonPress:
5668        case ButtonRelease:
5669        case MotionNotify:
5670        case EnterNotify:
5671        case LeaveNotify:
5672            break;
5673        default:
5674            return FALSE;
5675    }
5676
5677    while(it)
5678    {
5679        if (it != dev)
5680        {
5681            if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client)
5682                        && !it->deviceGrab.fromPassiveGrab)
5683            {
5684                if ((IsPointerDevice(it) && IsPointerDevice(dev)) ||
5685                        (IsKeyboardDevice(it) && IsKeyboardDevice(dev)))
5686                    return TRUE;
5687            }
5688        }
5689        it = it->next;
5690    }
5691
5692    return FALSE;
5693}
5694
5695/**
5696 * Set the filters for a extension.
5697 * The filters array needs to contain the Masks that are applicable for each
5698 * event type for the given extension.
5699 * e.g. if generic event type 2 should be let through for windows with
5700 * MyExampleMask set, make sure that filters[2] == MyExampleMask.
5701 */
5702_X_EXPORT void
5703SetGenericFilter(int extension, Mask* filters)
5704{
5705    generic_filters[extension & 0x7f] = filters;
5706}
5707
5708
5709/**
5710 * Grab a device for XI events and XGE events.
5711 * grabmode is used to ungrab a device.
5712 */
5713_X_EXPORT int
5714ExtGrabDevice(ClientPtr client,
5715              DeviceIntPtr dev,
5716              int device_mode,
5717              WindowPtr grabWindow,
5718              WindowPtr confineTo,
5719              TimeStamp ctime,
5720              Bool ownerEvents,
5721              CursorPtr cursor,
5722              Mask xi_mask,
5723              GenericMaskPtr ge_masks)
5724{
5725    GrabInfoPtr grabinfo;
5726    GrabRec     newGrab;
5727
5728    UpdateCurrentTime();
5729
5730    grabinfo = &dev->deviceGrab;
5731
5732    if (grabinfo->grab && !SameClient(grabinfo->grab, client))
5733        return AlreadyGrabbed;
5734
5735    if (!grabWindow->realized)
5736        return GrabNotViewable;
5737
5738    if ((CompareTimeStamps(ctime, currentTime) == LATER) ||
5739            (CompareTimeStamps(ctime, grabinfo->grabTime) == EARLIER))
5740        return GrabInvalidTime;
5741
5742    if (grabinfo->sync.frozen && grabinfo->sync.other &&
5743            !SameClient(grabinfo->sync.other, client))
5744        return GrabFrozen;
5745
5746    memset(&newGrab, 0, sizeof(GrabRec));
5747    newGrab.window         = grabWindow;
5748    newGrab.resource       = client->clientAsMask;
5749    newGrab.ownerEvents    = ownerEvents;
5750    newGrab.device         = dev;
5751    newGrab.cursor         = cursor;
5752    newGrab.confineTo      = confineTo;
5753    newGrab.eventMask      = xi_mask;
5754    newGrab.genericMasks   = NULL;
5755    newGrab.next           = NULL;
5756
5757    if (ge_masks)
5758    {
5759        newGrab.genericMasks  = xcalloc(1, sizeof(GenericMaskRec));
5760        *newGrab.genericMasks = *ge_masks;
5761        newGrab.genericMasks->next = NULL;
5762    }
5763
5764    if (IsPointerDevice(dev))
5765    {
5766        newGrab.keyboardMode = GrabModeAsync;
5767        newGrab.pointerMode  = device_mode;
5768    } else
5769    {
5770        newGrab.keyboardMode = device_mode;
5771        newGrab.pointerMode  = GrabModeAsync;
5772    }
5773
5774    (*grabinfo->ActivateGrab)(dev, &newGrab, ctime, FALSE);
5775    return GrabSuccess;
5776}
5777
5778