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