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