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