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