exevents.c revision 1b5d61b8
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
1297    if (listener->type == LISTENER_GRAB ||
1298        listener->type == LISTENER_POINTER_GRAB) {
1299
1300        *grab = listener->grab;
1301
1302        BUG_RETURN_VAL(!*grab, FALSE);
1303
1304        *client = rClient(*grab);
1305        *win = (*grab)->window;
1306        *mask = (*grab)->xi2mask;
1307    }
1308    else {
1309        rc = dixLookupResourceByType((void **) win, listener->listener,
1310                                     listener->resource_type,
1311                                     serverClient, DixSendAccess);
1312        if (rc != Success)
1313            return FALSE;
1314
1315        if (listener->level == XI2) {
1316            int evtype;
1317
1318            if (ti->emulate_pointer &&
1319                listener->type == LISTENER_POINTER_REGULAR)
1320                evtype = GetXI2Type(TouchGetPointerEventType(ev));
1321            else
1322                evtype = GetXI2Type(ev->any.type);
1323
1324            nt_list_for_each_entry(iclients,
1325                                   wOtherInputMasks(*win)->inputClients, next)
1326                if (xi2mask_isset(iclients->xi2mask, dev, evtype))
1327                break;
1328
1329            BUG_RETURN_VAL(!iclients, FALSE);
1330
1331            *mask = iclients->xi2mask;
1332            *client = rClient(iclients);
1333        }
1334        else if (listener->level == XI) {
1335            int xi_type = GetXIType(TouchGetPointerEventType(ev));
1336            Mask xi_filter = event_get_filter_from_type(dev, xi_type);
1337
1338            nt_list_for_each_entry(iclients,
1339                                   wOtherInputMasks(*win)->inputClients, next)
1340                if (iclients->mask[dev->id] & xi_filter)
1341                break;
1342            BUG_RETURN_VAL(!iclients, FALSE);
1343
1344            *client = rClient(iclients);
1345        }
1346        else {
1347            int coretype = GetCoreType(TouchGetPointerEventType(ev));
1348            Mask core_filter = event_get_filter_from_type(dev, coretype);
1349            OtherClients *oclients;
1350
1351            /* all others */
1352            nt_list_for_each_entry(oclients,
1353                                   (OtherClients *) wOtherClients(*win), next)
1354                if (oclients->mask & core_filter)
1355                    break;
1356
1357            /* if owner selected, oclients is NULL */
1358            *client = oclients ? rClient(oclients) : wClient(*win);
1359        }
1360
1361        *grab = NULL;
1362    }
1363
1364    return TRUE;
1365}
1366
1367static int
1368DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1369                          InternalEvent *ev, TouchListener * listener,
1370                          ClientPtr client, WindowPtr win, GrabPtr grab,
1371                          XI2Mask *xi2mask)
1372{
1373    InternalEvent motion, button;
1374    InternalEvent *ptrev = &motion;
1375    int nevents;
1376    DeviceIntPtr kbd;
1377
1378    /* We don't deliver pointer events to non-owners */
1379    if (!TouchResourceIsOwner(ti, listener->listener))
1380        return !Success;
1381
1382    if (!ti->emulate_pointer)
1383        return !Success;
1384
1385    nevents = TouchConvertToPointerEvent(ev, &motion, &button);
1386    BUG_RETURN_VAL(nevents == 0, BadValue);
1387
1388    if (nevents > 1)
1389        ptrev = &button;
1390
1391    kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
1392    event_set_state(dev, kbd, &ptrev->device_event);
1393    ptrev->device_event.corestate = event_get_corestate(dev, kbd);
1394
1395    if (grab) {
1396        /* this side-steps the usual activation mechanisms, but... */
1397        if (ev->any.type == ET_TouchBegin && !dev->deviceGrab.grab)
1398            ActivatePassiveGrab(dev, grab, ptrev, ev);  /* also delivers the event */
1399        else {
1400            int deliveries = 0;
1401
1402            /* 'grab' is the passive grab, but if the grab isn't active,
1403             * don't deliver */
1404            if (!dev->deviceGrab.grab)
1405                return !Success;
1406
1407            if (grab->ownerEvents) {
1408                WindowPtr focus = NullWindow;
1409                WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite);
1410
1411                deliveries = DeliverDeviceEvents(sprite_win, ptrev, grab, focus, dev);
1412            }
1413
1414            if (!deliveries)
1415                deliveries = DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
1416
1417            /* We must accept the touch sequence once a pointer listener has
1418             * received one event past ButtonPress. */
1419            if (deliveries && ev->any.type != ET_TouchBegin &&
1420                !(ev->device_event.flags & TOUCH_CLIENT_ID))
1421                TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
1422
1423            if (ev->any.type == ET_TouchEnd &&
1424                ti->num_listeners == 1 &&
1425                !dev->button->buttonsDown &&
1426                dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
1427                (*dev->deviceGrab.DeactivateGrab) (dev);
1428                CheckOldestTouch(dev);
1429                return Success;
1430            }
1431        }
1432    }
1433    else {
1434        GrabPtr devgrab = dev->deviceGrab.grab;
1435        WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite);
1436
1437        DeliverDeviceEvents(sprite_win, ptrev, grab, win, dev);
1438        /* FIXME: bad hack
1439         * Implicit passive grab activated in response to this event. Store
1440         * the event.
1441         */
1442        if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab) {
1443            TouchListener *l;
1444            GrabPtr g;
1445
1446            devgrab = dev->deviceGrab.grab;
1447            g = AllocGrab(devgrab);
1448            BUG_WARN(!g);
1449
1450            *dev->deviceGrab.sync.event = ev->device_event;
1451
1452            /* The listener array has a sequence of grabs and then one event
1453             * selection. Implicit grab activation occurs through delivering an
1454             * event selection. Thus, we update the last listener in the array.
1455             */
1456            l = &ti->listeners[ti->num_listeners - 1];
1457            l->listener = g->resource;
1458            l->grab = g;
1459            //l->resource_type = RT_NONE;
1460
1461            if (devgrab->grabtype != XI2 || devgrab->type != XI_TouchBegin)
1462                l->type = LISTENER_POINTER_GRAB;
1463            else
1464                l->type = LISTENER_GRAB;
1465        }
1466
1467    }
1468    if (ev->any.type == ET_TouchBegin)
1469        listener->state = LISTENER_IS_OWNER;
1470    else if (ev->any.type == ET_TouchEnd)
1471        listener->state = LISTENER_HAS_END;
1472
1473    return Success;
1474}
1475
1476static void
1477DeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1478                           InternalEvent *ev)
1479{
1480    DeviceEvent motion;
1481
1482    if (ti->num_listeners) {
1483        ClientPtr client;
1484        WindowPtr win;
1485        GrabPtr grab;
1486        XI2Mask *mask;
1487
1488        if (ti->listeners[0].type != LISTENER_POINTER_REGULAR &&
1489            ti->listeners[0].type != LISTENER_POINTER_GRAB)
1490            return;
1491
1492        motion = ev->device_event;
1493        motion.type = ET_TouchUpdate;
1494        motion.detail.button = 0;
1495
1496        if (!RetrieveTouchDeliveryData(dev, ti, (InternalEvent*)&motion,
1497                                       &ti->listeners[0], &client, &win, &grab,
1498                                       &mask))
1499            return;
1500
1501        /* There may be a pointer grab on the device */
1502        if (!grab) {
1503            grab = dev->deviceGrab.grab;
1504            if (grab) {
1505                win = grab->window;
1506                mask = grab->xi2mask;
1507                client = rClient(grab);
1508            }
1509        }
1510
1511        DeliverTouchEmulatedEvent(dev, ti, (InternalEvent*)&motion, &ti->listeners[0], client,
1512                                  win, grab, mask);
1513    }
1514    else {
1515        InternalEvent button;
1516        int converted;
1517
1518        converted = TouchConvertToPointerEvent(ev, (InternalEvent*)&motion, &button);
1519
1520        BUG_WARN(converted == 0);
1521        if (converted)
1522            ProcessOtherEvent((InternalEvent*)&motion, dev);
1523    }
1524}
1525
1526/**
1527 * Processes and delivers a TouchBegin, TouchUpdate, or a
1528 * TouchEnd event.
1529 *
1530 * Due to having rather different delivery semantics (see the Xi 2.2 protocol
1531 * spec for more information), this implements its own grab and event-selection
1532 * delivery logic.
1533 */
1534static void
1535ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
1536{
1537    TouchClassPtr t = dev->touch;
1538    TouchPointInfoPtr ti;
1539    uint32_t touchid;
1540    int type = ev->any.type;
1541    int emulate_pointer = ! !(ev->device_event.flags & TOUCH_POINTER_EMULATED);
1542    DeviceIntPtr kbd;
1543
1544    if (!t)
1545        return;
1546
1547    touchid = ev->device_event.touchid;
1548
1549    if (type == ET_TouchBegin && !(ev->device_event.flags & TOUCH_REPLAYING)) {
1550        ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
1551                             emulate_pointer);
1552    }
1553    else
1554        ti = TouchFindByClientID(dev, touchid);
1555
1556    /* Active pointer grab */
1557    if (emulate_pointer && dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab &&
1558        (dev->deviceGrab.grab->grabtype == CORE ||
1559         dev->deviceGrab.grab->grabtype == XI ||
1560         !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin)))
1561    {
1562        /* Active pointer grab on touch point and we get a TouchEnd - claim this
1563         * touchpoint accepted, otherwise clients waiting for ownership will
1564         * wait on this touchpoint until this client ungrabs, or the cows come
1565         * home, whichever is earlier */
1566        if (ti && type == ET_TouchEnd)
1567            TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
1568        else if (!ti && type != ET_TouchBegin) {
1569            /* Under the following circumstances we create a new touch record for an
1570             * existing touch:
1571             *
1572             * - The touch may be pointer emulated
1573             * - An explicit grab is active on the device
1574             * - The grab is a pointer grab
1575             *
1576             * This allows for an explicit grab to receive pointer events for an already
1577             * active touch.
1578             */
1579            ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
1580                                 emulate_pointer);
1581            if (!ti) {
1582                DebugF("[Xi] %s: Failed to create new dix record for explicitly "
1583                       "grabbed touchpoint %d\n",
1584                       dev->name, touchid);
1585                return;
1586            }
1587
1588            TouchBuildSprite(dev, ti, ev);
1589            TouchSetupListeners(dev, ti, ev);
1590        }
1591    }
1592
1593    if (!ti) {
1594        DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
1595               dev->name, type, touchid);
1596        goto out;
1597    }
1598
1599    /* if emulate_pointer is set, emulate the motion event right
1600     * here, so we can ignore it for button event emulation. TouchUpdate
1601     * events which _only_ emulate motion just work normally */
1602    if (emulate_pointer && ev->any.type != ET_TouchUpdate)
1603        DeliverEmulatedMotionEvent(dev, ti, ev);
1604
1605    if (emulate_pointer && IsMaster(dev))
1606        CheckMotion(&ev->device_event, dev);
1607
1608    kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
1609    event_set_state(NULL, kbd, &ev->device_event);
1610    ev->device_event.corestate = event_get_corestate(NULL, kbd);
1611
1612    /* Make sure we have a valid window trace for event delivery; must be
1613     * called after event type mutation. Touch end events are always processed
1614     * in order to end touch records. */
1615    /* FIXME: check this */
1616    if ((type == ET_TouchBegin &&
1617         !(ev->device_event.flags & TOUCH_REPLAYING) &&
1618         !TouchBuildSprite(dev, ti, ev)) ||
1619        (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0))
1620        return;
1621
1622    TouchCopyValuatorData(&ev->device_event, ti);
1623    /* WARNING: the event type may change to TouchUpdate in
1624     * DeliverTouchEvents if a TouchEnd was delivered to a grabbing
1625     * owner */
1626    DeliverTouchEvents(dev, ti, ev, ev->device_event.resource);
1627    if (ev->any.type == ET_TouchEnd)
1628        TouchEndTouch(dev, ti);
1629
1630 out:
1631    if (emulate_pointer)
1632        UpdateDeviceState(dev, &ev->device_event);
1633}
1634
1635static void
1636ProcessBarrierEvent(InternalEvent *e, DeviceIntPtr dev)
1637{
1638    Mask filter;
1639    WindowPtr pWin;
1640    BarrierEvent *be = &e->barrier_event;
1641    xEvent *ev;
1642    int rc;
1643    GrabPtr grab = dev->deviceGrab.grab;
1644
1645    if (!IsMaster(dev))
1646        return;
1647
1648    if (dixLookupWindow(&pWin, be->window, serverClient, DixReadAccess) != Success)
1649        return;
1650
1651    if (grab)
1652        be->flags |= XIBarrierDeviceIsGrabbed;
1653
1654    rc = EventToXI2(e, &ev);
1655    if (rc != Success) {
1656        ErrorF("[Xi] event conversion from %s failed with code %d\n", __func__, rc);
1657        return;
1658    }
1659
1660    /* A client has a grab, deliver to this client if the grab_window is the
1661       barrier window.
1662
1663       Otherwise, deliver normally to the client.
1664     */
1665    if (grab &&
1666        CLIENT_ID(be->barrierid) == CLIENT_ID(grab->resource) &&
1667        grab->window->drawable.id == be->window) {
1668        DeliverGrabbedEvent(e, dev, FALSE);
1669    } else {
1670        filter = GetEventFilter(dev, ev);
1671
1672        DeliverEventsToWindow(dev, pWin, ev, 1,
1673                              filter, NullGrab);
1674    }
1675    free(ev);
1676}
1677
1678/**
1679 * Process DeviceEvents and DeviceChangedEvents.
1680 */
1681static void
1682ProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device)
1683{
1684    GrabPtr grab;
1685    Bool deactivateDeviceGrab = FALSE;
1686    int key = 0, rootX, rootY;
1687    ButtonClassPtr b;
1688    int ret = 0;
1689    int corestate;
1690    DeviceIntPtr mouse = NULL, kbd = NULL;
1691    DeviceEvent *event = &ev->device_event;
1692
1693    if (IsPointerDevice(device)) {
1694        kbd = GetMaster(device, KEYBOARD_OR_FLOAT);
1695        mouse = device;
1696        if (!kbd->key)          /* can happen with floating SDs */
1697            kbd = NULL;
1698    }
1699    else {
1700        mouse = GetMaster(device, POINTER_OR_FLOAT);
1701        kbd = device;
1702        if (!mouse->valuator || !mouse->button) /* may be float. SDs */
1703            mouse = NULL;
1704    }
1705
1706    corestate = event_get_corestate(mouse, kbd);
1707    event_set_state(mouse, kbd, event);
1708
1709    ret = UpdateDeviceState(device, event);
1710    if (ret == DONT_PROCESS)
1711        return;
1712
1713    b = device->button;
1714
1715    if (IsMaster(device) || IsFloating(device))
1716        CheckMotion(event, device);
1717
1718    switch (event->type) {
1719    case ET_Motion:
1720    case ET_ButtonPress:
1721    case ET_ButtonRelease:
1722    case ET_KeyPress:
1723    case ET_KeyRelease:
1724    case ET_ProximityIn:
1725    case ET_ProximityOut:
1726        GetSpritePosition(device, &rootX, &rootY);
1727        event->root_x = rootX;
1728        event->root_y = rootY;
1729        NoticeEventTime((InternalEvent *) event, device);
1730        event->corestate = corestate;
1731        key = event->detail.key;
1732        break;
1733    default:
1734        break;
1735    }
1736
1737    /* send KeyPress and KeyRelease events to XACE plugins */
1738    if (XaceHookIsSet(XACE_KEY_AVAIL) &&
1739            (event->type == ET_KeyPress || event->type == ET_KeyRelease)) {
1740        xEvent *core;
1741        int count;
1742
1743        if (EventToCore(ev, &core, &count) == Success && count > 0) {
1744            XaceHook(XACE_KEY_AVAIL, core, device, 0);
1745            free(core);
1746        }
1747    }
1748
1749    if (DeviceEventCallback && !syncEvents.playingEvents) {
1750        DeviceEventInfoRec eventinfo;
1751        SpritePtr pSprite = device->spriteInfo->sprite;
1752
1753        /* see comment in EnqueueEvents regarding the next three lines */
1754        if (ev->any.type == ET_Motion)
1755            ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
1756
1757        eventinfo.device = device;
1758        eventinfo.event = ev;
1759        CallCallbacks(&DeviceEventCallback, (void *) &eventinfo);
1760    }
1761
1762    grab = device->deviceGrab.grab;
1763
1764    switch (event->type) {
1765    case ET_KeyPress:
1766        /* Don't deliver focus events (e.g. from KeymapNotify when running
1767         * nested) to clients. */
1768        if (event->source_type == EVENT_SOURCE_FOCUS)
1769            return;
1770        if (!grab && CheckDeviceGrabs(device, event, 0))
1771            return;
1772        break;
1773    case ET_KeyRelease:
1774        if (grab && device->deviceGrab.fromPassiveGrab &&
1775            (key == device->deviceGrab.activatingKey) &&
1776            GrabIsKeyboardGrab(device->deviceGrab.grab))
1777            deactivateDeviceGrab = TRUE;
1778        break;
1779    case ET_ButtonPress:
1780        if (b->map[key] == 0)   /* there's no button 0 */
1781            return;
1782        event->detail.button = b->map[key];
1783        if (!grab && CheckDeviceGrabs(device, event, 0)) {
1784            /* if a passive grab was activated, the event has been sent
1785             * already */
1786            return;
1787        }
1788        break;
1789    case ET_ButtonRelease:
1790        if (b->map[key] == 0)   /* there's no button 0 */
1791            return;
1792        event->detail.button = b->map[key];
1793        if (grab && !b->buttonsDown &&
1794            device->deviceGrab.fromPassiveGrab &&
1795            GrabIsPointerGrab(device->deviceGrab.grab))
1796            deactivateDeviceGrab = TRUE;
1797    default:
1798        break;
1799    }
1800
1801    /* Don't deliver focus events (e.g. from KeymapNotify when running
1802     * nested) to clients. */
1803    if (event->source_type != EVENT_SOURCE_FOCUS) {
1804        if (grab)
1805            DeliverGrabbedEvent((InternalEvent *) event, device,
1806                                deactivateDeviceGrab);
1807        else if (device->focus && !IsPointerEvent(ev))
1808            DeliverFocusedEvent(device, (InternalEvent *) event,
1809                                GetSpriteWindow(device));
1810        else
1811            DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent *) event,
1812                                NullGrab, NullWindow, device);
1813    }
1814
1815    if (deactivateDeviceGrab == TRUE) {
1816        (*device->deviceGrab.DeactivateGrab) (device);
1817
1818        if (!IsMaster (device) && !IsFloating (device)) {
1819            int flags, num_events = 0;
1820            InternalEvent dce;
1821
1822            flags = (IsPointerDevice (device)) ?
1823                DEVCHANGE_POINTER_EVENT : DEVCHANGE_KEYBOARD_EVENT;
1824            UpdateFromMaster (&dce, device, flags, &num_events);
1825            BUG_WARN(num_events > 1);
1826
1827            if (num_events == 1)
1828                ChangeMasterDeviceClasses(GetMaster (device, MASTER_ATTACHED),
1829                                          &dce.changed_event);
1830        }
1831
1832    }
1833
1834    event->detail.key = key;
1835}
1836
1837/**
1838 * Main device event processing function.
1839 * Called from when processing the events from the event queue.
1840 *
1841 */
1842void
1843ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
1844{
1845    verify_internal_event(ev);
1846
1847    switch (ev->any.type) {
1848    case ET_RawKeyPress:
1849    case ET_RawKeyRelease:
1850    case ET_RawButtonPress:
1851    case ET_RawButtonRelease:
1852    case ET_RawMotion:
1853    case ET_RawTouchBegin:
1854    case ET_RawTouchUpdate:
1855    case ET_RawTouchEnd:
1856        DeliverRawEvent(&ev->raw_event, device);
1857        break;
1858    case ET_TouchBegin:
1859    case ET_TouchUpdate:
1860    case ET_TouchEnd:
1861        ProcessTouchEvent(ev, device);
1862        break;
1863    case ET_TouchOwnership:
1864        /* TouchOwnership events are handled separately from the rest, as they
1865         * have more complex semantics. */
1866        ProcessTouchOwnershipEvent(&ev->touch_ownership_event, device);
1867        break;
1868    case ET_BarrierHit:
1869    case ET_BarrierLeave:
1870        ProcessBarrierEvent(ev, device);
1871        break;
1872    default:
1873        ProcessDeviceEvent(ev, device);
1874        break;
1875    }
1876}
1877
1878static int
1879DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1880                       InternalEvent *ev, TouchListener * listener,
1881                       ClientPtr client, WindowPtr win, GrabPtr grab,
1882                       XI2Mask *xi2mask)
1883{
1884    enum TouchListenerState state;
1885    int rc = Success;
1886    Bool has_ownershipmask;
1887
1888    if (listener->type == LISTENER_POINTER_REGULAR ||
1889        listener->type == LISTENER_POINTER_GRAB) {
1890        rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
1891                                       grab, xi2mask);
1892        if (rc == Success) {
1893            listener->state = LISTENER_IS_OWNER;
1894            /* async grabs cannot replay, so automatically accept this touch */
1895            if (listener->type == LISTENER_POINTER_GRAB &&
1896                dev->deviceGrab.grab &&
1897                dev->deviceGrab.fromPassiveGrab &&
1898                dev->deviceGrab.grab->pointerMode == GrabModeAsync)
1899                ActivateEarlyAccept(dev, ti);
1900        }
1901        goto out;
1902    }
1903
1904    has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
1905
1906    if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
1907        rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1908    if (!TouchResourceIsOwner(ti, listener->listener)) {
1909        if (has_ownershipmask)
1910            state = LISTENER_AWAITING_OWNER;
1911        else
1912            state = LISTENER_AWAITING_BEGIN;
1913    }
1914    else {
1915        if (has_ownershipmask)
1916            TouchSendOwnershipEvent(dev, ti, 0, listener->listener);
1917
1918        if (listener->type == LISTENER_REGULAR)
1919            state = LISTENER_HAS_ACCEPTED;
1920        else
1921            state = LISTENER_IS_OWNER;
1922    }
1923    listener->state = state;
1924
1925 out:
1926    return rc;
1927}
1928
1929static int
1930DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1931                     TouchListener * listener, ClientPtr client,
1932                     WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1933{
1934    int rc = Success;
1935
1936    if (listener->type == LISTENER_POINTER_REGULAR ||
1937        listener->type == LISTENER_POINTER_GRAB) {
1938        /* Note: If the active grab was ungrabbed, we already changed the
1939         * state to LISTENER_HAS_END but still get here. So we mustn't
1940         * actually send the event.
1941         * This is part two of the hack in DeactivatePointerGrab
1942         */
1943        if (listener->state != LISTENER_HAS_END) {
1944            rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
1945                                           grab, xi2mask);
1946
1947             /* Once we send a TouchEnd to a legacy listener, we're already well
1948              * past the accepting/rejecting stage (can only happen on
1949              * GrabModeSync + replay. This listener now gets the end event,
1950              * and we can continue.
1951              */
1952            if (rc == Success)
1953                listener->state = LISTENER_HAS_END;
1954        }
1955        goto out;
1956    }
1957
1958    /* A client is waiting for the begin, don't give it a TouchEnd */
1959    if (listener->state == LISTENER_AWAITING_BEGIN) {
1960        listener->state = LISTENER_HAS_END;
1961        goto out;
1962    }
1963
1964    /* Event in response to reject */
1965    if (ev->device_event.flags & TOUCH_REJECT ||
1966        (ev->device_event.flags & TOUCH_ACCEPT && !TouchResourceIsOwner(ti, listener->listener))) {
1967        /* Touch has been rejected, or accepted by its owner which is not this listener */
1968        if (listener->state != LISTENER_HAS_END)
1969            rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1970        listener->state = LISTENER_HAS_END;
1971    }
1972    else if (TouchResourceIsOwner(ti, listener->listener)) {
1973        Bool normal_end = !(ev->device_event.flags & TOUCH_ACCEPT);
1974
1975        /* FIXME: what about early acceptance */
1976        if (normal_end && listener->state != LISTENER_HAS_END)
1977            rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1978
1979        if ((ti->num_listeners > 1 ||
1980             (ti->num_grabs > 0 && listener->state != LISTENER_HAS_ACCEPTED)) &&
1981            (ev->device_event.flags & (TOUCH_ACCEPT | TOUCH_REJECT)) == 0) {
1982            ev->any.type = ET_TouchUpdate;
1983            ev->device_event.flags |= TOUCH_PENDING_END;
1984            ti->pending_finish = TRUE;
1985        }
1986
1987        if (normal_end)
1988            listener->state = LISTENER_HAS_END;
1989    }
1990
1991 out:
1992    return rc;
1993}
1994
1995static int
1996DeliverTouchEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1997                  TouchListener * listener, ClientPtr client,
1998                  WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1999{
2000    Bool has_ownershipmask = FALSE;
2001    int rc = Success;
2002
2003    if (xi2mask)
2004        has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
2005
2006    if (ev->any.type == ET_TouchOwnership) {
2007        ev->touch_ownership_event.deviceid = dev->id;
2008        if (!TouchResourceIsOwner(ti, listener->listener))
2009            goto out;
2010        rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
2011        listener->state = LISTENER_IS_OWNER;
2012    }
2013    else
2014        ev->device_event.deviceid = dev->id;
2015
2016    if (ev->any.type == ET_TouchBegin) {
2017        rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab,
2018                                    xi2mask);
2019    }
2020    else if (ev->any.type == ET_TouchUpdate) {
2021        if (listener->type == LISTENER_POINTER_REGULAR ||
2022            listener->type == LISTENER_POINTER_GRAB)
2023            DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, grab,
2024                                      xi2mask);
2025        else if (TouchResourceIsOwner(ti, listener->listener) ||
2026                 has_ownershipmask)
2027            rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
2028    }
2029    else if (ev->any.type == ET_TouchEnd)
2030        rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab,
2031                                  xi2mask);
2032
2033 out:
2034    return rc;
2035}
2036
2037/**
2038 * Delivers a touch events to all interested clients.  For TouchBegin events,
2039 * will update ti->listeners, ti->num_listeners, and ti->num_grabs.
2040 * May also mutate ev (type and flags) upon successful delivery.  If
2041 * @resource is non-zero, will only attempt delivery to the owner of that
2042 * resource.
2043 *
2044 * @return TRUE if the event was delivered at least once, FALSE otherwise
2045 */
2046void
2047DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
2048                   InternalEvent *ev, XID resource)
2049{
2050    int i;
2051
2052    if (ev->any.type == ET_TouchBegin &&
2053        !(ev->device_event.flags & (TOUCH_CLIENT_ID | TOUCH_REPLAYING)))
2054        TouchSetupListeners(dev, ti, ev);
2055
2056    TouchEventHistoryPush(ti, &ev->device_event);
2057
2058    for (i = 0; i < ti->num_listeners; i++) {
2059        GrabPtr grab = NULL;
2060        ClientPtr client;
2061        WindowPtr win;
2062        XI2Mask *mask;
2063        TouchListener *listener = &ti->listeners[i];
2064
2065        if (resource && listener->listener != resource)
2066            continue;
2067
2068        if (!RetrieveTouchDeliveryData(dev, ti, ev, listener, &client, &win,
2069                                       &grab, &mask))
2070            continue;
2071
2072        DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask);
2073    }
2074}
2075
2076int
2077InitProximityClassDeviceStruct(DeviceIntPtr dev)
2078{
2079    ProximityClassPtr proxc;
2080
2081    BUG_RETURN_VAL(dev == NULL, FALSE);
2082    BUG_RETURN_VAL(dev->proximity != NULL, FALSE);
2083
2084    proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
2085    if (!proxc)
2086        return FALSE;
2087    proxc->sourceid = dev->id;
2088    proxc->in_proximity = TRUE;
2089    dev->proximity = proxc;
2090    return TRUE;
2091}
2092
2093/**
2094 * Initialise the device's valuators. The memory must already be allocated,
2095 * this function merely inits the matching axis (specified through axnum) to
2096 * sane values.
2097 *
2098 * It is a condition that (minval < maxval).
2099 *
2100 * @see InitValuatorClassDeviceStruct
2101 */
2102Bool
2103InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
2104                       int maxval, int resolution, int min_res, int max_res,
2105                       int mode)
2106{
2107    AxisInfoPtr ax;
2108
2109    BUG_RETURN_VAL(dev == NULL, FALSE);
2110    BUG_RETURN_VAL(dev->valuator == NULL, FALSE);
2111    BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE);
2112    BUG_RETURN_VAL(minval > maxval && mode == Absolute, FALSE);
2113
2114    ax = dev->valuator->axes + axnum;
2115
2116    ax->min_value = minval;
2117    ax->max_value = maxval;
2118    ax->resolution = resolution;
2119    ax->min_resolution = min_res;
2120    ax->max_resolution = max_res;
2121    ax->label = label;
2122    ax->mode = mode;
2123
2124    if (mode & OutOfProximity)
2125        dev->proximity->in_proximity = FALSE;
2126
2127    return SetScrollValuator(dev, axnum, SCROLL_TYPE_NONE, 0, SCROLL_FLAG_NONE);
2128}
2129
2130/**
2131 * Set the given axis number as a scrolling valuator.
2132 */
2133Bool
2134SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type,
2135                  double increment, int flags)
2136{
2137    AxisInfoPtr ax;
2138    int *current_ax;
2139    InternalEvent dce;
2140    DeviceIntPtr master;
2141
2142    BUG_RETURN_VAL(dev == NULL, FALSE);
2143    BUG_RETURN_VAL(dev->valuator == NULL, FALSE);
2144    BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE);
2145
2146    switch (type) {
2147    case SCROLL_TYPE_VERTICAL:
2148        current_ax = &dev->valuator->v_scroll_axis;
2149        break;
2150    case SCROLL_TYPE_HORIZONTAL:
2151        current_ax = &dev->valuator->h_scroll_axis;
2152        break;
2153    case SCROLL_TYPE_NONE:
2154        ax = &dev->valuator->axes[axnum];
2155        ax->scroll.type = type;
2156        return TRUE;
2157    default:
2158        return FALSE;
2159    }
2160
2161    if (increment == 0.0)
2162        return FALSE;
2163
2164    if (*current_ax != -1 && axnum != *current_ax) {
2165        ax = &dev->valuator->axes[*current_ax];
2166        if (ax->scroll.type == type &&
2167            (flags & SCROLL_FLAG_PREFERRED) &&
2168            (ax->scroll.flags & SCROLL_FLAG_PREFERRED))
2169            return FALSE;
2170    }
2171    *current_ax = axnum;
2172
2173    ax = &dev->valuator->axes[axnum];
2174    ax->scroll.type = type;
2175    ax->scroll.increment = increment;
2176    ax->scroll.flags = flags;
2177
2178    master = GetMaster(dev, MASTER_ATTACHED);
2179    CreateClassesChangedEvent(&dce, master, dev,
2180                              DEVCHANGE_POINTER_EVENT |
2181                              DEVCHANGE_DEVICE_CHANGE);
2182    XISendDeviceChangedEvent(dev, &dce.changed_event);
2183
2184    /* if the current slave is us, update the master. If not, we'll update
2185     * whenever the next slave switch happens anyway. CMDC sends the event
2186     * for us */
2187    if (master && master->lastSlave == dev)
2188        ChangeMasterDeviceClasses(master, &dce.changed_event);
2189
2190    return TRUE;
2191}
2192
2193int
2194CheckGrabValues(ClientPtr client, GrabParameters *param)
2195{
2196    if (param->grabtype != CORE &&
2197        param->grabtype != XI && param->grabtype != XI2) {
2198        ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
2199        return BadImplementation;
2200    }
2201
2202    if ((param->this_device_mode != GrabModeSync) &&
2203        (param->this_device_mode != GrabModeAsync) &&
2204        (param->this_device_mode != XIGrabModeTouch)) {
2205        client->errorValue = param->this_device_mode;
2206        return BadValue;
2207    }
2208    if ((param->other_devices_mode != GrabModeSync) &&
2209        (param->other_devices_mode != GrabModeAsync) &&
2210        (param->other_devices_mode != XIGrabModeTouch)) {
2211        client->errorValue = param->other_devices_mode;
2212        return BadValue;
2213    }
2214
2215    if (param->modifiers != AnyModifier &&
2216        param->modifiers != XIAnyModifier &&
2217        (param->modifiers & ~AllModifiersMask)) {
2218        client->errorValue = param->modifiers;
2219        return BadValue;
2220    }
2221
2222    if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
2223        client->errorValue = param->ownerEvents;
2224        return BadValue;
2225    }
2226    return Success;
2227}
2228
2229int
2230GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
2231           int button, GrabParameters *param, enum InputLevel grabtype,
2232           GrabMask *mask)
2233{
2234    WindowPtr pWin, confineTo;
2235    CursorPtr cursor;
2236    GrabPtr grab;
2237    int rc, type = -1;
2238    Mask access_mode = DixGrabAccess;
2239
2240    rc = CheckGrabValues(client, param);
2241    if (rc != Success)
2242        return rc;
2243    if (param->confineTo == None)
2244        confineTo = NullWindow;
2245    else {
2246        rc = dixLookupWindow(&confineTo, param->confineTo, client,
2247                             DixSetAttrAccess);
2248        if (rc != Success)
2249            return rc;
2250    }
2251    if (param->cursor == None)
2252        cursor = NullCursor;
2253    else {
2254        rc = dixLookupResourceByType((void **) &cursor, param->cursor,
2255                                     RT_CURSOR, client, DixUseAccess);
2256        if (rc != Success) {
2257            client->errorValue = param->cursor;
2258            return rc;
2259        }
2260        access_mode |= DixForceAccess;
2261    }
2262    if (param->this_device_mode == GrabModeSync ||
2263        param->other_devices_mode == GrabModeSync)
2264        access_mode |= DixFreezeAccess;
2265    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
2266    if (rc != Success)
2267        return rc;
2268    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2269    if (rc != Success)
2270        return rc;
2271
2272    if (grabtype == XI)
2273        type = DeviceButtonPress;
2274    else if (grabtype == XI2)
2275        type = XI_ButtonPress;
2276
2277    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
2278                      mask, param, type, button, confineTo, cursor);
2279    if (!grab)
2280        return BadAlloc;
2281    return AddPassiveGrabToList(client, grab);
2282}
2283
2284/**
2285 * Grab the given key.
2286 */
2287int
2288GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
2289        int key, GrabParameters *param, enum InputLevel grabtype,
2290        GrabMask *mask)
2291{
2292    WindowPtr pWin;
2293    GrabPtr grab;
2294    KeyClassPtr k = dev->key;
2295    Mask access_mode = DixGrabAccess;
2296    int rc, type = -1;
2297
2298    rc = CheckGrabValues(client, param);
2299    if (rc != Success)
2300        return rc;
2301    if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL)
2302        return BadMatch;
2303    if (grabtype == XI) {
2304        if ((key > k->xkbInfo->desc->max_key_code ||
2305             key < k->xkbInfo->desc->min_key_code)
2306            && (key != AnyKey)) {
2307            client->errorValue = key;
2308            return BadValue;
2309        }
2310        type = DeviceKeyPress;
2311    }
2312    else if (grabtype == XI2)
2313        type = XI_KeyPress;
2314
2315    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2316    if (rc != Success)
2317        return rc;
2318    if (param->this_device_mode == GrabModeSync ||
2319        param->other_devices_mode == GrabModeSync)
2320        access_mode |= DixFreezeAccess;
2321    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
2322    if (rc != Success)
2323        return rc;
2324
2325    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
2326                      mask, param, type, key, NULL, NULL);
2327    if (!grab)
2328        return BadAlloc;
2329    return AddPassiveGrabToList(client, grab);
2330}
2331
2332/* Enter/FocusIn grab */
2333int
2334GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
2335           GrabParameters *param, GrabMask *mask)
2336{
2337    WindowPtr pWin;
2338    CursorPtr cursor;
2339    GrabPtr grab;
2340    Mask access_mode = DixGrabAccess;
2341    int rc;
2342
2343    rc = CheckGrabValues(client, param);
2344    if (rc != Success)
2345        return rc;
2346
2347    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2348    if (rc != Success)
2349        return rc;
2350    if (param->cursor == None)
2351        cursor = NullCursor;
2352    else {
2353        rc = dixLookupResourceByType((void **) &cursor, param->cursor,
2354                                     RT_CURSOR, client, DixUseAccess);
2355        if (rc != Success) {
2356            client->errorValue = param->cursor;
2357            return rc;
2358        }
2359        access_mode |= DixForceAccess;
2360    }
2361    if (param->this_device_mode == GrabModeSync ||
2362        param->other_devices_mode == GrabModeSync)
2363        access_mode |= DixFreezeAccess;
2364    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
2365    if (rc != Success)
2366        return rc;
2367
2368    grab = CreateGrab(client->index, dev, dev, pWin, XI2,
2369                      mask, param,
2370                      (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn, 0,
2371                      NULL, cursor);
2372
2373    if (!grab)
2374        return BadAlloc;
2375
2376    return AddPassiveGrabToList(client, grab);
2377}
2378
2379/* Touch grab */
2380int
2381GrabTouch(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
2382          GrabParameters *param, GrabMask *mask)
2383{
2384    WindowPtr pWin;
2385    GrabPtr grab;
2386    int rc;
2387
2388    rc = CheckGrabValues(client, param);
2389    if (rc != Success)
2390        return rc;
2391
2392    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2393    if (rc != Success)
2394        return rc;
2395    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGrabAccess);
2396    if (rc != Success)
2397        return rc;
2398
2399    grab = CreateGrab(client->index, dev, mod_dev, pWin, XI2,
2400                      mask, param, XI_TouchBegin, 0, NullWindow, NullCursor);
2401    if (!grab)
2402        return BadAlloc;
2403
2404    return AddPassiveGrabToList(client, grab);
2405}
2406
2407int
2408SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
2409                Mask mask, Mask exclusivemasks)
2410{
2411    int mskidx = dev->id;
2412    int i, ret;
2413    Mask check;
2414    InputClientsPtr others;
2415
2416    check = (mask & exclusivemasks);
2417    if (wOtherInputMasks(pWin)) {
2418        if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {
2419            /* It is illegal for two different clients to select on any of
2420             * the events for maskcheck. However, it is OK, for some client
2421             * to continue selecting on one of those events.
2422             */
2423            for (others = wOtherInputMasks(pWin)->inputClients; others;
2424                 others = others->next) {
2425                if (!SameClient(others, client) && (check &
2426                                                    others->mask[mskidx]))
2427                    return BadAccess;
2428            }
2429        }
2430        for (others = wOtherInputMasks(pWin)->inputClients; others;
2431             others = others->next) {
2432            if (SameClient(others, client)) {
2433                check = others->mask[mskidx];
2434                others->mask[mskidx] = mask;
2435                if (mask == 0) {
2436                    for (i = 0; i < EMASKSIZE; i++)
2437                        if (i != mskidx && others->mask[i] != 0)
2438                            break;
2439                    if (i == EMASKSIZE) {
2440                        RecalculateDeviceDeliverableEvents(pWin);
2441                        if (ShouldFreeInputMasks(pWin, FALSE))
2442                            FreeResource(others->resource, RT_NONE);
2443                        return Success;
2444                    }
2445                }
2446                goto maskSet;
2447            }
2448        }
2449    }
2450    check = 0;
2451    if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
2452        return ret;
2453 maskSet:
2454    if (dev->valuator)
2455        if ((dev->valuator->motionHintWindow == pWin) &&
2456            (mask & DevicePointerMotionHintMask) &&
2457            !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
2458            dev->valuator->motionHintWindow = NullWindow;
2459    RecalculateDeviceDeliverableEvents(pWin);
2460    return Success;
2461}
2462
2463static void
2464FreeInputClient(InputClientsPtr * other)
2465{
2466    xi2mask_free(&(*other)->xi2mask);
2467    free(*other);
2468    *other = NULL;
2469}
2470
2471static InputClientsPtr
2472AllocInputClient(void)
2473{
2474    return calloc(1, sizeof(InputClients));
2475}
2476
2477int
2478AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
2479{
2480    InputClientsPtr others;
2481
2482    if (!pWin->optional && !MakeWindowOptional(pWin))
2483        return BadAlloc;
2484    others = AllocInputClient();
2485    if (!others)
2486        return BadAlloc;
2487    if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
2488        goto bail;
2489    others->xi2mask = xi2mask_new();
2490    if (!others->xi2mask)
2491        goto bail;
2492    others->mask[mskidx] = mask;
2493    others->resource = FakeClientID(client->index);
2494    others->next = pWin->optional->inputMasks->inputClients;
2495    pWin->optional->inputMasks->inputClients = others;
2496    if (!AddResource(others->resource, RT_INPUTCLIENT, (void *) pWin))
2497        goto bail;
2498    return Success;
2499
2500 bail:
2501    FreeInputClient(&others);
2502    return BadAlloc;
2503}
2504
2505static Bool
2506MakeInputMasks(WindowPtr pWin)
2507{
2508    struct _OtherInputMasks *imasks;
2509
2510    imasks = calloc(1, sizeof(struct _OtherInputMasks));
2511    if (!imasks)
2512        return FALSE;
2513    imasks->xi2mask = xi2mask_new();
2514    if (!imasks->xi2mask) {
2515        free(imasks);
2516        return FALSE;
2517    }
2518    pWin->optional->inputMasks = imasks;
2519    return TRUE;
2520}
2521
2522static void
2523FreeInputMask(OtherInputMasks ** imask)
2524{
2525    xi2mask_free(&(*imask)->xi2mask);
2526    free(*imask);
2527    *imask = NULL;
2528}
2529
2530void
2531RecalculateDeviceDeliverableEvents(WindowPtr pWin)
2532{
2533    InputClientsPtr others;
2534    struct _OtherInputMasks *inputMasks;        /* default: NULL */
2535    WindowPtr pChild, tmp;
2536    int i;
2537
2538    pChild = pWin;
2539    while (1) {
2540        if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
2541            xi2mask_zero(inputMasks->xi2mask, -1);
2542            for (others = inputMasks->inputClients; others;
2543                 others = others->next) {
2544                for (i = 0; i < EMASKSIZE; i++)
2545                    inputMasks->inputEvents[i] |= others->mask[i];
2546                xi2mask_merge(inputMasks->xi2mask, others->xi2mask);
2547            }
2548            for (i = 0; i < EMASKSIZE; i++)
2549                inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
2550            for (tmp = pChild->parent; tmp; tmp = tmp->parent)
2551                if (wOtherInputMasks(tmp))
2552                    for (i = 0; i < EMASKSIZE; i++)
2553                        inputMasks->deliverableEvents[i] |=
2554                            (wOtherInputMasks(tmp)->deliverableEvents[i]
2555                             & ~inputMasks->dontPropagateMask[i] &
2556                             PropagateMask[i]);
2557        }
2558        if (pChild->firstChild) {
2559            pChild = pChild->firstChild;
2560            continue;
2561        }
2562        while (!pChild->nextSib && (pChild != pWin))
2563            pChild = pChild->parent;
2564        if (pChild == pWin)
2565            break;
2566        pChild = pChild->nextSib;
2567    }
2568}
2569
2570int
2571InputClientGone(WindowPtr pWin, XID id)
2572{
2573    InputClientsPtr other, prev;
2574
2575    if (!wOtherInputMasks(pWin))
2576        return Success;
2577    prev = 0;
2578    for (other = wOtherInputMasks(pWin)->inputClients; other;
2579         other = other->next) {
2580        if (other->resource == id) {
2581            if (prev) {
2582                prev->next = other->next;
2583                FreeInputClient(&other);
2584            }
2585            else if (!(other->next)) {
2586                if (ShouldFreeInputMasks(pWin, TRUE)) {
2587                    OtherInputMasks *mask = wOtherInputMasks(pWin);
2588
2589                    mask->inputClients = other->next;
2590                    FreeInputMask(&mask);
2591                    pWin->optional->inputMasks = (OtherInputMasks *) NULL;
2592                    CheckWindowOptionalNeed(pWin);
2593                    FreeInputClient(&other);
2594                }
2595                else {
2596                    other->resource = FakeClientID(0);
2597                    if (!AddResource(other->resource, RT_INPUTCLIENT,
2598                                     (void *) pWin))
2599                        return BadAlloc;
2600                }
2601            }
2602            else {
2603                wOtherInputMasks(pWin)->inputClients = other->next;
2604                FreeInputClient(&other);
2605            }
2606            RecalculateDeviceDeliverableEvents(pWin);
2607            return Success;
2608        }
2609        prev = other;
2610    }
2611    FatalError("client not on device event list");
2612}
2613
2614/**
2615 * Search for window in each touch trace for each device. Remove the window
2616 * and all its subwindows from the trace when found. The initial window
2617 * order is preserved.
2618 */
2619void
2620WindowGone(WindowPtr win)
2621{
2622    DeviceIntPtr dev;
2623
2624    for (dev = inputInfo.devices; dev; dev = dev->next) {
2625        TouchClassPtr t = dev->touch;
2626        int i;
2627
2628        if (!t)
2629            continue;
2630
2631        for (i = 0; i < t->num_touches; i++) {
2632            SpritePtr sprite = &t->touches[i].sprite;
2633            int j;
2634
2635            for (j = 0; j < sprite->spriteTraceGood; j++) {
2636                if (sprite->spriteTrace[j] == win) {
2637                    sprite->spriteTraceGood = j;
2638                    break;
2639                }
2640            }
2641        }
2642    }
2643}
2644
2645int
2646SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
2647          xEvent *ev, Mask mask, int count)
2648{
2649    WindowPtr pWin;
2650    WindowPtr effectiveFocus = NullWindow;      /* only set if dest==InputFocus */
2651    WindowPtr spriteWin = GetSpriteWindow(d);
2652
2653    if (dest == PointerWindow)
2654        pWin = spriteWin;
2655    else if (dest == InputFocus) {
2656        WindowPtr inputFocus;
2657
2658        if (!d->focus)
2659            inputFocus = spriteWin;
2660        else
2661            inputFocus = d->focus->win;
2662
2663        if (inputFocus == FollowKeyboardWin)
2664            inputFocus = inputInfo.keyboard->focus->win;
2665
2666        if (inputFocus == NoneWin)
2667            return Success;
2668
2669        /* If the input focus is PointerRootWin, send the event to where
2670         * the pointer is if possible, then perhaps propogate up to root. */
2671        if (inputFocus == PointerRootWin)
2672            inputFocus = GetCurrentRootWindow(d);
2673
2674        if (IsParent(inputFocus, spriteWin)) {
2675            effectiveFocus = inputFocus;
2676            pWin = spriteWin;
2677        }
2678        else
2679            effectiveFocus = pWin = inputFocus;
2680    }
2681    else
2682        dixLookupWindow(&pWin, dest, client, DixSendAccess);
2683    if (!pWin)
2684        return BadWindow;
2685    if ((propagate != xFalse) && (propagate != xTrue)) {
2686        client->errorValue = propagate;
2687        return BadValue;
2688    }
2689    ev->u.u.type |= 0x80;
2690    if (propagate) {
2691        for (; pWin; pWin = pWin->parent) {
2692            if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
2693                return Success;
2694            if (pWin == effectiveFocus)
2695                return Success;
2696            if (wOtherInputMasks(pWin))
2697                mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
2698            if (!mask)
2699                break;
2700        }
2701    }
2702    else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
2703        DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
2704    return Success;
2705}
2706
2707int
2708SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
2709{
2710    int i;
2711    ButtonClassPtr b = dev->button;
2712
2713    if (b == NULL)
2714        return BadMatch;
2715
2716    if (nElts != b->numButtons) {
2717        client->errorValue = nElts;
2718        return BadValue;
2719    }
2720    if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
2721        return BadValue;
2722    for (i = 0; i < nElts; i++)
2723        if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
2724            return MappingBusy;
2725    for (i = 0; i < nElts; i++)
2726        b->map[i + 1] = map[i];
2727    return Success;
2728}
2729
2730int
2731ChangeKeyMapping(ClientPtr client,
2732                 DeviceIntPtr dev,
2733                 unsigned len,
2734                 int type,
2735                 KeyCode firstKeyCode,
2736                 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
2737{
2738    KeySymsRec keysyms;
2739    KeyClassPtr k = dev->key;
2740
2741    if (k == NULL)
2742        return BadMatch;
2743
2744    if (len != (keyCodes * keySymsPerKeyCode))
2745        return BadLength;
2746
2747    if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
2748        (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
2749        client->errorValue = firstKeyCode;
2750        return BadValue;
2751    }
2752    if (keySymsPerKeyCode == 0) {
2753        client->errorValue = 0;
2754        return BadValue;
2755    }
2756    keysyms.minKeyCode = firstKeyCode;
2757    keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
2758    keysyms.mapWidth = keySymsPerKeyCode;
2759    keysyms.map = map;
2760
2761    XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
2762                          serverClient);
2763
2764    return Success;
2765}
2766
2767static void
2768DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
2769{
2770    WindowPtr parent;
2771
2772    /* Deactivate any grabs performed on this window, before making
2773     * any input focus changes.
2774     * Deactivating a device grab should cause focus events. */
2775
2776    if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
2777        (*dev->deviceGrab.DeactivateGrab) (dev);
2778
2779    /* If the focus window is a root window (ie. has no parent)
2780     * then don't delete the focus from it. */
2781
2782    if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
2783        int focusEventMode = NotifyNormal;
2784
2785        /* If a grab is in progress, then alter the mode of focus events. */
2786
2787        if (dev->deviceGrab.grab)
2788            focusEventMode = NotifyWhileGrabbed;
2789
2790        switch (dev->focus->revert) {
2791        case RevertToNone:
2792            if (!ActivateFocusInGrab(dev, pWin, NoneWin))
2793                DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
2794            dev->focus->win = NoneWin;
2795            dev->focus->traceGood = 0;
2796            break;
2797        case RevertToParent:
2798            parent = pWin;
2799            do {
2800                parent = parent->parent;
2801                dev->focus->traceGood--;
2802            }
2803            while (!parent->realized);
2804            if (!ActivateFocusInGrab(dev, pWin, parent))
2805                DoFocusEvents(dev, pWin, parent, focusEventMode);
2806            dev->focus->win = parent;
2807            dev->focus->revert = RevertToNone;
2808            break;
2809        case RevertToPointerRoot:
2810            if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
2811                DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
2812            dev->focus->win = PointerRootWin;
2813            dev->focus->traceGood = 0;
2814            break;
2815        case RevertToFollowKeyboard:
2816        {
2817            DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
2818
2819            if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
2820                kbd = inputInfo.keyboard;
2821            if (kbd->focus->win) {
2822                if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
2823                    DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
2824                dev->focus->win = FollowKeyboardWin;
2825                dev->focus->traceGood = 0;
2826            }
2827            else {
2828                if (!ActivateFocusInGrab(dev, pWin, NoneWin))
2829                    DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
2830                dev->focus->win = NoneWin;
2831                dev->focus->traceGood = 0;
2832            }
2833        }
2834            break;
2835        }
2836    }
2837
2838    if (dev->valuator)
2839        if (dev->valuator->motionHintWindow == pWin)
2840            dev->valuator->motionHintWindow = NullWindow;
2841}
2842
2843void
2844DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
2845{
2846    int i;
2847    DeviceIntPtr dev;
2848    InputClientsPtr ic;
2849    struct _OtherInputMasks *inputMasks;
2850
2851    for (dev = inputInfo.devices; dev; dev = dev->next) {
2852        DeleteDeviceFromAnyExtEvents(pWin, dev);
2853    }
2854
2855    for (dev = inputInfo.off_devices; dev; dev = dev->next)
2856        DeleteDeviceFromAnyExtEvents(pWin, dev);
2857
2858    if (freeResources)
2859        while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
2860            ic = inputMasks->inputClients;
2861            for (i = 0; i < EMASKSIZE; i++)
2862                inputMasks->dontPropagateMask[i] = 0;
2863            FreeResource(ic->resource, RT_NONE);
2864        }
2865}
2866
2867int
2868MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer *pEvents, Mask mask)
2869{
2870    DeviceIntPtr dev;
2871
2872    dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
2873                    DixReadAccess);
2874    if (!dev)
2875        return 0;
2876
2877    if (pEvents->type == DeviceMotionNotify) {
2878        if (mask & DevicePointerMotionHintMask) {
2879            if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
2880                return 1;       /* don't send, but pretend we did */
2881            }
2882            pEvents->detail = NotifyHint;
2883        }
2884        else {
2885            pEvents->detail = NotifyNormal;
2886        }
2887    }
2888    return 0;
2889}
2890
2891void
2892CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
2893                             deviceKeyButtonPointer *xE, GrabPtr grab,
2894                             ClientPtr client, Mask deliveryMask)
2895{
2896    DeviceIntPtr dev;
2897
2898    dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
2899                    DixGrabAccess);
2900    if (!dev)
2901        return;
2902
2903    if (type == DeviceMotionNotify)
2904        dev->valuator->motionHintWindow = pWin;
2905    else if ((type == DeviceButtonPress) && (!grab) &&
2906             (deliveryMask & DeviceButtonGrabMask)) {
2907        GrabPtr tempGrab;
2908
2909        tempGrab = AllocGrab(NULL);
2910        if (!tempGrab)
2911            return;
2912
2913        tempGrab->device = dev;
2914        tempGrab->resource = client->clientAsMask;
2915        tempGrab->window = pWin;
2916        tempGrab->ownerEvents =
2917            (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
2918        tempGrab->eventMask = deliveryMask;
2919        tempGrab->keyboardMode = GrabModeAsync;
2920        tempGrab->pointerMode = GrabModeAsync;
2921        tempGrab->confineTo = NullWindow;
2922        tempGrab->cursor = NullCursor;
2923        tempGrab->next = NULL;
2924        (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, currentTime, TRUE);
2925        FreeGrab(tempGrab);
2926    }
2927}
2928
2929static Mask
2930DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
2931{
2932    InputClientsPtr other;
2933
2934    if (!wOtherInputMasks(pWin))
2935        return 0;
2936    for (other = wOtherInputMasks(pWin)->inputClients; other;
2937         other = other->next) {
2938        if (SameClient(other, client))
2939            return other->mask[dev->id];
2940    }
2941    return 0;
2942}
2943
2944void
2945MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
2946{
2947    WindowPtr pWin;
2948    GrabPtr grab = dev->deviceGrab.grab;
2949
2950    pWin = dev->valuator->motionHintWindow;
2951
2952    if ((grab && SameClient(grab, client) &&
2953         ((grab->eventMask & DevicePointerMotionHintMask) ||
2954          (grab->ownerEvents &&
2955           (DeviceEventMaskForClient(dev, pWin, client) &
2956            DevicePointerMotionHintMask)))) ||
2957        (!grab &&
2958         (DeviceEventMaskForClient(dev, pWin, client) &
2959          DevicePointerMotionHintMask)))
2960        dev->valuator->motionHintWindow = NullWindow;
2961}
2962
2963int
2964DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
2965                             int maskndx)
2966{
2967    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2968
2969    if (mask & ~PropagateMask[maskndx]) {
2970        client->errorValue = mask;
2971        return BadValue;
2972    }
2973
2974    if (mask == 0) {
2975        if (inputMasks)
2976            inputMasks->dontPropagateMask[maskndx] = mask;
2977    }
2978    else {
2979        if (!inputMasks)
2980            AddExtensionClient(pWin, client, 0, 0);
2981        inputMasks = wOtherInputMasks(pWin);
2982        inputMasks->dontPropagateMask[maskndx] = mask;
2983    }
2984    RecalculateDeviceDeliverableEvents(pWin);
2985    if (ShouldFreeInputMasks(pWin, FALSE))
2986        FreeResource(inputMasks->inputClients->resource, RT_NONE);
2987    return Success;
2988}
2989
2990Bool
2991ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
2992{
2993    int i;
2994    Mask allInputEventMasks = 0;
2995    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2996
2997    for (i = 0; i < EMASKSIZE; i++)
2998        allInputEventMasks |= inputMasks->dontPropagateMask[i];
2999    if (!ignoreSelectedEvents)
3000        for (i = 0; i < EMASKSIZE; i++)
3001            allInputEventMasks |= inputMasks->inputEvents[i];
3002    if (allInputEventMasks == 0)
3003        return TRUE;
3004    else
3005        return FALSE;
3006}
3007
3008/***********************************************************************
3009 *
3010 * Walk through the window tree, finding all clients that want to know
3011 * about the Event.
3012 *
3013 */
3014
3015static void
3016FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
3017                       xEvent *ev, int count)
3018{
3019    WindowPtr p2;
3020
3021    while (p1) {
3022        p2 = p1->firstChild;
3023        DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
3024        FindInterestedChildren(dev, p2, mask, ev, count);
3025        p1 = p1->nextSib;
3026    }
3027}
3028
3029/***********************************************************************
3030 *
3031 * Send an event to interested clients in all windows on all screens.
3032 *
3033 */
3034
3035void
3036SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent *ev, int count)
3037{
3038    int i;
3039    WindowPtr pWin, p1;
3040
3041    for (i = 0; i < screenInfo.numScreens; i++) {
3042        pWin = screenInfo.screens[i]->root;
3043        if (!pWin)
3044            continue;
3045        DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
3046        p1 = pWin->firstChild;
3047        FindInterestedChildren(dev, p1, mask, ev, count);
3048    }
3049}
3050
3051/**
3052 * Set the XI2 mask for the given client on the given window.
3053 * @param dev The device to set the mask for.
3054 * @param win The window to set the mask on.
3055 * @param client The client setting the mask.
3056 * @param len Number of bytes in mask.
3057 * @param mask Event mask in the form of (1 << eventtype)
3058 */
3059int
3060XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
3061               unsigned int len, unsigned char *mask)
3062{
3063    OtherInputMasks *masks;
3064    InputClientsPtr others = NULL;
3065
3066    masks = wOtherInputMasks(win);
3067    if (masks) {
3068        for (others = wOtherInputMasks(win)->inputClients; others;
3069             others = others->next) {
3070            if (SameClient(others, client)) {
3071                xi2mask_zero(others->xi2mask, dev->id);
3072                break;
3073            }
3074        }
3075    }
3076
3077    if (len && !others) {
3078        if (AddExtensionClient(win, client, 0, 0) != Success)
3079            return BadAlloc;
3080        others = wOtherInputMasks(win)->inputClients;
3081    }
3082
3083    if (others) {
3084        xi2mask_zero(others->xi2mask, dev->id);
3085        len = min(len, xi2mask_mask_size(others->xi2mask));
3086    }
3087
3088    if (len) {
3089        xi2mask_set_one_mask(others->xi2mask, dev->id, mask, len);
3090    }
3091
3092    RecalculateDeviceDeliverableEvents(win);
3093
3094    return Success;
3095}
3096