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