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 * Copyright © 2010 Collabora Ltd.
49 * Copyright © 2011 Red Hat, Inc.
50 *
51 * Permission is hereby granted, free of charge, to any person obtaining a
52 * copy of this software and associated documentation files (the "Software"),
53 * to deal in the Software without restriction, including without limitation
54 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
55 * and/or sell copies of the Software, and to permit persons to whom the
56 * Software is furnished to do so, subject to the following conditions:
57 *
58 * The above copyright notice and this permission notice (including the next
59 * paragraph) shall be included in all copies or substantial portions of the
60 * Software.
61 *
62 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
65 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
66 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
67 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
68 * DEALINGS IN THE SOFTWARE.
69 *
70 * Author: Daniel Stone <daniel@fooishbar.org>
71 */
72
73/********************************************************************
74 *
75 *  Routines to register and initialize extension input devices.
76 *  This also contains ProcessOtherEvent, the routine called from DDX
77 *  to route extension events.
78 *
79 */
80
81#ifdef HAVE_DIX_CONFIG_H
82#include <dix-config.h>
83#endif
84
85#include "inputstr.h"
86#include <X11/X.h>
87#include <X11/Xproto.h>
88#include <X11/extensions/XI.h>
89#include <X11/extensions/XIproto.h>
90#include <X11/extensions/XI2proto.h>
91#include <X11/extensions/geproto.h>
92#include "windowstr.h"
93#include "miscstruct.h"
94#include "region.h"
95#include "exevents.h"
96#include "extnsionst.h"
97#include "exglobals.h"
98#include "eventstr.h"
99#include "dixevents.h"          /* DeliverFocusedEvent */
100#include "dixgrabs.h"           /* CreateGrab() */
101#include "scrnintstr.h"
102#include "listdev.h"            /* for CopySwapXXXClass */
103#include "xace.h"
104#include "xiquerydevice.h"      /* For List*Info */
105#include "eventconvert.h"
106#include "eventstr.h"
107#include "inpututils.h"
108#include "mi.h"
109
110#include <X11/extensions/XKBproto.h>
111#include "xkbsrv.h"
112
113#define WID(w) ((w) ? ((w)->drawable.id) : 0)
114#define AllModifiersMask ( \
115	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
116	Mod3Mask | Mod4Mask | Mod5Mask )
117#define AllButtonsMask ( \
118	Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
119
120Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
121                          Bool  /* ignoreSelectedEvents */
122    );
123static Bool MakeInputMasks(WindowPtr    /* pWin */
124    );
125
126/*
127 * Only let the given client know of core events which will affect its
128 * interpretation of input events, if the client's ClientPointer (or the
129 * paired keyboard) is the current device.
130 */
131int
132XIShouldNotify(ClientPtr client, DeviceIntPtr dev)
133{
134    DeviceIntPtr current_ptr = PickPointer(client);
135    DeviceIntPtr current_kbd = GetMaster(current_ptr, KEYBOARD_OR_FLOAT);
136
137    if (dev == current_kbd || dev == current_ptr)
138        return 1;
139
140    return 0;
141}
142
143Bool
144IsPointerEvent(InternalEvent *event)
145{
146    switch (event->any.type) {
147    case ET_ButtonPress:
148    case ET_ButtonRelease:
149    case ET_Motion:
150        /* XXX: enter/leave ?? */
151        return TRUE;
152    default:
153        break;
154    }
155    return FALSE;
156}
157
158Bool
159IsTouchEvent(InternalEvent *event)
160{
161    switch (event->any.type) {
162    case ET_TouchBegin:
163    case ET_TouchUpdate:
164    case ET_TouchEnd:
165        return TRUE;
166    default:
167        break;
168    }
169    return FALSE;
170}
171
172Bool
173IsGestureEvent(InternalEvent *event)
174{
175    switch (event->any.type) {
176    case ET_GesturePinchBegin:
177    case ET_GesturePinchUpdate:
178    case ET_GesturePinchEnd:
179    case ET_GestureSwipeBegin:
180    case ET_GestureSwipeUpdate:
181    case ET_GestureSwipeEnd:
182        return TRUE;
183    default:
184        break;
185    }
186    return FALSE;
187}
188
189Bool
190IsGestureBeginEvent(InternalEvent *event)
191{
192    switch (event->any.type) {
193    case ET_GesturePinchBegin:
194    case ET_GestureSwipeBegin:
195        return TRUE;
196    default:
197        break;
198    }
199    return FALSE;
200}
201
202Bool
203IsGestureEndEvent(InternalEvent *event)
204{
205    switch (event->any.type) {
206    case ET_GesturePinchEnd:
207    case ET_GestureSwipeEnd:
208        return TRUE;
209    default:
210        break;
211    }
212    return FALSE;
213}
214
215/**
216 * @return the device matching the deviceid of the device set in the event, or
217 * NULL if the event is not an XInput event.
218 */
219DeviceIntPtr
220XIGetDevice(xEvent *xE)
221{
222    DeviceIntPtr pDev = NULL;
223
224    if (xE->u.u.type == DeviceButtonPress ||
225        xE->u.u.type == DeviceButtonRelease ||
226        xE->u.u.type == DeviceMotionNotify ||
227        xE->u.u.type == ProximityIn ||
228        xE->u.u.type == ProximityOut || xE->u.u.type == DevicePropertyNotify) {
229        int rc;
230        int id;
231
232        id = ((deviceKeyButtonPointer *) xE)->deviceid & ~MORE_EVENTS;
233
234        rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
235        if (rc != Success)
236            ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
237    }
238    return pDev;
239}
240
241/**
242 * Copy the device->key into master->key and send a mapping notify to the
243 * clients if appropriate.
244 * master->key needs to be allocated by the caller.
245 *
246 * Device is the slave device. If it is attached to a master device, we may
247 * need to send a mapping notify to the client because it causes the MD
248 * to change state.
249 *
250 * Mapping notify needs to be sent in the following cases:
251 *      - different slave device on same master
252 *      - different master
253 *
254 * XXX: They way how the code is we also send a map notify if the slave device
255 * stays the same, but the master changes. This isn't really necessary though.
256 *
257 * XXX: this gives you funny behaviour with the ClientPointer. When a
258 * MappingNotify is sent to the client, the client usually responds with a
259 * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
260 * mapping, regardless of which keyboard sent the last mapping notify request.
261 * So depending on the CP setting, your keyboard may change layout in each
262 * app...
263 *
264 * This code is basically the old SwitchCoreKeyboard.
265 */
266
267void
268CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
269{
270    KeyClassPtr mk = master->key;
271
272    if (device == master)
273        return;
274
275    mk->sourceid = device->id;
276
277    if (!XkbDeviceApplyKeymap(master, device->key->xkbInfo->desc))
278        FatalError("Couldn't pivot keymap from device to core!\n");
279}
280
281/**
282 * Copies the feedback classes from device "from" into device "to". Classes
283 * are duplicated (not just flipping the pointers). All feedback classes are
284 * linked lists, the full list is duplicated.
285 */
286static void
287DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
288{
289    ClassesPtr classes;
290
291    if (from->intfeed) {
292        IntegerFeedbackPtr *i, it;
293
294        if (!to->intfeed) {
295            classes = to->unused_classes;
296            to->intfeed = classes->intfeed;
297            classes->intfeed = NULL;
298        }
299
300        i = &to->intfeed;
301        for (it = from->intfeed; it; it = it->next) {
302            if (!(*i)) {
303                *i = calloc(1, sizeof(IntegerFeedbackClassRec));
304                if (!(*i)) {
305                    ErrorF("[Xi] Cannot alloc memory for class copy.");
306                    return;
307                }
308            }
309            (*i)->CtrlProc = it->CtrlProc;
310            (*i)->ctrl = it->ctrl;
311
312            i = &(*i)->next;
313        }
314    }
315    else if (to->intfeed && !from->intfeed) {
316        classes = to->unused_classes;
317        classes->intfeed = to->intfeed;
318        to->intfeed = NULL;
319    }
320
321    if (from->stringfeed) {
322        StringFeedbackPtr *s, it;
323
324        if (!to->stringfeed) {
325            classes = to->unused_classes;
326            to->stringfeed = classes->stringfeed;
327            classes->stringfeed = NULL;
328        }
329
330        s = &to->stringfeed;
331        for (it = from->stringfeed; it; it = it->next) {
332            if (!(*s)) {
333                *s = calloc(1, sizeof(StringFeedbackClassRec));
334                if (!(*s)) {
335                    ErrorF("[Xi] Cannot alloc memory for class copy.");
336                    return;
337                }
338            }
339            (*s)->CtrlProc = it->CtrlProc;
340            (*s)->ctrl = it->ctrl;
341
342            s = &(*s)->next;
343        }
344    }
345    else if (to->stringfeed && !from->stringfeed) {
346        classes = to->unused_classes;
347        classes->stringfeed = to->stringfeed;
348        to->stringfeed = NULL;
349    }
350
351    if (from->bell) {
352        BellFeedbackPtr *b, it;
353
354        if (!to->bell) {
355            classes = to->unused_classes;
356            to->bell = classes->bell;
357            classes->bell = NULL;
358        }
359
360        b = &to->bell;
361        for (it = from->bell; it; it = it->next) {
362            if (!(*b)) {
363                *b = calloc(1, sizeof(BellFeedbackClassRec));
364                if (!(*b)) {
365                    ErrorF("[Xi] Cannot alloc memory for class copy.");
366                    return;
367                }
368            }
369            (*b)->BellProc = it->BellProc;
370            (*b)->CtrlProc = it->CtrlProc;
371            (*b)->ctrl = it->ctrl;
372
373            b = &(*b)->next;
374        }
375    }
376    else if (to->bell && !from->bell) {
377        classes = to->unused_classes;
378        classes->bell = to->bell;
379        to->bell = NULL;
380    }
381
382    if (from->leds) {
383        LedFeedbackPtr *l, it;
384
385        if (!to->leds) {
386            classes = to->unused_classes;
387            to->leds = classes->leds;
388            classes->leds = NULL;
389        }
390
391        l = &to->leds;
392        for (it = from->leds; it; it = it->next) {
393            if (!(*l)) {
394                *l = calloc(1, sizeof(LedFeedbackClassRec));
395                if (!(*l)) {
396                    ErrorF("[Xi] Cannot alloc memory for class copy.");
397                    return;
398                }
399            }
400            (*l)->CtrlProc = it->CtrlProc;
401            (*l)->ctrl = it->ctrl;
402            if ((*l)->xkb_sli)
403                XkbFreeSrvLedInfo((*l)->xkb_sli);
404            (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
405
406            l = &(*l)->next;
407        }
408    }
409    else if (to->leds && !from->leds) {
410        classes = to->unused_classes;
411        classes->leds = to->leds;
412        to->leds = NULL;
413    }
414}
415
416static void
417DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
418{
419    ClassesPtr classes;
420
421    /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
422     * kbdfeed to be set up properly, so let's do the feedback classes first.
423     */
424    if (from->kbdfeed) {
425        KbdFeedbackPtr *k, it;
426
427        if (!to->kbdfeed) {
428            classes = to->unused_classes;
429
430            to->kbdfeed = classes->kbdfeed;
431            if (!to->kbdfeed)
432                InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
433            classes->kbdfeed = NULL;
434        }
435
436        k = &to->kbdfeed;
437        for (it = from->kbdfeed; it; it = it->next) {
438            if (!(*k)) {
439                *k = calloc(1, sizeof(KbdFeedbackClassRec));
440                if (!*k) {
441                    ErrorF("[Xi] Cannot alloc memory for class copy.");
442                    return;
443                }
444            }
445            (*k)->BellProc = it->BellProc;
446            (*k)->CtrlProc = it->CtrlProc;
447            (*k)->ctrl = it->ctrl;
448            if ((*k)->xkb_sli)
449                XkbFreeSrvLedInfo((*k)->xkb_sli);
450            (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
451
452            k = &(*k)->next;
453        }
454    }
455    else if (to->kbdfeed && !from->kbdfeed) {
456        classes = to->unused_classes;
457        classes->kbdfeed = to->kbdfeed;
458        to->kbdfeed = NULL;
459    }
460
461    if (from->key) {
462        if (!to->key) {
463            classes = to->unused_classes;
464            to->key = classes->key;
465            if (!to->key)
466                InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
467            else
468                classes->key = NULL;
469        }
470
471        CopyKeyClass(from, to);
472    }
473    else if (to->key && !from->key) {
474        classes = to->unused_classes;
475        classes->key = to->key;
476        to->key = NULL;
477    }
478
479    /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps
480     * pointer point into the xkbInfo->desc struct.  XkbCopySrvLedInfo
481     * didn't update the pointers so we need to do it manually here.
482     */
483    if (to->kbdfeed) {
484        KbdFeedbackPtr k;
485
486        for (k = to->kbdfeed; k; k = k->next) {
487            if (!k->xkb_sli)
488                continue;
489            if (k->xkb_sli->flags & XkbSLI_IsDefault) {
490                k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators;
491                k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps;
492            }
493        }
494    }
495
496    /* We can't just copy over the focus class. When an app sets the focus,
497     * it'll do so on the master device. Copying the SDs focus means losing
498     * the focus.
499     * So we only copy the focus class if the device didn't have one,
500     * otherwise we leave it as it is.
501     */
502    if (from->focus) {
503        if (!to->focus) {
504            WindowPtr *oldTrace;
505
506            classes = to->unused_classes;
507            to->focus = classes->focus;
508            if (!to->focus) {
509                to->focus = calloc(1, sizeof(FocusClassRec));
510                if (!to->focus)
511                    FatalError("[Xi] no memory for class shift.\n");
512            }
513            else
514                classes->focus = NULL;
515
516            oldTrace = to->focus->trace;
517            memcpy(to->focus, from->focus, sizeof(FocusClassRec));
518            to->focus->trace = reallocarray(oldTrace,
519                                            to->focus->traceSize,
520                                            sizeof(WindowPtr));
521            if (!to->focus->trace && to->focus->traceSize)
522                FatalError("[Xi] no memory for trace.\n");
523            memcpy(to->focus->trace, from->focus->trace,
524                   from->focus->traceSize * sizeof(WindowPtr));
525            to->focus->sourceid = from->id;
526        }
527    }
528    else if (to->focus) {
529        classes = to->unused_classes;
530        classes->focus = to->focus;
531        to->focus = NULL;
532    }
533
534}
535
536/* FIXME: this should really be shared with the InitValuatorAxisClassRec and
537 * similar */
538static void
539DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
540{
541    ClassesPtr classes;
542
543    /* Feedback classes must be copied first */
544    if (from->ptrfeed) {
545        PtrFeedbackPtr *p, it;
546
547        if (!to->ptrfeed) {
548            classes = to->unused_classes;
549            to->ptrfeed = classes->ptrfeed;
550            classes->ptrfeed = NULL;
551        }
552
553        p = &to->ptrfeed;
554        for (it = from->ptrfeed; it; it = it->next) {
555            if (!(*p)) {
556                *p = calloc(1, sizeof(PtrFeedbackClassRec));
557                if (!*p) {
558                    ErrorF("[Xi] Cannot alloc memory for class copy.");
559                    return;
560                }
561            }
562            (*p)->CtrlProc = it->CtrlProc;
563            (*p)->ctrl = it->ctrl;
564
565            p = &(*p)->next;
566        }
567    }
568    else if (to->ptrfeed && !from->ptrfeed) {
569        classes = to->unused_classes;
570        classes->ptrfeed = to->ptrfeed;
571        to->ptrfeed = NULL;
572    }
573
574    if (from->valuator) {
575        ValuatorClassPtr v;
576
577        if (!to->valuator) {
578            classes = to->unused_classes;
579            to->valuator = classes->valuator;
580            if (to->valuator)
581                classes->valuator = NULL;
582        }
583
584        v = AllocValuatorClass(to->valuator, from->valuator->numAxes);
585
586        if (!v)
587            FatalError("[Xi] no memory for class shift.\n");
588
589        to->valuator = v;
590        memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
591
592        v->sourceid = from->id;
593    }
594    else if (to->valuator && !from->valuator) {
595        classes = to->unused_classes;
596        classes->valuator = to->valuator;
597        to->valuator = NULL;
598    }
599
600    if (from->button) {
601        if (!to->button) {
602            classes = to->unused_classes;
603            to->button = classes->button;
604            if (!to->button) {
605                to->button = calloc(1, sizeof(ButtonClassRec));
606                if (!to->button)
607                    FatalError("[Xi] no memory for class shift.\n");
608                to->button->numButtons = from->button->numButtons;
609            }
610            else
611                classes->button = NULL;
612        }
613
614        if (from->button->xkb_acts) {
615            size_t maxbuttons = max(to->button->numButtons, from->button->numButtons);
616            to->button->xkb_acts = xnfreallocarray(to->button->xkb_acts,
617                                                   maxbuttons,
618                                                   sizeof(XkbAction));
619            memset(to->button->xkb_acts, 0, maxbuttons * sizeof(XkbAction));
620            memcpy(to->button->xkb_acts, from->button->xkb_acts,
621                   from->button->numButtons * sizeof(XkbAction));
622        }
623        else {
624            free(to->button->xkb_acts);
625            to->button->xkb_acts = NULL;
626        }
627
628        memcpy(to->button->labels, from->button->labels,
629               from->button->numButtons * sizeof(Atom));
630        to->button->sourceid = from->id;
631    }
632    else if (to->button && !from->button) {
633        classes = to->unused_classes;
634        classes->button = to->button;
635        to->button = NULL;
636    }
637
638    if (from->proximity) {
639        if (!to->proximity) {
640            classes = to->unused_classes;
641            to->proximity = classes->proximity;
642            if (!to->proximity) {
643                to->proximity = calloc(1, sizeof(ProximityClassRec));
644                if (!to->proximity)
645                    FatalError("[Xi] no memory for class shift.\n");
646            }
647            else
648                classes->proximity = NULL;
649        }
650        memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
651        to->proximity->sourceid = from->id;
652    }
653    else if (to->proximity) {
654        classes = to->unused_classes;
655        classes->proximity = to->proximity;
656        to->proximity = NULL;
657    }
658
659    if (from->touch) {
660        TouchClassPtr t, f;
661
662        if (!to->touch) {
663            classes = to->unused_classes;
664            to->touch = classes->touch;
665            if (!to->touch) {
666                int i;
667
668                to->touch = calloc(1, sizeof(TouchClassRec));
669                if (!to->touch)
670                    FatalError("[Xi] no memory for class shift.\n");
671                to->touch->num_touches = from->touch->num_touches;
672                to->touch->touches = calloc(to->touch->num_touches,
673                                            sizeof(TouchPointInfoRec));
674                for (i = 0; i < to->touch->num_touches; i++)
675                    TouchInitTouchPoint(to->touch, to->valuator, i);
676                if (!to->touch)
677                    FatalError("[Xi] no memory for class shift.\n");
678            }
679            else
680                classes->touch = NULL;
681        }
682
683        t = to->touch;
684        f = from->touch;
685        t->sourceid = f->sourceid;
686        t->max_touches = f->max_touches;
687        t->mode = f->mode;
688        t->buttonsDown = f->buttonsDown;
689        t->state = f->state;
690        t->motionMask = f->motionMask;
691        /* to->touches and to->num_touches are separate on the master,
692         * don't copy */
693    }
694    /* Don't remove touch class if from->touch is non-existent. The to device
695     * may have an active touch grab, so we need to keep the touch class record
696     * around. */
697
698    if (from->gesture) {
699        if (!to->gesture) {
700            classes = to->unused_classes;
701            to->gesture = classes->gesture;
702            if (!to->gesture) {
703                if (!InitGestureClassDeviceStruct(to, from->gesture->max_touches))
704                    FatalError("[Xi] no memory for class shift.\n");
705            }
706            else
707                classes->gesture = NULL;
708        }
709
710        to->gesture->sourceid = from->gesture->sourceid;
711        /* to->gesture->gesture is separate on the master,  don't copy */
712    }
713    /* Don't remove gesture class if from->gesture is non-existent. The to device
714     * may have an active gesture grab, so we need to keep the gesture class record
715     * around. */
716}
717
718/**
719 * Copies the CONTENT of the classes of device from into the classes in device
720 * to. From and to are identical after finishing.
721 *
722 * If to does not have classes from currently has, the classes are stored in
723 * to's devPrivates system. Later, we recover it again from there if needed.
724 * Saves a few memory allocations.
725 */
726void
727DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to,
728                      DeviceChangedEvent *dce)
729{
730    input_lock();
731
732    /* generic feedback classes, not tied to pointer and/or keyboard */
733    DeepCopyFeedbackClasses(from, to);
734
735    if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
736        DeepCopyKeyboardClasses(from, to);
737    if ((dce->flags & DEVCHANGE_POINTER_EVENT))
738        DeepCopyPointerClasses(from, to);
739
740    input_unlock();
741}
742
743/**
744 * Send an XI2 DeviceChangedEvent to all interested clients.
745 */
746void
747XISendDeviceChangedEvent(DeviceIntPtr device, DeviceChangedEvent *dce)
748{
749    xXIDeviceChangedEvent *dcce;
750    int rc;
751
752    rc = EventToXI2((InternalEvent *) dce, (xEvent **) &dcce);
753    if (rc != Success) {
754        ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc);
755        return;
756    }
757
758    /* we don't actually swap if there's a NullClient, swapping is done
759     * later when event is delivered. */
760    SendEventToAllWindows(device, XI_DeviceChangedMask, (xEvent *) dcce, 1);
761    free(dcce);
762}
763
764static void
765ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
766{
767    DeviceIntPtr slave;
768    int rc;
769
770    /* For now, we don't have devices that change physically. */
771    if (!IsMaster(device))
772        return;
773
774    rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
775
776    if (rc != Success)
777        return;                 /* Device has disappeared */
778
779    if (IsMaster(slave))
780        return;
781
782    if (IsFloating(slave))
783        return;                 /* set floating since the event */
784
785    if (GetMaster(slave, MASTER_ATTACHED)->id != dce->masterid)
786        return;                 /* not our slave anymore, don't care */
787
788    /* FIXME: we probably need to send a DCE for the new slave now */
789
790    device->public.devicePrivate = slave->public.devicePrivate;
791
792    /* FIXME: the classes may have changed since we generated the event. */
793    DeepCopyDeviceClasses(slave, device, dce);
794    dce->deviceid = device->id;
795    XISendDeviceChangedEvent(device, dce);
796}
797
798/**
799 * Add state and motionMask to the filter for this event. The protocol
800 * supports some extra masks for motion when a button is down:
801 * ButtonXMotionMask and the DeviceButtonMotionMask to trigger only when at
802 * least one button (or that specific button is down). These masks need to
803 * be added to the filters for core/XI motion events.
804 *
805 * @param device The device to update the mask for
806 * @param state The current button state mask
807 * @param motion_mask The motion mask (DeviceButtonMotionMask or 0)
808 */
809static void
810UpdateDeviceMotionMask(DeviceIntPtr device, unsigned short state,
811                       Mask motion_mask)
812{
813    Mask mask;
814
815    mask = PointerMotionMask | state | motion_mask;
816    SetMaskForEvent(device->id, mask, DeviceMotionNotify);
817    SetMaskForEvent(device->id, mask, MotionNotify);
818}
819
820static void
821IncreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down,
822                    Mask *motion_mask, unsigned short *state)
823{
824    if (dev->valuator)
825        dev->valuator->motionHintWindow = NullWindow;
826
827    (*buttons_down)++;
828    *motion_mask = DeviceButtonMotionMask;
829    if (dev->button->map[key] <= 5)
830        *state |= (Button1Mask >> 1) << dev->button->map[key];
831}
832
833static void
834DecreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down,
835                    Mask *motion_mask, unsigned short *state)
836{
837    if (dev->valuator)
838        dev->valuator->motionHintWindow = NullWindow;
839
840    if (*buttons_down >= 1 && !--(*buttons_down))
841        *motion_mask = 0;
842    if (dev->button->map[key] <= 5)
843        *state &= ~((Button1Mask >> 1) << dev->button->map[key]);
844}
845
846/**
847 * Update the device state according to the data in the event.
848 *
849 * return values are
850 *   DEFAULT ... process as normal
851 *   DONT_PROCESS ... return immediately from caller
852 */
853#define DEFAULT 0
854#define DONT_PROCESS 1
855int
856UpdateDeviceState(DeviceIntPtr device, DeviceEvent *event)
857{
858    int i;
859    int key = 0, last_valuator;
860
861    KeyClassPtr k = NULL;
862    ButtonClassPtr b = NULL;
863    ValuatorClassPtr v = NULL;
864    TouchClassPtr t = NULL;
865
866    /* This event is always the first we get, before the actual events with
867     * the data. However, the way how the DDX is set up, "device" will
868     * actually be the slave device that caused the event.
869     */
870    switch (event->type) {
871    case ET_DeviceChanged:
872        ChangeMasterDeviceClasses(device, (DeviceChangedEvent *) event);
873        return DONT_PROCESS;    /* event has been sent already */
874    case ET_Motion:
875    case ET_ButtonPress:
876    case ET_ButtonRelease:
877    case ET_KeyPress:
878    case ET_KeyRelease:
879    case ET_ProximityIn:
880    case ET_ProximityOut:
881    case ET_TouchBegin:
882    case ET_TouchUpdate:
883    case ET_TouchEnd:
884        break;
885    default:
886        /* other events don't update the device */
887        return DEFAULT;
888    }
889
890    k = device->key;
891    v = device->valuator;
892    b = device->button;
893    t = device->touch;
894
895    key = event->detail.key;
896
897    /* Update device axis */
898    /* Check valuators first */
899    last_valuator = -1;
900    for (i = 0; i < MAX_VALUATORS; i++) {
901        if (BitIsOn(&event->valuators.mask, i)) {
902            if (!v) {
903                ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
904                       "Ignoring event.\n", device->name);
905                return DONT_PROCESS;
906            }
907            else if (v->numAxes < i) {
908                ErrorF("[Xi] Too many valuators reported for device '%s'. "
909                       "Ignoring event.\n", device->name);
910                return DONT_PROCESS;
911            }
912            last_valuator = i;
913        }
914    }
915
916    for (i = 0; i <= last_valuator && i < v->numAxes; i++) {
917        /* XXX: Relative/Absolute mode */
918        if (BitIsOn(&event->valuators.mask, i))
919            v->axisVal[i] = event->valuators.data[i];
920    }
921
922    if (event->type == ET_KeyPress) {
923        if (!k)
924            return DONT_PROCESS;
925
926        /* don't allow ddx to generate multiple downs, but repeats are okay */
927        if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
928            return DONT_PROCESS;
929
930        if (device->valuator)
931            device->valuator->motionHintWindow = NullWindow;
932        set_key_down(device, key, KEY_PROCESSED);
933    }
934    else if (event->type == ET_KeyRelease) {
935        if (!k)
936            return DONT_PROCESS;
937
938        if (!key_is_down(device, key, KEY_PROCESSED))   /* guard against duplicates */
939            return DONT_PROCESS;
940        if (device->valuator)
941            device->valuator->motionHintWindow = NullWindow;
942        set_key_up(device, key, KEY_PROCESSED);
943    }
944    else if (event->type == ET_ButtonPress) {
945        if (!b)
946            return DONT_PROCESS;
947
948        if (button_is_down(device, key, BUTTON_PROCESSED))
949            return DONT_PROCESS;
950
951        set_button_down(device, key, BUTTON_PROCESSED);
952
953        if (!b->map[key])
954            return DONT_PROCESS;
955
956        IncreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask,
957                            &b->state);
958        UpdateDeviceMotionMask(device, b->state, b->motionMask);
959    }
960    else if (event->type == ET_ButtonRelease) {
961        if (!b)
962            return DONT_PROCESS;
963
964        if (!button_is_down(device, key, BUTTON_PROCESSED))
965            return DONT_PROCESS;
966        if (IsMaster(device)) {
967            DeviceIntPtr sd;
968
969            /*
970             * Leave the button down if any slave has the
971             * button still down. Note that this depends on the
972             * event being delivered through the slave first
973             */
974            for (sd = inputInfo.devices; sd; sd = sd->next) {
975                if (IsMaster(sd) || GetMaster(sd, MASTER_POINTER) != device)
976                    continue;
977                if (!sd->button)
978                    continue;
979                for (i = 1; i <= sd->button->numButtons; i++)
980                    if (sd->button->map[i] == key &&
981                        button_is_down(sd, i, BUTTON_PROCESSED))
982                        return DONT_PROCESS;
983            }
984        }
985        set_button_up(device, key, BUTTON_PROCESSED);
986        if (!b->map[key])
987            return DONT_PROCESS;
988
989        DecreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask,
990                            &b->state);
991        UpdateDeviceMotionMask(device, b->state, b->motionMask);
992    }
993    else if (event->type == ET_ProximityIn)
994        device->proximity->in_proximity = TRUE;
995    else if (event->type == ET_ProximityOut)
996        device->proximity->in_proximity = FALSE;
997    else if (event->type == ET_TouchBegin) {
998        BUG_RETURN_VAL(!b || !v, DONT_PROCESS);
999        BUG_RETURN_VAL(!t, DONT_PROCESS);
1000
1001        if (!b->map[key])
1002            return DONT_PROCESS;
1003
1004        if (!(event->flags & TOUCH_POINTER_EMULATED) ||
1005            (event->flags & TOUCH_REPLAYING))
1006            return DONT_PROCESS;
1007
1008        IncreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask,
1009                            &t->state);
1010        UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask);
1011    }
1012    else if (event->type == ET_TouchEnd) {
1013        BUG_RETURN_VAL(!b || !v, DONT_PROCESS);
1014        BUG_RETURN_VAL(!t, DONT_PROCESS);
1015
1016        if (t->buttonsDown <= 0 || !b->map[key])
1017            return DONT_PROCESS;
1018
1019        if (!(event->flags & TOUCH_POINTER_EMULATED))
1020            return DONT_PROCESS;
1021
1022        DecreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask,
1023                            &t->state);
1024        UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask);
1025    }
1026
1027    return DEFAULT;
1028}
1029
1030/**
1031 * A client that does not have the TouchOwnership mask set may not receive a
1032 * TouchBegin event if there is at least one grab active.
1033 *
1034 * @return TRUE if the client selected for ownership events on the given
1035 * window for this device, FALSE otherwise
1036 */
1037static inline Bool
1038TouchClientWantsOwnershipEvents(ClientPtr client, DeviceIntPtr dev,
1039                                WindowPtr win)
1040{
1041    InputClients *iclient;
1042
1043    nt_list_for_each_entry(iclient, wOtherInputMasks(win)->inputClients, next) {
1044        if (rClient(iclient) != client)
1045            continue;
1046
1047        return xi2mask_isset(iclient->xi2mask, dev, XI_TouchOwnership);
1048    }
1049
1050    return FALSE;
1051}
1052
1053static void
1054TouchSendOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, int reason,
1055                        XID resource)
1056{
1057    int nev, i;
1058    InternalEvent *tel = InitEventList(GetMaximumEventsNum());
1059
1060    nev = GetTouchOwnershipEvents(tel, dev, ti, reason, resource, 0);
1061    for (i = 0; i < nev; i++)
1062        mieqProcessDeviceEvent(dev, tel + i, NULL);
1063
1064    FreeEventList(tel, GetMaximumEventsNum());
1065}
1066
1067/**
1068 * Attempts to deliver a touch event to the given client.
1069 */
1070static Bool
1071DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti,
1072                     GrabPtr grab, WindowPtr win, InternalEvent *ev)
1073{
1074    int err;
1075    xEvent *xi2;
1076    Mask filter;
1077    Window child = DeepestSpriteWin(&ti->sprite)->drawable.id;
1078
1079    /* FIXME: owner event handling */
1080
1081    /* If the client does not have the ownership mask set and is not
1082     * the current owner of the touch, only pretend we delivered */
1083    if (!grab && ti->num_grabs != 0 &&
1084        !TouchClientWantsOwnershipEvents(client, dev, win))
1085        return TRUE;
1086
1087    /* If we fail here, we're going to leave a client hanging. */
1088    err = EventToXI2(ev, &xi2);
1089    if (err != Success)
1090        FatalError("[Xi] %s: XI2 conversion failed in %s"
1091                   " (%d)\n", dev->name, __func__, err);
1092
1093    FixUpEventFromWindow(&ti->sprite, xi2, win, child, FALSE);
1094    filter = GetEventFilter(dev, xi2);
1095    if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success)
1096        return FALSE;
1097    err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab);
1098    free(xi2);
1099
1100    /* Returning the value from TryClientEvents isn't useful, since all our
1101     * resource-gone cleanups will update the delivery list anyway. */
1102    return TRUE;
1103}
1104
1105static void
1106ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti)
1107{
1108    ClientPtr client;
1109    XID error;
1110    GrabPtr grab = ti->listeners[0].grab;
1111
1112    BUG_RETURN(ti->listeners[0].type != TOUCH_LISTENER_GRAB &&
1113               ti->listeners[0].type != TOUCH_LISTENER_POINTER_GRAB);
1114    BUG_RETURN(!grab);
1115
1116    client = rClient(grab);
1117
1118    if (TouchAcceptReject(client, dev, XIAcceptTouch, ti->client_id,
1119                          ti->listeners[0].window->drawable.id, &error) != Success)
1120        ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n");
1121}
1122
1123/**
1124 * Find the oldest touch that still has a pointer emulation client.
1125 *
1126 * Pointer emulation can only be performed for the oldest touch. Otherwise, the
1127 * order of events seen by the client will be wrong. This function helps us find
1128 * the next touch to be emulated.
1129 *
1130 * @param dev The device to find touches for.
1131 */
1132static TouchPointInfoPtr
1133FindOldestPointerEmulatedTouch(DeviceIntPtr dev)
1134{
1135    TouchPointInfoPtr oldest = NULL;
1136    int i;
1137
1138    for (i = 0; i < dev->touch->num_touches; i++) {
1139        TouchPointInfoPtr ti = dev->touch->touches + i;
1140        int j;
1141
1142        if (!ti->active || !ti->emulate_pointer)
1143            continue;
1144
1145        for (j = 0; j < ti->num_listeners; j++) {
1146            if (ti->listeners[j].type == TOUCH_LISTENER_POINTER_GRAB ||
1147                ti->listeners[j].type == TOUCH_LISTENER_POINTER_REGULAR)
1148                break;
1149        }
1150        if (j == ti->num_listeners)
1151            continue;
1152
1153        if (!oldest) {
1154            oldest = ti;
1155            continue;
1156        }
1157
1158        if (oldest->client_id - ti->client_id < UINT_MAX / 2)
1159            oldest = ti;
1160    }
1161
1162    return oldest;
1163}
1164
1165/**
1166 * If the current owner has rejected the event, deliver the
1167 * TouchOwnership/TouchBegin to the next item in the sprite stack.
1168 */
1169static void
1170TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
1171                     TouchOwnershipEvent *ev)
1172{
1173    TouchListener *listener = &ti->listeners[0]; /* new owner */
1174    int accepted_early = listener->state == TOUCH_LISTENER_EARLY_ACCEPT;
1175
1176    /* Deliver the ownership */
1177    if (listener->state == TOUCH_LISTENER_AWAITING_OWNER || accepted_early)
1178        DeliverTouchEvents(dev, ti, (InternalEvent *) ev,
1179                           listener->listener);
1180    else if (listener->state == TOUCH_LISTENER_AWAITING_BEGIN) {
1181        /* We can't punt to a pointer listener unless all older pointer
1182         * emulated touches have been seen already. */
1183        if ((listener->type == TOUCH_LISTENER_POINTER_GRAB ||
1184             listener->type == TOUCH_LISTENER_POINTER_REGULAR) &&
1185            ti != FindOldestPointerEmulatedTouch(dev))
1186            return;
1187
1188        TouchEventHistoryReplay(ti, dev, listener->listener);
1189    }
1190
1191    /* New owner has Begin/Update but not end. If touch is pending_finish,
1192     * emulate the TouchEnd now */
1193    if (ti->pending_finish) {
1194        TouchEmitTouchEnd(dev, ti, 0, 0);
1195
1196        /* If the last owner is not a touch grab, finalise the touch, we
1197           won't get more correspondence on this.
1198         */
1199        if (ti->num_listeners == 1 &&
1200            (ti->num_grabs == 0 ||
1201             listener->grab->grabtype != XI2 ||
1202             !xi2mask_isset(listener->grab->xi2mask, dev, XI_TouchBegin))) {
1203            TouchEndTouch(dev, ti);
1204            return;
1205        }
1206    }
1207
1208    if (accepted_early)
1209        ActivateEarlyAccept(dev, ti);
1210}
1211
1212/**
1213 * Check the oldest touch to see if it needs to be replayed to its pointer
1214 * owner.
1215 *
1216 * Touch event propagation is paused if it hits a pointer listener while an
1217 * older touch with a pointer listener is waiting on accept or reject. This
1218 * function will restart propagation of a paused touch if needed.
1219 *
1220 * @param dev The device to check touches for.
1221 */
1222static void
1223CheckOldestTouch(DeviceIntPtr dev)
1224{
1225    TouchPointInfoPtr oldest = FindOldestPointerEmulatedTouch(dev);
1226
1227    if (oldest && oldest->listeners[0].state == TOUCH_LISTENER_AWAITING_BEGIN)
1228        TouchPuntToNextOwner(dev, oldest, NULL);
1229}
1230
1231/**
1232 * Process a touch rejection.
1233 *
1234 * @param sourcedev The source device of the touch sequence.
1235 * @param ti The touchpoint info record.
1236 * @param resource The resource of the client rejecting the touch.
1237 * @param ev TouchOwnership event to send. Set to NULL if no event should be
1238 *        sent.
1239 */
1240void
1241TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
1242              TouchOwnershipEvent *ev)
1243{
1244    Bool was_owner = (resource == ti->listeners[0].listener);
1245    int i;
1246
1247    /* Send a TouchEnd event to the resource being removed, but only if they
1248     * haven't received one yet already */
1249    for (i = 0; i < ti->num_listeners; i++) {
1250        if (ti->listeners[i].listener == resource) {
1251            if (ti->listeners[i].state != TOUCH_LISTENER_HAS_END)
1252                TouchEmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource);
1253            break;
1254        }
1255    }
1256
1257    /* Remove the resource from the listener list, updating
1258     * ti->num_listeners, as well as ti->num_grabs if it was a grab. */
1259    TouchRemoveListener(ti, resource);
1260
1261    /* If the current owner was removed and there are further listeners, deliver
1262     * the TouchOwnership or TouchBegin event to the new owner. */
1263    if (ev && ti->num_listeners > 0 && was_owner)
1264        TouchPuntToNextOwner(sourcedev, ti, ev);
1265    else if (ti->num_listeners == 0)
1266        TouchEndTouch(sourcedev, ti);
1267
1268    CheckOldestTouch(sourcedev);
1269}
1270
1271/**
1272 * Processes a TouchOwnership event, indicating a grab has accepted the touch
1273 * it currently owns, or a grab or selection has been removed.  Will generate
1274 * and send TouchEnd events to all clients removed from the delivery list, as
1275 * well as possibly sending the new TouchOwnership event.  May end the
1276 * touchpoint if it is pending finish.
1277 */
1278static void
1279ProcessTouchOwnershipEvent(TouchOwnershipEvent *ev,
1280                           DeviceIntPtr dev)
1281{
1282    TouchPointInfoPtr ti = TouchFindByClientID(dev, ev->touchid);
1283
1284    if (!ti) {
1285        DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
1286               dev->name, ev->type, ev->touchid);
1287        return;
1288    }
1289
1290    if (ev->reason == XIRejectTouch)
1291        TouchRejected(dev, ti, ev->resource, ev);
1292    else if (ev->reason == XIAcceptTouch) {
1293        int i;
1294
1295
1296        /* For pointer-emulated listeners that ungrabbed the active grab,
1297         * the state was forced to TOUCH_LISTENER_HAS_END. Still go
1298         * through the motions of ending the touch if the listener has
1299         * already seen the end. This ensures that the touch record is ended in
1300         * the server.
1301         */
1302        if (ti->listeners[0].state == TOUCH_LISTENER_HAS_END)
1303            TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener);
1304
1305        /* The touch owner has accepted the touch.  Send TouchEnd events to
1306         * everyone else, and truncate the list of listeners. */
1307        for (i = 1; i < ti->num_listeners; i++)
1308            TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener);
1309
1310        while (ti->num_listeners > 1)
1311            TouchRemoveListener(ti, ti->listeners[1].listener);
1312        /* Owner accepted after receiving end */
1313        if (ti->listeners[0].state == TOUCH_LISTENER_HAS_END)
1314            TouchEndTouch(dev, ti);
1315        else
1316            ti->listeners[0].state = TOUCH_LISTENER_HAS_ACCEPTED;
1317    }
1318    else {  /* this is the very first ownership event for a grab */
1319        DeliverTouchEvents(dev, ti, (InternalEvent *) ev, ev->resource);
1320    }
1321}
1322
1323/**
1324 * Copy the event's valuator information into the touchpoint, we may need
1325 * this for emulated TouchEnd events.
1326 */
1327static void
1328TouchCopyValuatorData(DeviceEvent *ev, TouchPointInfoPtr ti)
1329{
1330    int i;
1331
1332    for (i = 0; i < ARRAY_SIZE(ev->valuators.data); i++)
1333        if (BitIsOn(ev->valuators.mask, i))
1334            valuator_mask_set_double(ti->valuators, i, ev->valuators.data[i]);
1335}
1336
1337/**
1338 * Given a touch event and a potential listener, retrieve info needed for
1339 * processing the event.
1340 *
1341 * @param dev The device generating the touch event.
1342 * @param ti The touch point info record for the touch event.
1343 * @param ev The touch event to process.
1344 * @param listener The touch event listener that may receive the touch event.
1345 * @param[out] client The client that should receive the touch event.
1346 * @param[out] win The window to deliver the event on.
1347 * @param[out] grab The grab to deliver the event through, if any.
1348 * @param[out] mask The XI 2.x event mask of the grab or selection, if any.
1349 * @return TRUE if an event should be delivered to the listener, FALSE
1350 *         otherwise.
1351 */
1352static Bool
1353RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
1354                          InternalEvent *ev, TouchListener * listener,
1355                          ClientPtr *client, WindowPtr *win, GrabPtr *grab,
1356                          XI2Mask **mask)
1357{
1358    int rc;
1359    InputClients *iclients = NULL;
1360    *mask = NULL;
1361
1362    if (listener->type == TOUCH_LISTENER_GRAB ||
1363        listener->type == TOUCH_LISTENER_POINTER_GRAB) {
1364        *grab = listener->grab;
1365
1366        BUG_RETURN_VAL(!*grab, FALSE);
1367
1368        *client = rClient(*grab);
1369        *win = (*grab)->window;
1370        *mask = (*grab)->xi2mask;
1371    }
1372    else {
1373        rc = dixLookupResourceByType((void **) win, listener->listener,
1374                                     listener->resource_type,
1375                                     serverClient, DixSendAccess);
1376        if (rc != Success)
1377            return FALSE;
1378
1379        if (listener->level == XI2) {
1380            int evtype;
1381
1382            if (ti->emulate_pointer &&
1383                listener->type == TOUCH_LISTENER_POINTER_REGULAR)
1384                evtype = GetXI2Type(TouchGetPointerEventType(ev));
1385            else
1386                evtype = GetXI2Type(ev->any.type);
1387
1388            nt_list_for_each_entry(iclients,
1389                                   wOtherInputMasks(*win)->inputClients, next)
1390                if (xi2mask_isset(iclients->xi2mask, dev, evtype))
1391                break;
1392
1393            BUG_RETURN_VAL(!iclients, FALSE);
1394
1395            *mask = iclients->xi2mask;
1396            *client = rClient(iclients);
1397        }
1398        else if (listener->level == XI) {
1399            int xi_type = GetXIType(TouchGetPointerEventType(ev));
1400            Mask xi_filter = event_get_filter_from_type(dev, xi_type);
1401
1402            nt_list_for_each_entry(iclients,
1403                                   wOtherInputMasks(*win)->inputClients, next)
1404                if (iclients->mask[dev->id] & xi_filter)
1405                break;
1406            BUG_RETURN_VAL(!iclients, FALSE);
1407
1408            *client = rClient(iclients);
1409        }
1410        else {
1411            int coretype = GetCoreType(TouchGetPointerEventType(ev));
1412            Mask core_filter = event_get_filter_from_type(dev, coretype);
1413            OtherClients *oclients;
1414
1415            /* all others */
1416            nt_list_for_each_entry(oclients,
1417                                   (OtherClients *) wOtherClients(*win), next)
1418                if (oclients->mask & core_filter)
1419                    break;
1420
1421            /* if owner selected, oclients is NULL */
1422            *client = oclients ? rClient(oclients) : wClient(*win);
1423        }
1424
1425        *grab = NULL;
1426    }
1427
1428    return TRUE;
1429}
1430
1431static int
1432DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1433                          InternalEvent *ev, TouchListener * listener,
1434                          ClientPtr client, WindowPtr win, GrabPtr grab,
1435                          XI2Mask *xi2mask)
1436{
1437    InternalEvent motion, button;
1438    InternalEvent *ptrev = &motion;
1439    int nevents;
1440    DeviceIntPtr kbd;
1441
1442    /* There may be a pointer grab on the device */
1443    if (!grab) {
1444        grab = dev->deviceGrab.grab;
1445        if (grab) {
1446            win = grab->window;
1447            xi2mask = grab->xi2mask;
1448            client = rClient(grab);
1449        }
1450    }
1451
1452    /* We don't deliver pointer events to non-owners */
1453    if (!TouchResourceIsOwner(ti, listener->listener))
1454        return !Success;
1455
1456    if (!ti->emulate_pointer)
1457        return !Success;
1458
1459    nevents = TouchConvertToPointerEvent(ev, &motion, &button);
1460    BUG_RETURN_VAL(nevents == 0, BadValue);
1461
1462    /* Note that here we deliver only part of the events that are generated by the touch event:
1463     *
1464     * TouchBegin results in ButtonPress (motion is handled in DeliverEmulatedMotionEvent)
1465     * TouchUpdate results in Motion
1466     * TouchEnd results in ButtonRelease (motion is handled in DeliverEmulatedMotionEvent)
1467     */
1468    if (nevents > 1)
1469        ptrev = &button;
1470
1471    kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
1472    event_set_state(dev, kbd, &ptrev->device_event);
1473    ptrev->device_event.corestate = event_get_corestate(dev, kbd);
1474
1475    if (grab) {
1476        /* this side-steps the usual activation mechanisms, but... */
1477        if (ev->any.type == ET_TouchBegin && !dev->deviceGrab.grab)
1478            ActivatePassiveGrab(dev, grab, ptrev, ev);  /* also delivers the event */
1479        else {
1480            int deliveries = 0;
1481
1482            /* 'grab' is the passive grab, but if the grab isn't active,
1483             * don't deliver */
1484            if (!dev->deviceGrab.grab)
1485                return !Success;
1486
1487            if (grab->ownerEvents) {
1488                WindowPtr focus = NullWindow;
1489                WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite);
1490
1491                deliveries = DeliverDeviceEvents(sprite_win, ptrev, grab, focus, dev);
1492            }
1493
1494            if (!deliveries)
1495                deliveries = DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
1496
1497            /* We must accept the touch sequence once a pointer listener has
1498             * received one event past ButtonPress. */
1499            if (deliveries && ev->any.type != ET_TouchBegin &&
1500                !(ev->device_event.flags & TOUCH_CLIENT_ID))
1501                TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
1502
1503            if (ev->any.type == ET_TouchEnd &&
1504                ti->num_listeners == 1 &&
1505                !dev->button->buttonsDown &&
1506                dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
1507                (*dev->deviceGrab.DeactivateGrab) (dev);
1508                CheckOldestTouch(dev);
1509                return Success;
1510            }
1511        }
1512    }
1513    else {
1514        GrabPtr devgrab = dev->deviceGrab.grab;
1515        WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite);
1516
1517        DeliverDeviceEvents(sprite_win, ptrev, grab, win, dev);
1518        /* FIXME: bad hack
1519         * Implicit passive grab activated in response to this event. Store
1520         * the event.
1521         */
1522        if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab) {
1523            TouchListener *l;
1524            GrabPtr g;
1525
1526            devgrab = dev->deviceGrab.grab;
1527            g = AllocGrab(devgrab);
1528            BUG_WARN(!g);
1529
1530            CopyPartialInternalEvent(dev->deviceGrab.sync.event, ev);
1531
1532            /* The listener array has a sequence of grabs and then one event
1533             * selection. Implicit grab activation occurs through delivering an
1534             * event selection. Thus, we update the last listener in the array.
1535             */
1536            l = &ti->listeners[ti->num_listeners - 1];
1537            l->listener = g->resource;
1538            l->grab = g;
1539            //l->resource_type = RT_NONE;
1540
1541            if (devgrab->grabtype != XI2 || devgrab->type != XI_TouchBegin)
1542                l->type = TOUCH_LISTENER_POINTER_GRAB;
1543            else
1544                l->type = TOUCH_LISTENER_GRAB;
1545        }
1546
1547    }
1548    if (ev->any.type == ET_TouchBegin)
1549        listener->state = TOUCH_LISTENER_IS_OWNER;
1550    else if (ev->any.type == ET_TouchEnd)
1551        listener->state = TOUCH_LISTENER_HAS_END;
1552
1553    return Success;
1554}
1555
1556static void
1557DeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1558                           InternalEvent *ev)
1559{
1560    DeviceEvent motion;
1561
1562    if (ti->num_listeners) {
1563        ClientPtr client;
1564        WindowPtr win;
1565        GrabPtr grab;
1566        XI2Mask *mask;
1567
1568        if (ti->listeners[0].type != TOUCH_LISTENER_POINTER_REGULAR &&
1569            ti->listeners[0].type != TOUCH_LISTENER_POINTER_GRAB)
1570            return;
1571
1572        motion = ev->device_event;
1573        motion.type = ET_TouchUpdate;
1574        motion.detail.button = 0;
1575
1576        if (!RetrieveTouchDeliveryData(dev, ti, (InternalEvent*)&motion,
1577                                       &ti->listeners[0], &client, &win, &grab,
1578                                       &mask))
1579            return;
1580
1581        DeliverTouchEmulatedEvent(dev, ti, (InternalEvent*)&motion, &ti->listeners[0], client,
1582                                  win, grab, mask);
1583    }
1584    else {
1585        InternalEvent button;
1586        int converted;
1587
1588        converted = TouchConvertToPointerEvent(ev, (InternalEvent*)&motion, &button);
1589
1590        BUG_WARN(converted == 0);
1591        if (converted)
1592            ProcessOtherEvent((InternalEvent*)&motion, dev);
1593    }
1594}
1595
1596/**
1597 * Processes and delivers a TouchBegin, TouchUpdate, or a
1598 * TouchEnd event.
1599 *
1600 * Due to having rather different delivery semantics (see the Xi 2.2 protocol
1601 * spec for more information), this implements its own grab and event-selection
1602 * delivery logic.
1603 */
1604static void
1605ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
1606{
1607    TouchClassPtr t = dev->touch;
1608    TouchPointInfoPtr ti;
1609    uint32_t touchid;
1610    int type = ev->any.type;
1611    int emulate_pointer = ! !(ev->device_event.flags & TOUCH_POINTER_EMULATED);
1612    DeviceIntPtr kbd;
1613
1614    if (!t)
1615        return;
1616
1617    touchid = ev->device_event.touchid;
1618
1619    if (type == ET_TouchBegin && !(ev->device_event.flags & TOUCH_REPLAYING)) {
1620        ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
1621                             emulate_pointer);
1622    }
1623    else
1624        ti = TouchFindByClientID(dev, touchid);
1625
1626    /* Active pointer grab */
1627    if (emulate_pointer && dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab &&
1628        (dev->deviceGrab.grab->grabtype == CORE ||
1629         dev->deviceGrab.grab->grabtype == XI ||
1630         !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin)))
1631    {
1632        /* Active pointer grab on touch point and we get a TouchEnd - claim this
1633         * touchpoint accepted, otherwise clients waiting for ownership will
1634         * wait on this touchpoint until this client ungrabs, or the cows come
1635         * home, whichever is earlier */
1636        if (ti && type == ET_TouchEnd)
1637            TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
1638        else if (!ti && type != ET_TouchBegin) {
1639            /* Under the following circumstances we create a new touch record for an
1640             * existing touch:
1641             *
1642             * - The touch may be pointer emulated
1643             * - An explicit grab is active on the device
1644             * - The grab is a pointer grab
1645             *
1646             * This allows for an explicit grab to receive pointer events for an already
1647             * active touch.
1648             */
1649            ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
1650                                 emulate_pointer);
1651            if (!ti) {
1652                DebugF("[Xi] %s: Failed to create new dix record for explicitly "
1653                       "grabbed touchpoint %d\n",
1654                       dev->name, touchid);
1655                return;
1656            }
1657
1658            TouchBuildSprite(dev, ti, ev);
1659            TouchSetupListeners(dev, ti, ev);
1660        }
1661    }
1662
1663    if (!ti) {
1664        DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
1665               dev->name, type, touchid);
1666        goto out;
1667    }
1668
1669    /* if emulate_pointer is set, emulate the motion event right
1670     * here, so we can ignore it for button event emulation. TouchUpdate
1671     * events which _only_ emulate motion just work normally */
1672    if (emulate_pointer && (ev->any.type == ET_TouchBegin ||
1673                           (ev->any.type == ET_TouchEnd && ti->num_listeners > 0)))
1674        DeliverEmulatedMotionEvent(dev, ti, ev);
1675
1676    if (emulate_pointer && IsMaster(dev))
1677        CheckMotion(&ev->device_event, dev);
1678
1679    kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
1680    event_set_state(NULL, kbd, &ev->device_event);
1681    ev->device_event.corestate = event_get_corestate(NULL, kbd);
1682
1683    /* Make sure we have a valid window trace for event delivery; must be
1684     * called after event type mutation. Touch end events are always processed
1685     * in order to end touch records. */
1686    /* FIXME: check this */
1687    if ((type == ET_TouchBegin &&
1688         !(ev->device_event.flags & TOUCH_REPLAYING) &&
1689         !TouchBuildSprite(dev, ti, ev)) ||
1690        (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0))
1691        return;
1692
1693    TouchCopyValuatorData(&ev->device_event, ti);
1694    /* WARNING: the event type may change to TouchUpdate in
1695     * DeliverTouchEvents if a TouchEnd was delivered to a grabbing
1696     * owner */
1697    DeliverTouchEvents(dev, ti, ev, ev->device_event.resource);
1698    if (ev->any.type == ET_TouchEnd)
1699        TouchEndTouch(dev, ti);
1700
1701 out:
1702    if (emulate_pointer)
1703        UpdateDeviceState(dev, &ev->device_event);
1704}
1705
1706static void
1707ProcessBarrierEvent(InternalEvent *e, DeviceIntPtr dev)
1708{
1709    Mask filter;
1710    WindowPtr pWin;
1711    BarrierEvent *be = &e->barrier_event;
1712    xEvent *ev;
1713    int rc;
1714    GrabPtr grab = dev->deviceGrab.grab;
1715
1716    if (!IsMaster(dev))
1717        return;
1718
1719    if (dixLookupWindow(&pWin, be->window, serverClient, DixReadAccess) != Success)
1720        return;
1721
1722    if (grab)
1723        be->flags |= XIBarrierDeviceIsGrabbed;
1724
1725    rc = EventToXI2(e, &ev);
1726    if (rc != Success) {
1727        ErrorF("[Xi] event conversion from %s failed with code %d\n", __func__, rc);
1728        return;
1729    }
1730
1731    /* A client has a grab, deliver to this client if the grab_window is the
1732       barrier window.
1733
1734       Otherwise, deliver normally to the client.
1735     */
1736    if (grab &&
1737        CLIENT_ID(be->barrierid) == CLIENT_ID(grab->resource) &&
1738        grab->window->drawable.id == be->window) {
1739        DeliverGrabbedEvent(e, dev, FALSE);
1740    } else {
1741        filter = GetEventFilter(dev, ev);
1742
1743        DeliverEventsToWindow(dev, pWin, ev, 1,
1744                              filter, NullGrab);
1745    }
1746    free(ev);
1747}
1748
1749static BOOL
1750IsAnotherGestureActiveOnMaster(DeviceIntPtr dev, InternalEvent* ev)
1751{
1752    GestureClassPtr g = dev->gesture;
1753    if (g->gesture.active && g->gesture.sourceid != ev->gesture_event.sourceid) {
1754        return TRUE;
1755    }
1756    return FALSE;
1757}
1758
1759/**
1760 * Processes and delivers a Gesture{Pinch,Swipe}{Begin,Update,End}.
1761 *
1762 * Due to having rather different delivery semantics (see the Xi 2.4 protocol
1763 * spec for more information), this implements its own grab and event-selection
1764 * delivery logic.
1765 */
1766void
1767ProcessGestureEvent(InternalEvent *ev, DeviceIntPtr dev)
1768{
1769    GestureInfoPtr gi;
1770    DeviceIntPtr kbd;
1771    Bool deactivateGestureGrab = FALSE;
1772    Bool delivered = FALSE;
1773
1774    if (!dev->gesture)
1775        return;
1776
1777    if (IsMaster(dev) && IsAnotherGestureActiveOnMaster(dev, ev))
1778        return;
1779
1780    if (IsGestureBeginEvent(ev))
1781        gi = GestureBeginGesture(dev, ev);
1782    else
1783        gi = GestureFindActiveByEventType(dev, ev->any.type);
1784
1785    if (!gi) {
1786        /* This may happen if gesture is no longer active or was never started. */
1787        return;
1788    }
1789
1790    kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
1791    event_set_state_gesture(kbd, &ev->gesture_event);
1792
1793    if (IsGestureBeginEvent(ev))
1794        GestureSetupListener(dev, gi, ev);
1795
1796    if (IsGestureEndEvent(ev) &&
1797            dev->deviceGrab.grab &&
1798            dev->deviceGrab.fromPassiveGrab &&
1799            GrabIsGestureGrab(dev->deviceGrab.grab))
1800        deactivateGestureGrab = TRUE;
1801
1802    delivered = DeliverGestureEventToOwner(dev, gi, ev);
1803
1804    if (delivered && !deactivateGestureGrab &&
1805            (IsGestureBeginEvent(ev) || IsGestureEndEvent(ev)))
1806        FreezeThisEventIfNeededForSyncGrab(dev, ev);
1807
1808    if (IsGestureEndEvent(ev))
1809        GestureEndGesture(gi);
1810
1811    if (deactivateGestureGrab)
1812        (*dev->deviceGrab.DeactivateGrab) (dev);
1813}
1814
1815/**
1816 * Process DeviceEvents and DeviceChangedEvents.
1817 */
1818static void
1819ProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device)
1820{
1821    GrabPtr grab;
1822    Bool deactivateDeviceGrab = FALSE;
1823    int key = 0, rootX, rootY;
1824    ButtonClassPtr b;
1825    int ret = 0;
1826    int corestate;
1827    DeviceIntPtr mouse = NULL, kbd = NULL;
1828    DeviceEvent *event = &ev->device_event;
1829
1830    if (IsPointerDevice(device)) {
1831        kbd = GetMaster(device, KEYBOARD_OR_FLOAT);
1832        mouse = device;
1833        if (!kbd->key)          /* can happen with floating SDs */
1834            kbd = NULL;
1835    }
1836    else {
1837        mouse = GetMaster(device, POINTER_OR_FLOAT);
1838        kbd = device;
1839        if (!mouse->valuator || !mouse->button) /* may be float. SDs */
1840            mouse = NULL;
1841    }
1842
1843    corestate = event_get_corestate(mouse, kbd);
1844    event_set_state(mouse, kbd, event);
1845
1846    ret = UpdateDeviceState(device, event);
1847    if (ret == DONT_PROCESS)
1848        return;
1849
1850    b = device->button;
1851
1852    if (IsMaster(device) || IsFloating(device))
1853        CheckMotion(event, device);
1854
1855    switch (event->type) {
1856    case ET_Motion:
1857    case ET_ButtonPress:
1858    case ET_ButtonRelease:
1859    case ET_KeyPress:
1860    case ET_KeyRelease:
1861    case ET_ProximityIn:
1862    case ET_ProximityOut:
1863        GetSpritePosition(device, &rootX, &rootY);
1864        event->root_x = rootX;
1865        event->root_y = rootY;
1866        NoticeEventTime((InternalEvent *) event, device);
1867        event->corestate = corestate;
1868        key = event->detail.key;
1869        break;
1870    default:
1871        break;
1872    }
1873
1874    /* send KeyPress and KeyRelease events to XACE plugins */
1875    if (XaceHookIsSet(XACE_KEY_AVAIL) &&
1876            (event->type == ET_KeyPress || event->type == ET_KeyRelease)) {
1877        xEvent *core;
1878        int count;
1879
1880        if (EventToCore(ev, &core, &count) == Success && count > 0) {
1881            XaceHook(XACE_KEY_AVAIL, core, device, 0);
1882            free(core);
1883        }
1884    }
1885
1886    if (DeviceEventCallback && !syncEvents.playingEvents) {
1887        DeviceEventInfoRec eventinfo;
1888        SpritePtr pSprite = device->spriteInfo->sprite;
1889
1890        /* see comment in EnqueueEvents regarding the next three lines */
1891        if (ev->any.type == ET_Motion)
1892            ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
1893
1894        eventinfo.device = device;
1895        eventinfo.event = ev;
1896        CallCallbacks(&DeviceEventCallback, (void *) &eventinfo);
1897    }
1898
1899    grab = device->deviceGrab.grab;
1900
1901    switch (event->type) {
1902    case ET_KeyPress:
1903        /* Don't deliver focus events (e.g. from KeymapNotify when running
1904         * nested) to clients. */
1905        if (event->source_type == EVENT_SOURCE_FOCUS)
1906            return;
1907        if (!grab && CheckDeviceGrabs(device, ev, 0))
1908            return;
1909        break;
1910    case ET_KeyRelease:
1911        if (grab && device->deviceGrab.fromPassiveGrab &&
1912            (key == device->deviceGrab.activatingKey) &&
1913            GrabIsKeyboardGrab(device->deviceGrab.grab))
1914            deactivateDeviceGrab = TRUE;
1915        break;
1916    case ET_ButtonPress:
1917        if (b->map[key] == 0)   /* there's no button 0 */
1918            return;
1919        event->detail.button = b->map[key];
1920        if (!grab && CheckDeviceGrabs(device, ev, 0)) {
1921            /* if a passive grab was activated, the event has been sent
1922             * already */
1923            return;
1924        }
1925        break;
1926    case ET_ButtonRelease:
1927        if (b->map[key] == 0)   /* there's no button 0 */
1928            return;
1929        event->detail.button = b->map[key];
1930        if (grab && !b->buttonsDown &&
1931            device->deviceGrab.fromPassiveGrab &&
1932            GrabIsPointerGrab(device->deviceGrab.grab))
1933            deactivateDeviceGrab = TRUE;
1934    default:
1935        break;
1936    }
1937
1938    /* Don't deliver focus events (e.g. from KeymapNotify when running
1939     * nested) to clients. */
1940    if (event->source_type != EVENT_SOURCE_FOCUS) {
1941        if (grab)
1942            DeliverGrabbedEvent((InternalEvent *) event, device,
1943                                deactivateDeviceGrab);
1944        else if (device->focus && !IsPointerEvent(ev))
1945            DeliverFocusedEvent(device, (InternalEvent *) event,
1946                                GetSpriteWindow(device));
1947        else
1948            DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent *) event,
1949                                NullGrab, NullWindow, device);
1950    }
1951
1952    if (deactivateDeviceGrab == TRUE) {
1953        (*device->deviceGrab.DeactivateGrab) (device);
1954
1955        if (!IsMaster (device) && !IsFloating (device)) {
1956            int flags, num_events = 0;
1957            InternalEvent dce;
1958
1959            flags = (IsPointerDevice (device)) ?
1960                DEVCHANGE_POINTER_EVENT : DEVCHANGE_KEYBOARD_EVENT;
1961            UpdateFromMaster (&dce, device, flags, &num_events);
1962            BUG_WARN(num_events > 1);
1963
1964            if (num_events == 1)
1965                ChangeMasterDeviceClasses(GetMaster (device, MASTER_ATTACHED),
1966                                          &dce.changed_event);
1967        }
1968
1969    }
1970
1971    event->detail.key = key;
1972}
1973
1974/**
1975 * Main device event processing function.
1976 * Called from when processing the events from the event queue.
1977 *
1978 */
1979void
1980ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
1981{
1982    verify_internal_event(ev);
1983
1984    switch (ev->any.type) {
1985    case ET_RawKeyPress:
1986    case ET_RawKeyRelease:
1987    case ET_RawButtonPress:
1988    case ET_RawButtonRelease:
1989    case ET_RawMotion:
1990    case ET_RawTouchBegin:
1991    case ET_RawTouchUpdate:
1992    case ET_RawTouchEnd:
1993        DeliverRawEvent(&ev->raw_event, device);
1994        break;
1995    case ET_TouchBegin:
1996    case ET_TouchUpdate:
1997    case ET_TouchEnd:
1998        ProcessTouchEvent(ev, device);
1999        break;
2000    case ET_TouchOwnership:
2001        /* TouchOwnership events are handled separately from the rest, as they
2002         * have more complex semantics. */
2003        ProcessTouchOwnershipEvent(&ev->touch_ownership_event, device);
2004        break;
2005    case ET_BarrierHit:
2006    case ET_BarrierLeave:
2007        ProcessBarrierEvent(ev, device);
2008        break;
2009    case ET_GesturePinchBegin:
2010    case ET_GesturePinchUpdate:
2011    case ET_GesturePinchEnd:
2012    case ET_GestureSwipeBegin:
2013    case ET_GestureSwipeUpdate:
2014    case ET_GestureSwipeEnd:
2015        ProcessGestureEvent(ev, device);
2016        break;
2017    default:
2018        ProcessDeviceEvent(ev, device);
2019        break;
2020    }
2021}
2022
2023static int
2024DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
2025                       InternalEvent *ev, TouchListener * listener,
2026                       ClientPtr client, WindowPtr win, GrabPtr grab,
2027                       XI2Mask *xi2mask)
2028{
2029    enum TouchListenerState state;
2030    int rc = Success;
2031    Bool has_ownershipmask;
2032
2033    if (listener->type == TOUCH_LISTENER_POINTER_REGULAR ||
2034        listener->type == TOUCH_LISTENER_POINTER_GRAB) {
2035        rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
2036                                       grab, xi2mask);
2037        if (rc == Success) {
2038            listener->state = TOUCH_LISTENER_IS_OWNER;
2039            /* async grabs cannot replay, so automatically accept this touch */
2040            if (listener->type == TOUCH_LISTENER_POINTER_GRAB &&
2041                dev->deviceGrab.grab &&
2042                dev->deviceGrab.fromPassiveGrab &&
2043                dev->deviceGrab.grab->pointerMode == GrabModeAsync)
2044                ActivateEarlyAccept(dev, ti);
2045        }
2046        goto out;
2047    }
2048
2049    has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
2050
2051    if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
2052        rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
2053    if (!TouchResourceIsOwner(ti, listener->listener)) {
2054        if (has_ownershipmask)
2055            state = TOUCH_LISTENER_AWAITING_OWNER;
2056        else
2057            state = TOUCH_LISTENER_AWAITING_BEGIN;
2058    }
2059    else {
2060        if (has_ownershipmask)
2061            TouchSendOwnershipEvent(dev, ti, 0, listener->listener);
2062
2063        if (listener->type == TOUCH_LISTENER_REGULAR)
2064            state = TOUCH_LISTENER_HAS_ACCEPTED;
2065        else
2066            state = TOUCH_LISTENER_IS_OWNER;
2067    }
2068    listener->state = state;
2069
2070 out:
2071    return rc;
2072}
2073
2074static int
2075DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
2076                     TouchListener * listener, ClientPtr client,
2077                     WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
2078{
2079    int rc = Success;
2080
2081    if (listener->type == TOUCH_LISTENER_POINTER_REGULAR ||
2082        listener->type == TOUCH_LISTENER_POINTER_GRAB) {
2083        /* Note: If the active grab was ungrabbed, we already changed the
2084         * state to TOUCH_LISTENER_HAS_END but still get here. So we mustn't
2085         * actually send the event.
2086         * This is part two of the hack in DeactivatePointerGrab
2087         */
2088        if (listener->state != TOUCH_LISTENER_HAS_END) {
2089            rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
2090                                           grab, xi2mask);
2091
2092             /* Once we send a TouchEnd to a legacy listener, we're already well
2093              * past the accepting/rejecting stage (can only happen on
2094              * GrabModeSync + replay. This listener now gets the end event,
2095              * and we can continue.
2096              */
2097            if (rc == Success)
2098                listener->state = TOUCH_LISTENER_HAS_END;
2099        }
2100        goto out;
2101    }
2102
2103    /* A client is waiting for the begin, don't give it a TouchEnd */
2104    if (listener->state == TOUCH_LISTENER_AWAITING_BEGIN) {
2105        listener->state = TOUCH_LISTENER_HAS_END;
2106        goto out;
2107    }
2108
2109    /* Event in response to reject */
2110    if (ev->device_event.flags & TOUCH_REJECT ||
2111        (ev->device_event.flags & TOUCH_ACCEPT && !TouchResourceIsOwner(ti, listener->listener))) {
2112        /* Touch has been rejected, or accepted by its owner which is not this listener */
2113        if (listener->state != TOUCH_LISTENER_HAS_END)
2114            rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
2115        listener->state = TOUCH_LISTENER_HAS_END;
2116    }
2117    else if (TouchResourceIsOwner(ti, listener->listener)) {
2118        Bool normal_end = !(ev->device_event.flags & TOUCH_ACCEPT);
2119
2120        /* FIXME: what about early acceptance */
2121        if (normal_end && listener->state != TOUCH_LISTENER_HAS_END)
2122            rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
2123
2124        if ((ti->num_listeners > 1 ||
2125             (ti->num_grabs > 0 && listener->state != TOUCH_LISTENER_HAS_ACCEPTED)) &&
2126            (ev->device_event.flags & (TOUCH_ACCEPT | TOUCH_REJECT)) == 0) {
2127            ev->any.type = ET_TouchUpdate;
2128            ev->device_event.flags |= TOUCH_PENDING_END;
2129            ti->pending_finish = TRUE;
2130        }
2131
2132        if (normal_end)
2133            listener->state = TOUCH_LISTENER_HAS_END;
2134    }
2135
2136 out:
2137    return rc;
2138}
2139
2140static int
2141DeliverTouchEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
2142                  TouchListener * listener, ClientPtr client,
2143                  WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
2144{
2145    Bool has_ownershipmask = FALSE;
2146    int rc = Success;
2147
2148    if (xi2mask)
2149        has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
2150
2151    if (ev->any.type == ET_TouchOwnership) {
2152        ev->touch_ownership_event.deviceid = dev->id;
2153        if (!TouchResourceIsOwner(ti, listener->listener))
2154            goto out;
2155        rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
2156        listener->state = TOUCH_LISTENER_IS_OWNER;
2157    }
2158    else
2159        ev->device_event.deviceid = dev->id;
2160
2161    if (ev->any.type == ET_TouchBegin) {
2162        rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab,
2163                                    xi2mask);
2164    }
2165    else if (ev->any.type == ET_TouchUpdate) {
2166        if (listener->type == TOUCH_LISTENER_POINTER_REGULAR ||
2167            listener->type == TOUCH_LISTENER_POINTER_GRAB)
2168            DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, grab,
2169                                      xi2mask);
2170        else if (TouchResourceIsOwner(ti, listener->listener) ||
2171                 has_ownershipmask)
2172            rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
2173    }
2174    else if (ev->any.type == ET_TouchEnd)
2175        rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab,
2176                                  xi2mask);
2177
2178 out:
2179    return rc;
2180}
2181
2182/**
2183 * Delivers a touch events to all interested clients.  For TouchBegin events,
2184 * will update ti->listeners, ti->num_listeners, and ti->num_grabs.
2185 * May also mutate ev (type and flags) upon successful delivery.  If
2186 * @resource is non-zero, will only attempt delivery to the owner of that
2187 * resource.
2188 *
2189 * @return TRUE if the event was delivered at least once, FALSE otherwise
2190 */
2191void
2192DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
2193                   InternalEvent *ev, XID resource)
2194{
2195    int i;
2196
2197    if (ev->any.type == ET_TouchBegin &&
2198        !(ev->device_event.flags & (TOUCH_CLIENT_ID | TOUCH_REPLAYING)))
2199        TouchSetupListeners(dev, ti, ev);
2200
2201    TouchEventHistoryPush(ti, &ev->device_event);
2202
2203    for (i = 0; i < ti->num_listeners; i++) {
2204        GrabPtr grab = NULL;
2205        ClientPtr client;
2206        WindowPtr win;
2207        XI2Mask *mask;
2208        TouchListener *listener = &ti->listeners[i];
2209
2210        if (resource && listener->listener != resource)
2211            continue;
2212
2213        if (!RetrieveTouchDeliveryData(dev, ti, ev, listener, &client, &win,
2214                                       &grab, &mask))
2215            continue;
2216
2217        DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask);
2218    }
2219}
2220
2221/**
2222 * Attempts to deliver a gesture event to the given client.
2223 */
2224static Bool
2225DeliverOneGestureEvent(ClientPtr client, DeviceIntPtr dev, GestureInfoPtr gi,
2226                       GrabPtr grab, WindowPtr win, InternalEvent *ev)
2227{
2228    int err;
2229    xEvent *xi2;
2230    Mask filter;
2231    Window child = DeepestSpriteWin(&gi->sprite)->drawable.id;
2232
2233    /* If we fail here, we're going to leave a client hanging. */
2234    err = EventToXI2(ev, &xi2);
2235    if (err != Success)
2236        FatalError("[Xi] %s: XI2 conversion failed in %s"
2237                   " (%d)\n", dev->name, __func__, err);
2238
2239    FixUpEventFromWindow(&gi->sprite, xi2, win, child, FALSE);
2240    filter = GetEventFilter(dev, xi2);
2241    if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success)
2242        return FALSE;
2243    err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab);
2244    free(xi2);
2245
2246    /* Returning the value from TryClientEvents isn't useful, since all our
2247     * resource-gone cleanups will update the delivery list anyway. */
2248    return TRUE;
2249}
2250
2251/**
2252 * Given a gesture event and a potential listener, retrieve info needed for processing the event.
2253 *
2254 * @param dev The device generating the gesture event.
2255 * @param ev The gesture event to process.
2256 * @param listener The gesture event listener that may receive the gesture event.
2257 * @param[out] client The client that should receive the gesture event.
2258 * @param[out] win The window to deliver the event on.
2259 * @param[out] grab The grab to deliver the event through, if any.
2260 * @return TRUE if an event should be delivered to the listener, FALSE
2261 *         otherwise.
2262 */
2263static Bool
2264RetrieveGestureDeliveryData(DeviceIntPtr dev, InternalEvent *ev, GestureListener* listener,
2265                            ClientPtr *client, WindowPtr *win, GrabPtr *grab)
2266{
2267    int rc;
2268    int evtype;
2269    InputClients *iclients = NULL;
2270    *grab = NULL;
2271
2272    if (listener->type == GESTURE_LISTENER_GRAB ||
2273        listener->type == GESTURE_LISTENER_NONGESTURE_GRAB) {
2274        *grab = listener->grab;
2275
2276        BUG_RETURN_VAL(!*grab, FALSE);
2277
2278        *client = rClient(*grab);
2279        *win = (*grab)->window;
2280    }
2281    else {
2282        rc = dixLookupResourceByType((void **) win, listener->listener, listener->resource_type,
2283                                     serverClient, DixSendAccess);
2284        if (rc != Success)
2285            return FALSE;
2286
2287        /* note that we only will have XI2 listeners as
2288           listener->type == GESTURE_LISTENER_REGULAR */
2289        evtype = GetXI2Type(ev->any.type);
2290
2291        nt_list_for_each_entry(iclients, wOtherInputMasks(*win)->inputClients, next)
2292            if (xi2mask_isset(iclients->xi2mask, dev, evtype))
2293                break;
2294
2295        BUG_RETURN_VAL(!iclients, FALSE);
2296
2297        *client = rClient(iclients);
2298    }
2299
2300    return TRUE;
2301}
2302
2303/**
2304 * Delivers a gesture to the owner, if possible and needed. Returns whether
2305 * an event was delivered.
2306 */
2307Bool
2308DeliverGestureEventToOwner(DeviceIntPtr dev, GestureInfoPtr gi, InternalEvent *ev)
2309{
2310    GrabPtr grab = NULL;
2311    ClientPtr client;
2312    WindowPtr win;
2313
2314    if (!gi->has_listener || gi->listener.type == GESTURE_LISTENER_NONGESTURE_GRAB) {
2315        return 0;
2316    }
2317
2318    if (!RetrieveGestureDeliveryData(dev, ev, &gi->listener, &client, &win, &grab))
2319        return 0;
2320
2321    ev->gesture_event.deviceid = dev->id;
2322
2323    return DeliverOneGestureEvent(client, dev, gi, grab, win, ev);
2324}
2325
2326int
2327InitProximityClassDeviceStruct(DeviceIntPtr dev)
2328{
2329    ProximityClassPtr proxc;
2330
2331    BUG_RETURN_VAL(dev == NULL, FALSE);
2332    BUG_RETURN_VAL(dev->proximity != NULL, FALSE);
2333
2334    proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
2335    if (!proxc)
2336        return FALSE;
2337    proxc->sourceid = dev->id;
2338    proxc->in_proximity = TRUE;
2339    dev->proximity = proxc;
2340    return TRUE;
2341}
2342
2343/**
2344 * Initialise the device's valuators. The memory must already be allocated,
2345 * this function merely inits the matching axis (specified through axnum) to
2346 * sane values.
2347 *
2348 * It is a condition that (minval < maxval).
2349 *
2350 * @see InitValuatorClassDeviceStruct
2351 */
2352Bool
2353InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
2354                       int maxval, int resolution, int min_res, int max_res,
2355                       int mode)
2356{
2357    AxisInfoPtr ax;
2358
2359    BUG_RETURN_VAL(dev == NULL, FALSE);
2360    BUG_RETURN_VAL(dev->valuator == NULL, FALSE);
2361    BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE);
2362    BUG_RETURN_VAL(minval > maxval && mode == Absolute, FALSE);
2363
2364    ax = dev->valuator->axes + axnum;
2365
2366    ax->min_value = minval;
2367    ax->max_value = maxval;
2368    ax->resolution = resolution;
2369    ax->min_resolution = min_res;
2370    ax->max_resolution = max_res;
2371    ax->label = label;
2372    ax->mode = mode;
2373
2374    if (mode & OutOfProximity)
2375        dev->proximity->in_proximity = FALSE;
2376
2377    return SetScrollValuator(dev, axnum, SCROLL_TYPE_NONE, 0, SCROLL_FLAG_NONE);
2378}
2379
2380/**
2381 * Set the given axis number as a scrolling valuator.
2382 */
2383Bool
2384SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type,
2385                  double increment, int flags)
2386{
2387    AxisInfoPtr ax;
2388    int *current_ax;
2389    InternalEvent dce;
2390    DeviceIntPtr master;
2391
2392    BUG_RETURN_VAL(dev == NULL, FALSE);
2393    BUG_RETURN_VAL(dev->valuator == NULL, FALSE);
2394    BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE);
2395
2396    switch (type) {
2397    case SCROLL_TYPE_VERTICAL:
2398        current_ax = &dev->valuator->v_scroll_axis;
2399        break;
2400    case SCROLL_TYPE_HORIZONTAL:
2401        current_ax = &dev->valuator->h_scroll_axis;
2402        break;
2403    case SCROLL_TYPE_NONE:
2404        ax = &dev->valuator->axes[axnum];
2405        ax->scroll.type = type;
2406        return TRUE;
2407    default:
2408        return FALSE;
2409    }
2410
2411    if (increment == 0.0)
2412        return FALSE;
2413
2414    if (*current_ax != -1 && axnum != *current_ax) {
2415        ax = &dev->valuator->axes[*current_ax];
2416        if (ax->scroll.type == type &&
2417            (flags & SCROLL_FLAG_PREFERRED) &&
2418            (ax->scroll.flags & SCROLL_FLAG_PREFERRED))
2419            return FALSE;
2420    }
2421    *current_ax = axnum;
2422
2423    ax = &dev->valuator->axes[axnum];
2424    ax->scroll.type = type;
2425    ax->scroll.increment = increment;
2426    ax->scroll.flags = flags;
2427
2428    master = GetMaster(dev, MASTER_ATTACHED);
2429    CreateClassesChangedEvent(&dce, master, dev,
2430                              DEVCHANGE_POINTER_EVENT |
2431                              DEVCHANGE_DEVICE_CHANGE);
2432    XISendDeviceChangedEvent(dev, &dce.changed_event);
2433
2434    /* if the current slave is us, update the master. If not, we'll update
2435     * whenever the next slave switch happens anyway. CMDC sends the event
2436     * for us */
2437    if (master && master->lastSlave == dev)
2438        ChangeMasterDeviceClasses(master, &dce.changed_event);
2439
2440    return TRUE;
2441}
2442
2443int
2444CheckGrabValues(ClientPtr client, GrabParameters *param)
2445{
2446    if (param->grabtype != CORE &&
2447        param->grabtype != XI && param->grabtype != XI2) {
2448        ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
2449        return BadImplementation;
2450    }
2451
2452    if ((param->this_device_mode != GrabModeSync) &&
2453        (param->this_device_mode != GrabModeAsync) &&
2454        (param->this_device_mode != XIGrabModeTouch)) {
2455        client->errorValue = param->this_device_mode;
2456        return BadValue;
2457    }
2458    if ((param->other_devices_mode != GrabModeSync) &&
2459        (param->other_devices_mode != GrabModeAsync) &&
2460        (param->other_devices_mode != XIGrabModeTouch)) {
2461        client->errorValue = param->other_devices_mode;
2462        return BadValue;
2463    }
2464
2465    if (param->modifiers != AnyModifier &&
2466        param->modifiers != XIAnyModifier &&
2467        (param->modifiers & ~AllModifiersMask)) {
2468        client->errorValue = param->modifiers;
2469        return BadValue;
2470    }
2471
2472    if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
2473        client->errorValue = param->ownerEvents;
2474        return BadValue;
2475    }
2476    return Success;
2477}
2478
2479int
2480GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
2481           int button, GrabParameters *param, enum InputLevel grabtype,
2482           GrabMask *mask)
2483{
2484    WindowPtr pWin, confineTo;
2485    CursorPtr cursor;
2486    GrabPtr grab;
2487    int rc, type = -1;
2488    Mask access_mode = DixGrabAccess;
2489
2490    rc = CheckGrabValues(client, param);
2491    if (rc != Success)
2492        return rc;
2493    if (param->confineTo == None)
2494        confineTo = NullWindow;
2495    else {
2496        rc = dixLookupWindow(&confineTo, param->confineTo, client,
2497                             DixSetAttrAccess);
2498        if (rc != Success)
2499            return rc;
2500    }
2501    if (param->cursor == None)
2502        cursor = NullCursor;
2503    else {
2504        rc = dixLookupResourceByType((void **) &cursor, param->cursor,
2505                                     RT_CURSOR, client, DixUseAccess);
2506        if (rc != Success) {
2507            client->errorValue = param->cursor;
2508            return rc;
2509        }
2510        access_mode |= DixForceAccess;
2511    }
2512    if (param->this_device_mode == GrabModeSync ||
2513        param->other_devices_mode == GrabModeSync)
2514        access_mode |= DixFreezeAccess;
2515    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
2516    if (rc != Success)
2517        return rc;
2518    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2519    if (rc != Success)
2520        return rc;
2521
2522    if (grabtype == XI)
2523        type = DeviceButtonPress;
2524    else if (grabtype == XI2)
2525        type = XI_ButtonPress;
2526
2527    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
2528                      mask, param, type, button, confineTo, cursor);
2529    if (!grab)
2530        return BadAlloc;
2531    return AddPassiveGrabToList(client, grab);
2532}
2533
2534/**
2535 * Grab the given key.
2536 */
2537int
2538GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
2539        int key, GrabParameters *param, enum InputLevel grabtype,
2540        GrabMask *mask)
2541{
2542    WindowPtr pWin;
2543    GrabPtr grab;
2544    KeyClassPtr k = dev->key;
2545    Mask access_mode = DixGrabAccess;
2546    int rc, type = -1;
2547
2548    rc = CheckGrabValues(client, param);
2549    if (rc != Success)
2550        return rc;
2551    if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL)
2552        return BadMatch;
2553    if (grabtype == XI) {
2554        if ((key > k->xkbInfo->desc->max_key_code ||
2555             key < k->xkbInfo->desc->min_key_code)
2556            && (key != AnyKey)) {
2557            client->errorValue = key;
2558            return BadValue;
2559        }
2560        type = DeviceKeyPress;
2561    }
2562    else if (grabtype == XI2)
2563        type = XI_KeyPress;
2564
2565    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2566    if (rc != Success)
2567        return rc;
2568    if (param->this_device_mode == GrabModeSync ||
2569        param->other_devices_mode == GrabModeSync)
2570        access_mode |= DixFreezeAccess;
2571    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
2572    if (rc != Success)
2573        return rc;
2574
2575    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
2576                      mask, param, type, key, NULL, NULL);
2577    if (!grab)
2578        return BadAlloc;
2579    return AddPassiveGrabToList(client, grab);
2580}
2581
2582/* Enter/FocusIn grab */
2583int
2584GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
2585           GrabParameters *param, GrabMask *mask)
2586{
2587    WindowPtr pWin;
2588    CursorPtr cursor;
2589    GrabPtr grab;
2590    Mask access_mode = DixGrabAccess;
2591    int rc;
2592
2593    rc = CheckGrabValues(client, param);
2594    if (rc != Success)
2595        return rc;
2596
2597    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2598    if (rc != Success)
2599        return rc;
2600    if (param->cursor == None)
2601        cursor = NullCursor;
2602    else {
2603        rc = dixLookupResourceByType((void **) &cursor, param->cursor,
2604                                     RT_CURSOR, client, DixUseAccess);
2605        if (rc != Success) {
2606            client->errorValue = param->cursor;
2607            return rc;
2608        }
2609        access_mode |= DixForceAccess;
2610    }
2611    if (param->this_device_mode == GrabModeSync ||
2612        param->other_devices_mode == GrabModeSync)
2613        access_mode |= DixFreezeAccess;
2614    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
2615    if (rc != Success)
2616        return rc;
2617
2618    grab = CreateGrab(client->index, dev, dev, pWin, XI2,
2619                      mask, param,
2620                      (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn, 0,
2621                      NULL, cursor);
2622
2623    if (!grab)
2624        return BadAlloc;
2625
2626    return AddPassiveGrabToList(client, grab);
2627}
2628
2629/* Touch grab */
2630int
2631GrabTouchOrGesture(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
2632                   int type, GrabParameters *param, GrabMask *mask)
2633{
2634    WindowPtr pWin;
2635    GrabPtr grab;
2636    int rc;
2637
2638    rc = CheckGrabValues(client, param);
2639    if (rc != Success)
2640        return rc;
2641
2642    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2643    if (rc != Success)
2644        return rc;
2645    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGrabAccess);
2646    if (rc != Success)
2647        return rc;
2648
2649    grab = CreateGrab(client->index, dev, mod_dev, pWin, XI2,
2650                      mask, param, type, 0, NullWindow, NullCursor);
2651    if (!grab)
2652        return BadAlloc;
2653
2654    return AddPassiveGrabToList(client, grab);
2655}
2656
2657int
2658SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
2659                Mask mask, Mask exclusivemasks)
2660{
2661    int mskidx = dev->id;
2662    int i, ret;
2663    Mask check;
2664    InputClientsPtr others;
2665
2666    check = (mask & exclusivemasks);
2667    if (wOtherInputMasks(pWin)) {
2668        if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {
2669            /* It is illegal for two different clients to select on any of
2670             * the events for maskcheck. However, it is OK, for some client
2671             * to continue selecting on one of those events.
2672             */
2673            for (others = wOtherInputMasks(pWin)->inputClients; others;
2674                 others = others->next) {
2675                if (!SameClient(others, client) && (check &
2676                                                    others->mask[mskidx]))
2677                    return BadAccess;
2678            }
2679        }
2680        for (others = wOtherInputMasks(pWin)->inputClients; others;
2681             others = others->next) {
2682            if (SameClient(others, client)) {
2683                check = others->mask[mskidx];
2684                others->mask[mskidx] = mask;
2685                if (mask == 0) {
2686                    for (i = 0; i < EMASKSIZE; i++)
2687                        if (i != mskidx && others->mask[i] != 0)
2688                            break;
2689                    if (i == EMASKSIZE) {
2690                        RecalculateDeviceDeliverableEvents(pWin);
2691                        if (ShouldFreeInputMasks(pWin, FALSE))
2692                            FreeResource(others->resource, RT_NONE);
2693                        return Success;
2694                    }
2695                }
2696                goto maskSet;
2697            }
2698        }
2699    }
2700    check = 0;
2701    if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
2702        return ret;
2703 maskSet:
2704    if (dev->valuator)
2705        if ((dev->valuator->motionHintWindow == pWin) &&
2706            (mask & DevicePointerMotionHintMask) &&
2707            !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
2708            dev->valuator->motionHintWindow = NullWindow;
2709    RecalculateDeviceDeliverableEvents(pWin);
2710    return Success;
2711}
2712
2713static void
2714FreeInputClient(InputClientsPtr * other)
2715{
2716    xi2mask_free(&(*other)->xi2mask);
2717    free(*other);
2718    *other = NULL;
2719}
2720
2721static InputClientsPtr
2722AllocInputClient(void)
2723{
2724    return calloc(1, sizeof(InputClients));
2725}
2726
2727int
2728AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
2729{
2730    InputClientsPtr others;
2731
2732    if (!pWin->optional && !MakeWindowOptional(pWin))
2733        return BadAlloc;
2734    others = AllocInputClient();
2735    if (!others)
2736        return BadAlloc;
2737    if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
2738        goto bail;
2739    others->xi2mask = xi2mask_new();
2740    if (!others->xi2mask)
2741        goto bail;
2742    others->mask[mskidx] = mask;
2743    others->resource = FakeClientID(client->index);
2744    others->next = pWin->optional->inputMasks->inputClients;
2745    pWin->optional->inputMasks->inputClients = others;
2746    if (!AddResource(others->resource, RT_INPUTCLIENT, (void *) pWin))
2747        goto bail;
2748    return Success;
2749
2750 bail:
2751    FreeInputClient(&others);
2752    return BadAlloc;
2753}
2754
2755static Bool
2756MakeInputMasks(WindowPtr pWin)
2757{
2758    struct _OtherInputMasks *imasks;
2759
2760    imasks = calloc(1, sizeof(struct _OtherInputMasks));
2761    if (!imasks)
2762        return FALSE;
2763    imasks->xi2mask = xi2mask_new();
2764    if (!imasks->xi2mask) {
2765        free(imasks);
2766        return FALSE;
2767    }
2768    pWin->optional->inputMasks = imasks;
2769    return TRUE;
2770}
2771
2772static void
2773FreeInputMask(OtherInputMasks ** imask)
2774{
2775    xi2mask_free(&(*imask)->xi2mask);
2776    free(*imask);
2777    *imask = NULL;
2778}
2779
2780#define XIPropagateMask (KeyPressMask | \
2781                         KeyReleaseMask | \
2782                         ButtonPressMask | \
2783                         ButtonReleaseMask | \
2784                         PointerMotionMask)
2785
2786void
2787RecalculateDeviceDeliverableEvents(WindowPtr pWin)
2788{
2789    InputClientsPtr others;
2790    struct _OtherInputMasks *inputMasks;        /* default: NULL */
2791    WindowPtr pChild, tmp;
2792    int i;
2793
2794    pChild = pWin;
2795    while (1) {
2796        if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
2797            xi2mask_zero(inputMasks->xi2mask, -1);
2798            for (others = inputMasks->inputClients; others;
2799                 others = others->next) {
2800                for (i = 0; i < EMASKSIZE; i++)
2801                    inputMasks->inputEvents[i] |= others->mask[i];
2802                xi2mask_merge(inputMasks->xi2mask, others->xi2mask);
2803            }
2804            for (i = 0; i < EMASKSIZE; i++)
2805                inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
2806            for (tmp = pChild->parent; tmp; tmp = tmp->parent)
2807                if (wOtherInputMasks(tmp))
2808                    for (i = 0; i < EMASKSIZE; i++)
2809                        inputMasks->deliverableEvents[i] |=
2810                            (wOtherInputMasks(tmp)->deliverableEvents[i]
2811                             & ~inputMasks->dontPropagateMask[i] &
2812                             XIPropagateMask);
2813        }
2814        if (pChild->firstChild) {
2815            pChild = pChild->firstChild;
2816            continue;
2817        }
2818        while (!pChild->nextSib && (pChild != pWin))
2819            pChild = pChild->parent;
2820        if (pChild == pWin)
2821            break;
2822        pChild = pChild->nextSib;
2823    }
2824}
2825
2826int
2827InputClientGone(WindowPtr pWin, XID id)
2828{
2829    InputClientsPtr other, prev;
2830
2831    if (!wOtherInputMasks(pWin))
2832        return Success;
2833    prev = 0;
2834    for (other = wOtherInputMasks(pWin)->inputClients; other;
2835         other = other->next) {
2836        if (other->resource == id) {
2837            if (prev) {
2838                prev->next = other->next;
2839                FreeInputClient(&other);
2840            }
2841            else if (!(other->next)) {
2842                if (ShouldFreeInputMasks(pWin, TRUE)) {
2843                    OtherInputMasks *mask = wOtherInputMasks(pWin);
2844
2845                    mask->inputClients = other->next;
2846                    FreeInputMask(&mask);
2847                    pWin->optional->inputMasks = (OtherInputMasks *) NULL;
2848                    CheckWindowOptionalNeed(pWin);
2849                    FreeInputClient(&other);
2850                }
2851                else {
2852                    other->resource = FakeClientID(0);
2853                    if (!AddResource(other->resource, RT_INPUTCLIENT,
2854                                     (void *) pWin))
2855                        return BadAlloc;
2856                }
2857            }
2858            else {
2859                wOtherInputMasks(pWin)->inputClients = other->next;
2860                FreeInputClient(&other);
2861            }
2862            RecalculateDeviceDeliverableEvents(pWin);
2863            return Success;
2864        }
2865        prev = other;
2866    }
2867    FatalError("client not on device event list");
2868}
2869
2870/**
2871 * Search for window in each touch trace for each device. Remove the window
2872 * and all its subwindows from the trace when found. The initial window
2873 * order is preserved.
2874 */
2875void
2876WindowGone(WindowPtr win)
2877{
2878    DeviceIntPtr dev;
2879
2880    for (dev = inputInfo.devices; dev; dev = dev->next) {
2881        TouchClassPtr t = dev->touch;
2882        int i;
2883
2884        if (!t)
2885            continue;
2886
2887        for (i = 0; i < t->num_touches; i++) {
2888            SpritePtr sprite = &t->touches[i].sprite;
2889            int j;
2890
2891            for (j = 0; j < sprite->spriteTraceGood; j++) {
2892                if (sprite->spriteTrace[j] == win) {
2893                    sprite->spriteTraceGood = j;
2894                    break;
2895                }
2896            }
2897        }
2898    }
2899}
2900
2901int
2902SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
2903          xEvent *ev, Mask mask, int count)
2904{
2905    WindowPtr pWin;
2906    WindowPtr effectiveFocus = NullWindow;      /* only set if dest==InputFocus */
2907    WindowPtr spriteWin = GetSpriteWindow(d);
2908
2909    if (dest == PointerWindow)
2910        pWin = spriteWin;
2911    else if (dest == InputFocus) {
2912        WindowPtr inputFocus;
2913
2914        if (!d->focus)
2915            inputFocus = spriteWin;
2916        else
2917            inputFocus = d->focus->win;
2918
2919        if (inputFocus == FollowKeyboardWin)
2920            inputFocus = inputInfo.keyboard->focus->win;
2921
2922        if (inputFocus == NoneWin)
2923            return Success;
2924
2925        /* If the input focus is PointerRootWin, send the event to where
2926         * the pointer is if possible, then perhaps propagate up to root. */
2927        if (inputFocus == PointerRootWin)
2928            inputFocus = GetCurrentRootWindow(d);
2929
2930        if (IsParent(inputFocus, spriteWin)) {
2931            effectiveFocus = inputFocus;
2932            pWin = spriteWin;
2933        }
2934        else
2935            effectiveFocus = pWin = inputFocus;
2936    }
2937    else
2938        dixLookupWindow(&pWin, dest, client, DixSendAccess);
2939    if (!pWin)
2940        return BadWindow;
2941    if ((propagate != xFalse) && (propagate != xTrue)) {
2942        client->errorValue = propagate;
2943        return BadValue;
2944    }
2945    ev->u.u.type |= 0x80;
2946    if (propagate) {
2947        for (; pWin; pWin = pWin->parent) {
2948            if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
2949                return Success;
2950            if (pWin == effectiveFocus)
2951                return Success;
2952            if (wOtherInputMasks(pWin))
2953                mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
2954            if (!mask)
2955                break;
2956        }
2957    }
2958    else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
2959        DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
2960    return Success;
2961}
2962
2963int
2964SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
2965{
2966    int i;
2967    ButtonClassPtr b = dev->button;
2968
2969    if (b == NULL)
2970        return BadMatch;
2971
2972    if (nElts != b->numButtons) {
2973        client->errorValue = nElts;
2974        return BadValue;
2975    }
2976    if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
2977        return BadValue;
2978    for (i = 0; i < nElts; i++)
2979        if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
2980            return MappingBusy;
2981    for (i = 0; i < nElts; i++)
2982        b->map[i + 1] = map[i];
2983    return Success;
2984}
2985
2986int
2987ChangeKeyMapping(ClientPtr client,
2988                 DeviceIntPtr dev,
2989                 unsigned len,
2990                 int type,
2991                 KeyCode firstKeyCode,
2992                 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
2993{
2994    KeySymsRec keysyms;
2995    KeyClassPtr k = dev->key;
2996
2997    if (k == NULL)
2998        return BadMatch;
2999
3000    if (len != (keyCodes * keySymsPerKeyCode))
3001        return BadLength;
3002
3003    if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
3004        (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
3005        client->errorValue = firstKeyCode;
3006        return BadValue;
3007    }
3008    if (keySymsPerKeyCode == 0) {
3009        client->errorValue = 0;
3010        return BadValue;
3011    }
3012    keysyms.minKeyCode = firstKeyCode;
3013    keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
3014    keysyms.mapWidth = keySymsPerKeyCode;
3015    keysyms.map = map;
3016
3017    XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
3018                          serverClient);
3019
3020    return Success;
3021}
3022
3023static void
3024DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
3025{
3026    WindowPtr parent;
3027
3028    /* Deactivate any grabs performed on this window, before making
3029     * any input focus changes.
3030     * Deactivating a device grab should cause focus events. */
3031
3032    if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
3033        (*dev->deviceGrab.DeactivateGrab) (dev);
3034
3035    /* If the focus window is a root window (ie. has no parent)
3036     * then don't delete the focus from it. */
3037
3038    if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
3039        int focusEventMode = NotifyNormal;
3040
3041        /* If a grab is in progress, then alter the mode of focus events. */
3042
3043        if (dev->deviceGrab.grab)
3044            focusEventMode = NotifyWhileGrabbed;
3045
3046        switch (dev->focus->revert) {
3047        case RevertToNone:
3048            if (!ActivateFocusInGrab(dev, pWin, NoneWin))
3049                DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
3050            dev->focus->win = NoneWin;
3051            dev->focus->traceGood = 0;
3052            break;
3053        case RevertToParent:
3054            parent = pWin;
3055            do {
3056                parent = parent->parent;
3057                dev->focus->traceGood--;
3058            }
3059            while (!parent->realized);
3060            if (!ActivateFocusInGrab(dev, pWin, parent))
3061                DoFocusEvents(dev, pWin, parent, focusEventMode);
3062            dev->focus->win = parent;
3063            dev->focus->revert = RevertToNone;
3064            break;
3065        case RevertToPointerRoot:
3066            if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
3067                DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
3068            dev->focus->win = PointerRootWin;
3069            dev->focus->traceGood = 0;
3070            break;
3071        case RevertToFollowKeyboard:
3072        {
3073            DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
3074
3075            if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
3076                kbd = inputInfo.keyboard;
3077            if (kbd->focus->win) {
3078                if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
3079                    DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
3080                dev->focus->win = FollowKeyboardWin;
3081                dev->focus->traceGood = 0;
3082            }
3083            else {
3084                if (!ActivateFocusInGrab(dev, pWin, NoneWin))
3085                    DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
3086                dev->focus->win = NoneWin;
3087                dev->focus->traceGood = 0;
3088            }
3089        }
3090            break;
3091        }
3092    }
3093
3094    if (dev->valuator)
3095        if (dev->valuator->motionHintWindow == pWin)
3096            dev->valuator->motionHintWindow = NullWindow;
3097}
3098
3099void
3100DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
3101{
3102    int i;
3103    DeviceIntPtr dev;
3104    InputClientsPtr ic;
3105    struct _OtherInputMasks *inputMasks;
3106
3107    for (dev = inputInfo.devices; dev; dev = dev->next) {
3108        DeleteDeviceFromAnyExtEvents(pWin, dev);
3109    }
3110
3111    for (dev = inputInfo.off_devices; dev; dev = dev->next)
3112        DeleteDeviceFromAnyExtEvents(pWin, dev);
3113
3114    if (freeResources)
3115        while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
3116            ic = inputMasks->inputClients;
3117            for (i = 0; i < EMASKSIZE; i++)
3118                inputMasks->dontPropagateMask[i] = 0;
3119            FreeResource(ic->resource, RT_NONE);
3120        }
3121}
3122
3123int
3124MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer *pEvents, Mask mask)
3125{
3126    DeviceIntPtr dev;
3127
3128    dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
3129                    DixReadAccess);
3130    if (!dev)
3131        return 0;
3132
3133    if (pEvents->type == DeviceMotionNotify) {
3134        if (mask & DevicePointerMotionHintMask) {
3135            if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
3136                return 1;       /* don't send, but pretend we did */
3137            }
3138            pEvents->detail = NotifyHint;
3139        }
3140        else {
3141            pEvents->detail = NotifyNormal;
3142        }
3143    }
3144    return 0;
3145}
3146
3147void
3148CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
3149                             deviceKeyButtonPointer *xE, GrabPtr grab,
3150                             ClientPtr client, Mask deliveryMask)
3151{
3152    DeviceIntPtr dev;
3153
3154    dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
3155                    DixGrabAccess);
3156    if (!dev)
3157        return;
3158
3159    if (type == DeviceMotionNotify)
3160        dev->valuator->motionHintWindow = pWin;
3161    else if ((type == DeviceButtonPress) && (!grab) &&
3162             (deliveryMask & DeviceButtonGrabMask)) {
3163        GrabPtr tempGrab;
3164
3165        tempGrab = AllocGrab(NULL);
3166        if (!tempGrab)
3167            return;
3168
3169        tempGrab->device = dev;
3170        tempGrab->resource = client->clientAsMask;
3171        tempGrab->window = pWin;
3172        tempGrab->ownerEvents =
3173            (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
3174        tempGrab->eventMask = deliveryMask;
3175        tempGrab->keyboardMode = GrabModeAsync;
3176        tempGrab->pointerMode = GrabModeAsync;
3177        tempGrab->confineTo = NullWindow;
3178        tempGrab->cursor = NullCursor;
3179        tempGrab->next = NULL;
3180        (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, currentTime, TRUE);
3181        FreeGrab(tempGrab);
3182    }
3183}
3184
3185static Mask
3186DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
3187{
3188    InputClientsPtr other;
3189
3190    if (!wOtherInputMasks(pWin))
3191        return 0;
3192    for (other = wOtherInputMasks(pWin)->inputClients; other;
3193         other = other->next) {
3194        if (SameClient(other, client))
3195            return other->mask[dev->id];
3196    }
3197    return 0;
3198}
3199
3200void
3201MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
3202{
3203    WindowPtr pWin;
3204    GrabPtr grab = dev->deviceGrab.grab;
3205
3206    pWin = dev->valuator->motionHintWindow;
3207
3208    if ((grab && SameClient(grab, client) &&
3209         ((grab->eventMask & DevicePointerMotionHintMask) ||
3210          (grab->ownerEvents &&
3211           (DeviceEventMaskForClient(dev, pWin, client) &
3212            DevicePointerMotionHintMask)))) ||
3213        (!grab &&
3214         (DeviceEventMaskForClient(dev, pWin, client) &
3215          DevicePointerMotionHintMask)))
3216        dev->valuator->motionHintWindow = NullWindow;
3217}
3218
3219int
3220DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
3221                             int maskndx)
3222{
3223    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
3224
3225    if (mask & ~XIPropagateMask) {
3226        client->errorValue = mask;
3227        return BadValue;
3228    }
3229
3230    if (mask == 0) {
3231        if (inputMasks)
3232            inputMasks->dontPropagateMask[maskndx] = mask;
3233    }
3234    else {
3235        if (!inputMasks)
3236            AddExtensionClient(pWin, client, 0, 0);
3237        inputMasks = wOtherInputMasks(pWin);
3238        inputMasks->dontPropagateMask[maskndx] = mask;
3239    }
3240    RecalculateDeviceDeliverableEvents(pWin);
3241    if (ShouldFreeInputMasks(pWin, FALSE))
3242        FreeResource(inputMasks->inputClients->resource, RT_NONE);
3243    return Success;
3244}
3245
3246Bool
3247ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
3248{
3249    int i;
3250    Mask allInputEventMasks = 0;
3251    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
3252
3253    for (i = 0; i < EMASKSIZE; i++)
3254        allInputEventMasks |= inputMasks->dontPropagateMask[i];
3255    if (!ignoreSelectedEvents)
3256        for (i = 0; i < EMASKSIZE; i++)
3257            allInputEventMasks |= inputMasks->inputEvents[i];
3258    if (allInputEventMasks == 0)
3259        return TRUE;
3260    else
3261        return FALSE;
3262}
3263
3264/***********************************************************************
3265 *
3266 * Walk through the window tree, finding all clients that want to know
3267 * about the Event.
3268 *
3269 */
3270
3271static void
3272FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
3273                       xEvent *ev, int count)
3274{
3275    WindowPtr p2;
3276
3277    while (p1) {
3278        p2 = p1->firstChild;
3279        DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
3280        FindInterestedChildren(dev, p2, mask, ev, count);
3281        p1 = p1->nextSib;
3282    }
3283}
3284
3285/***********************************************************************
3286 *
3287 * Send an event to interested clients in all windows on all screens.
3288 *
3289 */
3290
3291void
3292SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent *ev, int count)
3293{
3294    int i;
3295    WindowPtr pWin, p1;
3296
3297    for (i = 0; i < screenInfo.numScreens; i++) {
3298        pWin = screenInfo.screens[i]->root;
3299        if (!pWin)
3300            continue;
3301        DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
3302        p1 = pWin->firstChild;
3303        FindInterestedChildren(dev, p1, mask, ev, count);
3304    }
3305}
3306
3307/**
3308 * Set the XI2 mask for the given client on the given window.
3309 * @param dev The device to set the mask for.
3310 * @param win The window to set the mask on.
3311 * @param client The client setting the mask.
3312 * @param len Number of bytes in mask.
3313 * @param mask Event mask in the form of (1 << eventtype)
3314 */
3315int
3316XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
3317               unsigned int len, unsigned char *mask)
3318{
3319    OtherInputMasks *masks;
3320    InputClientsPtr others = NULL;
3321
3322    masks = wOtherInputMasks(win);
3323    if (masks) {
3324        for (others = wOtherInputMasks(win)->inputClients; others;
3325             others = others->next) {
3326            if (SameClient(others, client)) {
3327                xi2mask_zero(others->xi2mask, dev->id);
3328                break;
3329            }
3330        }
3331    }
3332
3333    if (len && !others) {
3334        if (AddExtensionClient(win, client, 0, 0) != Success)
3335            return BadAlloc;
3336        others = wOtherInputMasks(win)->inputClients;
3337    }
3338
3339    if (others) {
3340        xi2mask_zero(others->xi2mask, dev->id);
3341        len = min(len, xi2mask_mask_size(others->xi2mask));
3342    }
3343
3344    if (len) {
3345        xi2mask_set_one_mask(others->xi2mask, dev->id, mask, len);
3346    }
3347
3348    RecalculateDeviceDeliverableEvents(win);
3349
3350    return Success;
3351}
3352