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