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