exevents.c revision 9ace9065
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
4705b261ecSmrg/********************************************************************
4805b261ecSmrg *
4905b261ecSmrg *  Routines to register and initialize extension input devices.
5005b261ecSmrg *  This also contains ProcessOtherEvent, the routine called from DDX
5105b261ecSmrg *  to route extension events.
5205b261ecSmrg *
5305b261ecSmrg */
5405b261ecSmrg
5505b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
5605b261ecSmrg#include <dix-config.h>
5705b261ecSmrg#endif
5805b261ecSmrg
596747b715Smrg#include "inputstr.h"
6005b261ecSmrg#include <X11/X.h>
6105b261ecSmrg#include <X11/Xproto.h>
6205b261ecSmrg#include <X11/extensions/XI.h>
6305b261ecSmrg#include <X11/extensions/XIproto.h>
646747b715Smrg#include <X11/extensions/XI2proto.h>
654642e01fSmrg#include <X11/extensions/geproto.h>
6605b261ecSmrg#include "windowstr.h"
6705b261ecSmrg#include "miscstruct.h"
6805b261ecSmrg#include "region.h"
6905b261ecSmrg#include "exevents.h"
7005b261ecSmrg#include "extnsionst.h"
7105b261ecSmrg#include "exglobals.h"
7205b261ecSmrg#include "dixevents.h"	/* DeliverFocusedEvent */
7305b261ecSmrg#include "dixgrabs.h"	/* CreateGrab() */
7405b261ecSmrg#include "scrnintstr.h"
754642e01fSmrg#include "listdev.h" /* for CopySwapXXXClass */
764642e01fSmrg#include "xace.h"
776747b715Smrg#include "xiquerydevice.h" /* For List*Info */
786747b715Smrg#include "eventconvert.h"
796747b715Smrg#include "eventstr.h"
8005b261ecSmrg
814642e01fSmrg#include <X11/extensions/XKBproto.h>
8205b261ecSmrg#include "xkbsrv.h"
8305b261ecSmrg
8405b261ecSmrg#define WID(w) ((w) ? ((w)->drawable.id) : 0)
8505b261ecSmrg#define AllModifiersMask ( \
8605b261ecSmrg	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
8705b261ecSmrg	Mod3Mask | Mod4Mask | Mod5Mask )
8805b261ecSmrg#define AllButtonsMask ( \
8905b261ecSmrg	Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
9005b261ecSmrg
914642e01fSmrgBool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
9205b261ecSmrg				 Bool	/* ignoreSelectedEvents */
9305b261ecSmrg    );
9405b261ecSmrgstatic Bool MakeInputMasks(WindowPtr	/* pWin */
9505b261ecSmrg    );
9605b261ecSmrg
976747b715Smrg/*
986747b715Smrg * Only let the given client know of core events which will affect its
996747b715Smrg * interpretation of input events, if the client's ClientPointer (or the
1006747b715Smrg * paired keyboard) is the current device.
1016747b715Smrg */
1026747b715Smrgint
1036747b715SmrgXIShouldNotify(ClientPtr client, DeviceIntPtr dev)
1046747b715Smrg{
1056747b715Smrg    DeviceIntPtr current_ptr = PickPointer(client);
1066747b715Smrg    DeviceIntPtr current_kbd = GetPairedDevice(current_ptr);
1076747b715Smrg
1086747b715Smrg    if (dev == current_kbd || dev == current_ptr)
1096747b715Smrg        return 1;
1104642e01fSmrg
1116747b715Smrg    return 0;
1126747b715Smrg}
11305b261ecSmrg
1144642e01fSmrgBool
1156747b715SmrgIsPointerEvent(InternalEvent* event)
1164642e01fSmrg{
1176747b715Smrg    switch(event->any.type)
1184642e01fSmrg    {
1196747b715Smrg        case ET_ButtonPress:
1206747b715Smrg        case ET_ButtonRelease:
1216747b715Smrg        case ET_Motion:
1226747b715Smrg            /* XXX: enter/leave ?? */
1234642e01fSmrg            return TRUE;
1244642e01fSmrg        default:
1256747b715Smrg            break;
1264642e01fSmrg    }
1274642e01fSmrg    return FALSE;
1284642e01fSmrg}
1294642e01fSmrg
1304642e01fSmrg/**
1314642e01fSmrg * @return the device matching the deviceid of the device set in the event, or
1324642e01fSmrg * NULL if the event is not an XInput event.
1334642e01fSmrg */
1344642e01fSmrgDeviceIntPtr
1354642e01fSmrgXIGetDevice(xEvent* xE)
13605b261ecSmrg{
1374642e01fSmrg    DeviceIntPtr pDev = NULL;
1384642e01fSmrg
1394642e01fSmrg    if (xE->u.u.type == DeviceButtonPress ||
1404642e01fSmrg        xE->u.u.type == DeviceButtonRelease ||
1414642e01fSmrg        xE->u.u.type == DeviceMotionNotify ||
1424642e01fSmrg        xE->u.u.type == ProximityIn ||
1434642e01fSmrg        xE->u.u.type == ProximityOut ||
1444642e01fSmrg        xE->u.u.type == DevicePropertyNotify)
1454642e01fSmrg    {
1464642e01fSmrg        int rc;
1474642e01fSmrg        int id;
1484642e01fSmrg
1494642e01fSmrg        id = ((deviceKeyButtonPointer*)xE)->deviceid & ~MORE_EVENTS;
1504642e01fSmrg
1514642e01fSmrg        rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
1524642e01fSmrg        if (rc != Success)
1534642e01fSmrg            ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
1544642e01fSmrg    }
1554642e01fSmrg    return pDev;
1564642e01fSmrg}
1574642e01fSmrg
1584642e01fSmrg
1594642e01fSmrg/**
1604642e01fSmrg * Copy the device->key into master->key and send a mapping notify to the
1614642e01fSmrg * clients if appropriate.
1624642e01fSmrg * master->key needs to be allocated by the caller.
1634642e01fSmrg *
1644642e01fSmrg * Device is the slave device. If it is attached to a master device, we may
1654642e01fSmrg * need to send a mapping notify to the client because it causes the MD
1664642e01fSmrg * to change state.
1674642e01fSmrg *
1684642e01fSmrg * Mapping notify needs to be sent in the following cases:
1694642e01fSmrg *      - different slave device on same master
1704642e01fSmrg *      - different master
1714642e01fSmrg *
1724642e01fSmrg * XXX: They way how the code is we also send a map notify if the slave device
1734642e01fSmrg * stays the same, but the master changes. This isn't really necessary though.
1744642e01fSmrg *
1754642e01fSmrg * XXX: this gives you funny behaviour with the ClientPointer. When a
1764642e01fSmrg * MappingNotify is sent to the client, the client usually responds with a
1774642e01fSmrg * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
1784642e01fSmrg * mapping, regardless of which keyboard sent the last mapping notify request.
1794642e01fSmrg * So depending on the CP setting, your keyboard may change layout in each
1804642e01fSmrg * app...
1814642e01fSmrg *
1824642e01fSmrg * This code is basically the old SwitchCoreKeyboard.
1834642e01fSmrg */
1844642e01fSmrg
1854642e01fSmrgvoid
1864642e01fSmrgCopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
1874642e01fSmrg{
1886747b715Smrg    KeyClassPtr mk = master->key;
1894642e01fSmrg
1904642e01fSmrg    if (device == master)
1914642e01fSmrg        return;
1924642e01fSmrg
1936747b715Smrg    mk->sourceid = device->id;
1944642e01fSmrg
1954642e01fSmrg
1966747b715Smrg    if (!XkbCopyDeviceKeymap(master, device))
1976747b715Smrg        FatalError("Couldn't pivot keymap from device to core!\n");
1984642e01fSmrg}
19905b261ecSmrg
2004642e01fSmrg/**
2014642e01fSmrg * Copies the feedback classes from device "from" into device "to". Classes
2024642e01fSmrg * are duplicated (not just flipping the pointers). All feedback classes are
2034642e01fSmrg * linked lists, the full list is duplicated.
2044642e01fSmrg */
2054642e01fSmrgstatic void
2064642e01fSmrgDeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
2074642e01fSmrg{
2084642e01fSmrg    ClassesPtr classes;
2094642e01fSmrg
2104642e01fSmrg
2114642e01fSmrg    if (from->intfeed)
2124642e01fSmrg    {
2134642e01fSmrg        IntegerFeedbackPtr *i, it;
2144642e01fSmrg
2154642e01fSmrg        if (!to->intfeed)
2164642e01fSmrg        {
2176747b715Smrg            classes = to->unused_classes;
2184642e01fSmrg            to->intfeed = classes->intfeed;
2196747b715Smrg            classes->intfeed = NULL;
2204642e01fSmrg        }
2214642e01fSmrg
2224642e01fSmrg        i = &to->intfeed;
2234642e01fSmrg        for (it = from->intfeed; it; it = it->next)
2244642e01fSmrg        {
2254642e01fSmrg            if (!(*i))
2264642e01fSmrg            {
2276747b715Smrg                *i = calloc(1, sizeof(IntegerFeedbackClassRec));
2284642e01fSmrg                if (!(*i))
2294642e01fSmrg                {
2304642e01fSmrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
2314642e01fSmrg                    return;
2324642e01fSmrg                }
2334642e01fSmrg            }
2344642e01fSmrg            (*i)->CtrlProc = it->CtrlProc;
2354642e01fSmrg            (*i)->ctrl     = it->ctrl;
2364642e01fSmrg
2374642e01fSmrg            i = &(*i)->next;
2384642e01fSmrg        }
2394642e01fSmrg    } else if (to->intfeed && !from->intfeed)
2404642e01fSmrg    {
2414642e01fSmrg        ClassesPtr classes;
2426747b715Smrg        classes = to->unused_classes;
2434642e01fSmrg        classes->intfeed = to->intfeed;
2444642e01fSmrg        to->intfeed      = NULL;
2454642e01fSmrg    }
2464642e01fSmrg
2474642e01fSmrg    if (from->stringfeed)
2484642e01fSmrg    {
2494642e01fSmrg        StringFeedbackPtr *s, it;
2504642e01fSmrg
2514642e01fSmrg        if (!to->stringfeed)
2524642e01fSmrg        {
2536747b715Smrg            classes = to->unused_classes;
2544642e01fSmrg            to->stringfeed = classes->stringfeed;
2556747b715Smrg            classes->stringfeed = NULL;
2564642e01fSmrg        }
2574642e01fSmrg
2584642e01fSmrg        s = &to->stringfeed;
2594642e01fSmrg        for (it = from->stringfeed; it; it = it->next)
2604642e01fSmrg        {
2614642e01fSmrg            if (!(*s))
2624642e01fSmrg            {
2636747b715Smrg                *s = calloc(1, sizeof(StringFeedbackClassRec));
2644642e01fSmrg                if (!(*s))
2654642e01fSmrg                {
2664642e01fSmrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
2674642e01fSmrg                    return;
2684642e01fSmrg                }
2694642e01fSmrg            }
2704642e01fSmrg            (*s)->CtrlProc = it->CtrlProc;
2714642e01fSmrg            (*s)->ctrl     = it->ctrl;
2724642e01fSmrg
2734642e01fSmrg            s = &(*s)->next;
2744642e01fSmrg        }
2754642e01fSmrg    } else if (to->stringfeed && !from->stringfeed)
2764642e01fSmrg    {
2774642e01fSmrg        ClassesPtr classes;
2786747b715Smrg        classes = to->unused_classes;
2794642e01fSmrg        classes->stringfeed = to->stringfeed;
2804642e01fSmrg        to->stringfeed      = NULL;
2814642e01fSmrg    }
2824642e01fSmrg
2834642e01fSmrg    if (from->bell)
2844642e01fSmrg    {
2854642e01fSmrg        BellFeedbackPtr *b, it;
2864642e01fSmrg
2874642e01fSmrg        if (!to->bell)
2884642e01fSmrg        {
2896747b715Smrg            classes = to->unused_classes;
2904642e01fSmrg            to->bell = classes->bell;
2916747b715Smrg            classes->bell = NULL;
2924642e01fSmrg        }
2934642e01fSmrg
2944642e01fSmrg        b = &to->bell;
2954642e01fSmrg        for (it = from->bell; it; it = it->next)
2964642e01fSmrg        {
2974642e01fSmrg            if (!(*b))
2984642e01fSmrg            {
2996747b715Smrg                *b = calloc(1, sizeof(BellFeedbackClassRec));
3004642e01fSmrg                if (!(*b))
3014642e01fSmrg                {
3024642e01fSmrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
3034642e01fSmrg                    return;
3044642e01fSmrg                }
3054642e01fSmrg            }
3064642e01fSmrg            (*b)->BellProc = it->BellProc;
3074642e01fSmrg            (*b)->CtrlProc = it->CtrlProc;
3084642e01fSmrg            (*b)->ctrl     = it->ctrl;
3094642e01fSmrg
3104642e01fSmrg            b = &(*b)->next;
3114642e01fSmrg        }
3124642e01fSmrg    } else if (to->bell && !from->bell)
3134642e01fSmrg    {
3144642e01fSmrg        ClassesPtr classes;
3156747b715Smrg        classes = to->unused_classes;
3164642e01fSmrg        classes->bell = to->bell;
3174642e01fSmrg        to->bell      = NULL;
3184642e01fSmrg    }
3194642e01fSmrg
3204642e01fSmrg    if (from->leds)
3214642e01fSmrg    {
3224642e01fSmrg        LedFeedbackPtr *l, it;
3234642e01fSmrg
3244642e01fSmrg        if (!to->leds)
3254642e01fSmrg        {
3266747b715Smrg            classes = to->unused_classes;
3274642e01fSmrg            to->leds = classes->leds;
3286747b715Smrg            classes->leds = NULL;
3294642e01fSmrg        }
3304642e01fSmrg
3314642e01fSmrg        l = &to->leds;
3324642e01fSmrg        for (it = from->leds; it; it = it->next)
3334642e01fSmrg        {
3344642e01fSmrg            if (!(*l))
3354642e01fSmrg            {
3366747b715Smrg                *l = calloc(1, sizeof(LedFeedbackClassRec));
3374642e01fSmrg                if (!(*l))
3384642e01fSmrg                {
3394642e01fSmrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
3404642e01fSmrg                    return;
3414642e01fSmrg                }
3424642e01fSmrg            }
3434642e01fSmrg            (*l)->CtrlProc = it->CtrlProc;
3444642e01fSmrg            (*l)->ctrl     = it->ctrl;
3454642e01fSmrg            if ((*l)->xkb_sli)
3464642e01fSmrg                XkbFreeSrvLedInfo((*l)->xkb_sli);
3474642e01fSmrg            (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
3484642e01fSmrg
3494642e01fSmrg            l = &(*l)->next;
3504642e01fSmrg        }
3514642e01fSmrg    } else if (to->leds && !from->leds)
3524642e01fSmrg    {
3534642e01fSmrg        ClassesPtr classes;
3546747b715Smrg        classes = to->unused_classes;
3554642e01fSmrg        classes->leds = to->leds;
3564642e01fSmrg        to->leds      = NULL;
3574642e01fSmrg    }
3584642e01fSmrg}
3594642e01fSmrg
3606747b715Smrgstatic void
3616747b715SmrgDeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
3624642e01fSmrg{
3634642e01fSmrg    ClassesPtr classes;
3644642e01fSmrg
3654642e01fSmrg    /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
3664642e01fSmrg     * kbdfeed to be set up properly, so let's do the feedback classes first.
3674642e01fSmrg     */
3686747b715Smrg    if (from->kbdfeed)
3696747b715Smrg    {
3706747b715Smrg        KbdFeedbackPtr *k, it;
3716747b715Smrg
3726747b715Smrg        if (!to->kbdfeed)
3736747b715Smrg        {
3746747b715Smrg            classes = to->unused_classes;
3756747b715Smrg
3766747b715Smrg            to->kbdfeed = classes->kbdfeed;
3776747b715Smrg            if (!to->kbdfeed)
3786747b715Smrg                InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
3796747b715Smrg            classes->kbdfeed = NULL;
3806747b715Smrg        }
3816747b715Smrg
3826747b715Smrg        k = &to->kbdfeed;
3836747b715Smrg        for(it = from->kbdfeed; it; it = it->next)
3846747b715Smrg        {
3856747b715Smrg            if (!(*k))
3866747b715Smrg            {
3876747b715Smrg                *k = calloc(1, sizeof(KbdFeedbackClassRec));
3886747b715Smrg                if (!*k)
3896747b715Smrg                {
3906747b715Smrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
3916747b715Smrg                    return;
3926747b715Smrg                }
3936747b715Smrg            }
3946747b715Smrg            (*k)->BellProc = it->BellProc;
3956747b715Smrg            (*k)->CtrlProc = it->CtrlProc;
3966747b715Smrg            (*k)->ctrl     = it->ctrl;
3976747b715Smrg            if ((*k)->xkb_sli)
3986747b715Smrg                XkbFreeSrvLedInfo((*k)->xkb_sli);
3996747b715Smrg            (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
4006747b715Smrg
4016747b715Smrg            k = &(*k)->next;
4026747b715Smrg        }
4036747b715Smrg    } else if (to->kbdfeed && !from->kbdfeed)
4046747b715Smrg    {
4056747b715Smrg        ClassesPtr classes;
4066747b715Smrg        classes = to->unused_classes;
4076747b715Smrg        classes->kbdfeed = to->kbdfeed;
4086747b715Smrg        to->kbdfeed      = NULL;
4096747b715Smrg    }
4104642e01fSmrg
4114642e01fSmrg    if (from->key)
4124642e01fSmrg    {
4134642e01fSmrg        if (!to->key)
4144642e01fSmrg        {
4156747b715Smrg            classes = to->unused_classes;
4164642e01fSmrg            to->key = classes->key;
4174642e01fSmrg            if (!to->key)
4186747b715Smrg                InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
4196747b715Smrg            else
4206747b715Smrg                classes->key = NULL;
4216747b715Smrg        }
4226747b715Smrg
4236747b715Smrg        CopyKeyClass(from, to);
4246747b715Smrg    } else if (to->key && !from->key)
4256747b715Smrg    {
4266747b715Smrg        ClassesPtr classes;
4276747b715Smrg        classes = to->unused_classes;
4286747b715Smrg        classes->key = to->key;
4296747b715Smrg        to->key      = NULL;
4306747b715Smrg    }
4316747b715Smrg
4326747b715Smrg    /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps
4336747b715Smrg     * pointer point into the xkbInfo->desc struct.  XkbCopySrvLedInfo
4346747b715Smrg     * didn't update the pointers so we need to do it manually here.
4356747b715Smrg     */
4366747b715Smrg    if (to->kbdfeed)
4376747b715Smrg    {
4386747b715Smrg        KbdFeedbackPtr k;
4396747b715Smrg
4406747b715Smrg        for (k = to->kbdfeed; k; k = k->next)
4416747b715Smrg        {
4426747b715Smrg            if (!k->xkb_sli)
4436747b715Smrg                continue;
4446747b715Smrg            if (k->xkb_sli->flags & XkbSLI_IsDefault)
4454642e01fSmrg            {
4466747b715Smrg                k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators;
4476747b715Smrg                k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps;
4486747b715Smrg            }
4496747b715Smrg        }
4506747b715Smrg    }
4516747b715Smrg
4526747b715Smrg    /* We can't just copy over the focus class. When an app sets the focus,
4536747b715Smrg     * it'll do so on the master device. Copying the SDs focus means losing
4546747b715Smrg     * the focus.
4556747b715Smrg     * So we only copy the focus class if the device didn't have one,
4566747b715Smrg     * otherwise we leave it as it is.
4576747b715Smrg     */
4586747b715Smrg    if (from->focus)
4596747b715Smrg    {
4606747b715Smrg        if (!to->focus)
4616747b715Smrg        {
4626747b715Smrg            WindowPtr *oldTrace;
4636747b715Smrg
4646747b715Smrg            classes = to->unused_classes;
4656747b715Smrg            to->focus = classes->focus;
4666747b715Smrg            if (!to->focus)
4676747b715Smrg            {
4686747b715Smrg                to->focus = calloc(1, sizeof(FocusClassRec));
4696747b715Smrg                if (!to->focus)
4704642e01fSmrg                    FatalError("[Xi] no memory for class shift.\n");
4714642e01fSmrg            } else
4726747b715Smrg                classes->focus = NULL;
4736747b715Smrg
4746747b715Smrg            oldTrace = to->focus->trace;
4756747b715Smrg            memcpy(to->focus, from->focus, sizeof(FocusClassRec));
4766747b715Smrg            to->focus->trace = realloc(oldTrace,
4776747b715Smrg                                  to->focus->traceSize * sizeof(WindowPtr));
4786747b715Smrg            if (!to->focus->trace && to->focus->traceSize)
4796747b715Smrg                FatalError("[Xi] no memory for trace.\n");
4806747b715Smrg            memcpy(to->focus->trace, from->focus->trace,
4816747b715Smrg                    from->focus->traceSize * sizeof(WindowPtr));
4826747b715Smrg            to->focus->sourceid = from->id;
4834642e01fSmrg        }
4846747b715Smrg    } else if (to->focus)
4856747b715Smrg    {
4866747b715Smrg        ClassesPtr classes;
4876747b715Smrg        classes = to->unused_classes;
4886747b715Smrg        classes->focus = to->focus;
4896747b715Smrg        to->focus      = NULL;
4906747b715Smrg    }
4914642e01fSmrg
4926747b715Smrg}
4934642e01fSmrg
4946747b715Smrgstatic void
4956747b715SmrgDeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
4966747b715Smrg{
4976747b715Smrg    ClassesPtr classes;
4986747b715Smrg
4996747b715Smrg    /* Feedback classes must be copied first */
5006747b715Smrg    if (from->ptrfeed)
5016747b715Smrg    {
5026747b715Smrg        PtrFeedbackPtr *p, it;
5036747b715Smrg        if (!to->ptrfeed)
5044642e01fSmrg        {
5056747b715Smrg            classes = to->unused_classes;
5066747b715Smrg            to->ptrfeed = classes->ptrfeed;
5076747b715Smrg            classes->ptrfeed = NULL;
5084642e01fSmrg        }
5094642e01fSmrg
5106747b715Smrg        p = &to->ptrfeed;
5116747b715Smrg        for (it = from->ptrfeed; it; it = it->next)
5126747b715Smrg        {
5136747b715Smrg            if (!(*p))
5146747b715Smrg            {
5156747b715Smrg                *p = calloc(1, sizeof(PtrFeedbackClassRec));
5166747b715Smrg                if (!*p)
5176747b715Smrg                {
5186747b715Smrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
5196747b715Smrg                    return;
5206747b715Smrg                }
5216747b715Smrg            }
5226747b715Smrg            (*p)->CtrlProc = it->CtrlProc;
5236747b715Smrg            (*p)->ctrl     = it->ctrl;
5244642e01fSmrg
5256747b715Smrg            p = &(*p)->next;
5266747b715Smrg        }
5276747b715Smrg    } else if (to->ptrfeed && !from->ptrfeed)
5284642e01fSmrg    {
5294642e01fSmrg        ClassesPtr classes;
5306747b715Smrg        classes = to->unused_classes;
5316747b715Smrg        classes->ptrfeed = to->ptrfeed;
5326747b715Smrg        to->ptrfeed      = NULL;
5334642e01fSmrg    }
5344642e01fSmrg
5354642e01fSmrg    if (from->valuator)
5364642e01fSmrg    {
5374642e01fSmrg        ValuatorClassPtr v;
5389ace9065Smrg
5394642e01fSmrg        if (!to->valuator)
5404642e01fSmrg        {
5416747b715Smrg            classes = to->unused_classes;
5424642e01fSmrg            to->valuator = classes->valuator;
5434642e01fSmrg            if (to->valuator)
5444642e01fSmrg                classes->valuator = NULL;
5454642e01fSmrg        }
5464642e01fSmrg
5479ace9065Smrg        v = AllocValuatorClass(to->valuator, from->valuator->numAxes);
5489ace9065Smrg
5494642e01fSmrg        if (!v)
5504642e01fSmrg            FatalError("[Xi] no memory for class shift.\n");
5514642e01fSmrg
5529ace9065Smrg        to->valuator = v;
5534642e01fSmrg        memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
5544642e01fSmrg
5556747b715Smrg        v->sourceid = from->id;
5564642e01fSmrg    } else if (to->valuator && !from->valuator)
5574642e01fSmrg    {
5584642e01fSmrg        ClassesPtr classes;
5596747b715Smrg        classes = to->unused_classes;
5604642e01fSmrg        classes->valuator = to->valuator;
5614642e01fSmrg        to->valuator      = NULL;
5624642e01fSmrg    }
5634642e01fSmrg
5644642e01fSmrg    if (from->button)
5654642e01fSmrg    {
5664642e01fSmrg        if (!to->button)
5674642e01fSmrg        {
5686747b715Smrg            classes = to->unused_classes;
5694642e01fSmrg            to->button = classes->button;
5704642e01fSmrg            if (!to->button)
5714642e01fSmrg            {
5726747b715Smrg                to->button = calloc(1, sizeof(ButtonClassRec));
5734642e01fSmrg                if (!to->button)
5744642e01fSmrg                    FatalError("[Xi] no memory for class shift.\n");
5754642e01fSmrg            } else
5764642e01fSmrg                classes->button = NULL;
5774642e01fSmrg        }
5784642e01fSmrg
5794642e01fSmrg        if (from->button->xkb_acts)
5804642e01fSmrg        {
5814642e01fSmrg            if (!to->button->xkb_acts)
5824642e01fSmrg            {
5836747b715Smrg                to->button->xkb_acts = calloc(1, sizeof(XkbAction));
5844642e01fSmrg                if (!to->button->xkb_acts)
5854642e01fSmrg                    FatalError("[Xi] not enough memory for xkb_acts.\n");
5864642e01fSmrg            }
5874642e01fSmrg            memcpy(to->button->xkb_acts, from->button->xkb_acts,
5884642e01fSmrg                    sizeof(XkbAction));
5894642e01fSmrg        } else
5906747b715Smrg            free(to->button->xkb_acts);
5916747b715Smrg
5926747b715Smrg         memcpy(to->button->labels, from->button->labels,
5936747b715Smrg                from->button->numButtons * sizeof(Atom));
5946747b715Smrg        to->button->sourceid = from->id;
5954642e01fSmrg    } else if (to->button && !from->button)
5964642e01fSmrg    {
5974642e01fSmrg        ClassesPtr classes;
5986747b715Smrg        classes = to->unused_classes;
5994642e01fSmrg        classes->button = to->button;
6004642e01fSmrg        to->button      = NULL;
6014642e01fSmrg    }
6024642e01fSmrg
6034642e01fSmrg    if (from->proximity)
6044642e01fSmrg    {
6054642e01fSmrg        if (!to->proximity)
6064642e01fSmrg        {
6076747b715Smrg            classes = to->unused_classes;
6084642e01fSmrg            to->proximity = classes->proximity;
6094642e01fSmrg            if (!to->proximity)
6104642e01fSmrg            {
6116747b715Smrg                to->proximity = calloc(1, sizeof(ProximityClassRec));
6124642e01fSmrg                if (!to->proximity)
6134642e01fSmrg                    FatalError("[Xi] no memory for class shift.\n");
6144642e01fSmrg            } else
6154642e01fSmrg                classes->proximity = NULL;
6164642e01fSmrg        }
6174642e01fSmrg        memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
6186747b715Smrg        to->proximity->sourceid = from->id;
6194642e01fSmrg    } else if (to->proximity)
6204642e01fSmrg    {
6214642e01fSmrg        ClassesPtr classes;
6226747b715Smrg        classes = to->unused_classes;
6234642e01fSmrg        classes->proximity = to->proximity;
6244642e01fSmrg        to->proximity      = NULL;
6254642e01fSmrg    }
6264642e01fSmrg
6274642e01fSmrg    if (from->absolute)
6284642e01fSmrg    {
6294642e01fSmrg        if (!to->absolute)
6304642e01fSmrg        {
6316747b715Smrg            classes = to->unused_classes;
6324642e01fSmrg            to->absolute = classes->absolute;
6334642e01fSmrg            if (!to->absolute)
6344642e01fSmrg            {
6356747b715Smrg                to->absolute = calloc(1, sizeof(AbsoluteClassRec));
6364642e01fSmrg                if (!to->absolute)
6374642e01fSmrg                    FatalError("[Xi] no memory for class shift.\n");
6384642e01fSmrg            } else
6394642e01fSmrg                classes->absolute = NULL;
6404642e01fSmrg        }
6414642e01fSmrg        memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec));
6426747b715Smrg        to->absolute->sourceid = from->id;
6434642e01fSmrg    } else if (to->absolute)
6444642e01fSmrg    {
6456747b715Smrg        ClassesPtr classes;
6466747b715Smrg        classes = to->unused_classes;
6476747b715Smrg        classes->absolute = to->absolute;
6486747b715Smrg        to->absolute      = NULL;
6496747b715Smrg    }
6506747b715Smrg}
6516747b715Smrg
6526747b715Smrg/**
6536747b715Smrg * Copies the CONTENT of the classes of device from into the classes in device
6546747b715Smrg * to. From and to are identical after finishing.
6556747b715Smrg *
6566747b715Smrg * If to does not have classes from currenly has, the classes are stored in
6576747b715Smrg * to's devPrivates system. Later, we recover it again from there if needed.
6586747b715Smrg * Saves a few memory allocations.
6596747b715Smrg */
6606747b715Smrgvoid
6616747b715SmrgDeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dce)
6626747b715Smrg{
6636747b715Smrg    /* generic feedback classes, not tied to pointer and/or keyboard */
6646747b715Smrg    DeepCopyFeedbackClasses(from, to);
6656747b715Smrg
6666747b715Smrg    if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
6676747b715Smrg        DeepCopyKeyboardClasses(from, to);
6686747b715Smrg    if ((dce->flags & DEVCHANGE_POINTER_EVENT))
6696747b715Smrg        DeepCopyPointerClasses(from, to);
6706747b715Smrg}
6716747b715Smrg
6726747b715Smrg
6736747b715Smrg/**
6746747b715Smrg * Send an XI2 DeviceChangedEvent to all interested clients.
6756747b715Smrg */
6766747b715Smrgvoid
6776747b715SmrgXISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, DeviceChangedEvent *dce)
6786747b715Smrg{
6796747b715Smrg    xXIDeviceChangedEvent *dcce;
6806747b715Smrg    int rc;
6816747b715Smrg
6826747b715Smrg    rc = EventToXI2((InternalEvent*)dce, (xEvent**)&dcce);
6836747b715Smrg    if (rc != Success)
6846747b715Smrg    {
6856747b715Smrg        ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc);
6866747b715Smrg        return;
6874642e01fSmrg    }
6886747b715Smrg
6896747b715Smrg    /* we don't actually swap if there's a NullClient, swapping is done
6906747b715Smrg     * later when event is delivered. */
6916747b715Smrg    SendEventToAllWindows(master, XI_DeviceChangedMask, (xEvent*)dcce, 1);
6926747b715Smrg    free(dcce);
6934642e01fSmrg}
6944642e01fSmrg
6956747b715Smrgstatic void
6966747b715SmrgChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
6976747b715Smrg{
6986747b715Smrg    DeviceIntPtr slave;
6996747b715Smrg    int rc;
7006747b715Smrg
7016747b715Smrg    /* For now, we don't have devices that change physically. */
7026747b715Smrg    if (!IsMaster(device))
7036747b715Smrg        return;
7046747b715Smrg
7056747b715Smrg    rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
7066747b715Smrg
7076747b715Smrg    if (rc != Success)
7086747b715Smrg        return; /* Device has disappeared */
7096747b715Smrg
7106747b715Smrg    if (!slave->u.master)
7116747b715Smrg        return; /* set floating since the event */
7126747b715Smrg
7136747b715Smrg    if (slave->u.master->id != dce->masterid)
7146747b715Smrg        return; /* not our slave anymore, don't care */
7156747b715Smrg
7166747b715Smrg    /* FIXME: we probably need to send a DCE for the new slave now */
7176747b715Smrg
7186747b715Smrg    device->public.devicePrivate = slave->public.devicePrivate;
7196747b715Smrg
7206747b715Smrg    /* FIXME: the classes may have changed since we generated the event. */
7216747b715Smrg    DeepCopyDeviceClasses(slave, device, dce);
7226747b715Smrg    XISendDeviceChangedEvent(slave, device, dce);
7236747b715Smrg}
7244642e01fSmrg
7254642e01fSmrg/**
7264642e01fSmrg * Update the device state according to the data in the event.
7274642e01fSmrg *
7284642e01fSmrg * return values are
7294642e01fSmrg *   DEFAULT ... process as normal
7304642e01fSmrg *   DONT_PROCESS ... return immediately from caller
7314642e01fSmrg */
7324642e01fSmrg#define DEFAULT 0
7334642e01fSmrg#define DONT_PROCESS 1
7344642e01fSmrgint
7356747b715SmrgUpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
7364642e01fSmrg{
7374642e01fSmrg    int i;
7384642e01fSmrg    int key = 0,
7396747b715Smrg        bit = 0,
7406747b715Smrg        last_valuator;
7414642e01fSmrg
7424642e01fSmrg    KeyClassPtr k       = NULL;
7434642e01fSmrg    ButtonClassPtr b    = NULL;
7444642e01fSmrg    ValuatorClassPtr v  = NULL;
7454642e01fSmrg
7466747b715Smrg    /* This event is always the first we get, before the actual events with
7476747b715Smrg     * the data. However, the way how the DDX is set up, "device" will
7486747b715Smrg     * actually be the slave device that caused the event.
7496747b715Smrg     */
7506747b715Smrg    switch(event->type)
7516747b715Smrg    {
7526747b715Smrg        case ET_DeviceChanged:
7536747b715Smrg            ChangeMasterDeviceClasses(device, (DeviceChangedEvent*)event);
7546747b715Smrg            return DONT_PROCESS; /* event has been sent already */
7556747b715Smrg        case ET_Motion:
7566747b715Smrg        case ET_ButtonPress:
7576747b715Smrg        case ET_ButtonRelease:
7586747b715Smrg        case ET_KeyPress:
7596747b715Smrg        case ET_KeyRelease:
7606747b715Smrg        case ET_ProximityIn:
7616747b715Smrg        case ET_ProximityOut:
7626747b715Smrg            break;
7636747b715Smrg        default:
7646747b715Smrg            /* other events don't update the device */
7656747b715Smrg            return DEFAULT;
7666747b715Smrg    }
7674642e01fSmrg
7684642e01fSmrg    k = device->key;
7694642e01fSmrg    v = device->valuator;
7704642e01fSmrg    b = device->button;
7714642e01fSmrg
7726747b715Smrg    key = event->detail.key;
7736747b715Smrg    bit = 1 << (key & 7);
7744642e01fSmrg
7756747b715Smrg    /* Update device axis */
7766747b715Smrg    /* Check valuators first */
7776747b715Smrg    last_valuator = -1;
7786747b715Smrg    for (i = 0; i < MAX_VALUATORS; i++)
7794642e01fSmrg    {
7806747b715Smrg        if (BitIsOn(&event->valuators.mask, i))
7816747b715Smrg        {
7826747b715Smrg            if (!v)
7836747b715Smrg            {
7846747b715Smrg                ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
7856747b715Smrg                        "Ignoring event.\n", device->name);
7866747b715Smrg                return DONT_PROCESS;
7876747b715Smrg            } else if (v->numAxes < i)
7886747b715Smrg            {
7896747b715Smrg                ErrorF("[Xi] Too many valuators reported for device '%s'. "
7906747b715Smrg                        "Ignoring event.\n", device->name);
7916747b715Smrg                return DONT_PROCESS;
7926747b715Smrg            }
7936747b715Smrg            last_valuator = i;
7946747b715Smrg        }
7954642e01fSmrg    }
7964642e01fSmrg
7976747b715Smrg    for (i = 0; i <= last_valuator && i < v->numAxes; i++)
7986747b715Smrg    {
7996747b715Smrg        if (BitIsOn(&event->valuators.mask, i))
8006747b715Smrg        {
8016747b715Smrg            /* XXX: Relative/Absolute mode */
8026747b715Smrg            v->axisVal[i] = event->valuators.data[i];
8036747b715Smrg            v->axisVal[i] += (event->valuators.data_frac[i] * 1.0f / (1 << 16) / (1 << 16));
8046747b715Smrg        }
8054642e01fSmrg    }
80605b261ecSmrg
8076747b715Smrg    if (event->type == ET_KeyPress) {
80805b261ecSmrg        if (!k)
8094642e01fSmrg            return DONT_PROCESS;
81005b261ecSmrg
8116747b715Smrg	/* don't allow ddx to generate multiple downs, but repeats are okay */
8126747b715Smrg	if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
8136747b715Smrg	    return DONT_PROCESS;
8146747b715Smrg
8154642e01fSmrg	if (device->valuator)
8164642e01fSmrg	    device->valuator->motionHintWindow = NullWindow;
8176747b715Smrg	set_key_down(device, key, KEY_PROCESSED);
8186747b715Smrg    } else if (event->type == ET_KeyRelease) {
81905b261ecSmrg        if (!k)
8204642e01fSmrg            return DONT_PROCESS;
82105b261ecSmrg
8226747b715Smrg	if (!key_is_down(device, key, KEY_PROCESSED))	/* guard against duplicates */
8234642e01fSmrg	    return DONT_PROCESS;
8244642e01fSmrg	if (device->valuator)
8254642e01fSmrg	    device->valuator->motionHintWindow = NullWindow;
8266747b715Smrg	set_key_up(device, key, KEY_PROCESSED);
8276747b715Smrg    } else if (event->type == ET_ButtonPress) {
8286747b715Smrg        Mask mask;
82905b261ecSmrg        if (!b)
8304642e01fSmrg            return DONT_PROCESS;
8314642e01fSmrg
8326747b715Smrg        if (button_is_down(device, key, BUTTON_PROCESSED))
8334642e01fSmrg            return DONT_PROCESS;
8346747b715Smrg
8356747b715Smrg        set_button_down(device, key, BUTTON_PROCESSED);
8364642e01fSmrg	if (device->valuator)
8374642e01fSmrg	    device->valuator->motionHintWindow = NullWindow;
8384642e01fSmrg        if (!b->map[key])
8394642e01fSmrg            return DONT_PROCESS;
8404642e01fSmrg        b->buttonsDown++;
84105b261ecSmrg	b->motionMask = DeviceButtonMotionMask;
8424642e01fSmrg        if (b->map[key] <= 5)
8434642e01fSmrg	    b->state |= (Button1Mask >> 1) << b->map[key];
8446747b715Smrg
8456747b715Smrg        /* Add state and motionMask to the filter for this event */
8466747b715Smrg        mask = DevicePointerMotionMask | b->state | b->motionMask;
8476747b715Smrg        SetMaskForEvent(device->id, mask, DeviceMotionNotify);
8486747b715Smrg        mask = PointerMotionMask | b->state | b->motionMask;
8496747b715Smrg        SetMaskForEvent(device->id, mask, MotionNotify);
8506747b715Smrg    } else if (event->type == ET_ButtonRelease) {
8516747b715Smrg        Mask mask;
85205b261ecSmrg        if (!b)
8534642e01fSmrg            return DONT_PROCESS;
8544642e01fSmrg
8556747b715Smrg        if (!button_is_down(device, key, BUTTON_PROCESSED))
8564642e01fSmrg            return DONT_PROCESS;
8576747b715Smrg        if (IsMaster(device)) {
8584642e01fSmrg            DeviceIntPtr sd;
8594642e01fSmrg
8604642e01fSmrg            /*
8614642e01fSmrg             * Leave the button down if any slave has the
8624642e01fSmrg             * button still down. Note that this depends on the
8634642e01fSmrg             * event being delivered through the slave first
8644642e01fSmrg             */
8654642e01fSmrg            for (sd = inputInfo.devices; sd; sd = sd->next) {
8666747b715Smrg                if (IsMaster(sd) || sd->u.master != device)
8674642e01fSmrg                    continue;
8686747b715Smrg                if (!sd->button)
8696747b715Smrg                    continue;
8708223e2f2Smrg                for (i = 1; i <= sd->button->numButtons; i++)
8718223e2f2Smrg                    if (sd->button->map[i] == key &&
8728223e2f2Smrg                        button_is_down(sd, i, BUTTON_PROCESSED))
8738223e2f2Smrg                        return DONT_PROCESS;
8744642e01fSmrg            }
8754642e01fSmrg        }
8766747b715Smrg        set_button_up(device, key, BUTTON_PROCESSED);
8774642e01fSmrg	if (device->valuator)
8784642e01fSmrg	    device->valuator->motionHintWindow = NullWindow;
8794642e01fSmrg        if (!b->map[key])
8804642e01fSmrg            return DONT_PROCESS;
88105b261ecSmrg        if (b->buttonsDown >= 1 && !--b->buttonsDown)
88205b261ecSmrg	    b->motionMask = 0;
8834642e01fSmrg	if (b->map[key] <= 5)
8844642e01fSmrg	    b->state &= ~((Button1Mask >> 1) << b->map[key]);
8856747b715Smrg
8866747b715Smrg        /* Add state and motionMask to the filter for this event */
8876747b715Smrg        mask = DevicePointerMotionMask | b->state | b->motionMask;
8886747b715Smrg        SetMaskForEvent(device->id, mask, DeviceMotionNotify);
8896747b715Smrg        mask = PointerMotionMask | b->state | b->motionMask;
8906747b715Smrg        SetMaskForEvent(device->id, mask, MotionNotify);
8916747b715Smrg    } else if (event->type == ET_ProximityIn)
8929ace9065Smrg	device->proximity->in_proximity = TRUE;
8936747b715Smrg    else if (event->type == ET_ProximityOut)
8949ace9065Smrg	device->proximity->in_proximity = FALSE;
8954642e01fSmrg
8964642e01fSmrg    return DEFAULT;
8974642e01fSmrg}
8984642e01fSmrg
8996747b715Smrgstatic void
9006747b715SmrgProcessRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
9016747b715Smrg{
9026747b715Smrg    GrabPtr grab = device->deviceGrab.grab;
9036747b715Smrg
9046747b715Smrg    if (grab)
9056747b715Smrg        DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE);
9066747b715Smrg    else { /* deliver to all root windows */
9076747b715Smrg        xEvent *xi;
9086747b715Smrg        int i;
9096747b715Smrg
9106747b715Smrg        i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi);
9116747b715Smrg        if (i != Success)
9126747b715Smrg        {
9136747b715Smrg            ErrorF("[Xi] %s: XI2 conversion failed in ProcessRawEvent (%d)\n",
9146747b715Smrg                    device->name, i);
9156747b715Smrg            return;
9166747b715Smrg        }
9176747b715Smrg
9186747b715Smrg        for (i = 0; i < screenInfo.numScreens; i++)
9196747b715Smrg            DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1,
9206747b715Smrg                                  GetEventFilter(device, xi), NULL);
9216747b715Smrg        free(xi);
9226747b715Smrg    }
9236747b715Smrg}
9246747b715Smrg
9254642e01fSmrg/**
9264642e01fSmrg * Main device event processing function.
9274642e01fSmrg * Called from when processing the events from the event queue.
9284642e01fSmrg *
9294642e01fSmrg */
9304642e01fSmrgvoid
9316747b715SmrgProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
9324642e01fSmrg{
9336747b715Smrg    GrabPtr grab;
9344642e01fSmrg    Bool deactivateDeviceGrab = FALSE;
9354642e01fSmrg    int key = 0, rootX, rootY;
9364642e01fSmrg    ButtonClassPtr b;
9374642e01fSmrg    KeyClassPtr k;
9384642e01fSmrg    ValuatorClassPtr v;
9394642e01fSmrg    int ret = 0;
9406747b715Smrg    int state, i;
9414642e01fSmrg    DeviceIntPtr mouse = NULL, kbd = NULL;
9426747b715Smrg    DeviceEvent *event = &ev->device_event;
9436747b715Smrg
9446747b715Smrg    CHECKEVENT(ev);
9456747b715Smrg
9466747b715Smrg    if (ev->any.type == ET_RawKeyPress ||
9476747b715Smrg        ev->any.type == ET_RawKeyRelease ||
9486747b715Smrg        ev->any.type == ET_RawButtonPress ||
9496747b715Smrg        ev->any.type == ET_RawButtonRelease ||
9506747b715Smrg        ev->any.type == ET_RawMotion)
9516747b715Smrg    {
9526747b715Smrg        ProcessRawEvent(&ev->raw_event, device);
9536747b715Smrg        return;
9546747b715Smrg    }
9554642e01fSmrg
9564642e01fSmrg    if (IsPointerDevice(device))
9574642e01fSmrg    {
9584642e01fSmrg        kbd = GetPairedDevice(device);
9594642e01fSmrg        mouse = device;
9604642e01fSmrg        if (!kbd->key) /* can happen with floating SDs */
9614642e01fSmrg            kbd = NULL;
9624642e01fSmrg    } else
9634642e01fSmrg    {
9644642e01fSmrg        mouse = GetPairedDevice(device);
9654642e01fSmrg        kbd = device;
9664642e01fSmrg        if (!mouse->valuator || !mouse->button) /* may be float. SDs */
9674642e01fSmrg            mouse = NULL;
9684642e01fSmrg    }
9694642e01fSmrg
9704642e01fSmrg    /* State needs to be assembled BEFORE the device is updated. */
9716747b715Smrg    state = (kbd && kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->state) : 0;
9726747b715Smrg    state |= (mouse && mouse->button) ? (mouse->button->state) : 0;
9736747b715Smrg
9746747b715Smrg    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
9756747b715Smrg        if (BitIsOn(mouse->button->down, i))
9766747b715Smrg            SetBit(event->buttons, i);
9776747b715Smrg
9786747b715Smrg    if (kbd && kbd->key)
9796747b715Smrg    {
9806747b715Smrg        XkbStatePtr state;
9816747b715Smrg        /* we need the state before the event happens */
9826747b715Smrg        if (event->type == ET_KeyPress || event->type == ET_KeyRelease)
9836747b715Smrg            state = &kbd->key->xkbInfo->prev_state;
9846747b715Smrg        else
9856747b715Smrg            state = &kbd->key->xkbInfo->state;
9866747b715Smrg
9876747b715Smrg        event->mods.base = state->base_mods;
9886747b715Smrg        event->mods.latched = state->latched_mods;
9896747b715Smrg        event->mods.locked = state->locked_mods;
9906747b715Smrg        event->mods.effective = state->mods;
9916747b715Smrg
9926747b715Smrg        event->group.base = state->base_group;
9936747b715Smrg        event->group.latched = state->latched_group;
9946747b715Smrg        event->group.locked = state->locked_group;
9956747b715Smrg        event->group.effective = state->group;
9966747b715Smrg    }
9974642e01fSmrg
9986747b715Smrg    ret = UpdateDeviceState(device, event);
9994642e01fSmrg    if (ret == DONT_PROCESS)
10004642e01fSmrg        return;
10014642e01fSmrg
10024642e01fSmrg    v = device->valuator;
10034642e01fSmrg    b = device->button;
10044642e01fSmrg    k = device->key;
10054642e01fSmrg
10066747b715Smrg    if (IsMaster(device) || !device->u.master)
10076747b715Smrg        CheckMotion(event, device);
10084642e01fSmrg
10096747b715Smrg    switch (event->type)
10106747b715Smrg    {
10116747b715Smrg        case ET_Motion:
10126747b715Smrg        case ET_ButtonPress:
10136747b715Smrg        case ET_ButtonRelease:
10146747b715Smrg        case ET_KeyPress:
10156747b715Smrg        case ET_KeyRelease:
10166747b715Smrg        case ET_ProximityIn:
10176747b715Smrg        case ET_ProximityOut:
10186747b715Smrg            GetSpritePosition(device, &rootX, &rootY);
10196747b715Smrg            event->root_x = rootX;
10206747b715Smrg            event->root_y = rootY;
10216747b715Smrg            NoticeEventTime((InternalEvent*)event);
10226747b715Smrg            event->corestate = state;
10236747b715Smrg            key = event->detail.key;
10246747b715Smrg            break;
10256747b715Smrg        default:
10266747b715Smrg            break;
10274642e01fSmrg    }
10286747b715Smrg
10296747b715Smrg    if (DeviceEventCallback && !syncEvents.playingEvents) {
10304642e01fSmrg	DeviceEventInfoRec eventinfo;
10316747b715Smrg	SpritePtr pSprite = device->spriteInfo->sprite;
10324642e01fSmrg
10336747b715Smrg	/* see comment in EnqueueEvents regarding the next three lines */
10346747b715Smrg	if (ev->any.type == ET_Motion)
10356747b715Smrg	    ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
10364642e01fSmrg
10376747b715Smrg	eventinfo.device = device;
10386747b715Smrg	eventinfo.event = ev;
10396747b715Smrg	CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
10404642e01fSmrg    }
10414642e01fSmrg
10426747b715Smrg    grab = device->deviceGrab.grab;
10434642e01fSmrg
10446747b715Smrg    switch(event->type)
10456747b715Smrg    {
10466747b715Smrg        case ET_KeyPress:
10476747b715Smrg            if (!grab && CheckDeviceGrabs(device, event, 0)) {
10486747b715Smrg                device->deviceGrab.activatingKey = key;
10496747b715Smrg                return;
10506747b715Smrg            }
10516747b715Smrg            break;
10526747b715Smrg        case ET_KeyRelease:
10536747b715Smrg            if (grab && device->deviceGrab.fromPassiveGrab &&
10546747b715Smrg                (key == device->deviceGrab.activatingKey) &&
10556747b715Smrg                (device->deviceGrab.grab->type == KeyPress ||
10566747b715Smrg                 device->deviceGrab.grab->type == DeviceKeyPress ||
10576747b715Smrg                 device->deviceGrab.grab->type == XI_KeyPress))
10586747b715Smrg                deactivateDeviceGrab = TRUE;
10596747b715Smrg            break;
10606747b715Smrg        case ET_ButtonPress:
10616747b715Smrg            event->detail.button = b->map[key];
10626747b715Smrg            if (!event->detail.button) { /* there's no button 0 */
10636747b715Smrg                event->detail.button = key;
10646747b715Smrg                return;
10656747b715Smrg            }
10666747b715Smrg            if (!grab && CheckDeviceGrabs(device, event, 0))
10676747b715Smrg            {
10686747b715Smrg                /* if a passive grab was activated, the event has been sent
10696747b715Smrg                 * already */
10706747b715Smrg                return;
10716747b715Smrg            }
10726747b715Smrg            break;
10736747b715Smrg        case ET_ButtonRelease:
10746747b715Smrg            event->detail.button = b->map[key];
10756747b715Smrg            if (!event->detail.button) { /* there's no button 0 */
10766747b715Smrg                event->detail.button = key;
10776747b715Smrg                return;
10786747b715Smrg            }
10796747b715Smrg            if (grab && !b->buttonsDown &&
10806747b715Smrg                device->deviceGrab.fromPassiveGrab &&
10816747b715Smrg                (device->deviceGrab.grab->type == ButtonPress ||
10826747b715Smrg                 device->deviceGrab.grab->type == DeviceButtonPress ||
10836747b715Smrg                 device->deviceGrab.grab->type == XI_ButtonPress))
10846747b715Smrg                deactivateDeviceGrab = TRUE;
10856747b715Smrg        default:
10866747b715Smrg            break;
10874642e01fSmrg    }
108805b261ecSmrg
10896747b715Smrg
109005b261ecSmrg    if (grab)
10916747b715Smrg        DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
10926747b715Smrg    else if (device->focus && !IsPointerEvent((InternalEvent*)ev))
10936747b715Smrg        DeliverFocusedEvent(device, (InternalEvent*)event,
10946747b715Smrg                            GetSpriteWindow(device));
109505b261ecSmrg    else
10966747b715Smrg        DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event,
10976747b715Smrg                            NullGrab, NullWindow, device);
109805b261ecSmrg
109905b261ecSmrg    if (deactivateDeviceGrab == TRUE)
11004642e01fSmrg	(*device->deviceGrab.DeactivateGrab) (device);
11016747b715Smrg    event->detail.key = key;
110205b261ecSmrg}
110305b261ecSmrg
11046747b715Smrgint
110505b261ecSmrgInitProximityClassDeviceStruct(DeviceIntPtr dev)
110605b261ecSmrg{
110705b261ecSmrg    ProximityClassPtr proxc;
110805b261ecSmrg
11096747b715Smrg    proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
111005b261ecSmrg    if (!proxc)
111105b261ecSmrg	return FALSE;
11126747b715Smrg    proxc->sourceid = dev->id;
11139ace9065Smrg    proxc->in_proximity = TRUE;
111405b261ecSmrg    dev->proximity = proxc;
111505b261ecSmrg    return TRUE;
111605b261ecSmrg}
111705b261ecSmrg
11184642e01fSmrg/**
11194642e01fSmrg * Initialise the device's valuators. The memory must already be allocated,
11204642e01fSmrg * this function merely inits the matching axis (specified through axnum) to
11214642e01fSmrg * sane values.
11224642e01fSmrg *
11234642e01fSmrg * It is a condition that (minval < maxval).
11244642e01fSmrg *
11254642e01fSmrg * @see InitValuatorClassDeviceStruct
11264642e01fSmrg */
11276747b715Smrgvoid
11286747b715SmrgInitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
11299ace9065Smrg		       int resolution, int min_res, int max_res, int mode)
113005b261ecSmrg{
113105b261ecSmrg    AxisInfoPtr ax;
11324642e01fSmrg
11334642e01fSmrg    if (!dev || !dev->valuator || minval > maxval)
113405b261ecSmrg        return;
11356747b715Smrg    if (axnum >= dev->valuator->numAxes)
11366747b715Smrg        return;
113705b261ecSmrg
113805b261ecSmrg    ax = dev->valuator->axes + axnum;
113905b261ecSmrg
114005b261ecSmrg    ax->min_value = minval;
114105b261ecSmrg    ax->max_value = maxval;
114205b261ecSmrg    ax->resolution = resolution;
114305b261ecSmrg    ax->min_resolution = min_res;
114405b261ecSmrg    ax->max_resolution = max_res;
11456747b715Smrg    ax->label = label;
11469ace9065Smrg    ax->mode = mode;
11479ace9065Smrg
11489ace9065Smrg    if (mode & OutOfProximity)
11499ace9065Smrg        dev->proximity->in_proximity = FALSE;
115005b261ecSmrg}
115105b261ecSmrg
115205b261ecSmrgstatic void
115305b261ecSmrgFixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
115405b261ecSmrg		     ButtonClassPtr b, ValuatorClassPtr v, int first)
115505b261ecSmrg{
115605b261ecSmrg    ev->type = DeviceStateNotify;
115705b261ecSmrg    ev->deviceid = dev->id;
115805b261ecSmrg    ev->time = currentTime.milliseconds;
115905b261ecSmrg    ev->classes_reported = 0;
116005b261ecSmrg    ev->num_keys = 0;
116105b261ecSmrg    ev->num_buttons = 0;
116205b261ecSmrg    ev->num_valuators = 0;
116305b261ecSmrg
116405b261ecSmrg    if (b) {
116505b261ecSmrg	ev->classes_reported |= (1 << ButtonClass);
116605b261ecSmrg	ev->num_buttons = b->numButtons;
11674642e01fSmrg	memcpy((char*)ev->buttons, (char*)b->down, 4);
116805b261ecSmrg    } else if (k) {
116905b261ecSmrg	ev->classes_reported |= (1 << KeyClass);
11706747b715Smrg	ev->num_keys = k->xkbInfo->desc->max_key_code -
11716747b715Smrg                       k->xkbInfo->desc->min_key_code;
117205b261ecSmrg	memmove((char *)&ev->keys[0], (char *)k->down, 4);
117305b261ecSmrg    }
117405b261ecSmrg    if (v) {
117505b261ecSmrg	int nval = v->numAxes - first;
117605b261ecSmrg
117705b261ecSmrg	ev->classes_reported |= (1 << ValuatorClass);
11789ace9065Smrg	ev->classes_reported |= valuator_get_mode(dev, 0) << ModeBitsShift;
117905b261ecSmrg	ev->num_valuators = nval < 3 ? nval : 3;
118005b261ecSmrg	switch (ev->num_valuators) {
118105b261ecSmrg	case 3:
118205b261ecSmrg	    ev->valuator2 = v->axisVal[first + 2];
118305b261ecSmrg	case 2:
118405b261ecSmrg	    ev->valuator1 = v->axisVal[first + 1];
118505b261ecSmrg	case 1:
118605b261ecSmrg	    ev->valuator0 = v->axisVal[first];
118705b261ecSmrg	    break;
118805b261ecSmrg	}
118905b261ecSmrg    }
119005b261ecSmrg}
119105b261ecSmrg
119205b261ecSmrgstatic void
119305b261ecSmrgFixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
119405b261ecSmrg		  int first)
119505b261ecSmrg{
119605b261ecSmrg    int nval = v->numAxes - first;
119705b261ecSmrg
119805b261ecSmrg    ev->type = DeviceValuator;
119905b261ecSmrg    ev->deviceid = dev->id;
120005b261ecSmrg    ev->num_valuators = nval < 3 ? nval : 3;
120105b261ecSmrg    ev->first_valuator = first;
120205b261ecSmrg    switch (ev->num_valuators) {
120305b261ecSmrg    case 3:
120405b261ecSmrg	ev->valuator2 = v->axisVal[first + 2];
120505b261ecSmrg    case 2:
120605b261ecSmrg	ev->valuator1 = v->axisVal[first + 1];
120705b261ecSmrg    case 1:
120805b261ecSmrg	ev->valuator0 = v->axisVal[first];
120905b261ecSmrg	break;
121005b261ecSmrg    }
121105b261ecSmrg    first += ev->num_valuators;
121205b261ecSmrg}
121305b261ecSmrg
121405b261ecSmrgvoid
121505b261ecSmrgDeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
121605b261ecSmrg		 WindowPtr pWin)
121705b261ecSmrg{
121805b261ecSmrg    deviceFocus event;
12196747b715Smrg    xXIFocusInEvent *xi2event;
12206747b715Smrg    DeviceIntPtr mouse;
12216747b715Smrg    int btlen, len, i;
12226747b715Smrg
12236747b715Smrg    mouse = (IsMaster(dev) || dev->u.master) ? GetMaster(dev, MASTER_POINTER) : dev;
12246747b715Smrg
12256747b715Smrg    /* XI 2 event */
12266747b715Smrg    btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
12276747b715Smrg    btlen = bytes_to_int32(btlen);
12286747b715Smrg    len = sizeof(xXIFocusInEvent) + btlen * 4;
12296747b715Smrg
12306747b715Smrg    xi2event = calloc(1, len);
12316747b715Smrg    xi2event->type         = GenericEvent;
12326747b715Smrg    xi2event->extension    = IReqCode;
12336747b715Smrg    xi2event->evtype       = type;
12346747b715Smrg    xi2event->length       = bytes_to_int32(len - sizeof(xEvent));
12356747b715Smrg    xi2event->buttons_len  = btlen;
12366747b715Smrg    xi2event->detail       = detail;
12376747b715Smrg    xi2event->time         = currentTime.milliseconds;
12386747b715Smrg    xi2event->deviceid     = dev->id;
12396747b715Smrg    xi2event->sourceid     = dev->id; /* a device doesn't change focus by itself */
12406747b715Smrg    xi2event->mode         = mode;
12416747b715Smrg    xi2event->root_x       = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
12426747b715Smrg    xi2event->root_y       = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
12436747b715Smrg
12446747b715Smrg    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
12456747b715Smrg        if (BitIsOn(mouse->button->down, i))
12466747b715Smrg            SetBit(&xi2event[1], i);
12476747b715Smrg
12486747b715Smrg    if (dev->key)
12496747b715Smrg    {
12506747b715Smrg        xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods;
12516747b715Smrg        xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods;
12526747b715Smrg        xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods;
12536747b715Smrg        xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods;
12546747b715Smrg
12556747b715Smrg        xi2event->group.base_group = dev->key->xkbInfo->state.base_group;
12566747b715Smrg        xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group;
12576747b715Smrg        xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group;
12586747b715Smrg        xi2event->group.effective_group = dev->key->xkbInfo->state.group;
12596747b715Smrg    }
126005b261ecSmrg
12619ace9065Smrg    FixUpEventFromWindow(dev->spriteInfo->sprite, (xEvent*)xi2event, pWin,
12629ace9065Smrg                         None, FALSE);
126305b261ecSmrg
12646747b715Smrg    DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
12656747b715Smrg                          GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
12666747b715Smrg
12676747b715Smrg    free(xi2event);
12686747b715Smrg
12696747b715Smrg    /* XI 1.x event */
127005b261ecSmrg    event.deviceid = dev->id;
127105b261ecSmrg    event.mode = mode;
12726747b715Smrg    event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
127305b261ecSmrg    event.detail = detail;
127405b261ecSmrg    event.window = pWin->drawable.id;
127505b261ecSmrg    event.time = currentTime.milliseconds;
127605b261ecSmrg
12776747b715Smrg    DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
12786747b715Smrg				DeviceFocusChangeMask, NullGrab);
127905b261ecSmrg
12809ace9065Smrg    if ((event.type == DeviceFocusIn) &&
128105b261ecSmrg	(wOtherInputMasks(pWin)) &&
128205b261ecSmrg	(wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
128305b261ecSmrg    {
128405b261ecSmrg	int evcount = 1;
128505b261ecSmrg	deviceStateNotify *ev, *sev;
128605b261ecSmrg	deviceKeyStateNotify *kev;
128705b261ecSmrg	deviceButtonStateNotify *bev;
128805b261ecSmrg
128905b261ecSmrg	KeyClassPtr k;
129005b261ecSmrg	ButtonClassPtr b;
129105b261ecSmrg	ValuatorClassPtr v;
129205b261ecSmrg	int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
129305b261ecSmrg
129405b261ecSmrg	if ((b = dev->button) != NULL) {
129505b261ecSmrg	    nbuttons = b->numButtons;
129605b261ecSmrg	    if (nbuttons > 32)
129705b261ecSmrg		evcount++;
129805b261ecSmrg	}
129905b261ecSmrg	if ((k = dev->key) != NULL) {
13006747b715Smrg	    nkeys = k->xkbInfo->desc->max_key_code -
13016747b715Smrg                    k->xkbInfo->desc->min_key_code;
130205b261ecSmrg	    if (nkeys > 32)
130305b261ecSmrg		evcount++;
130405b261ecSmrg	    if (nbuttons > 0) {
130505b261ecSmrg		evcount++;
130605b261ecSmrg	    }
130705b261ecSmrg	}
130805b261ecSmrg	if ((v = dev->valuator) != NULL) {
130905b261ecSmrg	    nval = v->numAxes;
131005b261ecSmrg
131105b261ecSmrg	    if (nval > 3)
131205b261ecSmrg		evcount++;
131305b261ecSmrg	    if (nval > 6) {
131405b261ecSmrg		if (!(k && b))
131505b261ecSmrg		    evcount++;
131605b261ecSmrg		if (nval > 9)
131705b261ecSmrg		    evcount += ((nval - 7) / 3);
131805b261ecSmrg	    }
131905b261ecSmrg	}
132005b261ecSmrg
13216747b715Smrg	sev = ev = (deviceStateNotify *) malloc(evcount * sizeof(xEvent));
132205b261ecSmrg	FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
132305b261ecSmrg
132405b261ecSmrg	if (b != NULL) {
132505b261ecSmrg	    FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
132605b261ecSmrg	    first += 3;
132705b261ecSmrg	    nval -= 3;
132805b261ecSmrg	    if (nbuttons > 32) {
132905b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
133005b261ecSmrg		bev = (deviceButtonStateNotify *) ev++;
133105b261ecSmrg		bev->type = DeviceButtonStateNotify;
133205b261ecSmrg		bev->deviceid = dev->id;
13334642e01fSmrg		memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
133405b261ecSmrg	    }
133505b261ecSmrg	    if (nval > 0) {
133605b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
133705b261ecSmrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
133805b261ecSmrg		first += 3;
133905b261ecSmrg		nval -= 3;
134005b261ecSmrg	    }
134105b261ecSmrg	}
134205b261ecSmrg
134305b261ecSmrg	if (k != NULL) {
134405b261ecSmrg	    FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
134505b261ecSmrg	    first += 3;
134605b261ecSmrg	    nval -= 3;
134705b261ecSmrg	    if (nkeys > 32) {
134805b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
134905b261ecSmrg		kev = (deviceKeyStateNotify *) ev++;
135005b261ecSmrg		kev->type = DeviceKeyStateNotify;
135105b261ecSmrg		kev->deviceid = dev->id;
135205b261ecSmrg		memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
135305b261ecSmrg	    }
135405b261ecSmrg	    if (nval > 0) {
135505b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
135605b261ecSmrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
135705b261ecSmrg		first += 3;
135805b261ecSmrg		nval -= 3;
135905b261ecSmrg	    }
136005b261ecSmrg	}
136105b261ecSmrg
136205b261ecSmrg	while (nval > 0) {
136305b261ecSmrg	    FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
136405b261ecSmrg	    first += 3;
136505b261ecSmrg	    nval -= 3;
136605b261ecSmrg	    if (nval > 0) {
136705b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
136805b261ecSmrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
136905b261ecSmrg		first += 3;
137005b261ecSmrg		nval -= 3;
137105b261ecSmrg	    }
137205b261ecSmrg	}
137305b261ecSmrg
13746747b715Smrg	DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
13756747b715Smrg				    DeviceStateNotifyMask, NullGrab);
13766747b715Smrg	free(sev);
137705b261ecSmrg    }
137805b261ecSmrg}
137905b261ecSmrg
138005b261ecSmrgint
13816747b715SmrgCheckGrabValues(ClientPtr client, GrabParameters* param)
138205b261ecSmrg{
13836747b715Smrg    if (param->grabtype != GRABTYPE_CORE &&
13846747b715Smrg        param->grabtype != GRABTYPE_XI &&
13856747b715Smrg        param->grabtype != GRABTYPE_XI2)
13866747b715Smrg    {
13876747b715Smrg        ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
13886747b715Smrg        return BadImplementation;
13896747b715Smrg    }
139005b261ecSmrg
13916747b715Smrg    if ((param->this_device_mode != GrabModeSync) &&
13926747b715Smrg	(param->this_device_mode != GrabModeAsync)) {
13936747b715Smrg	client->errorValue = param->this_device_mode;
139405b261ecSmrg	return BadValue;
139505b261ecSmrg    }
13966747b715Smrg    if ((param->other_devices_mode != GrabModeSync) &&
13976747b715Smrg	(param->other_devices_mode != GrabModeAsync)) {
13986747b715Smrg	client->errorValue = param->other_devices_mode;
139905b261ecSmrg	return BadValue;
140005b261ecSmrg    }
14016747b715Smrg
14026747b715Smrg    if (param->grabtype != GRABTYPE_XI2 && (param->modifiers != AnyModifier) &&
14036747b715Smrg        (param->modifiers & ~AllModifiersMask)) {
14046747b715Smrg	client->errorValue = param->modifiers;
140505b261ecSmrg	return BadValue;
140605b261ecSmrg    }
14076747b715Smrg
14086747b715Smrg    if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
14096747b715Smrg	client->errorValue = param->ownerEvents;
141005b261ecSmrg	return BadValue;
141105b261ecSmrg    }
14126747b715Smrg    return Success;
14136747b715Smrg}
14146747b715Smrg
14156747b715Smrgint
14166747b715SmrgGrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
14176747b715Smrg           int button, GrabParameters *param, GrabType grabtype,
14186747b715Smrg	   GrabMask *mask)
14196747b715Smrg{
14206747b715Smrg    WindowPtr pWin, confineTo;
14216747b715Smrg    CursorPtr cursor;
14226747b715Smrg    GrabPtr grab;
14236747b715Smrg    int rc, type = -1;
14246747b715Smrg    Mask access_mode = DixGrabAccess;
14256747b715Smrg
14266747b715Smrg    rc = CheckGrabValues(client, param);
142705b261ecSmrg    if (rc != Success)
142805b261ecSmrg	return rc;
14296747b715Smrg    if (param->confineTo == None)
143005b261ecSmrg	confineTo = NullWindow;
143105b261ecSmrg    else {
14326747b715Smrg	rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess);
143305b261ecSmrg	if (rc != Success)
143405b261ecSmrg	    return rc;
143505b261ecSmrg    }
14366747b715Smrg    if (param->cursor == None)
143705b261ecSmrg	cursor = NullCursor;
143805b261ecSmrg    else {
14396747b715Smrg	rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
14406747b715Smrg				     RT_CURSOR, client, DixUseAccess);
14414642e01fSmrg	if (rc != Success)
14424642e01fSmrg	{
14436747b715Smrg	    client->errorValue = param->cursor;
14446747b715Smrg	    return rc;
144505b261ecSmrg	}
14464642e01fSmrg	access_mode |= DixForceAccess;
144705b261ecSmrg    }
14486747b715Smrg    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
14494642e01fSmrg	access_mode |= DixFreezeAccess;
14504642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
14516747b715Smrg    if (rc != Success)
14526747b715Smrg	return rc;
14536747b715Smrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
14544642e01fSmrg    if (rc != Success)
14554642e01fSmrg	return rc;
145605b261ecSmrg
14576747b715Smrg    if (grabtype == GRABTYPE_XI)
14586747b715Smrg        type = DeviceButtonPress;
14596747b715Smrg    else if (grabtype == GRABTYPE_XI2)
14606747b715Smrg        type = XI_ButtonPress;
14616747b715Smrg
14626747b715Smrg    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
14636747b715Smrg                      mask, param, type, button, confineTo, cursor);
146405b261ecSmrg    if (!grab)
146505b261ecSmrg	return BadAlloc;
14664642e01fSmrg    return AddPassiveGrabToList(client, grab);
146705b261ecSmrg}
146805b261ecSmrg
14696747b715Smrg/**
14706747b715Smrg * Grab the given key. If grabtype is GRABTYPE_XI, the key is a keycode. If
14716747b715Smrg * grabtype is GRABTYPE_XI2, the key is a keysym.
14726747b715Smrg */
147305b261ecSmrgint
14746747b715SmrgGrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
14756747b715Smrg        int key, GrabParameters *param, GrabType grabtype, GrabMask *mask)
147605b261ecSmrg{
147705b261ecSmrg    WindowPtr pWin;
147805b261ecSmrg    GrabPtr grab;
147905b261ecSmrg    KeyClassPtr k = dev->key;
14804642e01fSmrg    Mask access_mode = DixGrabAccess;
14816747b715Smrg    int rc, type = -1;
148205b261ecSmrg
14836747b715Smrg    rc = CheckGrabValues(client, param);
14846747b715Smrg    if (rc != Success)
14856747b715Smrg        return rc;
148605b261ecSmrg    if (k == NULL)
148705b261ecSmrg	return BadMatch;
14886747b715Smrg    if (grabtype == GRABTYPE_XI)
14896747b715Smrg    {
14906747b715Smrg        if ((key > k->xkbInfo->desc->max_key_code ||
14916747b715Smrg                    key < k->xkbInfo->desc->min_key_code)
14926747b715Smrg                && (key != AnyKey)) {
14936747b715Smrg            client->errorValue = key;
14946747b715Smrg            return BadValue;
14956747b715Smrg        }
14966747b715Smrg        type = DeviceKeyPress;
14976747b715Smrg    } else if (grabtype == GRABTYPE_XI2)
14986747b715Smrg        type = XI_KeyPress;
14996747b715Smrg
15006747b715Smrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
15014642e01fSmrg    if (rc != Success)
15024642e01fSmrg	return rc;
15036747b715Smrg    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
15044642e01fSmrg	access_mode |= DixFreezeAccess;
15054642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
150605b261ecSmrg    if (rc != Success)
150705b261ecSmrg	return rc;
150805b261ecSmrg
15096747b715Smrg    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
15106747b715Smrg                      mask, param, type, key, NULL, NULL);
151105b261ecSmrg    if (!grab)
151205b261ecSmrg	return BadAlloc;
15134642e01fSmrg    return AddPassiveGrabToList(client, grab);
151405b261ecSmrg}
151505b261ecSmrg
15166747b715Smrg/* Enter/FocusIn grab */
15176747b715Smrgint
15186747b715SmrgGrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
15196747b715Smrg           GrabParameters *param, GrabMask *mask)
15206747b715Smrg{
15216747b715Smrg    WindowPtr pWin;
15226747b715Smrg    CursorPtr cursor;
15236747b715Smrg    GrabPtr grab;
15246747b715Smrg    Mask access_mode = DixGrabAccess;
15256747b715Smrg    int rc;
15266747b715Smrg
15276747b715Smrg    rc = CheckGrabValues(client, param);
15286747b715Smrg    if (rc != Success)
15296747b715Smrg        return rc;
15306747b715Smrg
15316747b715Smrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
15326747b715Smrg    if (rc != Success)
15336747b715Smrg	return rc;
15346747b715Smrg    if (param->cursor == None)
15356747b715Smrg	cursor = NullCursor;
15366747b715Smrg    else {
15376747b715Smrg	rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
15386747b715Smrg				     RT_CURSOR, client, DixUseAccess);
15396747b715Smrg	if (rc != Success)
15406747b715Smrg	{
15416747b715Smrg	    client->errorValue = param->cursor;
15426747b715Smrg	    return rc;
15436747b715Smrg	}
15446747b715Smrg	access_mode |= DixForceAccess;
15456747b715Smrg    }
15466747b715Smrg    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
15476747b715Smrg	access_mode |= DixFreezeAccess;
15486747b715Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
15496747b715Smrg    if (rc != Success)
15506747b715Smrg	return rc;
15516747b715Smrg
15526747b715Smrg    grab = CreateGrab(client->index, dev, dev, pWin, GRABTYPE_XI2,
15536747b715Smrg                      mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn,
15546747b715Smrg                      0, NULL, cursor);
15556747b715Smrg
15566747b715Smrg    if (!grab)
15576747b715Smrg        return BadAlloc;
15586747b715Smrg
15596747b715Smrg    return AddPassiveGrabToList(client, grab);
15606747b715Smrg}
15616747b715Smrg
156205b261ecSmrgint
156305b261ecSmrgSelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
15646747b715Smrg		Mask mask, Mask exclusivemasks)
156505b261ecSmrg{
156605b261ecSmrg    int mskidx = dev->id;
156705b261ecSmrg    int i, ret;
156805b261ecSmrg    Mask check;
156905b261ecSmrg    InputClientsPtr others;
157005b261ecSmrg
157105b261ecSmrg    check = (mask & exclusivemasks);
157205b261ecSmrg    if (wOtherInputMasks(pWin)) {
157305b261ecSmrg	if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {	/* It is illegal for two different
157405b261ecSmrg									 * clients to select on any of the
157505b261ecSmrg									 * events for maskcheck. However,
157605b261ecSmrg									 * it is OK, for some client to
157705b261ecSmrg									 * continue selecting on one of those
157805b261ecSmrg									 * events.  */
157905b261ecSmrg	    for (others = wOtherInputMasks(pWin)->inputClients; others;
158005b261ecSmrg		 others = others->next) {
158105b261ecSmrg		if (!SameClient(others, client) && (check &
158205b261ecSmrg						    others->mask[mskidx]))
158305b261ecSmrg		    return BadAccess;
158405b261ecSmrg	    }
158505b261ecSmrg	}
158605b261ecSmrg	for (others = wOtherInputMasks(pWin)->inputClients; others;
158705b261ecSmrg	     others = others->next) {
158805b261ecSmrg	    if (SameClient(others, client)) {
158905b261ecSmrg		check = others->mask[mskidx];
159005b261ecSmrg		others->mask[mskidx] = mask;
159105b261ecSmrg		if (mask == 0) {
159205b261ecSmrg		    for (i = 0; i < EMASKSIZE; i++)
159305b261ecSmrg			if (i != mskidx && others->mask[i] != 0)
159405b261ecSmrg			    break;
159505b261ecSmrg		    if (i == EMASKSIZE) {
159605b261ecSmrg			RecalculateDeviceDeliverableEvents(pWin);
159705b261ecSmrg			if (ShouldFreeInputMasks(pWin, FALSE))
159805b261ecSmrg			    FreeResource(others->resource, RT_NONE);
159905b261ecSmrg			return Success;
160005b261ecSmrg		    }
160105b261ecSmrg		}
160205b261ecSmrg		goto maskSet;
160305b261ecSmrg	    }
160405b261ecSmrg	}
160505b261ecSmrg    }
160605b261ecSmrg    check = 0;
160705b261ecSmrg    if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
160805b261ecSmrg	return ret;
160905b261ecSmrg  maskSet:
161005b261ecSmrg    if (dev->valuator)
161105b261ecSmrg	if ((dev->valuator->motionHintWindow == pWin) &&
161205b261ecSmrg	    (mask & DevicePointerMotionHintMask) &&
16134642e01fSmrg	    !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
161405b261ecSmrg	    dev->valuator->motionHintWindow = NullWindow;
161505b261ecSmrg    RecalculateDeviceDeliverableEvents(pWin);
161605b261ecSmrg    return Success;
161705b261ecSmrg}
161805b261ecSmrg
161905b261ecSmrgint
162005b261ecSmrgAddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
162105b261ecSmrg{
162205b261ecSmrg    InputClientsPtr others;
162305b261ecSmrg
162405b261ecSmrg    if (!pWin->optional && !MakeWindowOptional(pWin))
162505b261ecSmrg	return BadAlloc;
16266747b715Smrg    others = calloc(1, sizeof(InputClients));
162705b261ecSmrg    if (!others)
162805b261ecSmrg	return BadAlloc;
162905b261ecSmrg    if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
16309ace9065Smrg	goto bail;
163105b261ecSmrg    others->mask[mskidx] = mask;
163205b261ecSmrg    others->resource = FakeClientID(client->index);
163305b261ecSmrg    others->next = pWin->optional->inputMasks->inputClients;
163405b261ecSmrg    pWin->optional->inputMasks->inputClients = others;
163505b261ecSmrg    if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
16369ace9065Smrg	goto bail;
163705b261ecSmrg    return Success;
16389ace9065Smrg
16399ace9065Smrgbail:
16409ace9065Smrg    free(others);
16419ace9065Smrg    return BadAlloc;
164205b261ecSmrg}
164305b261ecSmrg
164405b261ecSmrgstatic Bool
164505b261ecSmrgMakeInputMasks(WindowPtr pWin)
164605b261ecSmrg{
164705b261ecSmrg    struct _OtherInputMasks *imasks;
164805b261ecSmrg
16496747b715Smrg    imasks = calloc(1, sizeof(struct _OtherInputMasks));
165005b261ecSmrg    if (!imasks)
165105b261ecSmrg	return FALSE;
165205b261ecSmrg    pWin->optional->inputMasks = imasks;
165305b261ecSmrg    return TRUE;
165405b261ecSmrg}
165505b261ecSmrg
165605b261ecSmrgvoid
165705b261ecSmrgRecalculateDeviceDeliverableEvents(WindowPtr pWin)
165805b261ecSmrg{
165905b261ecSmrg    InputClientsPtr others;
166005b261ecSmrg    struct _OtherInputMasks *inputMasks;	/* default: NULL */
166105b261ecSmrg    WindowPtr pChild, tmp;
16626747b715Smrg    int i, j;
166305b261ecSmrg
166405b261ecSmrg    pChild = pWin;
166505b261ecSmrg    while (1) {
166605b261ecSmrg	if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
16676747b715Smrg            for (i = 0; i < EMASKSIZE; i++)
16686747b715Smrg                memset(inputMasks->xi2mask[i], 0, sizeof(inputMasks->xi2mask[i]));
166905b261ecSmrg	    for (others = inputMasks->inputClients; others;
167005b261ecSmrg		 others = others->next) {
167105b261ecSmrg		for (i = 0; i < EMASKSIZE; i++)
167205b261ecSmrg		    inputMasks->inputEvents[i] |= others->mask[i];
16736747b715Smrg                for (i = 0; i < EMASKSIZE; i++)
16746747b715Smrg                    for (j = 0; j < XI2MASKSIZE; j++)
16756747b715Smrg                        inputMasks->xi2mask[i][j] |= others->xi2mask[i][j];
167605b261ecSmrg	    }
167705b261ecSmrg	    for (i = 0; i < EMASKSIZE; i++)
167805b261ecSmrg		inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
167905b261ecSmrg	    for (tmp = pChild->parent; tmp; tmp = tmp->parent)
168005b261ecSmrg		if (wOtherInputMasks(tmp))
168105b261ecSmrg		    for (i = 0; i < EMASKSIZE; i++)
168205b261ecSmrg			inputMasks->deliverableEvents[i] |=
168305b261ecSmrg			    (wOtherInputMasks(tmp)->deliverableEvents[i]
168405b261ecSmrg			     & ~inputMasks->
168505b261ecSmrg			     dontPropagateMask[i] & PropagateMask[i]);
168605b261ecSmrg	}
168705b261ecSmrg	if (pChild->firstChild) {
168805b261ecSmrg	    pChild = pChild->firstChild;
168905b261ecSmrg	    continue;
169005b261ecSmrg	}
169105b261ecSmrg	while (!pChild->nextSib && (pChild != pWin))
169205b261ecSmrg	    pChild = pChild->parent;
169305b261ecSmrg	if (pChild == pWin)
169405b261ecSmrg	    break;
169505b261ecSmrg	pChild = pChild->nextSib;
169605b261ecSmrg    }
169705b261ecSmrg}
169805b261ecSmrg
169905b261ecSmrgint
170005b261ecSmrgInputClientGone(WindowPtr pWin, XID id)
170105b261ecSmrg{
170205b261ecSmrg    InputClientsPtr other, prev;
170305b261ecSmrg
170405b261ecSmrg    if (!wOtherInputMasks(pWin))
17056747b715Smrg	return Success;
170605b261ecSmrg    prev = 0;
170705b261ecSmrg    for (other = wOtherInputMasks(pWin)->inputClients; other;
170805b261ecSmrg	 other = other->next) {
170905b261ecSmrg	if (other->resource == id) {
171005b261ecSmrg	    if (prev) {
171105b261ecSmrg		prev->next = other->next;
17126747b715Smrg		free(other);
171305b261ecSmrg	    } else if (!(other->next)) {
171405b261ecSmrg		if (ShouldFreeInputMasks(pWin, TRUE)) {
171505b261ecSmrg		    wOtherInputMasks(pWin)->inputClients = other->next;
17166747b715Smrg		    free(wOtherInputMasks(pWin));
171705b261ecSmrg		    pWin->optional->inputMasks = (OtherInputMasks *) NULL;
171805b261ecSmrg		    CheckWindowOptionalNeed(pWin);
17196747b715Smrg		    free(other);
172005b261ecSmrg		} else {
172105b261ecSmrg		    other->resource = FakeClientID(0);
172205b261ecSmrg		    if (!AddResource(other->resource, RT_INPUTCLIENT,
172305b261ecSmrg				     (pointer) pWin))
172405b261ecSmrg			return BadAlloc;
172505b261ecSmrg		}
172605b261ecSmrg	    } else {
172705b261ecSmrg		wOtherInputMasks(pWin)->inputClients = other->next;
17286747b715Smrg		free(other);
172905b261ecSmrg	    }
173005b261ecSmrg	    RecalculateDeviceDeliverableEvents(pWin);
17316747b715Smrg	    return Success;
173205b261ecSmrg	}
173305b261ecSmrg	prev = other;
173405b261ecSmrg    }
173505b261ecSmrg    FatalError("client not on device event list");
173605b261ecSmrg}
173705b261ecSmrg
173805b261ecSmrgint
173905b261ecSmrgSendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
174005b261ecSmrg	  xEvent * ev, Mask mask, int count)
174105b261ecSmrg{
174205b261ecSmrg    WindowPtr pWin;
174305b261ecSmrg    WindowPtr effectiveFocus = NullWindow;	/* only set if dest==InputFocus */
17444642e01fSmrg    WindowPtr spriteWin = GetSpriteWindow(d);
174505b261ecSmrg
174605b261ecSmrg    if (dest == PointerWindow)
174705b261ecSmrg	pWin = spriteWin;
174805b261ecSmrg    else if (dest == InputFocus) {
174905b261ecSmrg	WindowPtr inputFocus;
175005b261ecSmrg
175105b261ecSmrg	if (!d->focus)
175205b261ecSmrg	    inputFocus = spriteWin;
175305b261ecSmrg	else
175405b261ecSmrg	    inputFocus = d->focus->win;
175505b261ecSmrg
175605b261ecSmrg	if (inputFocus == FollowKeyboardWin)
175705b261ecSmrg	    inputFocus = inputInfo.keyboard->focus->win;
175805b261ecSmrg
175905b261ecSmrg	if (inputFocus == NoneWin)
176005b261ecSmrg	    return Success;
176105b261ecSmrg
176205b261ecSmrg	/* If the input focus is PointerRootWin, send the event to where
176305b261ecSmrg	 * the pointer is if possible, then perhaps propogate up to root. */
176405b261ecSmrg	if (inputFocus == PointerRootWin)
17654642e01fSmrg	    inputFocus = GetCurrentRootWindow(d);
176605b261ecSmrg
176705b261ecSmrg	if (IsParent(inputFocus, spriteWin)) {
176805b261ecSmrg	    effectiveFocus = inputFocus;
176905b261ecSmrg	    pWin = spriteWin;
177005b261ecSmrg	} else
177105b261ecSmrg	    effectiveFocus = pWin = inputFocus;
177205b261ecSmrg    } else
17734642e01fSmrg	dixLookupWindow(&pWin, dest, client, DixSendAccess);
177405b261ecSmrg    if (!pWin)
177505b261ecSmrg	return BadWindow;
177605b261ecSmrg    if ((propagate != xFalse) && (propagate != xTrue)) {
177705b261ecSmrg	client->errorValue = propagate;
177805b261ecSmrg	return BadValue;
177905b261ecSmrg    }
178005b261ecSmrg    ev->u.u.type |= 0x80;
178105b261ecSmrg    if (propagate) {
178205b261ecSmrg	for (; pWin; pWin = pWin->parent) {
17836747b715Smrg	    if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
178405b261ecSmrg		return Success;
178505b261ecSmrg	    if (pWin == effectiveFocus)
178605b261ecSmrg		return Success;
178705b261ecSmrg	    if (wOtherInputMasks(pWin))
178805b261ecSmrg		mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
178905b261ecSmrg	    if (!mask)
179005b261ecSmrg		break;
179105b261ecSmrg	}
17924642e01fSmrg    } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
17936747b715Smrg	DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
179405b261ecSmrg    return Success;
179505b261ecSmrg}
179605b261ecSmrg
179705b261ecSmrgint
179805b261ecSmrgSetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
179905b261ecSmrg{
180005b261ecSmrg    int i;
180105b261ecSmrg    ButtonClassPtr b = dev->button;
180205b261ecSmrg
180305b261ecSmrg    if (b == NULL)
180405b261ecSmrg	return BadMatch;
180505b261ecSmrg
180605b261ecSmrg    if (nElts != b->numButtons) {
180705b261ecSmrg	client->errorValue = nElts;
180805b261ecSmrg	return BadValue;
180905b261ecSmrg    }
181005b261ecSmrg    if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
181105b261ecSmrg	return BadValue;
181205b261ecSmrg    for (i = 0; i < nElts; i++)
181305b261ecSmrg	if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
181405b261ecSmrg	    return MappingBusy;
181505b261ecSmrg    for (i = 0; i < nElts; i++)
181605b261ecSmrg	b->map[i + 1] = map[i];
181705b261ecSmrg    return Success;
181805b261ecSmrg}
181905b261ecSmrg
182005b261ecSmrgint
182105b261ecSmrgChangeKeyMapping(ClientPtr client,
182205b261ecSmrg		 DeviceIntPtr dev,
182305b261ecSmrg		 unsigned len,
182405b261ecSmrg		 int type,
182505b261ecSmrg		 KeyCode firstKeyCode,
182605b261ecSmrg		 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
182705b261ecSmrg{
182805b261ecSmrg    KeySymsRec keysyms;
182905b261ecSmrg    KeyClassPtr k = dev->key;
183005b261ecSmrg
183105b261ecSmrg    if (k == NULL)
18326747b715Smrg	return BadMatch;
183305b261ecSmrg
183405b261ecSmrg    if (len != (keyCodes * keySymsPerKeyCode))
183505b261ecSmrg	return BadLength;
183605b261ecSmrg
18376747b715Smrg    if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
18386747b715Smrg	(firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
183905b261ecSmrg	client->errorValue = firstKeyCode;
184005b261ecSmrg	return BadValue;
184105b261ecSmrg    }
184205b261ecSmrg    if (keySymsPerKeyCode == 0) {
184305b261ecSmrg	client->errorValue = 0;
184405b261ecSmrg	return BadValue;
184505b261ecSmrg    }
184605b261ecSmrg    keysyms.minKeyCode = firstKeyCode;
184705b261ecSmrg    keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
184805b261ecSmrg    keysyms.mapWidth = keySymsPerKeyCode;
184905b261ecSmrg    keysyms.map = map;
18506747b715Smrg
18516747b715Smrg    XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
18526747b715Smrg                          serverClient);
18536747b715Smrg
18546747b715Smrg    return Success;
185505b261ecSmrg}
185605b261ecSmrg
185705b261ecSmrgstatic void
185805b261ecSmrgDeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
185905b261ecSmrg{
186005b261ecSmrg    WindowPtr parent;
186105b261ecSmrg
186205b261ecSmrg    /* Deactivate any grabs performed on this window, before making
186305b261ecSmrg     * any input focus changes.
186405b261ecSmrg     * Deactivating a device grab should cause focus events. */
186505b261ecSmrg
18664642e01fSmrg    if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
18674642e01fSmrg	(*dev->deviceGrab.DeactivateGrab) (dev);
186805b261ecSmrg
18694642e01fSmrg    /* If the focus window is a root window (ie. has no parent)
187005b261ecSmrg     * then don't delete the focus from it. */
187105b261ecSmrg
187205b261ecSmrg    if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
187305b261ecSmrg	int focusEventMode = NotifyNormal;
187405b261ecSmrg
187505b261ecSmrg	/* If a grab is in progress, then alter the mode of focus events. */
187605b261ecSmrg
18774642e01fSmrg	if (dev->deviceGrab.grab)
187805b261ecSmrg	    focusEventMode = NotifyWhileGrabbed;
187905b261ecSmrg
188005b261ecSmrg	switch (dev->focus->revert) {
188105b261ecSmrg	case RevertToNone:
18826747b715Smrg	    if (!ActivateFocusInGrab(dev, pWin, NoneWin))
18836747b715Smrg		DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
188405b261ecSmrg	    dev->focus->win = NoneWin;
188505b261ecSmrg	    dev->focus->traceGood = 0;
188605b261ecSmrg	    break;
188705b261ecSmrg	case RevertToParent:
188805b261ecSmrg	    parent = pWin;
188905b261ecSmrg	    do {
189005b261ecSmrg		parent = parent->parent;
189105b261ecSmrg		dev->focus->traceGood--;
189205b261ecSmrg	    }
189305b261ecSmrg	    while (!parent->realized);
18946747b715Smrg	    if (!ActivateFocusInGrab(dev, pWin, parent))
18956747b715Smrg		DoFocusEvents(dev, pWin, parent, focusEventMode);
189605b261ecSmrg	    dev->focus->win = parent;
189705b261ecSmrg	    dev->focus->revert = RevertToNone;
189805b261ecSmrg	    break;
189905b261ecSmrg	case RevertToPointerRoot:
19006747b715Smrg	    if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
19016747b715Smrg		DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
190205b261ecSmrg	    dev->focus->win = PointerRootWin;
190305b261ecSmrg	    dev->focus->traceGood = 0;
190405b261ecSmrg	    break;
190505b261ecSmrg	case RevertToFollowKeyboard:
19066747b715Smrg            {
19076747b715Smrg                DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
19086747b715Smrg                if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
19096747b715Smrg                    kbd = inputInfo.keyboard;
19106747b715Smrg	    if (kbd->focus->win) {
19116747b715Smrg		if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
19126747b715Smrg		    DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
191305b261ecSmrg		dev->focus->win = FollowKeyboardWin;
191405b261ecSmrg		dev->focus->traceGood = 0;
191505b261ecSmrg	    } else {
19166747b715Smrg                if (!ActivateFocusInGrab(dev, pWin, NoneWin))
19176747b715Smrg                    DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
191805b261ecSmrg		dev->focus->win = NoneWin;
191905b261ecSmrg		dev->focus->traceGood = 0;
192005b261ecSmrg	    }
19216747b715Smrg            }
192205b261ecSmrg	    break;
192305b261ecSmrg	}
192405b261ecSmrg    }
192505b261ecSmrg
192605b261ecSmrg    if (dev->valuator)
192705b261ecSmrg	if (dev->valuator->motionHintWindow == pWin)
192805b261ecSmrg	    dev->valuator->motionHintWindow = NullWindow;
192905b261ecSmrg}
193005b261ecSmrg
193105b261ecSmrgvoid
193205b261ecSmrgDeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
193305b261ecSmrg{
193405b261ecSmrg    int i;
193505b261ecSmrg    DeviceIntPtr dev;
193605b261ecSmrg    InputClientsPtr ic;
193705b261ecSmrg    struct _OtherInputMasks *inputMasks;
193805b261ecSmrg
193905b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
194005b261ecSmrg	DeleteDeviceFromAnyExtEvents(pWin, dev);
194105b261ecSmrg    }
194205b261ecSmrg
194305b261ecSmrg    for (dev = inputInfo.off_devices; dev; dev = dev->next)
194405b261ecSmrg	DeleteDeviceFromAnyExtEvents(pWin, dev);
194505b261ecSmrg
194605b261ecSmrg    if (freeResources)
194705b261ecSmrg	while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
194805b261ecSmrg	    ic = inputMasks->inputClients;
194905b261ecSmrg	    for (i = 0; i < EMASKSIZE; i++)
195005b261ecSmrg		inputMasks->dontPropagateMask[i] = 0;
195105b261ecSmrg	    FreeResource(ic->resource, RT_NONE);
195205b261ecSmrg	}
195305b261ecSmrg}
195405b261ecSmrg
195505b261ecSmrgint
195605b261ecSmrgMaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
195705b261ecSmrg{
195805b261ecSmrg    DeviceIntPtr dev;
195905b261ecSmrg
19604642e01fSmrg    dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
19614642e01fSmrg		    DixReadAccess);
196205b261ecSmrg    if (!dev)
196305b261ecSmrg        return 0;
196405b261ecSmrg
196505b261ecSmrg    if (pEvents->type == DeviceMotionNotify) {
196605b261ecSmrg	if (mask & DevicePointerMotionHintMask) {
196705b261ecSmrg	    if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
196805b261ecSmrg		return 1;	/* don't send, but pretend we did */
196905b261ecSmrg	    }
197005b261ecSmrg	    pEvents->detail = NotifyHint;
197105b261ecSmrg	} else {
197205b261ecSmrg	    pEvents->detail = NotifyNormal;
197305b261ecSmrg	}
197405b261ecSmrg    }
19756747b715Smrg    return 0;
197605b261ecSmrg}
197705b261ecSmrg
197805b261ecSmrgvoid
197905b261ecSmrgCheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
198005b261ecSmrg			     deviceKeyButtonPointer * xE, GrabPtr grab,
198105b261ecSmrg			     ClientPtr client, Mask deliveryMask)
198205b261ecSmrg{
198305b261ecSmrg    DeviceIntPtr dev;
198405b261ecSmrg
19854642e01fSmrg    dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
19866747b715Smrg		    DixGrabAccess);
198705b261ecSmrg    if (!dev)
198805b261ecSmrg        return;
198905b261ecSmrg
199005b261ecSmrg    if (type == DeviceMotionNotify)
199105b261ecSmrg	dev->valuator->motionHintWindow = pWin;
199205b261ecSmrg    else if ((type == DeviceButtonPress) && (!grab) &&
199305b261ecSmrg	     (deliveryMask & DeviceButtonGrabMask)) {
199405b261ecSmrg	GrabRec tempGrab;
199505b261ecSmrg
199605b261ecSmrg	tempGrab.device = dev;
199705b261ecSmrg	tempGrab.resource = client->clientAsMask;
199805b261ecSmrg	tempGrab.window = pWin;
199905b261ecSmrg	tempGrab.ownerEvents =
200005b261ecSmrg	    (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
200105b261ecSmrg	tempGrab.eventMask = deliveryMask;
200205b261ecSmrg	tempGrab.keyboardMode = GrabModeAsync;
200305b261ecSmrg	tempGrab.pointerMode = GrabModeAsync;
200405b261ecSmrg	tempGrab.confineTo = NullWindow;
200505b261ecSmrg	tempGrab.cursor = NullCursor;
20064642e01fSmrg        tempGrab.next = NULL;
20074642e01fSmrg	(*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
200805b261ecSmrg    }
200905b261ecSmrg}
201005b261ecSmrg
201105b261ecSmrgstatic Mask
201205b261ecSmrgDeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
201305b261ecSmrg{
201405b261ecSmrg    InputClientsPtr other;
201505b261ecSmrg
201605b261ecSmrg    if (!wOtherInputMasks(pWin))
201705b261ecSmrg	return 0;
201805b261ecSmrg    for (other = wOtherInputMasks(pWin)->inputClients; other;
201905b261ecSmrg	 other = other->next) {
202005b261ecSmrg	if (SameClient(other, client))
202105b261ecSmrg	    return other->mask[dev->id];
202205b261ecSmrg    }
202305b261ecSmrg    return 0;
202405b261ecSmrg}
202505b261ecSmrg
202605b261ecSmrgvoid
202705b261ecSmrgMaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
202805b261ecSmrg{
202905b261ecSmrg    WindowPtr pWin;
20304642e01fSmrg    GrabPtr grab = dev->deviceGrab.grab;
203105b261ecSmrg
203205b261ecSmrg    pWin = dev->valuator->motionHintWindow;
203305b261ecSmrg
203405b261ecSmrg    if ((grab && SameClient(grab, client) &&
203505b261ecSmrg	 ((grab->eventMask & DevicePointerMotionHintMask) ||
203605b261ecSmrg	  (grab->ownerEvents &&
203705b261ecSmrg	   (DeviceEventMaskForClient(dev, pWin, client) &
203805b261ecSmrg	    DevicePointerMotionHintMask)))) ||
203905b261ecSmrg	(!grab &&
204005b261ecSmrg	 (DeviceEventMaskForClient(dev, pWin, client) &
204105b261ecSmrg	  DevicePointerMotionHintMask)))
204205b261ecSmrg	dev->valuator->motionHintWindow = NullWindow;
204305b261ecSmrg}
204405b261ecSmrg
204505b261ecSmrgint
204605b261ecSmrgDeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
204705b261ecSmrg			     int maskndx)
204805b261ecSmrg{
204905b261ecSmrg    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
205005b261ecSmrg
205105b261ecSmrg    if (mask & ~PropagateMask[maskndx]) {
205205b261ecSmrg	client->errorValue = mask;
205305b261ecSmrg	return BadValue;
205405b261ecSmrg    }
205505b261ecSmrg
205605b261ecSmrg    if (mask == 0) {
205705b261ecSmrg	if (inputMasks)
205805b261ecSmrg	    inputMasks->dontPropagateMask[maskndx] = mask;
205905b261ecSmrg    } else {
206005b261ecSmrg	if (!inputMasks)
206105b261ecSmrg	    AddExtensionClient(pWin, client, 0, 0);
206205b261ecSmrg	inputMasks = wOtherInputMasks(pWin);
206305b261ecSmrg	inputMasks->dontPropagateMask[maskndx] = mask;
206405b261ecSmrg    }
206505b261ecSmrg    RecalculateDeviceDeliverableEvents(pWin);
206605b261ecSmrg    if (ShouldFreeInputMasks(pWin, FALSE))
206705b261ecSmrg	FreeResource(inputMasks->inputClients->resource, RT_NONE);
206805b261ecSmrg    return Success;
206905b261ecSmrg}
207005b261ecSmrg
20714642e01fSmrgBool
207205b261ecSmrgShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
207305b261ecSmrg{
207405b261ecSmrg    int i;
207505b261ecSmrg    Mask allInputEventMasks = 0;
207605b261ecSmrg    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
207705b261ecSmrg
207805b261ecSmrg    for (i = 0; i < EMASKSIZE; i++)
207905b261ecSmrg	allInputEventMasks |= inputMasks->dontPropagateMask[i];
208005b261ecSmrg    if (!ignoreSelectedEvents)
208105b261ecSmrg	for (i = 0; i < EMASKSIZE; i++)
208205b261ecSmrg	    allInputEventMasks |= inputMasks->inputEvents[i];
208305b261ecSmrg    if (allInputEventMasks == 0)
208405b261ecSmrg	return TRUE;
208505b261ecSmrg    else
208605b261ecSmrg	return FALSE;
208705b261ecSmrg}
208805b261ecSmrg
208905b261ecSmrg/***********************************************************************
209005b261ecSmrg *
209105b261ecSmrg * Walk through the window tree, finding all clients that want to know
209205b261ecSmrg * about the Event.
209305b261ecSmrg *
209405b261ecSmrg */
209505b261ecSmrg
209605b261ecSmrgstatic void
209705b261ecSmrgFindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
209805b261ecSmrg                       xEvent * ev, int count)
209905b261ecSmrg{
210005b261ecSmrg    WindowPtr p2;
210105b261ecSmrg
210205b261ecSmrg    while (p1) {
210305b261ecSmrg        p2 = p1->firstChild;
21046747b715Smrg        DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
210505b261ecSmrg        FindInterestedChildren(dev, p2, mask, ev, count);
210605b261ecSmrg        p1 = p1->nextSib;
210705b261ecSmrg    }
210805b261ecSmrg}
210905b261ecSmrg
211005b261ecSmrg/***********************************************************************
211105b261ecSmrg *
211205b261ecSmrg * Send an event to interested clients in all windows on all screens.
211305b261ecSmrg *
211405b261ecSmrg */
211505b261ecSmrg
211605b261ecSmrgvoid
211705b261ecSmrgSendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
211805b261ecSmrg{
211905b261ecSmrg    int i;
212005b261ecSmrg    WindowPtr pWin, p1;
212105b261ecSmrg
212205b261ecSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
21236747b715Smrg        pWin = screenInfo.screens[i]->root;
21244642e01fSmrg        if (!pWin)
21254642e01fSmrg            continue;
21266747b715Smrg        DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
212705b261ecSmrg        p1 = pWin->firstChild;
212805b261ecSmrg        FindInterestedChildren(dev, p1, mask, ev, count);
212905b261ecSmrg    }
213005b261ecSmrg}
21314642e01fSmrg
21326747b715Smrg/**
21336747b715Smrg * Set the XI2 mask for the given client on the given window.
21346747b715Smrg * @param dev The device to set the mask for.
21356747b715Smrg * @param win The window to set the mask on.
21366747b715Smrg * @param client The client setting the mask.
21376747b715Smrg * @param len Number of bytes in mask.
21386747b715Smrg * @param mask Event mask in the form of (1 << eventtype)
21396747b715Smrg */
21406747b715Smrgint
21416747b715SmrgXISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
21426747b715Smrg               unsigned int len, unsigned char* mask)
21436747b715Smrg{
21446747b715Smrg    OtherInputMasks *masks;
21456747b715Smrg    InputClientsPtr others = NULL;
21466747b715Smrg
21476747b715Smrg    masks = wOtherInputMasks(win);
21486747b715Smrg    if (masks)
21496747b715Smrg    {
21506747b715Smrg	for (others = wOtherInputMasks(win)->inputClients; others;
21516747b715Smrg	     others = others->next) {
21526747b715Smrg	    if (SameClient(others, client)) {
21536747b715Smrg                memset(others->xi2mask[dev->id], 0,
21546747b715Smrg                       sizeof(others->xi2mask[dev->id]));
21556747b715Smrg                break;
21566747b715Smrg            }
21576747b715Smrg        }
21586747b715Smrg    }
21596747b715Smrg
21606747b715Smrg    len = min(len, sizeof(others->xi2mask[dev->id]));
21616747b715Smrg
21626747b715Smrg    if (len && !others)
21636747b715Smrg    {
21646747b715Smrg        if (AddExtensionClient(win, client, 0, 0) != Success)
21656747b715Smrg            return BadAlloc;
21666747b715Smrg        others= wOtherInputMasks(win)->inputClients;
21676747b715Smrg    }
21686747b715Smrg
21696747b715Smrg    if (others)
21706747b715Smrg        memset(others->xi2mask[dev->id], 0, sizeof(others->xi2mask[dev->id]));
21716747b715Smrg
21726747b715Smrg    if (len)
21736747b715Smrg        memcpy(others->xi2mask[dev->id], mask, len);
21746747b715Smrg
21756747b715Smrg    RecalculateDeviceDeliverableEvents(win);
21766747b715Smrg
21776747b715Smrg    return Success;
21786747b715Smrg}
2179