exevents.c revision 4642e01f
1/************************************************************
2
3Copyright 1989, 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
25Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
26
27			All Rights Reserved
28
29Permission to use, copy, modify, and distribute this software and its
30documentation for any purpose and without fee is hereby granted,
31provided that the above copyright notice appear in all copies and that
32both that copyright notice and this permission notice appear in
33supporting documentation, and that the name of Hewlett-Packard not be
34used in advertising or publicity pertaining to distribution of the
35software without specific, written prior permission.
36
37HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43SOFTWARE.
44
45********************************************************/
46
47/********************************************************************
48 *
49 *  Routines to register and initialize extension input devices.
50 *  This also contains ProcessOtherEvent, the routine called from DDX
51 *  to route extension events.
52 *
53 */
54
55#define	 NEED_EVENTS
56#ifdef HAVE_DIX_CONFIG_H
57#include <dix-config.h>
58#endif
59
60#include <X11/X.h>
61#include <X11/Xproto.h>
62#include <X11/extensions/XI.h>
63#include <X11/extensions/XIproto.h>
64#include <X11/extensions/geproto.h>
65#include "inputstr.h"
66#include "windowstr.h"
67#include "miscstruct.h"
68#include "region.h"
69#include "exevents.h"
70#include "extnsionst.h"
71#include "exglobals.h"
72#include "dixevents.h"	/* DeliverFocusedEvent */
73#include "dixgrabs.h"	/* CreateGrab() */
74#include "scrnintstr.h"
75#include "listdev.h" /* for CopySwapXXXClass */
76#include "xace.h"
77
78#ifdef XKB
79#include <X11/extensions/XKBproto.h>
80#include "xkbsrv.h"
81extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies);
82#endif
83
84#define WID(w) ((w) ? ((w)->drawable.id) : 0)
85#define AllModifiersMask ( \
86	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
87	Mod3Mask | Mod4Mask | Mod5Mask )
88#define AllButtonsMask ( \
89	Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
90#define Motion_Filter(class) (DevicePointerMotionMask | \
91			      (class)->state | (class)->motionMask)
92
93Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
94				 Bool	/* ignoreSelectedEvents */
95    );
96static Bool MakeInputMasks(WindowPtr	/* pWin */
97    );
98
99/* Used to sture classes currently not in use by an MD */
100extern DevPrivateKey UnusedClassesPrivateKey;
101
102
103void
104RegisterOtherDevice(DeviceIntPtr device)
105{
106    device->public.processInputProc = ProcessOtherEvent;
107    device->public.realInputProc = ProcessOtherEvent;
108}
109
110Bool
111IsPointerEvent(xEvent* xE)
112{
113    switch(xE->u.u.type)
114    {
115        case ButtonPress:
116        case ButtonRelease:
117        case MotionNotify:
118        case EnterNotify:
119        case LeaveNotify:
120            return TRUE;
121        default:
122            if (xE->u.u.type == DeviceButtonPress ||
123                xE->u.u.type == DeviceButtonRelease ||
124                xE->u.u.type == DeviceMotionNotify ||
125                xE->u.u.type == ProximityIn ||
126                xE->u.u.type == ProximityOut)
127            {
128                return TRUE;
129            }
130    }
131    return FALSE;
132}
133
134/**
135 * @return the device matching the deviceid of the device set in the event, or
136 * NULL if the event is not an XInput event.
137 */
138DeviceIntPtr
139XIGetDevice(xEvent* xE)
140{
141    DeviceIntPtr pDev = NULL;
142
143    if (xE->u.u.type == DeviceButtonPress ||
144        xE->u.u.type == DeviceButtonRelease ||
145        xE->u.u.type == DeviceMotionNotify ||
146        xE->u.u.type == ProximityIn ||
147        xE->u.u.type == ProximityOut ||
148        xE->u.u.type == DevicePropertyNotify)
149    {
150        int rc;
151        int id;
152
153        id = ((deviceKeyButtonPointer*)xE)->deviceid & ~MORE_EVENTS;
154
155        rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
156        if (rc != Success)
157            ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
158    }
159    return pDev;
160}
161
162
163/**
164 * Copy the device->key into master->key and send a mapping notify to the
165 * clients if appropriate.
166 * master->key needs to be allocated by the caller.
167 *
168 * Device is the slave device. If it is attached to a master device, we may
169 * need to send a mapping notify to the client because it causes the MD
170 * to change state.
171 *
172 * Mapping notify needs to be sent in the following cases:
173 *      - different slave device on same master
174 *      - different master
175 *
176 * XXX: They way how the code is we also send a map notify if the slave device
177 * stays the same, but the master changes. This isn't really necessary though.
178 *
179 * XXX: this gives you funny behaviour with the ClientPointer. When a
180 * MappingNotify is sent to the client, the client usually responds with a
181 * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
182 * mapping, regardless of which keyboard sent the last mapping notify request.
183 * So depending on the CP setting, your keyboard may change layout in each
184 * app...
185 *
186 * This code is basically the old SwitchCoreKeyboard.
187 */
188
189void
190CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
191{
192    static DeviceIntPtr lastMapNotifyDevice = NULL;
193    KeyClassPtr mk, dk; /* master, device */
194    BOOL sendNotify = FALSE;
195    int i;
196
197    if (device == master)
198        return;
199
200    dk = device->key;
201    mk = master->key;
202
203    if (device != dixLookupPrivate(&master->devPrivates,
204                                   CoreDevicePrivateKey)) {
205        memcpy(mk->modifierMap, dk->modifierMap, MAP_LENGTH);
206
207        if (dk->maxKeysPerModifier)
208        {
209            mk->modifierKeyMap = xrealloc(mk->modifierKeyMap,
210                                          8 * dk->maxKeysPerModifier);
211            if (!mk->modifierKeyMap)
212                FatalError("[Xi] no memory for class shift.\n");
213            memcpy(mk->modifierKeyMap, dk->modifierKeyMap,
214                    (8 * dk->maxKeysPerModifier));
215        } else
216        {
217            xfree(mk->modifierKeyMap);
218            mk->modifierKeyMap = NULL;
219        }
220
221        mk->maxKeysPerModifier = dk->maxKeysPerModifier;
222        mk->curKeySyms.minKeyCode = dk->curKeySyms.minKeyCode;
223        mk->curKeySyms.maxKeyCode = dk->curKeySyms.maxKeyCode;
224        SetKeySymsMap(&mk->curKeySyms, &dk->curKeySyms);
225
226        /*
227         * Copy state from the extended keyboard to core.  If you omit this,
228         * holding Ctrl on keyboard one, and pressing Q on keyboard two, will
229         * cause your app to quit.  This feels wrong to me, hence the below
230         * code.
231         *
232         * XXX: If you synthesise core modifier events, the state will get
233         *      clobbered here.  You'll have to work out something sensible
234         *      to fix that.  Good luck.
235         */
236
237#define KEYBOARD_MASK (ShiftMask | LockMask | ControlMask | Mod1Mask | \
238        Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)
239        mk->state &= ~(KEYBOARD_MASK);
240        mk->state |= (dk->state & KEYBOARD_MASK);
241#undef KEYBOARD_MASK
242        for (i = 0; i < 8; i++)
243            mk->modifierKeyCount[i] = dk->modifierKeyCount[i];
244
245#ifdef XKB
246        if (!noXkbExtension && dk->xkbInfo && dk->xkbInfo->desc) {
247            if (!mk->xkbInfo || !mk->xkbInfo->desc)
248            {
249                XkbInitDevice(master);
250                XkbFinishDeviceInit(master);
251            }
252            if (!XkbCopyKeymap(dk->xkbInfo->desc, mk->xkbInfo->desc, True))
253                FatalError("Couldn't pivot keymap from device to core!\n");
254        }
255#endif
256
257        dixSetPrivate(&master->devPrivates, CoreDevicePrivateKey, device);
258        sendNotify = TRUE;
259    } else if (lastMapNotifyDevice != master)
260        sendNotify = TRUE;
261
262    if (sendNotify)
263    {
264        SendMappingNotify(master, MappingKeyboard,
265                           mk->curKeySyms.minKeyCode,
266                          (mk->curKeySyms.maxKeyCode -
267                           mk->curKeySyms.minKeyCode),
268                          serverClient);
269        lastMapNotifyDevice = master;
270    }
271}
272
273/**
274 * Copies the feedback classes from device "from" into device "to". Classes
275 * are duplicated (not just flipping the pointers). All feedback classes are
276 * linked lists, the full list is duplicated.
277 */
278static void
279DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
280{
281    ClassesPtr classes;
282
283    if (from->kbdfeed)
284    {
285        KbdFeedbackPtr *k, it;
286
287        if (!to->kbdfeed)
288        {
289            classes = dixLookupPrivate(&to->devPrivates,
290                                       UnusedClassesPrivateKey);
291            to->kbdfeed = classes->kbdfeed;
292        }
293
294        k = &to->kbdfeed;
295        for(it = from->kbdfeed; it; it = it->next)
296        {
297            if (!(*k))
298            {
299                *k = xcalloc(1, sizeof(KbdFeedbackClassRec));
300                if (!*k)
301                {
302                    ErrorF("[Xi] Cannot alloc memory for class copy.");
303                    return;
304                }
305            }
306            (*k)->BellProc = it->BellProc;
307            (*k)->CtrlProc = it->CtrlProc;
308            (*k)->ctrl     = it->ctrl;
309#ifdef XKB
310            if ((*k)->xkb_sli)
311                XkbFreeSrvLedInfo((*k)->xkb_sli);
312            (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
313#endif
314
315            k = &(*k)->next;
316        }
317    } else if (to->kbdfeed && !from->kbdfeed)
318    {
319        ClassesPtr classes;
320        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
321        classes->kbdfeed = to->kbdfeed;
322        to->kbdfeed      = NULL;
323    }
324
325    if (from->ptrfeed)
326    {
327        PtrFeedbackPtr *p, it;
328        if (!to->ptrfeed)
329        {
330            classes = dixLookupPrivate(&to->devPrivates,
331                                       UnusedClassesPrivateKey);
332            to->ptrfeed = classes->ptrfeed;
333        }
334
335        p = &to->ptrfeed;
336        for (it = from->ptrfeed; it; it = it->next)
337        {
338            if (!(*p))
339            {
340                *p = xcalloc(1, sizeof(PtrFeedbackClassRec));
341                if (!*p)
342                {
343                    ErrorF("[Xi] Cannot alloc memory for class copy.");
344                    return;
345                }
346            }
347            (*p)->CtrlProc = it->CtrlProc;
348            (*p)->ctrl     = it->ctrl;
349
350            p = &(*p)->next;
351        }
352    } else if (to->ptrfeed && !from->ptrfeed)
353    {
354        ClassesPtr classes;
355        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
356        classes->ptrfeed = to->ptrfeed;
357        to->ptrfeed      = NULL;
358    }
359
360    if (from->intfeed)
361    {
362        IntegerFeedbackPtr *i, it;
363
364        if (!to->intfeed)
365        {
366            classes = dixLookupPrivate(&to->devPrivates,
367                                       UnusedClassesPrivateKey);
368            to->intfeed = classes->intfeed;
369        }
370
371        i = &to->intfeed;
372        for (it = from->intfeed; it; it = it->next)
373        {
374            if (!(*i))
375            {
376                *i = xcalloc(1, sizeof(IntegerFeedbackClassRec));
377                if (!(*i))
378                {
379                    ErrorF("[Xi] Cannot alloc memory for class copy.");
380                    return;
381                }
382            }
383            (*i)->CtrlProc = it->CtrlProc;
384            (*i)->ctrl     = it->ctrl;
385
386            i = &(*i)->next;
387        }
388    } else if (to->intfeed && !from->intfeed)
389    {
390        ClassesPtr classes;
391        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
392        classes->intfeed = to->intfeed;
393        to->intfeed      = NULL;
394    }
395
396    if (from->stringfeed)
397    {
398        StringFeedbackPtr *s, it;
399
400        if (!to->stringfeed)
401        {
402            classes = dixLookupPrivate(&to->devPrivates,
403                                       UnusedClassesPrivateKey);
404            to->stringfeed = classes->stringfeed;
405        }
406
407        s = &to->stringfeed;
408        for (it = from->stringfeed; it; it = it->next)
409        {
410            if (!(*s))
411            {
412                *s = xcalloc(1, sizeof(StringFeedbackClassRec));
413                if (!(*s))
414                {
415                    ErrorF("[Xi] Cannot alloc memory for class copy.");
416                    return;
417                }
418            }
419            (*s)->CtrlProc = it->CtrlProc;
420            (*s)->ctrl     = it->ctrl;
421
422            s = &(*s)->next;
423        }
424    } else if (to->stringfeed && !from->stringfeed)
425    {
426        ClassesPtr classes;
427        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
428        classes->stringfeed = to->stringfeed;
429        to->stringfeed      = NULL;
430    }
431
432    if (from->bell)
433    {
434        BellFeedbackPtr *b, it;
435
436        if (!to->bell)
437        {
438            classes = dixLookupPrivate(&to->devPrivates,
439                                       UnusedClassesPrivateKey);
440            to->bell = classes->bell;
441        }
442
443        b = &to->bell;
444        for (it = from->bell; it; it = it->next)
445        {
446            if (!(*b))
447            {
448                *b = xcalloc(1, sizeof(BellFeedbackClassRec));
449                if (!(*b))
450                {
451                    ErrorF("[Xi] Cannot alloc memory for class copy.");
452                    return;
453                }
454            }
455            (*b)->BellProc = it->BellProc;
456            (*b)->CtrlProc = it->CtrlProc;
457            (*b)->ctrl     = it->ctrl;
458
459            b = &(*b)->next;
460        }
461    } else if (to->bell && !from->bell)
462    {
463        ClassesPtr classes;
464        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
465        classes->bell = to->bell;
466        to->bell      = NULL;
467    }
468
469    if (from->leds)
470    {
471        LedFeedbackPtr *l, it;
472
473        if (!to->leds)
474        {
475            classes = dixLookupPrivate(&to->devPrivates,
476                                       UnusedClassesPrivateKey);
477            to->leds = classes->leds;
478        }
479
480        l = &to->leds;
481        for (it = from->leds; it; it = it->next)
482        {
483            if (!(*l))
484            {
485                *l = xcalloc(1, sizeof(LedFeedbackClassRec));
486                if (!(*l))
487                {
488                    ErrorF("[Xi] Cannot alloc memory for class copy.");
489                    return;
490                }
491            }
492            (*l)->CtrlProc = it->CtrlProc;
493            (*l)->ctrl     = it->ctrl;
494#ifdef XKB
495            if ((*l)->xkb_sli)
496                XkbFreeSrvLedInfo((*l)->xkb_sli);
497            (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
498#endif
499
500            l = &(*l)->next;
501        }
502    } else if (to->leds && !from->leds)
503    {
504        ClassesPtr classes;
505        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
506        classes->leds = to->leds;
507        to->leds      = NULL;
508    }
509}
510
511/**
512 * Copies the CONTENT of the classes of device from into the classes in device
513 * to. From and to are identical after finishing.
514 *
515 * If to does not have classes from currenly has, the classes are stored in
516 * to's devPrivates system. Later, we recover it again from there if needed.
517 * Saves a few memory allocations.
518 */
519
520void
521DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
522{
523    ClassesPtr classes;
524
525    /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
526     * kbdfeed to be set up properly, so let's do the feedback classes first.
527     */
528    DeepCopyFeedbackClasses(from, to);
529
530    if (from->key)
531    {
532        KeyCode             *oldModKeyMap;
533        KeySym              *oldMap;
534#ifdef XKB
535        struct _XkbSrvInfo  *oldXkbInfo;
536#endif
537        if (!to->key)
538        {
539            classes = dixLookupPrivate(&to->devPrivates,
540                                       UnusedClassesPrivateKey);
541            to->key = classes->key;
542            if (!to->key)
543            {
544                to->key = xcalloc(1, sizeof(KeyClassRec));
545                if (!to->key)
546                    FatalError("[Xi] no memory for class shift.\n");
547            } else
548                classes->key = NULL;
549        }
550
551        oldModKeyMap    = to->key->modifierKeyMap;
552        oldMap          = to->key->curKeySyms.map;
553#ifdef XKB
554        oldXkbInfo      = to->key->xkbInfo;
555#endif
556
557        if (!oldMap) /* newly created key struct */
558        {
559            int bytes = (to->key->curKeySyms.maxKeyCode -
560                         to->key->curKeySyms.minKeyCode + 1) *
561                         to->key->curKeySyms.mapWidth;
562            oldMap = (KeySym *)xcalloc(sizeof(KeySym), bytes);
563            memcpy(oldMap, from->key->curKeySyms.map, bytes);
564        }
565
566        to->key->modifierKeyMap = oldModKeyMap;
567        to->key->curKeySyms.map = oldMap;
568#ifdef XKB
569        to->key->xkbInfo        = oldXkbInfo;
570#endif
571
572        CopyKeyClass(from, to);
573    } else if (to->key && !from->key)
574    {
575        ClassesPtr classes;
576        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
577        classes->key = to->key;
578        to->key      = NULL;
579    }
580
581    if (from->valuator)
582    {
583        ValuatorClassPtr v;
584        if (!to->valuator)
585        {
586            classes = dixLookupPrivate(&to->devPrivates,
587                                       UnusedClassesPrivateKey);
588            to->valuator = classes->valuator;
589            if (to->valuator)
590                classes->valuator = NULL;
591        }
592
593        to->valuator = xrealloc(to->valuator, sizeof(ValuatorClassRec) +
594                from->valuator->numAxes * sizeof(AxisInfo) +
595                from->valuator->numAxes * sizeof(unsigned int));
596        v = to->valuator;
597        if (!v)
598            FatalError("[Xi] no memory for class shift.\n");
599
600        v->numAxes = from->valuator->numAxes;
601        v->axes = (AxisInfoPtr)&v[1];
602        memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
603
604        v->axisVal = (int*)(v->axes + from->valuator->numAxes);
605    } else if (to->valuator && !from->valuator)
606    {
607        ClassesPtr classes;
608        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
609        classes->valuator = to->valuator;
610        to->valuator      = NULL;
611    }
612
613    if (from->button)
614    {
615        if (!to->button)
616        {
617            classes = dixLookupPrivate(&to->devPrivates,
618                                       UnusedClassesPrivateKey);
619            to->button = classes->button;
620            if (!to->button)
621            {
622                to->button = xcalloc(1, sizeof(ButtonClassRec));
623                if (!to->button)
624                    FatalError("[Xi] no memory for class shift.\n");
625            } else
626                classes->button = NULL;
627        }
628
629#ifdef XKB
630        if (from->button->xkb_acts)
631        {
632            if (!to->button->xkb_acts)
633            {
634                to->button->xkb_acts = xcalloc(1, sizeof(XkbAction));
635                if (!to->button->xkb_acts)
636                    FatalError("[Xi] not enough memory for xkb_acts.\n");
637            }
638            memcpy(to->button->xkb_acts, from->button->xkb_acts,
639                    sizeof(XkbAction));
640        } else
641            xfree(to->button->xkb_acts);
642#endif
643    } else if (to->button && !from->button)
644    {
645        ClassesPtr classes;
646        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
647        classes->button = to->button;
648        to->button      = NULL;
649    }
650
651
652    /* We can't just copy over the focus class. When an app sets the focus,
653     * it'll do so on the master device. Copying the SDs focus means losing
654     * the focus.
655     * So we only copy the focus class if the device didn't have one,
656     * otherwise we leave it as it is.
657     */
658    if (from->focus)
659    {
660        if (!to->focus)
661        {
662            WindowPtr *oldTrace;
663
664            classes = dixLookupPrivate(&to->devPrivates,
665                                       UnusedClassesPrivateKey);
666            to->focus = classes->focus;
667            if (!to->focus)
668            {
669                to->focus = xcalloc(1, sizeof(FocusClassRec));
670                if (!to->focus)
671                    FatalError("[Xi] no memory for class shift.\n");
672            } else
673                classes->focus = NULL;
674
675            oldTrace = to->focus->trace;
676            memcpy(to->focus, from->focus, sizeof(FocusClassRec));
677            to->focus->trace = xrealloc(oldTrace,
678                                  to->focus->traceSize * sizeof(WindowPtr));
679            if (!to->focus->trace && to->focus->traceSize)
680                FatalError("[Xi] no memory for trace.\n");
681            memcpy(to->focus->trace, from->focus->trace,
682                    from->focus->traceSize * sizeof(WindowPtr));
683        }
684    } else if (to->focus)
685    {
686        ClassesPtr classes;
687        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
688        classes->focus = to->focus;
689        to->focus      = NULL;
690    }
691
692    if (from->proximity)
693    {
694        if (!to->proximity)
695        {
696            classes = dixLookupPrivate(&to->devPrivates,
697                                       UnusedClassesPrivateKey);
698            to->proximity = classes->proximity;
699            if (!to->proximity)
700            {
701                to->proximity = xcalloc(1, sizeof(ProximityClassRec));
702                if (!to->proximity)
703                    FatalError("[Xi] no memory for class shift.\n");
704            } else
705                classes->proximity = NULL;
706        }
707        memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
708    } else if (to->proximity)
709    {
710        ClassesPtr classes;
711        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
712        classes->proximity = to->proximity;
713        to->proximity      = NULL;
714    }
715
716    if (from->absolute)
717    {
718        if (!to->absolute)
719        {
720            classes = dixLookupPrivate(&to->devPrivates,
721                                       UnusedClassesPrivateKey);
722            to->absolute = classes->absolute;
723            if (!to->absolute)
724            {
725                to->absolute = xcalloc(1, sizeof(AbsoluteClassRec));
726                if (!to->absolute)
727                    FatalError("[Xi] no memory for class shift.\n");
728            } else
729                classes->absolute = NULL;
730        }
731        memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec));
732    } else if (to->absolute)
733    {
734        ClassesPtr classes;
735        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
736        classes->absolute = to->absolute;
737        to->absolute      = NULL;
738    }
739}
740
741
742/**
743 * Update the device state according to the data in the event.
744 *
745 * return values are
746 *   DEFAULT ... process as normal
747 *   DONT_PROCESS ... return immediately from caller
748 *   IS_REPEAT .. event is a repeat event.
749 */
750#define DEFAULT 0
751#define DONT_PROCESS 1
752#define IS_REPEAT 2
753int
754UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
755{
756    int i;
757    int key = 0,
758        bit = 0;
759
760    KeyClassPtr k       = NULL;
761    ButtonClassPtr b    = NULL;
762    ValuatorClassPtr v  = NULL;
763    deviceValuator *xV  = (deviceValuator *) xE;
764    BYTE *kptr          = NULL;
765    CARD16 modifiers    = 0,
766           mask         = 0;
767
768    /* currently no other generic event modifies the device */
769    if (xE->u.u.type == GenericEvent)
770        return DEFAULT;
771
772    k = device->key;
773    v = device->valuator;
774    b = device->button;
775
776
777    if (xE->u.u.type != DeviceValuator)
778    {
779        key = xE->u.u.detail;
780        bit = 1 << (key & 7);
781    }
782
783    /* Update device axis */
784    /* Don't update valuators for the VCP, it never sends XI events anyway */
785    for (i = 1; !device->isMaster && i < count; i++) {
786	if ((++xV)->type == DeviceValuator) {
787	    int *axisvals;
788            int first = xV->first_valuator;
789            BOOL change = FALSE;
790
791
792	    if (xV->num_valuators &&
793                (!v || (xV->num_valuators &&
794                      (first + xV->num_valuators > v->numAxes))))
795		FatalError("Bad valuators reported for device %s\n",
796			   device->name);
797	    if (v && v->axisVal) {
798                /* v->axisVal is always in absolute coordinates. Only the
799                 * delivery mode changes.
800                 * If device is mode Absolute
801                 *     dev = event
802                 * If device is mode Relative
803                 *      swap = (event - device)
804                 *      dev = event
805                 *      event = delta
806                 */
807                int delta;
808                axisvals = v->axisVal;
809                if (v->mode == Relative) /* device reports relative */
810                    change = TRUE;
811
812                switch (xV->num_valuators) {
813                    case 6:
814                        if (change) delta = xV->valuator5 - *(axisvals + first + 5);
815                        *(axisvals + first + 5) = xV->valuator5;
816                        if (change) xV->valuator5 = delta;
817                    case 5:
818                        if (change) delta = xV->valuator4 - *(axisvals + first + 4);
819                        *(axisvals + first + 4) = xV->valuator4;
820                        if (change) xV->valuator4 = delta;
821                    case 4:
822                        if (change) delta = xV->valuator3 - *(axisvals + first + 3);
823                        *(axisvals + first + 3) = xV->valuator3;
824                        if (change) xV->valuator3 = delta;
825                    case 3:
826                        if (change) delta = xV->valuator2 - *(axisvals + first + 2);
827                        *(axisvals + first + 2) = xV->valuator2;
828                        if (change) xV->valuator2 = delta;
829                    case 2:
830                        if (change) delta = xV->valuator1 - *(axisvals + first + 1);
831                        *(axisvals + first + 1) = xV->valuator1;
832                        if (change) xV->valuator1 = delta;
833                    case 1:
834                        if (change) delta = xV->valuator0 - *(axisvals + first);
835                        *(axisvals + first) = xV->valuator0;
836                        if (change) xV->valuator0 = delta;
837                    case 0:
838                    default:
839                        break;
840                }
841	    }
842	}
843    }
844
845    if (xE->u.u.type == DeviceKeyPress) {
846        if (!k)
847            return DONT_PROCESS;
848
849	modifiers = k->modifierMap[key];
850	kptr = &k->down[key >> 3];
851	if (*kptr & bit) {	/* allow ddx to generate multiple downs */
852	    return IS_REPEAT;
853	}
854	if (device->valuator)
855	    device->valuator->motionHintWindow = NullWindow;
856	*kptr |= bit;
857	k->prev_state = k->state;
858	for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
859	    if (mask & modifiers) {
860		/* This key affects modifier "i" */
861		k->modifierKeyCount[i]++;
862		k->state |= mask;
863		modifiers &= ~mask;
864	    }
865	}
866    } else if (xE->u.u.type == DeviceKeyRelease) {
867        if (!k)
868            return DONT_PROCESS;
869
870	kptr = &k->down[key >> 3];
871	if (!(*kptr & bit))	/* guard against duplicates */
872	    return DONT_PROCESS;
873	modifiers = k->modifierMap[key];
874	if (device->valuator)
875	    device->valuator->motionHintWindow = NullWindow;
876	*kptr &= ~bit;
877	k->prev_state = k->state;
878	for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
879	    if (mask & modifiers) {
880		/* This key affects modifier "i" */
881		if (--k->modifierKeyCount[i] <= 0) {
882		    k->modifierKeyCount[i] = 0;
883		    k->state &= ~mask;
884		}
885		modifiers &= ~mask;
886	    }
887	}
888    } else if (xE->u.u.type == DeviceButtonPress) {
889        if (!b)
890            return DONT_PROCESS;
891
892        kptr = &b->down[key >> 3];
893        if ((*kptr & bit) != 0)
894            return DONT_PROCESS;
895        *kptr |= bit;
896	if (device->valuator)
897	    device->valuator->motionHintWindow = NullWindow;
898        if (!b->map[key])
899            return DONT_PROCESS;
900        b->buttonsDown++;
901	b->motionMask = DeviceButtonMotionMask;
902        if (b->map[key] <= 5)
903	    b->state |= (Button1Mask >> 1) << b->map[key];
904	SetMaskForEvent(device->id, Motion_Filter(b), DeviceMotionNotify);
905    } else if (xE->u.u.type == DeviceButtonRelease) {
906        if (!b)
907            return DONT_PROCESS;
908
909        kptr = &b->down[key>>3];
910        if (!(*kptr & bit))
911            return DONT_PROCESS;
912        if (device->isMaster) {
913            DeviceIntPtr sd;
914
915            /*
916             * Leave the button down if any slave has the
917             * button still down. Note that this depends on the
918             * event being delivered through the slave first
919             */
920            for (sd = inputInfo.devices; sd; sd = sd->next) {
921                if (sd->isMaster || sd->u.master != device)
922                    continue;
923                if ((sd->button->down[key>>3] & bit) != 0)
924                    return DONT_PROCESS;
925            }
926        }
927        *kptr &= ~bit;
928	if (device->valuator)
929	    device->valuator->motionHintWindow = NullWindow;
930        if (!b->map[key])
931            return DONT_PROCESS;
932        if (b->buttonsDown >= 1 && !--b->buttonsDown)
933	    b->motionMask = 0;
934	if (b->map[key] <= 5)
935	    b->state &= ~((Button1Mask >> 1) << b->map[key]);
936	SetMaskForEvent(device->id, Motion_Filter(b), DeviceMotionNotify);
937    } else if (xE->u.u.type == ProximityIn)
938	device->valuator->mode &= ~OutOfProximity;
939    else if (xE->u.u.type == ProximityOut)
940	device->valuator->mode |= OutOfProximity;
941
942    return DEFAULT;
943}
944
945/**
946 * Main device event processing function.
947 * Called from when processing the events from the event queue.
948 *
949 */
950void
951ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
952{
953    int i;
954    CARD16 modifiers;
955    GrabPtr grab = device->deviceGrab.grab;
956    Bool deactivateDeviceGrab = FALSE;
957    int key = 0, rootX, rootY;
958    ButtonClassPtr b;
959    KeyClassPtr k;
960    ValuatorClassPtr v;
961    deviceValuator *xV  = (deviceValuator *) xE;
962    int ret = 0;
963    int state;
964    DeviceIntPtr mouse = NULL, kbd = NULL;
965
966    if (IsPointerDevice(device))
967    {
968        kbd = GetPairedDevice(device);
969        mouse = device;
970        if (!kbd->key) /* can happen with floating SDs */
971            kbd = NULL;
972    } else
973    {
974        mouse = GetPairedDevice(device);
975        kbd = device;
976        if (!mouse->valuator || !mouse->button) /* may be float. SDs */
977            mouse = NULL;
978    }
979
980    /* State needs to be assembled BEFORE the device is updated. */
981    state = (kbd) ? kbd->key->state : 0;
982    state |= (mouse) ? (mouse->button->state) : 0;
983
984    ret = UpdateDeviceState(device, xE, count);
985    if (ret == DONT_PROCESS)
986        return;
987
988    v = device->valuator;
989    b = device->button;
990    k = device->key;
991
992    if (device->isMaster)
993        CheckMotion(xE, device);
994
995    if (xE->u.u.type != DeviceValuator && xE->u.u.type != GenericEvent) {
996	GetSpritePosition(device, &rootX, &rootY);
997	xE->u.keyButtonPointer.rootX = rootX;
998	xE->u.keyButtonPointer.rootY = rootY;
999	NoticeEventTime(xE);
1000
1001        xE->u.keyButtonPointer.state = state;
1002
1003        key = xE->u.u.detail;
1004    }
1005    if (DeviceEventCallback) {
1006	DeviceEventInfoRec eventinfo;
1007
1008	eventinfo.events = (xEventPtr) xE;
1009	eventinfo.count = count;
1010	CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
1011    }
1012
1013    /* Valuator event handling */
1014    /* Don't care about valuators for the VCP, it never sends XI events */
1015
1016    for (i = 1; !device->isMaster && i < count; i++) {
1017	if ((++xV)->type == DeviceValuator) {
1018	    int first = xV->first_valuator;
1019	    if (xV->num_valuators
1020		&& (!v
1021		    || (xV->num_valuators
1022			&& (first + xV->num_valuators > v->numAxes))))
1023		FatalError("Bad valuators reported for device %s\n",
1024			   device->name);
1025	    xV->device_state = 0;
1026	    if (k)
1027		xV->device_state |= k->state;
1028	    if (b)
1029		xV->device_state |= b->state;
1030	}
1031    }
1032
1033    if (xE->u.u.type == DeviceKeyPress) {
1034        if (ret == IS_REPEAT) {	/* allow ddx to generate multiple downs */
1035            modifiers = k->modifierMap[key];
1036	    if (!modifiers) {
1037		xE->u.u.type = DeviceKeyRelease;
1038		ProcessOtherEvent(xE, device, count);
1039		xE->u.u.type = DeviceKeyPress;
1040		/* release can have side effects, don't fall through */
1041		ProcessOtherEvent(xE, device, count);
1042	    }
1043	    return;
1044	}
1045	if (!grab && CheckDeviceGrabs(device, xE, 0, count)) {
1046	    device->deviceGrab.activatingKey = key;
1047	    return;
1048	}
1049    } else if (xE->u.u.type == DeviceKeyRelease) {
1050	if (device->deviceGrab.fromPassiveGrab &&
1051            (key == device->deviceGrab.activatingKey))
1052	    deactivateDeviceGrab = TRUE;
1053    } else if (xE->u.u.type == DeviceButtonPress) {
1054	xE->u.u.detail = b->map[key];
1055	if (xE->u.u.detail == 0) {
1056	    xE->u.u.detail = key;
1057	    return;
1058	}
1059        if (!grab && CheckDeviceGrabs(device, xE, 0, count))
1060        {
1061            /* if a passive grab was activated, the event has been sent
1062             * already */
1063            return;
1064        }
1065
1066    } else if (xE->u.u.type == DeviceButtonRelease) {
1067	xE->u.u.detail = b->map[key];
1068	if (xE->u.u.detail == 0) {
1069	    xE->u.u.detail = key;
1070	    return;
1071	}
1072        if (!b->buttonsDown && device->deviceGrab.fromPassiveGrab)
1073            deactivateDeviceGrab = TRUE;
1074    }
1075
1076    if (grab)
1077        DeliverGrabbedEvent(xE, device, deactivateDeviceGrab, count);
1078    else if (device->focus && !IsPointerEvent(xE))
1079	DeliverFocusedEvent(device, xE, GetSpriteWindow(device), count);
1080    else
1081	DeliverDeviceEvents(GetSpriteWindow(device), xE, NullGrab, NullWindow,
1082			    device, count);
1083
1084    if (deactivateDeviceGrab == TRUE)
1085	(*device->deviceGrab.DeactivateGrab) (device);
1086    xE->u.u.detail = key;
1087}
1088
1089_X_EXPORT int
1090InitProximityClassDeviceStruct(DeviceIntPtr dev)
1091{
1092    ProximityClassPtr proxc;
1093
1094    proxc = (ProximityClassPtr) xalloc(sizeof(ProximityClassRec));
1095    if (!proxc)
1096	return FALSE;
1097    dev->proximity = proxc;
1098    return TRUE;
1099}
1100
1101/**
1102 * Initialise the device's valuators. The memory must already be allocated,
1103 * this function merely inits the matching axis (specified through axnum) to
1104 * sane values.
1105 *
1106 * It is a condition that (minval < maxval).
1107 *
1108 * @see InitValuatorClassDeviceStruct
1109 */
1110_X_EXPORT void
1111InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, int minval, int maxval,
1112		       int resolution, int min_res, int max_res)
1113{
1114    AxisInfoPtr ax;
1115
1116    if (!dev || !dev->valuator || minval > maxval)
1117        return;
1118
1119    ax = dev->valuator->axes + axnum;
1120
1121    ax->min_value = minval;
1122    ax->max_value = maxval;
1123    ax->resolution = resolution;
1124    ax->min_resolution = min_res;
1125    ax->max_resolution = max_res;
1126}
1127
1128static void
1129FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
1130		     ButtonClassPtr b, ValuatorClassPtr v, int first)
1131{
1132    ev->type = DeviceStateNotify;
1133    ev->deviceid = dev->id;
1134    ev->time = currentTime.milliseconds;
1135    ev->classes_reported = 0;
1136    ev->num_keys = 0;
1137    ev->num_buttons = 0;
1138    ev->num_valuators = 0;
1139
1140    if (b) {
1141	ev->classes_reported |= (1 << ButtonClass);
1142	ev->num_buttons = b->numButtons;
1143	memcpy((char*)ev->buttons, (char*)b->down, 4);
1144    } else if (k) {
1145	ev->classes_reported |= (1 << KeyClass);
1146	ev->num_keys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode;
1147	memmove((char *)&ev->keys[0], (char *)k->down, 4);
1148    }
1149    if (v) {
1150	int nval = v->numAxes - first;
1151
1152	ev->classes_reported |= (1 << ValuatorClass);
1153	ev->classes_reported |= (dev->valuator->mode << ModeBitsShift);
1154	ev->num_valuators = nval < 3 ? nval : 3;
1155	switch (ev->num_valuators) {
1156	case 3:
1157	    ev->valuator2 = v->axisVal[first + 2];
1158	case 2:
1159	    ev->valuator1 = v->axisVal[first + 1];
1160	case 1:
1161	    ev->valuator0 = v->axisVal[first];
1162	    break;
1163	}
1164    }
1165}
1166
1167static void
1168FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
1169		  int first)
1170{
1171    int nval = v->numAxes - first;
1172
1173    ev->type = DeviceValuator;
1174    ev->deviceid = dev->id;
1175    ev->num_valuators = nval < 3 ? nval : 3;
1176    ev->first_valuator = first;
1177    switch (ev->num_valuators) {
1178    case 3:
1179	ev->valuator2 = v->axisVal[first + 2];
1180    case 2:
1181	ev->valuator1 = v->axisVal[first + 1];
1182    case 1:
1183	ev->valuator0 = v->axisVal[first];
1184	break;
1185    }
1186    first += ev->num_valuators;
1187}
1188
1189void
1190DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
1191		 WindowPtr pWin)
1192{
1193    deviceFocus event;
1194
1195    if (type == FocusIn)
1196	type = DeviceFocusIn;
1197    else
1198	type = DeviceFocusOut;
1199
1200    event.deviceid = dev->id;
1201    event.mode = mode;
1202    event.type = type;
1203    event.detail = detail;
1204    event.window = pWin->drawable.id;
1205    event.time = currentTime.milliseconds;
1206
1207    (void)DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
1208				DeviceFocusChangeMask, NullGrab, dev->id);
1209
1210    if ((type == DeviceFocusIn) &&
1211	(wOtherInputMasks(pWin)) &&
1212	(wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
1213    {
1214	int evcount = 1;
1215	deviceStateNotify *ev, *sev;
1216	deviceKeyStateNotify *kev;
1217	deviceButtonStateNotify *bev;
1218
1219	KeyClassPtr k;
1220	ButtonClassPtr b;
1221	ValuatorClassPtr v;
1222	int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
1223
1224	if ((b = dev->button) != NULL) {
1225	    nbuttons = b->numButtons;
1226	    if (nbuttons > 32)
1227		evcount++;
1228	}
1229	if ((k = dev->key) != NULL) {
1230	    nkeys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode;
1231	    if (nkeys > 32)
1232		evcount++;
1233	    if (nbuttons > 0) {
1234		evcount++;
1235	    }
1236	}
1237	if ((v = dev->valuator) != NULL) {
1238	    nval = v->numAxes;
1239
1240	    if (nval > 3)
1241		evcount++;
1242	    if (nval > 6) {
1243		if (!(k && b))
1244		    evcount++;
1245		if (nval > 9)
1246		    evcount += ((nval - 7) / 3);
1247	    }
1248	}
1249
1250	sev = ev = (deviceStateNotify *) xalloc(evcount * sizeof(xEvent));
1251	FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
1252
1253	if (b != NULL) {
1254	    FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
1255	    first += 3;
1256	    nval -= 3;
1257	    if (nbuttons > 32) {
1258		(ev - 1)->deviceid |= MORE_EVENTS;
1259		bev = (deviceButtonStateNotify *) ev++;
1260		bev->type = DeviceButtonStateNotify;
1261		bev->deviceid = dev->id;
1262		memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
1263	    }
1264	    if (nval > 0) {
1265		(ev - 1)->deviceid |= MORE_EVENTS;
1266		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1267		first += 3;
1268		nval -= 3;
1269	    }
1270	}
1271
1272	if (k != NULL) {
1273	    FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
1274	    first += 3;
1275	    nval -= 3;
1276	    if (nkeys > 32) {
1277		(ev - 1)->deviceid |= MORE_EVENTS;
1278		kev = (deviceKeyStateNotify *) ev++;
1279		kev->type = DeviceKeyStateNotify;
1280		kev->deviceid = dev->id;
1281		memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
1282	    }
1283	    if (nval > 0) {
1284		(ev - 1)->deviceid |= MORE_EVENTS;
1285		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1286		first += 3;
1287		nval -= 3;
1288	    }
1289	}
1290
1291	while (nval > 0) {
1292	    FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
1293	    first += 3;
1294	    nval -= 3;
1295	    if (nval > 0) {
1296		(ev - 1)->deviceid |= MORE_EVENTS;
1297		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1298		first += 3;
1299		nval -= 3;
1300	    }
1301	}
1302
1303	(void)DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
1304				    DeviceStateNotifyMask, NullGrab, dev->id);
1305	xfree(sev);
1306    }
1307}
1308
1309int
1310GrabButton(ClientPtr client, DeviceIntPtr dev, BYTE this_device_mode,
1311	   BYTE other_devices_mode, CARD16 modifiers,
1312	   DeviceIntPtr modifier_device, CARD8 button, Window grabWindow,
1313	   BOOL ownerEvents, Cursor rcursor, Window rconfineTo, Mask eventMask)
1314{
1315    WindowPtr pWin, confineTo;
1316    CursorPtr cursor;
1317    GrabPtr grab;
1318    Mask access_mode = DixGrabAccess;
1319    int rc;
1320
1321    if ((this_device_mode != GrabModeSync) &&
1322	(this_device_mode != GrabModeAsync)) {
1323	client->errorValue = this_device_mode;
1324	return BadValue;
1325    }
1326    if ((other_devices_mode != GrabModeSync) &&
1327	(other_devices_mode != GrabModeAsync)) {
1328	client->errorValue = other_devices_mode;
1329	return BadValue;
1330    }
1331    if ((modifiers != AnyModifier) && (modifiers & ~AllModifiersMask)) {
1332	client->errorValue = modifiers;
1333	return BadValue;
1334    }
1335    if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) {
1336	client->errorValue = ownerEvents;
1337	return BadValue;
1338    }
1339    rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
1340    if (rc != Success)
1341	return rc;
1342    if (rconfineTo == None)
1343	confineTo = NullWindow;
1344    else {
1345	rc = dixLookupWindow(&confineTo, rconfineTo, client, DixSetAttrAccess);
1346	if (rc != Success)
1347	    return rc;
1348    }
1349    if (rcursor == None)
1350	cursor = NullCursor;
1351    else {
1352	rc = dixLookupResource((pointer *)&cursor, rcursor, RT_CURSOR,
1353			       client, DixUseAccess);
1354	if (rc != Success)
1355	{
1356	    client->errorValue = rcursor;
1357	    return (rc == BadValue) ? BadCursor : rc;
1358	}
1359	access_mode |= DixForceAccess;
1360    }
1361    if (this_device_mode == GrabModeSync || other_devices_mode == GrabModeSync)
1362	access_mode |= DixFreezeAccess;
1363    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1364    if (rc != Success)
1365	return rc;
1366
1367    grab = CreateGrab(client->index, dev, pWin, eventMask,
1368		      (Bool) ownerEvents, (Bool) this_device_mode,
1369		      (Bool) other_devices_mode, modifier_device, modifiers,
1370		      DeviceButtonPress, button, confineTo, cursor);
1371    if (!grab)
1372	return BadAlloc;
1373    return AddPassiveGrabToList(client, grab);
1374}
1375
1376int
1377GrabKey(ClientPtr client, DeviceIntPtr dev, BYTE this_device_mode,
1378	BYTE other_devices_mode, CARD16 modifiers,
1379	DeviceIntPtr modifier_device, CARD8 key, Window grabWindow,
1380	BOOL ownerEvents, Mask mask)
1381{
1382    WindowPtr pWin;
1383    GrabPtr grab;
1384    KeyClassPtr k = dev->key;
1385    Mask access_mode = DixGrabAccess;
1386    int rc;
1387
1388    if (k == NULL)
1389	return BadMatch;
1390    if ((other_devices_mode != GrabModeSync) &&
1391	(other_devices_mode != GrabModeAsync)) {
1392	client->errorValue = other_devices_mode;
1393	return BadValue;
1394    }
1395    if ((this_device_mode != GrabModeSync) &&
1396	(this_device_mode != GrabModeAsync)) {
1397	client->errorValue = this_device_mode;
1398	return BadValue;
1399    }
1400    if (((key > k->curKeySyms.maxKeyCode) || (key < k->curKeySyms.minKeyCode))
1401	&& (key != AnyKey)) {
1402	client->errorValue = key;
1403	return BadValue;
1404    }
1405    if ((modifiers != AnyModifier) && (modifiers & ~AllModifiersMask)) {
1406	client->errorValue = modifiers;
1407	return BadValue;
1408    }
1409    if ((ownerEvents != xTrue) && (ownerEvents != xFalse)) {
1410	client->errorValue = ownerEvents;
1411	return BadValue;
1412    }
1413    rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
1414    if (rc != Success)
1415	return rc;
1416    if (this_device_mode == GrabModeSync || other_devices_mode == GrabModeSync)
1417	access_mode |= DixFreezeAccess;
1418    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1419    if (rc != Success)
1420	return rc;
1421
1422    grab = CreateGrab(client->index, dev, pWin,
1423		      mask, ownerEvents, this_device_mode, other_devices_mode,
1424		      modifier_device, modifiers, DeviceKeyPress, key,
1425		      NullWindow, NullCursor);
1426    if (!grab)
1427	return BadAlloc;
1428    return AddPassiveGrabToList(client, grab);
1429}
1430
1431int
1432SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
1433		Mask mask, Mask exclusivemasks, Mask validmasks)
1434{
1435    int mskidx = dev->id;
1436    int i, ret;
1437    Mask check;
1438    InputClientsPtr others;
1439
1440    if (mask & ~validmasks) {
1441	client->errorValue = mask;
1442	return BadValue;
1443    }
1444    check = (mask & exclusivemasks);
1445    if (wOtherInputMasks(pWin)) {
1446	if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {	/* It is illegal for two different
1447									 * clients to select on any of the
1448									 * events for maskcheck. However,
1449									 * it is OK, for some client to
1450									 * continue selecting on one of those
1451									 * events.  */
1452	    for (others = wOtherInputMasks(pWin)->inputClients; others;
1453		 others = others->next) {
1454		if (!SameClient(others, client) && (check &
1455						    others->mask[mskidx]))
1456		    return BadAccess;
1457	    }
1458	}
1459	for (others = wOtherInputMasks(pWin)->inputClients; others;
1460	     others = others->next) {
1461	    if (SameClient(others, client)) {
1462		check = others->mask[mskidx];
1463		others->mask[mskidx] = mask;
1464		if (mask == 0) {
1465		    for (i = 0; i < EMASKSIZE; i++)
1466			if (i != mskidx && others->mask[i] != 0)
1467			    break;
1468		    if (i == EMASKSIZE) {
1469			RecalculateDeviceDeliverableEvents(pWin);
1470			if (ShouldFreeInputMasks(pWin, FALSE))
1471			    FreeResource(others->resource, RT_NONE);
1472			return Success;
1473		    }
1474		}
1475		goto maskSet;
1476	    }
1477	}
1478    }
1479    check = 0;
1480    if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
1481	return ret;
1482  maskSet:
1483    if (dev->valuator)
1484	if ((dev->valuator->motionHintWindow == pWin) &&
1485	    (mask & DevicePointerMotionHintMask) &&
1486	    !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
1487	    dev->valuator->motionHintWindow = NullWindow;
1488    RecalculateDeviceDeliverableEvents(pWin);
1489    return Success;
1490}
1491
1492int
1493AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
1494{
1495    InputClientsPtr others;
1496
1497    if (!pWin->optional && !MakeWindowOptional(pWin))
1498	return BadAlloc;
1499    others = xcalloc(1, sizeof(InputClients));
1500    if (!others)
1501	return BadAlloc;
1502    if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
1503	return BadAlloc;
1504    others->mask[mskidx] = mask;
1505    others->resource = FakeClientID(client->index);
1506    others->next = pWin->optional->inputMasks->inputClients;
1507    pWin->optional->inputMasks->inputClients = others;
1508    if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
1509	return BadAlloc;
1510    return Success;
1511}
1512
1513static Bool
1514MakeInputMasks(WindowPtr pWin)
1515{
1516    struct _OtherInputMasks *imasks;
1517
1518    imasks = xcalloc(1, sizeof(struct _OtherInputMasks));
1519    if (!imasks)
1520	return FALSE;
1521    pWin->optional->inputMasks = imasks;
1522    return TRUE;
1523}
1524
1525void
1526RecalculateDeviceDeliverableEvents(WindowPtr pWin)
1527{
1528    InputClientsPtr others;
1529    struct _OtherInputMasks *inputMasks;	/* default: NULL */
1530    WindowPtr pChild, tmp;
1531    int i;
1532
1533    pChild = pWin;
1534    while (1) {
1535	if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
1536	    for (others = inputMasks->inputClients; others;
1537		 others = others->next) {
1538		for (i = 0; i < EMASKSIZE; i++)
1539		    inputMasks->inputEvents[i] |= others->mask[i];
1540	    }
1541	    for (i = 0; i < EMASKSIZE; i++)
1542		inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
1543	    for (tmp = pChild->parent; tmp; tmp = tmp->parent)
1544		if (wOtherInputMasks(tmp))
1545		    for (i = 0; i < EMASKSIZE; i++)
1546			inputMasks->deliverableEvents[i] |=
1547			    (wOtherInputMasks(tmp)->deliverableEvents[i]
1548			     & ~inputMasks->
1549			     dontPropagateMask[i] & PropagateMask[i]);
1550	}
1551	if (pChild->firstChild) {
1552	    pChild = pChild->firstChild;
1553	    continue;
1554	}
1555	while (!pChild->nextSib && (pChild != pWin))
1556	    pChild = pChild->parent;
1557	if (pChild == pWin)
1558	    break;
1559	pChild = pChild->nextSib;
1560    }
1561}
1562
1563int
1564InputClientGone(WindowPtr pWin, XID id)
1565{
1566    InputClientsPtr other, prev;
1567
1568    if (!wOtherInputMasks(pWin))
1569	return (Success);
1570    prev = 0;
1571    for (other = wOtherInputMasks(pWin)->inputClients; other;
1572	 other = other->next) {
1573	if (other->resource == id) {
1574	    if (prev) {
1575		prev->next = other->next;
1576		xfree(other);
1577	    } else if (!(other->next)) {
1578		if (ShouldFreeInputMasks(pWin, TRUE)) {
1579		    wOtherInputMasks(pWin)->inputClients = other->next;
1580		    xfree(wOtherInputMasks(pWin));
1581		    pWin->optional->inputMasks = (OtherInputMasks *) NULL;
1582		    CheckWindowOptionalNeed(pWin);
1583		    xfree(other);
1584		} else {
1585		    other->resource = FakeClientID(0);
1586		    if (!AddResource(other->resource, RT_INPUTCLIENT,
1587				     (pointer) pWin))
1588			return BadAlloc;
1589		}
1590	    } else {
1591		wOtherInputMasks(pWin)->inputClients = other->next;
1592		xfree(other);
1593	    }
1594	    RecalculateDeviceDeliverableEvents(pWin);
1595	    return (Success);
1596	}
1597	prev = other;
1598    }
1599    FatalError("client not on device event list");
1600}
1601
1602int
1603SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
1604	  xEvent * ev, Mask mask, int count)
1605{
1606    WindowPtr pWin;
1607    WindowPtr effectiveFocus = NullWindow;	/* only set if dest==InputFocus */
1608    WindowPtr spriteWin = GetSpriteWindow(d);
1609
1610    if (dest == PointerWindow)
1611	pWin = spriteWin;
1612    else if (dest == InputFocus) {
1613	WindowPtr inputFocus;
1614
1615	if (!d->focus)
1616	    inputFocus = spriteWin;
1617	else
1618	    inputFocus = d->focus->win;
1619
1620	if (inputFocus == FollowKeyboardWin)
1621	    inputFocus = inputInfo.keyboard->focus->win;
1622
1623	if (inputFocus == NoneWin)
1624	    return Success;
1625
1626	/* If the input focus is PointerRootWin, send the event to where
1627	 * the pointer is if possible, then perhaps propogate up to root. */
1628	if (inputFocus == PointerRootWin)
1629	    inputFocus = GetCurrentRootWindow(d);
1630
1631	if (IsParent(inputFocus, spriteWin)) {
1632	    effectiveFocus = inputFocus;
1633	    pWin = spriteWin;
1634	} else
1635	    effectiveFocus = pWin = inputFocus;
1636    } else
1637	dixLookupWindow(&pWin, dest, client, DixSendAccess);
1638    if (!pWin)
1639	return BadWindow;
1640    if ((propagate != xFalse) && (propagate != xTrue)) {
1641	client->errorValue = propagate;
1642	return BadValue;
1643    }
1644    ev->u.u.type |= 0x80;
1645    if (propagate) {
1646	for (; pWin; pWin = pWin->parent) {
1647	    if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab, d->id))
1648		return Success;
1649	    if (pWin == effectiveFocus)
1650		return Success;
1651	    if (wOtherInputMasks(pWin))
1652		mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
1653	    if (!mask)
1654		break;
1655	}
1656    } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
1657	(void)(DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab, d->id));
1658    return Success;
1659}
1660
1661int
1662SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
1663{
1664    int i;
1665    ButtonClassPtr b = dev->button;
1666
1667    if (b == NULL)
1668	return BadMatch;
1669
1670    if (nElts != b->numButtons) {
1671	client->errorValue = nElts;
1672	return BadValue;
1673    }
1674    if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
1675	return BadValue;
1676    for (i = 0; i < nElts; i++)
1677	if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
1678	    return MappingBusy;
1679    for (i = 0; i < nElts; i++)
1680	b->map[i + 1] = map[i];
1681    return Success;
1682}
1683
1684int
1685SetModifierMapping(ClientPtr client, DeviceIntPtr dev, int len, int rlen,
1686		   int numKeyPerModifier, KeyCode * inputMap, KeyClassPtr * k)
1687{
1688    KeyCode *map = NULL;
1689    int inputMapLen;
1690    int i;
1691
1692    *k = dev->key;
1693    if (*k == NULL)
1694	return BadMatch;
1695    if (len != ((numKeyPerModifier << 1) + rlen))
1696	return BadLength;
1697
1698    inputMapLen = 8 * numKeyPerModifier;
1699
1700    /*
1701     *  Now enforce the restriction that "all of the non-zero keycodes must be
1702     *  in the range specified by min-keycode and max-keycode in the
1703     *  connection setup (else a Value error)"
1704     */
1705    i = inputMapLen;
1706    while (i--) {
1707	if (inputMap[i]
1708	    && (inputMap[i] < (*k)->curKeySyms.minKeyCode
1709		|| inputMap[i] > (*k)->curKeySyms.maxKeyCode)) {
1710	    client->errorValue = inputMap[i];
1711	    return -1;	/* BadValue collides with MappingFailed */
1712	}
1713    }
1714
1715    /*
1716     *  Now enforce the restriction that none of the old or new
1717     *  modifier keys may be down while we change the mapping,  and
1718     *  that the DDX layer likes the choice.
1719     */
1720    if (!AllModifierKeysAreUp(dev, (*k)->modifierKeyMap,
1721			      (int)(*k)->maxKeysPerModifier, inputMap,
1722			      (int)numKeyPerModifier)
1723	|| !AllModifierKeysAreUp(dev, inputMap, (int)numKeyPerModifier,
1724				 (*k)->modifierKeyMap,
1725				 (int)(*k)->maxKeysPerModifier)) {
1726	return MappingBusy;
1727    } else {
1728	for (i = 0; i < inputMapLen; i++) {
1729	    if (inputMap[i] && !LegalModifier(inputMap[i], dev)) {
1730		return MappingFailed;
1731	    }
1732	}
1733    }
1734
1735    /*
1736     *  Now build the keyboard's modifier bitmap from the
1737     *  list of keycodes.
1738     */
1739    if (inputMapLen) {
1740	map = (KeyCode *) xalloc(inputMapLen);
1741	if (!map)
1742	    return BadAlloc;
1743    }
1744    if ((*k)->modifierKeyMap)
1745	xfree((*k)->modifierKeyMap);
1746    if (inputMapLen) {
1747	(*k)->modifierKeyMap = map;
1748	memmove((char *)(*k)->modifierKeyMap, (char *)inputMap, inputMapLen);
1749    } else
1750	(*k)->modifierKeyMap = NULL;
1751
1752    (*k)->maxKeysPerModifier = numKeyPerModifier;
1753    for (i = 0; i < MAP_LENGTH; i++)
1754	(*k)->modifierMap[i] = 0;
1755    for (i = 0; i < inputMapLen; i++)
1756	if (inputMap[i]) {
1757	    (*k)->modifierMap[inputMap[i]]
1758		|= (1 << (i / (*k)->maxKeysPerModifier));
1759	}
1760
1761    return (MappingSuccess);
1762}
1763
1764void
1765SendDeviceMappingNotify(ClientPtr client, CARD8 request,
1766			KeyCode firstKeyCode, CARD8 count, DeviceIntPtr dev)
1767{
1768    xEvent event;
1769    deviceMappingNotify *ev = (deviceMappingNotify *) & event;
1770
1771    ev->type = DeviceMappingNotify;
1772    ev->request = request;
1773    ev->deviceid = dev->id;
1774    ev->time = currentTime.milliseconds;
1775    if (request == MappingKeyboard) {
1776	ev->firstKeyCode = firstKeyCode;
1777	ev->count = count;
1778    }
1779
1780#ifdef XKB
1781    if (!noXkbExtension && (request == MappingKeyboard ||
1782                            request == MappingModifier))
1783        XkbApplyMappingChange(dev, request, firstKeyCode, count, client);
1784#endif
1785
1786    SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) ev, 1);
1787}
1788
1789int
1790ChangeKeyMapping(ClientPtr client,
1791		 DeviceIntPtr dev,
1792		 unsigned len,
1793		 int type,
1794		 KeyCode firstKeyCode,
1795		 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
1796{
1797    KeySymsRec keysyms;
1798    KeyClassPtr k = dev->key;
1799
1800    if (k == NULL)
1801	return (BadMatch);
1802
1803    if (len != (keyCodes * keySymsPerKeyCode))
1804	return BadLength;
1805
1806    if ((firstKeyCode < k->curKeySyms.minKeyCode) ||
1807	(firstKeyCode + keyCodes - 1 > k->curKeySyms.maxKeyCode)) {
1808	client->errorValue = firstKeyCode;
1809	return BadValue;
1810    }
1811    if (keySymsPerKeyCode == 0) {
1812	client->errorValue = 0;
1813	return BadValue;
1814    }
1815    keysyms.minKeyCode = firstKeyCode;
1816    keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
1817    keysyms.mapWidth = keySymsPerKeyCode;
1818    keysyms.map = map;
1819    if (!SetKeySymsMap(&k->curKeySyms, &keysyms))
1820	return BadAlloc;
1821    SendDeviceMappingNotify(client, MappingKeyboard, firstKeyCode, keyCodes, dev);
1822    return client->noClientException;
1823}
1824
1825static void
1826DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
1827{
1828    WindowPtr parent;
1829
1830    /* Deactivate any grabs performed on this window, before making
1831     * any input focus changes.
1832     * Deactivating a device grab should cause focus events. */
1833
1834    if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
1835	(*dev->deviceGrab.DeactivateGrab) (dev);
1836
1837    /* If the focus window is a root window (ie. has no parent)
1838     * then don't delete the focus from it. */
1839
1840    if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
1841	int focusEventMode = NotifyNormal;
1842
1843	/* If a grab is in progress, then alter the mode of focus events. */
1844
1845	if (dev->deviceGrab.grab)
1846	    focusEventMode = NotifyWhileGrabbed;
1847
1848	switch (dev->focus->revert) {
1849	case RevertToNone:
1850	    DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1851	    dev->focus->win = NoneWin;
1852	    dev->focus->traceGood = 0;
1853	    break;
1854	case RevertToParent:
1855	    parent = pWin;
1856	    do {
1857		parent = parent->parent;
1858		dev->focus->traceGood--;
1859	    }
1860	    while (!parent->realized);
1861	    DoFocusEvents(dev, pWin, parent, focusEventMode);
1862	    dev->focus->win = parent;
1863	    dev->focus->revert = RevertToNone;
1864	    break;
1865	case RevertToPointerRoot:
1866	    DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
1867	    dev->focus->win = PointerRootWin;
1868	    dev->focus->traceGood = 0;
1869	    break;
1870	case RevertToFollowKeyboard:
1871	    if (inputInfo.keyboard->focus->win) {
1872		DoFocusEvents(dev, pWin, inputInfo.keyboard->focus->win,
1873			      focusEventMode);
1874		dev->focus->win = FollowKeyboardWin;
1875		dev->focus->traceGood = 0;
1876	    } else {
1877		DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1878		dev->focus->win = NoneWin;
1879		dev->focus->traceGood = 0;
1880	    }
1881	    break;
1882	}
1883    }
1884
1885    if (dev->valuator)
1886	if (dev->valuator->motionHintWindow == pWin)
1887	    dev->valuator->motionHintWindow = NullWindow;
1888}
1889
1890void
1891DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
1892{
1893    int i;
1894    DeviceIntPtr dev;
1895    InputClientsPtr ic;
1896    struct _OtherInputMasks *inputMasks;
1897
1898    for (dev = inputInfo.devices; dev; dev = dev->next) {
1899	if (dev == inputInfo.pointer || dev == inputInfo.keyboard)
1900	    continue;
1901	DeleteDeviceFromAnyExtEvents(pWin, dev);
1902    }
1903
1904    for (dev = inputInfo.off_devices; dev; dev = dev->next)
1905	DeleteDeviceFromAnyExtEvents(pWin, dev);
1906
1907    if (freeResources)
1908	while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
1909	    ic = inputMasks->inputClients;
1910	    for (i = 0; i < EMASKSIZE; i++)
1911		inputMasks->dontPropagateMask[i] = 0;
1912	    FreeResource(ic->resource, RT_NONE);
1913	}
1914}
1915
1916int
1917MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
1918{
1919    DeviceIntPtr dev;
1920
1921    dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
1922		    DixReadAccess);
1923    if (!dev)
1924        return 0;
1925
1926    if (pEvents->type == DeviceMotionNotify) {
1927	if (mask & DevicePointerMotionHintMask) {
1928	    if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
1929		return 1;	/* don't send, but pretend we did */
1930	    }
1931	    pEvents->detail = NotifyHint;
1932	} else {
1933	    pEvents->detail = NotifyNormal;
1934	}
1935    }
1936    return (0);
1937}
1938
1939void
1940CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
1941			     deviceKeyButtonPointer * xE, GrabPtr grab,
1942			     ClientPtr client, Mask deliveryMask)
1943{
1944    DeviceIntPtr dev;
1945
1946    dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
1947		    DixReadAccess);
1948    if (!dev)
1949        return;
1950
1951    if (type == DeviceMotionNotify)
1952	dev->valuator->motionHintWindow = pWin;
1953    else if ((type == DeviceButtonPress) && (!grab) &&
1954	     (deliveryMask & DeviceButtonGrabMask)) {
1955	GrabRec tempGrab;
1956
1957	tempGrab.device = dev;
1958	tempGrab.resource = client->clientAsMask;
1959	tempGrab.window = pWin;
1960	tempGrab.ownerEvents =
1961	    (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
1962	tempGrab.eventMask = deliveryMask;
1963	tempGrab.keyboardMode = GrabModeAsync;
1964	tempGrab.pointerMode = GrabModeAsync;
1965	tempGrab.confineTo = NullWindow;
1966	tempGrab.cursor = NullCursor;
1967        tempGrab.genericMasks = NULL;
1968        tempGrab.next = NULL;
1969	(*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
1970    }
1971}
1972
1973static Mask
1974DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
1975{
1976    InputClientsPtr other;
1977
1978    if (!wOtherInputMasks(pWin))
1979	return 0;
1980    for (other = wOtherInputMasks(pWin)->inputClients; other;
1981	 other = other->next) {
1982	if (SameClient(other, client))
1983	    return other->mask[dev->id];
1984    }
1985    return 0;
1986}
1987
1988void
1989MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
1990{
1991    WindowPtr pWin;
1992    GrabPtr grab = dev->deviceGrab.grab;
1993
1994    pWin = dev->valuator->motionHintWindow;
1995
1996    if ((grab && SameClient(grab, client) &&
1997	 ((grab->eventMask & DevicePointerMotionHintMask) ||
1998	  (grab->ownerEvents &&
1999	   (DeviceEventMaskForClient(dev, pWin, client) &
2000	    DevicePointerMotionHintMask)))) ||
2001	(!grab &&
2002	 (DeviceEventMaskForClient(dev, pWin, client) &
2003	  DevicePointerMotionHintMask)))
2004	dev->valuator->motionHintWindow = NullWindow;
2005}
2006
2007int
2008DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
2009			     int maskndx)
2010{
2011    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2012
2013    if (mask & ~PropagateMask[maskndx]) {
2014	client->errorValue = mask;
2015	return BadValue;
2016    }
2017
2018    if (mask == 0) {
2019	if (inputMasks)
2020	    inputMasks->dontPropagateMask[maskndx] = mask;
2021    } else {
2022	if (!inputMasks)
2023	    AddExtensionClient(pWin, client, 0, 0);
2024	inputMasks = wOtherInputMasks(pWin);
2025	inputMasks->dontPropagateMask[maskndx] = mask;
2026    }
2027    RecalculateDeviceDeliverableEvents(pWin);
2028    if (ShouldFreeInputMasks(pWin, FALSE))
2029	FreeResource(inputMasks->inputClients->resource, RT_NONE);
2030    return Success;
2031}
2032
2033Bool
2034ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
2035{
2036    int i;
2037    Mask allInputEventMasks = 0;
2038    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2039
2040    for (i = 0; i < EMASKSIZE; i++)
2041	allInputEventMasks |= inputMasks->dontPropagateMask[i];
2042    if (!ignoreSelectedEvents)
2043	for (i = 0; i < EMASKSIZE; i++)
2044	    allInputEventMasks |= inputMasks->inputEvents[i];
2045    if (allInputEventMasks == 0)
2046	return TRUE;
2047    else
2048	return FALSE;
2049}
2050
2051/***********************************************************************
2052 *
2053 * Walk through the window tree, finding all clients that want to know
2054 * about the Event.
2055 *
2056 */
2057
2058static void
2059FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
2060                       xEvent * ev, int count)
2061{
2062    WindowPtr p2;
2063
2064    while (p1) {
2065        p2 = p1->firstChild;
2066        (void)DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab, dev->id);
2067        FindInterestedChildren(dev, p2, mask, ev, count);
2068        p1 = p1->nextSib;
2069    }
2070}
2071
2072/***********************************************************************
2073 *
2074 * Send an event to interested clients in all windows on all screens.
2075 *
2076 */
2077
2078void
2079SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
2080{
2081    int i;
2082    WindowPtr pWin, p1;
2083
2084    for (i = 0; i < screenInfo.numScreens; i++) {
2085        pWin = WindowTable[i];
2086        if (!pWin)
2087            continue;
2088        (void)DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab, dev->id);
2089        p1 = pWin->firstChild;
2090        FindInterestedChildren(dev, p1, mask, ev, count);
2091    }
2092}
2093
2094