105b261ecSmrg/************************************************************
205b261ecSmrg
305b261ecSmrgCopyright 1989, 1998  The Open Group
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthe above copyright notice appear in all copies and that both that
805b261ecSmrgcopyright notice and this permission notice appear in supporting
905b261ecSmrgdocumentation.
1005b261ecSmrg
1105b261ecSmrgThe above copyright notice and this permission notice shall be included in
1205b261ecSmrgall copies or substantial portions of the Software.
1305b261ecSmrg
1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2005b261ecSmrg
2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be
2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings
2305b261ecSmrgin this Software without prior written authorization from The Open Group.
2405b261ecSmrg
2505b261ecSmrgCopyright 1989 by Hewlett-Packard Company, Palo Alto, California.
2605b261ecSmrg
2705b261ecSmrg			All Rights Reserved
2805b261ecSmrg
2905b261ecSmrgPermission to use, copy, modify, and distribute this software and its
3005b261ecSmrgdocumentation for any purpose and without fee is hereby granted,
3105b261ecSmrgprovided that the above copyright notice appear in all copies and that
3205b261ecSmrgboth that copyright notice and this permission notice appear in
3305b261ecSmrgsupporting documentation, and that the name of Hewlett-Packard not be
3405b261ecSmrgused in advertising or publicity pertaining to distribution of the
3505b261ecSmrgsoftware without specific, written prior permission.
3605b261ecSmrg
3705b261ecSmrgHEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
3805b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
3905b261ecSmrgHEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
4005b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
4205b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4305b261ecSmrgSOFTWARE.
4405b261ecSmrg
4505b261ecSmrg********************************************************/
4605b261ecSmrg
4735c4bbdfSmrg/*
4835c4bbdfSmrg * Copyright © 2010 Collabora Ltd.
4935c4bbdfSmrg * Copyright © 2011 Red Hat, Inc.
5035c4bbdfSmrg *
5135c4bbdfSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5235c4bbdfSmrg * copy of this software and associated documentation files (the "Software"),
5335c4bbdfSmrg * to deal in the Software without restriction, including without limitation
5435c4bbdfSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
5535c4bbdfSmrg * and/or sell copies of the Software, and to permit persons to whom the
5635c4bbdfSmrg * Software is furnished to do so, subject to the following conditions:
5735c4bbdfSmrg *
5835c4bbdfSmrg * The above copyright notice and this permission notice (including the next
5935c4bbdfSmrg * paragraph) shall be included in all copies or substantial portions of the
6035c4bbdfSmrg * Software.
6135c4bbdfSmrg *
6235c4bbdfSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6335c4bbdfSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6435c4bbdfSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
6535c4bbdfSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
6635c4bbdfSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
6735c4bbdfSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
6835c4bbdfSmrg * DEALINGS IN THE SOFTWARE.
6935c4bbdfSmrg *
7035c4bbdfSmrg * Author: Daniel Stone <daniel@fooishbar.org>
7135c4bbdfSmrg */
7235c4bbdfSmrg
7305b261ecSmrg/********************************************************************
7405b261ecSmrg *
7505b261ecSmrg *  Routines to register and initialize extension input devices.
7605b261ecSmrg *  This also contains ProcessOtherEvent, the routine called from DDX
7705b261ecSmrg *  to route extension events.
7805b261ecSmrg *
7905b261ecSmrg */
8005b261ecSmrg
8105b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
8205b261ecSmrg#include <dix-config.h>
8305b261ecSmrg#endif
8405b261ecSmrg
856747b715Smrg#include "inputstr.h"
8605b261ecSmrg#include <X11/X.h>
8705b261ecSmrg#include <X11/Xproto.h>
8805b261ecSmrg#include <X11/extensions/XI.h>
8905b261ecSmrg#include <X11/extensions/XIproto.h>
906747b715Smrg#include <X11/extensions/XI2proto.h>
914642e01fSmrg#include <X11/extensions/geproto.h>
9205b261ecSmrg#include "windowstr.h"
9305b261ecSmrg#include "miscstruct.h"
9405b261ecSmrg#include "region.h"
9505b261ecSmrg#include "exevents.h"
9605b261ecSmrg#include "extnsionst.h"
9705b261ecSmrg#include "exglobals.h"
98ed6184dfSmrg#include "eventstr.h"
9935c4bbdfSmrg#include "dixevents.h"          /* DeliverFocusedEvent */
10035c4bbdfSmrg#include "dixgrabs.h"           /* CreateGrab() */
10105b261ecSmrg#include "scrnintstr.h"
10235c4bbdfSmrg#include "listdev.h"            /* for CopySwapXXXClass */
1034642e01fSmrg#include "xace.h"
10435c4bbdfSmrg#include "xiquerydevice.h"      /* For List*Info */
1056747b715Smrg#include "eventconvert.h"
1066747b715Smrg#include "eventstr.h"
10735c4bbdfSmrg#include "inpututils.h"
10835c4bbdfSmrg#include "mi.h"
10905b261ecSmrg
1104642e01fSmrg#include <X11/extensions/XKBproto.h>
11105b261ecSmrg#include "xkbsrv.h"
11205b261ecSmrg
11305b261ecSmrg#define WID(w) ((w) ? ((w)->drawable.id) : 0)
11405b261ecSmrg#define AllModifiersMask ( \
11505b261ecSmrg	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
11605b261ecSmrg	Mod3Mask | Mod4Mask | Mod5Mask )
11705b261ecSmrg#define AllButtonsMask ( \
11805b261ecSmrg	Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
11905b261ecSmrg
1204642e01fSmrgBool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
12135c4bbdfSmrg                          Bool  /* ignoreSelectedEvents */
12205b261ecSmrg    );
12335c4bbdfSmrgstatic Bool MakeInputMasks(WindowPtr    /* pWin */
12405b261ecSmrg    );
12505b261ecSmrg
1266747b715Smrg/*
1276747b715Smrg * Only let the given client know of core events which will affect its
1286747b715Smrg * interpretation of input events, if the client's ClientPointer (or the
1296747b715Smrg * paired keyboard) is the current device.
1306747b715Smrg */
1316747b715Smrgint
1326747b715SmrgXIShouldNotify(ClientPtr client, DeviceIntPtr dev)
1336747b715Smrg{
1346747b715Smrg    DeviceIntPtr current_ptr = PickPointer(client);
13535c4bbdfSmrg    DeviceIntPtr current_kbd = GetMaster(current_ptr, KEYBOARD_OR_FLOAT);
1366747b715Smrg
1376747b715Smrg    if (dev == current_kbd || dev == current_ptr)
1386747b715Smrg        return 1;
1394642e01fSmrg
1406747b715Smrg    return 0;
1416747b715Smrg}
14205b261ecSmrg
1434642e01fSmrgBool
14435c4bbdfSmrgIsPointerEvent(InternalEvent *event)
1454642e01fSmrg{
14635c4bbdfSmrg    switch (event->any.type) {
14735c4bbdfSmrg    case ET_ButtonPress:
14835c4bbdfSmrg    case ET_ButtonRelease:
14935c4bbdfSmrg    case ET_Motion:
15035c4bbdfSmrg        /* XXX: enter/leave ?? */
15135c4bbdfSmrg        return TRUE;
15235c4bbdfSmrg    default:
15335c4bbdfSmrg        break;
15435c4bbdfSmrg    }
15535c4bbdfSmrg    return FALSE;
15635c4bbdfSmrg}
15735c4bbdfSmrg
15835c4bbdfSmrgBool
15935c4bbdfSmrgIsTouchEvent(InternalEvent *event)
16035c4bbdfSmrg{
16135c4bbdfSmrg    switch (event->any.type) {
16235c4bbdfSmrg    case ET_TouchBegin:
16335c4bbdfSmrg    case ET_TouchUpdate:
16435c4bbdfSmrg    case ET_TouchEnd:
16535c4bbdfSmrg        return TRUE;
16635c4bbdfSmrg    default:
16735c4bbdfSmrg        break;
1684642e01fSmrg    }
1694642e01fSmrg    return FALSE;
1704642e01fSmrg}
1714642e01fSmrg
172ed6184dfSmrgBool
173ed6184dfSmrgIsGestureEvent(InternalEvent *event)
174ed6184dfSmrg{
175ed6184dfSmrg    switch (event->any.type) {
176ed6184dfSmrg    case ET_GesturePinchBegin:
177ed6184dfSmrg    case ET_GesturePinchUpdate:
178ed6184dfSmrg    case ET_GesturePinchEnd:
179ed6184dfSmrg    case ET_GestureSwipeBegin:
180ed6184dfSmrg    case ET_GestureSwipeUpdate:
181ed6184dfSmrg    case ET_GestureSwipeEnd:
182ed6184dfSmrg        return TRUE;
183ed6184dfSmrg    default:
184ed6184dfSmrg        break;
185ed6184dfSmrg    }
186ed6184dfSmrg    return FALSE;
187ed6184dfSmrg}
188ed6184dfSmrg
189ed6184dfSmrgBool
190ed6184dfSmrgIsGestureBeginEvent(InternalEvent *event)
191ed6184dfSmrg{
192ed6184dfSmrg    switch (event->any.type) {
193ed6184dfSmrg    case ET_GesturePinchBegin:
194ed6184dfSmrg    case ET_GestureSwipeBegin:
195ed6184dfSmrg        return TRUE;
196ed6184dfSmrg    default:
197ed6184dfSmrg        break;
198ed6184dfSmrg    }
199ed6184dfSmrg    return FALSE;
200ed6184dfSmrg}
201ed6184dfSmrg
202ed6184dfSmrgBool
203ed6184dfSmrgIsGestureEndEvent(InternalEvent *event)
204ed6184dfSmrg{
205ed6184dfSmrg    switch (event->any.type) {
206ed6184dfSmrg    case ET_GesturePinchEnd:
207ed6184dfSmrg    case ET_GestureSwipeEnd:
208ed6184dfSmrg        return TRUE;
209ed6184dfSmrg    default:
210ed6184dfSmrg        break;
211ed6184dfSmrg    }
212ed6184dfSmrg    return FALSE;
213ed6184dfSmrg}
214ed6184dfSmrg
2154642e01fSmrg/**
2164642e01fSmrg * @return the device matching the deviceid of the device set in the event, or
2174642e01fSmrg * NULL if the event is not an XInput event.
2184642e01fSmrg */
2194642e01fSmrgDeviceIntPtr
22035c4bbdfSmrgXIGetDevice(xEvent *xE)
22105b261ecSmrg{
2224642e01fSmrg    DeviceIntPtr pDev = NULL;
2234642e01fSmrg
2244642e01fSmrg    if (xE->u.u.type == DeviceButtonPress ||
2254642e01fSmrg        xE->u.u.type == DeviceButtonRelease ||
2264642e01fSmrg        xE->u.u.type == DeviceMotionNotify ||
2274642e01fSmrg        xE->u.u.type == ProximityIn ||
22835c4bbdfSmrg        xE->u.u.type == ProximityOut || xE->u.u.type == DevicePropertyNotify) {
2294642e01fSmrg        int rc;
2304642e01fSmrg        int id;
2314642e01fSmrg
23235c4bbdfSmrg        id = ((deviceKeyButtonPointer *) xE)->deviceid & ~MORE_EVENTS;
2334642e01fSmrg
2344642e01fSmrg        rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
2354642e01fSmrg        if (rc != Success)
2364642e01fSmrg            ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
2374642e01fSmrg    }
2384642e01fSmrg    return pDev;
2394642e01fSmrg}
2404642e01fSmrg
2414642e01fSmrg/**
2424642e01fSmrg * Copy the device->key into master->key and send a mapping notify to the
2434642e01fSmrg * clients if appropriate.
2444642e01fSmrg * master->key needs to be allocated by the caller.
2454642e01fSmrg *
2464642e01fSmrg * Device is the slave device. If it is attached to a master device, we may
2474642e01fSmrg * need to send a mapping notify to the client because it causes the MD
2484642e01fSmrg * to change state.
2494642e01fSmrg *
2504642e01fSmrg * Mapping notify needs to be sent in the following cases:
2514642e01fSmrg *      - different slave device on same master
2524642e01fSmrg *      - different master
2534642e01fSmrg *
2544642e01fSmrg * XXX: They way how the code is we also send a map notify if the slave device
2554642e01fSmrg * stays the same, but the master changes. This isn't really necessary though.
2564642e01fSmrg *
2574642e01fSmrg * XXX: this gives you funny behaviour with the ClientPointer. When a
2584642e01fSmrg * MappingNotify is sent to the client, the client usually responds with a
2594642e01fSmrg * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
2604642e01fSmrg * mapping, regardless of which keyboard sent the last mapping notify request.
2614642e01fSmrg * So depending on the CP setting, your keyboard may change layout in each
2624642e01fSmrg * app...
2634642e01fSmrg *
2644642e01fSmrg * This code is basically the old SwitchCoreKeyboard.
2654642e01fSmrg */
2664642e01fSmrg
2674642e01fSmrgvoid
2684642e01fSmrgCopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
2694642e01fSmrg{
2706747b715Smrg    KeyClassPtr mk = master->key;
2714642e01fSmrg
2724642e01fSmrg    if (device == master)
2734642e01fSmrg        return;
2744642e01fSmrg
2756747b715Smrg    mk->sourceid = device->id;
2764642e01fSmrg
27735c4bbdfSmrg    if (!XkbDeviceApplyKeymap(master, device->key->xkbInfo->desc))
2786747b715Smrg        FatalError("Couldn't pivot keymap from device to core!\n");
2794642e01fSmrg}
28005b261ecSmrg
2814642e01fSmrg/**
2824642e01fSmrg * Copies the feedback classes from device "from" into device "to". Classes
2834642e01fSmrg * are duplicated (not just flipping the pointers). All feedback classes are
2844642e01fSmrg * linked lists, the full list is duplicated.
2854642e01fSmrg */
2864642e01fSmrgstatic void
2874642e01fSmrgDeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
2884642e01fSmrg{
2894642e01fSmrg    ClassesPtr classes;
2904642e01fSmrg
29135c4bbdfSmrg    if (from->intfeed) {
2924642e01fSmrg        IntegerFeedbackPtr *i, it;
2934642e01fSmrg
29435c4bbdfSmrg        if (!to->intfeed) {
2956747b715Smrg            classes = to->unused_classes;
2964642e01fSmrg            to->intfeed = classes->intfeed;
2976747b715Smrg            classes->intfeed = NULL;
2984642e01fSmrg        }
2994642e01fSmrg
3004642e01fSmrg        i = &to->intfeed;
30135c4bbdfSmrg        for (it = from->intfeed; it; it = it->next) {
30235c4bbdfSmrg            if (!(*i)) {
3036747b715Smrg                *i = calloc(1, sizeof(IntegerFeedbackClassRec));
30435c4bbdfSmrg                if (!(*i)) {
3054642e01fSmrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
3064642e01fSmrg                    return;
3074642e01fSmrg                }
3084642e01fSmrg            }
3094642e01fSmrg            (*i)->CtrlProc = it->CtrlProc;
31035c4bbdfSmrg            (*i)->ctrl = it->ctrl;
3114642e01fSmrg
3124642e01fSmrg            i = &(*i)->next;
3134642e01fSmrg        }
31435c4bbdfSmrg    }
31535c4bbdfSmrg    else if (to->intfeed && !from->intfeed) {
3166747b715Smrg        classes = to->unused_classes;
3174642e01fSmrg        classes->intfeed = to->intfeed;
31835c4bbdfSmrg        to->intfeed = NULL;
3194642e01fSmrg    }
3204642e01fSmrg
32135c4bbdfSmrg    if (from->stringfeed) {
3224642e01fSmrg        StringFeedbackPtr *s, it;
3234642e01fSmrg
32435c4bbdfSmrg        if (!to->stringfeed) {
3256747b715Smrg            classes = to->unused_classes;
3264642e01fSmrg            to->stringfeed = classes->stringfeed;
3276747b715Smrg            classes->stringfeed = NULL;
3284642e01fSmrg        }
3294642e01fSmrg
3304642e01fSmrg        s = &to->stringfeed;
33135c4bbdfSmrg        for (it = from->stringfeed; it; it = it->next) {
33235c4bbdfSmrg            if (!(*s)) {
3336747b715Smrg                *s = calloc(1, sizeof(StringFeedbackClassRec));
33435c4bbdfSmrg                if (!(*s)) {
3354642e01fSmrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
3364642e01fSmrg                    return;
3374642e01fSmrg                }
3384642e01fSmrg            }
3394642e01fSmrg            (*s)->CtrlProc = it->CtrlProc;
34035c4bbdfSmrg            (*s)->ctrl = it->ctrl;
3414642e01fSmrg
3424642e01fSmrg            s = &(*s)->next;
3434642e01fSmrg        }
34435c4bbdfSmrg    }
34535c4bbdfSmrg    else if (to->stringfeed && !from->stringfeed) {
3466747b715Smrg        classes = to->unused_classes;
3474642e01fSmrg        classes->stringfeed = to->stringfeed;
34835c4bbdfSmrg        to->stringfeed = NULL;
3494642e01fSmrg    }
3504642e01fSmrg
35135c4bbdfSmrg    if (from->bell) {
3524642e01fSmrg        BellFeedbackPtr *b, it;
3534642e01fSmrg
35435c4bbdfSmrg        if (!to->bell) {
3556747b715Smrg            classes = to->unused_classes;
3564642e01fSmrg            to->bell = classes->bell;
3576747b715Smrg            classes->bell = NULL;
3584642e01fSmrg        }
3594642e01fSmrg
3604642e01fSmrg        b = &to->bell;
36135c4bbdfSmrg        for (it = from->bell; it; it = it->next) {
36235c4bbdfSmrg            if (!(*b)) {
3636747b715Smrg                *b = calloc(1, sizeof(BellFeedbackClassRec));
36435c4bbdfSmrg                if (!(*b)) {
3654642e01fSmrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
3664642e01fSmrg                    return;
3674642e01fSmrg                }
3684642e01fSmrg            }
3694642e01fSmrg            (*b)->BellProc = it->BellProc;
3704642e01fSmrg            (*b)->CtrlProc = it->CtrlProc;
37135c4bbdfSmrg            (*b)->ctrl = it->ctrl;
3724642e01fSmrg
3734642e01fSmrg            b = &(*b)->next;
3744642e01fSmrg        }
37535c4bbdfSmrg    }
37635c4bbdfSmrg    else if (to->bell && !from->bell) {
3776747b715Smrg        classes = to->unused_classes;
3784642e01fSmrg        classes->bell = to->bell;
37935c4bbdfSmrg        to->bell = NULL;
3804642e01fSmrg    }
3814642e01fSmrg
38235c4bbdfSmrg    if (from->leds) {
3834642e01fSmrg        LedFeedbackPtr *l, it;
3844642e01fSmrg
38535c4bbdfSmrg        if (!to->leds) {
3866747b715Smrg            classes = to->unused_classes;
3874642e01fSmrg            to->leds = classes->leds;
3886747b715Smrg            classes->leds = NULL;
3894642e01fSmrg        }
3904642e01fSmrg
3914642e01fSmrg        l = &to->leds;
39235c4bbdfSmrg        for (it = from->leds; it; it = it->next) {
39335c4bbdfSmrg            if (!(*l)) {
3946747b715Smrg                *l = calloc(1, sizeof(LedFeedbackClassRec));
39535c4bbdfSmrg                if (!(*l)) {
3964642e01fSmrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
3974642e01fSmrg                    return;
3984642e01fSmrg                }
3994642e01fSmrg            }
4004642e01fSmrg            (*l)->CtrlProc = it->CtrlProc;
40135c4bbdfSmrg            (*l)->ctrl = it->ctrl;
4024642e01fSmrg            if ((*l)->xkb_sli)
4034642e01fSmrg                XkbFreeSrvLedInfo((*l)->xkb_sli);
4044642e01fSmrg            (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
4054642e01fSmrg
4064642e01fSmrg            l = &(*l)->next;
4074642e01fSmrg        }
40835c4bbdfSmrg    }
40935c4bbdfSmrg    else if (to->leds && !from->leds) {
4106747b715Smrg        classes = to->unused_classes;
4114642e01fSmrg        classes->leds = to->leds;
41235c4bbdfSmrg        to->leds = NULL;
4134642e01fSmrg    }
4144642e01fSmrg}
4154642e01fSmrg
4166747b715Smrgstatic void
4176747b715SmrgDeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
4184642e01fSmrg{
4194642e01fSmrg    ClassesPtr classes;
4204642e01fSmrg
4214642e01fSmrg    /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
4224642e01fSmrg     * kbdfeed to be set up properly, so let's do the feedback classes first.
4234642e01fSmrg     */
42435c4bbdfSmrg    if (from->kbdfeed) {
4256747b715Smrg        KbdFeedbackPtr *k, it;
4266747b715Smrg
42735c4bbdfSmrg        if (!to->kbdfeed) {
4286747b715Smrg            classes = to->unused_classes;
4296747b715Smrg
4306747b715Smrg            to->kbdfeed = classes->kbdfeed;
4316747b715Smrg            if (!to->kbdfeed)
4326747b715Smrg                InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
4336747b715Smrg            classes->kbdfeed = NULL;
4346747b715Smrg        }
4356747b715Smrg
4366747b715Smrg        k = &to->kbdfeed;
43735c4bbdfSmrg        for (it = from->kbdfeed; it; it = it->next) {
43835c4bbdfSmrg            if (!(*k)) {
4396747b715Smrg                *k = calloc(1, sizeof(KbdFeedbackClassRec));
44035c4bbdfSmrg                if (!*k) {
4416747b715Smrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
4426747b715Smrg                    return;
4436747b715Smrg                }
4446747b715Smrg            }
4456747b715Smrg            (*k)->BellProc = it->BellProc;
4466747b715Smrg            (*k)->CtrlProc = it->CtrlProc;
44735c4bbdfSmrg            (*k)->ctrl = it->ctrl;
4486747b715Smrg            if ((*k)->xkb_sli)
4496747b715Smrg                XkbFreeSrvLedInfo((*k)->xkb_sli);
4506747b715Smrg            (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
4516747b715Smrg
4526747b715Smrg            k = &(*k)->next;
4536747b715Smrg        }
45435c4bbdfSmrg    }
45535c4bbdfSmrg    else if (to->kbdfeed && !from->kbdfeed) {
4566747b715Smrg        classes = to->unused_classes;
4576747b715Smrg        classes->kbdfeed = to->kbdfeed;
45835c4bbdfSmrg        to->kbdfeed = NULL;
4596747b715Smrg    }
4604642e01fSmrg
46135c4bbdfSmrg    if (from->key) {
46235c4bbdfSmrg        if (!to->key) {
4636747b715Smrg            classes = to->unused_classes;
4644642e01fSmrg            to->key = classes->key;
4654642e01fSmrg            if (!to->key)
4666747b715Smrg                InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
4676747b715Smrg            else
4686747b715Smrg                classes->key = NULL;
4696747b715Smrg        }
4706747b715Smrg
4716747b715Smrg        CopyKeyClass(from, to);
47235c4bbdfSmrg    }
47335c4bbdfSmrg    else if (to->key && !from->key) {
4746747b715Smrg        classes = to->unused_classes;
4756747b715Smrg        classes->key = to->key;
47635c4bbdfSmrg        to->key = NULL;
4776747b715Smrg    }
4786747b715Smrg
4796747b715Smrg    /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps
4806747b715Smrg     * pointer point into the xkbInfo->desc struct.  XkbCopySrvLedInfo
4816747b715Smrg     * didn't update the pointers so we need to do it manually here.
4826747b715Smrg     */
48335c4bbdfSmrg    if (to->kbdfeed) {
4846747b715Smrg        KbdFeedbackPtr k;
4856747b715Smrg
48635c4bbdfSmrg        for (k = to->kbdfeed; k; k = k->next) {
4876747b715Smrg            if (!k->xkb_sli)
4886747b715Smrg                continue;
48935c4bbdfSmrg            if (k->xkb_sli->flags & XkbSLI_IsDefault) {
4906747b715Smrg                k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators;
4916747b715Smrg                k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps;
4926747b715Smrg            }
4936747b715Smrg        }
4946747b715Smrg    }
4956747b715Smrg
4966747b715Smrg    /* We can't just copy over the focus class. When an app sets the focus,
4976747b715Smrg     * it'll do so on the master device. Copying the SDs focus means losing
4986747b715Smrg     * the focus.
4996747b715Smrg     * So we only copy the focus class if the device didn't have one,
5006747b715Smrg     * otherwise we leave it as it is.
5016747b715Smrg     */
50235c4bbdfSmrg    if (from->focus) {
50335c4bbdfSmrg        if (!to->focus) {
5046747b715Smrg            WindowPtr *oldTrace;
5056747b715Smrg
5066747b715Smrg            classes = to->unused_classes;
5076747b715Smrg            to->focus = classes->focus;
50835c4bbdfSmrg            if (!to->focus) {
5096747b715Smrg                to->focus = calloc(1, sizeof(FocusClassRec));
5106747b715Smrg                if (!to->focus)
5114642e01fSmrg                    FatalError("[Xi] no memory for class shift.\n");
51235c4bbdfSmrg            }
51335c4bbdfSmrg            else
5146747b715Smrg                classes->focus = NULL;
5156747b715Smrg
5166747b715Smrg            oldTrace = to->focus->trace;
5176747b715Smrg            memcpy(to->focus, from->focus, sizeof(FocusClassRec));
51835c4bbdfSmrg            to->focus->trace = reallocarray(oldTrace,
51935c4bbdfSmrg                                            to->focus->traceSize,
52035c4bbdfSmrg                                            sizeof(WindowPtr));
5216747b715Smrg            if (!to->focus->trace && to->focus->traceSize)
5226747b715Smrg                FatalError("[Xi] no memory for trace.\n");
5236747b715Smrg            memcpy(to->focus->trace, from->focus->trace,
52435c4bbdfSmrg                   from->focus->traceSize * sizeof(WindowPtr));
5256747b715Smrg            to->focus->sourceid = from->id;
5264642e01fSmrg        }
52735c4bbdfSmrg    }
52835c4bbdfSmrg    else if (to->focus) {
5296747b715Smrg        classes = to->unused_classes;
5306747b715Smrg        classes->focus = to->focus;
53135c4bbdfSmrg        to->focus = NULL;
5326747b715Smrg    }
5334642e01fSmrg
5346747b715Smrg}
5354642e01fSmrg
53635c4bbdfSmrg/* FIXME: this should really be shared with the InitValuatorAxisClassRec and
53735c4bbdfSmrg * similar */
5386747b715Smrgstatic void
5396747b715SmrgDeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
5406747b715Smrg{
5416747b715Smrg    ClassesPtr classes;
5426747b715Smrg
5436747b715Smrg    /* Feedback classes must be copied first */
54435c4bbdfSmrg    if (from->ptrfeed) {
5456747b715Smrg        PtrFeedbackPtr *p, it;
54635c4bbdfSmrg
54735c4bbdfSmrg        if (!to->ptrfeed) {
5486747b715Smrg            classes = to->unused_classes;
5496747b715Smrg            to->ptrfeed = classes->ptrfeed;
5506747b715Smrg            classes->ptrfeed = NULL;
5514642e01fSmrg        }
5524642e01fSmrg
5536747b715Smrg        p = &to->ptrfeed;
55435c4bbdfSmrg        for (it = from->ptrfeed; it; it = it->next) {
55535c4bbdfSmrg            if (!(*p)) {
5566747b715Smrg                *p = calloc(1, sizeof(PtrFeedbackClassRec));
55735c4bbdfSmrg                if (!*p) {
5586747b715Smrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
5596747b715Smrg                    return;
5606747b715Smrg                }
5616747b715Smrg            }
5626747b715Smrg            (*p)->CtrlProc = it->CtrlProc;
56335c4bbdfSmrg            (*p)->ctrl = it->ctrl;
5644642e01fSmrg
5656747b715Smrg            p = &(*p)->next;
5666747b715Smrg        }
56735c4bbdfSmrg    }
56835c4bbdfSmrg    else if (to->ptrfeed && !from->ptrfeed) {
5696747b715Smrg        classes = to->unused_classes;
5706747b715Smrg        classes->ptrfeed = to->ptrfeed;
57135c4bbdfSmrg        to->ptrfeed = NULL;
5724642e01fSmrg    }
5734642e01fSmrg
57435c4bbdfSmrg    if (from->valuator) {
5754642e01fSmrg        ValuatorClassPtr v;
5769ace9065Smrg
57735c4bbdfSmrg        if (!to->valuator) {
5786747b715Smrg            classes = to->unused_classes;
5794642e01fSmrg            to->valuator = classes->valuator;
5804642e01fSmrg            if (to->valuator)
5814642e01fSmrg                classes->valuator = NULL;
5824642e01fSmrg        }
5834642e01fSmrg
5849ace9065Smrg        v = AllocValuatorClass(to->valuator, from->valuator->numAxes);
5859ace9065Smrg
5864642e01fSmrg        if (!v)
5874642e01fSmrg            FatalError("[Xi] no memory for class shift.\n");
5884642e01fSmrg
5899ace9065Smrg        to->valuator = v;
5904642e01fSmrg        memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
5914642e01fSmrg
5926747b715Smrg        v->sourceid = from->id;
59335c4bbdfSmrg    }
59435c4bbdfSmrg    else if (to->valuator && !from->valuator) {
5956747b715Smrg        classes = to->unused_classes;
5964642e01fSmrg        classes->valuator = to->valuator;
59735c4bbdfSmrg        to->valuator = NULL;
5984642e01fSmrg    }
5994642e01fSmrg
60035c4bbdfSmrg    if (from->button) {
60135c4bbdfSmrg        if (!to->button) {
6026747b715Smrg            classes = to->unused_classes;
6034642e01fSmrg            to->button = classes->button;
60435c4bbdfSmrg            if (!to->button) {
6056747b715Smrg                to->button = calloc(1, sizeof(ButtonClassRec));
6064642e01fSmrg                if (!to->button)
6074642e01fSmrg                    FatalError("[Xi] no memory for class shift.\n");
608d9252ffbSmrg                to->button->numButtons = from->button->numButtons;
60935c4bbdfSmrg            }
61035c4bbdfSmrg            else
6114642e01fSmrg                classes->button = NULL;
6124642e01fSmrg        }
6134642e01fSmrg
61435c4bbdfSmrg        if (from->button->xkb_acts) {
615d9252ffbSmrg            size_t maxbuttons = max(to->button->numButtons, from->button->numButtons);
616d9252ffbSmrg            to->button->xkb_acts = xnfreallocarray(to->button->xkb_acts,
617d9252ffbSmrg                                                   maxbuttons,
618d9252ffbSmrg                                                   sizeof(XkbAction));
619d9252ffbSmrg            memset(to->button->xkb_acts, 0, maxbuttons * sizeof(XkbAction));
6204642e01fSmrg            memcpy(to->button->xkb_acts, from->button->xkb_acts,
621d9252ffbSmrg                   from->button->numButtons * sizeof(XkbAction));
62235c4bbdfSmrg        }
623a1e1cf94Smrg        else {
6246747b715Smrg            free(to->button->xkb_acts);
625a1e1cf94Smrg            to->button->xkb_acts = NULL;
626a1e1cf94Smrg        }
6276747b715Smrg
62835c4bbdfSmrg        memcpy(to->button->labels, from->button->labels,
62935c4bbdfSmrg               from->button->numButtons * sizeof(Atom));
6306747b715Smrg        to->button->sourceid = from->id;
63135c4bbdfSmrg    }
63235c4bbdfSmrg    else if (to->button && !from->button) {
6336747b715Smrg        classes = to->unused_classes;
6344642e01fSmrg        classes->button = to->button;
63535c4bbdfSmrg        to->button = NULL;
6364642e01fSmrg    }
6374642e01fSmrg
63835c4bbdfSmrg    if (from->proximity) {
63935c4bbdfSmrg        if (!to->proximity) {
6406747b715Smrg            classes = to->unused_classes;
6414642e01fSmrg            to->proximity = classes->proximity;
64235c4bbdfSmrg            if (!to->proximity) {
6436747b715Smrg                to->proximity = calloc(1, sizeof(ProximityClassRec));
6444642e01fSmrg                if (!to->proximity)
6454642e01fSmrg                    FatalError("[Xi] no memory for class shift.\n");
64635c4bbdfSmrg            }
64735c4bbdfSmrg            else
6484642e01fSmrg                classes->proximity = NULL;
6494642e01fSmrg        }
6504642e01fSmrg        memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
6516747b715Smrg        to->proximity->sourceid = from->id;
65235c4bbdfSmrg    }
65335c4bbdfSmrg    else if (to->proximity) {
6546747b715Smrg        classes = to->unused_classes;
6554642e01fSmrg        classes->proximity = to->proximity;
65635c4bbdfSmrg        to->proximity = NULL;
6574642e01fSmrg    }
6584642e01fSmrg
65935c4bbdfSmrg    if (from->touch) {
66035c4bbdfSmrg        TouchClassPtr t, f;
66135c4bbdfSmrg
66235c4bbdfSmrg        if (!to->touch) {
6636747b715Smrg            classes = to->unused_classes;
66435c4bbdfSmrg            to->touch = classes->touch;
66535c4bbdfSmrg            if (!to->touch) {
66635c4bbdfSmrg                int i;
66735c4bbdfSmrg
66835c4bbdfSmrg                to->touch = calloc(1, sizeof(TouchClassRec));
66935c4bbdfSmrg                if (!to->touch)
67035c4bbdfSmrg                    FatalError("[Xi] no memory for class shift.\n");
67135c4bbdfSmrg                to->touch->num_touches = from->touch->num_touches;
67235c4bbdfSmrg                to->touch->touches = calloc(to->touch->num_touches,
67335c4bbdfSmrg                                            sizeof(TouchPointInfoRec));
67435c4bbdfSmrg                for (i = 0; i < to->touch->num_touches; i++)
67535c4bbdfSmrg                    TouchInitTouchPoint(to->touch, to->valuator, i);
67635c4bbdfSmrg                if (!to->touch)
6774642e01fSmrg                    FatalError("[Xi] no memory for class shift.\n");
67835c4bbdfSmrg            }
67935c4bbdfSmrg            else
68035c4bbdfSmrg                classes->touch = NULL;
6814642e01fSmrg        }
68235c4bbdfSmrg
68335c4bbdfSmrg        t = to->touch;
68435c4bbdfSmrg        f = from->touch;
68535c4bbdfSmrg        t->sourceid = f->sourceid;
68635c4bbdfSmrg        t->max_touches = f->max_touches;
68735c4bbdfSmrg        t->mode = f->mode;
68835c4bbdfSmrg        t->buttonsDown = f->buttonsDown;
68935c4bbdfSmrg        t->state = f->state;
69035c4bbdfSmrg        t->motionMask = f->motionMask;
69135c4bbdfSmrg        /* to->touches and to->num_touches are separate on the master,
69235c4bbdfSmrg         * don't copy */
6936747b715Smrg    }
69435c4bbdfSmrg    /* Don't remove touch class if from->touch is non-existent. The to device
69535c4bbdfSmrg     * may have an active touch grab, so we need to keep the touch class record
69635c4bbdfSmrg     * around. */
697ed6184dfSmrg
698ed6184dfSmrg    if (from->gesture) {
699ed6184dfSmrg        if (!to->gesture) {
700ed6184dfSmrg            classes = to->unused_classes;
701ed6184dfSmrg            to->gesture = classes->gesture;
702ed6184dfSmrg            if (!to->gesture) {
703ed6184dfSmrg                if (!InitGestureClassDeviceStruct(to, from->gesture->max_touches))
704ed6184dfSmrg                    FatalError("[Xi] no memory for class shift.\n");
705ed6184dfSmrg            }
706ed6184dfSmrg            else
707ed6184dfSmrg                classes->gesture = NULL;
708ed6184dfSmrg        }
709ed6184dfSmrg
710ed6184dfSmrg        to->gesture->sourceid = from->gesture->sourceid;
711ed6184dfSmrg        /* to->gesture->gesture is separate on the master,  don't copy */
712ed6184dfSmrg    }
713ed6184dfSmrg    /* Don't remove gesture class if from->gesture is non-existent. The to device
714ed6184dfSmrg     * may have an active gesture grab, so we need to keep the gesture class record
715ed6184dfSmrg     * around. */
7166747b715Smrg}
7176747b715Smrg
7186747b715Smrg/**
7196747b715Smrg * Copies the CONTENT of the classes of device from into the classes in device
7206747b715Smrg * to. From and to are identical after finishing.
7216747b715Smrg *
722ed6184dfSmrg * If to does not have classes from currently has, the classes are stored in
7236747b715Smrg * to's devPrivates system. Later, we recover it again from there if needed.
7246747b715Smrg * Saves a few memory allocations.
7256747b715Smrg */
7266747b715Smrgvoid
72735c4bbdfSmrgDeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to,
72835c4bbdfSmrg                      DeviceChangedEvent *dce)
7296747b715Smrg{
7301b5d61b8Smrg    input_lock();
73135c4bbdfSmrg
7326747b715Smrg    /* generic feedback classes, not tied to pointer and/or keyboard */
7336747b715Smrg    DeepCopyFeedbackClasses(from, to);
7346747b715Smrg
7356747b715Smrg    if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
7366747b715Smrg        DeepCopyKeyboardClasses(from, to);
7376747b715Smrg    if ((dce->flags & DEVCHANGE_POINTER_EVENT))
7386747b715Smrg        DeepCopyPointerClasses(from, to);
7396747b715Smrg
7401b5d61b8Smrg    input_unlock();
74135c4bbdfSmrg}
7426747b715Smrg
7436747b715Smrg/**
7446747b715Smrg * Send an XI2 DeviceChangedEvent to all interested clients.
7456747b715Smrg */
7466747b715Smrgvoid
74735c4bbdfSmrgXISendDeviceChangedEvent(DeviceIntPtr device, DeviceChangedEvent *dce)
7486747b715Smrg{
7496747b715Smrg    xXIDeviceChangedEvent *dcce;
7506747b715Smrg    int rc;
7516747b715Smrg
75235c4bbdfSmrg    rc = EventToXI2((InternalEvent *) dce, (xEvent **) &dcce);
75335c4bbdfSmrg    if (rc != Success) {
7546747b715Smrg        ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc);
7556747b715Smrg        return;
7564642e01fSmrg    }
7576747b715Smrg
7586747b715Smrg    /* we don't actually swap if there's a NullClient, swapping is done
7596747b715Smrg     * later when event is delivered. */
76035c4bbdfSmrg    SendEventToAllWindows(device, XI_DeviceChangedMask, (xEvent *) dcce, 1);
7616747b715Smrg    free(dcce);
7624642e01fSmrg}
7634642e01fSmrg
7646747b715Smrgstatic void
7656747b715SmrgChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
7666747b715Smrg{
7676747b715Smrg    DeviceIntPtr slave;
7686747b715Smrg    int rc;
7696747b715Smrg
7706747b715Smrg    /* For now, we don't have devices that change physically. */
7716747b715Smrg    if (!IsMaster(device))
7726747b715Smrg        return;
7736747b715Smrg
7746747b715Smrg    rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
7756747b715Smrg
7766747b715Smrg    if (rc != Success)
77735c4bbdfSmrg        return;                 /* Device has disappeared */
7786747b715Smrg
77935c4bbdfSmrg    if (IsMaster(slave))
78035c4bbdfSmrg        return;
78135c4bbdfSmrg
78235c4bbdfSmrg    if (IsFloating(slave))
78335c4bbdfSmrg        return;                 /* set floating since the event */
7846747b715Smrg
78535c4bbdfSmrg    if (GetMaster(slave, MASTER_ATTACHED)->id != dce->masterid)
78635c4bbdfSmrg        return;                 /* not our slave anymore, don't care */
7876747b715Smrg
7886747b715Smrg    /* FIXME: we probably need to send a DCE for the new slave now */
7896747b715Smrg
7906747b715Smrg    device->public.devicePrivate = slave->public.devicePrivate;
7916747b715Smrg
7926747b715Smrg    /* FIXME: the classes may have changed since we generated the event. */
7936747b715Smrg    DeepCopyDeviceClasses(slave, device, dce);
79435c4bbdfSmrg    dce->deviceid = device->id;
79535c4bbdfSmrg    XISendDeviceChangedEvent(device, dce);
79635c4bbdfSmrg}
79735c4bbdfSmrg
79835c4bbdfSmrg/**
79935c4bbdfSmrg * Add state and motionMask to the filter for this event. The protocol
80035c4bbdfSmrg * supports some extra masks for motion when a button is down:
80135c4bbdfSmrg * ButtonXMotionMask and the DeviceButtonMotionMask to trigger only when at
80235c4bbdfSmrg * least one button (or that specific button is down). These masks need to
80335c4bbdfSmrg * be added to the filters for core/XI motion events.
80435c4bbdfSmrg *
80535c4bbdfSmrg * @param device The device to update the mask for
80635c4bbdfSmrg * @param state The current button state mask
80735c4bbdfSmrg * @param motion_mask The motion mask (DeviceButtonMotionMask or 0)
80835c4bbdfSmrg */
80935c4bbdfSmrgstatic void
81035c4bbdfSmrgUpdateDeviceMotionMask(DeviceIntPtr device, unsigned short state,
81135c4bbdfSmrg                       Mask motion_mask)
81235c4bbdfSmrg{
81335c4bbdfSmrg    Mask mask;
81435c4bbdfSmrg
81535c4bbdfSmrg    mask = PointerMotionMask | state | motion_mask;
816ed6184dfSmrg    SetMaskForEvent(device->id, mask, DeviceMotionNotify);
81735c4bbdfSmrg    SetMaskForEvent(device->id, mask, MotionNotify);
81835c4bbdfSmrg}
81935c4bbdfSmrg
82035c4bbdfSmrgstatic void
82135c4bbdfSmrgIncreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down,
82235c4bbdfSmrg                    Mask *motion_mask, unsigned short *state)
82335c4bbdfSmrg{
82435c4bbdfSmrg    if (dev->valuator)
82535c4bbdfSmrg        dev->valuator->motionHintWindow = NullWindow;
82635c4bbdfSmrg
82735c4bbdfSmrg    (*buttons_down)++;
82835c4bbdfSmrg    *motion_mask = DeviceButtonMotionMask;
82935c4bbdfSmrg    if (dev->button->map[key] <= 5)
83035c4bbdfSmrg        *state |= (Button1Mask >> 1) << dev->button->map[key];
83135c4bbdfSmrg}
83235c4bbdfSmrg
83335c4bbdfSmrgstatic void
83435c4bbdfSmrgDecreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down,
83535c4bbdfSmrg                    Mask *motion_mask, unsigned short *state)
83635c4bbdfSmrg{
83735c4bbdfSmrg    if (dev->valuator)
83835c4bbdfSmrg        dev->valuator->motionHintWindow = NullWindow;
83935c4bbdfSmrg
84035c4bbdfSmrg    if (*buttons_down >= 1 && !--(*buttons_down))
84135c4bbdfSmrg        *motion_mask = 0;
84235c4bbdfSmrg    if (dev->button->map[key] <= 5)
84335c4bbdfSmrg        *state &= ~((Button1Mask >> 1) << dev->button->map[key]);
8446747b715Smrg}
8454642e01fSmrg
8464642e01fSmrg/**
8474642e01fSmrg * Update the device state according to the data in the event.
8484642e01fSmrg *
8494642e01fSmrg * return values are
8504642e01fSmrg *   DEFAULT ... process as normal
8514642e01fSmrg *   DONT_PROCESS ... return immediately from caller
8524642e01fSmrg */
8534642e01fSmrg#define DEFAULT 0
8544642e01fSmrg#define DONT_PROCESS 1
8554642e01fSmrgint
85635c4bbdfSmrgUpdateDeviceState(DeviceIntPtr device, DeviceEvent *event)
8574642e01fSmrg{
8584642e01fSmrg    int i;
85935c4bbdfSmrg    int key = 0, last_valuator;
8604642e01fSmrg
86135c4bbdfSmrg    KeyClassPtr k = NULL;
86235c4bbdfSmrg    ButtonClassPtr b = NULL;
86335c4bbdfSmrg    ValuatorClassPtr v = NULL;
86435c4bbdfSmrg    TouchClassPtr t = NULL;
8654642e01fSmrg
8666747b715Smrg    /* This event is always the first we get, before the actual events with
8676747b715Smrg     * the data. However, the way how the DDX is set up, "device" will
8686747b715Smrg     * actually be the slave device that caused the event.
8696747b715Smrg     */
87035c4bbdfSmrg    switch (event->type) {
87135c4bbdfSmrg    case ET_DeviceChanged:
87235c4bbdfSmrg        ChangeMasterDeviceClasses(device, (DeviceChangedEvent *) event);
87335c4bbdfSmrg        return DONT_PROCESS;    /* event has been sent already */
87435c4bbdfSmrg    case ET_Motion:
87535c4bbdfSmrg    case ET_ButtonPress:
87635c4bbdfSmrg    case ET_ButtonRelease:
87735c4bbdfSmrg    case ET_KeyPress:
87835c4bbdfSmrg    case ET_KeyRelease:
87935c4bbdfSmrg    case ET_ProximityIn:
88035c4bbdfSmrg    case ET_ProximityOut:
88135c4bbdfSmrg    case ET_TouchBegin:
88235c4bbdfSmrg    case ET_TouchUpdate:
88335c4bbdfSmrg    case ET_TouchEnd:
88435c4bbdfSmrg        break;
88535c4bbdfSmrg    default:
88635c4bbdfSmrg        /* other events don't update the device */
88735c4bbdfSmrg        return DEFAULT;
8886747b715Smrg    }
8894642e01fSmrg
8904642e01fSmrg    k = device->key;
8914642e01fSmrg    v = device->valuator;
8924642e01fSmrg    b = device->button;
89335c4bbdfSmrg    t = device->touch;
8944642e01fSmrg
8956747b715Smrg    key = event->detail.key;
8964642e01fSmrg
8976747b715Smrg    /* Update device axis */
8986747b715Smrg    /* Check valuators first */
8996747b715Smrg    last_valuator = -1;
90035c4bbdfSmrg    for (i = 0; i < MAX_VALUATORS; i++) {
90135c4bbdfSmrg        if (BitIsOn(&event->valuators.mask, i)) {
90235c4bbdfSmrg            if (!v) {
9036747b715Smrg                ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
90435c4bbdfSmrg                       "Ignoring event.\n", device->name);
9056747b715Smrg                return DONT_PROCESS;
90635c4bbdfSmrg            }
90735c4bbdfSmrg            else if (v->numAxes < i) {
9086747b715Smrg                ErrorF("[Xi] Too many valuators reported for device '%s'. "
90935c4bbdfSmrg                       "Ignoring event.\n", device->name);
9106747b715Smrg                return DONT_PROCESS;
9116747b715Smrg            }
9126747b715Smrg            last_valuator = i;
9136747b715Smrg        }
9144642e01fSmrg    }
9154642e01fSmrg
91635c4bbdfSmrg    for (i = 0; i <= last_valuator && i < v->numAxes; i++) {
91735c4bbdfSmrg        /* XXX: Relative/Absolute mode */
9186747b715Smrg        if (BitIsOn(&event->valuators.mask, i))
9196747b715Smrg            v->axisVal[i] = event->valuators.data[i];
9204642e01fSmrg    }
92105b261ecSmrg
9226747b715Smrg    if (event->type == ET_KeyPress) {
92305b261ecSmrg        if (!k)
9244642e01fSmrg            return DONT_PROCESS;
92505b261ecSmrg
92635c4bbdfSmrg        /* don't allow ddx to generate multiple downs, but repeats are okay */
92735c4bbdfSmrg        if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
92835c4bbdfSmrg            return DONT_PROCESS;
9296747b715Smrg
93035c4bbdfSmrg        if (device->valuator)
93135c4bbdfSmrg            device->valuator->motionHintWindow = NullWindow;
93235c4bbdfSmrg        set_key_down(device, key, KEY_PROCESSED);
93335c4bbdfSmrg    }
93435c4bbdfSmrg    else if (event->type == ET_KeyRelease) {
93505b261ecSmrg        if (!k)
9364642e01fSmrg            return DONT_PROCESS;
93705b261ecSmrg
93835c4bbdfSmrg        if (!key_is_down(device, key, KEY_PROCESSED))   /* guard against duplicates */
93935c4bbdfSmrg            return DONT_PROCESS;
94035c4bbdfSmrg        if (device->valuator)
94135c4bbdfSmrg            device->valuator->motionHintWindow = NullWindow;
94235c4bbdfSmrg        set_key_up(device, key, KEY_PROCESSED);
94335c4bbdfSmrg    }
94435c4bbdfSmrg    else if (event->type == ET_ButtonPress) {
94505b261ecSmrg        if (!b)
9464642e01fSmrg            return DONT_PROCESS;
9474642e01fSmrg
9486747b715Smrg        if (button_is_down(device, key, BUTTON_PROCESSED))
9494642e01fSmrg            return DONT_PROCESS;
9506747b715Smrg
9516747b715Smrg        set_button_down(device, key, BUTTON_PROCESSED);
95235c4bbdfSmrg
9534642e01fSmrg        if (!b->map[key])
9544642e01fSmrg            return DONT_PROCESS;
95535c4bbdfSmrg
95635c4bbdfSmrg        IncreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask,
95735c4bbdfSmrg                            &b->state);
95835c4bbdfSmrg        UpdateDeviceMotionMask(device, b->state, b->motionMask);
95935c4bbdfSmrg    }
96035c4bbdfSmrg    else if (event->type == ET_ButtonRelease) {
96105b261ecSmrg        if (!b)
9624642e01fSmrg            return DONT_PROCESS;
9634642e01fSmrg
9646747b715Smrg        if (!button_is_down(device, key, BUTTON_PROCESSED))
9654642e01fSmrg            return DONT_PROCESS;
9666747b715Smrg        if (IsMaster(device)) {
9674642e01fSmrg            DeviceIntPtr sd;
9684642e01fSmrg
9694642e01fSmrg            /*
9704642e01fSmrg             * Leave the button down if any slave has the
9714642e01fSmrg             * button still down. Note that this depends on the
9724642e01fSmrg             * event being delivered through the slave first
9734642e01fSmrg             */
9744642e01fSmrg            for (sd = inputInfo.devices; sd; sd = sd->next) {
97535c4bbdfSmrg                if (IsMaster(sd) || GetMaster(sd, MASTER_POINTER) != device)
9764642e01fSmrg                    continue;
9776747b715Smrg                if (!sd->button)
9786747b715Smrg                    continue;
9798223e2f2Smrg                for (i = 1; i <= sd->button->numButtons; i++)
9808223e2f2Smrg                    if (sd->button->map[i] == key &&
9818223e2f2Smrg                        button_is_down(sd, i, BUTTON_PROCESSED))
9828223e2f2Smrg                        return DONT_PROCESS;
9834642e01fSmrg            }
9844642e01fSmrg        }
9856747b715Smrg        set_button_up(device, key, BUTTON_PROCESSED);
9864642e01fSmrg        if (!b->map[key])
9874642e01fSmrg            return DONT_PROCESS;
98835c4bbdfSmrg
98935c4bbdfSmrg        DecreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask,
99035c4bbdfSmrg                            &b->state);
99135c4bbdfSmrg        UpdateDeviceMotionMask(device, b->state, b->motionMask);
99235c4bbdfSmrg    }
99335c4bbdfSmrg    else if (event->type == ET_ProximityIn)
99435c4bbdfSmrg        device->proximity->in_proximity = TRUE;
9956747b715Smrg    else if (event->type == ET_ProximityOut)
99635c4bbdfSmrg        device->proximity->in_proximity = FALSE;
99735c4bbdfSmrg    else if (event->type == ET_TouchBegin) {
99835c4bbdfSmrg        BUG_RETURN_VAL(!b || !v, DONT_PROCESS);
99935c4bbdfSmrg        BUG_RETURN_VAL(!t, DONT_PROCESS);
10004642e01fSmrg
100135c4bbdfSmrg        if (!b->map[key])
100235c4bbdfSmrg            return DONT_PROCESS;
10034642e01fSmrg
100435c4bbdfSmrg        if (!(event->flags & TOUCH_POINTER_EMULATED) ||
100535c4bbdfSmrg            (event->flags & TOUCH_REPLAYING))
100635c4bbdfSmrg            return DONT_PROCESS;
10076747b715Smrg
100835c4bbdfSmrg        IncreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask,
100935c4bbdfSmrg                            &t->state);
101035c4bbdfSmrg        UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask);
101135c4bbdfSmrg    }
101235c4bbdfSmrg    else if (event->type == ET_TouchEnd) {
101335c4bbdfSmrg        BUG_RETURN_VAL(!b || !v, DONT_PROCESS);
101435c4bbdfSmrg        BUG_RETURN_VAL(!t, DONT_PROCESS);
10156747b715Smrg
101635c4bbdfSmrg        if (t->buttonsDown <= 0 || !b->map[key])
101735c4bbdfSmrg            return DONT_PROCESS;
101835c4bbdfSmrg
101935c4bbdfSmrg        if (!(event->flags & TOUCH_POINTER_EMULATED))
102035c4bbdfSmrg            return DONT_PROCESS;
10216747b715Smrg
102235c4bbdfSmrg        DecreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask,
102335c4bbdfSmrg                            &t->state);
102435c4bbdfSmrg        UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask);
10256747b715Smrg    }
102635c4bbdfSmrg
102735c4bbdfSmrg    return DEFAULT;
10286747b715Smrg}
10296747b715Smrg
10304642e01fSmrg/**
103135c4bbdfSmrg * A client that does not have the TouchOwnership mask set may not receive a
103235c4bbdfSmrg * TouchBegin event if there is at least one grab active.
10334642e01fSmrg *
103435c4bbdfSmrg * @return TRUE if the client selected for ownership events on the given
103535c4bbdfSmrg * window for this device, FALSE otherwise
10364642e01fSmrg */
103735c4bbdfSmrgstatic inline Bool
103835c4bbdfSmrgTouchClientWantsOwnershipEvents(ClientPtr client, DeviceIntPtr dev,
103935c4bbdfSmrg                                WindowPtr win)
10404642e01fSmrg{
104135c4bbdfSmrg    InputClients *iclient;
10426747b715Smrg
104335c4bbdfSmrg    nt_list_for_each_entry(iclient, wOtherInputMasks(win)->inputClients, next) {
104435c4bbdfSmrg        if (rClient(iclient) != client)
104535c4bbdfSmrg            continue;
10466747b715Smrg
104735c4bbdfSmrg        return xi2mask_isset(iclient->xi2mask, dev, XI_TouchOwnership);
10486747b715Smrg    }
10494642e01fSmrg
105035c4bbdfSmrg    return FALSE;
105135c4bbdfSmrg}
10524642e01fSmrg
105335c4bbdfSmrgstatic void
105435c4bbdfSmrgTouchSendOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, int reason,
105535c4bbdfSmrg                        XID resource)
105635c4bbdfSmrg{
105735c4bbdfSmrg    int nev, i;
105835c4bbdfSmrg    InternalEvent *tel = InitEventList(GetMaximumEventsNum());
10596747b715Smrg
106035c4bbdfSmrg    nev = GetTouchOwnershipEvents(tel, dev, ti, reason, resource, 0);
106135c4bbdfSmrg    for (i = 0; i < nev; i++)
106235c4bbdfSmrg        mieqProcessDeviceEvent(dev, tel + i, NULL);
10636747b715Smrg
106435c4bbdfSmrg    FreeEventList(tel, GetMaximumEventsNum());
106535c4bbdfSmrg}
10666747b715Smrg
106735c4bbdfSmrg/**
106835c4bbdfSmrg * Attempts to deliver a touch event to the given client.
106935c4bbdfSmrg */
107035c4bbdfSmrgstatic Bool
107135c4bbdfSmrgDeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti,
107235c4bbdfSmrg                     GrabPtr grab, WindowPtr win, InternalEvent *ev)
107335c4bbdfSmrg{
107435c4bbdfSmrg    int err;
107535c4bbdfSmrg    xEvent *xi2;
107635c4bbdfSmrg    Mask filter;
107735c4bbdfSmrg    Window child = DeepestSpriteWin(&ti->sprite)->drawable.id;
107835c4bbdfSmrg
107935c4bbdfSmrg    /* FIXME: owner event handling */
108035c4bbdfSmrg
108135c4bbdfSmrg    /* If the client does not have the ownership mask set and is not
108235c4bbdfSmrg     * the current owner of the touch, only pretend we delivered */
108335c4bbdfSmrg    if (!grab && ti->num_grabs != 0 &&
108435c4bbdfSmrg        !TouchClientWantsOwnershipEvents(client, dev, win))
108535c4bbdfSmrg        return TRUE;
108635c4bbdfSmrg
108735c4bbdfSmrg    /* If we fail here, we're going to leave a client hanging. */
108835c4bbdfSmrg    err = EventToXI2(ev, &xi2);
108935c4bbdfSmrg    if (err != Success)
109035c4bbdfSmrg        FatalError("[Xi] %s: XI2 conversion failed in %s"
109135c4bbdfSmrg                   " (%d)\n", dev->name, __func__, err);
109235c4bbdfSmrg
109335c4bbdfSmrg    FixUpEventFromWindow(&ti->sprite, xi2, win, child, FALSE);
109435c4bbdfSmrg    filter = GetEventFilter(dev, xi2);
109535c4bbdfSmrg    if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success)
109635c4bbdfSmrg        return FALSE;
109735c4bbdfSmrg    err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab);
109835c4bbdfSmrg    free(xi2);
109935c4bbdfSmrg
110035c4bbdfSmrg    /* Returning the value from TryClientEvents isn't useful, since all our
110135c4bbdfSmrg     * resource-gone cleanups will update the delivery list anyway. */
110235c4bbdfSmrg    return TRUE;
110335c4bbdfSmrg}
11046747b715Smrg
110535c4bbdfSmrgstatic void
110635c4bbdfSmrgActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti)
110735c4bbdfSmrg{
110835c4bbdfSmrg    ClientPtr client;
110935c4bbdfSmrg    XID error;
111035c4bbdfSmrg    GrabPtr grab = ti->listeners[0].grab;
11114642e01fSmrg
1112ed6184dfSmrg    BUG_RETURN(ti->listeners[0].type != TOUCH_LISTENER_GRAB &&
1113ed6184dfSmrg               ti->listeners[0].type != TOUCH_LISTENER_POINTER_GRAB);
111435c4bbdfSmrg    BUG_RETURN(!grab);
11154642e01fSmrg
111635c4bbdfSmrg    client = rClient(grab);
11174642e01fSmrg
111835c4bbdfSmrg    if (TouchAcceptReject(client, dev, XIAcceptTouch, ti->client_id,
111935c4bbdfSmrg                          ti->listeners[0].window->drawable.id, &error) != Success)
112035c4bbdfSmrg        ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n");
112135c4bbdfSmrg}
11224642e01fSmrg
112335c4bbdfSmrg/**
112435c4bbdfSmrg * Find the oldest touch that still has a pointer emulation client.
112535c4bbdfSmrg *
112635c4bbdfSmrg * Pointer emulation can only be performed for the oldest touch. Otherwise, the
112735c4bbdfSmrg * order of events seen by the client will be wrong. This function helps us find
112835c4bbdfSmrg * the next touch to be emulated.
112935c4bbdfSmrg *
113035c4bbdfSmrg * @param dev The device to find touches for.
113135c4bbdfSmrg */
113235c4bbdfSmrgstatic TouchPointInfoPtr
113335c4bbdfSmrgFindOldestPointerEmulatedTouch(DeviceIntPtr dev)
113435c4bbdfSmrg{
113535c4bbdfSmrg    TouchPointInfoPtr oldest = NULL;
113635c4bbdfSmrg    int i;
11376747b715Smrg
113835c4bbdfSmrg    for (i = 0; i < dev->touch->num_touches; i++) {
113935c4bbdfSmrg        TouchPointInfoPtr ti = dev->touch->touches + i;
114035c4bbdfSmrg        int j;
11414642e01fSmrg
114235c4bbdfSmrg        if (!ti->active || !ti->emulate_pointer)
114335c4bbdfSmrg            continue;
11444642e01fSmrg
114535c4bbdfSmrg        for (j = 0; j < ti->num_listeners; j++) {
1146ed6184dfSmrg            if (ti->listeners[j].type == TOUCH_LISTENER_POINTER_GRAB ||
1147ed6184dfSmrg                ti->listeners[j].type == TOUCH_LISTENER_POINTER_REGULAR)
114835c4bbdfSmrg                break;
114935c4bbdfSmrg        }
115035c4bbdfSmrg        if (j == ti->num_listeners)
115135c4bbdfSmrg            continue;
11524642e01fSmrg
115335c4bbdfSmrg        if (!oldest) {
115435c4bbdfSmrg            oldest = ti;
115535c4bbdfSmrg            continue;
115635c4bbdfSmrg        }
11574642e01fSmrg
115835c4bbdfSmrg        if (oldest->client_id - ti->client_id < UINT_MAX / 2)
115935c4bbdfSmrg            oldest = ti;
11604642e01fSmrg    }
116105b261ecSmrg
116235c4bbdfSmrg    return oldest;
116305b261ecSmrg}
116405b261ecSmrg
116535c4bbdfSmrg/**
116635c4bbdfSmrg * If the current owner has rejected the event, deliver the
116735c4bbdfSmrg * TouchOwnership/TouchBegin to the next item in the sprite stack.
116835c4bbdfSmrg */
116935c4bbdfSmrgstatic void
117035c4bbdfSmrgTouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
117135c4bbdfSmrg                     TouchOwnershipEvent *ev)
117205b261ecSmrg{
117335c4bbdfSmrg    TouchListener *listener = &ti->listeners[0]; /* new owner */
1174ed6184dfSmrg    int accepted_early = listener->state == TOUCH_LISTENER_EARLY_ACCEPT;
117535c4bbdfSmrg
117635c4bbdfSmrg    /* Deliver the ownership */
1177ed6184dfSmrg    if (listener->state == TOUCH_LISTENER_AWAITING_OWNER || accepted_early)
117835c4bbdfSmrg        DeliverTouchEvents(dev, ti, (InternalEvent *) ev,
117935c4bbdfSmrg                           listener->listener);
1180ed6184dfSmrg    else if (listener->state == TOUCH_LISTENER_AWAITING_BEGIN) {
118135c4bbdfSmrg        /* We can't punt to a pointer listener unless all older pointer
118235c4bbdfSmrg         * emulated touches have been seen already. */
1183ed6184dfSmrg        if ((listener->type == TOUCH_LISTENER_POINTER_GRAB ||
1184ed6184dfSmrg             listener->type == TOUCH_LISTENER_POINTER_REGULAR) &&
118535c4bbdfSmrg            ti != FindOldestPointerEmulatedTouch(dev))
118635c4bbdfSmrg            return;
118705b261ecSmrg
118835c4bbdfSmrg        TouchEventHistoryReplay(ti, dev, listener->listener);
118935c4bbdfSmrg    }
119005b261ecSmrg
119135c4bbdfSmrg    /* New owner has Begin/Update but not end. If touch is pending_finish,
119235c4bbdfSmrg     * emulate the TouchEnd now */
119335c4bbdfSmrg    if (ti->pending_finish) {
119435c4bbdfSmrg        TouchEmitTouchEnd(dev, ti, 0, 0);
119535c4bbdfSmrg
119635c4bbdfSmrg        /* If the last owner is not a touch grab, finalise the touch, we
119735c4bbdfSmrg           won't get more correspondence on this.
119835c4bbdfSmrg         */
119935c4bbdfSmrg        if (ti->num_listeners == 1 &&
120035c4bbdfSmrg            (ti->num_grabs == 0 ||
120135c4bbdfSmrg             listener->grab->grabtype != XI2 ||
120235c4bbdfSmrg             !xi2mask_isset(listener->grab->xi2mask, dev, XI_TouchBegin))) {
120335c4bbdfSmrg            TouchEndTouch(dev, ti);
120435c4bbdfSmrg            return;
120535c4bbdfSmrg        }
120635c4bbdfSmrg    }
120735c4bbdfSmrg
120835c4bbdfSmrg    if (accepted_early)
120935c4bbdfSmrg        ActivateEarlyAccept(dev, ti);
121035c4bbdfSmrg}
121135c4bbdfSmrg
121235c4bbdfSmrg/**
121335c4bbdfSmrg * Check the oldest touch to see if it needs to be replayed to its pointer
121435c4bbdfSmrg * owner.
121535c4bbdfSmrg *
121635c4bbdfSmrg * Touch event propagation is paused if it hits a pointer listener while an
121735c4bbdfSmrg * older touch with a pointer listener is waiting on accept or reject. This
121835c4bbdfSmrg * function will restart propagation of a paused touch if needed.
121935c4bbdfSmrg *
122035c4bbdfSmrg * @param dev The device to check touches for.
122135c4bbdfSmrg */
122235c4bbdfSmrgstatic void
122335c4bbdfSmrgCheckOldestTouch(DeviceIntPtr dev)
122435c4bbdfSmrg{
122535c4bbdfSmrg    TouchPointInfoPtr oldest = FindOldestPointerEmulatedTouch(dev);
122635c4bbdfSmrg
1227ed6184dfSmrg    if (oldest && oldest->listeners[0].state == TOUCH_LISTENER_AWAITING_BEGIN)
122835c4bbdfSmrg        TouchPuntToNextOwner(dev, oldest, NULL);
122935c4bbdfSmrg}
123035c4bbdfSmrg
123135c4bbdfSmrg/**
123235c4bbdfSmrg * Process a touch rejection.
123335c4bbdfSmrg *
123435c4bbdfSmrg * @param sourcedev The source device of the touch sequence.
123535c4bbdfSmrg * @param ti The touchpoint info record.
123635c4bbdfSmrg * @param resource The resource of the client rejecting the touch.
123735c4bbdfSmrg * @param ev TouchOwnership event to send. Set to NULL if no event should be
123835c4bbdfSmrg *        sent.
123935c4bbdfSmrg */
124035c4bbdfSmrgvoid
124135c4bbdfSmrgTouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
124235c4bbdfSmrg              TouchOwnershipEvent *ev)
124335c4bbdfSmrg{
124435c4bbdfSmrg    Bool was_owner = (resource == ti->listeners[0].listener);
124535c4bbdfSmrg    int i;
124635c4bbdfSmrg
124735c4bbdfSmrg    /* Send a TouchEnd event to the resource being removed, but only if they
124835c4bbdfSmrg     * haven't received one yet already */
124935c4bbdfSmrg    for (i = 0; i < ti->num_listeners; i++) {
125035c4bbdfSmrg        if (ti->listeners[i].listener == resource) {
1251ed6184dfSmrg            if (ti->listeners[i].state != TOUCH_LISTENER_HAS_END)
125235c4bbdfSmrg                TouchEmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource);
125335c4bbdfSmrg            break;
125435c4bbdfSmrg        }
125535c4bbdfSmrg    }
125635c4bbdfSmrg
125735c4bbdfSmrg    /* Remove the resource from the listener list, updating
125835c4bbdfSmrg     * ti->num_listeners, as well as ti->num_grabs if it was a grab. */
125935c4bbdfSmrg    TouchRemoveListener(ti, resource);
126035c4bbdfSmrg
126135c4bbdfSmrg    /* If the current owner was removed and there are further listeners, deliver
126235c4bbdfSmrg     * the TouchOwnership or TouchBegin event to the new owner. */
126335c4bbdfSmrg    if (ev && ti->num_listeners > 0 && was_owner)
126435c4bbdfSmrg        TouchPuntToNextOwner(sourcedev, ti, ev);
126535c4bbdfSmrg    else if (ti->num_listeners == 0)
126635c4bbdfSmrg        TouchEndTouch(sourcedev, ti);
126735c4bbdfSmrg
126835c4bbdfSmrg    CheckOldestTouch(sourcedev);
126935c4bbdfSmrg}
127035c4bbdfSmrg
127135c4bbdfSmrg/**
127235c4bbdfSmrg * Processes a TouchOwnership event, indicating a grab has accepted the touch
127335c4bbdfSmrg * it currently owns, or a grab or selection has been removed.  Will generate
127435c4bbdfSmrg * and send TouchEnd events to all clients removed from the delivery list, as
127535c4bbdfSmrg * well as possibly sending the new TouchOwnership event.  May end the
127635c4bbdfSmrg * touchpoint if it is pending finish.
127735c4bbdfSmrg */
127835c4bbdfSmrgstatic void
127935c4bbdfSmrgProcessTouchOwnershipEvent(TouchOwnershipEvent *ev,
128035c4bbdfSmrg                           DeviceIntPtr dev)
128135c4bbdfSmrg{
128235c4bbdfSmrg    TouchPointInfoPtr ti = TouchFindByClientID(dev, ev->touchid);
128335c4bbdfSmrg
128435c4bbdfSmrg    if (!ti) {
128535c4bbdfSmrg        DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
128635c4bbdfSmrg               dev->name, ev->type, ev->touchid);
128735c4bbdfSmrg        return;
128835c4bbdfSmrg    }
128935c4bbdfSmrg
129035c4bbdfSmrg    if (ev->reason == XIRejectTouch)
129135c4bbdfSmrg        TouchRejected(dev, ti, ev->resource, ev);
129235c4bbdfSmrg    else if (ev->reason == XIAcceptTouch) {
129335c4bbdfSmrg        int i;
129435c4bbdfSmrg
129535c4bbdfSmrg
129635c4bbdfSmrg        /* For pointer-emulated listeners that ungrabbed the active grab,
1297ed6184dfSmrg         * the state was forced to TOUCH_LISTENER_HAS_END. Still go
129835c4bbdfSmrg         * through the motions of ending the touch if the listener has
129935c4bbdfSmrg         * already seen the end. This ensures that the touch record is ended in
130035c4bbdfSmrg         * the server.
130135c4bbdfSmrg         */
1302ed6184dfSmrg        if (ti->listeners[0].state == TOUCH_LISTENER_HAS_END)
130335c4bbdfSmrg            TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener);
130435c4bbdfSmrg
130535c4bbdfSmrg        /* The touch owner has accepted the touch.  Send TouchEnd events to
130635c4bbdfSmrg         * everyone else, and truncate the list of listeners. */
130735c4bbdfSmrg        for (i = 1; i < ti->num_listeners; i++)
130835c4bbdfSmrg            TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener);
130935c4bbdfSmrg
131035c4bbdfSmrg        while (ti->num_listeners > 1)
131135c4bbdfSmrg            TouchRemoveListener(ti, ti->listeners[1].listener);
131235c4bbdfSmrg        /* Owner accepted after receiving end */
1313ed6184dfSmrg        if (ti->listeners[0].state == TOUCH_LISTENER_HAS_END)
131435c4bbdfSmrg            TouchEndTouch(dev, ti);
131535c4bbdfSmrg        else
1316ed6184dfSmrg            ti->listeners[0].state = TOUCH_LISTENER_HAS_ACCEPTED;
131735c4bbdfSmrg    }
131835c4bbdfSmrg    else {  /* this is the very first ownership event for a grab */
131935c4bbdfSmrg        DeliverTouchEvents(dev, ti, (InternalEvent *) ev, ev->resource);
132035c4bbdfSmrg    }
132135c4bbdfSmrg}
132235c4bbdfSmrg
132335c4bbdfSmrg/**
132435c4bbdfSmrg * Copy the event's valuator information into the touchpoint, we may need
132535c4bbdfSmrg * this for emulated TouchEnd events.
132635c4bbdfSmrg */
132735c4bbdfSmrgstatic void
132835c4bbdfSmrgTouchCopyValuatorData(DeviceEvent *ev, TouchPointInfoPtr ti)
132935c4bbdfSmrg{
133035c4bbdfSmrg    int i;
133135c4bbdfSmrg
133235c4bbdfSmrg    for (i = 0; i < ARRAY_SIZE(ev->valuators.data); i++)
133335c4bbdfSmrg        if (BitIsOn(ev->valuators.mask, i))
133435c4bbdfSmrg            valuator_mask_set_double(ti->valuators, i, ev->valuators.data[i]);
133535c4bbdfSmrg}
133635c4bbdfSmrg
133735c4bbdfSmrg/**
133835c4bbdfSmrg * Given a touch event and a potential listener, retrieve info needed for
133935c4bbdfSmrg * processing the event.
134035c4bbdfSmrg *
134135c4bbdfSmrg * @param dev The device generating the touch event.
134235c4bbdfSmrg * @param ti The touch point info record for the touch event.
134335c4bbdfSmrg * @param ev The touch event to process.
134435c4bbdfSmrg * @param listener The touch event listener that may receive the touch event.
134535c4bbdfSmrg * @param[out] client The client that should receive the touch event.
134635c4bbdfSmrg * @param[out] win The window to deliver the event on.
134735c4bbdfSmrg * @param[out] grab The grab to deliver the event through, if any.
134835c4bbdfSmrg * @param[out] mask The XI 2.x event mask of the grab or selection, if any.
134935c4bbdfSmrg * @return TRUE if an event should be delivered to the listener, FALSE
135035c4bbdfSmrg *         otherwise.
135135c4bbdfSmrg */
135235c4bbdfSmrgstatic Bool
135335c4bbdfSmrgRetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
135435c4bbdfSmrg                          InternalEvent *ev, TouchListener * listener,
135535c4bbdfSmrg                          ClientPtr *client, WindowPtr *win, GrabPtr *grab,
135635c4bbdfSmrg                          XI2Mask **mask)
135735c4bbdfSmrg{
135835c4bbdfSmrg    int rc;
135935c4bbdfSmrg    InputClients *iclients = NULL;
136035c4bbdfSmrg    *mask = NULL;
136135c4bbdfSmrg
1362ed6184dfSmrg    if (listener->type == TOUCH_LISTENER_GRAB ||
1363ed6184dfSmrg        listener->type == TOUCH_LISTENER_POINTER_GRAB) {
136435c4bbdfSmrg        *grab = listener->grab;
136535c4bbdfSmrg
136635c4bbdfSmrg        BUG_RETURN_VAL(!*grab, FALSE);
136735c4bbdfSmrg
136835c4bbdfSmrg        *client = rClient(*grab);
136935c4bbdfSmrg        *win = (*grab)->window;
137035c4bbdfSmrg        *mask = (*grab)->xi2mask;
137135c4bbdfSmrg    }
137235c4bbdfSmrg    else {
137335c4bbdfSmrg        rc = dixLookupResourceByType((void **) win, listener->listener,
137435c4bbdfSmrg                                     listener->resource_type,
137535c4bbdfSmrg                                     serverClient, DixSendAccess);
137635c4bbdfSmrg        if (rc != Success)
137735c4bbdfSmrg            return FALSE;
137835c4bbdfSmrg
137935c4bbdfSmrg        if (listener->level == XI2) {
138035c4bbdfSmrg            int evtype;
138135c4bbdfSmrg
138235c4bbdfSmrg            if (ti->emulate_pointer &&
1383ed6184dfSmrg                listener->type == TOUCH_LISTENER_POINTER_REGULAR)
138435c4bbdfSmrg                evtype = GetXI2Type(TouchGetPointerEventType(ev));
138535c4bbdfSmrg            else
138635c4bbdfSmrg                evtype = GetXI2Type(ev->any.type);
138735c4bbdfSmrg
138835c4bbdfSmrg            nt_list_for_each_entry(iclients,
138935c4bbdfSmrg                                   wOtherInputMasks(*win)->inputClients, next)
139035c4bbdfSmrg                if (xi2mask_isset(iclients->xi2mask, dev, evtype))
139135c4bbdfSmrg                break;
139235c4bbdfSmrg
139335c4bbdfSmrg            BUG_RETURN_VAL(!iclients, FALSE);
139435c4bbdfSmrg
139535c4bbdfSmrg            *mask = iclients->xi2mask;
139635c4bbdfSmrg            *client = rClient(iclients);
139735c4bbdfSmrg        }
139835c4bbdfSmrg        else if (listener->level == XI) {
139935c4bbdfSmrg            int xi_type = GetXIType(TouchGetPointerEventType(ev));
140035c4bbdfSmrg            Mask xi_filter = event_get_filter_from_type(dev, xi_type);
140135c4bbdfSmrg
140235c4bbdfSmrg            nt_list_for_each_entry(iclients,
140335c4bbdfSmrg                                   wOtherInputMasks(*win)->inputClients, next)
140435c4bbdfSmrg                if (iclients->mask[dev->id] & xi_filter)
140535c4bbdfSmrg                break;
140635c4bbdfSmrg            BUG_RETURN_VAL(!iclients, FALSE);
140735c4bbdfSmrg
140835c4bbdfSmrg            *client = rClient(iclients);
140935c4bbdfSmrg        }
141035c4bbdfSmrg        else {
141135c4bbdfSmrg            int coretype = GetCoreType(TouchGetPointerEventType(ev));
141235c4bbdfSmrg            Mask core_filter = event_get_filter_from_type(dev, coretype);
141335c4bbdfSmrg            OtherClients *oclients;
141435c4bbdfSmrg
141535c4bbdfSmrg            /* all others */
141635c4bbdfSmrg            nt_list_for_each_entry(oclients,
141735c4bbdfSmrg                                   (OtherClients *) wOtherClients(*win), next)
141835c4bbdfSmrg                if (oclients->mask & core_filter)
141935c4bbdfSmrg                    break;
142035c4bbdfSmrg
142135c4bbdfSmrg            /* if owner selected, oclients is NULL */
142235c4bbdfSmrg            *client = oclients ? rClient(oclients) : wClient(*win);
142335c4bbdfSmrg        }
1424ed6184dfSmrg
1425ed6184dfSmrg        *grab = NULL;
142635c4bbdfSmrg    }
142735c4bbdfSmrg
142835c4bbdfSmrg    return TRUE;
142935c4bbdfSmrg}
143035c4bbdfSmrg
143135c4bbdfSmrgstatic int
143235c4bbdfSmrgDeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
143335c4bbdfSmrg                          InternalEvent *ev, TouchListener * listener,
143435c4bbdfSmrg                          ClientPtr client, WindowPtr win, GrabPtr grab,
143535c4bbdfSmrg                          XI2Mask *xi2mask)
143635c4bbdfSmrg{
143735c4bbdfSmrg    InternalEvent motion, button;
143835c4bbdfSmrg    InternalEvent *ptrev = &motion;
143935c4bbdfSmrg    int nevents;
144035c4bbdfSmrg    DeviceIntPtr kbd;
144135c4bbdfSmrg
1442ed6184dfSmrg    /* There may be a pointer grab on the device */
1443ed6184dfSmrg    if (!grab) {
1444ed6184dfSmrg        grab = dev->deviceGrab.grab;
1445ed6184dfSmrg        if (grab) {
1446ed6184dfSmrg            win = grab->window;
1447ed6184dfSmrg            xi2mask = grab->xi2mask;
1448ed6184dfSmrg            client = rClient(grab);
1449ed6184dfSmrg        }
1450ed6184dfSmrg    }
1451ed6184dfSmrg
145235c4bbdfSmrg    /* We don't deliver pointer events to non-owners */
145335c4bbdfSmrg    if (!TouchResourceIsOwner(ti, listener->listener))
145435c4bbdfSmrg        return !Success;
145535c4bbdfSmrg
145635c4bbdfSmrg    if (!ti->emulate_pointer)
145735c4bbdfSmrg        return !Success;
145835c4bbdfSmrg
145935c4bbdfSmrg    nevents = TouchConvertToPointerEvent(ev, &motion, &button);
146035c4bbdfSmrg    BUG_RETURN_VAL(nevents == 0, BadValue);
146135c4bbdfSmrg
1462ed6184dfSmrg    /* Note that here we deliver only part of the events that are generated by the touch event:
1463ed6184dfSmrg     *
1464ed6184dfSmrg     * TouchBegin results in ButtonPress (motion is handled in DeliverEmulatedMotionEvent)
1465ed6184dfSmrg     * TouchUpdate results in Motion
1466ed6184dfSmrg     * TouchEnd results in ButtonRelease (motion is handled in DeliverEmulatedMotionEvent)
1467ed6184dfSmrg     */
146835c4bbdfSmrg    if (nevents > 1)
146935c4bbdfSmrg        ptrev = &button;
147035c4bbdfSmrg
147135c4bbdfSmrg    kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
147235c4bbdfSmrg    event_set_state(dev, kbd, &ptrev->device_event);
147335c4bbdfSmrg    ptrev->device_event.corestate = event_get_corestate(dev, kbd);
147435c4bbdfSmrg
147535c4bbdfSmrg    if (grab) {
147635c4bbdfSmrg        /* this side-steps the usual activation mechanisms, but... */
147735c4bbdfSmrg        if (ev->any.type == ET_TouchBegin && !dev->deviceGrab.grab)
147835c4bbdfSmrg            ActivatePassiveGrab(dev, grab, ptrev, ev);  /* also delivers the event */
147935c4bbdfSmrg        else {
148035c4bbdfSmrg            int deliveries = 0;
148135c4bbdfSmrg
148235c4bbdfSmrg            /* 'grab' is the passive grab, but if the grab isn't active,
148335c4bbdfSmrg             * don't deliver */
148435c4bbdfSmrg            if (!dev->deviceGrab.grab)
148535c4bbdfSmrg                return !Success;
148635c4bbdfSmrg
148735c4bbdfSmrg            if (grab->ownerEvents) {
148835c4bbdfSmrg                WindowPtr focus = NullWindow;
148935c4bbdfSmrg                WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite);
149035c4bbdfSmrg
149135c4bbdfSmrg                deliveries = DeliverDeviceEvents(sprite_win, ptrev, grab, focus, dev);
149235c4bbdfSmrg            }
149335c4bbdfSmrg
149435c4bbdfSmrg            if (!deliveries)
149535c4bbdfSmrg                deliveries = DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
149635c4bbdfSmrg
149735c4bbdfSmrg            /* We must accept the touch sequence once a pointer listener has
149835c4bbdfSmrg             * received one event past ButtonPress. */
149935c4bbdfSmrg            if (deliveries && ev->any.type != ET_TouchBegin &&
150035c4bbdfSmrg                !(ev->device_event.flags & TOUCH_CLIENT_ID))
150135c4bbdfSmrg                TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
150235c4bbdfSmrg
150335c4bbdfSmrg            if (ev->any.type == ET_TouchEnd &&
150435c4bbdfSmrg                ti->num_listeners == 1 &&
150535c4bbdfSmrg                !dev->button->buttonsDown &&
150635c4bbdfSmrg                dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
150735c4bbdfSmrg                (*dev->deviceGrab.DeactivateGrab) (dev);
150835c4bbdfSmrg                CheckOldestTouch(dev);
150935c4bbdfSmrg                return Success;
151035c4bbdfSmrg            }
151135c4bbdfSmrg        }
151235c4bbdfSmrg    }
151335c4bbdfSmrg    else {
151435c4bbdfSmrg        GrabPtr devgrab = dev->deviceGrab.grab;
151535c4bbdfSmrg        WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite);
151635c4bbdfSmrg
151735c4bbdfSmrg        DeliverDeviceEvents(sprite_win, ptrev, grab, win, dev);
151835c4bbdfSmrg        /* FIXME: bad hack
151935c4bbdfSmrg         * Implicit passive grab activated in response to this event. Store
152035c4bbdfSmrg         * the event.
152135c4bbdfSmrg         */
152235c4bbdfSmrg        if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab) {
152335c4bbdfSmrg            TouchListener *l;
152435c4bbdfSmrg            GrabPtr g;
152535c4bbdfSmrg
152635c4bbdfSmrg            devgrab = dev->deviceGrab.grab;
152735c4bbdfSmrg            g = AllocGrab(devgrab);
152835c4bbdfSmrg            BUG_WARN(!g);
152935c4bbdfSmrg
1530dc61d50dSmrg            CopyPartialInternalEvent(dev->deviceGrab.sync.event, ev);
153135c4bbdfSmrg
153235c4bbdfSmrg            /* The listener array has a sequence of grabs and then one event
153335c4bbdfSmrg             * selection. Implicit grab activation occurs through delivering an
153435c4bbdfSmrg             * event selection. Thus, we update the last listener in the array.
153535c4bbdfSmrg             */
153635c4bbdfSmrg            l = &ti->listeners[ti->num_listeners - 1];
153735c4bbdfSmrg            l->listener = g->resource;
153835c4bbdfSmrg            l->grab = g;
153935c4bbdfSmrg            //l->resource_type = RT_NONE;
154035c4bbdfSmrg
154135c4bbdfSmrg            if (devgrab->grabtype != XI2 || devgrab->type != XI_TouchBegin)
1542ed6184dfSmrg                l->type = TOUCH_LISTENER_POINTER_GRAB;
154335c4bbdfSmrg            else
1544ed6184dfSmrg                l->type = TOUCH_LISTENER_GRAB;
154535c4bbdfSmrg        }
154635c4bbdfSmrg
154735c4bbdfSmrg    }
154835c4bbdfSmrg    if (ev->any.type == ET_TouchBegin)
1549ed6184dfSmrg        listener->state = TOUCH_LISTENER_IS_OWNER;
155035c4bbdfSmrg    else if (ev->any.type == ET_TouchEnd)
1551ed6184dfSmrg        listener->state = TOUCH_LISTENER_HAS_END;
155235c4bbdfSmrg
155335c4bbdfSmrg    return Success;
155435c4bbdfSmrg}
155535c4bbdfSmrg
155635c4bbdfSmrgstatic void
155735c4bbdfSmrgDeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
155835c4bbdfSmrg                           InternalEvent *ev)
155935c4bbdfSmrg{
156035c4bbdfSmrg    DeviceEvent motion;
156135c4bbdfSmrg
156235c4bbdfSmrg    if (ti->num_listeners) {
156335c4bbdfSmrg        ClientPtr client;
156435c4bbdfSmrg        WindowPtr win;
156535c4bbdfSmrg        GrabPtr grab;
156635c4bbdfSmrg        XI2Mask *mask;
156735c4bbdfSmrg
1568ed6184dfSmrg        if (ti->listeners[0].type != TOUCH_LISTENER_POINTER_REGULAR &&
1569ed6184dfSmrg            ti->listeners[0].type != TOUCH_LISTENER_POINTER_GRAB)
157035c4bbdfSmrg            return;
157135c4bbdfSmrg
157235c4bbdfSmrg        motion = ev->device_event;
157335c4bbdfSmrg        motion.type = ET_TouchUpdate;
157435c4bbdfSmrg        motion.detail.button = 0;
157535c4bbdfSmrg
157635c4bbdfSmrg        if (!RetrieveTouchDeliveryData(dev, ti, (InternalEvent*)&motion,
157735c4bbdfSmrg                                       &ti->listeners[0], &client, &win, &grab,
157835c4bbdfSmrg                                       &mask))
157935c4bbdfSmrg            return;
158035c4bbdfSmrg
158135c4bbdfSmrg        DeliverTouchEmulatedEvent(dev, ti, (InternalEvent*)&motion, &ti->listeners[0], client,
158235c4bbdfSmrg                                  win, grab, mask);
158335c4bbdfSmrg    }
158435c4bbdfSmrg    else {
158535c4bbdfSmrg        InternalEvent button;
158635c4bbdfSmrg        int converted;
158735c4bbdfSmrg
158835c4bbdfSmrg        converted = TouchConvertToPointerEvent(ev, (InternalEvent*)&motion, &button);
158935c4bbdfSmrg
159035c4bbdfSmrg        BUG_WARN(converted == 0);
159135c4bbdfSmrg        if (converted)
159235c4bbdfSmrg            ProcessOtherEvent((InternalEvent*)&motion, dev);
159335c4bbdfSmrg    }
159435c4bbdfSmrg}
159535c4bbdfSmrg
159635c4bbdfSmrg/**
159735c4bbdfSmrg * Processes and delivers a TouchBegin, TouchUpdate, or a
159835c4bbdfSmrg * TouchEnd event.
159935c4bbdfSmrg *
160035c4bbdfSmrg * Due to having rather different delivery semantics (see the Xi 2.2 protocol
160135c4bbdfSmrg * spec for more information), this implements its own grab and event-selection
160235c4bbdfSmrg * delivery logic.
160335c4bbdfSmrg */
160435c4bbdfSmrgstatic void
160535c4bbdfSmrgProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
160635c4bbdfSmrg{
160735c4bbdfSmrg    TouchClassPtr t = dev->touch;
160835c4bbdfSmrg    TouchPointInfoPtr ti;
160935c4bbdfSmrg    uint32_t touchid;
161035c4bbdfSmrg    int type = ev->any.type;
161135c4bbdfSmrg    int emulate_pointer = ! !(ev->device_event.flags & TOUCH_POINTER_EMULATED);
161235c4bbdfSmrg    DeviceIntPtr kbd;
161335c4bbdfSmrg
161435c4bbdfSmrg    if (!t)
161535c4bbdfSmrg        return;
161635c4bbdfSmrg
161735c4bbdfSmrg    touchid = ev->device_event.touchid;
161835c4bbdfSmrg
161935c4bbdfSmrg    if (type == ET_TouchBegin && !(ev->device_event.flags & TOUCH_REPLAYING)) {
162035c4bbdfSmrg        ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
162135c4bbdfSmrg                             emulate_pointer);
162235c4bbdfSmrg    }
162335c4bbdfSmrg    else
162435c4bbdfSmrg        ti = TouchFindByClientID(dev, touchid);
162535c4bbdfSmrg
162635c4bbdfSmrg    /* Active pointer grab */
162735c4bbdfSmrg    if (emulate_pointer && dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab &&
162835c4bbdfSmrg        (dev->deviceGrab.grab->grabtype == CORE ||
162935c4bbdfSmrg         dev->deviceGrab.grab->grabtype == XI ||
163035c4bbdfSmrg         !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin)))
163135c4bbdfSmrg    {
163235c4bbdfSmrg        /* Active pointer grab on touch point and we get a TouchEnd - claim this
163335c4bbdfSmrg         * touchpoint accepted, otherwise clients waiting for ownership will
163435c4bbdfSmrg         * wait on this touchpoint until this client ungrabs, or the cows come
163535c4bbdfSmrg         * home, whichever is earlier */
163635c4bbdfSmrg        if (ti && type == ET_TouchEnd)
163735c4bbdfSmrg            TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
163835c4bbdfSmrg        else if (!ti && type != ET_TouchBegin) {
163935c4bbdfSmrg            /* Under the following circumstances we create a new touch record for an
164035c4bbdfSmrg             * existing touch:
164135c4bbdfSmrg             *
164235c4bbdfSmrg             * - The touch may be pointer emulated
164335c4bbdfSmrg             * - An explicit grab is active on the device
164435c4bbdfSmrg             * - The grab is a pointer grab
164535c4bbdfSmrg             *
164635c4bbdfSmrg             * This allows for an explicit grab to receive pointer events for an already
164735c4bbdfSmrg             * active touch.
164835c4bbdfSmrg             */
164935c4bbdfSmrg            ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
165035c4bbdfSmrg                                 emulate_pointer);
165135c4bbdfSmrg            if (!ti) {
165235c4bbdfSmrg                DebugF("[Xi] %s: Failed to create new dix record for explicitly "
165335c4bbdfSmrg                       "grabbed touchpoint %d\n",
165435c4bbdfSmrg                       dev->name, touchid);
165535c4bbdfSmrg                return;
165635c4bbdfSmrg            }
165735c4bbdfSmrg
165835c4bbdfSmrg            TouchBuildSprite(dev, ti, ev);
165935c4bbdfSmrg            TouchSetupListeners(dev, ti, ev);
166035c4bbdfSmrg        }
166135c4bbdfSmrg    }
166235c4bbdfSmrg
166335c4bbdfSmrg    if (!ti) {
166435c4bbdfSmrg        DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
166535c4bbdfSmrg               dev->name, type, touchid);
166635c4bbdfSmrg        goto out;
166735c4bbdfSmrg    }
166835c4bbdfSmrg
166935c4bbdfSmrg    /* if emulate_pointer is set, emulate the motion event right
167035c4bbdfSmrg     * here, so we can ignore it for button event emulation. TouchUpdate
167135c4bbdfSmrg     * events which _only_ emulate motion just work normally */
1672ed6184dfSmrg    if (emulate_pointer && (ev->any.type == ET_TouchBegin ||
1673ed6184dfSmrg                           (ev->any.type == ET_TouchEnd && ti->num_listeners > 0)))
167435c4bbdfSmrg        DeliverEmulatedMotionEvent(dev, ti, ev);
167535c4bbdfSmrg
167635c4bbdfSmrg    if (emulate_pointer && IsMaster(dev))
167735c4bbdfSmrg        CheckMotion(&ev->device_event, dev);
167835c4bbdfSmrg
167935c4bbdfSmrg    kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
168035c4bbdfSmrg    event_set_state(NULL, kbd, &ev->device_event);
168135c4bbdfSmrg    ev->device_event.corestate = event_get_corestate(NULL, kbd);
168235c4bbdfSmrg
168335c4bbdfSmrg    /* Make sure we have a valid window trace for event delivery; must be
168435c4bbdfSmrg     * called after event type mutation. Touch end events are always processed
168535c4bbdfSmrg     * in order to end touch records. */
168635c4bbdfSmrg    /* FIXME: check this */
168735c4bbdfSmrg    if ((type == ET_TouchBegin &&
168835c4bbdfSmrg         !(ev->device_event.flags & TOUCH_REPLAYING) &&
168935c4bbdfSmrg         !TouchBuildSprite(dev, ti, ev)) ||
169035c4bbdfSmrg        (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0))
169135c4bbdfSmrg        return;
169235c4bbdfSmrg
169335c4bbdfSmrg    TouchCopyValuatorData(&ev->device_event, ti);
169435c4bbdfSmrg    /* WARNING: the event type may change to TouchUpdate in
169535c4bbdfSmrg     * DeliverTouchEvents if a TouchEnd was delivered to a grabbing
169635c4bbdfSmrg     * owner */
169735c4bbdfSmrg    DeliverTouchEvents(dev, ti, ev, ev->device_event.resource);
169835c4bbdfSmrg    if (ev->any.type == ET_TouchEnd)
169935c4bbdfSmrg        TouchEndTouch(dev, ti);
170035c4bbdfSmrg
170135c4bbdfSmrg out:
170235c4bbdfSmrg    if (emulate_pointer)
170335c4bbdfSmrg        UpdateDeviceState(dev, &ev->device_event);
170435c4bbdfSmrg}
170535c4bbdfSmrg
170635c4bbdfSmrgstatic void
170735c4bbdfSmrgProcessBarrierEvent(InternalEvent *e, DeviceIntPtr dev)
170835c4bbdfSmrg{
170935c4bbdfSmrg    Mask filter;
171035c4bbdfSmrg    WindowPtr pWin;
171135c4bbdfSmrg    BarrierEvent *be = &e->barrier_event;
171235c4bbdfSmrg    xEvent *ev;
171335c4bbdfSmrg    int rc;
171435c4bbdfSmrg    GrabPtr grab = dev->deviceGrab.grab;
171535c4bbdfSmrg
171635c4bbdfSmrg    if (!IsMaster(dev))
171735c4bbdfSmrg        return;
171835c4bbdfSmrg
171935c4bbdfSmrg    if (dixLookupWindow(&pWin, be->window, serverClient, DixReadAccess) != Success)
172035c4bbdfSmrg        return;
172135c4bbdfSmrg
172235c4bbdfSmrg    if (grab)
172335c4bbdfSmrg        be->flags |= XIBarrierDeviceIsGrabbed;
172435c4bbdfSmrg
172535c4bbdfSmrg    rc = EventToXI2(e, &ev);
172635c4bbdfSmrg    if (rc != Success) {
172735c4bbdfSmrg        ErrorF("[Xi] event conversion from %s failed with code %d\n", __func__, rc);
172835c4bbdfSmrg        return;
172935c4bbdfSmrg    }
173035c4bbdfSmrg
173135c4bbdfSmrg    /* A client has a grab, deliver to this client if the grab_window is the
173235c4bbdfSmrg       barrier window.
173335c4bbdfSmrg
173435c4bbdfSmrg       Otherwise, deliver normally to the client.
173535c4bbdfSmrg     */
173635c4bbdfSmrg    if (grab &&
173735c4bbdfSmrg        CLIENT_ID(be->barrierid) == CLIENT_ID(grab->resource) &&
173835c4bbdfSmrg        grab->window->drawable.id == be->window) {
173935c4bbdfSmrg        DeliverGrabbedEvent(e, dev, FALSE);
174035c4bbdfSmrg    } else {
174135c4bbdfSmrg        filter = GetEventFilter(dev, ev);
174235c4bbdfSmrg
174335c4bbdfSmrg        DeliverEventsToWindow(dev, pWin, ev, 1,
174435c4bbdfSmrg                              filter, NullGrab);
174535c4bbdfSmrg    }
174635c4bbdfSmrg    free(ev);
174735c4bbdfSmrg}
174835c4bbdfSmrg
1749ed6184dfSmrgstatic BOOL
1750ed6184dfSmrgIsAnotherGestureActiveOnMaster(DeviceIntPtr dev, InternalEvent* ev)
1751ed6184dfSmrg{
1752ed6184dfSmrg    GestureClassPtr g = dev->gesture;
1753ed6184dfSmrg    if (g->gesture.active && g->gesture.sourceid != ev->gesture_event.sourceid) {
1754ed6184dfSmrg        return TRUE;
1755ed6184dfSmrg    }
1756ed6184dfSmrg    return FALSE;
1757ed6184dfSmrg}
1758ed6184dfSmrg
1759ed6184dfSmrg/**
1760ed6184dfSmrg * Processes and delivers a Gesture{Pinch,Swipe}{Begin,Update,End}.
1761ed6184dfSmrg *
1762ed6184dfSmrg * Due to having rather different delivery semantics (see the Xi 2.4 protocol
1763ed6184dfSmrg * spec for more information), this implements its own grab and event-selection
1764ed6184dfSmrg * delivery logic.
1765ed6184dfSmrg */
1766ed6184dfSmrgvoid
1767ed6184dfSmrgProcessGestureEvent(InternalEvent *ev, DeviceIntPtr dev)
1768ed6184dfSmrg{
1769ed6184dfSmrg    GestureInfoPtr gi;
1770ed6184dfSmrg    DeviceIntPtr kbd;
1771ed6184dfSmrg    Bool deactivateGestureGrab = FALSE;
1772ed6184dfSmrg    Bool delivered = FALSE;
1773ed6184dfSmrg
1774ed6184dfSmrg    if (!dev->gesture)
1775ed6184dfSmrg        return;
1776ed6184dfSmrg
1777ed6184dfSmrg    if (IsMaster(dev) && IsAnotherGestureActiveOnMaster(dev, ev))
1778ed6184dfSmrg        return;
1779ed6184dfSmrg
1780ed6184dfSmrg    if (IsGestureBeginEvent(ev))
1781ed6184dfSmrg        gi = GestureBeginGesture(dev, ev);
1782ed6184dfSmrg    else
1783ed6184dfSmrg        gi = GestureFindActiveByEventType(dev, ev->any.type);
1784ed6184dfSmrg
1785ed6184dfSmrg    if (!gi) {
1786ed6184dfSmrg        /* This may happen if gesture is no longer active or was never started. */
1787ed6184dfSmrg        return;
1788ed6184dfSmrg    }
1789ed6184dfSmrg
1790ed6184dfSmrg    kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
1791ed6184dfSmrg    event_set_state_gesture(kbd, &ev->gesture_event);
1792ed6184dfSmrg
1793ed6184dfSmrg    if (IsGestureBeginEvent(ev))
1794ed6184dfSmrg        GestureSetupListener(dev, gi, ev);
1795ed6184dfSmrg
1796ed6184dfSmrg    if (IsGestureEndEvent(ev) &&
1797ed6184dfSmrg            dev->deviceGrab.grab &&
1798ed6184dfSmrg            dev->deviceGrab.fromPassiveGrab &&
1799ed6184dfSmrg            GrabIsGestureGrab(dev->deviceGrab.grab))
1800ed6184dfSmrg        deactivateGestureGrab = TRUE;
1801ed6184dfSmrg
1802ed6184dfSmrg    delivered = DeliverGestureEventToOwner(dev, gi, ev);
1803ed6184dfSmrg
1804ed6184dfSmrg    if (delivered && !deactivateGestureGrab &&
1805ed6184dfSmrg            (IsGestureBeginEvent(ev) || IsGestureEndEvent(ev)))
1806ed6184dfSmrg        FreezeThisEventIfNeededForSyncGrab(dev, ev);
1807ed6184dfSmrg
1808ed6184dfSmrg    if (IsGestureEndEvent(ev))
1809ed6184dfSmrg        GestureEndGesture(gi);
1810ed6184dfSmrg
1811ed6184dfSmrg    if (deactivateGestureGrab)
1812ed6184dfSmrg        (*dev->deviceGrab.DeactivateGrab) (dev);
1813ed6184dfSmrg}
1814ed6184dfSmrg
181535c4bbdfSmrg/**
181635c4bbdfSmrg * Process DeviceEvents and DeviceChangedEvents.
181735c4bbdfSmrg */
181835c4bbdfSmrgstatic void
181935c4bbdfSmrgProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device)
182035c4bbdfSmrg{
182135c4bbdfSmrg    GrabPtr grab;
182235c4bbdfSmrg    Bool deactivateDeviceGrab = FALSE;
182335c4bbdfSmrg    int key = 0, rootX, rootY;
182435c4bbdfSmrg    ButtonClassPtr b;
182535c4bbdfSmrg    int ret = 0;
182635c4bbdfSmrg    int corestate;
182735c4bbdfSmrg    DeviceIntPtr mouse = NULL, kbd = NULL;
182835c4bbdfSmrg    DeviceEvent *event = &ev->device_event;
182935c4bbdfSmrg
183035c4bbdfSmrg    if (IsPointerDevice(device)) {
183135c4bbdfSmrg        kbd = GetMaster(device, KEYBOARD_OR_FLOAT);
183235c4bbdfSmrg        mouse = device;
183335c4bbdfSmrg        if (!kbd->key)          /* can happen with floating SDs */
183435c4bbdfSmrg            kbd = NULL;
183535c4bbdfSmrg    }
183635c4bbdfSmrg    else {
183735c4bbdfSmrg        mouse = GetMaster(device, POINTER_OR_FLOAT);
183835c4bbdfSmrg        kbd = device;
183935c4bbdfSmrg        if (!mouse->valuator || !mouse->button) /* may be float. SDs */
184035c4bbdfSmrg            mouse = NULL;
184135c4bbdfSmrg    }
184235c4bbdfSmrg
184335c4bbdfSmrg    corestate = event_get_corestate(mouse, kbd);
184435c4bbdfSmrg    event_set_state(mouse, kbd, event);
184535c4bbdfSmrg
184635c4bbdfSmrg    ret = UpdateDeviceState(device, event);
184735c4bbdfSmrg    if (ret == DONT_PROCESS)
184835c4bbdfSmrg        return;
184935c4bbdfSmrg
185035c4bbdfSmrg    b = device->button;
185135c4bbdfSmrg
185235c4bbdfSmrg    if (IsMaster(device) || IsFloating(device))
185335c4bbdfSmrg        CheckMotion(event, device);
185435c4bbdfSmrg
185535c4bbdfSmrg    switch (event->type) {
185635c4bbdfSmrg    case ET_Motion:
185735c4bbdfSmrg    case ET_ButtonPress:
185835c4bbdfSmrg    case ET_ButtonRelease:
185935c4bbdfSmrg    case ET_KeyPress:
186035c4bbdfSmrg    case ET_KeyRelease:
186135c4bbdfSmrg    case ET_ProximityIn:
186235c4bbdfSmrg    case ET_ProximityOut:
186335c4bbdfSmrg        GetSpritePosition(device, &rootX, &rootY);
186435c4bbdfSmrg        event->root_x = rootX;
186535c4bbdfSmrg        event->root_y = rootY;
186635c4bbdfSmrg        NoticeEventTime((InternalEvent *) event, device);
186735c4bbdfSmrg        event->corestate = corestate;
186835c4bbdfSmrg        key = event->detail.key;
186935c4bbdfSmrg        break;
187035c4bbdfSmrg    default:
187135c4bbdfSmrg        break;
187235c4bbdfSmrg    }
187335c4bbdfSmrg
187435c4bbdfSmrg    /* send KeyPress and KeyRelease events to XACE plugins */
187535c4bbdfSmrg    if (XaceHookIsSet(XACE_KEY_AVAIL) &&
187635c4bbdfSmrg            (event->type == ET_KeyPress || event->type == ET_KeyRelease)) {
187735c4bbdfSmrg        xEvent *core;
187835c4bbdfSmrg        int count;
187935c4bbdfSmrg
188035c4bbdfSmrg        if (EventToCore(ev, &core, &count) == Success && count > 0) {
188135c4bbdfSmrg            XaceHook(XACE_KEY_AVAIL, core, device, 0);
188235c4bbdfSmrg            free(core);
188335c4bbdfSmrg        }
188435c4bbdfSmrg    }
188535c4bbdfSmrg
188635c4bbdfSmrg    if (DeviceEventCallback && !syncEvents.playingEvents) {
188735c4bbdfSmrg        DeviceEventInfoRec eventinfo;
188835c4bbdfSmrg        SpritePtr pSprite = device->spriteInfo->sprite;
188935c4bbdfSmrg
189035c4bbdfSmrg        /* see comment in EnqueueEvents regarding the next three lines */
189135c4bbdfSmrg        if (ev->any.type == ET_Motion)
189235c4bbdfSmrg            ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
189335c4bbdfSmrg
189435c4bbdfSmrg        eventinfo.device = device;
189535c4bbdfSmrg        eventinfo.event = ev;
189635c4bbdfSmrg        CallCallbacks(&DeviceEventCallback, (void *) &eventinfo);
189735c4bbdfSmrg    }
189835c4bbdfSmrg
189935c4bbdfSmrg    grab = device->deviceGrab.grab;
190035c4bbdfSmrg
190135c4bbdfSmrg    switch (event->type) {
190235c4bbdfSmrg    case ET_KeyPress:
19031b5d61b8Smrg        /* Don't deliver focus events (e.g. from KeymapNotify when running
19041b5d61b8Smrg         * nested) to clients. */
19051b5d61b8Smrg        if (event->source_type == EVENT_SOURCE_FOCUS)
19061b5d61b8Smrg            return;
1907ed6184dfSmrg        if (!grab && CheckDeviceGrabs(device, ev, 0))
190835c4bbdfSmrg            return;
190935c4bbdfSmrg        break;
191035c4bbdfSmrg    case ET_KeyRelease:
191135c4bbdfSmrg        if (grab && device->deviceGrab.fromPassiveGrab &&
191235c4bbdfSmrg            (key == device->deviceGrab.activatingKey) &&
191335c4bbdfSmrg            GrabIsKeyboardGrab(device->deviceGrab.grab))
191435c4bbdfSmrg            deactivateDeviceGrab = TRUE;
191535c4bbdfSmrg        break;
191635c4bbdfSmrg    case ET_ButtonPress:
191735c4bbdfSmrg        if (b->map[key] == 0)   /* there's no button 0 */
191835c4bbdfSmrg            return;
191935c4bbdfSmrg        event->detail.button = b->map[key];
1920ed6184dfSmrg        if (!grab && CheckDeviceGrabs(device, ev, 0)) {
192135c4bbdfSmrg            /* if a passive grab was activated, the event has been sent
192235c4bbdfSmrg             * already */
192335c4bbdfSmrg            return;
192435c4bbdfSmrg        }
192535c4bbdfSmrg        break;
192635c4bbdfSmrg    case ET_ButtonRelease:
192735c4bbdfSmrg        if (b->map[key] == 0)   /* there's no button 0 */
192835c4bbdfSmrg            return;
192935c4bbdfSmrg        event->detail.button = b->map[key];
193035c4bbdfSmrg        if (grab && !b->buttonsDown &&
193135c4bbdfSmrg            device->deviceGrab.fromPassiveGrab &&
193235c4bbdfSmrg            GrabIsPointerGrab(device->deviceGrab.grab))
193335c4bbdfSmrg            deactivateDeviceGrab = TRUE;
193435c4bbdfSmrg    default:
193535c4bbdfSmrg        break;
193635c4bbdfSmrg    }
193735c4bbdfSmrg
19381b5d61b8Smrg    /* Don't deliver focus events (e.g. from KeymapNotify when running
19391b5d61b8Smrg     * nested) to clients. */
19401b5d61b8Smrg    if (event->source_type != EVENT_SOURCE_FOCUS) {
19411b5d61b8Smrg        if (grab)
19421b5d61b8Smrg            DeliverGrabbedEvent((InternalEvent *) event, device,
19431b5d61b8Smrg                                deactivateDeviceGrab);
19441b5d61b8Smrg        else if (device->focus && !IsPointerEvent(ev))
19451b5d61b8Smrg            DeliverFocusedEvent(device, (InternalEvent *) event,
19461b5d61b8Smrg                                GetSpriteWindow(device));
19471b5d61b8Smrg        else
19481b5d61b8Smrg            DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent *) event,
19491b5d61b8Smrg                                NullGrab, NullWindow, device);
19501b5d61b8Smrg    }
195135c4bbdfSmrg
195235c4bbdfSmrg    if (deactivateDeviceGrab == TRUE) {
195335c4bbdfSmrg        (*device->deviceGrab.DeactivateGrab) (device);
195435c4bbdfSmrg
195535c4bbdfSmrg        if (!IsMaster (device) && !IsFloating (device)) {
195635c4bbdfSmrg            int flags, num_events = 0;
195735c4bbdfSmrg            InternalEvent dce;
195835c4bbdfSmrg
195935c4bbdfSmrg            flags = (IsPointerDevice (device)) ?
196035c4bbdfSmrg                DEVCHANGE_POINTER_EVENT : DEVCHANGE_KEYBOARD_EVENT;
196135c4bbdfSmrg            UpdateFromMaster (&dce, device, flags, &num_events);
196235c4bbdfSmrg            BUG_WARN(num_events > 1);
196335c4bbdfSmrg
196435c4bbdfSmrg            if (num_events == 1)
196535c4bbdfSmrg                ChangeMasterDeviceClasses(GetMaster (device, MASTER_ATTACHED),
196635c4bbdfSmrg                                          &dce.changed_event);
196735c4bbdfSmrg        }
196835c4bbdfSmrg
196935c4bbdfSmrg    }
197035c4bbdfSmrg
197135c4bbdfSmrg    event->detail.key = key;
197235c4bbdfSmrg}
197335c4bbdfSmrg
197435c4bbdfSmrg/**
197535c4bbdfSmrg * Main device event processing function.
197635c4bbdfSmrg * Called from when processing the events from the event queue.
197735c4bbdfSmrg *
197835c4bbdfSmrg */
197935c4bbdfSmrgvoid
198035c4bbdfSmrgProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
198135c4bbdfSmrg{
198235c4bbdfSmrg    verify_internal_event(ev);
198335c4bbdfSmrg
198435c4bbdfSmrg    switch (ev->any.type) {
198535c4bbdfSmrg    case ET_RawKeyPress:
198635c4bbdfSmrg    case ET_RawKeyRelease:
198735c4bbdfSmrg    case ET_RawButtonPress:
198835c4bbdfSmrg    case ET_RawButtonRelease:
198935c4bbdfSmrg    case ET_RawMotion:
199035c4bbdfSmrg    case ET_RawTouchBegin:
199135c4bbdfSmrg    case ET_RawTouchUpdate:
199235c4bbdfSmrg    case ET_RawTouchEnd:
199335c4bbdfSmrg        DeliverRawEvent(&ev->raw_event, device);
199435c4bbdfSmrg        break;
199535c4bbdfSmrg    case ET_TouchBegin:
199635c4bbdfSmrg    case ET_TouchUpdate:
199735c4bbdfSmrg    case ET_TouchEnd:
199835c4bbdfSmrg        ProcessTouchEvent(ev, device);
199935c4bbdfSmrg        break;
200035c4bbdfSmrg    case ET_TouchOwnership:
200135c4bbdfSmrg        /* TouchOwnership events are handled separately from the rest, as they
200235c4bbdfSmrg         * have more complex semantics. */
200335c4bbdfSmrg        ProcessTouchOwnershipEvent(&ev->touch_ownership_event, device);
200435c4bbdfSmrg        break;
200535c4bbdfSmrg    case ET_BarrierHit:
200635c4bbdfSmrg    case ET_BarrierLeave:
200735c4bbdfSmrg        ProcessBarrierEvent(ev, device);
200835c4bbdfSmrg        break;
2009ed6184dfSmrg    case ET_GesturePinchBegin:
2010ed6184dfSmrg    case ET_GesturePinchUpdate:
2011ed6184dfSmrg    case ET_GesturePinchEnd:
2012ed6184dfSmrg    case ET_GestureSwipeBegin:
2013ed6184dfSmrg    case ET_GestureSwipeUpdate:
2014ed6184dfSmrg    case ET_GestureSwipeEnd:
2015ed6184dfSmrg        ProcessGestureEvent(ev, device);
2016ed6184dfSmrg        break;
201735c4bbdfSmrg    default:
201835c4bbdfSmrg        ProcessDeviceEvent(ev, device);
201935c4bbdfSmrg        break;
202035c4bbdfSmrg    }
202135c4bbdfSmrg}
202235c4bbdfSmrg
202335c4bbdfSmrgstatic int
202435c4bbdfSmrgDeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
202535c4bbdfSmrg                       InternalEvent *ev, TouchListener * listener,
202635c4bbdfSmrg                       ClientPtr client, WindowPtr win, GrabPtr grab,
202735c4bbdfSmrg                       XI2Mask *xi2mask)
202835c4bbdfSmrg{
202935c4bbdfSmrg    enum TouchListenerState state;
203035c4bbdfSmrg    int rc = Success;
203135c4bbdfSmrg    Bool has_ownershipmask;
203235c4bbdfSmrg
2033ed6184dfSmrg    if (listener->type == TOUCH_LISTENER_POINTER_REGULAR ||
2034ed6184dfSmrg        listener->type == TOUCH_LISTENER_POINTER_GRAB) {
203535c4bbdfSmrg        rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
203635c4bbdfSmrg                                       grab, xi2mask);
203735c4bbdfSmrg        if (rc == Success) {
2038ed6184dfSmrg            listener->state = TOUCH_LISTENER_IS_OWNER;
203935c4bbdfSmrg            /* async grabs cannot replay, so automatically accept this touch */
2040ed6184dfSmrg            if (listener->type == TOUCH_LISTENER_POINTER_GRAB &&
204135c4bbdfSmrg                dev->deviceGrab.grab &&
204235c4bbdfSmrg                dev->deviceGrab.fromPassiveGrab &&
204335c4bbdfSmrg                dev->deviceGrab.grab->pointerMode == GrabModeAsync)
204435c4bbdfSmrg                ActivateEarlyAccept(dev, ti);
204535c4bbdfSmrg        }
204635c4bbdfSmrg        goto out;
204735c4bbdfSmrg    }
204835c4bbdfSmrg
204935c4bbdfSmrg    has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
205035c4bbdfSmrg
205135c4bbdfSmrg    if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
205235c4bbdfSmrg        rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
205335c4bbdfSmrg    if (!TouchResourceIsOwner(ti, listener->listener)) {
205435c4bbdfSmrg        if (has_ownershipmask)
2055ed6184dfSmrg            state = TOUCH_LISTENER_AWAITING_OWNER;
205635c4bbdfSmrg        else
2057ed6184dfSmrg            state = TOUCH_LISTENER_AWAITING_BEGIN;
205835c4bbdfSmrg    }
205935c4bbdfSmrg    else {
206035c4bbdfSmrg        if (has_ownershipmask)
206135c4bbdfSmrg            TouchSendOwnershipEvent(dev, ti, 0, listener->listener);
206235c4bbdfSmrg
2063ed6184dfSmrg        if (listener->type == TOUCH_LISTENER_REGULAR)
2064ed6184dfSmrg            state = TOUCH_LISTENER_HAS_ACCEPTED;
206535c4bbdfSmrg        else
2066ed6184dfSmrg            state = TOUCH_LISTENER_IS_OWNER;
206735c4bbdfSmrg    }
206835c4bbdfSmrg    listener->state = state;
206935c4bbdfSmrg
207035c4bbdfSmrg out:
207135c4bbdfSmrg    return rc;
207235c4bbdfSmrg}
207335c4bbdfSmrg
207435c4bbdfSmrgstatic int
207535c4bbdfSmrgDeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
207635c4bbdfSmrg                     TouchListener * listener, ClientPtr client,
207735c4bbdfSmrg                     WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
207835c4bbdfSmrg{
207935c4bbdfSmrg    int rc = Success;
208035c4bbdfSmrg
2081ed6184dfSmrg    if (listener->type == TOUCH_LISTENER_POINTER_REGULAR ||
2082ed6184dfSmrg        listener->type == TOUCH_LISTENER_POINTER_GRAB) {
208335c4bbdfSmrg        /* Note: If the active grab was ungrabbed, we already changed the
2084ed6184dfSmrg         * state to TOUCH_LISTENER_HAS_END but still get here. So we mustn't
208535c4bbdfSmrg         * actually send the event.
208635c4bbdfSmrg         * This is part two of the hack in DeactivatePointerGrab
208735c4bbdfSmrg         */
2088ed6184dfSmrg        if (listener->state != TOUCH_LISTENER_HAS_END) {
208935c4bbdfSmrg            rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
209035c4bbdfSmrg                                           grab, xi2mask);
209135c4bbdfSmrg
209235c4bbdfSmrg             /* Once we send a TouchEnd to a legacy listener, we're already well
209335c4bbdfSmrg              * past the accepting/rejecting stage (can only happen on
209435c4bbdfSmrg              * GrabModeSync + replay. This listener now gets the end event,
209535c4bbdfSmrg              * and we can continue.
209635c4bbdfSmrg              */
209735c4bbdfSmrg            if (rc == Success)
2098ed6184dfSmrg                listener->state = TOUCH_LISTENER_HAS_END;
209935c4bbdfSmrg        }
210035c4bbdfSmrg        goto out;
210135c4bbdfSmrg    }
210235c4bbdfSmrg
210335c4bbdfSmrg    /* A client is waiting for the begin, don't give it a TouchEnd */
2104ed6184dfSmrg    if (listener->state == TOUCH_LISTENER_AWAITING_BEGIN) {
2105ed6184dfSmrg        listener->state = TOUCH_LISTENER_HAS_END;
210635c4bbdfSmrg        goto out;
210735c4bbdfSmrg    }
210835c4bbdfSmrg
210935c4bbdfSmrg    /* Event in response to reject */
211035c4bbdfSmrg    if (ev->device_event.flags & TOUCH_REJECT ||
211135c4bbdfSmrg        (ev->device_event.flags & TOUCH_ACCEPT && !TouchResourceIsOwner(ti, listener->listener))) {
211235c4bbdfSmrg        /* Touch has been rejected, or accepted by its owner which is not this listener */
2113ed6184dfSmrg        if (listener->state != TOUCH_LISTENER_HAS_END)
211435c4bbdfSmrg            rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
2115ed6184dfSmrg        listener->state = TOUCH_LISTENER_HAS_END;
211635c4bbdfSmrg    }
211735c4bbdfSmrg    else if (TouchResourceIsOwner(ti, listener->listener)) {
211835c4bbdfSmrg        Bool normal_end = !(ev->device_event.flags & TOUCH_ACCEPT);
211935c4bbdfSmrg
212035c4bbdfSmrg        /* FIXME: what about early acceptance */
2121ed6184dfSmrg        if (normal_end && listener->state != TOUCH_LISTENER_HAS_END)
212235c4bbdfSmrg            rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
212335c4bbdfSmrg
212435c4bbdfSmrg        if ((ti->num_listeners > 1 ||
2125ed6184dfSmrg             (ti->num_grabs > 0 && listener->state != TOUCH_LISTENER_HAS_ACCEPTED)) &&
212635c4bbdfSmrg            (ev->device_event.flags & (TOUCH_ACCEPT | TOUCH_REJECT)) == 0) {
212735c4bbdfSmrg            ev->any.type = ET_TouchUpdate;
212835c4bbdfSmrg            ev->device_event.flags |= TOUCH_PENDING_END;
212935c4bbdfSmrg            ti->pending_finish = TRUE;
213035c4bbdfSmrg        }
213135c4bbdfSmrg
213235c4bbdfSmrg        if (normal_end)
2133ed6184dfSmrg            listener->state = TOUCH_LISTENER_HAS_END;
213435c4bbdfSmrg    }
213535c4bbdfSmrg
213635c4bbdfSmrg out:
213735c4bbdfSmrg    return rc;
213835c4bbdfSmrg}
213935c4bbdfSmrg
214035c4bbdfSmrgstatic int
214135c4bbdfSmrgDeliverTouchEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
214235c4bbdfSmrg                  TouchListener * listener, ClientPtr client,
214335c4bbdfSmrg                  WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
214435c4bbdfSmrg{
214535c4bbdfSmrg    Bool has_ownershipmask = FALSE;
214635c4bbdfSmrg    int rc = Success;
214735c4bbdfSmrg
214835c4bbdfSmrg    if (xi2mask)
214935c4bbdfSmrg        has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
215035c4bbdfSmrg
215135c4bbdfSmrg    if (ev->any.type == ET_TouchOwnership) {
215235c4bbdfSmrg        ev->touch_ownership_event.deviceid = dev->id;
215335c4bbdfSmrg        if (!TouchResourceIsOwner(ti, listener->listener))
215435c4bbdfSmrg            goto out;
215535c4bbdfSmrg        rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
2156ed6184dfSmrg        listener->state = TOUCH_LISTENER_IS_OWNER;
215735c4bbdfSmrg    }
215835c4bbdfSmrg    else
215935c4bbdfSmrg        ev->device_event.deviceid = dev->id;
216035c4bbdfSmrg
216135c4bbdfSmrg    if (ev->any.type == ET_TouchBegin) {
216235c4bbdfSmrg        rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab,
216335c4bbdfSmrg                                    xi2mask);
216435c4bbdfSmrg    }
216535c4bbdfSmrg    else if (ev->any.type == ET_TouchUpdate) {
2166ed6184dfSmrg        if (listener->type == TOUCH_LISTENER_POINTER_REGULAR ||
2167ed6184dfSmrg            listener->type == TOUCH_LISTENER_POINTER_GRAB)
216835c4bbdfSmrg            DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, grab,
216935c4bbdfSmrg                                      xi2mask);
217035c4bbdfSmrg        else if (TouchResourceIsOwner(ti, listener->listener) ||
217135c4bbdfSmrg                 has_ownershipmask)
217235c4bbdfSmrg            rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
217335c4bbdfSmrg    }
217435c4bbdfSmrg    else if (ev->any.type == ET_TouchEnd)
217535c4bbdfSmrg        rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab,
217635c4bbdfSmrg                                  xi2mask);
217735c4bbdfSmrg
217835c4bbdfSmrg out:
217935c4bbdfSmrg    return rc;
218035c4bbdfSmrg}
218135c4bbdfSmrg
218235c4bbdfSmrg/**
218335c4bbdfSmrg * Delivers a touch events to all interested clients.  For TouchBegin events,
218435c4bbdfSmrg * will update ti->listeners, ti->num_listeners, and ti->num_grabs.
218535c4bbdfSmrg * May also mutate ev (type and flags) upon successful delivery.  If
218635c4bbdfSmrg * @resource is non-zero, will only attempt delivery to the owner of that
218735c4bbdfSmrg * resource.
218835c4bbdfSmrg *
218935c4bbdfSmrg * @return TRUE if the event was delivered at least once, FALSE otherwise
219035c4bbdfSmrg */
219135c4bbdfSmrgvoid
219235c4bbdfSmrgDeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
219335c4bbdfSmrg                   InternalEvent *ev, XID resource)
219435c4bbdfSmrg{
219535c4bbdfSmrg    int i;
219635c4bbdfSmrg
219735c4bbdfSmrg    if (ev->any.type == ET_TouchBegin &&
219835c4bbdfSmrg        !(ev->device_event.flags & (TOUCH_CLIENT_ID | TOUCH_REPLAYING)))
219935c4bbdfSmrg        TouchSetupListeners(dev, ti, ev);
220035c4bbdfSmrg
220135c4bbdfSmrg    TouchEventHistoryPush(ti, &ev->device_event);
220235c4bbdfSmrg
220335c4bbdfSmrg    for (i = 0; i < ti->num_listeners; i++) {
220435c4bbdfSmrg        GrabPtr grab = NULL;
220535c4bbdfSmrg        ClientPtr client;
220635c4bbdfSmrg        WindowPtr win;
220735c4bbdfSmrg        XI2Mask *mask;
220835c4bbdfSmrg        TouchListener *listener = &ti->listeners[i];
220935c4bbdfSmrg
221035c4bbdfSmrg        if (resource && listener->listener != resource)
221135c4bbdfSmrg            continue;
221235c4bbdfSmrg
221335c4bbdfSmrg        if (!RetrieveTouchDeliveryData(dev, ti, ev, listener, &client, &win,
221435c4bbdfSmrg                                       &grab, &mask))
221535c4bbdfSmrg            continue;
221635c4bbdfSmrg
221735c4bbdfSmrg        DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask);
221835c4bbdfSmrg    }
221935c4bbdfSmrg}
222035c4bbdfSmrg
2221ed6184dfSmrg/**
2222ed6184dfSmrg * Attempts to deliver a gesture event to the given client.
2223ed6184dfSmrg */
2224ed6184dfSmrgstatic Bool
2225ed6184dfSmrgDeliverOneGestureEvent(ClientPtr client, DeviceIntPtr dev, GestureInfoPtr gi,
2226ed6184dfSmrg                       GrabPtr grab, WindowPtr win, InternalEvent *ev)
2227ed6184dfSmrg{
2228ed6184dfSmrg    int err;
2229ed6184dfSmrg    xEvent *xi2;
2230ed6184dfSmrg    Mask filter;
2231ed6184dfSmrg    Window child = DeepestSpriteWin(&gi->sprite)->drawable.id;
2232ed6184dfSmrg
2233ed6184dfSmrg    /* If we fail here, we're going to leave a client hanging. */
2234ed6184dfSmrg    err = EventToXI2(ev, &xi2);
2235ed6184dfSmrg    if (err != Success)
2236ed6184dfSmrg        FatalError("[Xi] %s: XI2 conversion failed in %s"
2237ed6184dfSmrg                   " (%d)\n", dev->name, __func__, err);
2238ed6184dfSmrg
2239ed6184dfSmrg    FixUpEventFromWindow(&gi->sprite, xi2, win, child, FALSE);
2240ed6184dfSmrg    filter = GetEventFilter(dev, xi2);
2241ed6184dfSmrg    if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success)
2242ed6184dfSmrg        return FALSE;
2243ed6184dfSmrg    err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab);
2244ed6184dfSmrg    free(xi2);
2245ed6184dfSmrg
2246ed6184dfSmrg    /* Returning the value from TryClientEvents isn't useful, since all our
2247ed6184dfSmrg     * resource-gone cleanups will update the delivery list anyway. */
2248ed6184dfSmrg    return TRUE;
2249ed6184dfSmrg}
2250ed6184dfSmrg
2251ed6184dfSmrg/**
2252ed6184dfSmrg * Given a gesture event and a potential listener, retrieve info needed for processing the event.
2253ed6184dfSmrg *
2254ed6184dfSmrg * @param dev The device generating the gesture event.
2255ed6184dfSmrg * @param ev The gesture event to process.
2256ed6184dfSmrg * @param listener The gesture event listener that may receive the gesture event.
2257ed6184dfSmrg * @param[out] client The client that should receive the gesture event.
2258ed6184dfSmrg * @param[out] win The window to deliver the event on.
2259ed6184dfSmrg * @param[out] grab The grab to deliver the event through, if any.
2260ed6184dfSmrg * @return TRUE if an event should be delivered to the listener, FALSE
2261ed6184dfSmrg *         otherwise.
2262ed6184dfSmrg */
2263ed6184dfSmrgstatic Bool
2264ed6184dfSmrgRetrieveGestureDeliveryData(DeviceIntPtr dev, InternalEvent *ev, GestureListener* listener,
2265ed6184dfSmrg                            ClientPtr *client, WindowPtr *win, GrabPtr *grab)
2266ed6184dfSmrg{
2267ed6184dfSmrg    int rc;
2268ed6184dfSmrg    int evtype;
2269ed6184dfSmrg    InputClients *iclients = NULL;
2270ed6184dfSmrg    *grab = NULL;
2271ed6184dfSmrg
2272ed6184dfSmrg    if (listener->type == GESTURE_LISTENER_GRAB ||
2273ed6184dfSmrg        listener->type == GESTURE_LISTENER_NONGESTURE_GRAB) {
2274ed6184dfSmrg        *grab = listener->grab;
2275ed6184dfSmrg
2276ed6184dfSmrg        BUG_RETURN_VAL(!*grab, FALSE);
2277ed6184dfSmrg
2278ed6184dfSmrg        *client = rClient(*grab);
2279ed6184dfSmrg        *win = (*grab)->window;
2280ed6184dfSmrg    }
2281ed6184dfSmrg    else {
2282ed6184dfSmrg        rc = dixLookupResourceByType((void **) win, listener->listener, listener->resource_type,
2283ed6184dfSmrg                                     serverClient, DixSendAccess);
2284ed6184dfSmrg        if (rc != Success)
2285ed6184dfSmrg            return FALSE;
2286ed6184dfSmrg
2287ed6184dfSmrg        /* note that we only will have XI2 listeners as
2288ed6184dfSmrg           listener->type == GESTURE_LISTENER_REGULAR */
2289ed6184dfSmrg        evtype = GetXI2Type(ev->any.type);
2290ed6184dfSmrg
2291ed6184dfSmrg        nt_list_for_each_entry(iclients, wOtherInputMasks(*win)->inputClients, next)
2292ed6184dfSmrg            if (xi2mask_isset(iclients->xi2mask, dev, evtype))
2293ed6184dfSmrg                break;
2294ed6184dfSmrg
2295ed6184dfSmrg        BUG_RETURN_VAL(!iclients, FALSE);
2296ed6184dfSmrg
2297ed6184dfSmrg        *client = rClient(iclients);
2298ed6184dfSmrg    }
2299ed6184dfSmrg
2300ed6184dfSmrg    return TRUE;
2301ed6184dfSmrg}
2302ed6184dfSmrg
2303ed6184dfSmrg/**
2304ed6184dfSmrg * Delivers a gesture to the owner, if possible and needed. Returns whether
2305ed6184dfSmrg * an event was delivered.
2306ed6184dfSmrg */
2307ed6184dfSmrgBool
2308ed6184dfSmrgDeliverGestureEventToOwner(DeviceIntPtr dev, GestureInfoPtr gi, InternalEvent *ev)
2309ed6184dfSmrg{
2310ed6184dfSmrg    GrabPtr grab = NULL;
2311ed6184dfSmrg    ClientPtr client;
2312ed6184dfSmrg    WindowPtr win;
2313ed6184dfSmrg
2314ed6184dfSmrg    if (!gi->has_listener || gi->listener.type == GESTURE_LISTENER_NONGESTURE_GRAB) {
2315ed6184dfSmrg        return 0;
2316ed6184dfSmrg    }
2317ed6184dfSmrg
2318ed6184dfSmrg    if (!RetrieveGestureDeliveryData(dev, ev, &gi->listener, &client, &win, &grab))
2319ed6184dfSmrg        return 0;
2320ed6184dfSmrg
2321ed6184dfSmrg    ev->gesture_event.deviceid = dev->id;
2322ed6184dfSmrg
2323ed6184dfSmrg    return DeliverOneGestureEvent(client, dev, gi, grab, win, ev);
2324ed6184dfSmrg}
2325ed6184dfSmrg
232635c4bbdfSmrgint
232735c4bbdfSmrgInitProximityClassDeviceStruct(DeviceIntPtr dev)
232835c4bbdfSmrg{
232935c4bbdfSmrg    ProximityClassPtr proxc;
233035c4bbdfSmrg
233135c4bbdfSmrg    BUG_RETURN_VAL(dev == NULL, FALSE);
233235c4bbdfSmrg    BUG_RETURN_VAL(dev->proximity != NULL, FALSE);
233335c4bbdfSmrg
233435c4bbdfSmrg    proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
233535c4bbdfSmrg    if (!proxc)
233635c4bbdfSmrg        return FALSE;
233735c4bbdfSmrg    proxc->sourceid = dev->id;
233835c4bbdfSmrg    proxc->in_proximity = TRUE;
233935c4bbdfSmrg    dev->proximity = proxc;
234035c4bbdfSmrg    return TRUE;
234135c4bbdfSmrg}
234235c4bbdfSmrg
234335c4bbdfSmrg/**
234435c4bbdfSmrg * Initialise the device's valuators. The memory must already be allocated,
23454642e01fSmrg * this function merely inits the matching axis (specified through axnum) to
23464642e01fSmrg * sane values.
23474642e01fSmrg *
23484642e01fSmrg * It is a condition that (minval < maxval).
23494642e01fSmrg *
23504642e01fSmrg * @see InitValuatorClassDeviceStruct
23514642e01fSmrg */
235235c4bbdfSmrgBool
235335c4bbdfSmrgInitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
235435c4bbdfSmrg                       int maxval, int resolution, int min_res, int max_res,
235535c4bbdfSmrg                       int mode)
235605b261ecSmrg{
235705b261ecSmrg    AxisInfoPtr ax;
23584642e01fSmrg
235935c4bbdfSmrg    BUG_RETURN_VAL(dev == NULL, FALSE);
236035c4bbdfSmrg    BUG_RETURN_VAL(dev->valuator == NULL, FALSE);
236135c4bbdfSmrg    BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE);
236235c4bbdfSmrg    BUG_RETURN_VAL(minval > maxval && mode == Absolute, FALSE);
236305b261ecSmrg
236405b261ecSmrg    ax = dev->valuator->axes + axnum;
236505b261ecSmrg
236605b261ecSmrg    ax->min_value = minval;
236705b261ecSmrg    ax->max_value = maxval;
236805b261ecSmrg    ax->resolution = resolution;
236905b261ecSmrg    ax->min_resolution = min_res;
237005b261ecSmrg    ax->max_resolution = max_res;
23716747b715Smrg    ax->label = label;
23729ace9065Smrg    ax->mode = mode;
23739ace9065Smrg
23749ace9065Smrg    if (mode & OutOfProximity)
23759ace9065Smrg        dev->proximity->in_proximity = FALSE;
237605b261ecSmrg
237735c4bbdfSmrg    return SetScrollValuator(dev, axnum, SCROLL_TYPE_NONE, 0, SCROLL_FLAG_NONE);
237805b261ecSmrg}
237905b261ecSmrg
238035c4bbdfSmrg/**
238135c4bbdfSmrg * Set the given axis number as a scrolling valuator.
238235c4bbdfSmrg */
238335c4bbdfSmrgBool
238435c4bbdfSmrgSetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type,
238535c4bbdfSmrg                  double increment, int flags)
238605b261ecSmrg{
238735c4bbdfSmrg    AxisInfoPtr ax;
238835c4bbdfSmrg    int *current_ax;
238935c4bbdfSmrg    InternalEvent dce;
239035c4bbdfSmrg    DeviceIntPtr master;
239135c4bbdfSmrg
239235c4bbdfSmrg    BUG_RETURN_VAL(dev == NULL, FALSE);
239335c4bbdfSmrg    BUG_RETURN_VAL(dev->valuator == NULL, FALSE);
239435c4bbdfSmrg    BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE);
239535c4bbdfSmrg
239635c4bbdfSmrg    switch (type) {
239735c4bbdfSmrg    case SCROLL_TYPE_VERTICAL:
239835c4bbdfSmrg        current_ax = &dev->valuator->v_scroll_axis;
239935c4bbdfSmrg        break;
240035c4bbdfSmrg    case SCROLL_TYPE_HORIZONTAL:
240135c4bbdfSmrg        current_ax = &dev->valuator->h_scroll_axis;
240235c4bbdfSmrg        break;
240335c4bbdfSmrg    case SCROLL_TYPE_NONE:
240435c4bbdfSmrg        ax = &dev->valuator->axes[axnum];
240535c4bbdfSmrg        ax->scroll.type = type;
240635c4bbdfSmrg        return TRUE;
240735c4bbdfSmrg    default:
240835c4bbdfSmrg        return FALSE;
240905b261ecSmrg    }
241005b261ecSmrg
241135c4bbdfSmrg    if (increment == 0.0)
241235c4bbdfSmrg        return FALSE;
24136747b715Smrg
241435c4bbdfSmrg    if (*current_ax != -1 && axnum != *current_ax) {
241535c4bbdfSmrg        ax = &dev->valuator->axes[*current_ax];
241635c4bbdfSmrg        if (ax->scroll.type == type &&
241735c4bbdfSmrg            (flags & SCROLL_FLAG_PREFERRED) &&
241835c4bbdfSmrg            (ax->scroll.flags & SCROLL_FLAG_PREFERRED))
241935c4bbdfSmrg            return FALSE;
24206747b715Smrg    }
242135c4bbdfSmrg    *current_ax = axnum;
242205b261ecSmrg
242335c4bbdfSmrg    ax = &dev->valuator->axes[axnum];
242435c4bbdfSmrg    ax->scroll.type = type;
242535c4bbdfSmrg    ax->scroll.increment = increment;
242635c4bbdfSmrg    ax->scroll.flags = flags;
24276747b715Smrg
242835c4bbdfSmrg    master = GetMaster(dev, MASTER_ATTACHED);
242935c4bbdfSmrg    CreateClassesChangedEvent(&dce, master, dev,
243035c4bbdfSmrg                              DEVCHANGE_POINTER_EVENT |
243135c4bbdfSmrg                              DEVCHANGE_DEVICE_CHANGE);
243235c4bbdfSmrg    XISendDeviceChangedEvent(dev, &dce.changed_event);
24336747b715Smrg
243435c4bbdfSmrg    /* if the current slave is us, update the master. If not, we'll update
243535c4bbdfSmrg     * whenever the next slave switch happens anyway. CMDC sends the event
243635c4bbdfSmrg     * for us */
243735c4bbdfSmrg    if (master && master->lastSlave == dev)
243835c4bbdfSmrg        ChangeMasterDeviceClasses(master, &dce.changed_event);
243905b261ecSmrg
244035c4bbdfSmrg    return TRUE;
244105b261ecSmrg}
244205b261ecSmrg
244305b261ecSmrgint
244435c4bbdfSmrgCheckGrabValues(ClientPtr client, GrabParameters *param)
244505b261ecSmrg{
244635c4bbdfSmrg    if (param->grabtype != CORE &&
244735c4bbdfSmrg        param->grabtype != XI && param->grabtype != XI2) {
24486747b715Smrg        ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
24496747b715Smrg        return BadImplementation;
24506747b715Smrg    }
245105b261ecSmrg
24526747b715Smrg    if ((param->this_device_mode != GrabModeSync) &&
245335c4bbdfSmrg        (param->this_device_mode != GrabModeAsync) &&
245435c4bbdfSmrg        (param->this_device_mode != XIGrabModeTouch)) {
245535c4bbdfSmrg        client->errorValue = param->this_device_mode;
245635c4bbdfSmrg        return BadValue;
245705b261ecSmrg    }
24586747b715Smrg    if ((param->other_devices_mode != GrabModeSync) &&
245935c4bbdfSmrg        (param->other_devices_mode != GrabModeAsync) &&
246035c4bbdfSmrg        (param->other_devices_mode != XIGrabModeTouch)) {
246135c4bbdfSmrg        client->errorValue = param->other_devices_mode;
246235c4bbdfSmrg        return BadValue;
246305b261ecSmrg    }
24646747b715Smrg
246535c4bbdfSmrg    if (param->modifiers != AnyModifier &&
246635c4bbdfSmrg        param->modifiers != XIAnyModifier &&
24676747b715Smrg        (param->modifiers & ~AllModifiersMask)) {
246835c4bbdfSmrg        client->errorValue = param->modifiers;
246935c4bbdfSmrg        return BadValue;
247005b261ecSmrg    }
24716747b715Smrg
24726747b715Smrg    if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
247335c4bbdfSmrg        client->errorValue = param->ownerEvents;
247435c4bbdfSmrg        return BadValue;
247505b261ecSmrg    }
24766747b715Smrg    return Success;
24776747b715Smrg}
24786747b715Smrg
24796747b715Smrgint
24806747b715SmrgGrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
248135c4bbdfSmrg           int button, GrabParameters *param, enum InputLevel grabtype,
248235c4bbdfSmrg           GrabMask *mask)
24836747b715Smrg{
24846747b715Smrg    WindowPtr pWin, confineTo;
24856747b715Smrg    CursorPtr cursor;
24866747b715Smrg    GrabPtr grab;
24876747b715Smrg    int rc, type = -1;
24886747b715Smrg    Mask access_mode = DixGrabAccess;
24896747b715Smrg
24906747b715Smrg    rc = CheckGrabValues(client, param);
249105b261ecSmrg    if (rc != Success)
249235c4bbdfSmrg        return rc;
24936747b715Smrg    if (param->confineTo == None)
249435c4bbdfSmrg        confineTo = NullWindow;
249505b261ecSmrg    else {
249635c4bbdfSmrg        rc = dixLookupWindow(&confineTo, param->confineTo, client,
249735c4bbdfSmrg                             DixSetAttrAccess);
249835c4bbdfSmrg        if (rc != Success)
249935c4bbdfSmrg            return rc;
250005b261ecSmrg    }
25016747b715Smrg    if (param->cursor == None)
250235c4bbdfSmrg        cursor = NullCursor;
250305b261ecSmrg    else {
250435c4bbdfSmrg        rc = dixLookupResourceByType((void **) &cursor, param->cursor,
250535c4bbdfSmrg                                     RT_CURSOR, client, DixUseAccess);
250635c4bbdfSmrg        if (rc != Success) {
250735c4bbdfSmrg            client->errorValue = param->cursor;
250835c4bbdfSmrg            return rc;
250935c4bbdfSmrg        }
251035c4bbdfSmrg        access_mode |= DixForceAccess;
251135c4bbdfSmrg    }
251235c4bbdfSmrg    if (param->this_device_mode == GrabModeSync ||
251335c4bbdfSmrg        param->other_devices_mode == GrabModeSync)
251435c4bbdfSmrg        access_mode |= DixFreezeAccess;
25154642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
25166747b715Smrg    if (rc != Success)
251735c4bbdfSmrg        return rc;
25186747b715Smrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
25194642e01fSmrg    if (rc != Success)
252035c4bbdfSmrg        return rc;
252105b261ecSmrg
252235c4bbdfSmrg    if (grabtype == XI)
25236747b715Smrg        type = DeviceButtonPress;
252435c4bbdfSmrg    else if (grabtype == XI2)
25256747b715Smrg        type = XI_ButtonPress;
25266747b715Smrg
25276747b715Smrg    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
25286747b715Smrg                      mask, param, type, button, confineTo, cursor);
252905b261ecSmrg    if (!grab)
253035c4bbdfSmrg        return BadAlloc;
25314642e01fSmrg    return AddPassiveGrabToList(client, grab);
253205b261ecSmrg}
253305b261ecSmrg
25346747b715Smrg/**
253535c4bbdfSmrg * Grab the given key.
25366747b715Smrg */
253705b261ecSmrgint
25386747b715SmrgGrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
253935c4bbdfSmrg        int key, GrabParameters *param, enum InputLevel grabtype,
254035c4bbdfSmrg        GrabMask *mask)
254105b261ecSmrg{
254205b261ecSmrg    WindowPtr pWin;
254305b261ecSmrg    GrabPtr grab;
254405b261ecSmrg    KeyClassPtr k = dev->key;
25454642e01fSmrg    Mask access_mode = DixGrabAccess;
25466747b715Smrg    int rc, type = -1;
254705b261ecSmrg
25486747b715Smrg    rc = CheckGrabValues(client, param);
25496747b715Smrg    if (rc != Success)
25506747b715Smrg        return rc;
2551475c125cSmrg    if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL)
255235c4bbdfSmrg        return BadMatch;
255335c4bbdfSmrg    if (grabtype == XI) {
25546747b715Smrg        if ((key > k->xkbInfo->desc->max_key_code ||
255535c4bbdfSmrg             key < k->xkbInfo->desc->min_key_code)
255635c4bbdfSmrg            && (key != AnyKey)) {
25576747b715Smrg            client->errorValue = key;
25586747b715Smrg            return BadValue;
25596747b715Smrg        }
25606747b715Smrg        type = DeviceKeyPress;
256135c4bbdfSmrg    }
256235c4bbdfSmrg    else if (grabtype == XI2)
25636747b715Smrg        type = XI_KeyPress;
25646747b715Smrg
25656747b715Smrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
25664642e01fSmrg    if (rc != Success)
256735c4bbdfSmrg        return rc;
256835c4bbdfSmrg    if (param->this_device_mode == GrabModeSync ||
256935c4bbdfSmrg        param->other_devices_mode == GrabModeSync)
257035c4bbdfSmrg        access_mode |= DixFreezeAccess;
25714642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
257205b261ecSmrg    if (rc != Success)
257335c4bbdfSmrg        return rc;
257405b261ecSmrg
25756747b715Smrg    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
25766747b715Smrg                      mask, param, type, key, NULL, NULL);
257705b261ecSmrg    if (!grab)
257835c4bbdfSmrg        return BadAlloc;
25794642e01fSmrg    return AddPassiveGrabToList(client, grab);
258005b261ecSmrg}
258105b261ecSmrg
25826747b715Smrg/* Enter/FocusIn grab */
25836747b715Smrgint
25846747b715SmrgGrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
25856747b715Smrg           GrabParameters *param, GrabMask *mask)
25866747b715Smrg{
25876747b715Smrg    WindowPtr pWin;
25886747b715Smrg    CursorPtr cursor;
25896747b715Smrg    GrabPtr grab;
25906747b715Smrg    Mask access_mode = DixGrabAccess;
25916747b715Smrg    int rc;
25926747b715Smrg
25936747b715Smrg    rc = CheckGrabValues(client, param);
25946747b715Smrg    if (rc != Success)
25956747b715Smrg        return rc;
25966747b715Smrg
25976747b715Smrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
25986747b715Smrg    if (rc != Success)
259935c4bbdfSmrg        return rc;
26006747b715Smrg    if (param->cursor == None)
260135c4bbdfSmrg        cursor = NullCursor;
26026747b715Smrg    else {
260335c4bbdfSmrg        rc = dixLookupResourceByType((void **) &cursor, param->cursor,
260435c4bbdfSmrg                                     RT_CURSOR, client, DixUseAccess);
260535c4bbdfSmrg        if (rc != Success) {
260635c4bbdfSmrg            client->errorValue = param->cursor;
260735c4bbdfSmrg            return rc;
260835c4bbdfSmrg        }
260935c4bbdfSmrg        access_mode |= DixForceAccess;
261035c4bbdfSmrg    }
261135c4bbdfSmrg    if (param->this_device_mode == GrabModeSync ||
261235c4bbdfSmrg        param->other_devices_mode == GrabModeSync)
261335c4bbdfSmrg        access_mode |= DixFreezeAccess;
26146747b715Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
26156747b715Smrg    if (rc != Success)
261635c4bbdfSmrg        return rc;
261735c4bbdfSmrg
261835c4bbdfSmrg    grab = CreateGrab(client->index, dev, dev, pWin, XI2,
261935c4bbdfSmrg                      mask, param,
262035c4bbdfSmrg                      (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn, 0,
262135c4bbdfSmrg                      NULL, cursor);
262235c4bbdfSmrg
262335c4bbdfSmrg    if (!grab)
262435c4bbdfSmrg        return BadAlloc;
262535c4bbdfSmrg
262635c4bbdfSmrg    return AddPassiveGrabToList(client, grab);
262735c4bbdfSmrg}
262835c4bbdfSmrg
262935c4bbdfSmrg/* Touch grab */
263035c4bbdfSmrgint
2631ed6184dfSmrgGrabTouchOrGesture(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
2632ed6184dfSmrg                   int type, GrabParameters *param, GrabMask *mask)
263335c4bbdfSmrg{
263435c4bbdfSmrg    WindowPtr pWin;
263535c4bbdfSmrg    GrabPtr grab;
263635c4bbdfSmrg    int rc;
263735c4bbdfSmrg
263835c4bbdfSmrg    rc = CheckGrabValues(client, param);
263935c4bbdfSmrg    if (rc != Success)
264035c4bbdfSmrg        return rc;
26416747b715Smrg
264235c4bbdfSmrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
264335c4bbdfSmrg    if (rc != Success)
264435c4bbdfSmrg        return rc;
264535c4bbdfSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGrabAccess);
264635c4bbdfSmrg    if (rc != Success)
264735c4bbdfSmrg        return rc;
26486747b715Smrg
264935c4bbdfSmrg    grab = CreateGrab(client->index, dev, mod_dev, pWin, XI2,
2650ed6184dfSmrg                      mask, param, type, 0, NullWindow, NullCursor);
26516747b715Smrg    if (!grab)
26526747b715Smrg        return BadAlloc;
26536747b715Smrg
26546747b715Smrg    return AddPassiveGrabToList(client, grab);
26556747b715Smrg}
26566747b715Smrg
265705b261ecSmrgint
265805b261ecSmrgSelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
265935c4bbdfSmrg                Mask mask, Mask exclusivemasks)
266005b261ecSmrg{
266105b261ecSmrg    int mskidx = dev->id;
266205b261ecSmrg    int i, ret;
266305b261ecSmrg    Mask check;
266405b261ecSmrg    InputClientsPtr others;
266505b261ecSmrg
266605b261ecSmrg    check = (mask & exclusivemasks);
266705b261ecSmrg    if (wOtherInputMasks(pWin)) {
266835c4bbdfSmrg        if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {
266935c4bbdfSmrg            /* It is illegal for two different clients to select on any of
267035c4bbdfSmrg             * the events for maskcheck. However, it is OK, for some client
267135c4bbdfSmrg             * to continue selecting on one of those events.
267235c4bbdfSmrg             */
267335c4bbdfSmrg            for (others = wOtherInputMasks(pWin)->inputClients; others;
267435c4bbdfSmrg                 others = others->next) {
267535c4bbdfSmrg                if (!SameClient(others, client) && (check &
267635c4bbdfSmrg                                                    others->mask[mskidx]))
267735c4bbdfSmrg                    return BadAccess;
267835c4bbdfSmrg            }
267935c4bbdfSmrg        }
268035c4bbdfSmrg        for (others = wOtherInputMasks(pWin)->inputClients; others;
268135c4bbdfSmrg             others = others->next) {
268235c4bbdfSmrg            if (SameClient(others, client)) {
268335c4bbdfSmrg                check = others->mask[mskidx];
268435c4bbdfSmrg                others->mask[mskidx] = mask;
268535c4bbdfSmrg                if (mask == 0) {
268635c4bbdfSmrg                    for (i = 0; i < EMASKSIZE; i++)
268735c4bbdfSmrg                        if (i != mskidx && others->mask[i] != 0)
268835c4bbdfSmrg                            break;
268935c4bbdfSmrg                    if (i == EMASKSIZE) {
269035c4bbdfSmrg                        RecalculateDeviceDeliverableEvents(pWin);
269135c4bbdfSmrg                        if (ShouldFreeInputMasks(pWin, FALSE))
269235c4bbdfSmrg                            FreeResource(others->resource, RT_NONE);
269335c4bbdfSmrg                        return Success;
269435c4bbdfSmrg                    }
269535c4bbdfSmrg                }
269635c4bbdfSmrg                goto maskSet;
269735c4bbdfSmrg            }
269835c4bbdfSmrg        }
269905b261ecSmrg    }
270005b261ecSmrg    check = 0;
270105b261ecSmrg    if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
270235c4bbdfSmrg        return ret;
270335c4bbdfSmrg maskSet:
270405b261ecSmrg    if (dev->valuator)
270535c4bbdfSmrg        if ((dev->valuator->motionHintWindow == pWin) &&
270635c4bbdfSmrg            (mask & DevicePointerMotionHintMask) &&
270735c4bbdfSmrg            !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
270835c4bbdfSmrg            dev->valuator->motionHintWindow = NullWindow;
270905b261ecSmrg    RecalculateDeviceDeliverableEvents(pWin);
271005b261ecSmrg    return Success;
271105b261ecSmrg}
271205b261ecSmrg
271335c4bbdfSmrgstatic void
271435c4bbdfSmrgFreeInputClient(InputClientsPtr * other)
271535c4bbdfSmrg{
271635c4bbdfSmrg    xi2mask_free(&(*other)->xi2mask);
271735c4bbdfSmrg    free(*other);
271835c4bbdfSmrg    *other = NULL;
271935c4bbdfSmrg}
272035c4bbdfSmrg
272135c4bbdfSmrgstatic InputClientsPtr
272235c4bbdfSmrgAllocInputClient(void)
272335c4bbdfSmrg{
272435c4bbdfSmrg    return calloc(1, sizeof(InputClients));
272535c4bbdfSmrg}
272635c4bbdfSmrg
272705b261ecSmrgint
272805b261ecSmrgAddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
272905b261ecSmrg{
273005b261ecSmrg    InputClientsPtr others;
273105b261ecSmrg
273205b261ecSmrg    if (!pWin->optional && !MakeWindowOptional(pWin))
273335c4bbdfSmrg        return BadAlloc;
273435c4bbdfSmrg    others = AllocInputClient();
273505b261ecSmrg    if (!others)
273635c4bbdfSmrg        return BadAlloc;
273705b261ecSmrg    if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
273835c4bbdfSmrg        goto bail;
273935c4bbdfSmrg    others->xi2mask = xi2mask_new();
274035c4bbdfSmrg    if (!others->xi2mask)
274135c4bbdfSmrg        goto bail;
274205b261ecSmrg    others->mask[mskidx] = mask;
274305b261ecSmrg    others->resource = FakeClientID(client->index);
274405b261ecSmrg    others->next = pWin->optional->inputMasks->inputClients;
274505b261ecSmrg    pWin->optional->inputMasks->inputClients = others;
274635c4bbdfSmrg    if (!AddResource(others->resource, RT_INPUTCLIENT, (void *) pWin))
274735c4bbdfSmrg        goto bail;
274805b261ecSmrg    return Success;
27499ace9065Smrg
275035c4bbdfSmrg bail:
275135c4bbdfSmrg    FreeInputClient(&others);
27529ace9065Smrg    return BadAlloc;
275305b261ecSmrg}
275405b261ecSmrg
275505b261ecSmrgstatic Bool
275605b261ecSmrgMakeInputMasks(WindowPtr pWin)
275705b261ecSmrg{
275805b261ecSmrg    struct _OtherInputMasks *imasks;
275905b261ecSmrg
27606747b715Smrg    imasks = calloc(1, sizeof(struct _OtherInputMasks));
276105b261ecSmrg    if (!imasks)
276235c4bbdfSmrg        return FALSE;
276335c4bbdfSmrg    imasks->xi2mask = xi2mask_new();
276435c4bbdfSmrg    if (!imasks->xi2mask) {
276535c4bbdfSmrg        free(imasks);
276635c4bbdfSmrg        return FALSE;
276735c4bbdfSmrg    }
276805b261ecSmrg    pWin->optional->inputMasks = imasks;
276905b261ecSmrg    return TRUE;
277005b261ecSmrg}
277105b261ecSmrg
277235c4bbdfSmrgstatic void
277335c4bbdfSmrgFreeInputMask(OtherInputMasks ** imask)
277435c4bbdfSmrg{
277535c4bbdfSmrg    xi2mask_free(&(*imask)->xi2mask);
277635c4bbdfSmrg    free(*imask);
277735c4bbdfSmrg    *imask = NULL;
277835c4bbdfSmrg}
277935c4bbdfSmrg
2780ed6184dfSmrg#define XIPropagateMask (KeyPressMask | \
2781ed6184dfSmrg                         KeyReleaseMask | \
2782ed6184dfSmrg                         ButtonPressMask | \
2783ed6184dfSmrg                         ButtonReleaseMask | \
2784ed6184dfSmrg                         PointerMotionMask)
2785ed6184dfSmrg
278605b261ecSmrgvoid
278705b261ecSmrgRecalculateDeviceDeliverableEvents(WindowPtr pWin)
278805b261ecSmrg{
278905b261ecSmrg    InputClientsPtr others;
279035c4bbdfSmrg    struct _OtherInputMasks *inputMasks;        /* default: NULL */
279105b261ecSmrg    WindowPtr pChild, tmp;
279235c4bbdfSmrg    int i;
279305b261ecSmrg
279405b261ecSmrg    pChild = pWin;
279505b261ecSmrg    while (1) {
279635c4bbdfSmrg        if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
279735c4bbdfSmrg            xi2mask_zero(inputMasks->xi2mask, -1);
279835c4bbdfSmrg            for (others = inputMasks->inputClients; others;
279935c4bbdfSmrg                 others = others->next) {
28006747b715Smrg                for (i = 0; i < EMASKSIZE; i++)
280135c4bbdfSmrg                    inputMasks->inputEvents[i] |= others->mask[i];
280235c4bbdfSmrg                xi2mask_merge(inputMasks->xi2mask, others->xi2mask);
280335c4bbdfSmrg            }
280435c4bbdfSmrg            for (i = 0; i < EMASKSIZE; i++)
280535c4bbdfSmrg                inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
280635c4bbdfSmrg            for (tmp = pChild->parent; tmp; tmp = tmp->parent)
280735c4bbdfSmrg                if (wOtherInputMasks(tmp))
280835c4bbdfSmrg                    for (i = 0; i < EMASKSIZE; i++)
280935c4bbdfSmrg                        inputMasks->deliverableEvents[i] |=
281035c4bbdfSmrg                            (wOtherInputMasks(tmp)->deliverableEvents[i]
281135c4bbdfSmrg                             & ~inputMasks->dontPropagateMask[i] &
2812ed6184dfSmrg                             XIPropagateMask);
281335c4bbdfSmrg        }
281435c4bbdfSmrg        if (pChild->firstChild) {
281535c4bbdfSmrg            pChild = pChild->firstChild;
281635c4bbdfSmrg            continue;
281735c4bbdfSmrg        }
281835c4bbdfSmrg        while (!pChild->nextSib && (pChild != pWin))
281935c4bbdfSmrg            pChild = pChild->parent;
282035c4bbdfSmrg        if (pChild == pWin)
282135c4bbdfSmrg            break;
282235c4bbdfSmrg        pChild = pChild->nextSib;
282305b261ecSmrg    }
282405b261ecSmrg}
282505b261ecSmrg
282605b261ecSmrgint
282705b261ecSmrgInputClientGone(WindowPtr pWin, XID id)
282805b261ecSmrg{
282905b261ecSmrg    InputClientsPtr other, prev;
283005b261ecSmrg
283105b261ecSmrg    if (!wOtherInputMasks(pWin))
283235c4bbdfSmrg        return Success;
283305b261ecSmrg    prev = 0;
283405b261ecSmrg    for (other = wOtherInputMasks(pWin)->inputClients; other;
283535c4bbdfSmrg         other = other->next) {
283635c4bbdfSmrg        if (other->resource == id) {
283735c4bbdfSmrg            if (prev) {
283835c4bbdfSmrg                prev->next = other->next;
283935c4bbdfSmrg                FreeInputClient(&other);
284035c4bbdfSmrg            }
284135c4bbdfSmrg            else if (!(other->next)) {
284235c4bbdfSmrg                if (ShouldFreeInputMasks(pWin, TRUE)) {
284335c4bbdfSmrg                    OtherInputMasks *mask = wOtherInputMasks(pWin);
284435c4bbdfSmrg
284535c4bbdfSmrg                    mask->inputClients = other->next;
284635c4bbdfSmrg                    FreeInputMask(&mask);
284735c4bbdfSmrg                    pWin->optional->inputMasks = (OtherInputMasks *) NULL;
284835c4bbdfSmrg                    CheckWindowOptionalNeed(pWin);
284935c4bbdfSmrg                    FreeInputClient(&other);
285035c4bbdfSmrg                }
285135c4bbdfSmrg                else {
285235c4bbdfSmrg                    other->resource = FakeClientID(0);
285335c4bbdfSmrg                    if (!AddResource(other->resource, RT_INPUTCLIENT,
285435c4bbdfSmrg                                     (void *) pWin))
285535c4bbdfSmrg                        return BadAlloc;
285635c4bbdfSmrg                }
285735c4bbdfSmrg            }
285835c4bbdfSmrg            else {
285935c4bbdfSmrg                wOtherInputMasks(pWin)->inputClients = other->next;
286035c4bbdfSmrg                FreeInputClient(&other);
286135c4bbdfSmrg            }
286235c4bbdfSmrg            RecalculateDeviceDeliverableEvents(pWin);
286335c4bbdfSmrg            return Success;
286435c4bbdfSmrg        }
286535c4bbdfSmrg        prev = other;
286605b261ecSmrg    }
286705b261ecSmrg    FatalError("client not on device event list");
286805b261ecSmrg}
286905b261ecSmrg
287035c4bbdfSmrg/**
287135c4bbdfSmrg * Search for window in each touch trace for each device. Remove the window
287235c4bbdfSmrg * and all its subwindows from the trace when found. The initial window
287335c4bbdfSmrg * order is preserved.
287435c4bbdfSmrg */
287535c4bbdfSmrgvoid
287635c4bbdfSmrgWindowGone(WindowPtr win)
287735c4bbdfSmrg{
287835c4bbdfSmrg    DeviceIntPtr dev;
287935c4bbdfSmrg
288035c4bbdfSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
288135c4bbdfSmrg        TouchClassPtr t = dev->touch;
288235c4bbdfSmrg        int i;
288335c4bbdfSmrg
288435c4bbdfSmrg        if (!t)
288535c4bbdfSmrg            continue;
288635c4bbdfSmrg
288735c4bbdfSmrg        for (i = 0; i < t->num_touches; i++) {
288835c4bbdfSmrg            SpritePtr sprite = &t->touches[i].sprite;
288935c4bbdfSmrg            int j;
289035c4bbdfSmrg
289135c4bbdfSmrg            for (j = 0; j < sprite->spriteTraceGood; j++) {
289235c4bbdfSmrg                if (sprite->spriteTrace[j] == win) {
289335c4bbdfSmrg                    sprite->spriteTraceGood = j;
289435c4bbdfSmrg                    break;
289535c4bbdfSmrg                }
289635c4bbdfSmrg            }
289735c4bbdfSmrg        }
289835c4bbdfSmrg    }
289935c4bbdfSmrg}
290035c4bbdfSmrg
290105b261ecSmrgint
290205b261ecSmrgSendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
290335c4bbdfSmrg          xEvent *ev, Mask mask, int count)
290405b261ecSmrg{
290505b261ecSmrg    WindowPtr pWin;
290635c4bbdfSmrg    WindowPtr effectiveFocus = NullWindow;      /* only set if dest==InputFocus */
29074642e01fSmrg    WindowPtr spriteWin = GetSpriteWindow(d);
290805b261ecSmrg
290905b261ecSmrg    if (dest == PointerWindow)
291035c4bbdfSmrg        pWin = spriteWin;
291105b261ecSmrg    else if (dest == InputFocus) {
291235c4bbdfSmrg        WindowPtr inputFocus;
291335c4bbdfSmrg
291435c4bbdfSmrg        if (!d->focus)
291535c4bbdfSmrg            inputFocus = spriteWin;
291635c4bbdfSmrg        else
291735c4bbdfSmrg            inputFocus = d->focus->win;
291835c4bbdfSmrg
291935c4bbdfSmrg        if (inputFocus == FollowKeyboardWin)
292035c4bbdfSmrg            inputFocus = inputInfo.keyboard->focus->win;
292135c4bbdfSmrg
292235c4bbdfSmrg        if (inputFocus == NoneWin)
292335c4bbdfSmrg            return Success;
292435c4bbdfSmrg
292535c4bbdfSmrg        /* If the input focus is PointerRootWin, send the event to where
2926ed6184dfSmrg         * the pointer is if possible, then perhaps propagate up to root. */
292735c4bbdfSmrg        if (inputFocus == PointerRootWin)
292835c4bbdfSmrg            inputFocus = GetCurrentRootWindow(d);
292935c4bbdfSmrg
293035c4bbdfSmrg        if (IsParent(inputFocus, spriteWin)) {
293135c4bbdfSmrg            effectiveFocus = inputFocus;
293235c4bbdfSmrg            pWin = spriteWin;
293335c4bbdfSmrg        }
293435c4bbdfSmrg        else
293535c4bbdfSmrg            effectiveFocus = pWin = inputFocus;
293635c4bbdfSmrg    }
293735c4bbdfSmrg    else
293835c4bbdfSmrg        dixLookupWindow(&pWin, dest, client, DixSendAccess);
293905b261ecSmrg    if (!pWin)
294035c4bbdfSmrg        return BadWindow;
294105b261ecSmrg    if ((propagate != xFalse) && (propagate != xTrue)) {
294235c4bbdfSmrg        client->errorValue = propagate;
294335c4bbdfSmrg        return BadValue;
294405b261ecSmrg    }
294505b261ecSmrg    ev->u.u.type |= 0x80;
294605b261ecSmrg    if (propagate) {
294735c4bbdfSmrg        for (; pWin; pWin = pWin->parent) {
294835c4bbdfSmrg            if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
294935c4bbdfSmrg                return Success;
295035c4bbdfSmrg            if (pWin == effectiveFocus)
295135c4bbdfSmrg                return Success;
295235c4bbdfSmrg            if (wOtherInputMasks(pWin))
295335c4bbdfSmrg                mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
295435c4bbdfSmrg            if (!mask)
295535c4bbdfSmrg                break;
295635c4bbdfSmrg        }
295735c4bbdfSmrg    }
295835c4bbdfSmrg    else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
295935c4bbdfSmrg        DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
296005b261ecSmrg    return Success;
296105b261ecSmrg}
296205b261ecSmrg
296305b261ecSmrgint
296405b261ecSmrgSetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
296505b261ecSmrg{
296605b261ecSmrg    int i;
296705b261ecSmrg    ButtonClassPtr b = dev->button;
296805b261ecSmrg
296905b261ecSmrg    if (b == NULL)
297035c4bbdfSmrg        return BadMatch;
297105b261ecSmrg
297205b261ecSmrg    if (nElts != b->numButtons) {
297335c4bbdfSmrg        client->errorValue = nElts;
297435c4bbdfSmrg        return BadValue;
297505b261ecSmrg    }
297605b261ecSmrg    if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
297735c4bbdfSmrg        return BadValue;
297805b261ecSmrg    for (i = 0; i < nElts; i++)
297935c4bbdfSmrg        if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
298035c4bbdfSmrg            return MappingBusy;
298105b261ecSmrg    for (i = 0; i < nElts; i++)
298235c4bbdfSmrg        b->map[i + 1] = map[i];
298305b261ecSmrg    return Success;
298405b261ecSmrg}
298505b261ecSmrg
298605b261ecSmrgint
298705b261ecSmrgChangeKeyMapping(ClientPtr client,
298835c4bbdfSmrg                 DeviceIntPtr dev,
298935c4bbdfSmrg                 unsigned len,
299035c4bbdfSmrg                 int type,
299135c4bbdfSmrg                 KeyCode firstKeyCode,
299235c4bbdfSmrg                 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
299305b261ecSmrg{
299405b261ecSmrg    KeySymsRec keysyms;
299505b261ecSmrg    KeyClassPtr k = dev->key;
299605b261ecSmrg
299705b261ecSmrg    if (k == NULL)
299835c4bbdfSmrg        return BadMatch;
299905b261ecSmrg
300005b261ecSmrg    if (len != (keyCodes * keySymsPerKeyCode))
300135c4bbdfSmrg        return BadLength;
300205b261ecSmrg
30036747b715Smrg    if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
300435c4bbdfSmrg        (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
300535c4bbdfSmrg        client->errorValue = firstKeyCode;
300635c4bbdfSmrg        return BadValue;
300705b261ecSmrg    }
300805b261ecSmrg    if (keySymsPerKeyCode == 0) {
300935c4bbdfSmrg        client->errorValue = 0;
301035c4bbdfSmrg        return BadValue;
301105b261ecSmrg    }
301205b261ecSmrg    keysyms.minKeyCode = firstKeyCode;
301305b261ecSmrg    keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
301405b261ecSmrg    keysyms.mapWidth = keySymsPerKeyCode;
301505b261ecSmrg    keysyms.map = map;
30166747b715Smrg
30176747b715Smrg    XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
30186747b715Smrg                          serverClient);
30196747b715Smrg
30206747b715Smrg    return Success;
302105b261ecSmrg}
302205b261ecSmrg
302305b261ecSmrgstatic void
302405b261ecSmrgDeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
302505b261ecSmrg{
302605b261ecSmrg    WindowPtr parent;
302705b261ecSmrg
302805b261ecSmrg    /* Deactivate any grabs performed on this window, before making
302905b261ecSmrg     * any input focus changes.
303005b261ecSmrg     * Deactivating a device grab should cause focus events. */
303105b261ecSmrg
30324642e01fSmrg    if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
303335c4bbdfSmrg        (*dev->deviceGrab.DeactivateGrab) (dev);
303405b261ecSmrg
30354642e01fSmrg    /* If the focus window is a root window (ie. has no parent)
303605b261ecSmrg     * then don't delete the focus from it. */
303705b261ecSmrg
303805b261ecSmrg    if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
303935c4bbdfSmrg        int focusEventMode = NotifyNormal;
304035c4bbdfSmrg
304135c4bbdfSmrg        /* If a grab is in progress, then alter the mode of focus events. */
304235c4bbdfSmrg
304335c4bbdfSmrg        if (dev->deviceGrab.grab)
304435c4bbdfSmrg            focusEventMode = NotifyWhileGrabbed;
304535c4bbdfSmrg
304635c4bbdfSmrg        switch (dev->focus->revert) {
304735c4bbdfSmrg        case RevertToNone:
304835c4bbdfSmrg            if (!ActivateFocusInGrab(dev, pWin, NoneWin))
304935c4bbdfSmrg                DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
305035c4bbdfSmrg            dev->focus->win = NoneWin;
305135c4bbdfSmrg            dev->focus->traceGood = 0;
305235c4bbdfSmrg            break;
305335c4bbdfSmrg        case RevertToParent:
305435c4bbdfSmrg            parent = pWin;
305535c4bbdfSmrg            do {
305635c4bbdfSmrg                parent = parent->parent;
305735c4bbdfSmrg                dev->focus->traceGood--;
305835c4bbdfSmrg            }
305935c4bbdfSmrg            while (!parent->realized);
306035c4bbdfSmrg            if (!ActivateFocusInGrab(dev, pWin, parent))
306135c4bbdfSmrg                DoFocusEvents(dev, pWin, parent, focusEventMode);
306235c4bbdfSmrg            dev->focus->win = parent;
306335c4bbdfSmrg            dev->focus->revert = RevertToNone;
306435c4bbdfSmrg            break;
306535c4bbdfSmrg        case RevertToPointerRoot:
306635c4bbdfSmrg            if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
306735c4bbdfSmrg                DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
306835c4bbdfSmrg            dev->focus->win = PointerRootWin;
306935c4bbdfSmrg            dev->focus->traceGood = 0;
307035c4bbdfSmrg            break;
307135c4bbdfSmrg        case RevertToFollowKeyboard:
307235c4bbdfSmrg        {
307335c4bbdfSmrg            DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
307435c4bbdfSmrg
307535c4bbdfSmrg            if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
307635c4bbdfSmrg                kbd = inputInfo.keyboard;
307735c4bbdfSmrg            if (kbd->focus->win) {
307835c4bbdfSmrg                if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
307935c4bbdfSmrg                    DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
308035c4bbdfSmrg                dev->focus->win = FollowKeyboardWin;
308135c4bbdfSmrg                dev->focus->traceGood = 0;
308235c4bbdfSmrg            }
308335c4bbdfSmrg            else {
30846747b715Smrg                if (!ActivateFocusInGrab(dev, pWin, NoneWin))
30856747b715Smrg                    DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
308635c4bbdfSmrg                dev->focus->win = NoneWin;
308735c4bbdfSmrg                dev->focus->traceGood = 0;
30886747b715Smrg            }
308935c4bbdfSmrg        }
309035c4bbdfSmrg            break;
309135c4bbdfSmrg        }
309205b261ecSmrg    }
309305b261ecSmrg
309405b261ecSmrg    if (dev->valuator)
309535c4bbdfSmrg        if (dev->valuator->motionHintWindow == pWin)
309635c4bbdfSmrg            dev->valuator->motionHintWindow = NullWindow;
309705b261ecSmrg}
309805b261ecSmrg
309905b261ecSmrgvoid
310005b261ecSmrgDeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
310105b261ecSmrg{
310205b261ecSmrg    int i;
310305b261ecSmrg    DeviceIntPtr dev;
310405b261ecSmrg    InputClientsPtr ic;
310505b261ecSmrg    struct _OtherInputMasks *inputMasks;
310605b261ecSmrg
310705b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
310835c4bbdfSmrg        DeleteDeviceFromAnyExtEvents(pWin, dev);
310905b261ecSmrg    }
311005b261ecSmrg
311105b261ecSmrg    for (dev = inputInfo.off_devices; dev; dev = dev->next)
311235c4bbdfSmrg        DeleteDeviceFromAnyExtEvents(pWin, dev);
311305b261ecSmrg
311405b261ecSmrg    if (freeResources)
311535c4bbdfSmrg        while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
311635c4bbdfSmrg            ic = inputMasks->inputClients;
311735c4bbdfSmrg            for (i = 0; i < EMASKSIZE; i++)
311835c4bbdfSmrg                inputMasks->dontPropagateMask[i] = 0;
311935c4bbdfSmrg            FreeResource(ic->resource, RT_NONE);
312035c4bbdfSmrg        }
312105b261ecSmrg}
312205b261ecSmrg
312305b261ecSmrgint
312435c4bbdfSmrgMaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer *pEvents, Mask mask)
312505b261ecSmrg{
312605b261ecSmrg    DeviceIntPtr dev;
312705b261ecSmrg
31284642e01fSmrg    dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
312935c4bbdfSmrg                    DixReadAccess);
313005b261ecSmrg    if (!dev)
313105b261ecSmrg        return 0;
313205b261ecSmrg
313305b261ecSmrg    if (pEvents->type == DeviceMotionNotify) {
313435c4bbdfSmrg        if (mask & DevicePointerMotionHintMask) {
313535c4bbdfSmrg            if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
313635c4bbdfSmrg                return 1;       /* don't send, but pretend we did */
313735c4bbdfSmrg            }
313835c4bbdfSmrg            pEvents->detail = NotifyHint;
313935c4bbdfSmrg        }
314035c4bbdfSmrg        else {
314135c4bbdfSmrg            pEvents->detail = NotifyNormal;
314235c4bbdfSmrg        }
314305b261ecSmrg    }
31446747b715Smrg    return 0;
314505b261ecSmrg}
314605b261ecSmrg
314705b261ecSmrgvoid
314805b261ecSmrgCheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
314935c4bbdfSmrg                             deviceKeyButtonPointer *xE, GrabPtr grab,
315035c4bbdfSmrg                             ClientPtr client, Mask deliveryMask)
315105b261ecSmrg{
315205b261ecSmrg    DeviceIntPtr dev;
315305b261ecSmrg
31544642e01fSmrg    dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
315535c4bbdfSmrg                    DixGrabAccess);
315605b261ecSmrg    if (!dev)
315705b261ecSmrg        return;
315805b261ecSmrg
315905b261ecSmrg    if (type == DeviceMotionNotify)
316035c4bbdfSmrg        dev->valuator->motionHintWindow = pWin;
316105b261ecSmrg    else if ((type == DeviceButtonPress) && (!grab) &&
316235c4bbdfSmrg             (deliveryMask & DeviceButtonGrabMask)) {
316335c4bbdfSmrg        GrabPtr tempGrab;
316405b261ecSmrg
316535c4bbdfSmrg        tempGrab = AllocGrab(NULL);
316635c4bbdfSmrg        if (!tempGrab)
316735c4bbdfSmrg            return;
316835c4bbdfSmrg
316935c4bbdfSmrg        tempGrab->device = dev;
317035c4bbdfSmrg        tempGrab->resource = client->clientAsMask;
317135c4bbdfSmrg        tempGrab->window = pWin;
317235c4bbdfSmrg        tempGrab->ownerEvents =
317335c4bbdfSmrg            (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
317435c4bbdfSmrg        tempGrab->eventMask = deliveryMask;
317535c4bbdfSmrg        tempGrab->keyboardMode = GrabModeAsync;
317635c4bbdfSmrg        tempGrab->pointerMode = GrabModeAsync;
317735c4bbdfSmrg        tempGrab->confineTo = NullWindow;
317835c4bbdfSmrg        tempGrab->cursor = NullCursor;
317935c4bbdfSmrg        tempGrab->next = NULL;
318035c4bbdfSmrg        (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, currentTime, TRUE);
318135c4bbdfSmrg        FreeGrab(tempGrab);
318205b261ecSmrg    }
318305b261ecSmrg}
318405b261ecSmrg
318505b261ecSmrgstatic Mask
318605b261ecSmrgDeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
318705b261ecSmrg{
318805b261ecSmrg    InputClientsPtr other;
318905b261ecSmrg
319005b261ecSmrg    if (!wOtherInputMasks(pWin))
319135c4bbdfSmrg        return 0;
319205b261ecSmrg    for (other = wOtherInputMasks(pWin)->inputClients; other;
319335c4bbdfSmrg         other = other->next) {
319435c4bbdfSmrg        if (SameClient(other, client))
319535c4bbdfSmrg            return other->mask[dev->id];
319605b261ecSmrg    }
319705b261ecSmrg    return 0;
319805b261ecSmrg}
319905b261ecSmrg
320005b261ecSmrgvoid
320105b261ecSmrgMaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
320205b261ecSmrg{
320305b261ecSmrg    WindowPtr pWin;
32044642e01fSmrg    GrabPtr grab = dev->deviceGrab.grab;
320505b261ecSmrg
320605b261ecSmrg    pWin = dev->valuator->motionHintWindow;
320705b261ecSmrg
320805b261ecSmrg    if ((grab && SameClient(grab, client) &&
320935c4bbdfSmrg         ((grab->eventMask & DevicePointerMotionHintMask) ||
321035c4bbdfSmrg          (grab->ownerEvents &&
321135c4bbdfSmrg           (DeviceEventMaskForClient(dev, pWin, client) &
321235c4bbdfSmrg            DevicePointerMotionHintMask)))) ||
321335c4bbdfSmrg        (!grab &&
321435c4bbdfSmrg         (DeviceEventMaskForClient(dev, pWin, client) &
321535c4bbdfSmrg          DevicePointerMotionHintMask)))
321635c4bbdfSmrg        dev->valuator->motionHintWindow = NullWindow;
321705b261ecSmrg}
321805b261ecSmrg
321905b261ecSmrgint
322005b261ecSmrgDeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
322135c4bbdfSmrg                             int maskndx)
322205b261ecSmrg{
322305b261ecSmrg    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
322405b261ecSmrg
3225ed6184dfSmrg    if (mask & ~XIPropagateMask) {
322635c4bbdfSmrg        client->errorValue = mask;
322735c4bbdfSmrg        return BadValue;
322805b261ecSmrg    }
322905b261ecSmrg
323005b261ecSmrg    if (mask == 0) {
323135c4bbdfSmrg        if (inputMasks)
323235c4bbdfSmrg            inputMasks->dontPropagateMask[maskndx] = mask;
323335c4bbdfSmrg    }
323435c4bbdfSmrg    else {
323535c4bbdfSmrg        if (!inputMasks)
323635c4bbdfSmrg            AddExtensionClient(pWin, client, 0, 0);
323735c4bbdfSmrg        inputMasks = wOtherInputMasks(pWin);
323835c4bbdfSmrg        inputMasks->dontPropagateMask[maskndx] = mask;
323905b261ecSmrg    }
324005b261ecSmrg    RecalculateDeviceDeliverableEvents(pWin);
324105b261ecSmrg    if (ShouldFreeInputMasks(pWin, FALSE))
324235c4bbdfSmrg        FreeResource(inputMasks->inputClients->resource, RT_NONE);
324305b261ecSmrg    return Success;
324405b261ecSmrg}
324505b261ecSmrg
32464642e01fSmrgBool
324705b261ecSmrgShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
324805b261ecSmrg{
324905b261ecSmrg    int i;
325005b261ecSmrg    Mask allInputEventMasks = 0;
325105b261ecSmrg    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
325205b261ecSmrg
325305b261ecSmrg    for (i = 0; i < EMASKSIZE; i++)
325435c4bbdfSmrg        allInputEventMasks |= inputMasks->dontPropagateMask[i];
325505b261ecSmrg    if (!ignoreSelectedEvents)
325635c4bbdfSmrg        for (i = 0; i < EMASKSIZE; i++)
325735c4bbdfSmrg            allInputEventMasks |= inputMasks->inputEvents[i];
325805b261ecSmrg    if (allInputEventMasks == 0)
325935c4bbdfSmrg        return TRUE;
326005b261ecSmrg    else
326135c4bbdfSmrg        return FALSE;
326205b261ecSmrg}
326305b261ecSmrg
326405b261ecSmrg/***********************************************************************
326505b261ecSmrg *
326605b261ecSmrg * Walk through the window tree, finding all clients that want to know
326705b261ecSmrg * about the Event.
326805b261ecSmrg *
326905b261ecSmrg */
327005b261ecSmrg
327105b261ecSmrgstatic void
327205b261ecSmrgFindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
327335c4bbdfSmrg                       xEvent *ev, int count)
327405b261ecSmrg{
327505b261ecSmrg    WindowPtr p2;
327605b261ecSmrg
327705b261ecSmrg    while (p1) {
327805b261ecSmrg        p2 = p1->firstChild;
32796747b715Smrg        DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
328005b261ecSmrg        FindInterestedChildren(dev, p2, mask, ev, count);
328105b261ecSmrg        p1 = p1->nextSib;
328205b261ecSmrg    }
328305b261ecSmrg}
328405b261ecSmrg
328505b261ecSmrg/***********************************************************************
328605b261ecSmrg *
328705b261ecSmrg * Send an event to interested clients in all windows on all screens.
328805b261ecSmrg *
328905b261ecSmrg */
329005b261ecSmrg
329105b261ecSmrgvoid
329235c4bbdfSmrgSendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent *ev, int count)
329305b261ecSmrg{
329405b261ecSmrg    int i;
329505b261ecSmrg    WindowPtr pWin, p1;
329605b261ecSmrg
329705b261ecSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
32986747b715Smrg        pWin = screenInfo.screens[i]->root;
32994642e01fSmrg        if (!pWin)
33004642e01fSmrg            continue;
33016747b715Smrg        DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
330205b261ecSmrg        p1 = pWin->firstChild;
330305b261ecSmrg        FindInterestedChildren(dev, p1, mask, ev, count);
330405b261ecSmrg    }
330505b261ecSmrg}
33064642e01fSmrg
33076747b715Smrg/**
33086747b715Smrg * Set the XI2 mask for the given client on the given window.
33096747b715Smrg * @param dev The device to set the mask for.
33106747b715Smrg * @param win The window to set the mask on.
33116747b715Smrg * @param client The client setting the mask.
33126747b715Smrg * @param len Number of bytes in mask.
33136747b715Smrg * @param mask Event mask in the form of (1 << eventtype)
33146747b715Smrg */
33156747b715Smrgint
33166747b715SmrgXISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
331735c4bbdfSmrg               unsigned int len, unsigned char *mask)
33186747b715Smrg{
33196747b715Smrg    OtherInputMasks *masks;
33206747b715Smrg    InputClientsPtr others = NULL;
33216747b715Smrg
33226747b715Smrg    masks = wOtherInputMasks(win);
332335c4bbdfSmrg    if (masks) {
332435c4bbdfSmrg        for (others = wOtherInputMasks(win)->inputClients; others;
332535c4bbdfSmrg             others = others->next) {
332635c4bbdfSmrg            if (SameClient(others, client)) {
332735c4bbdfSmrg                xi2mask_zero(others->xi2mask, dev->id);
33286747b715Smrg                break;
33296747b715Smrg            }
33306747b715Smrg        }
33316747b715Smrg    }
33326747b715Smrg
333335c4bbdfSmrg    if (len && !others) {
33346747b715Smrg        if (AddExtensionClient(win, client, 0, 0) != Success)
33356747b715Smrg            return BadAlloc;
333635c4bbdfSmrg        others = wOtherInputMasks(win)->inputClients;
33376747b715Smrg    }
33386747b715Smrg
333935c4bbdfSmrg    if (others) {
334035c4bbdfSmrg        xi2mask_zero(others->xi2mask, dev->id);
334135c4bbdfSmrg        len = min(len, xi2mask_mask_size(others->xi2mask));
334235c4bbdfSmrg    }
33436747b715Smrg
334435c4bbdfSmrg    if (len) {
334535c4bbdfSmrg        xi2mask_set_one_mask(others->xi2mask, dev->id, mask, len);
334635c4bbdfSmrg    }
33476747b715Smrg
33486747b715Smrg    RecalculateDeviceDeliverableEvents(win);
33496747b715Smrg
33506747b715Smrg    return Success;
33516747b715Smrg}
3352