exevents.c revision 8223e2f2
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
11405b261ecSmrgvoid
11505b261ecSmrgRegisterOtherDevice(DeviceIntPtr device)
11605b261ecSmrg{
11705b261ecSmrg    device->public.processInputProc = ProcessOtherEvent;
11805b261ecSmrg    device->public.realInputProc = ProcessOtherEvent;
11905b261ecSmrg}
12005b261ecSmrg
1214642e01fSmrgBool
1226747b715SmrgIsPointerEvent(InternalEvent* event)
1234642e01fSmrg{
1246747b715Smrg    switch(event->any.type)
1254642e01fSmrg    {
1266747b715Smrg        case ET_ButtonPress:
1276747b715Smrg        case ET_ButtonRelease:
1286747b715Smrg        case ET_Motion:
1296747b715Smrg            /* XXX: enter/leave ?? */
1304642e01fSmrg            return TRUE;
1314642e01fSmrg        default:
1326747b715Smrg            break;
1334642e01fSmrg    }
1344642e01fSmrg    return FALSE;
1354642e01fSmrg}
1364642e01fSmrg
1374642e01fSmrg/**
1384642e01fSmrg * @return the device matching the deviceid of the device set in the event, or
1394642e01fSmrg * NULL if the event is not an XInput event.
1404642e01fSmrg */
1414642e01fSmrgDeviceIntPtr
1424642e01fSmrgXIGetDevice(xEvent* xE)
14305b261ecSmrg{
1444642e01fSmrg    DeviceIntPtr pDev = NULL;
1454642e01fSmrg
1464642e01fSmrg    if (xE->u.u.type == DeviceButtonPress ||
1474642e01fSmrg        xE->u.u.type == DeviceButtonRelease ||
1484642e01fSmrg        xE->u.u.type == DeviceMotionNotify ||
1494642e01fSmrg        xE->u.u.type == ProximityIn ||
1504642e01fSmrg        xE->u.u.type == ProximityOut ||
1514642e01fSmrg        xE->u.u.type == DevicePropertyNotify)
1524642e01fSmrg    {
1534642e01fSmrg        int rc;
1544642e01fSmrg        int id;
1554642e01fSmrg
1564642e01fSmrg        id = ((deviceKeyButtonPointer*)xE)->deviceid & ~MORE_EVENTS;
1574642e01fSmrg
1584642e01fSmrg        rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
1594642e01fSmrg        if (rc != Success)
1604642e01fSmrg            ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
1614642e01fSmrg    }
1624642e01fSmrg    return pDev;
1634642e01fSmrg}
1644642e01fSmrg
1654642e01fSmrg
1664642e01fSmrg/**
1674642e01fSmrg * Copy the device->key into master->key and send a mapping notify to the
1684642e01fSmrg * clients if appropriate.
1694642e01fSmrg * master->key needs to be allocated by the caller.
1704642e01fSmrg *
1714642e01fSmrg * Device is the slave device. If it is attached to a master device, we may
1724642e01fSmrg * need to send a mapping notify to the client because it causes the MD
1734642e01fSmrg * to change state.
1744642e01fSmrg *
1754642e01fSmrg * Mapping notify needs to be sent in the following cases:
1764642e01fSmrg *      - different slave device on same master
1774642e01fSmrg *      - different master
1784642e01fSmrg *
1794642e01fSmrg * XXX: They way how the code is we also send a map notify if the slave device
1804642e01fSmrg * stays the same, but the master changes. This isn't really necessary though.
1814642e01fSmrg *
1824642e01fSmrg * XXX: this gives you funny behaviour with the ClientPointer. When a
1834642e01fSmrg * MappingNotify is sent to the client, the client usually responds with a
1844642e01fSmrg * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
1854642e01fSmrg * mapping, regardless of which keyboard sent the last mapping notify request.
1864642e01fSmrg * So depending on the CP setting, your keyboard may change layout in each
1874642e01fSmrg * app...
1884642e01fSmrg *
1894642e01fSmrg * This code is basically the old SwitchCoreKeyboard.
1904642e01fSmrg */
1914642e01fSmrg
1924642e01fSmrgvoid
1934642e01fSmrgCopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
1944642e01fSmrg{
1956747b715Smrg    KeyClassPtr mk = master->key;
1964642e01fSmrg
1974642e01fSmrg    if (device == master)
1984642e01fSmrg        return;
1994642e01fSmrg
2006747b715Smrg    mk->sourceid = device->id;
2014642e01fSmrg
2024642e01fSmrg
2036747b715Smrg    if (!XkbCopyDeviceKeymap(master, device))
2046747b715Smrg        FatalError("Couldn't pivot keymap from device to core!\n");
2054642e01fSmrg}
20605b261ecSmrg
2074642e01fSmrg/**
2084642e01fSmrg * Copies the feedback classes from device "from" into device "to". Classes
2094642e01fSmrg * are duplicated (not just flipping the pointers). All feedback classes are
2104642e01fSmrg * linked lists, the full list is duplicated.
2114642e01fSmrg */
2124642e01fSmrgstatic void
2134642e01fSmrgDeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
2144642e01fSmrg{
2154642e01fSmrg    ClassesPtr classes;
2164642e01fSmrg
2174642e01fSmrg
2184642e01fSmrg    if (from->intfeed)
2194642e01fSmrg    {
2204642e01fSmrg        IntegerFeedbackPtr *i, it;
2214642e01fSmrg
2224642e01fSmrg        if (!to->intfeed)
2234642e01fSmrg        {
2246747b715Smrg            classes = to->unused_classes;
2254642e01fSmrg            to->intfeed = classes->intfeed;
2266747b715Smrg            classes->intfeed = NULL;
2274642e01fSmrg        }
2284642e01fSmrg
2294642e01fSmrg        i = &to->intfeed;
2304642e01fSmrg        for (it = from->intfeed; it; it = it->next)
2314642e01fSmrg        {
2324642e01fSmrg            if (!(*i))
2334642e01fSmrg            {
2346747b715Smrg                *i = calloc(1, sizeof(IntegerFeedbackClassRec));
2354642e01fSmrg                if (!(*i))
2364642e01fSmrg                {
2374642e01fSmrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
2384642e01fSmrg                    return;
2394642e01fSmrg                }
2404642e01fSmrg            }
2414642e01fSmrg            (*i)->CtrlProc = it->CtrlProc;
2424642e01fSmrg            (*i)->ctrl     = it->ctrl;
2434642e01fSmrg
2444642e01fSmrg            i = &(*i)->next;
2454642e01fSmrg        }
2464642e01fSmrg    } else if (to->intfeed && !from->intfeed)
2474642e01fSmrg    {
2484642e01fSmrg        ClassesPtr classes;
2496747b715Smrg        classes = to->unused_classes;
2504642e01fSmrg        classes->intfeed = to->intfeed;
2514642e01fSmrg        to->intfeed      = NULL;
2524642e01fSmrg    }
2534642e01fSmrg
2544642e01fSmrg    if (from->stringfeed)
2554642e01fSmrg    {
2564642e01fSmrg        StringFeedbackPtr *s, it;
2574642e01fSmrg
2584642e01fSmrg        if (!to->stringfeed)
2594642e01fSmrg        {
2606747b715Smrg            classes = to->unused_classes;
2614642e01fSmrg            to->stringfeed = classes->stringfeed;
2626747b715Smrg            classes->stringfeed = NULL;
2634642e01fSmrg        }
2644642e01fSmrg
2654642e01fSmrg        s = &to->stringfeed;
2664642e01fSmrg        for (it = from->stringfeed; it; it = it->next)
2674642e01fSmrg        {
2684642e01fSmrg            if (!(*s))
2694642e01fSmrg            {
2706747b715Smrg                *s = calloc(1, sizeof(StringFeedbackClassRec));
2714642e01fSmrg                if (!(*s))
2724642e01fSmrg                {
2734642e01fSmrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
2744642e01fSmrg                    return;
2754642e01fSmrg                }
2764642e01fSmrg            }
2774642e01fSmrg            (*s)->CtrlProc = it->CtrlProc;
2784642e01fSmrg            (*s)->ctrl     = it->ctrl;
2794642e01fSmrg
2804642e01fSmrg            s = &(*s)->next;
2814642e01fSmrg        }
2824642e01fSmrg    } else if (to->stringfeed && !from->stringfeed)
2834642e01fSmrg    {
2844642e01fSmrg        ClassesPtr classes;
2856747b715Smrg        classes = to->unused_classes;
2864642e01fSmrg        classes->stringfeed = to->stringfeed;
2874642e01fSmrg        to->stringfeed      = NULL;
2884642e01fSmrg    }
2894642e01fSmrg
2904642e01fSmrg    if (from->bell)
2914642e01fSmrg    {
2924642e01fSmrg        BellFeedbackPtr *b, it;
2934642e01fSmrg
2944642e01fSmrg        if (!to->bell)
2954642e01fSmrg        {
2966747b715Smrg            classes = to->unused_classes;
2974642e01fSmrg            to->bell = classes->bell;
2986747b715Smrg            classes->bell = NULL;
2994642e01fSmrg        }
3004642e01fSmrg
3014642e01fSmrg        b = &to->bell;
3024642e01fSmrg        for (it = from->bell; it; it = it->next)
3034642e01fSmrg        {
3044642e01fSmrg            if (!(*b))
3054642e01fSmrg            {
3066747b715Smrg                *b = calloc(1, sizeof(BellFeedbackClassRec));
3074642e01fSmrg                if (!(*b))
3084642e01fSmrg                {
3094642e01fSmrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
3104642e01fSmrg                    return;
3114642e01fSmrg                }
3124642e01fSmrg            }
3134642e01fSmrg            (*b)->BellProc = it->BellProc;
3144642e01fSmrg            (*b)->CtrlProc = it->CtrlProc;
3154642e01fSmrg            (*b)->ctrl     = it->ctrl;
3164642e01fSmrg
3174642e01fSmrg            b = &(*b)->next;
3184642e01fSmrg        }
3194642e01fSmrg    } else if (to->bell && !from->bell)
3204642e01fSmrg    {
3214642e01fSmrg        ClassesPtr classes;
3226747b715Smrg        classes = to->unused_classes;
3234642e01fSmrg        classes->bell = to->bell;
3244642e01fSmrg        to->bell      = NULL;
3254642e01fSmrg    }
3264642e01fSmrg
3274642e01fSmrg    if (from->leds)
3284642e01fSmrg    {
3294642e01fSmrg        LedFeedbackPtr *l, it;
3304642e01fSmrg
3314642e01fSmrg        if (!to->leds)
3324642e01fSmrg        {
3336747b715Smrg            classes = to->unused_classes;
3344642e01fSmrg            to->leds = classes->leds;
3356747b715Smrg            classes->leds = NULL;
3364642e01fSmrg        }
3374642e01fSmrg
3384642e01fSmrg        l = &to->leds;
3394642e01fSmrg        for (it = from->leds; it; it = it->next)
3404642e01fSmrg        {
3414642e01fSmrg            if (!(*l))
3424642e01fSmrg            {
3436747b715Smrg                *l = calloc(1, sizeof(LedFeedbackClassRec));
3444642e01fSmrg                if (!(*l))
3454642e01fSmrg                {
3464642e01fSmrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
3474642e01fSmrg                    return;
3484642e01fSmrg                }
3494642e01fSmrg            }
3504642e01fSmrg            (*l)->CtrlProc = it->CtrlProc;
3514642e01fSmrg            (*l)->ctrl     = it->ctrl;
3524642e01fSmrg            if ((*l)->xkb_sli)
3534642e01fSmrg                XkbFreeSrvLedInfo((*l)->xkb_sli);
3544642e01fSmrg            (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
3554642e01fSmrg
3564642e01fSmrg            l = &(*l)->next;
3574642e01fSmrg        }
3584642e01fSmrg    } else if (to->leds && !from->leds)
3594642e01fSmrg    {
3604642e01fSmrg        ClassesPtr classes;
3616747b715Smrg        classes = to->unused_classes;
3624642e01fSmrg        classes->leds = to->leds;
3634642e01fSmrg        to->leds      = NULL;
3644642e01fSmrg    }
3654642e01fSmrg}
3664642e01fSmrg
3676747b715Smrgstatic void
3686747b715SmrgDeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
3694642e01fSmrg{
3704642e01fSmrg    ClassesPtr classes;
3714642e01fSmrg
3724642e01fSmrg    /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
3734642e01fSmrg     * kbdfeed to be set up properly, so let's do the feedback classes first.
3744642e01fSmrg     */
3756747b715Smrg    if (from->kbdfeed)
3766747b715Smrg    {
3776747b715Smrg        KbdFeedbackPtr *k, it;
3786747b715Smrg
3796747b715Smrg        if (!to->kbdfeed)
3806747b715Smrg        {
3816747b715Smrg            classes = to->unused_classes;
3826747b715Smrg
3836747b715Smrg            to->kbdfeed = classes->kbdfeed;
3846747b715Smrg            if (!to->kbdfeed)
3856747b715Smrg                InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
3866747b715Smrg            classes->kbdfeed = NULL;
3876747b715Smrg        }
3886747b715Smrg
3896747b715Smrg        k = &to->kbdfeed;
3906747b715Smrg        for(it = from->kbdfeed; it; it = it->next)
3916747b715Smrg        {
3926747b715Smrg            if (!(*k))
3936747b715Smrg            {
3946747b715Smrg                *k = calloc(1, sizeof(KbdFeedbackClassRec));
3956747b715Smrg                if (!*k)
3966747b715Smrg                {
3976747b715Smrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
3986747b715Smrg                    return;
3996747b715Smrg                }
4006747b715Smrg            }
4016747b715Smrg            (*k)->BellProc = it->BellProc;
4026747b715Smrg            (*k)->CtrlProc = it->CtrlProc;
4036747b715Smrg            (*k)->ctrl     = it->ctrl;
4046747b715Smrg            if ((*k)->xkb_sli)
4056747b715Smrg                XkbFreeSrvLedInfo((*k)->xkb_sli);
4066747b715Smrg            (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
4076747b715Smrg
4086747b715Smrg            k = &(*k)->next;
4096747b715Smrg        }
4106747b715Smrg    } else if (to->kbdfeed && !from->kbdfeed)
4116747b715Smrg    {
4126747b715Smrg        ClassesPtr classes;
4136747b715Smrg        classes = to->unused_classes;
4146747b715Smrg        classes->kbdfeed = to->kbdfeed;
4156747b715Smrg        to->kbdfeed      = NULL;
4166747b715Smrg    }
4174642e01fSmrg
4184642e01fSmrg    if (from->key)
4194642e01fSmrg    {
4204642e01fSmrg        if (!to->key)
4214642e01fSmrg        {
4226747b715Smrg            classes = to->unused_classes;
4234642e01fSmrg            to->key = classes->key;
4244642e01fSmrg            if (!to->key)
4256747b715Smrg                InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
4266747b715Smrg            else
4276747b715Smrg                classes->key = NULL;
4286747b715Smrg        }
4296747b715Smrg
4306747b715Smrg        CopyKeyClass(from, to);
4316747b715Smrg    } else if (to->key && !from->key)
4326747b715Smrg    {
4336747b715Smrg        ClassesPtr classes;
4346747b715Smrg        classes = to->unused_classes;
4356747b715Smrg        classes->key = to->key;
4366747b715Smrg        to->key      = NULL;
4376747b715Smrg    }
4386747b715Smrg
4396747b715Smrg    /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps
4406747b715Smrg     * pointer point into the xkbInfo->desc struct.  XkbCopySrvLedInfo
4416747b715Smrg     * didn't update the pointers so we need to do it manually here.
4426747b715Smrg     */
4436747b715Smrg    if (to->kbdfeed)
4446747b715Smrg    {
4456747b715Smrg        KbdFeedbackPtr k;
4466747b715Smrg
4476747b715Smrg        for (k = to->kbdfeed; k; k = k->next)
4486747b715Smrg        {
4496747b715Smrg            if (!k->xkb_sli)
4506747b715Smrg                continue;
4516747b715Smrg            if (k->xkb_sli->flags & XkbSLI_IsDefault)
4524642e01fSmrg            {
4536747b715Smrg                k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators;
4546747b715Smrg                k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps;
4556747b715Smrg            }
4566747b715Smrg        }
4576747b715Smrg    }
4586747b715Smrg
4596747b715Smrg    /* We can't just copy over the focus class. When an app sets the focus,
4606747b715Smrg     * it'll do so on the master device. Copying the SDs focus means losing
4616747b715Smrg     * the focus.
4626747b715Smrg     * So we only copy the focus class if the device didn't have one,
4636747b715Smrg     * otherwise we leave it as it is.
4646747b715Smrg     */
4656747b715Smrg    if (from->focus)
4666747b715Smrg    {
4676747b715Smrg        if (!to->focus)
4686747b715Smrg        {
4696747b715Smrg            WindowPtr *oldTrace;
4706747b715Smrg
4716747b715Smrg            classes = to->unused_classes;
4726747b715Smrg            to->focus = classes->focus;
4736747b715Smrg            if (!to->focus)
4746747b715Smrg            {
4756747b715Smrg                to->focus = calloc(1, sizeof(FocusClassRec));
4766747b715Smrg                if (!to->focus)
4774642e01fSmrg                    FatalError("[Xi] no memory for class shift.\n");
4784642e01fSmrg            } else
4796747b715Smrg                classes->focus = NULL;
4806747b715Smrg
4816747b715Smrg            oldTrace = to->focus->trace;
4826747b715Smrg            memcpy(to->focus, from->focus, sizeof(FocusClassRec));
4836747b715Smrg            to->focus->trace = realloc(oldTrace,
4846747b715Smrg                                  to->focus->traceSize * sizeof(WindowPtr));
4856747b715Smrg            if (!to->focus->trace && to->focus->traceSize)
4866747b715Smrg                FatalError("[Xi] no memory for trace.\n");
4876747b715Smrg            memcpy(to->focus->trace, from->focus->trace,
4886747b715Smrg                    from->focus->traceSize * sizeof(WindowPtr));
4896747b715Smrg            to->focus->sourceid = from->id;
4904642e01fSmrg        }
4916747b715Smrg    } else if (to->focus)
4926747b715Smrg    {
4936747b715Smrg        ClassesPtr classes;
4946747b715Smrg        classes = to->unused_classes;
4956747b715Smrg        classes->focus = to->focus;
4966747b715Smrg        to->focus      = NULL;
4976747b715Smrg    }
4984642e01fSmrg
4996747b715Smrg}
5004642e01fSmrg
5016747b715Smrgstatic void
5026747b715SmrgDeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
5036747b715Smrg{
5046747b715Smrg    ClassesPtr classes;
5056747b715Smrg
5066747b715Smrg    /* Feedback classes must be copied first */
5076747b715Smrg    if (from->ptrfeed)
5086747b715Smrg    {
5096747b715Smrg        PtrFeedbackPtr *p, it;
5106747b715Smrg        if (!to->ptrfeed)
5114642e01fSmrg        {
5126747b715Smrg            classes = to->unused_classes;
5136747b715Smrg            to->ptrfeed = classes->ptrfeed;
5146747b715Smrg            classes->ptrfeed = NULL;
5154642e01fSmrg        }
5164642e01fSmrg
5176747b715Smrg        p = &to->ptrfeed;
5186747b715Smrg        for (it = from->ptrfeed; it; it = it->next)
5196747b715Smrg        {
5206747b715Smrg            if (!(*p))
5216747b715Smrg            {
5226747b715Smrg                *p = calloc(1, sizeof(PtrFeedbackClassRec));
5236747b715Smrg                if (!*p)
5246747b715Smrg                {
5256747b715Smrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
5266747b715Smrg                    return;
5276747b715Smrg                }
5286747b715Smrg            }
5296747b715Smrg            (*p)->CtrlProc = it->CtrlProc;
5306747b715Smrg            (*p)->ctrl     = it->ctrl;
5314642e01fSmrg
5326747b715Smrg            p = &(*p)->next;
5336747b715Smrg        }
5346747b715Smrg    } else if (to->ptrfeed && !from->ptrfeed)
5354642e01fSmrg    {
5364642e01fSmrg        ClassesPtr classes;
5376747b715Smrg        classes = to->unused_classes;
5386747b715Smrg        classes->ptrfeed = to->ptrfeed;
5396747b715Smrg        to->ptrfeed      = NULL;
5404642e01fSmrg    }
5414642e01fSmrg
5424642e01fSmrg    if (from->valuator)
5434642e01fSmrg    {
5444642e01fSmrg        ValuatorClassPtr v;
5454642e01fSmrg        if (!to->valuator)
5464642e01fSmrg        {
5476747b715Smrg            classes = to->unused_classes;
5484642e01fSmrg            to->valuator = classes->valuator;
5494642e01fSmrg            if (to->valuator)
5504642e01fSmrg                classes->valuator = NULL;
5514642e01fSmrg        }
5524642e01fSmrg
5536747b715Smrg        to->valuator = realloc(to->valuator, sizeof(ValuatorClassRec) +
5544642e01fSmrg                from->valuator->numAxes * sizeof(AxisInfo) +
5556747b715Smrg                from->valuator->numAxes * sizeof(double));
5564642e01fSmrg        v = to->valuator;
5574642e01fSmrg        if (!v)
5584642e01fSmrg            FatalError("[Xi] no memory for class shift.\n");
5594642e01fSmrg
5604642e01fSmrg        v->numAxes = from->valuator->numAxes;
5614642e01fSmrg        v->axes = (AxisInfoPtr)&v[1];
5624642e01fSmrg        memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
5634642e01fSmrg
5646747b715Smrg        v->axisVal = (double*)(v->axes + from->valuator->numAxes);
5656747b715Smrg        v->sourceid = from->id;
5666747b715Smrg        v->mode = from->valuator->mode;
5674642e01fSmrg    } else if (to->valuator && !from->valuator)
5684642e01fSmrg    {
5694642e01fSmrg        ClassesPtr classes;
5706747b715Smrg        classes = to->unused_classes;
5714642e01fSmrg        classes->valuator = to->valuator;
5724642e01fSmrg        to->valuator      = NULL;
5734642e01fSmrg    }
5744642e01fSmrg
5754642e01fSmrg    if (from->button)
5764642e01fSmrg    {
5774642e01fSmrg        if (!to->button)
5784642e01fSmrg        {
5796747b715Smrg            classes = to->unused_classes;
5804642e01fSmrg            to->button = classes->button;
5814642e01fSmrg            if (!to->button)
5824642e01fSmrg            {
5836747b715Smrg                to->button = calloc(1, sizeof(ButtonClassRec));
5844642e01fSmrg                if (!to->button)
5854642e01fSmrg                    FatalError("[Xi] no memory for class shift.\n");
5864642e01fSmrg            } else
5874642e01fSmrg                classes->button = NULL;
5884642e01fSmrg        }
5894642e01fSmrg
5904642e01fSmrg        if (from->button->xkb_acts)
5914642e01fSmrg        {
5924642e01fSmrg            if (!to->button->xkb_acts)
5934642e01fSmrg            {
5946747b715Smrg                to->button->xkb_acts = calloc(1, sizeof(XkbAction));
5954642e01fSmrg                if (!to->button->xkb_acts)
5964642e01fSmrg                    FatalError("[Xi] not enough memory for xkb_acts.\n");
5974642e01fSmrg            }
5984642e01fSmrg            memcpy(to->button->xkb_acts, from->button->xkb_acts,
5994642e01fSmrg                    sizeof(XkbAction));
6004642e01fSmrg        } else
6016747b715Smrg            free(to->button->xkb_acts);
6026747b715Smrg
6036747b715Smrg         memcpy(to->button->labels, from->button->labels,
6046747b715Smrg                from->button->numButtons * sizeof(Atom));
6056747b715Smrg        to->button->sourceid = from->id;
6064642e01fSmrg    } else if (to->button && !from->button)
6074642e01fSmrg    {
6084642e01fSmrg        ClassesPtr classes;
6096747b715Smrg        classes = to->unused_classes;
6104642e01fSmrg        classes->button = to->button;
6114642e01fSmrg        to->button      = NULL;
6124642e01fSmrg    }
6134642e01fSmrg
6144642e01fSmrg    if (from->proximity)
6154642e01fSmrg    {
6164642e01fSmrg        if (!to->proximity)
6174642e01fSmrg        {
6186747b715Smrg            classes = to->unused_classes;
6194642e01fSmrg            to->proximity = classes->proximity;
6204642e01fSmrg            if (!to->proximity)
6214642e01fSmrg            {
6226747b715Smrg                to->proximity = calloc(1, sizeof(ProximityClassRec));
6234642e01fSmrg                if (!to->proximity)
6244642e01fSmrg                    FatalError("[Xi] no memory for class shift.\n");
6254642e01fSmrg            } else
6264642e01fSmrg                classes->proximity = NULL;
6274642e01fSmrg        }
6284642e01fSmrg        memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
6296747b715Smrg        to->proximity->sourceid = from->id;
6304642e01fSmrg    } else if (to->proximity)
6314642e01fSmrg    {
6324642e01fSmrg        ClassesPtr classes;
6336747b715Smrg        classes = to->unused_classes;
6344642e01fSmrg        classes->proximity = to->proximity;
6354642e01fSmrg        to->proximity      = NULL;
6364642e01fSmrg    }
6374642e01fSmrg
6384642e01fSmrg    if (from->absolute)
6394642e01fSmrg    {
6404642e01fSmrg        if (!to->absolute)
6414642e01fSmrg        {
6426747b715Smrg            classes = to->unused_classes;
6434642e01fSmrg            to->absolute = classes->absolute;
6444642e01fSmrg            if (!to->absolute)
6454642e01fSmrg            {
6466747b715Smrg                to->absolute = calloc(1, sizeof(AbsoluteClassRec));
6474642e01fSmrg                if (!to->absolute)
6484642e01fSmrg                    FatalError("[Xi] no memory for class shift.\n");
6494642e01fSmrg            } else
6504642e01fSmrg                classes->absolute = NULL;
6514642e01fSmrg        }
6524642e01fSmrg        memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec));
6536747b715Smrg        to->absolute->sourceid = from->id;
6544642e01fSmrg    } else if (to->absolute)
6554642e01fSmrg    {
6566747b715Smrg        ClassesPtr classes;
6576747b715Smrg        classes = to->unused_classes;
6586747b715Smrg        classes->absolute = to->absolute;
6596747b715Smrg        to->absolute      = NULL;
6606747b715Smrg    }
6616747b715Smrg}
6626747b715Smrg
6636747b715Smrg/**
6646747b715Smrg * Copies the CONTENT of the classes of device from into the classes in device
6656747b715Smrg * to. From and to are identical after finishing.
6666747b715Smrg *
6676747b715Smrg * If to does not have classes from currenly has, the classes are stored in
6686747b715Smrg * to's devPrivates system. Later, we recover it again from there if needed.
6696747b715Smrg * Saves a few memory allocations.
6706747b715Smrg */
6716747b715Smrgvoid
6726747b715SmrgDeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dce)
6736747b715Smrg{
6746747b715Smrg    /* generic feedback classes, not tied to pointer and/or keyboard */
6756747b715Smrg    DeepCopyFeedbackClasses(from, to);
6766747b715Smrg
6776747b715Smrg    if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
6786747b715Smrg        DeepCopyKeyboardClasses(from, to);
6796747b715Smrg    if ((dce->flags & DEVCHANGE_POINTER_EVENT))
6806747b715Smrg        DeepCopyPointerClasses(from, to);
6816747b715Smrg}
6826747b715Smrg
6836747b715Smrg
6846747b715Smrg/**
6856747b715Smrg * Send an XI2 DeviceChangedEvent to all interested clients.
6866747b715Smrg */
6876747b715Smrgvoid
6886747b715SmrgXISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, DeviceChangedEvent *dce)
6896747b715Smrg{
6906747b715Smrg    xXIDeviceChangedEvent *dcce;
6916747b715Smrg    int rc;
6926747b715Smrg
6936747b715Smrg    rc = EventToXI2((InternalEvent*)dce, (xEvent**)&dcce);
6946747b715Smrg    if (rc != Success)
6956747b715Smrg    {
6966747b715Smrg        ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc);
6976747b715Smrg        return;
6984642e01fSmrg    }
6996747b715Smrg
7006747b715Smrg    /* we don't actually swap if there's a NullClient, swapping is done
7016747b715Smrg     * later when event is delivered. */
7026747b715Smrg    SendEventToAllWindows(master, XI_DeviceChangedMask, (xEvent*)dcce, 1);
7036747b715Smrg    free(dcce);
7044642e01fSmrg}
7054642e01fSmrg
7066747b715Smrgstatic void
7076747b715SmrgChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
7086747b715Smrg{
7096747b715Smrg    DeviceIntPtr slave;
7106747b715Smrg    int rc;
7116747b715Smrg
7126747b715Smrg    /* For now, we don't have devices that change physically. */
7136747b715Smrg    if (!IsMaster(device))
7146747b715Smrg        return;
7156747b715Smrg
7166747b715Smrg    rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
7176747b715Smrg
7186747b715Smrg    if (rc != Success)
7196747b715Smrg        return; /* Device has disappeared */
7206747b715Smrg
7216747b715Smrg    if (!slave->u.master)
7226747b715Smrg        return; /* set floating since the event */
7236747b715Smrg
7246747b715Smrg    if (slave->u.master->id != dce->masterid)
7256747b715Smrg        return; /* not our slave anymore, don't care */
7266747b715Smrg
7276747b715Smrg    /* FIXME: we probably need to send a DCE for the new slave now */
7286747b715Smrg
7296747b715Smrg    device->public.devicePrivate = slave->public.devicePrivate;
7306747b715Smrg
7316747b715Smrg    /* FIXME: the classes may have changed since we generated the event. */
7326747b715Smrg    DeepCopyDeviceClasses(slave, device, dce);
7336747b715Smrg    XISendDeviceChangedEvent(slave, device, dce);
7346747b715Smrg}
7354642e01fSmrg
7364642e01fSmrg/**
7374642e01fSmrg * Update the device state according to the data in the event.
7384642e01fSmrg *
7394642e01fSmrg * return values are
7404642e01fSmrg *   DEFAULT ... process as normal
7414642e01fSmrg *   DONT_PROCESS ... return immediately from caller
7424642e01fSmrg */
7434642e01fSmrg#define DEFAULT 0
7444642e01fSmrg#define DONT_PROCESS 1
7454642e01fSmrgint
7466747b715SmrgUpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
7474642e01fSmrg{
7484642e01fSmrg    int i;
7494642e01fSmrg    int key = 0,
7506747b715Smrg        bit = 0,
7516747b715Smrg        last_valuator;
7524642e01fSmrg
7534642e01fSmrg    KeyClassPtr k       = NULL;
7544642e01fSmrg    ButtonClassPtr b    = NULL;
7554642e01fSmrg    ValuatorClassPtr v  = NULL;
7564642e01fSmrg
7576747b715Smrg    /* This event is always the first we get, before the actual events with
7586747b715Smrg     * the data. However, the way how the DDX is set up, "device" will
7596747b715Smrg     * actually be the slave device that caused the event.
7606747b715Smrg     */
7616747b715Smrg    switch(event->type)
7626747b715Smrg    {
7636747b715Smrg        case ET_DeviceChanged:
7646747b715Smrg            ChangeMasterDeviceClasses(device, (DeviceChangedEvent*)event);
7656747b715Smrg            return DONT_PROCESS; /* event has been sent already */
7666747b715Smrg        case ET_Motion:
7676747b715Smrg        case ET_ButtonPress:
7686747b715Smrg        case ET_ButtonRelease:
7696747b715Smrg        case ET_KeyPress:
7706747b715Smrg        case ET_KeyRelease:
7716747b715Smrg        case ET_ProximityIn:
7726747b715Smrg        case ET_ProximityOut:
7736747b715Smrg            break;
7746747b715Smrg        default:
7756747b715Smrg            /* other events don't update the device */
7766747b715Smrg            return DEFAULT;
7776747b715Smrg    }
7784642e01fSmrg
7794642e01fSmrg    k = device->key;
7804642e01fSmrg    v = device->valuator;
7814642e01fSmrg    b = device->button;
7824642e01fSmrg
7836747b715Smrg    key = event->detail.key;
7846747b715Smrg    bit = 1 << (key & 7);
7854642e01fSmrg
7866747b715Smrg    /* Update device axis */
7876747b715Smrg    /* Check valuators first */
7886747b715Smrg    last_valuator = -1;
7896747b715Smrg    for (i = 0; i < MAX_VALUATORS; i++)
7904642e01fSmrg    {
7916747b715Smrg        if (BitIsOn(&event->valuators.mask, i))
7926747b715Smrg        {
7936747b715Smrg            if (!v)
7946747b715Smrg            {
7956747b715Smrg                ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
7966747b715Smrg                        "Ignoring event.\n", device->name);
7976747b715Smrg                return DONT_PROCESS;
7986747b715Smrg            } else if (v->numAxes < i)
7996747b715Smrg            {
8006747b715Smrg                ErrorF("[Xi] Too many valuators reported for device '%s'. "
8016747b715Smrg                        "Ignoring event.\n", device->name);
8026747b715Smrg                return DONT_PROCESS;
8036747b715Smrg            }
8046747b715Smrg            last_valuator = i;
8056747b715Smrg        }
8064642e01fSmrg    }
8074642e01fSmrg
8086747b715Smrg    for (i = 0; i <= last_valuator && i < v->numAxes; i++)
8096747b715Smrg    {
8106747b715Smrg        if (BitIsOn(&event->valuators.mask, i))
8116747b715Smrg        {
8126747b715Smrg            /* XXX: Relative/Absolute mode */
8136747b715Smrg            v->axisVal[i] = event->valuators.data[i];
8146747b715Smrg            v->axisVal[i] += (event->valuators.data_frac[i] * 1.0f / (1 << 16) / (1 << 16));
8156747b715Smrg        }
8164642e01fSmrg    }
81705b261ecSmrg
8186747b715Smrg    if (event->type == ET_KeyPress) {
81905b261ecSmrg        if (!k)
8204642e01fSmrg            return DONT_PROCESS;
82105b261ecSmrg
8226747b715Smrg	/* don't allow ddx to generate multiple downs, but repeats are okay */
8236747b715Smrg	if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
8246747b715Smrg	    return DONT_PROCESS;
8256747b715Smrg
8264642e01fSmrg	if (device->valuator)
8274642e01fSmrg	    device->valuator->motionHintWindow = NullWindow;
8286747b715Smrg	set_key_down(device, key, KEY_PROCESSED);
8296747b715Smrg    } else if (event->type == ET_KeyRelease) {
83005b261ecSmrg        if (!k)
8314642e01fSmrg            return DONT_PROCESS;
83205b261ecSmrg
8336747b715Smrg	if (!key_is_down(device, key, KEY_PROCESSED))	/* guard against duplicates */
8344642e01fSmrg	    return DONT_PROCESS;
8354642e01fSmrg	if (device->valuator)
8364642e01fSmrg	    device->valuator->motionHintWindow = NullWindow;
8376747b715Smrg	set_key_up(device, key, KEY_PROCESSED);
8386747b715Smrg    } else if (event->type == ET_ButtonPress) {
8396747b715Smrg        Mask mask;
84005b261ecSmrg        if (!b)
8414642e01fSmrg            return DONT_PROCESS;
8424642e01fSmrg
8436747b715Smrg        if (button_is_down(device, key, BUTTON_PROCESSED))
8444642e01fSmrg            return DONT_PROCESS;
8456747b715Smrg
8466747b715Smrg        set_button_down(device, key, BUTTON_PROCESSED);
8474642e01fSmrg	if (device->valuator)
8484642e01fSmrg	    device->valuator->motionHintWindow = NullWindow;
8494642e01fSmrg        if (!b->map[key])
8504642e01fSmrg            return DONT_PROCESS;
8514642e01fSmrg        b->buttonsDown++;
85205b261ecSmrg	b->motionMask = DeviceButtonMotionMask;
8534642e01fSmrg        if (b->map[key] <= 5)
8544642e01fSmrg	    b->state |= (Button1Mask >> 1) << b->map[key];
8556747b715Smrg
8566747b715Smrg        /* Add state and motionMask to the filter for this event */
8576747b715Smrg        mask = DevicePointerMotionMask | b->state | b->motionMask;
8586747b715Smrg        SetMaskForEvent(device->id, mask, DeviceMotionNotify);
8596747b715Smrg        mask = PointerMotionMask | b->state | b->motionMask;
8606747b715Smrg        SetMaskForEvent(device->id, mask, MotionNotify);
8616747b715Smrg    } else if (event->type == ET_ButtonRelease) {
8626747b715Smrg        Mask mask;
86305b261ecSmrg        if (!b)
8644642e01fSmrg            return DONT_PROCESS;
8654642e01fSmrg
8666747b715Smrg        if (!button_is_down(device, key, BUTTON_PROCESSED))
8674642e01fSmrg            return DONT_PROCESS;
8686747b715Smrg        if (IsMaster(device)) {
8694642e01fSmrg            DeviceIntPtr sd;
8704642e01fSmrg
8714642e01fSmrg            /*
8724642e01fSmrg             * Leave the button down if any slave has the
8734642e01fSmrg             * button still down. Note that this depends on the
8744642e01fSmrg             * event being delivered through the slave first
8754642e01fSmrg             */
8764642e01fSmrg            for (sd = inputInfo.devices; sd; sd = sd->next) {
8776747b715Smrg                if (IsMaster(sd) || sd->u.master != device)
8784642e01fSmrg                    continue;
8796747b715Smrg                if (!sd->button)
8806747b715Smrg                    continue;
8818223e2f2Smrg                for (i = 1; i <= sd->button->numButtons; i++)
8828223e2f2Smrg                    if (sd->button->map[i] == key &&
8838223e2f2Smrg                        button_is_down(sd, i, BUTTON_PROCESSED))
8848223e2f2Smrg                        return DONT_PROCESS;
8854642e01fSmrg            }
8864642e01fSmrg        }
8876747b715Smrg        set_button_up(device, key, BUTTON_PROCESSED);
8884642e01fSmrg	if (device->valuator)
8894642e01fSmrg	    device->valuator->motionHintWindow = NullWindow;
8904642e01fSmrg        if (!b->map[key])
8914642e01fSmrg            return DONT_PROCESS;
89205b261ecSmrg        if (b->buttonsDown >= 1 && !--b->buttonsDown)
89305b261ecSmrg	    b->motionMask = 0;
8944642e01fSmrg	if (b->map[key] <= 5)
8954642e01fSmrg	    b->state &= ~((Button1Mask >> 1) << b->map[key]);
8966747b715Smrg
8976747b715Smrg        /* Add state and motionMask to the filter for this event */
8986747b715Smrg        mask = DevicePointerMotionMask | b->state | b->motionMask;
8996747b715Smrg        SetMaskForEvent(device->id, mask, DeviceMotionNotify);
9006747b715Smrg        mask = PointerMotionMask | b->state | b->motionMask;
9016747b715Smrg        SetMaskForEvent(device->id, mask, MotionNotify);
9026747b715Smrg    } else if (event->type == ET_ProximityIn)
9034642e01fSmrg	device->valuator->mode &= ~OutOfProximity;
9046747b715Smrg    else if (event->type == ET_ProximityOut)
9054642e01fSmrg	device->valuator->mode |= OutOfProximity;
9064642e01fSmrg
9074642e01fSmrg    return DEFAULT;
9084642e01fSmrg}
9094642e01fSmrg
9106747b715Smrgstatic void
9116747b715SmrgProcessRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
9126747b715Smrg{
9136747b715Smrg    GrabPtr grab = device->deviceGrab.grab;
9146747b715Smrg
9156747b715Smrg    if (grab)
9166747b715Smrg        DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE);
9176747b715Smrg    else { /* deliver to all root windows */
9186747b715Smrg        xEvent *xi;
9196747b715Smrg        int i;
9206747b715Smrg
9216747b715Smrg        i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi);
9226747b715Smrg        if (i != Success)
9236747b715Smrg        {
9246747b715Smrg            ErrorF("[Xi] %s: XI2 conversion failed in ProcessRawEvent (%d)\n",
9256747b715Smrg                    device->name, i);
9266747b715Smrg            return;
9276747b715Smrg        }
9286747b715Smrg
9296747b715Smrg        for (i = 0; i < screenInfo.numScreens; i++)
9306747b715Smrg            DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1,
9316747b715Smrg                                  GetEventFilter(device, xi), NULL);
9326747b715Smrg        free(xi);
9336747b715Smrg    }
9346747b715Smrg}
9356747b715Smrg
9364642e01fSmrg/**
9374642e01fSmrg * Main device event processing function.
9384642e01fSmrg * Called from when processing the events from the event queue.
9394642e01fSmrg *
9404642e01fSmrg */
9414642e01fSmrgvoid
9426747b715SmrgProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
9434642e01fSmrg{
9446747b715Smrg    GrabPtr grab;
9454642e01fSmrg    Bool deactivateDeviceGrab = FALSE;
9464642e01fSmrg    int key = 0, rootX, rootY;
9474642e01fSmrg    ButtonClassPtr b;
9484642e01fSmrg    KeyClassPtr k;
9494642e01fSmrg    ValuatorClassPtr v;
9504642e01fSmrg    int ret = 0;
9516747b715Smrg    int state, i;
9524642e01fSmrg    DeviceIntPtr mouse = NULL, kbd = NULL;
9536747b715Smrg    DeviceEvent *event = &ev->device_event;
9546747b715Smrg
9556747b715Smrg    CHECKEVENT(ev);
9566747b715Smrg
9576747b715Smrg    if (ev->any.type == ET_RawKeyPress ||
9586747b715Smrg        ev->any.type == ET_RawKeyRelease ||
9596747b715Smrg        ev->any.type == ET_RawButtonPress ||
9606747b715Smrg        ev->any.type == ET_RawButtonRelease ||
9616747b715Smrg        ev->any.type == ET_RawMotion)
9626747b715Smrg    {
9636747b715Smrg        ProcessRawEvent(&ev->raw_event, device);
9646747b715Smrg        return;
9656747b715Smrg    }
9664642e01fSmrg
9674642e01fSmrg    if (IsPointerDevice(device))
9684642e01fSmrg    {
9694642e01fSmrg        kbd = GetPairedDevice(device);
9704642e01fSmrg        mouse = device;
9714642e01fSmrg        if (!kbd->key) /* can happen with floating SDs */
9724642e01fSmrg            kbd = NULL;
9734642e01fSmrg    } else
9744642e01fSmrg    {
9754642e01fSmrg        mouse = GetPairedDevice(device);
9764642e01fSmrg        kbd = device;
9774642e01fSmrg        if (!mouse->valuator || !mouse->button) /* may be float. SDs */
9784642e01fSmrg            mouse = NULL;
9794642e01fSmrg    }
9804642e01fSmrg
9814642e01fSmrg    /* State needs to be assembled BEFORE the device is updated. */
9826747b715Smrg    state = (kbd && kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->state) : 0;
9836747b715Smrg    state |= (mouse && mouse->button) ? (mouse->button->state) : 0;
9846747b715Smrg
9856747b715Smrg    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
9866747b715Smrg        if (BitIsOn(mouse->button->down, i))
9876747b715Smrg            SetBit(event->buttons, i);
9886747b715Smrg
9896747b715Smrg    if (kbd && kbd->key)
9906747b715Smrg    {
9916747b715Smrg        XkbStatePtr state;
9926747b715Smrg        /* we need the state before the event happens */
9936747b715Smrg        if (event->type == ET_KeyPress || event->type == ET_KeyRelease)
9946747b715Smrg            state = &kbd->key->xkbInfo->prev_state;
9956747b715Smrg        else
9966747b715Smrg            state = &kbd->key->xkbInfo->state;
9976747b715Smrg
9986747b715Smrg        event->mods.base = state->base_mods;
9996747b715Smrg        event->mods.latched = state->latched_mods;
10006747b715Smrg        event->mods.locked = state->locked_mods;
10016747b715Smrg        event->mods.effective = state->mods;
10026747b715Smrg
10036747b715Smrg        event->group.base = state->base_group;
10046747b715Smrg        event->group.latched = state->latched_group;
10056747b715Smrg        event->group.locked = state->locked_group;
10066747b715Smrg        event->group.effective = state->group;
10076747b715Smrg    }
10084642e01fSmrg
10096747b715Smrg    ret = UpdateDeviceState(device, event);
10104642e01fSmrg    if (ret == DONT_PROCESS)
10114642e01fSmrg        return;
10124642e01fSmrg
10134642e01fSmrg    v = device->valuator;
10144642e01fSmrg    b = device->button;
10154642e01fSmrg    k = device->key;
10164642e01fSmrg
10176747b715Smrg    if (IsMaster(device) || !device->u.master)
10186747b715Smrg        CheckMotion(event, device);
10194642e01fSmrg
10206747b715Smrg    switch (event->type)
10216747b715Smrg    {
10226747b715Smrg        case ET_Motion:
10236747b715Smrg        case ET_ButtonPress:
10246747b715Smrg        case ET_ButtonRelease:
10256747b715Smrg        case ET_KeyPress:
10266747b715Smrg        case ET_KeyRelease:
10276747b715Smrg        case ET_ProximityIn:
10286747b715Smrg        case ET_ProximityOut:
10296747b715Smrg            GetSpritePosition(device, &rootX, &rootY);
10306747b715Smrg            event->root_x = rootX;
10316747b715Smrg            event->root_y = rootY;
10326747b715Smrg            NoticeEventTime((InternalEvent*)event);
10336747b715Smrg            event->corestate = state;
10346747b715Smrg            key = event->detail.key;
10356747b715Smrg            break;
10366747b715Smrg        default:
10376747b715Smrg            break;
10384642e01fSmrg    }
10396747b715Smrg
10406747b715Smrg    if (DeviceEventCallback && !syncEvents.playingEvents) {
10414642e01fSmrg	DeviceEventInfoRec eventinfo;
10426747b715Smrg	SpritePtr pSprite = device->spriteInfo->sprite;
10434642e01fSmrg
10446747b715Smrg	/* see comment in EnqueueEvents regarding the next three lines */
10456747b715Smrg	if (ev->any.type == ET_Motion)
10466747b715Smrg	    ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
10474642e01fSmrg
10486747b715Smrg	eventinfo.device = device;
10496747b715Smrg	eventinfo.event = ev;
10506747b715Smrg	CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
10514642e01fSmrg    }
10524642e01fSmrg
10536747b715Smrg    grab = device->deviceGrab.grab;
10544642e01fSmrg
10556747b715Smrg    switch(event->type)
10566747b715Smrg    {
10576747b715Smrg        case ET_KeyPress:
10586747b715Smrg            if (!grab && CheckDeviceGrabs(device, event, 0)) {
10596747b715Smrg                device->deviceGrab.activatingKey = key;
10606747b715Smrg                return;
10616747b715Smrg            }
10626747b715Smrg            break;
10636747b715Smrg        case ET_KeyRelease:
10646747b715Smrg            if (grab && device->deviceGrab.fromPassiveGrab &&
10656747b715Smrg                (key == device->deviceGrab.activatingKey) &&
10666747b715Smrg                (device->deviceGrab.grab->type == KeyPress ||
10676747b715Smrg                 device->deviceGrab.grab->type == DeviceKeyPress ||
10686747b715Smrg                 device->deviceGrab.grab->type == XI_KeyPress))
10696747b715Smrg                deactivateDeviceGrab = TRUE;
10706747b715Smrg            break;
10716747b715Smrg        case ET_ButtonPress:
10726747b715Smrg            event->detail.button = b->map[key];
10736747b715Smrg            if (!event->detail.button) { /* there's no button 0 */
10746747b715Smrg                event->detail.button = key;
10756747b715Smrg                return;
10766747b715Smrg            }
10776747b715Smrg            if (!grab && CheckDeviceGrabs(device, event, 0))
10786747b715Smrg            {
10796747b715Smrg                /* if a passive grab was activated, the event has been sent
10806747b715Smrg                 * already */
10816747b715Smrg                return;
10826747b715Smrg            }
10836747b715Smrg            break;
10846747b715Smrg        case ET_ButtonRelease:
10856747b715Smrg            event->detail.button = b->map[key];
10866747b715Smrg            if (!event->detail.button) { /* there's no button 0 */
10876747b715Smrg                event->detail.button = key;
10886747b715Smrg                return;
10896747b715Smrg            }
10906747b715Smrg            if (grab && !b->buttonsDown &&
10916747b715Smrg                device->deviceGrab.fromPassiveGrab &&
10926747b715Smrg                (device->deviceGrab.grab->type == ButtonPress ||
10936747b715Smrg                 device->deviceGrab.grab->type == DeviceButtonPress ||
10946747b715Smrg                 device->deviceGrab.grab->type == XI_ButtonPress))
10956747b715Smrg                deactivateDeviceGrab = TRUE;
10966747b715Smrg        default:
10976747b715Smrg            break;
10984642e01fSmrg    }
109905b261ecSmrg
11006747b715Smrg
110105b261ecSmrg    if (grab)
11026747b715Smrg        DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
11036747b715Smrg    else if (device->focus && !IsPointerEvent((InternalEvent*)ev))
11046747b715Smrg        DeliverFocusedEvent(device, (InternalEvent*)event,
11056747b715Smrg                            GetSpriteWindow(device));
110605b261ecSmrg    else
11076747b715Smrg        DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event,
11086747b715Smrg                            NullGrab, NullWindow, device);
110905b261ecSmrg
111005b261ecSmrg    if (deactivateDeviceGrab == TRUE)
11114642e01fSmrg	(*device->deviceGrab.DeactivateGrab) (device);
11126747b715Smrg    event->detail.key = key;
111305b261ecSmrg}
111405b261ecSmrg
11156747b715Smrgint
111605b261ecSmrgInitProximityClassDeviceStruct(DeviceIntPtr dev)
111705b261ecSmrg{
111805b261ecSmrg    ProximityClassPtr proxc;
111905b261ecSmrg
11206747b715Smrg    proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
112105b261ecSmrg    if (!proxc)
112205b261ecSmrg	return FALSE;
11236747b715Smrg    proxc->sourceid = dev->id;
112405b261ecSmrg    dev->proximity = proxc;
112505b261ecSmrg    return TRUE;
112605b261ecSmrg}
112705b261ecSmrg
11284642e01fSmrg/**
11294642e01fSmrg * Initialise the device's valuators. The memory must already be allocated,
11304642e01fSmrg * this function merely inits the matching axis (specified through axnum) to
11314642e01fSmrg * sane values.
11324642e01fSmrg *
11334642e01fSmrg * It is a condition that (minval < maxval).
11344642e01fSmrg *
11354642e01fSmrg * @see InitValuatorClassDeviceStruct
11364642e01fSmrg */
11376747b715Smrgvoid
11386747b715SmrgInitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
113905b261ecSmrg		       int resolution, int min_res, int max_res)
114005b261ecSmrg{
114105b261ecSmrg    AxisInfoPtr ax;
11424642e01fSmrg
11434642e01fSmrg    if (!dev || !dev->valuator || minval > maxval)
114405b261ecSmrg        return;
11456747b715Smrg    if (axnum >= dev->valuator->numAxes)
11466747b715Smrg        return;
114705b261ecSmrg
114805b261ecSmrg    ax = dev->valuator->axes + axnum;
114905b261ecSmrg
115005b261ecSmrg    ax->min_value = minval;
115105b261ecSmrg    ax->max_value = maxval;
115205b261ecSmrg    ax->resolution = resolution;
115305b261ecSmrg    ax->min_resolution = min_res;
115405b261ecSmrg    ax->max_resolution = max_res;
11556747b715Smrg    ax->label = label;
115605b261ecSmrg}
115705b261ecSmrg
115805b261ecSmrgstatic void
115905b261ecSmrgFixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
116005b261ecSmrg		     ButtonClassPtr b, ValuatorClassPtr v, int first)
116105b261ecSmrg{
116205b261ecSmrg    ev->type = DeviceStateNotify;
116305b261ecSmrg    ev->deviceid = dev->id;
116405b261ecSmrg    ev->time = currentTime.milliseconds;
116505b261ecSmrg    ev->classes_reported = 0;
116605b261ecSmrg    ev->num_keys = 0;
116705b261ecSmrg    ev->num_buttons = 0;
116805b261ecSmrg    ev->num_valuators = 0;
116905b261ecSmrg
117005b261ecSmrg    if (b) {
117105b261ecSmrg	ev->classes_reported |= (1 << ButtonClass);
117205b261ecSmrg	ev->num_buttons = b->numButtons;
11734642e01fSmrg	memcpy((char*)ev->buttons, (char*)b->down, 4);
117405b261ecSmrg    } else if (k) {
117505b261ecSmrg	ev->classes_reported |= (1 << KeyClass);
11766747b715Smrg	ev->num_keys = k->xkbInfo->desc->max_key_code -
11776747b715Smrg                       k->xkbInfo->desc->min_key_code;
117805b261ecSmrg	memmove((char *)&ev->keys[0], (char *)k->down, 4);
117905b261ecSmrg    }
118005b261ecSmrg    if (v) {
118105b261ecSmrg	int nval = v->numAxes - first;
118205b261ecSmrg
118305b261ecSmrg	ev->classes_reported |= (1 << ValuatorClass);
118405b261ecSmrg	ev->classes_reported |= (dev->valuator->mode << ModeBitsShift);
118505b261ecSmrg	ev->num_valuators = nval < 3 ? nval : 3;
118605b261ecSmrg	switch (ev->num_valuators) {
118705b261ecSmrg	case 3:
118805b261ecSmrg	    ev->valuator2 = v->axisVal[first + 2];
118905b261ecSmrg	case 2:
119005b261ecSmrg	    ev->valuator1 = v->axisVal[first + 1];
119105b261ecSmrg	case 1:
119205b261ecSmrg	    ev->valuator0 = v->axisVal[first];
119305b261ecSmrg	    break;
119405b261ecSmrg	}
119505b261ecSmrg    }
119605b261ecSmrg}
119705b261ecSmrg
119805b261ecSmrgstatic void
119905b261ecSmrgFixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
120005b261ecSmrg		  int first)
120105b261ecSmrg{
120205b261ecSmrg    int nval = v->numAxes - first;
120305b261ecSmrg
120405b261ecSmrg    ev->type = DeviceValuator;
120505b261ecSmrg    ev->deviceid = dev->id;
120605b261ecSmrg    ev->num_valuators = nval < 3 ? nval : 3;
120705b261ecSmrg    ev->first_valuator = first;
120805b261ecSmrg    switch (ev->num_valuators) {
120905b261ecSmrg    case 3:
121005b261ecSmrg	ev->valuator2 = v->axisVal[first + 2];
121105b261ecSmrg    case 2:
121205b261ecSmrg	ev->valuator1 = v->axisVal[first + 1];
121305b261ecSmrg    case 1:
121405b261ecSmrg	ev->valuator0 = v->axisVal[first];
121505b261ecSmrg	break;
121605b261ecSmrg    }
121705b261ecSmrg    first += ev->num_valuators;
121805b261ecSmrg}
121905b261ecSmrg
122005b261ecSmrgvoid
122105b261ecSmrgDeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
122205b261ecSmrg		 WindowPtr pWin)
122305b261ecSmrg{
122405b261ecSmrg    deviceFocus event;
12256747b715Smrg    xXIFocusInEvent *xi2event;
12266747b715Smrg    DeviceIntPtr mouse;
12276747b715Smrg    int btlen, len, i;
12286747b715Smrg
12296747b715Smrg    mouse = (IsMaster(dev) || dev->u.master) ? GetMaster(dev, MASTER_POINTER) : dev;
12306747b715Smrg
12316747b715Smrg    /* XI 2 event */
12326747b715Smrg    btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
12336747b715Smrg    btlen = bytes_to_int32(btlen);
12346747b715Smrg    len = sizeof(xXIFocusInEvent) + btlen * 4;
12356747b715Smrg
12366747b715Smrg    xi2event = calloc(1, len);
12376747b715Smrg    xi2event->type         = GenericEvent;
12386747b715Smrg    xi2event->extension    = IReqCode;
12396747b715Smrg    xi2event->evtype       = type;
12406747b715Smrg    xi2event->length       = bytes_to_int32(len - sizeof(xEvent));
12416747b715Smrg    xi2event->buttons_len  = btlen;
12426747b715Smrg    xi2event->detail       = detail;
12436747b715Smrg    xi2event->time         = currentTime.milliseconds;
12446747b715Smrg    xi2event->deviceid     = dev->id;
12456747b715Smrg    xi2event->sourceid     = dev->id; /* a device doesn't change focus by itself */
12466747b715Smrg    xi2event->mode         = mode;
12476747b715Smrg    xi2event->root_x       = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
12486747b715Smrg    xi2event->root_y       = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
12496747b715Smrg
12506747b715Smrg    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
12516747b715Smrg        if (BitIsOn(mouse->button->down, i))
12526747b715Smrg            SetBit(&xi2event[1], i);
12536747b715Smrg
12546747b715Smrg    if (dev->key)
12556747b715Smrg    {
12566747b715Smrg        xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods;
12576747b715Smrg        xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods;
12586747b715Smrg        xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods;
12596747b715Smrg        xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods;
12606747b715Smrg
12616747b715Smrg        xi2event->group.base_group = dev->key->xkbInfo->state.base_group;
12626747b715Smrg        xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group;
12636747b715Smrg        xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group;
12646747b715Smrg        xi2event->group.effective_group = dev->key->xkbInfo->state.group;
12656747b715Smrg    }
126605b261ecSmrg
12676747b715Smrg    FixUpEventFromWindow(dev, (xEvent*)xi2event, pWin, None, FALSE);
126805b261ecSmrg
12696747b715Smrg    DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
12706747b715Smrg                          GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
12716747b715Smrg
12726747b715Smrg    free(xi2event);
12736747b715Smrg
12746747b715Smrg    /* XI 1.x event */
127505b261ecSmrg    event.deviceid = dev->id;
127605b261ecSmrg    event.mode = mode;
12776747b715Smrg    event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
127805b261ecSmrg    event.detail = detail;
127905b261ecSmrg    event.window = pWin->drawable.id;
128005b261ecSmrg    event.time = currentTime.milliseconds;
128105b261ecSmrg
12826747b715Smrg    DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
12836747b715Smrg				DeviceFocusChangeMask, NullGrab);
128405b261ecSmrg
128505b261ecSmrg    if ((type == DeviceFocusIn) &&
128605b261ecSmrg	(wOtherInputMasks(pWin)) &&
128705b261ecSmrg	(wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
128805b261ecSmrg    {
128905b261ecSmrg	int evcount = 1;
129005b261ecSmrg	deviceStateNotify *ev, *sev;
129105b261ecSmrg	deviceKeyStateNotify *kev;
129205b261ecSmrg	deviceButtonStateNotify *bev;
129305b261ecSmrg
129405b261ecSmrg	KeyClassPtr k;
129505b261ecSmrg	ButtonClassPtr b;
129605b261ecSmrg	ValuatorClassPtr v;
129705b261ecSmrg	int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
129805b261ecSmrg
129905b261ecSmrg	if ((b = dev->button) != NULL) {
130005b261ecSmrg	    nbuttons = b->numButtons;
130105b261ecSmrg	    if (nbuttons > 32)
130205b261ecSmrg		evcount++;
130305b261ecSmrg	}
130405b261ecSmrg	if ((k = dev->key) != NULL) {
13056747b715Smrg	    nkeys = k->xkbInfo->desc->max_key_code -
13066747b715Smrg                    k->xkbInfo->desc->min_key_code;
130705b261ecSmrg	    if (nkeys > 32)
130805b261ecSmrg		evcount++;
130905b261ecSmrg	    if (nbuttons > 0) {
131005b261ecSmrg		evcount++;
131105b261ecSmrg	    }
131205b261ecSmrg	}
131305b261ecSmrg	if ((v = dev->valuator) != NULL) {
131405b261ecSmrg	    nval = v->numAxes;
131505b261ecSmrg
131605b261ecSmrg	    if (nval > 3)
131705b261ecSmrg		evcount++;
131805b261ecSmrg	    if (nval > 6) {
131905b261ecSmrg		if (!(k && b))
132005b261ecSmrg		    evcount++;
132105b261ecSmrg		if (nval > 9)
132205b261ecSmrg		    evcount += ((nval - 7) / 3);
132305b261ecSmrg	    }
132405b261ecSmrg	}
132505b261ecSmrg
13266747b715Smrg	sev = ev = (deviceStateNotify *) malloc(evcount * sizeof(xEvent));
132705b261ecSmrg	FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
132805b261ecSmrg
132905b261ecSmrg	if (b != NULL) {
133005b261ecSmrg	    FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
133105b261ecSmrg	    first += 3;
133205b261ecSmrg	    nval -= 3;
133305b261ecSmrg	    if (nbuttons > 32) {
133405b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
133505b261ecSmrg		bev = (deviceButtonStateNotify *) ev++;
133605b261ecSmrg		bev->type = DeviceButtonStateNotify;
133705b261ecSmrg		bev->deviceid = dev->id;
13384642e01fSmrg		memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
133905b261ecSmrg	    }
134005b261ecSmrg	    if (nval > 0) {
134105b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
134205b261ecSmrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
134305b261ecSmrg		first += 3;
134405b261ecSmrg		nval -= 3;
134505b261ecSmrg	    }
134605b261ecSmrg	}
134705b261ecSmrg
134805b261ecSmrg	if (k != NULL) {
134905b261ecSmrg	    FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
135005b261ecSmrg	    first += 3;
135105b261ecSmrg	    nval -= 3;
135205b261ecSmrg	    if (nkeys > 32) {
135305b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
135405b261ecSmrg		kev = (deviceKeyStateNotify *) ev++;
135505b261ecSmrg		kev->type = DeviceKeyStateNotify;
135605b261ecSmrg		kev->deviceid = dev->id;
135705b261ecSmrg		memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
135805b261ecSmrg	    }
135905b261ecSmrg	    if (nval > 0) {
136005b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
136105b261ecSmrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
136205b261ecSmrg		first += 3;
136305b261ecSmrg		nval -= 3;
136405b261ecSmrg	    }
136505b261ecSmrg	}
136605b261ecSmrg
136705b261ecSmrg	while (nval > 0) {
136805b261ecSmrg	    FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
136905b261ecSmrg	    first += 3;
137005b261ecSmrg	    nval -= 3;
137105b261ecSmrg	    if (nval > 0) {
137205b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
137305b261ecSmrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
137405b261ecSmrg		first += 3;
137505b261ecSmrg		nval -= 3;
137605b261ecSmrg	    }
137705b261ecSmrg	}
137805b261ecSmrg
13796747b715Smrg	DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
13806747b715Smrg				    DeviceStateNotifyMask, NullGrab);
13816747b715Smrg	free(sev);
138205b261ecSmrg    }
138305b261ecSmrg}
138405b261ecSmrg
138505b261ecSmrgint
13866747b715SmrgCheckGrabValues(ClientPtr client, GrabParameters* param)
138705b261ecSmrg{
13886747b715Smrg    if (param->grabtype != GRABTYPE_CORE &&
13896747b715Smrg        param->grabtype != GRABTYPE_XI &&
13906747b715Smrg        param->grabtype != GRABTYPE_XI2)
13916747b715Smrg    {
13926747b715Smrg        ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
13936747b715Smrg        return BadImplementation;
13946747b715Smrg    }
139505b261ecSmrg
13966747b715Smrg    if ((param->this_device_mode != GrabModeSync) &&
13976747b715Smrg	(param->this_device_mode != GrabModeAsync)) {
13986747b715Smrg	client->errorValue = param->this_device_mode;
139905b261ecSmrg	return BadValue;
140005b261ecSmrg    }
14016747b715Smrg    if ((param->other_devices_mode != GrabModeSync) &&
14026747b715Smrg	(param->other_devices_mode != GrabModeAsync)) {
14036747b715Smrg	client->errorValue = param->other_devices_mode;
140405b261ecSmrg	return BadValue;
140505b261ecSmrg    }
14066747b715Smrg
14076747b715Smrg    if (param->grabtype != GRABTYPE_XI2 && (param->modifiers != AnyModifier) &&
14086747b715Smrg        (param->modifiers & ~AllModifiersMask)) {
14096747b715Smrg	client->errorValue = param->modifiers;
141005b261ecSmrg	return BadValue;
141105b261ecSmrg    }
14126747b715Smrg
14136747b715Smrg    if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
14146747b715Smrg	client->errorValue = param->ownerEvents;
141505b261ecSmrg	return BadValue;
141605b261ecSmrg    }
14176747b715Smrg    return Success;
14186747b715Smrg}
14196747b715Smrg
14206747b715Smrgint
14216747b715SmrgGrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
14226747b715Smrg           int button, GrabParameters *param, GrabType grabtype,
14236747b715Smrg	   GrabMask *mask)
14246747b715Smrg{
14256747b715Smrg    WindowPtr pWin, confineTo;
14266747b715Smrg    CursorPtr cursor;
14276747b715Smrg    GrabPtr grab;
14286747b715Smrg    int rc, type = -1;
14296747b715Smrg    Mask access_mode = DixGrabAccess;
14306747b715Smrg
14316747b715Smrg    rc = CheckGrabValues(client, param);
143205b261ecSmrg    if (rc != Success)
143305b261ecSmrg	return rc;
14346747b715Smrg    if (param->confineTo == None)
143505b261ecSmrg	confineTo = NullWindow;
143605b261ecSmrg    else {
14376747b715Smrg	rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess);
143805b261ecSmrg	if (rc != Success)
143905b261ecSmrg	    return rc;
144005b261ecSmrg    }
14416747b715Smrg    if (param->cursor == None)
144205b261ecSmrg	cursor = NullCursor;
144305b261ecSmrg    else {
14446747b715Smrg	rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
14456747b715Smrg				     RT_CURSOR, client, DixUseAccess);
14464642e01fSmrg	if (rc != Success)
14474642e01fSmrg	{
14486747b715Smrg	    client->errorValue = param->cursor;
14496747b715Smrg	    return rc;
145005b261ecSmrg	}
14514642e01fSmrg	access_mode |= DixForceAccess;
145205b261ecSmrg    }
14536747b715Smrg    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
14544642e01fSmrg	access_mode |= DixFreezeAccess;
14554642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
14566747b715Smrg    if (rc != Success)
14576747b715Smrg	return rc;
14586747b715Smrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
14594642e01fSmrg    if (rc != Success)
14604642e01fSmrg	return rc;
146105b261ecSmrg
14626747b715Smrg    if (grabtype == GRABTYPE_XI)
14636747b715Smrg        type = DeviceButtonPress;
14646747b715Smrg    else if (grabtype == GRABTYPE_XI2)
14656747b715Smrg        type = XI_ButtonPress;
14666747b715Smrg
14676747b715Smrg    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
14686747b715Smrg                      mask, param, type, button, confineTo, cursor);
146905b261ecSmrg    if (!grab)
147005b261ecSmrg	return BadAlloc;
14714642e01fSmrg    return AddPassiveGrabToList(client, grab);
147205b261ecSmrg}
147305b261ecSmrg
14746747b715Smrg/**
14756747b715Smrg * Grab the given key. If grabtype is GRABTYPE_XI, the key is a keycode. If
14766747b715Smrg * grabtype is GRABTYPE_XI2, the key is a keysym.
14776747b715Smrg */
147805b261ecSmrgint
14796747b715SmrgGrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
14806747b715Smrg        int key, GrabParameters *param, GrabType grabtype, GrabMask *mask)
148105b261ecSmrg{
148205b261ecSmrg    WindowPtr pWin;
148305b261ecSmrg    GrabPtr grab;
148405b261ecSmrg    KeyClassPtr k = dev->key;
14854642e01fSmrg    Mask access_mode = DixGrabAccess;
14866747b715Smrg    int rc, type = -1;
148705b261ecSmrg
14886747b715Smrg    rc = CheckGrabValues(client, param);
14896747b715Smrg    if (rc != Success)
14906747b715Smrg        return rc;
149105b261ecSmrg    if (k == NULL)
149205b261ecSmrg	return BadMatch;
14936747b715Smrg    if (grabtype == GRABTYPE_XI)
14946747b715Smrg    {
14956747b715Smrg        if ((key > k->xkbInfo->desc->max_key_code ||
14966747b715Smrg                    key < k->xkbInfo->desc->min_key_code)
14976747b715Smrg                && (key != AnyKey)) {
14986747b715Smrg            client->errorValue = key;
14996747b715Smrg            return BadValue;
15006747b715Smrg        }
15016747b715Smrg        type = DeviceKeyPress;
15026747b715Smrg    } else if (grabtype == GRABTYPE_XI2)
15036747b715Smrg        type = XI_KeyPress;
15046747b715Smrg
15056747b715Smrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
15064642e01fSmrg    if (rc != Success)
15074642e01fSmrg	return rc;
15086747b715Smrg    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
15094642e01fSmrg	access_mode |= DixFreezeAccess;
15104642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
151105b261ecSmrg    if (rc != Success)
151205b261ecSmrg	return rc;
151305b261ecSmrg
15146747b715Smrg    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
15156747b715Smrg                      mask, param, type, key, NULL, NULL);
151605b261ecSmrg    if (!grab)
151705b261ecSmrg	return BadAlloc;
15184642e01fSmrg    return AddPassiveGrabToList(client, grab);
151905b261ecSmrg}
152005b261ecSmrg
15216747b715Smrg/* Enter/FocusIn grab */
15226747b715Smrgint
15236747b715SmrgGrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
15246747b715Smrg           GrabParameters *param, GrabMask *mask)
15256747b715Smrg{
15266747b715Smrg    WindowPtr pWin;
15276747b715Smrg    CursorPtr cursor;
15286747b715Smrg    GrabPtr grab;
15296747b715Smrg    Mask access_mode = DixGrabAccess;
15306747b715Smrg    int rc;
15316747b715Smrg
15326747b715Smrg    rc = CheckGrabValues(client, param);
15336747b715Smrg    if (rc != Success)
15346747b715Smrg        return rc;
15356747b715Smrg
15366747b715Smrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
15376747b715Smrg    if (rc != Success)
15386747b715Smrg	return rc;
15396747b715Smrg    if (param->cursor == None)
15406747b715Smrg	cursor = NullCursor;
15416747b715Smrg    else {
15426747b715Smrg	rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
15436747b715Smrg				     RT_CURSOR, client, DixUseAccess);
15446747b715Smrg	if (rc != Success)
15456747b715Smrg	{
15466747b715Smrg	    client->errorValue = param->cursor;
15476747b715Smrg	    return rc;
15486747b715Smrg	}
15496747b715Smrg	access_mode |= DixForceAccess;
15506747b715Smrg    }
15516747b715Smrg    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
15526747b715Smrg	access_mode |= DixFreezeAccess;
15536747b715Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
15546747b715Smrg    if (rc != Success)
15556747b715Smrg	return rc;
15566747b715Smrg
15576747b715Smrg    grab = CreateGrab(client->index, dev, dev, pWin, GRABTYPE_XI2,
15586747b715Smrg                      mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn,
15596747b715Smrg                      0, NULL, cursor);
15606747b715Smrg
15616747b715Smrg    if (!grab)
15626747b715Smrg        return BadAlloc;
15636747b715Smrg
15646747b715Smrg    return AddPassiveGrabToList(client, grab);
15656747b715Smrg}
15666747b715Smrg
156705b261ecSmrgint
156805b261ecSmrgSelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
15696747b715Smrg		Mask mask, Mask exclusivemasks)
157005b261ecSmrg{
157105b261ecSmrg    int mskidx = dev->id;
157205b261ecSmrg    int i, ret;
157305b261ecSmrg    Mask check;
157405b261ecSmrg    InputClientsPtr others;
157505b261ecSmrg
157605b261ecSmrg    check = (mask & exclusivemasks);
157705b261ecSmrg    if (wOtherInputMasks(pWin)) {
157805b261ecSmrg	if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {	/* It is illegal for two different
157905b261ecSmrg									 * clients to select on any of the
158005b261ecSmrg									 * events for maskcheck. However,
158105b261ecSmrg									 * it is OK, for some client to
158205b261ecSmrg									 * continue selecting on one of those
158305b261ecSmrg									 * events.  */
158405b261ecSmrg	    for (others = wOtherInputMasks(pWin)->inputClients; others;
158505b261ecSmrg		 others = others->next) {
158605b261ecSmrg		if (!SameClient(others, client) && (check &
158705b261ecSmrg						    others->mask[mskidx]))
158805b261ecSmrg		    return BadAccess;
158905b261ecSmrg	    }
159005b261ecSmrg	}
159105b261ecSmrg	for (others = wOtherInputMasks(pWin)->inputClients; others;
159205b261ecSmrg	     others = others->next) {
159305b261ecSmrg	    if (SameClient(others, client)) {
159405b261ecSmrg		check = others->mask[mskidx];
159505b261ecSmrg		others->mask[mskidx] = mask;
159605b261ecSmrg		if (mask == 0) {
159705b261ecSmrg		    for (i = 0; i < EMASKSIZE; i++)
159805b261ecSmrg			if (i != mskidx && others->mask[i] != 0)
159905b261ecSmrg			    break;
160005b261ecSmrg		    if (i == EMASKSIZE) {
160105b261ecSmrg			RecalculateDeviceDeliverableEvents(pWin);
160205b261ecSmrg			if (ShouldFreeInputMasks(pWin, FALSE))
160305b261ecSmrg			    FreeResource(others->resource, RT_NONE);
160405b261ecSmrg			return Success;
160505b261ecSmrg		    }
160605b261ecSmrg		}
160705b261ecSmrg		goto maskSet;
160805b261ecSmrg	    }
160905b261ecSmrg	}
161005b261ecSmrg    }
161105b261ecSmrg    check = 0;
161205b261ecSmrg    if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
161305b261ecSmrg	return ret;
161405b261ecSmrg  maskSet:
161505b261ecSmrg    if (dev->valuator)
161605b261ecSmrg	if ((dev->valuator->motionHintWindow == pWin) &&
161705b261ecSmrg	    (mask & DevicePointerMotionHintMask) &&
16184642e01fSmrg	    !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
161905b261ecSmrg	    dev->valuator->motionHintWindow = NullWindow;
162005b261ecSmrg    RecalculateDeviceDeliverableEvents(pWin);
162105b261ecSmrg    return Success;
162205b261ecSmrg}
162305b261ecSmrg
162405b261ecSmrgint
162505b261ecSmrgAddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
162605b261ecSmrg{
162705b261ecSmrg    InputClientsPtr others;
162805b261ecSmrg
162905b261ecSmrg    if (!pWin->optional && !MakeWindowOptional(pWin))
163005b261ecSmrg	return BadAlloc;
16316747b715Smrg    others = calloc(1, sizeof(InputClients));
163205b261ecSmrg    if (!others)
163305b261ecSmrg	return BadAlloc;
163405b261ecSmrg    if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
163505b261ecSmrg	return BadAlloc;
163605b261ecSmrg    others->mask[mskidx] = mask;
163705b261ecSmrg    others->resource = FakeClientID(client->index);
163805b261ecSmrg    others->next = pWin->optional->inputMasks->inputClients;
163905b261ecSmrg    pWin->optional->inputMasks->inputClients = others;
164005b261ecSmrg    if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
164105b261ecSmrg	return BadAlloc;
164205b261ecSmrg    return Success;
164305b261ecSmrg}
164405b261ecSmrg
164505b261ecSmrgstatic Bool
164605b261ecSmrgMakeInputMasks(WindowPtr pWin)
164705b261ecSmrg{
164805b261ecSmrg    struct _OtherInputMasks *imasks;
164905b261ecSmrg
16506747b715Smrg    imasks = calloc(1, sizeof(struct _OtherInputMasks));
165105b261ecSmrg    if (!imasks)
165205b261ecSmrg	return FALSE;
165305b261ecSmrg    pWin->optional->inputMasks = imasks;
165405b261ecSmrg    return TRUE;
165505b261ecSmrg}
165605b261ecSmrg
165705b261ecSmrgvoid
165805b261ecSmrgRecalculateDeviceDeliverableEvents(WindowPtr pWin)
165905b261ecSmrg{
166005b261ecSmrg    InputClientsPtr others;
166105b261ecSmrg    struct _OtherInputMasks *inputMasks;	/* default: NULL */
166205b261ecSmrg    WindowPtr pChild, tmp;
16636747b715Smrg    int i, j;
166405b261ecSmrg
166505b261ecSmrg    pChild = pWin;
166605b261ecSmrg    while (1) {
166705b261ecSmrg	if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
16686747b715Smrg            for (i = 0; i < EMASKSIZE; i++)
16696747b715Smrg                memset(inputMasks->xi2mask[i], 0, sizeof(inputMasks->xi2mask[i]));
167005b261ecSmrg	    for (others = inputMasks->inputClients; others;
167105b261ecSmrg		 others = others->next) {
167205b261ecSmrg		for (i = 0; i < EMASKSIZE; i++)
167305b261ecSmrg		    inputMasks->inputEvents[i] |= others->mask[i];
16746747b715Smrg                for (i = 0; i < EMASKSIZE; i++)
16756747b715Smrg                    for (j = 0; j < XI2MASKSIZE; j++)
16766747b715Smrg                        inputMasks->xi2mask[i][j] |= others->xi2mask[i][j];
167705b261ecSmrg	    }
167805b261ecSmrg	    for (i = 0; i < EMASKSIZE; i++)
167905b261ecSmrg		inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
168005b261ecSmrg	    for (tmp = pChild->parent; tmp; tmp = tmp->parent)
168105b261ecSmrg		if (wOtherInputMasks(tmp))
168205b261ecSmrg		    for (i = 0; i < EMASKSIZE; i++)
168305b261ecSmrg			inputMasks->deliverableEvents[i] |=
168405b261ecSmrg			    (wOtherInputMasks(tmp)->deliverableEvents[i]
168505b261ecSmrg			     & ~inputMasks->
168605b261ecSmrg			     dontPropagateMask[i] & PropagateMask[i]);
168705b261ecSmrg	}
168805b261ecSmrg	if (pChild->firstChild) {
168905b261ecSmrg	    pChild = pChild->firstChild;
169005b261ecSmrg	    continue;
169105b261ecSmrg	}
169205b261ecSmrg	while (!pChild->nextSib && (pChild != pWin))
169305b261ecSmrg	    pChild = pChild->parent;
169405b261ecSmrg	if (pChild == pWin)
169505b261ecSmrg	    break;
169605b261ecSmrg	pChild = pChild->nextSib;
169705b261ecSmrg    }
169805b261ecSmrg}
169905b261ecSmrg
170005b261ecSmrgint
170105b261ecSmrgInputClientGone(WindowPtr pWin, XID id)
170205b261ecSmrg{
170305b261ecSmrg    InputClientsPtr other, prev;
170405b261ecSmrg
170505b261ecSmrg    if (!wOtherInputMasks(pWin))
17066747b715Smrg	return Success;
170705b261ecSmrg    prev = 0;
170805b261ecSmrg    for (other = wOtherInputMasks(pWin)->inputClients; other;
170905b261ecSmrg	 other = other->next) {
171005b261ecSmrg	if (other->resource == id) {
171105b261ecSmrg	    if (prev) {
171205b261ecSmrg		prev->next = other->next;
17136747b715Smrg		free(other);
171405b261ecSmrg	    } else if (!(other->next)) {
171505b261ecSmrg		if (ShouldFreeInputMasks(pWin, TRUE)) {
171605b261ecSmrg		    wOtherInputMasks(pWin)->inputClients = other->next;
17176747b715Smrg		    free(wOtherInputMasks(pWin));
171805b261ecSmrg		    pWin->optional->inputMasks = (OtherInputMasks *) NULL;
171905b261ecSmrg		    CheckWindowOptionalNeed(pWin);
17206747b715Smrg		    free(other);
172105b261ecSmrg		} else {
172205b261ecSmrg		    other->resource = FakeClientID(0);
172305b261ecSmrg		    if (!AddResource(other->resource, RT_INPUTCLIENT,
172405b261ecSmrg				     (pointer) pWin))
172505b261ecSmrg			return BadAlloc;
172605b261ecSmrg		}
172705b261ecSmrg	    } else {
172805b261ecSmrg		wOtherInputMasks(pWin)->inputClients = other->next;
17296747b715Smrg		free(other);
173005b261ecSmrg	    }
173105b261ecSmrg	    RecalculateDeviceDeliverableEvents(pWin);
17326747b715Smrg	    return Success;
173305b261ecSmrg	}
173405b261ecSmrg	prev = other;
173505b261ecSmrg    }
173605b261ecSmrg    FatalError("client not on device event list");
173705b261ecSmrg}
173805b261ecSmrg
173905b261ecSmrgint
174005b261ecSmrgSendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
174105b261ecSmrg	  xEvent * ev, Mask mask, int count)
174205b261ecSmrg{
174305b261ecSmrg    WindowPtr pWin;
174405b261ecSmrg    WindowPtr effectiveFocus = NullWindow;	/* only set if dest==InputFocus */
17454642e01fSmrg    WindowPtr spriteWin = GetSpriteWindow(d);
174605b261ecSmrg
174705b261ecSmrg    if (dest == PointerWindow)
174805b261ecSmrg	pWin = spriteWin;
174905b261ecSmrg    else if (dest == InputFocus) {
175005b261ecSmrg	WindowPtr inputFocus;
175105b261ecSmrg
175205b261ecSmrg	if (!d->focus)
175305b261ecSmrg	    inputFocus = spriteWin;
175405b261ecSmrg	else
175505b261ecSmrg	    inputFocus = d->focus->win;
175605b261ecSmrg
175705b261ecSmrg	if (inputFocus == FollowKeyboardWin)
175805b261ecSmrg	    inputFocus = inputInfo.keyboard->focus->win;
175905b261ecSmrg
176005b261ecSmrg	if (inputFocus == NoneWin)
176105b261ecSmrg	    return Success;
176205b261ecSmrg
176305b261ecSmrg	/* If the input focus is PointerRootWin, send the event to where
176405b261ecSmrg	 * the pointer is if possible, then perhaps propogate up to root. */
176505b261ecSmrg	if (inputFocus == PointerRootWin)
17664642e01fSmrg	    inputFocus = GetCurrentRootWindow(d);
176705b261ecSmrg
176805b261ecSmrg	if (IsParent(inputFocus, spriteWin)) {
176905b261ecSmrg	    effectiveFocus = inputFocus;
177005b261ecSmrg	    pWin = spriteWin;
177105b261ecSmrg	} else
177205b261ecSmrg	    effectiveFocus = pWin = inputFocus;
177305b261ecSmrg    } else
17744642e01fSmrg	dixLookupWindow(&pWin, dest, client, DixSendAccess);
177505b261ecSmrg    if (!pWin)
177605b261ecSmrg	return BadWindow;
177705b261ecSmrg    if ((propagate != xFalse) && (propagate != xTrue)) {
177805b261ecSmrg	client->errorValue = propagate;
177905b261ecSmrg	return BadValue;
178005b261ecSmrg    }
178105b261ecSmrg    ev->u.u.type |= 0x80;
178205b261ecSmrg    if (propagate) {
178305b261ecSmrg	for (; pWin; pWin = pWin->parent) {
17846747b715Smrg	    if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
178505b261ecSmrg		return Success;
178605b261ecSmrg	    if (pWin == effectiveFocus)
178705b261ecSmrg		return Success;
178805b261ecSmrg	    if (wOtherInputMasks(pWin))
178905b261ecSmrg		mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
179005b261ecSmrg	    if (!mask)
179105b261ecSmrg		break;
179205b261ecSmrg	}
17934642e01fSmrg    } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
17946747b715Smrg	DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
179505b261ecSmrg    return Success;
179605b261ecSmrg}
179705b261ecSmrg
179805b261ecSmrgint
179905b261ecSmrgSetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
180005b261ecSmrg{
180105b261ecSmrg    int i;
180205b261ecSmrg    ButtonClassPtr b = dev->button;
180305b261ecSmrg
180405b261ecSmrg    if (b == NULL)
180505b261ecSmrg	return BadMatch;
180605b261ecSmrg
180705b261ecSmrg    if (nElts != b->numButtons) {
180805b261ecSmrg	client->errorValue = nElts;
180905b261ecSmrg	return BadValue;
181005b261ecSmrg    }
181105b261ecSmrg    if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
181205b261ecSmrg	return BadValue;
181305b261ecSmrg    for (i = 0; i < nElts; i++)
181405b261ecSmrg	if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
181505b261ecSmrg	    return MappingBusy;
181605b261ecSmrg    for (i = 0; i < nElts; i++)
181705b261ecSmrg	b->map[i + 1] = map[i];
181805b261ecSmrg    return Success;
181905b261ecSmrg}
182005b261ecSmrg
182105b261ecSmrgint
182205b261ecSmrgChangeKeyMapping(ClientPtr client,
182305b261ecSmrg		 DeviceIntPtr dev,
182405b261ecSmrg		 unsigned len,
182505b261ecSmrg		 int type,
182605b261ecSmrg		 KeyCode firstKeyCode,
182705b261ecSmrg		 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
182805b261ecSmrg{
182905b261ecSmrg    KeySymsRec keysyms;
183005b261ecSmrg    KeyClassPtr k = dev->key;
183105b261ecSmrg
183205b261ecSmrg    if (k == NULL)
18336747b715Smrg	return BadMatch;
183405b261ecSmrg
183505b261ecSmrg    if (len != (keyCodes * keySymsPerKeyCode))
183605b261ecSmrg	return BadLength;
183705b261ecSmrg
18386747b715Smrg    if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
18396747b715Smrg	(firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
184005b261ecSmrg	client->errorValue = firstKeyCode;
184105b261ecSmrg	return BadValue;
184205b261ecSmrg    }
184305b261ecSmrg    if (keySymsPerKeyCode == 0) {
184405b261ecSmrg	client->errorValue = 0;
184505b261ecSmrg	return BadValue;
184605b261ecSmrg    }
184705b261ecSmrg    keysyms.minKeyCode = firstKeyCode;
184805b261ecSmrg    keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
184905b261ecSmrg    keysyms.mapWidth = keySymsPerKeyCode;
185005b261ecSmrg    keysyms.map = map;
18516747b715Smrg
18526747b715Smrg    XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
18536747b715Smrg                          serverClient);
18546747b715Smrg
18556747b715Smrg    return Success;
185605b261ecSmrg}
185705b261ecSmrg
185805b261ecSmrgstatic void
185905b261ecSmrgDeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
186005b261ecSmrg{
186105b261ecSmrg    WindowPtr parent;
186205b261ecSmrg
186305b261ecSmrg    /* Deactivate any grabs performed on this window, before making
186405b261ecSmrg     * any input focus changes.
186505b261ecSmrg     * Deactivating a device grab should cause focus events. */
186605b261ecSmrg
18674642e01fSmrg    if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
18684642e01fSmrg	(*dev->deviceGrab.DeactivateGrab) (dev);
186905b261ecSmrg
18704642e01fSmrg    /* If the focus window is a root window (ie. has no parent)
187105b261ecSmrg     * then don't delete the focus from it. */
187205b261ecSmrg
187305b261ecSmrg    if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
187405b261ecSmrg	int focusEventMode = NotifyNormal;
187505b261ecSmrg
187605b261ecSmrg	/* If a grab is in progress, then alter the mode of focus events. */
187705b261ecSmrg
18784642e01fSmrg	if (dev->deviceGrab.grab)
187905b261ecSmrg	    focusEventMode = NotifyWhileGrabbed;
188005b261ecSmrg
188105b261ecSmrg	switch (dev->focus->revert) {
188205b261ecSmrg	case RevertToNone:
18836747b715Smrg	    if (!ActivateFocusInGrab(dev, pWin, NoneWin))
18846747b715Smrg		DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
188505b261ecSmrg	    dev->focus->win = NoneWin;
188605b261ecSmrg	    dev->focus->traceGood = 0;
188705b261ecSmrg	    break;
188805b261ecSmrg	case RevertToParent:
188905b261ecSmrg	    parent = pWin;
189005b261ecSmrg	    do {
189105b261ecSmrg		parent = parent->parent;
189205b261ecSmrg		dev->focus->traceGood--;
189305b261ecSmrg	    }
189405b261ecSmrg	    while (!parent->realized);
18956747b715Smrg	    if (!ActivateFocusInGrab(dev, pWin, parent))
18966747b715Smrg		DoFocusEvents(dev, pWin, parent, focusEventMode);
189705b261ecSmrg	    dev->focus->win = parent;
189805b261ecSmrg	    dev->focus->revert = RevertToNone;
189905b261ecSmrg	    break;
190005b261ecSmrg	case RevertToPointerRoot:
19016747b715Smrg	    if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
19026747b715Smrg		DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
190305b261ecSmrg	    dev->focus->win = PointerRootWin;
190405b261ecSmrg	    dev->focus->traceGood = 0;
190505b261ecSmrg	    break;
190605b261ecSmrg	case RevertToFollowKeyboard:
19076747b715Smrg            {
19086747b715Smrg                DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
19096747b715Smrg                if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
19106747b715Smrg                    kbd = inputInfo.keyboard;
19116747b715Smrg	    if (kbd->focus->win) {
19126747b715Smrg		if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
19136747b715Smrg		    DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
191405b261ecSmrg		dev->focus->win = FollowKeyboardWin;
191505b261ecSmrg		dev->focus->traceGood = 0;
191605b261ecSmrg	    } else {
19176747b715Smrg                if (!ActivateFocusInGrab(dev, pWin, NoneWin))
19186747b715Smrg                    DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
191905b261ecSmrg		dev->focus->win = NoneWin;
192005b261ecSmrg		dev->focus->traceGood = 0;
192105b261ecSmrg	    }
19226747b715Smrg            }
192305b261ecSmrg	    break;
192405b261ecSmrg	}
192505b261ecSmrg    }
192605b261ecSmrg
192705b261ecSmrg    if (dev->valuator)
192805b261ecSmrg	if (dev->valuator->motionHintWindow == pWin)
192905b261ecSmrg	    dev->valuator->motionHintWindow = NullWindow;
193005b261ecSmrg}
193105b261ecSmrg
193205b261ecSmrgvoid
193305b261ecSmrgDeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
193405b261ecSmrg{
193505b261ecSmrg    int i;
193605b261ecSmrg    DeviceIntPtr dev;
193705b261ecSmrg    InputClientsPtr ic;
193805b261ecSmrg    struct _OtherInputMasks *inputMasks;
193905b261ecSmrg
194005b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
194105b261ecSmrg	DeleteDeviceFromAnyExtEvents(pWin, dev);
194205b261ecSmrg    }
194305b261ecSmrg
194405b261ecSmrg    for (dev = inputInfo.off_devices; dev; dev = dev->next)
194505b261ecSmrg	DeleteDeviceFromAnyExtEvents(pWin, dev);
194605b261ecSmrg
194705b261ecSmrg    if (freeResources)
194805b261ecSmrg	while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
194905b261ecSmrg	    ic = inputMasks->inputClients;
195005b261ecSmrg	    for (i = 0; i < EMASKSIZE; i++)
195105b261ecSmrg		inputMasks->dontPropagateMask[i] = 0;
195205b261ecSmrg	    FreeResource(ic->resource, RT_NONE);
195305b261ecSmrg	}
195405b261ecSmrg}
195505b261ecSmrg
195605b261ecSmrgint
195705b261ecSmrgMaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
195805b261ecSmrg{
195905b261ecSmrg    DeviceIntPtr dev;
196005b261ecSmrg
19614642e01fSmrg    dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
19624642e01fSmrg		    DixReadAccess);
196305b261ecSmrg    if (!dev)
196405b261ecSmrg        return 0;
196505b261ecSmrg
196605b261ecSmrg    if (pEvents->type == DeviceMotionNotify) {
196705b261ecSmrg	if (mask & DevicePointerMotionHintMask) {
196805b261ecSmrg	    if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
196905b261ecSmrg		return 1;	/* don't send, but pretend we did */
197005b261ecSmrg	    }
197105b261ecSmrg	    pEvents->detail = NotifyHint;
197205b261ecSmrg	} else {
197305b261ecSmrg	    pEvents->detail = NotifyNormal;
197405b261ecSmrg	}
197505b261ecSmrg    }
19766747b715Smrg    return 0;
197705b261ecSmrg}
197805b261ecSmrg
197905b261ecSmrgvoid
198005b261ecSmrgCheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
198105b261ecSmrg			     deviceKeyButtonPointer * xE, GrabPtr grab,
198205b261ecSmrg			     ClientPtr client, Mask deliveryMask)
198305b261ecSmrg{
198405b261ecSmrg    DeviceIntPtr dev;
198505b261ecSmrg
19864642e01fSmrg    dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
19876747b715Smrg		    DixGrabAccess);
198805b261ecSmrg    if (!dev)
198905b261ecSmrg        return;
199005b261ecSmrg
199105b261ecSmrg    if (type == DeviceMotionNotify)
199205b261ecSmrg	dev->valuator->motionHintWindow = pWin;
199305b261ecSmrg    else if ((type == DeviceButtonPress) && (!grab) &&
199405b261ecSmrg	     (deliveryMask & DeviceButtonGrabMask)) {
199505b261ecSmrg	GrabRec tempGrab;
199605b261ecSmrg
199705b261ecSmrg	tempGrab.device = dev;
199805b261ecSmrg	tempGrab.resource = client->clientAsMask;
199905b261ecSmrg	tempGrab.window = pWin;
200005b261ecSmrg	tempGrab.ownerEvents =
200105b261ecSmrg	    (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
200205b261ecSmrg	tempGrab.eventMask = deliveryMask;
200305b261ecSmrg	tempGrab.keyboardMode = GrabModeAsync;
200405b261ecSmrg	tempGrab.pointerMode = GrabModeAsync;
200505b261ecSmrg	tempGrab.confineTo = NullWindow;
200605b261ecSmrg	tempGrab.cursor = NullCursor;
20074642e01fSmrg        tempGrab.next = NULL;
20084642e01fSmrg	(*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
200905b261ecSmrg    }
201005b261ecSmrg}
201105b261ecSmrg
201205b261ecSmrgstatic Mask
201305b261ecSmrgDeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
201405b261ecSmrg{
201505b261ecSmrg    InputClientsPtr other;
201605b261ecSmrg
201705b261ecSmrg    if (!wOtherInputMasks(pWin))
201805b261ecSmrg	return 0;
201905b261ecSmrg    for (other = wOtherInputMasks(pWin)->inputClients; other;
202005b261ecSmrg	 other = other->next) {
202105b261ecSmrg	if (SameClient(other, client))
202205b261ecSmrg	    return other->mask[dev->id];
202305b261ecSmrg    }
202405b261ecSmrg    return 0;
202505b261ecSmrg}
202605b261ecSmrg
202705b261ecSmrgvoid
202805b261ecSmrgMaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
202905b261ecSmrg{
203005b261ecSmrg    WindowPtr pWin;
20314642e01fSmrg    GrabPtr grab = dev->deviceGrab.grab;
203205b261ecSmrg
203305b261ecSmrg    pWin = dev->valuator->motionHintWindow;
203405b261ecSmrg
203505b261ecSmrg    if ((grab && SameClient(grab, client) &&
203605b261ecSmrg	 ((grab->eventMask & DevicePointerMotionHintMask) ||
203705b261ecSmrg	  (grab->ownerEvents &&
203805b261ecSmrg	   (DeviceEventMaskForClient(dev, pWin, client) &
203905b261ecSmrg	    DevicePointerMotionHintMask)))) ||
204005b261ecSmrg	(!grab &&
204105b261ecSmrg	 (DeviceEventMaskForClient(dev, pWin, client) &
204205b261ecSmrg	  DevicePointerMotionHintMask)))
204305b261ecSmrg	dev->valuator->motionHintWindow = NullWindow;
204405b261ecSmrg}
204505b261ecSmrg
204605b261ecSmrgint
204705b261ecSmrgDeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
204805b261ecSmrg			     int maskndx)
204905b261ecSmrg{
205005b261ecSmrg    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
205105b261ecSmrg
205205b261ecSmrg    if (mask & ~PropagateMask[maskndx]) {
205305b261ecSmrg	client->errorValue = mask;
205405b261ecSmrg	return BadValue;
205505b261ecSmrg    }
205605b261ecSmrg
205705b261ecSmrg    if (mask == 0) {
205805b261ecSmrg	if (inputMasks)
205905b261ecSmrg	    inputMasks->dontPropagateMask[maskndx] = mask;
206005b261ecSmrg    } else {
206105b261ecSmrg	if (!inputMasks)
206205b261ecSmrg	    AddExtensionClient(pWin, client, 0, 0);
206305b261ecSmrg	inputMasks = wOtherInputMasks(pWin);
206405b261ecSmrg	inputMasks->dontPropagateMask[maskndx] = mask;
206505b261ecSmrg    }
206605b261ecSmrg    RecalculateDeviceDeliverableEvents(pWin);
206705b261ecSmrg    if (ShouldFreeInputMasks(pWin, FALSE))
206805b261ecSmrg	FreeResource(inputMasks->inputClients->resource, RT_NONE);
206905b261ecSmrg    return Success;
207005b261ecSmrg}
207105b261ecSmrg
20724642e01fSmrgBool
207305b261ecSmrgShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
207405b261ecSmrg{
207505b261ecSmrg    int i;
207605b261ecSmrg    Mask allInputEventMasks = 0;
207705b261ecSmrg    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
207805b261ecSmrg
207905b261ecSmrg    for (i = 0; i < EMASKSIZE; i++)
208005b261ecSmrg	allInputEventMasks |= inputMasks->dontPropagateMask[i];
208105b261ecSmrg    if (!ignoreSelectedEvents)
208205b261ecSmrg	for (i = 0; i < EMASKSIZE; i++)
208305b261ecSmrg	    allInputEventMasks |= inputMasks->inputEvents[i];
208405b261ecSmrg    if (allInputEventMasks == 0)
208505b261ecSmrg	return TRUE;
208605b261ecSmrg    else
208705b261ecSmrg	return FALSE;
208805b261ecSmrg}
208905b261ecSmrg
209005b261ecSmrg/***********************************************************************
209105b261ecSmrg *
209205b261ecSmrg * Walk through the window tree, finding all clients that want to know
209305b261ecSmrg * about the Event.
209405b261ecSmrg *
209505b261ecSmrg */
209605b261ecSmrg
209705b261ecSmrgstatic void
209805b261ecSmrgFindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
209905b261ecSmrg                       xEvent * ev, int count)
210005b261ecSmrg{
210105b261ecSmrg    WindowPtr p2;
210205b261ecSmrg
210305b261ecSmrg    while (p1) {
210405b261ecSmrg        p2 = p1->firstChild;
21056747b715Smrg        DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
210605b261ecSmrg        FindInterestedChildren(dev, p2, mask, ev, count);
210705b261ecSmrg        p1 = p1->nextSib;
210805b261ecSmrg    }
210905b261ecSmrg}
211005b261ecSmrg
211105b261ecSmrg/***********************************************************************
211205b261ecSmrg *
211305b261ecSmrg * Send an event to interested clients in all windows on all screens.
211405b261ecSmrg *
211505b261ecSmrg */
211605b261ecSmrg
211705b261ecSmrgvoid
211805b261ecSmrgSendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
211905b261ecSmrg{
212005b261ecSmrg    int i;
212105b261ecSmrg    WindowPtr pWin, p1;
212205b261ecSmrg
212305b261ecSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
21246747b715Smrg        pWin = screenInfo.screens[i]->root;
21254642e01fSmrg        if (!pWin)
21264642e01fSmrg            continue;
21276747b715Smrg        DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
212805b261ecSmrg        p1 = pWin->firstChild;
212905b261ecSmrg        FindInterestedChildren(dev, p1, mask, ev, count);
213005b261ecSmrg    }
213105b261ecSmrg}
21324642e01fSmrg
21336747b715Smrg/**
21346747b715Smrg * Set the XI2 mask for the given client on the given window.
21356747b715Smrg * @param dev The device to set the mask for.
21366747b715Smrg * @param win The window to set the mask on.
21376747b715Smrg * @param client The client setting the mask.
21386747b715Smrg * @param len Number of bytes in mask.
21396747b715Smrg * @param mask Event mask in the form of (1 << eventtype)
21406747b715Smrg */
21416747b715Smrgint
21426747b715SmrgXISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
21436747b715Smrg               unsigned int len, unsigned char* mask)
21446747b715Smrg{
21456747b715Smrg    OtherInputMasks *masks;
21466747b715Smrg    InputClientsPtr others = NULL;
21476747b715Smrg
21486747b715Smrg    masks = wOtherInputMasks(win);
21496747b715Smrg    if (masks)
21506747b715Smrg    {
21516747b715Smrg	for (others = wOtherInputMasks(win)->inputClients; others;
21526747b715Smrg	     others = others->next) {
21536747b715Smrg	    if (SameClient(others, client)) {
21546747b715Smrg                memset(others->xi2mask[dev->id], 0,
21556747b715Smrg                       sizeof(others->xi2mask[dev->id]));
21566747b715Smrg                break;
21576747b715Smrg            }
21586747b715Smrg        }
21596747b715Smrg    }
21606747b715Smrg
21616747b715Smrg    len = min(len, sizeof(others->xi2mask[dev->id]));
21626747b715Smrg
21636747b715Smrg    if (len && !others)
21646747b715Smrg    {
21656747b715Smrg        if (AddExtensionClient(win, client, 0, 0) != Success)
21666747b715Smrg            return BadAlloc;
21676747b715Smrg        others= wOtherInputMasks(win)->inputClients;
21686747b715Smrg    }
21696747b715Smrg
21706747b715Smrg    if (others)
21716747b715Smrg        memset(others->xi2mask[dev->id], 0, sizeof(others->xi2mask[dev->id]));
21726747b715Smrg
21736747b715Smrg    if (len)
21746747b715Smrg        memcpy(others->xi2mask[dev->id], mask, len);
21756747b715Smrg
21766747b715Smrg    RecalculateDeviceDeliverableEvents(win);
21776747b715Smrg
21786747b715Smrg    return Success;
21796747b715Smrg}
2180