exevents.c revision 706f2543
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
592         memcpy(to->button->labels, from->button->labels,
593                from->button->numButtons * sizeof(Atom));
594        to->button->sourceid = from->id;
595    } else if (to->button && !from->button)
596    {
597        ClassesPtr classes;
598        classes = to->unused_classes;
599        classes->button = to->button;
600        to->button      = NULL;
601    }
602
603    if (from->proximity)
604    {
605        if (!to->proximity)
606        {
607            classes = to->unused_classes;
608            to->proximity = classes->proximity;
609            if (!to->proximity)
610            {
611                to->proximity = calloc(1, sizeof(ProximityClassRec));
612                if (!to->proximity)
613                    FatalError("[Xi] no memory for class shift.\n");
614            } else
615                classes->proximity = NULL;
616        }
617        memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
618        to->proximity->sourceid = from->id;
619    } else if (to->proximity)
620    {
621        ClassesPtr classes;
622        classes = to->unused_classes;
623        classes->proximity = to->proximity;
624        to->proximity      = NULL;
625    }
626
627    if (from->absolute)
628    {
629        if (!to->absolute)
630        {
631            classes = to->unused_classes;
632            to->absolute = classes->absolute;
633            if (!to->absolute)
634            {
635                to->absolute = calloc(1, sizeof(AbsoluteClassRec));
636                if (!to->absolute)
637                    FatalError("[Xi] no memory for class shift.\n");
638            } else
639                classes->absolute = NULL;
640        }
641        memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec));
642        to->absolute->sourceid = from->id;
643    } else if (to->absolute)
644    {
645        ClassesPtr classes;
646        classes = to->unused_classes;
647        classes->absolute = to->absolute;
648        to->absolute      = NULL;
649    }
650}
651
652/**
653 * Copies the CONTENT of the classes of device from into the classes in device
654 * to. From and to are identical after finishing.
655 *
656 * If to does not have classes from currenly has, the classes are stored in
657 * to's devPrivates system. Later, we recover it again from there if needed.
658 * Saves a few memory allocations.
659 */
660void
661DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dce)
662{
663    /* generic feedback classes, not tied to pointer and/or keyboard */
664    DeepCopyFeedbackClasses(from, to);
665
666    if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
667        DeepCopyKeyboardClasses(from, to);
668    if ((dce->flags & DEVCHANGE_POINTER_EVENT))
669        DeepCopyPointerClasses(from, to);
670}
671
672
673/**
674 * Send an XI2 DeviceChangedEvent to all interested clients.
675 */
676void
677XISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, DeviceChangedEvent *dce)
678{
679    xXIDeviceChangedEvent *dcce;
680    int rc;
681
682    rc = EventToXI2((InternalEvent*)dce, (xEvent**)&dcce);
683    if (rc != Success)
684    {
685        ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc);
686        return;
687    }
688
689    /* we don't actually swap if there's a NullClient, swapping is done
690     * later when event is delivered. */
691    SendEventToAllWindows(master, XI_DeviceChangedMask, (xEvent*)dcce, 1);
692    free(dcce);
693}
694
695static void
696ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
697{
698    DeviceIntPtr slave;
699    int rc;
700
701    /* For now, we don't have devices that change physically. */
702    if (!IsMaster(device))
703        return;
704
705    rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
706
707    if (rc != Success)
708        return; /* Device has disappeared */
709
710    if (!slave->u.master)
711        return; /* set floating since the event */
712
713    if (slave->u.master->id != dce->masterid)
714        return; /* not our slave anymore, don't care */
715
716    /* FIXME: we probably need to send a DCE for the new slave now */
717
718    device->public.devicePrivate = slave->public.devicePrivate;
719
720    /* FIXME: the classes may have changed since we generated the event. */
721    DeepCopyDeviceClasses(slave, device, dce);
722    XISendDeviceChangedEvent(slave, device, dce);
723}
724
725/**
726 * Update the device state according to the data in the event.
727 *
728 * return values are
729 *   DEFAULT ... process as normal
730 *   DONT_PROCESS ... return immediately from caller
731 */
732#define DEFAULT 0
733#define DONT_PROCESS 1
734int
735UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
736{
737    int i;
738    int key = 0,
739        bit = 0,
740        last_valuator;
741
742    KeyClassPtr k       = NULL;
743    ButtonClassPtr b    = NULL;
744    ValuatorClassPtr v  = NULL;
745
746    /* This event is always the first we get, before the actual events with
747     * the data. However, the way how the DDX is set up, "device" will
748     * actually be the slave device that caused the event.
749     */
750    switch(event->type)
751    {
752        case ET_DeviceChanged:
753            ChangeMasterDeviceClasses(device, (DeviceChangedEvent*)event);
754            return DONT_PROCESS; /* event has been sent already */
755        case ET_Motion:
756        case ET_ButtonPress:
757        case ET_ButtonRelease:
758        case ET_KeyPress:
759        case ET_KeyRelease:
760        case ET_ProximityIn:
761        case ET_ProximityOut:
762            break;
763        default:
764            /* other events don't update the device */
765            return DEFAULT;
766    }
767
768    k = device->key;
769    v = device->valuator;
770    b = device->button;
771
772    key = event->detail.key;
773    bit = 1 << (key & 7);
774
775    /* Update device axis */
776    /* Check valuators first */
777    last_valuator = -1;
778    for (i = 0; i < MAX_VALUATORS; i++)
779    {
780        if (BitIsOn(&event->valuators.mask, i))
781        {
782            if (!v)
783            {
784                ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
785                        "Ignoring event.\n", device->name);
786                return DONT_PROCESS;
787            } else if (v->numAxes < i)
788            {
789                ErrorF("[Xi] Too many valuators reported for device '%s'. "
790                        "Ignoring event.\n", device->name);
791                return DONT_PROCESS;
792            }
793            last_valuator = i;
794        }
795    }
796
797    for (i = 0; i <= last_valuator && i < v->numAxes; i++)
798    {
799        if (BitIsOn(&event->valuators.mask, i))
800        {
801            /* XXX: Relative/Absolute mode */
802            v->axisVal[i] = event->valuators.data[i];
803            v->axisVal[i] += (event->valuators.data_frac[i] * 1.0f / (1 << 16) / (1 << 16));
804        }
805    }
806
807    if (event->type == ET_KeyPress) {
808        if (!k)
809            return DONT_PROCESS;
810
811	/* don't allow ddx to generate multiple downs, but repeats are okay */
812	if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
813	    return DONT_PROCESS;
814
815	if (device->valuator)
816	    device->valuator->motionHintWindow = NullWindow;
817	set_key_down(device, key, KEY_PROCESSED);
818    } else if (event->type == ET_KeyRelease) {
819        if (!k)
820            return DONT_PROCESS;
821
822	if (!key_is_down(device, key, KEY_PROCESSED))	/* guard against duplicates */
823	    return DONT_PROCESS;
824	if (device->valuator)
825	    device->valuator->motionHintWindow = NullWindow;
826	set_key_up(device, key, KEY_PROCESSED);
827    } else if (event->type == ET_ButtonPress) {
828        Mask mask;
829        if (!b)
830            return DONT_PROCESS;
831
832        if (button_is_down(device, key, BUTTON_PROCESSED))
833            return DONT_PROCESS;
834
835        set_button_down(device, key, BUTTON_PROCESSED);
836	if (device->valuator)
837	    device->valuator->motionHintWindow = NullWindow;
838        if (!b->map[key])
839            return DONT_PROCESS;
840        b->buttonsDown++;
841	b->motionMask = DeviceButtonMotionMask;
842        if (b->map[key] <= 5)
843	    b->state |= (Button1Mask >> 1) << b->map[key];
844
845        /* Add state and motionMask to the filter for this event */
846        mask = DevicePointerMotionMask | b->state | b->motionMask;
847        SetMaskForEvent(device->id, mask, DeviceMotionNotify);
848        mask = PointerMotionMask | b->state | b->motionMask;
849        SetMaskForEvent(device->id, mask, MotionNotify);
850    } else if (event->type == ET_ButtonRelease) {
851        Mask mask;
852        if (!b)
853            return DONT_PROCESS;
854
855        if (!button_is_down(device, key, BUTTON_PROCESSED))
856            return DONT_PROCESS;
857        if (IsMaster(device)) {
858            DeviceIntPtr sd;
859
860            /*
861             * Leave the button down if any slave has the
862             * button still down. Note that this depends on the
863             * event being delivered through the slave first
864             */
865            for (sd = inputInfo.devices; sd; sd = sd->next) {
866                if (IsMaster(sd) || sd->u.master != device)
867                    continue;
868                if (!sd->button)
869                    continue;
870                for (i = 1; i <= sd->button->numButtons; i++)
871                    if (sd->button->map[i] == key &&
872                        button_is_down(sd, i, BUTTON_PROCESSED))
873                        return DONT_PROCESS;
874            }
875        }
876        set_button_up(device, key, BUTTON_PROCESSED);
877	if (device->valuator)
878	    device->valuator->motionHintWindow = NullWindow;
879        if (!b->map[key])
880            return DONT_PROCESS;
881        if (b->buttonsDown >= 1 && !--b->buttonsDown)
882	    b->motionMask = 0;
883	if (b->map[key] <= 5)
884	    b->state &= ~((Button1Mask >> 1) << b->map[key]);
885
886        /* Add state and motionMask to the filter for this event */
887        mask = DevicePointerMotionMask | b->state | b->motionMask;
888        SetMaskForEvent(device->id, mask, DeviceMotionNotify);
889        mask = PointerMotionMask | b->state | b->motionMask;
890        SetMaskForEvent(device->id, mask, MotionNotify);
891    } else if (event->type == ET_ProximityIn)
892	device->proximity->in_proximity = TRUE;
893    else if (event->type == ET_ProximityOut)
894	device->proximity->in_proximity = FALSE;
895
896    return DEFAULT;
897}
898
899static void
900ProcessRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
901{
902    GrabPtr grab = device->deviceGrab.grab;
903
904    if (grab)
905        DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE);
906    else { /* deliver to all root windows */
907        xEvent *xi;
908        int i;
909
910        i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi);
911        if (i != Success)
912        {
913            ErrorF("[Xi] %s: XI2 conversion failed in ProcessRawEvent (%d)\n",
914                    device->name, i);
915            return;
916        }
917
918        for (i = 0; i < screenInfo.numScreens; i++)
919            DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1,
920                                  GetEventFilter(device, xi), NULL);
921        free(xi);
922    }
923}
924
925/**
926 * Main device event processing function.
927 * Called from when processing the events from the event queue.
928 *
929 */
930void
931ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
932{
933    GrabPtr grab;
934    Bool deactivateDeviceGrab = FALSE;
935    int key = 0, rootX, rootY;
936    ButtonClassPtr b;
937    KeyClassPtr k;
938    ValuatorClassPtr v;
939    int ret = 0;
940    int state, i;
941    DeviceIntPtr mouse = NULL, kbd = NULL;
942    DeviceEvent *event = &ev->device_event;
943
944    CHECKEVENT(ev);
945
946    if (ev->any.type == ET_RawKeyPress ||
947        ev->any.type == ET_RawKeyRelease ||
948        ev->any.type == ET_RawButtonPress ||
949        ev->any.type == ET_RawButtonRelease ||
950        ev->any.type == ET_RawMotion)
951    {
952        ProcessRawEvent(&ev->raw_event, device);
953        return;
954    }
955
956    if (IsPointerDevice(device))
957    {
958        kbd = GetPairedDevice(device);
959        mouse = device;
960        if (!kbd->key) /* can happen with floating SDs */
961            kbd = NULL;
962    } else
963    {
964        mouse = GetPairedDevice(device);
965        kbd = device;
966        if (!mouse->valuator || !mouse->button) /* may be float. SDs */
967            mouse = NULL;
968    }
969
970    /* State needs to be assembled BEFORE the device is updated. */
971    state = (kbd && kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->state) : 0;
972    state |= (mouse && mouse->button) ? (mouse->button->state) : 0;
973
974    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
975        if (BitIsOn(mouse->button->down, i))
976            SetBit(event->buttons, i);
977
978    if (kbd && kbd->key)
979    {
980        XkbStatePtr state;
981        /* we need the state before the event happens */
982        if (event->type == ET_KeyPress || event->type == ET_KeyRelease)
983            state = &kbd->key->xkbInfo->prev_state;
984        else
985            state = &kbd->key->xkbInfo->state;
986
987        event->mods.base = state->base_mods;
988        event->mods.latched = state->latched_mods;
989        event->mods.locked = state->locked_mods;
990        event->mods.effective = state->mods;
991
992        event->group.base = state->base_group;
993        event->group.latched = state->latched_group;
994        event->group.locked = state->locked_group;
995        event->group.effective = state->group;
996    }
997
998    ret = UpdateDeviceState(device, event);
999    if (ret == DONT_PROCESS)
1000        return;
1001
1002    v = device->valuator;
1003    b = device->button;
1004    k = device->key;
1005
1006    if (IsMaster(device) || !device->u.master)
1007        CheckMotion(event, device);
1008
1009    switch (event->type)
1010    {
1011        case ET_Motion:
1012        case ET_ButtonPress:
1013        case ET_ButtonRelease:
1014        case ET_KeyPress:
1015        case ET_KeyRelease:
1016        case ET_ProximityIn:
1017        case ET_ProximityOut:
1018            GetSpritePosition(device, &rootX, &rootY);
1019            event->root_x = rootX;
1020            event->root_y = rootY;
1021            NoticeEventTime((InternalEvent*)event);
1022            event->corestate = state;
1023            key = event->detail.key;
1024            break;
1025        default:
1026            break;
1027    }
1028
1029    if (DeviceEventCallback && !syncEvents.playingEvents) {
1030	DeviceEventInfoRec eventinfo;
1031	SpritePtr pSprite = device->spriteInfo->sprite;
1032
1033	/* see comment in EnqueueEvents regarding the next three lines */
1034	if (ev->any.type == ET_Motion)
1035	    ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
1036
1037	eventinfo.device = device;
1038	eventinfo.event = ev;
1039	CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
1040    }
1041
1042    grab = device->deviceGrab.grab;
1043
1044    switch(event->type)
1045    {
1046        case ET_KeyPress:
1047            if (!grab && CheckDeviceGrabs(device, event, 0)) {
1048                device->deviceGrab.activatingKey = key;
1049                return;
1050            }
1051            break;
1052        case ET_KeyRelease:
1053            if (grab && device->deviceGrab.fromPassiveGrab &&
1054                (key == device->deviceGrab.activatingKey) &&
1055                (device->deviceGrab.grab->type == KeyPress ||
1056                 device->deviceGrab.grab->type == DeviceKeyPress ||
1057                 device->deviceGrab.grab->type == XI_KeyPress))
1058                deactivateDeviceGrab = TRUE;
1059            break;
1060        case ET_ButtonPress:
1061            event->detail.button = b->map[key];
1062            if (!event->detail.button) { /* there's no button 0 */
1063                event->detail.button = key;
1064                return;
1065            }
1066            if (!grab && CheckDeviceGrabs(device, event, 0))
1067            {
1068                /* if a passive grab was activated, the event has been sent
1069                 * already */
1070                return;
1071            }
1072            break;
1073        case ET_ButtonRelease:
1074            event->detail.button = b->map[key];
1075            if (!event->detail.button) { /* there's no button 0 */
1076                event->detail.button = key;
1077                return;
1078            }
1079            if (grab && !b->buttonsDown &&
1080                device->deviceGrab.fromPassiveGrab &&
1081                (device->deviceGrab.grab->type == ButtonPress ||
1082                 device->deviceGrab.grab->type == DeviceButtonPress ||
1083                 device->deviceGrab.grab->type == XI_ButtonPress))
1084                deactivateDeviceGrab = TRUE;
1085        default:
1086            break;
1087    }
1088
1089
1090    if (grab)
1091        DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
1092    else if (device->focus && !IsPointerEvent((InternalEvent*)ev))
1093        DeliverFocusedEvent(device, (InternalEvent*)event,
1094                            GetSpriteWindow(device));
1095    else
1096        DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event,
1097                            NullGrab, NullWindow, device);
1098
1099    if (deactivateDeviceGrab == TRUE)
1100	(*device->deviceGrab.DeactivateGrab) (device);
1101    event->detail.key = key;
1102}
1103
1104int
1105InitProximityClassDeviceStruct(DeviceIntPtr dev)
1106{
1107    ProximityClassPtr proxc;
1108
1109    proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
1110    if (!proxc)
1111	return FALSE;
1112    proxc->sourceid = dev->id;
1113    proxc->in_proximity = TRUE;
1114    dev->proximity = proxc;
1115    return TRUE;
1116}
1117
1118/**
1119 * Initialise the device's valuators. The memory must already be allocated,
1120 * this function merely inits the matching axis (specified through axnum) to
1121 * sane values.
1122 *
1123 * It is a condition that (minval < maxval).
1124 *
1125 * @see InitValuatorClassDeviceStruct
1126 */
1127void
1128InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
1129		       int resolution, int min_res, int max_res, int mode)
1130{
1131    AxisInfoPtr ax;
1132
1133    if (!dev || !dev->valuator || minval > maxval)
1134        return;
1135    if (axnum >= dev->valuator->numAxes)
1136        return;
1137
1138    ax = dev->valuator->axes + axnum;
1139
1140    ax->min_value = minval;
1141    ax->max_value = maxval;
1142    ax->resolution = resolution;
1143    ax->min_resolution = min_res;
1144    ax->max_resolution = max_res;
1145    ax->label = label;
1146    ax->mode = mode;
1147
1148    if (mode & OutOfProximity)
1149        dev->proximity->in_proximity = FALSE;
1150}
1151
1152static void
1153FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
1154		     ButtonClassPtr b, ValuatorClassPtr v, int first)
1155{
1156    ev->type = DeviceStateNotify;
1157    ev->deviceid = dev->id;
1158    ev->time = currentTime.milliseconds;
1159    ev->classes_reported = 0;
1160    ev->num_keys = 0;
1161    ev->num_buttons = 0;
1162    ev->num_valuators = 0;
1163
1164    if (b) {
1165	ev->classes_reported |= (1 << ButtonClass);
1166	ev->num_buttons = b->numButtons;
1167	memcpy((char*)ev->buttons, (char*)b->down, 4);
1168    } else if (k) {
1169	ev->classes_reported |= (1 << KeyClass);
1170	ev->num_keys = k->xkbInfo->desc->max_key_code -
1171                       k->xkbInfo->desc->min_key_code;
1172	memmove((char *)&ev->keys[0], (char *)k->down, 4);
1173    }
1174    if (v) {
1175	int nval = v->numAxes - first;
1176
1177	ev->classes_reported |= (1 << ValuatorClass);
1178	ev->classes_reported |= valuator_get_mode(dev, 0) << ModeBitsShift;
1179	ev->num_valuators = nval < 3 ? nval : 3;
1180	switch (ev->num_valuators) {
1181	case 3:
1182	    ev->valuator2 = v->axisVal[first + 2];
1183	case 2:
1184	    ev->valuator1 = v->axisVal[first + 1];
1185	case 1:
1186	    ev->valuator0 = v->axisVal[first];
1187	    break;
1188	}
1189    }
1190}
1191
1192static void
1193FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
1194		  int first)
1195{
1196    int nval = v->numAxes - first;
1197
1198    ev->type = DeviceValuator;
1199    ev->deviceid = dev->id;
1200    ev->num_valuators = nval < 3 ? nval : 3;
1201    ev->first_valuator = first;
1202    switch (ev->num_valuators) {
1203    case 3:
1204	ev->valuator2 = v->axisVal[first + 2];
1205    case 2:
1206	ev->valuator1 = v->axisVal[first + 1];
1207    case 1:
1208	ev->valuator0 = v->axisVal[first];
1209	break;
1210    }
1211    first += ev->num_valuators;
1212}
1213
1214void
1215DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
1216		 WindowPtr pWin)
1217{
1218    deviceFocus event;
1219    xXIFocusInEvent *xi2event;
1220    DeviceIntPtr mouse;
1221    int btlen, len, i;
1222
1223    mouse = (IsMaster(dev) || dev->u.master) ? GetMaster(dev, MASTER_POINTER) : dev;
1224
1225    /* XI 2 event */
1226    btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
1227    btlen = bytes_to_int32(btlen);
1228    len = sizeof(xXIFocusInEvent) + btlen * 4;
1229
1230    xi2event = calloc(1, len);
1231    xi2event->type         = GenericEvent;
1232    xi2event->extension    = IReqCode;
1233    xi2event->evtype       = type;
1234    xi2event->length       = bytes_to_int32(len - sizeof(xEvent));
1235    xi2event->buttons_len  = btlen;
1236    xi2event->detail       = detail;
1237    xi2event->time         = currentTime.milliseconds;
1238    xi2event->deviceid     = dev->id;
1239    xi2event->sourceid     = dev->id; /* a device doesn't change focus by itself */
1240    xi2event->mode         = mode;
1241    xi2event->root_x       = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
1242    xi2event->root_y       = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
1243
1244    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
1245        if (BitIsOn(mouse->button->down, i))
1246            SetBit(&xi2event[1], i);
1247
1248    if (dev->key)
1249    {
1250        xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods;
1251        xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods;
1252        xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods;
1253        xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods;
1254
1255        xi2event->group.base_group = dev->key->xkbInfo->state.base_group;
1256        xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group;
1257        xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group;
1258        xi2event->group.effective_group = dev->key->xkbInfo->state.group;
1259    }
1260
1261    FixUpEventFromWindow(dev->spriteInfo->sprite, (xEvent*)xi2event, pWin,
1262                         None, FALSE);
1263
1264    DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
1265                          GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
1266
1267    free(xi2event);
1268
1269    /* XI 1.x event */
1270    event.deviceid = dev->id;
1271    event.mode = mode;
1272    event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
1273    event.detail = detail;
1274    event.window = pWin->drawable.id;
1275    event.time = currentTime.milliseconds;
1276
1277    DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
1278				DeviceFocusChangeMask, NullGrab);
1279
1280    if ((event.type == DeviceFocusIn) &&
1281	(wOtherInputMasks(pWin)) &&
1282	(wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
1283    {
1284	int evcount = 1;
1285	deviceStateNotify *ev, *sev;
1286	deviceKeyStateNotify *kev;
1287	deviceButtonStateNotify *bev;
1288
1289	KeyClassPtr k;
1290	ButtonClassPtr b;
1291	ValuatorClassPtr v;
1292	int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
1293
1294	if ((b = dev->button) != NULL) {
1295	    nbuttons = b->numButtons;
1296	    if (nbuttons > 32)
1297		evcount++;
1298	}
1299	if ((k = dev->key) != NULL) {
1300	    nkeys = k->xkbInfo->desc->max_key_code -
1301                    k->xkbInfo->desc->min_key_code;
1302	    if (nkeys > 32)
1303		evcount++;
1304	    if (nbuttons > 0) {
1305		evcount++;
1306	    }
1307	}
1308	if ((v = dev->valuator) != NULL) {
1309	    nval = v->numAxes;
1310
1311	    if (nval > 3)
1312		evcount++;
1313	    if (nval > 6) {
1314		if (!(k && b))
1315		    evcount++;
1316		if (nval > 9)
1317		    evcount += ((nval - 7) / 3);
1318	    }
1319	}
1320
1321	sev = ev = (deviceStateNotify *) malloc(evcount * sizeof(xEvent));
1322	FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
1323
1324	if (b != NULL) {
1325	    FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
1326	    first += 3;
1327	    nval -= 3;
1328	    if (nbuttons > 32) {
1329		(ev - 1)->deviceid |= MORE_EVENTS;
1330		bev = (deviceButtonStateNotify *) ev++;
1331		bev->type = DeviceButtonStateNotify;
1332		bev->deviceid = dev->id;
1333		memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
1334	    }
1335	    if (nval > 0) {
1336		(ev - 1)->deviceid |= MORE_EVENTS;
1337		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1338		first += 3;
1339		nval -= 3;
1340	    }
1341	}
1342
1343	if (k != NULL) {
1344	    FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
1345	    first += 3;
1346	    nval -= 3;
1347	    if (nkeys > 32) {
1348		(ev - 1)->deviceid |= MORE_EVENTS;
1349		kev = (deviceKeyStateNotify *) ev++;
1350		kev->type = DeviceKeyStateNotify;
1351		kev->deviceid = dev->id;
1352		memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
1353	    }
1354	    if (nval > 0) {
1355		(ev - 1)->deviceid |= MORE_EVENTS;
1356		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1357		first += 3;
1358		nval -= 3;
1359	    }
1360	}
1361
1362	while (nval > 0) {
1363	    FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
1364	    first += 3;
1365	    nval -= 3;
1366	    if (nval > 0) {
1367		(ev - 1)->deviceid |= MORE_EVENTS;
1368		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
1369		first += 3;
1370		nval -= 3;
1371	    }
1372	}
1373
1374	DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
1375				    DeviceStateNotifyMask, NullGrab);
1376	free(sev);
1377    }
1378}
1379
1380int
1381CheckGrabValues(ClientPtr client, GrabParameters* param)
1382{
1383    if (param->grabtype != GRABTYPE_CORE &&
1384        param->grabtype != GRABTYPE_XI &&
1385        param->grabtype != GRABTYPE_XI2)
1386    {
1387        ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
1388        return BadImplementation;
1389    }
1390
1391    if ((param->this_device_mode != GrabModeSync) &&
1392	(param->this_device_mode != GrabModeAsync)) {
1393	client->errorValue = param->this_device_mode;
1394	return BadValue;
1395    }
1396    if ((param->other_devices_mode != GrabModeSync) &&
1397	(param->other_devices_mode != GrabModeAsync)) {
1398	client->errorValue = param->other_devices_mode;
1399	return BadValue;
1400    }
1401
1402    if (param->grabtype != GRABTYPE_XI2 && (param->modifiers != AnyModifier) &&
1403        (param->modifiers & ~AllModifiersMask)) {
1404	client->errorValue = param->modifiers;
1405	return BadValue;
1406    }
1407
1408    if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
1409	client->errorValue = param->ownerEvents;
1410	return BadValue;
1411    }
1412    return Success;
1413}
1414
1415int
1416GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
1417           int button, GrabParameters *param, GrabType grabtype,
1418	   GrabMask *mask)
1419{
1420    WindowPtr pWin, confineTo;
1421    CursorPtr cursor;
1422    GrabPtr grab;
1423    int rc, type = -1;
1424    Mask access_mode = DixGrabAccess;
1425
1426    rc = CheckGrabValues(client, param);
1427    if (rc != Success)
1428	return rc;
1429    if (param->confineTo == None)
1430	confineTo = NullWindow;
1431    else {
1432	rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess);
1433	if (rc != Success)
1434	    return rc;
1435    }
1436    if (param->cursor == None)
1437	cursor = NullCursor;
1438    else {
1439	rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
1440				     RT_CURSOR, client, DixUseAccess);
1441	if (rc != Success)
1442	{
1443	    client->errorValue = param->cursor;
1444	    return rc;
1445	}
1446	access_mode |= DixForceAccess;
1447    }
1448    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1449	access_mode |= DixFreezeAccess;
1450    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1451    if (rc != Success)
1452	return rc;
1453    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1454    if (rc != Success)
1455	return rc;
1456
1457    if (grabtype == GRABTYPE_XI)
1458        type = DeviceButtonPress;
1459    else if (grabtype == GRABTYPE_XI2)
1460        type = XI_ButtonPress;
1461
1462    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
1463                      mask, param, type, button, confineTo, cursor);
1464    if (!grab)
1465	return BadAlloc;
1466    return AddPassiveGrabToList(client, grab);
1467}
1468
1469/**
1470 * Grab the given key. If grabtype is GRABTYPE_XI, the key is a keycode. If
1471 * grabtype is GRABTYPE_XI2, the key is a keysym.
1472 */
1473int
1474GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
1475        int key, GrabParameters *param, GrabType grabtype, GrabMask *mask)
1476{
1477    WindowPtr pWin;
1478    GrabPtr grab;
1479    KeyClassPtr k = dev->key;
1480    Mask access_mode = DixGrabAccess;
1481    int rc, type = -1;
1482
1483    rc = CheckGrabValues(client, param);
1484    if (rc != Success)
1485        return rc;
1486    if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL)
1487	return BadMatch;
1488    if (grabtype == GRABTYPE_XI)
1489    {
1490        if ((key > k->xkbInfo->desc->max_key_code ||
1491                    key < k->xkbInfo->desc->min_key_code)
1492                && (key != AnyKey)) {
1493            client->errorValue = key;
1494            return BadValue;
1495        }
1496        type = DeviceKeyPress;
1497    } else if (grabtype == GRABTYPE_XI2)
1498        type = XI_KeyPress;
1499
1500    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1501    if (rc != Success)
1502	return rc;
1503    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1504	access_mode |= DixFreezeAccess;
1505    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1506    if (rc != Success)
1507	return rc;
1508
1509    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
1510                      mask, param, type, key, NULL, NULL);
1511    if (!grab)
1512	return BadAlloc;
1513    return AddPassiveGrabToList(client, grab);
1514}
1515
1516/* Enter/FocusIn grab */
1517int
1518GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
1519           GrabParameters *param, GrabMask *mask)
1520{
1521    WindowPtr pWin;
1522    CursorPtr cursor;
1523    GrabPtr grab;
1524    Mask access_mode = DixGrabAccess;
1525    int rc;
1526
1527    rc = CheckGrabValues(client, param);
1528    if (rc != Success)
1529        return rc;
1530
1531    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
1532    if (rc != Success)
1533	return rc;
1534    if (param->cursor == None)
1535	cursor = NullCursor;
1536    else {
1537	rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
1538				     RT_CURSOR, client, DixUseAccess);
1539	if (rc != Success)
1540	{
1541	    client->errorValue = param->cursor;
1542	    return rc;
1543	}
1544	access_mode |= DixForceAccess;
1545    }
1546    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
1547	access_mode |= DixFreezeAccess;
1548    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
1549    if (rc != Success)
1550	return rc;
1551
1552    grab = CreateGrab(client->index, dev, dev, pWin, GRABTYPE_XI2,
1553                      mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn,
1554                      0, NULL, cursor);
1555
1556    if (!grab)
1557        return BadAlloc;
1558
1559    return AddPassiveGrabToList(client, grab);
1560}
1561
1562int
1563SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
1564		Mask mask, Mask exclusivemasks)
1565{
1566    int mskidx = dev->id;
1567    int i, ret;
1568    Mask check;
1569    InputClientsPtr others;
1570
1571    check = (mask & exclusivemasks);
1572    if (wOtherInputMasks(pWin)) {
1573	if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {	/* It is illegal for two different
1574									 * clients to select on any of the
1575									 * events for maskcheck. However,
1576									 * it is OK, for some client to
1577									 * continue selecting on one of those
1578									 * events.  */
1579	    for (others = wOtherInputMasks(pWin)->inputClients; others;
1580		 others = others->next) {
1581		if (!SameClient(others, client) && (check &
1582						    others->mask[mskidx]))
1583		    return BadAccess;
1584	    }
1585	}
1586	for (others = wOtherInputMasks(pWin)->inputClients; others;
1587	     others = others->next) {
1588	    if (SameClient(others, client)) {
1589		check = others->mask[mskidx];
1590		others->mask[mskidx] = mask;
1591		if (mask == 0) {
1592		    for (i = 0; i < EMASKSIZE; i++)
1593			if (i != mskidx && others->mask[i] != 0)
1594			    break;
1595		    if (i == EMASKSIZE) {
1596			RecalculateDeviceDeliverableEvents(pWin);
1597			if (ShouldFreeInputMasks(pWin, FALSE))
1598			    FreeResource(others->resource, RT_NONE);
1599			return Success;
1600		    }
1601		}
1602		goto maskSet;
1603	    }
1604	}
1605    }
1606    check = 0;
1607    if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
1608	return ret;
1609  maskSet:
1610    if (dev->valuator)
1611	if ((dev->valuator->motionHintWindow == pWin) &&
1612	    (mask & DevicePointerMotionHintMask) &&
1613	    !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
1614	    dev->valuator->motionHintWindow = NullWindow;
1615    RecalculateDeviceDeliverableEvents(pWin);
1616    return Success;
1617}
1618
1619int
1620AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
1621{
1622    InputClientsPtr others;
1623
1624    if (!pWin->optional && !MakeWindowOptional(pWin))
1625	return BadAlloc;
1626    others = calloc(1, sizeof(InputClients));
1627    if (!others)
1628	return BadAlloc;
1629    if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
1630	goto bail;
1631    others->mask[mskidx] = mask;
1632    others->resource = FakeClientID(client->index);
1633    others->next = pWin->optional->inputMasks->inputClients;
1634    pWin->optional->inputMasks->inputClients = others;
1635    if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
1636	goto bail;
1637    return Success;
1638
1639bail:
1640    free(others);
1641    return BadAlloc;
1642}
1643
1644static Bool
1645MakeInputMasks(WindowPtr pWin)
1646{
1647    struct _OtherInputMasks *imasks;
1648
1649    imasks = calloc(1, sizeof(struct _OtherInputMasks));
1650    if (!imasks)
1651	return FALSE;
1652    pWin->optional->inputMasks = imasks;
1653    return TRUE;
1654}
1655
1656void
1657RecalculateDeviceDeliverableEvents(WindowPtr pWin)
1658{
1659    InputClientsPtr others;
1660    struct _OtherInputMasks *inputMasks;	/* default: NULL */
1661    WindowPtr pChild, tmp;
1662    int i, j;
1663
1664    pChild = pWin;
1665    while (1) {
1666	if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
1667            for (i = 0; i < EMASKSIZE; i++)
1668                memset(inputMasks->xi2mask[i], 0, sizeof(inputMasks->xi2mask[i]));
1669	    for (others = inputMasks->inputClients; others;
1670		 others = others->next) {
1671		for (i = 0; i < EMASKSIZE; i++)
1672		    inputMasks->inputEvents[i] |= others->mask[i];
1673                for (i = 0; i < EMASKSIZE; i++)
1674                    for (j = 0; j < XI2MASKSIZE; j++)
1675                        inputMasks->xi2mask[i][j] |= others->xi2mask[i][j];
1676	    }
1677	    for (i = 0; i < EMASKSIZE; i++)
1678		inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
1679	    for (tmp = pChild->parent; tmp; tmp = tmp->parent)
1680		if (wOtherInputMasks(tmp))
1681		    for (i = 0; i < EMASKSIZE; i++)
1682			inputMasks->deliverableEvents[i] |=
1683			    (wOtherInputMasks(tmp)->deliverableEvents[i]
1684			     & ~inputMasks->
1685			     dontPropagateMask[i] & PropagateMask[i]);
1686	}
1687	if (pChild->firstChild) {
1688	    pChild = pChild->firstChild;
1689	    continue;
1690	}
1691	while (!pChild->nextSib && (pChild != pWin))
1692	    pChild = pChild->parent;
1693	if (pChild == pWin)
1694	    break;
1695	pChild = pChild->nextSib;
1696    }
1697}
1698
1699int
1700InputClientGone(WindowPtr pWin, XID id)
1701{
1702    InputClientsPtr other, prev;
1703
1704    if (!wOtherInputMasks(pWin))
1705	return Success;
1706    prev = 0;
1707    for (other = wOtherInputMasks(pWin)->inputClients; other;
1708	 other = other->next) {
1709	if (other->resource == id) {
1710	    if (prev) {
1711		prev->next = other->next;
1712		free(other);
1713	    } else if (!(other->next)) {
1714		if (ShouldFreeInputMasks(pWin, TRUE)) {
1715		    wOtherInputMasks(pWin)->inputClients = other->next;
1716		    free(wOtherInputMasks(pWin));
1717		    pWin->optional->inputMasks = (OtherInputMasks *) NULL;
1718		    CheckWindowOptionalNeed(pWin);
1719		    free(other);
1720		} else {
1721		    other->resource = FakeClientID(0);
1722		    if (!AddResource(other->resource, RT_INPUTCLIENT,
1723				     (pointer) pWin))
1724			return BadAlloc;
1725		}
1726	    } else {
1727		wOtherInputMasks(pWin)->inputClients = other->next;
1728		free(other);
1729	    }
1730	    RecalculateDeviceDeliverableEvents(pWin);
1731	    return Success;
1732	}
1733	prev = other;
1734    }
1735    FatalError("client not on device event list");
1736}
1737
1738int
1739SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
1740	  xEvent * ev, Mask mask, int count)
1741{
1742    WindowPtr pWin;
1743    WindowPtr effectiveFocus = NullWindow;	/* only set if dest==InputFocus */
1744    WindowPtr spriteWin = GetSpriteWindow(d);
1745
1746    if (dest == PointerWindow)
1747	pWin = spriteWin;
1748    else if (dest == InputFocus) {
1749	WindowPtr inputFocus;
1750
1751	if (!d->focus)
1752	    inputFocus = spriteWin;
1753	else
1754	    inputFocus = d->focus->win;
1755
1756	if (inputFocus == FollowKeyboardWin)
1757	    inputFocus = inputInfo.keyboard->focus->win;
1758
1759	if (inputFocus == NoneWin)
1760	    return Success;
1761
1762	/* If the input focus is PointerRootWin, send the event to where
1763	 * the pointer is if possible, then perhaps propogate up to root. */
1764	if (inputFocus == PointerRootWin)
1765	    inputFocus = GetCurrentRootWindow(d);
1766
1767	if (IsParent(inputFocus, spriteWin)) {
1768	    effectiveFocus = inputFocus;
1769	    pWin = spriteWin;
1770	} else
1771	    effectiveFocus = pWin = inputFocus;
1772    } else
1773	dixLookupWindow(&pWin, dest, client, DixSendAccess);
1774    if (!pWin)
1775	return BadWindow;
1776    if ((propagate != xFalse) && (propagate != xTrue)) {
1777	client->errorValue = propagate;
1778	return BadValue;
1779    }
1780    ev->u.u.type |= 0x80;
1781    if (propagate) {
1782	for (; pWin; pWin = pWin->parent) {
1783	    if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
1784		return Success;
1785	    if (pWin == effectiveFocus)
1786		return Success;
1787	    if (wOtherInputMasks(pWin))
1788		mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
1789	    if (!mask)
1790		break;
1791	}
1792    } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
1793	DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
1794    return Success;
1795}
1796
1797int
1798SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
1799{
1800    int i;
1801    ButtonClassPtr b = dev->button;
1802
1803    if (b == NULL)
1804	return BadMatch;
1805
1806    if (nElts != b->numButtons) {
1807	client->errorValue = nElts;
1808	return BadValue;
1809    }
1810    if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
1811	return BadValue;
1812    for (i = 0; i < nElts; i++)
1813	if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
1814	    return MappingBusy;
1815    for (i = 0; i < nElts; i++)
1816	b->map[i + 1] = map[i];
1817    return Success;
1818}
1819
1820int
1821ChangeKeyMapping(ClientPtr client,
1822		 DeviceIntPtr dev,
1823		 unsigned len,
1824		 int type,
1825		 KeyCode firstKeyCode,
1826		 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
1827{
1828    KeySymsRec keysyms;
1829    KeyClassPtr k = dev->key;
1830
1831    if (k == NULL)
1832	return BadMatch;
1833
1834    if (len != (keyCodes * keySymsPerKeyCode))
1835	return BadLength;
1836
1837    if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
1838	(firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
1839	client->errorValue = firstKeyCode;
1840	return BadValue;
1841    }
1842    if (keySymsPerKeyCode == 0) {
1843	client->errorValue = 0;
1844	return BadValue;
1845    }
1846    keysyms.minKeyCode = firstKeyCode;
1847    keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
1848    keysyms.mapWidth = keySymsPerKeyCode;
1849    keysyms.map = map;
1850
1851    XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
1852                          serverClient);
1853
1854    return Success;
1855}
1856
1857static void
1858DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
1859{
1860    WindowPtr parent;
1861
1862    /* Deactivate any grabs performed on this window, before making
1863     * any input focus changes.
1864     * Deactivating a device grab should cause focus events. */
1865
1866    if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
1867	(*dev->deviceGrab.DeactivateGrab) (dev);
1868
1869    /* If the focus window is a root window (ie. has no parent)
1870     * then don't delete the focus from it. */
1871
1872    if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
1873	int focusEventMode = NotifyNormal;
1874
1875	/* If a grab is in progress, then alter the mode of focus events. */
1876
1877	if (dev->deviceGrab.grab)
1878	    focusEventMode = NotifyWhileGrabbed;
1879
1880	switch (dev->focus->revert) {
1881	case RevertToNone:
1882	    if (!ActivateFocusInGrab(dev, pWin, NoneWin))
1883		DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1884	    dev->focus->win = NoneWin;
1885	    dev->focus->traceGood = 0;
1886	    break;
1887	case RevertToParent:
1888	    parent = pWin;
1889	    do {
1890		parent = parent->parent;
1891		dev->focus->traceGood--;
1892	    }
1893	    while (!parent->realized);
1894	    if (!ActivateFocusInGrab(dev, pWin, parent))
1895		DoFocusEvents(dev, pWin, parent, focusEventMode);
1896	    dev->focus->win = parent;
1897	    dev->focus->revert = RevertToNone;
1898	    break;
1899	case RevertToPointerRoot:
1900	    if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
1901		DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
1902	    dev->focus->win = PointerRootWin;
1903	    dev->focus->traceGood = 0;
1904	    break;
1905	case RevertToFollowKeyboard:
1906            {
1907                DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
1908                if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
1909                    kbd = inputInfo.keyboard;
1910	    if (kbd->focus->win) {
1911		if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
1912		    DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
1913		dev->focus->win = FollowKeyboardWin;
1914		dev->focus->traceGood = 0;
1915	    } else {
1916                if (!ActivateFocusInGrab(dev, pWin, NoneWin))
1917                    DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
1918		dev->focus->win = NoneWin;
1919		dev->focus->traceGood = 0;
1920	    }
1921            }
1922	    break;
1923	}
1924    }
1925
1926    if (dev->valuator)
1927	if (dev->valuator->motionHintWindow == pWin)
1928	    dev->valuator->motionHintWindow = NullWindow;
1929}
1930
1931void
1932DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
1933{
1934    int i;
1935    DeviceIntPtr dev;
1936    InputClientsPtr ic;
1937    struct _OtherInputMasks *inputMasks;
1938
1939    for (dev = inputInfo.devices; dev; dev = dev->next) {
1940	DeleteDeviceFromAnyExtEvents(pWin, dev);
1941    }
1942
1943    for (dev = inputInfo.off_devices; dev; dev = dev->next)
1944	DeleteDeviceFromAnyExtEvents(pWin, dev);
1945
1946    if (freeResources)
1947	while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
1948	    ic = inputMasks->inputClients;
1949	    for (i = 0; i < EMASKSIZE; i++)
1950		inputMasks->dontPropagateMask[i] = 0;
1951	    FreeResource(ic->resource, RT_NONE);
1952	}
1953}
1954
1955int
1956MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
1957{
1958    DeviceIntPtr dev;
1959
1960    dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
1961		    DixReadAccess);
1962    if (!dev)
1963        return 0;
1964
1965    if (pEvents->type == DeviceMotionNotify) {
1966	if (mask & DevicePointerMotionHintMask) {
1967	    if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
1968		return 1;	/* don't send, but pretend we did */
1969	    }
1970	    pEvents->detail = NotifyHint;
1971	} else {
1972	    pEvents->detail = NotifyNormal;
1973	}
1974    }
1975    return 0;
1976}
1977
1978void
1979CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
1980			     deviceKeyButtonPointer * xE, GrabPtr grab,
1981			     ClientPtr client, Mask deliveryMask)
1982{
1983    DeviceIntPtr dev;
1984
1985    dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
1986		    DixGrabAccess);
1987    if (!dev)
1988        return;
1989
1990    if (type == DeviceMotionNotify)
1991	dev->valuator->motionHintWindow = pWin;
1992    else if ((type == DeviceButtonPress) && (!grab) &&
1993	     (deliveryMask & DeviceButtonGrabMask)) {
1994	GrabRec tempGrab;
1995
1996	tempGrab.device = dev;
1997	tempGrab.resource = client->clientAsMask;
1998	tempGrab.window = pWin;
1999	tempGrab.ownerEvents =
2000	    (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
2001	tempGrab.eventMask = deliveryMask;
2002	tempGrab.keyboardMode = GrabModeAsync;
2003	tempGrab.pointerMode = GrabModeAsync;
2004	tempGrab.confineTo = NullWindow;
2005	tempGrab.cursor = NullCursor;
2006        tempGrab.next = NULL;
2007	(*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
2008    }
2009}
2010
2011static Mask
2012DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
2013{
2014    InputClientsPtr other;
2015
2016    if (!wOtherInputMasks(pWin))
2017	return 0;
2018    for (other = wOtherInputMasks(pWin)->inputClients; other;
2019	 other = other->next) {
2020	if (SameClient(other, client))
2021	    return other->mask[dev->id];
2022    }
2023    return 0;
2024}
2025
2026void
2027MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
2028{
2029    WindowPtr pWin;
2030    GrabPtr grab = dev->deviceGrab.grab;
2031
2032    pWin = dev->valuator->motionHintWindow;
2033
2034    if ((grab && SameClient(grab, client) &&
2035	 ((grab->eventMask & DevicePointerMotionHintMask) ||
2036	  (grab->ownerEvents &&
2037	   (DeviceEventMaskForClient(dev, pWin, client) &
2038	    DevicePointerMotionHintMask)))) ||
2039	(!grab &&
2040	 (DeviceEventMaskForClient(dev, pWin, client) &
2041	  DevicePointerMotionHintMask)))
2042	dev->valuator->motionHintWindow = NullWindow;
2043}
2044
2045int
2046DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
2047			     int maskndx)
2048{
2049    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2050
2051    if (mask & ~PropagateMask[maskndx]) {
2052	client->errorValue = mask;
2053	return BadValue;
2054    }
2055
2056    if (mask == 0) {
2057	if (inputMasks)
2058	    inputMasks->dontPropagateMask[maskndx] = mask;
2059    } else {
2060	if (!inputMasks)
2061	    AddExtensionClient(pWin, client, 0, 0);
2062	inputMasks = wOtherInputMasks(pWin);
2063	inputMasks->dontPropagateMask[maskndx] = mask;
2064    }
2065    RecalculateDeviceDeliverableEvents(pWin);
2066    if (ShouldFreeInputMasks(pWin, FALSE))
2067	FreeResource(inputMasks->inputClients->resource, RT_NONE);
2068    return Success;
2069}
2070
2071Bool
2072ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
2073{
2074    int i;
2075    Mask allInputEventMasks = 0;
2076    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2077
2078    for (i = 0; i < EMASKSIZE; i++)
2079	allInputEventMasks |= inputMasks->dontPropagateMask[i];
2080    if (!ignoreSelectedEvents)
2081	for (i = 0; i < EMASKSIZE; i++)
2082	    allInputEventMasks |= inputMasks->inputEvents[i];
2083    if (allInputEventMasks == 0)
2084	return TRUE;
2085    else
2086	return FALSE;
2087}
2088
2089/***********************************************************************
2090 *
2091 * Walk through the window tree, finding all clients that want to know
2092 * about the Event.
2093 *
2094 */
2095
2096static void
2097FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
2098                       xEvent * ev, int count)
2099{
2100    WindowPtr p2;
2101
2102    while (p1) {
2103        p2 = p1->firstChild;
2104        DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
2105        FindInterestedChildren(dev, p2, mask, ev, count);
2106        p1 = p1->nextSib;
2107    }
2108}
2109
2110/***********************************************************************
2111 *
2112 * Send an event to interested clients in all windows on all screens.
2113 *
2114 */
2115
2116void
2117SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
2118{
2119    int i;
2120    WindowPtr pWin, p1;
2121
2122    for (i = 0; i < screenInfo.numScreens; i++) {
2123        pWin = screenInfo.screens[i]->root;
2124        if (!pWin)
2125            continue;
2126        DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
2127        p1 = pWin->firstChild;
2128        FindInterestedChildren(dev, p1, mask, ev, count);
2129    }
2130}
2131
2132/**
2133 * Set the XI2 mask for the given client on the given window.
2134 * @param dev The device to set the mask for.
2135 * @param win The window to set the mask on.
2136 * @param client The client setting the mask.
2137 * @param len Number of bytes in mask.
2138 * @param mask Event mask in the form of (1 << eventtype)
2139 */
2140int
2141XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
2142               unsigned int len, unsigned char* mask)
2143{
2144    OtherInputMasks *masks;
2145    InputClientsPtr others = NULL;
2146
2147    masks = wOtherInputMasks(win);
2148    if (masks)
2149    {
2150	for (others = wOtherInputMasks(win)->inputClients; others;
2151	     others = others->next) {
2152	    if (SameClient(others, client)) {
2153                memset(others->xi2mask[dev->id], 0,
2154                       sizeof(others->xi2mask[dev->id]));
2155                break;
2156            }
2157        }
2158    }
2159
2160    len = min(len, sizeof(others->xi2mask[dev->id]));
2161
2162    if (len && !others)
2163    {
2164        if (AddExtensionClient(win, client, 0, 0) != Success)
2165            return BadAlloc;
2166        others= wOtherInputMasks(win)->inputClients;
2167    }
2168
2169    if (others)
2170        memset(others->xi2mask[dev->id], 0, sizeof(others->xi2mask[dev->id]));
2171
2172    if (len)
2173        memcpy(others->xi2mask[dev->id], mask, len);
2174
2175    RecalculateDeviceDeliverableEvents(win);
2176
2177    return Success;
2178}
2179