exevents.c revision f5d46ea4
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 contains the logical button map - maps are CARD8
1228     * so we need 256 bits for the possibly maximum mapping */
1229    btlen = (mouse->button) ? bits_to_bytes(256) : 0;
1230    btlen = bytes_to_int32(btlen);
1231    len = sizeof(xXIFocusInEvent) + btlen * 4;
1232
1233    xi2event = calloc(1, len);
1234    xi2event->type         = GenericEvent;
1235    xi2event->extension    = IReqCode;
1236    xi2event->evtype       = type;
1237    xi2event->length       = bytes_to_int32(len - sizeof(xEvent));
1238    xi2event->buttons_len  = btlen;
1239    xi2event->detail       = detail;
1240    xi2event->time         = currentTime.milliseconds;
1241    xi2event->deviceid     = dev->id;
1242    xi2event->sourceid     = dev->id; /* a device doesn't change focus by itself */
1243    xi2event->mode         = mode;
1244    xi2event->root_x       = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
1245    xi2event->root_y       = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
1246
1247    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
1248        if (BitIsOn(mouse->button->down, i))
1249            SetBit(&xi2event[1], i);
1250
1251    if (dev->key)
1252    {
1253        xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods;
1254        xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods;
1255        xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods;
1256        xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods;
1257
1258        xi2event->group.base_group = dev->key->xkbInfo->state.base_group;
1259        xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group;
1260        xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group;
1261        xi2event->group.effective_group = dev->key->xkbInfo->state.group;
1262    }
1263
1264    FixUpEventFromWindow(dev->spriteInfo->sprite, (xEvent*)xi2event, pWin,
1265                         None, FALSE);
1266
1267    DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
1268                          GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
1269
1270    free(xi2event);
1271
1272    /* XI 1.x event */
1273    event.deviceid = dev->id;
1274    event.mode = mode;
1275    event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
1276    event.detail = detail;
1277    event.window = pWin->drawable.id;
1278    event.time = currentTime.milliseconds;
1279
1280    DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
1281				DeviceFocusChangeMask, NullGrab);
1282
1283    if ((event.type == DeviceFocusIn) &&
1284	(wOtherInputMasks(pWin)) &&
1285	(wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
1286    {
1287	int evcount = 1;
1288        deviceStateNotify sev[6 + (MAX_VALUATORS + 2)/3];
1289        deviceStateNotify *ev;
1290	deviceKeyStateNotify *kev;
1291	deviceButtonStateNotify *bev;
1292
1293	KeyClassPtr k;
1294	ButtonClassPtr b;
1295	ValuatorClassPtr v;
1296	int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
1297
1298	if ((b = dev->button) != NULL) {
1299	    nbuttons = b->numButtons;
1300	    if (nbuttons > 32)
1301		evcount++;
1302	}
1303	if ((k = dev->key) != NULL) {
1304	    nkeys = k->xkbInfo->desc->max_key_code -
1305                    k->xkbInfo->desc->min_key_code;
1306	    if (nkeys > 32)
1307		evcount++;
1308	    if (nbuttons > 0) {
1309		evcount++;
1310	    }
1311	}
1312	if ((v = dev->valuator) != NULL) {
1313	    nval = v->numAxes;
1314
1315	    if (nval > 3)
1316		evcount++;
1317	    if (nval > 6) {
1318		if (!(k && b))
1319		    evcount++;
1320		if (nval > 9)
1321		    evcount += ((nval - 7) / 3);
1322	    }
1323	}
1324
1325        ev = sev;
1326	FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
1327
1328	if (b != NULL) {
1329	    FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
1330	    first += 3;
1331	    nval -= 3;
1332	    if (nbuttons > 32) {
1333		(ev - 1)->deviceid |= MORE_EVENTS;
1334		bev = (deviceButtonStateNotify *) ev++;
1335		bev->type = DeviceButtonStateNotify;
1336		bev->deviceid = dev->id;
1337		memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
1338	    }
1339	    if (nval > 0) {
1340		(ev - 1)->deviceid |= MORE_EVENTS;
1341		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1342		first += 3;
1343		nval -= 3;
1344	    }
1345	}
1346
1347	if (k != NULL) {
1348	    FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
1349	    first += 3;
1350	    nval -= 3;
1351	    if (nkeys > 32) {
1352		(ev - 1)->deviceid |= MORE_EVENTS;
1353		kev = (deviceKeyStateNotify *) ev++;
1354		kev->type = DeviceKeyStateNotify;
1355		kev->deviceid = dev->id;
1356		memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
1357	    }
1358	    if (nval > 0) {
1359		(ev - 1)->deviceid |= MORE_EVENTS;
1360		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1361		first += 3;
1362		nval -= 3;
1363	    }
1364	}
1365
1366	while (nval > 0) {
1367	    FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
1368	    first += 3;
1369	    nval -= 3;
1370	    if (nval > 0) {
1371		(ev - 1)->deviceid |= MORE_EVENTS;
1372		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1373		first += 3;
1374		nval -= 3;
1375	    }
1376	}
1377
1378	DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
1379				    DeviceStateNotifyMask, NullGrab);
1380    }
1381}
1382
1383int
1384CheckGrabValues(ClientPtr client, GrabParameters* param)
1385{
1386    if (param->grabtype != GRABTYPE_CORE &&
1387        param->grabtype != GRABTYPE_XI &&
1388        param->grabtype != GRABTYPE_XI2)
1389    {
1390        ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
1391        return BadImplementation;
1392    }
1393
1394    if ((param->this_device_mode != GrabModeSync) &&
1395	(param->this_device_mode != GrabModeAsync)) {
1396	client->errorValue = param->this_device_mode;
1397	return BadValue;
1398    }
1399    if ((param->other_devices_mode != GrabModeSync) &&
1400	(param->other_devices_mode != GrabModeAsync)) {
1401	client->errorValue = param->other_devices_mode;
1402	return BadValue;
1403    }
1404
1405    if (param->grabtype != GRABTYPE_XI2 && (param->modifiers != AnyModifier) &&
1406        (param->modifiers & ~AllModifiersMask)) {
1407	client->errorValue = param->modifiers;
1408	return BadValue;
1409    }
1410
1411    if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
1412	client->errorValue = param->ownerEvents;
1413	return BadValue;
1414    }
1415    return Success;
1416}
1417
1418int
1419GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
1420           int button, GrabParameters *param, GrabType grabtype,
1421	   GrabMask *mask)
1422{
1423    WindowPtr pWin, confineTo;
1424    CursorPtr cursor;
1425    GrabPtr grab;
1426    int rc, type = -1;
1427    Mask access_mode = DixGrabAccess;
1428
1429    rc = CheckGrabValues(client, param);
1430    if (rc != Success)
1431	return rc;
1432    if (param->confineTo == None)
1433	confineTo = NullWindow;
1434    else {
1435	rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess);
1436	if (rc != Success)
1437	    return rc;
1438    }
1439    if (param->cursor == None)
1440	cursor = NullCursor;
1441    else {
1442	rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
1443				     RT_CURSOR, client, DixUseAccess);
1444	if (rc != Success)
1445	{
1446	    client->errorValue = param->cursor;
1447	    return rc;
1448	}
1449	access_mode |= DixForceAccess;
1450    }
1451    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1452	access_mode |= DixFreezeAccess;
1453    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1454    if (rc != Success)
1455	return rc;
1456    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1457    if (rc != Success)
1458	return rc;
1459
1460    if (grabtype == GRABTYPE_XI)
1461        type = DeviceButtonPress;
1462    else if (grabtype == GRABTYPE_XI2)
1463        type = XI_ButtonPress;
1464
1465    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
1466                      mask, param, type, button, confineTo, cursor);
1467    if (!grab)
1468	return BadAlloc;
1469    return AddPassiveGrabToList(client, grab);
1470}
1471
1472/**
1473 * Grab the given key. If grabtype is GRABTYPE_XI, the key is a keycode. If
1474 * grabtype is GRABTYPE_XI2, the key is a keysym.
1475 */
1476int
1477GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
1478        int key, GrabParameters *param, GrabType grabtype, GrabMask *mask)
1479{
1480    WindowPtr pWin;
1481    GrabPtr grab;
1482    KeyClassPtr k = dev->key;
1483    Mask access_mode = DixGrabAccess;
1484    int rc, type = -1;
1485
1486    rc = CheckGrabValues(client, param);
1487    if (rc != Success)
1488        return rc;
1489    if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL)
1490	return BadMatch;
1491    if (grabtype == GRABTYPE_XI)
1492    {
1493        if ((key > k->xkbInfo->desc->max_key_code ||
1494                    key < k->xkbInfo->desc->min_key_code)
1495                && (key != AnyKey)) {
1496            client->errorValue = key;
1497            return BadValue;
1498        }
1499        type = DeviceKeyPress;
1500    } else if (grabtype == GRABTYPE_XI2)
1501        type = XI_KeyPress;
1502
1503    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1504    if (rc != Success)
1505	return rc;
1506    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1507	access_mode |= DixFreezeAccess;
1508    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1509    if (rc != Success)
1510	return rc;
1511
1512    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
1513                      mask, param, type, key, NULL, NULL);
1514    if (!grab)
1515	return BadAlloc;
1516    return AddPassiveGrabToList(client, grab);
1517}
1518
1519/* Enter/FocusIn grab */
1520int
1521GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
1522           GrabParameters *param, GrabMask *mask)
1523{
1524    WindowPtr pWin;
1525    CursorPtr cursor;
1526    GrabPtr grab;
1527    Mask access_mode = DixGrabAccess;
1528    int rc;
1529
1530    rc = CheckGrabValues(client, param);
1531    if (rc != Success)
1532        return rc;
1533
1534    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1535    if (rc != Success)
1536	return rc;
1537    if (param->cursor == None)
1538	cursor = NullCursor;
1539    else {
1540	rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
1541				     RT_CURSOR, client, DixUseAccess);
1542	if (rc != Success)
1543	{
1544	    client->errorValue = param->cursor;
1545	    return rc;
1546	}
1547	access_mode |= DixForceAccess;
1548    }
1549    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1550	access_mode |= DixFreezeAccess;
1551    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1552    if (rc != Success)
1553	return rc;
1554
1555    grab = CreateGrab(client->index, dev, dev, pWin, GRABTYPE_XI2,
1556                      mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn,
1557                      0, NULL, cursor);
1558
1559    if (!grab)
1560        return BadAlloc;
1561
1562    return AddPassiveGrabToList(client, grab);
1563}
1564
1565int
1566SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
1567		Mask mask, Mask exclusivemasks)
1568{
1569    int mskidx = dev->id;
1570    int i, ret;
1571    Mask check;
1572    InputClientsPtr others;
1573
1574    check = (mask & exclusivemasks);
1575    if (wOtherInputMasks(pWin)) {
1576	if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {	/* It is illegal for two different
1577									 * clients to select on any of the
1578									 * events for maskcheck. However,
1579									 * it is OK, for some client to
1580									 * continue selecting on one of those
1581									 * events.  */
1582	    for (others = wOtherInputMasks(pWin)->inputClients; others;
1583		 others = others->next) {
1584		if (!SameClient(others, client) && (check &
1585						    others->mask[mskidx]))
1586		    return BadAccess;
1587	    }
1588	}
1589	for (others = wOtherInputMasks(pWin)->inputClients; others;
1590	     others = others->next) {
1591	    if (SameClient(others, client)) {
1592		check = others->mask[mskidx];
1593		others->mask[mskidx] = mask;
1594		if (mask == 0) {
1595		    for (i = 0; i < EMASKSIZE; i++)
1596			if (i != mskidx && others->mask[i] != 0)
1597			    break;
1598		    if (i == EMASKSIZE) {
1599			RecalculateDeviceDeliverableEvents(pWin);
1600			if (ShouldFreeInputMasks(pWin, FALSE))
1601			    FreeResource(others->resource, RT_NONE);
1602			return Success;
1603		    }
1604		}
1605		goto maskSet;
1606	    }
1607	}
1608    }
1609    check = 0;
1610    if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
1611	return ret;
1612  maskSet:
1613    if (dev->valuator)
1614	if ((dev->valuator->motionHintWindow == pWin) &&
1615	    (mask & DevicePointerMotionHintMask) &&
1616	    !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
1617	    dev->valuator->motionHintWindow = NullWindow;
1618    RecalculateDeviceDeliverableEvents(pWin);
1619    return Success;
1620}
1621
1622int
1623AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
1624{
1625    InputClientsPtr others;
1626
1627    if (!pWin->optional && !MakeWindowOptional(pWin))
1628	return BadAlloc;
1629    others = calloc(1, sizeof(InputClients));
1630    if (!others)
1631	return BadAlloc;
1632    if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
1633	goto bail;
1634    others->mask[mskidx] = mask;
1635    others->resource = FakeClientID(client->index);
1636    others->next = pWin->optional->inputMasks->inputClients;
1637    pWin->optional->inputMasks->inputClients = others;
1638    if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
1639	goto bail;
1640    return Success;
1641
1642bail:
1643    free(others);
1644    return BadAlloc;
1645}
1646
1647static Bool
1648MakeInputMasks(WindowPtr pWin)
1649{
1650    struct _OtherInputMasks *imasks;
1651
1652    imasks = calloc(1, sizeof(struct _OtherInputMasks));
1653    if (!imasks)
1654	return FALSE;
1655    pWin->optional->inputMasks = imasks;
1656    return TRUE;
1657}
1658
1659void
1660RecalculateDeviceDeliverableEvents(WindowPtr pWin)
1661{
1662    InputClientsPtr others;
1663    struct _OtherInputMasks *inputMasks;	/* default: NULL */
1664    WindowPtr pChild, tmp;
1665    int i, j;
1666
1667    pChild = pWin;
1668    while (1) {
1669	if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
1670            for (i = 0; i < EMASKSIZE; i++)
1671                memset(inputMasks->xi2mask[i], 0, sizeof(inputMasks->xi2mask[i]));
1672	    for (others = inputMasks->inputClients; others;
1673		 others = others->next) {
1674		for (i = 0; i < EMASKSIZE; i++)
1675		    inputMasks->inputEvents[i] |= others->mask[i];
1676                for (i = 0; i < EMASKSIZE; i++)
1677                    for (j = 0; j < XI2MASKSIZE; j++)
1678                        inputMasks->xi2mask[i][j] |= others->xi2mask[i][j];
1679	    }
1680	    for (i = 0; i < EMASKSIZE; i++)
1681		inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
1682	    for (tmp = pChild->parent; tmp; tmp = tmp->parent)
1683		if (wOtherInputMasks(tmp))
1684		    for (i = 0; i < EMASKSIZE; i++)
1685			inputMasks->deliverableEvents[i] |=
1686			    (wOtherInputMasks(tmp)->deliverableEvents[i]
1687			     & ~inputMasks->
1688			     dontPropagateMask[i] & PropagateMask[i]);
1689	}
1690	if (pChild->firstChild) {
1691	    pChild = pChild->firstChild;
1692	    continue;
1693	}
1694	while (!pChild->nextSib && (pChild != pWin))
1695	    pChild = pChild->parent;
1696	if (pChild == pWin)
1697	    break;
1698	pChild = pChild->nextSib;
1699    }
1700}
1701
1702int
1703InputClientGone(WindowPtr pWin, XID id)
1704{
1705    InputClientsPtr other, prev;
1706
1707    if (!wOtherInputMasks(pWin))
1708	return Success;
1709    prev = 0;
1710    for (other = wOtherInputMasks(pWin)->inputClients; other;
1711	 other = other->next) {
1712	if (other->resource == id) {
1713	    if (prev) {
1714		prev->next = other->next;
1715		free(other);
1716	    } else if (!(other->next)) {
1717		if (ShouldFreeInputMasks(pWin, TRUE)) {
1718		    wOtherInputMasks(pWin)->inputClients = other->next;
1719		    free(wOtherInputMasks(pWin));
1720		    pWin->optional->inputMasks = (OtherInputMasks *) NULL;
1721		    CheckWindowOptionalNeed(pWin);
1722		    free(other);
1723		} else {
1724		    other->resource = FakeClientID(0);
1725		    if (!AddResource(other->resource, RT_INPUTCLIENT,
1726				     (pointer) pWin))
1727			return BadAlloc;
1728		}
1729	    } else {
1730		wOtherInputMasks(pWin)->inputClients = other->next;
1731		free(other);
1732	    }
1733	    RecalculateDeviceDeliverableEvents(pWin);
1734	    return Success;
1735	}
1736	prev = other;
1737    }
1738    FatalError("client not on device event list");
1739}
1740
1741int
1742SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
1743	  xEvent * ev, Mask mask, int count)
1744{
1745    WindowPtr pWin;
1746    WindowPtr effectiveFocus = NullWindow;	/* only set if dest==InputFocus */
1747    WindowPtr spriteWin = GetSpriteWindow(d);
1748
1749    if (dest == PointerWindow)
1750	pWin = spriteWin;
1751    else if (dest == InputFocus) {
1752	WindowPtr inputFocus;
1753
1754	if (!d->focus)
1755	    inputFocus = spriteWin;
1756	else
1757	    inputFocus = d->focus->win;
1758
1759	if (inputFocus == FollowKeyboardWin)
1760	    inputFocus = inputInfo.keyboard->focus->win;
1761
1762	if (inputFocus == NoneWin)
1763	    return Success;
1764
1765	/* If the input focus is PointerRootWin, send the event to where
1766	 * the pointer is if possible, then perhaps propogate up to root. */
1767	if (inputFocus == PointerRootWin)
1768	    inputFocus = GetCurrentRootWindow(d);
1769
1770	if (IsParent(inputFocus, spriteWin)) {
1771	    effectiveFocus = inputFocus;
1772	    pWin = spriteWin;
1773	} else
1774	    effectiveFocus = pWin = inputFocus;
1775    } else
1776	dixLookupWindow(&pWin, dest, client, DixSendAccess);
1777    if (!pWin)
1778	return BadWindow;
1779    if ((propagate != xFalse) && (propagate != xTrue)) {
1780	client->errorValue = propagate;
1781	return BadValue;
1782    }
1783    ev->u.u.type |= 0x80;
1784    if (propagate) {
1785	for (; pWin; pWin = pWin->parent) {
1786	    if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
1787		return Success;
1788	    if (pWin == effectiveFocus)
1789		return Success;
1790	    if (wOtherInputMasks(pWin))
1791		mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
1792	    if (!mask)
1793		break;
1794	}
1795    } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
1796	DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
1797    return Success;
1798}
1799
1800int
1801SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
1802{
1803    int i;
1804    ButtonClassPtr b = dev->button;
1805
1806    if (b == NULL)
1807	return BadMatch;
1808
1809    if (nElts != b->numButtons) {
1810	client->errorValue = nElts;
1811	return BadValue;
1812    }
1813    if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
1814	return BadValue;
1815    for (i = 0; i < nElts; i++)
1816	if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
1817	    return MappingBusy;
1818    for (i = 0; i < nElts; i++)
1819	b->map[i + 1] = map[i];
1820    return Success;
1821}
1822
1823int
1824ChangeKeyMapping(ClientPtr client,
1825		 DeviceIntPtr dev,
1826		 unsigned len,
1827		 int type,
1828		 KeyCode firstKeyCode,
1829		 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
1830{
1831    KeySymsRec keysyms;
1832    KeyClassPtr k = dev->key;
1833
1834    if (k == NULL)
1835	return BadMatch;
1836
1837    if (len != (keyCodes * keySymsPerKeyCode))
1838	return BadLength;
1839
1840    if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
1841	(firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
1842	client->errorValue = firstKeyCode;
1843	return BadValue;
1844    }
1845    if (keySymsPerKeyCode == 0) {
1846	client->errorValue = 0;
1847	return BadValue;
1848    }
1849    keysyms.minKeyCode = firstKeyCode;
1850    keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
1851    keysyms.mapWidth = keySymsPerKeyCode;
1852    keysyms.map = map;
1853
1854    XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
1855                          serverClient);
1856
1857    return Success;
1858}
1859
1860static void
1861DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
1862{
1863    WindowPtr parent;
1864
1865    /* Deactivate any grabs performed on this window, before making
1866     * any input focus changes.
1867     * Deactivating a device grab should cause focus events. */
1868
1869    if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
1870	(*dev->deviceGrab.DeactivateGrab) (dev);
1871
1872    /* If the focus window is a root window (ie. has no parent)
1873     * then don't delete the focus from it. */
1874
1875    if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
1876	int focusEventMode = NotifyNormal;
1877
1878	/* If a grab is in progress, then alter the mode of focus events. */
1879
1880	if (dev->deviceGrab.grab)
1881	    focusEventMode = NotifyWhileGrabbed;
1882
1883	switch (dev->focus->revert) {
1884	case RevertToNone:
1885	    if (!ActivateFocusInGrab(dev, pWin, NoneWin))
1886		DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1887	    dev->focus->win = NoneWin;
1888	    dev->focus->traceGood = 0;
1889	    break;
1890	case RevertToParent:
1891	    parent = pWin;
1892	    do {
1893		parent = parent->parent;
1894		dev->focus->traceGood--;
1895	    }
1896	    while (!parent->realized);
1897	    if (!ActivateFocusInGrab(dev, pWin, parent))
1898		DoFocusEvents(dev, pWin, parent, focusEventMode);
1899	    dev->focus->win = parent;
1900	    dev->focus->revert = RevertToNone;
1901	    break;
1902	case RevertToPointerRoot:
1903	    if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
1904		DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
1905	    dev->focus->win = PointerRootWin;
1906	    dev->focus->traceGood = 0;
1907	    break;
1908	case RevertToFollowKeyboard:
1909            {
1910                DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
1911                if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
1912                    kbd = inputInfo.keyboard;
1913	    if (kbd->focus->win) {
1914		if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
1915		    DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
1916		dev->focus->win = FollowKeyboardWin;
1917		dev->focus->traceGood = 0;
1918	    } else {
1919                if (!ActivateFocusInGrab(dev, pWin, NoneWin))
1920                    DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1921		dev->focus->win = NoneWin;
1922		dev->focus->traceGood = 0;
1923	    }
1924            }
1925	    break;
1926	}
1927    }
1928
1929    if (dev->valuator)
1930	if (dev->valuator->motionHintWindow == pWin)
1931	    dev->valuator->motionHintWindow = NullWindow;
1932}
1933
1934void
1935DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
1936{
1937    int i;
1938    DeviceIntPtr dev;
1939    InputClientsPtr ic;
1940    struct _OtherInputMasks *inputMasks;
1941
1942    for (dev = inputInfo.devices; dev; dev = dev->next) {
1943	DeleteDeviceFromAnyExtEvents(pWin, dev);
1944    }
1945
1946    for (dev = inputInfo.off_devices; dev; dev = dev->next)
1947	DeleteDeviceFromAnyExtEvents(pWin, dev);
1948
1949    if (freeResources)
1950	while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
1951	    ic = inputMasks->inputClients;
1952	    for (i = 0; i < EMASKSIZE; i++)
1953		inputMasks->dontPropagateMask[i] = 0;
1954	    FreeResource(ic->resource, RT_NONE);
1955	}
1956}
1957
1958int
1959MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
1960{
1961    DeviceIntPtr dev;
1962
1963    dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
1964		    DixReadAccess);
1965    if (!dev)
1966        return 0;
1967
1968    if (pEvents->type == DeviceMotionNotify) {
1969	if (mask & DevicePointerMotionHintMask) {
1970	    if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
1971		return 1;	/* don't send, but pretend we did */
1972	    }
1973	    pEvents->detail = NotifyHint;
1974	} else {
1975	    pEvents->detail = NotifyNormal;
1976	}
1977    }
1978    return 0;
1979}
1980
1981void
1982CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
1983			     deviceKeyButtonPointer * xE, GrabPtr grab,
1984			     ClientPtr client, Mask deliveryMask)
1985{
1986    DeviceIntPtr dev;
1987
1988    dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
1989		    DixGrabAccess);
1990    if (!dev)
1991        return;
1992
1993    if (type == DeviceMotionNotify)
1994	dev->valuator->motionHintWindow = pWin;
1995    else if ((type == DeviceButtonPress) && (!grab) &&
1996	     (deliveryMask & DeviceButtonGrabMask)) {
1997	GrabRec tempGrab;
1998
1999	tempGrab.device = dev;
2000	tempGrab.resource = client->clientAsMask;
2001	tempGrab.window = pWin;
2002	tempGrab.ownerEvents =
2003	    (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
2004	tempGrab.eventMask = deliveryMask;
2005	tempGrab.keyboardMode = GrabModeAsync;
2006	tempGrab.pointerMode = GrabModeAsync;
2007	tempGrab.confineTo = NullWindow;
2008	tempGrab.cursor = NullCursor;
2009        tempGrab.next = NULL;
2010	(*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
2011    }
2012}
2013
2014static Mask
2015DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
2016{
2017    InputClientsPtr other;
2018
2019    if (!wOtherInputMasks(pWin))
2020	return 0;
2021    for (other = wOtherInputMasks(pWin)->inputClients; other;
2022	 other = other->next) {
2023	if (SameClient(other, client))
2024	    return other->mask[dev->id];
2025    }
2026    return 0;
2027}
2028
2029void
2030MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
2031{
2032    WindowPtr pWin;
2033    GrabPtr grab = dev->deviceGrab.grab;
2034
2035    pWin = dev->valuator->motionHintWindow;
2036
2037    if ((grab && SameClient(grab, client) &&
2038	 ((grab->eventMask & DevicePointerMotionHintMask) ||
2039	  (grab->ownerEvents &&
2040	   (DeviceEventMaskForClient(dev, pWin, client) &
2041	    DevicePointerMotionHintMask)))) ||
2042	(!grab &&
2043	 (DeviceEventMaskForClient(dev, pWin, client) &
2044	  DevicePointerMotionHintMask)))
2045	dev->valuator->motionHintWindow = NullWindow;
2046}
2047
2048int
2049DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
2050			     int maskndx)
2051{
2052    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2053
2054    if (mask & ~PropagateMask[maskndx]) {
2055	client->errorValue = mask;
2056	return BadValue;
2057    }
2058
2059    if (mask == 0) {
2060	if (inputMasks)
2061	    inputMasks->dontPropagateMask[maskndx] = mask;
2062    } else {
2063	if (!inputMasks)
2064	    AddExtensionClient(pWin, client, 0, 0);
2065	inputMasks = wOtherInputMasks(pWin);
2066	inputMasks->dontPropagateMask[maskndx] = mask;
2067    }
2068    RecalculateDeviceDeliverableEvents(pWin);
2069    if (ShouldFreeInputMasks(pWin, FALSE))
2070	FreeResource(inputMasks->inputClients->resource, RT_NONE);
2071    return Success;
2072}
2073
2074Bool
2075ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
2076{
2077    int i;
2078    Mask allInputEventMasks = 0;
2079    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2080
2081    for (i = 0; i < EMASKSIZE; i++)
2082	allInputEventMasks |= inputMasks->dontPropagateMask[i];
2083    if (!ignoreSelectedEvents)
2084	for (i = 0; i < EMASKSIZE; i++)
2085	    allInputEventMasks |= inputMasks->inputEvents[i];
2086    if (allInputEventMasks == 0)
2087	return TRUE;
2088    else
2089	return FALSE;
2090}
2091
2092/***********************************************************************
2093 *
2094 * Walk through the window tree, finding all clients that want to know
2095 * about the Event.
2096 *
2097 */
2098
2099static void
2100FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
2101                       xEvent * ev, int count)
2102{
2103    WindowPtr p2;
2104
2105    while (p1) {
2106        p2 = p1->firstChild;
2107        DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
2108        FindInterestedChildren(dev, p2, mask, ev, count);
2109        p1 = p1->nextSib;
2110    }
2111}
2112
2113/***********************************************************************
2114 *
2115 * Send an event to interested clients in all windows on all screens.
2116 *
2117 */
2118
2119void
2120SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
2121{
2122    int i;
2123    WindowPtr pWin, p1;
2124
2125    for (i = 0; i < screenInfo.numScreens; i++) {
2126        pWin = screenInfo.screens[i]->root;
2127        if (!pWin)
2128            continue;
2129        DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
2130        p1 = pWin->firstChild;
2131        FindInterestedChildren(dev, p1, mask, ev, count);
2132    }
2133}
2134
2135/**
2136 * Set the XI2 mask for the given client on the given window.
2137 * @param dev The device to set the mask for.
2138 * @param win The window to set the mask on.
2139 * @param client The client setting the mask.
2140 * @param len Number of bytes in mask.
2141 * @param mask Event mask in the form of (1 << eventtype)
2142 */
2143int
2144XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
2145               unsigned int len, unsigned char* mask)
2146{
2147    OtherInputMasks *masks;
2148    InputClientsPtr others = NULL;
2149
2150    masks = wOtherInputMasks(win);
2151    if (masks)
2152    {
2153	for (others = wOtherInputMasks(win)->inputClients; others;
2154	     others = others->next) {
2155	    if (SameClient(others, client)) {
2156                memset(others->xi2mask[dev->id], 0,
2157                       sizeof(others->xi2mask[dev->id]));
2158                break;
2159            }
2160        }
2161    }
2162
2163    len = min(len, sizeof(others->xi2mask[dev->id]));
2164
2165    if (len && !others)
2166    {
2167        if (AddExtensionClient(win, client, 0, 0) != Success)
2168            return BadAlloc;
2169        others= wOtherInputMasks(win)->inputClients;
2170    }
2171
2172    if (others)
2173        memset(others->xi2mask[dev->id], 0, sizeof(others->xi2mask[dev->id]));
2174
2175    if (len)
2176        memcpy(others->xi2mask[dev->id], mask, len);
2177
2178    RecalculateDeviceDeliverableEvents(win);
2179
2180    return Success;
2181}
2182