exevents.c revision 6747b715
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;
8816747b715Smrg                if (button_is_down(sd, key, BUTTON_PROCESSED))
8824642e01fSmrg                    return DONT_PROCESS;
8834642e01fSmrg            }
8844642e01fSmrg        }
8856747b715Smrg        set_button_up(device, key, BUTTON_PROCESSED);
8864642e01fSmrg	if (device->valuator)
8874642e01fSmrg	    device->valuator->motionHintWindow = NullWindow;
8884642e01fSmrg        if (!b->map[key])
8894642e01fSmrg            return DONT_PROCESS;
89005b261ecSmrg        if (b->buttonsDown >= 1 && !--b->buttonsDown)
89105b261ecSmrg	    b->motionMask = 0;
8924642e01fSmrg	if (b->map[key] <= 5)
8934642e01fSmrg	    b->state &= ~((Button1Mask >> 1) << b->map[key]);
8946747b715Smrg
8956747b715Smrg        /* Add state and motionMask to the filter for this event */
8966747b715Smrg        mask = DevicePointerMotionMask | b->state | b->motionMask;
8976747b715Smrg        SetMaskForEvent(device->id, mask, DeviceMotionNotify);
8986747b715Smrg        mask = PointerMotionMask | b->state | b->motionMask;
8996747b715Smrg        SetMaskForEvent(device->id, mask, MotionNotify);
9006747b715Smrg    } else if (event->type == ET_ProximityIn)
9014642e01fSmrg	device->valuator->mode &= ~OutOfProximity;
9026747b715Smrg    else if (event->type == ET_ProximityOut)
9034642e01fSmrg	device->valuator->mode |= OutOfProximity;
9044642e01fSmrg
9054642e01fSmrg    return DEFAULT;
9064642e01fSmrg}
9074642e01fSmrg
9086747b715Smrgstatic void
9096747b715SmrgProcessRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
9106747b715Smrg{
9116747b715Smrg    GrabPtr grab = device->deviceGrab.grab;
9126747b715Smrg
9136747b715Smrg    if (grab)
9146747b715Smrg        DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE);
9156747b715Smrg    else { /* deliver to all root windows */
9166747b715Smrg        xEvent *xi;
9176747b715Smrg        int i;
9186747b715Smrg
9196747b715Smrg        i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi);
9206747b715Smrg        if (i != Success)
9216747b715Smrg        {
9226747b715Smrg            ErrorF("[Xi] %s: XI2 conversion failed in ProcessRawEvent (%d)\n",
9236747b715Smrg                    device->name, i);
9246747b715Smrg            return;
9256747b715Smrg        }
9266747b715Smrg
9276747b715Smrg        for (i = 0; i < screenInfo.numScreens; i++)
9286747b715Smrg            DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1,
9296747b715Smrg                                  GetEventFilter(device, xi), NULL);
9306747b715Smrg        free(xi);
9316747b715Smrg    }
9326747b715Smrg}
9336747b715Smrg
9344642e01fSmrg/**
9354642e01fSmrg * Main device event processing function.
9364642e01fSmrg * Called from when processing the events from the event queue.
9374642e01fSmrg *
9384642e01fSmrg */
9394642e01fSmrgvoid
9406747b715SmrgProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
9414642e01fSmrg{
9426747b715Smrg    GrabPtr grab;
9434642e01fSmrg    Bool deactivateDeviceGrab = FALSE;
9444642e01fSmrg    int key = 0, rootX, rootY;
9454642e01fSmrg    ButtonClassPtr b;
9464642e01fSmrg    KeyClassPtr k;
9474642e01fSmrg    ValuatorClassPtr v;
9484642e01fSmrg    int ret = 0;
9496747b715Smrg    int state, i;
9504642e01fSmrg    DeviceIntPtr mouse = NULL, kbd = NULL;
9516747b715Smrg    DeviceEvent *event = &ev->device_event;
9526747b715Smrg
9536747b715Smrg    CHECKEVENT(ev);
9546747b715Smrg
9556747b715Smrg    if (ev->any.type == ET_RawKeyPress ||
9566747b715Smrg        ev->any.type == ET_RawKeyRelease ||
9576747b715Smrg        ev->any.type == ET_RawButtonPress ||
9586747b715Smrg        ev->any.type == ET_RawButtonRelease ||
9596747b715Smrg        ev->any.type == ET_RawMotion)
9606747b715Smrg    {
9616747b715Smrg        ProcessRawEvent(&ev->raw_event, device);
9626747b715Smrg        return;
9636747b715Smrg    }
9644642e01fSmrg
9654642e01fSmrg    if (IsPointerDevice(device))
9664642e01fSmrg    {
9674642e01fSmrg        kbd = GetPairedDevice(device);
9684642e01fSmrg        mouse = device;
9694642e01fSmrg        if (!kbd->key) /* can happen with floating SDs */
9704642e01fSmrg            kbd = NULL;
9714642e01fSmrg    } else
9724642e01fSmrg    {
9734642e01fSmrg        mouse = GetPairedDevice(device);
9744642e01fSmrg        kbd = device;
9754642e01fSmrg        if (!mouse->valuator || !mouse->button) /* may be float. SDs */
9764642e01fSmrg            mouse = NULL;
9774642e01fSmrg    }
9784642e01fSmrg
9794642e01fSmrg    /* State needs to be assembled BEFORE the device is updated. */
9806747b715Smrg    state = (kbd && kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->state) : 0;
9816747b715Smrg    state |= (mouse && mouse->button) ? (mouse->button->state) : 0;
9826747b715Smrg
9836747b715Smrg    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
9846747b715Smrg        if (BitIsOn(mouse->button->down, i))
9856747b715Smrg            SetBit(event->buttons, i);
9866747b715Smrg
9876747b715Smrg    if (kbd && kbd->key)
9886747b715Smrg    {
9896747b715Smrg        XkbStatePtr state;
9906747b715Smrg        /* we need the state before the event happens */
9916747b715Smrg        if (event->type == ET_KeyPress || event->type == ET_KeyRelease)
9926747b715Smrg            state = &kbd->key->xkbInfo->prev_state;
9936747b715Smrg        else
9946747b715Smrg            state = &kbd->key->xkbInfo->state;
9956747b715Smrg
9966747b715Smrg        event->mods.base = state->base_mods;
9976747b715Smrg        event->mods.latched = state->latched_mods;
9986747b715Smrg        event->mods.locked = state->locked_mods;
9996747b715Smrg        event->mods.effective = state->mods;
10006747b715Smrg
10016747b715Smrg        event->group.base = state->base_group;
10026747b715Smrg        event->group.latched = state->latched_group;
10036747b715Smrg        event->group.locked = state->locked_group;
10046747b715Smrg        event->group.effective = state->group;
10056747b715Smrg    }
10064642e01fSmrg
10076747b715Smrg    ret = UpdateDeviceState(device, event);
10084642e01fSmrg    if (ret == DONT_PROCESS)
10094642e01fSmrg        return;
10104642e01fSmrg
10114642e01fSmrg    v = device->valuator;
10124642e01fSmrg    b = device->button;
10134642e01fSmrg    k = device->key;
10144642e01fSmrg
10156747b715Smrg    if (IsMaster(device) || !device->u.master)
10166747b715Smrg        CheckMotion(event, device);
10174642e01fSmrg
10186747b715Smrg    switch (event->type)
10196747b715Smrg    {
10206747b715Smrg        case ET_Motion:
10216747b715Smrg        case ET_ButtonPress:
10226747b715Smrg        case ET_ButtonRelease:
10236747b715Smrg        case ET_KeyPress:
10246747b715Smrg        case ET_KeyRelease:
10256747b715Smrg        case ET_ProximityIn:
10266747b715Smrg        case ET_ProximityOut:
10276747b715Smrg            GetSpritePosition(device, &rootX, &rootY);
10286747b715Smrg            event->root_x = rootX;
10296747b715Smrg            event->root_y = rootY;
10306747b715Smrg            NoticeEventTime((InternalEvent*)event);
10316747b715Smrg            event->corestate = state;
10326747b715Smrg            key = event->detail.key;
10336747b715Smrg            break;
10346747b715Smrg        default:
10356747b715Smrg            break;
10364642e01fSmrg    }
10376747b715Smrg
10386747b715Smrg    if (DeviceEventCallback && !syncEvents.playingEvents) {
10394642e01fSmrg	DeviceEventInfoRec eventinfo;
10406747b715Smrg	SpritePtr pSprite = device->spriteInfo->sprite;
10414642e01fSmrg
10426747b715Smrg	/* see comment in EnqueueEvents regarding the next three lines */
10436747b715Smrg	if (ev->any.type == ET_Motion)
10446747b715Smrg	    ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
10454642e01fSmrg
10466747b715Smrg	eventinfo.device = device;
10476747b715Smrg	eventinfo.event = ev;
10486747b715Smrg	CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
10494642e01fSmrg    }
10504642e01fSmrg
10516747b715Smrg    grab = device->deviceGrab.grab;
10524642e01fSmrg
10536747b715Smrg    switch(event->type)
10546747b715Smrg    {
10556747b715Smrg        case ET_KeyPress:
10566747b715Smrg            if (!grab && CheckDeviceGrabs(device, event, 0)) {
10576747b715Smrg                device->deviceGrab.activatingKey = key;
10586747b715Smrg                return;
10596747b715Smrg            }
10606747b715Smrg            break;
10616747b715Smrg        case ET_KeyRelease:
10626747b715Smrg            if (grab && device->deviceGrab.fromPassiveGrab &&
10636747b715Smrg                (key == device->deviceGrab.activatingKey) &&
10646747b715Smrg                (device->deviceGrab.grab->type == KeyPress ||
10656747b715Smrg                 device->deviceGrab.grab->type == DeviceKeyPress ||
10666747b715Smrg                 device->deviceGrab.grab->type == XI_KeyPress))
10676747b715Smrg                deactivateDeviceGrab = TRUE;
10686747b715Smrg            break;
10696747b715Smrg        case ET_ButtonPress:
10706747b715Smrg            event->detail.button = b->map[key];
10716747b715Smrg            if (!event->detail.button) { /* there's no button 0 */
10726747b715Smrg                event->detail.button = key;
10736747b715Smrg                return;
10746747b715Smrg            }
10756747b715Smrg            if (!grab && CheckDeviceGrabs(device, event, 0))
10766747b715Smrg            {
10776747b715Smrg                /* if a passive grab was activated, the event has been sent
10786747b715Smrg                 * already */
10796747b715Smrg                return;
10806747b715Smrg            }
10816747b715Smrg            break;
10826747b715Smrg        case ET_ButtonRelease:
10836747b715Smrg            event->detail.button = b->map[key];
10846747b715Smrg            if (!event->detail.button) { /* there's no button 0 */
10856747b715Smrg                event->detail.button = key;
10866747b715Smrg                return;
10876747b715Smrg            }
10886747b715Smrg            if (grab && !b->buttonsDown &&
10896747b715Smrg                device->deviceGrab.fromPassiveGrab &&
10906747b715Smrg                (device->deviceGrab.grab->type == ButtonPress ||
10916747b715Smrg                 device->deviceGrab.grab->type == DeviceButtonPress ||
10926747b715Smrg                 device->deviceGrab.grab->type == XI_ButtonPress))
10936747b715Smrg                deactivateDeviceGrab = TRUE;
10946747b715Smrg        default:
10956747b715Smrg            break;
10964642e01fSmrg    }
109705b261ecSmrg
10986747b715Smrg
109905b261ecSmrg    if (grab)
11006747b715Smrg        DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
11016747b715Smrg    else if (device->focus && !IsPointerEvent((InternalEvent*)ev))
11026747b715Smrg        DeliverFocusedEvent(device, (InternalEvent*)event,
11036747b715Smrg                            GetSpriteWindow(device));
110405b261ecSmrg    else
11056747b715Smrg        DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event,
11066747b715Smrg                            NullGrab, NullWindow, device);
110705b261ecSmrg
110805b261ecSmrg    if (deactivateDeviceGrab == TRUE)
11094642e01fSmrg	(*device->deviceGrab.DeactivateGrab) (device);
11106747b715Smrg    event->detail.key = key;
111105b261ecSmrg}
111205b261ecSmrg
11136747b715Smrgint
111405b261ecSmrgInitProximityClassDeviceStruct(DeviceIntPtr dev)
111505b261ecSmrg{
111605b261ecSmrg    ProximityClassPtr proxc;
111705b261ecSmrg
11186747b715Smrg    proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
111905b261ecSmrg    if (!proxc)
112005b261ecSmrg	return FALSE;
11216747b715Smrg    proxc->sourceid = dev->id;
112205b261ecSmrg    dev->proximity = proxc;
112305b261ecSmrg    return TRUE;
112405b261ecSmrg}
112505b261ecSmrg
11264642e01fSmrg/**
11274642e01fSmrg * Initialise the device's valuators. The memory must already be allocated,
11284642e01fSmrg * this function merely inits the matching axis (specified through axnum) to
11294642e01fSmrg * sane values.
11304642e01fSmrg *
11314642e01fSmrg * It is a condition that (minval < maxval).
11324642e01fSmrg *
11334642e01fSmrg * @see InitValuatorClassDeviceStruct
11344642e01fSmrg */
11356747b715Smrgvoid
11366747b715SmrgInitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
113705b261ecSmrg		       int resolution, int min_res, int max_res)
113805b261ecSmrg{
113905b261ecSmrg    AxisInfoPtr ax;
11404642e01fSmrg
11414642e01fSmrg    if (!dev || !dev->valuator || minval > maxval)
114205b261ecSmrg        return;
11436747b715Smrg    if (axnum >= dev->valuator->numAxes)
11446747b715Smrg        return;
114505b261ecSmrg
114605b261ecSmrg    ax = dev->valuator->axes + axnum;
114705b261ecSmrg
114805b261ecSmrg    ax->min_value = minval;
114905b261ecSmrg    ax->max_value = maxval;
115005b261ecSmrg    ax->resolution = resolution;
115105b261ecSmrg    ax->min_resolution = min_res;
115205b261ecSmrg    ax->max_resolution = max_res;
11536747b715Smrg    ax->label = label;
115405b261ecSmrg}
115505b261ecSmrg
115605b261ecSmrgstatic void
115705b261ecSmrgFixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
115805b261ecSmrg		     ButtonClassPtr b, ValuatorClassPtr v, int first)
115905b261ecSmrg{
116005b261ecSmrg    ev->type = DeviceStateNotify;
116105b261ecSmrg    ev->deviceid = dev->id;
116205b261ecSmrg    ev->time = currentTime.milliseconds;
116305b261ecSmrg    ev->classes_reported = 0;
116405b261ecSmrg    ev->num_keys = 0;
116505b261ecSmrg    ev->num_buttons = 0;
116605b261ecSmrg    ev->num_valuators = 0;
116705b261ecSmrg
116805b261ecSmrg    if (b) {
116905b261ecSmrg	ev->classes_reported |= (1 << ButtonClass);
117005b261ecSmrg	ev->num_buttons = b->numButtons;
11714642e01fSmrg	memcpy((char*)ev->buttons, (char*)b->down, 4);
117205b261ecSmrg    } else if (k) {
117305b261ecSmrg	ev->classes_reported |= (1 << KeyClass);
11746747b715Smrg	ev->num_keys = k->xkbInfo->desc->max_key_code -
11756747b715Smrg                       k->xkbInfo->desc->min_key_code;
117605b261ecSmrg	memmove((char *)&ev->keys[0], (char *)k->down, 4);
117705b261ecSmrg    }
117805b261ecSmrg    if (v) {
117905b261ecSmrg	int nval = v->numAxes - first;
118005b261ecSmrg
118105b261ecSmrg	ev->classes_reported |= (1 << ValuatorClass);
118205b261ecSmrg	ev->classes_reported |= (dev->valuator->mode << ModeBitsShift);
118305b261ecSmrg	ev->num_valuators = nval < 3 ? nval : 3;
118405b261ecSmrg	switch (ev->num_valuators) {
118505b261ecSmrg	case 3:
118605b261ecSmrg	    ev->valuator2 = v->axisVal[first + 2];
118705b261ecSmrg	case 2:
118805b261ecSmrg	    ev->valuator1 = v->axisVal[first + 1];
118905b261ecSmrg	case 1:
119005b261ecSmrg	    ev->valuator0 = v->axisVal[first];
119105b261ecSmrg	    break;
119205b261ecSmrg	}
119305b261ecSmrg    }
119405b261ecSmrg}
119505b261ecSmrg
119605b261ecSmrgstatic void
119705b261ecSmrgFixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
119805b261ecSmrg		  int first)
119905b261ecSmrg{
120005b261ecSmrg    int nval = v->numAxes - first;
120105b261ecSmrg
120205b261ecSmrg    ev->type = DeviceValuator;
120305b261ecSmrg    ev->deviceid = dev->id;
120405b261ecSmrg    ev->num_valuators = nval < 3 ? nval : 3;
120505b261ecSmrg    ev->first_valuator = first;
120605b261ecSmrg    switch (ev->num_valuators) {
120705b261ecSmrg    case 3:
120805b261ecSmrg	ev->valuator2 = v->axisVal[first + 2];
120905b261ecSmrg    case 2:
121005b261ecSmrg	ev->valuator1 = v->axisVal[first + 1];
121105b261ecSmrg    case 1:
121205b261ecSmrg	ev->valuator0 = v->axisVal[first];
121305b261ecSmrg	break;
121405b261ecSmrg    }
121505b261ecSmrg    first += ev->num_valuators;
121605b261ecSmrg}
121705b261ecSmrg
121805b261ecSmrgvoid
121905b261ecSmrgDeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
122005b261ecSmrg		 WindowPtr pWin)
122105b261ecSmrg{
122205b261ecSmrg    deviceFocus event;
12236747b715Smrg    xXIFocusInEvent *xi2event;
12246747b715Smrg    DeviceIntPtr mouse;
12256747b715Smrg    int btlen, len, i;
12266747b715Smrg
12276747b715Smrg    mouse = (IsMaster(dev) || dev->u.master) ? GetMaster(dev, MASTER_POINTER) : dev;
12286747b715Smrg
12296747b715Smrg    /* XI 2 event */
12306747b715Smrg    btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
12316747b715Smrg    btlen = bytes_to_int32(btlen);
12326747b715Smrg    len = sizeof(xXIFocusInEvent) + btlen * 4;
12336747b715Smrg
12346747b715Smrg    xi2event = calloc(1, len);
12356747b715Smrg    xi2event->type         = GenericEvent;
12366747b715Smrg    xi2event->extension    = IReqCode;
12376747b715Smrg    xi2event->evtype       = type;
12386747b715Smrg    xi2event->length       = bytes_to_int32(len - sizeof(xEvent));
12396747b715Smrg    xi2event->buttons_len  = btlen;
12406747b715Smrg    xi2event->detail       = detail;
12416747b715Smrg    xi2event->time         = currentTime.milliseconds;
12426747b715Smrg    xi2event->deviceid     = dev->id;
12436747b715Smrg    xi2event->sourceid     = dev->id; /* a device doesn't change focus by itself */
12446747b715Smrg    xi2event->mode         = mode;
12456747b715Smrg    xi2event->root_x       = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
12466747b715Smrg    xi2event->root_y       = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
12476747b715Smrg
12486747b715Smrg    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
12496747b715Smrg        if (BitIsOn(mouse->button->down, i))
12506747b715Smrg            SetBit(&xi2event[1], i);
12516747b715Smrg
12526747b715Smrg    if (dev->key)
12536747b715Smrg    {
12546747b715Smrg        xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods;
12556747b715Smrg        xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods;
12566747b715Smrg        xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods;
12576747b715Smrg        xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods;
12586747b715Smrg
12596747b715Smrg        xi2event->group.base_group = dev->key->xkbInfo->state.base_group;
12606747b715Smrg        xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group;
12616747b715Smrg        xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group;
12626747b715Smrg        xi2event->group.effective_group = dev->key->xkbInfo->state.group;
12636747b715Smrg    }
126405b261ecSmrg
12656747b715Smrg    FixUpEventFromWindow(dev, (xEvent*)xi2event, pWin, None, FALSE);
126605b261ecSmrg
12676747b715Smrg    DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
12686747b715Smrg                          GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
12696747b715Smrg
12706747b715Smrg    free(xi2event);
12716747b715Smrg
12726747b715Smrg    /* XI 1.x event */
127305b261ecSmrg    event.deviceid = dev->id;
127405b261ecSmrg    event.mode = mode;
12756747b715Smrg    event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
127605b261ecSmrg    event.detail = detail;
127705b261ecSmrg    event.window = pWin->drawable.id;
127805b261ecSmrg    event.time = currentTime.milliseconds;
127905b261ecSmrg
12806747b715Smrg    DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
12816747b715Smrg				DeviceFocusChangeMask, NullGrab);
128205b261ecSmrg
128305b261ecSmrg    if ((type == DeviceFocusIn) &&
128405b261ecSmrg	(wOtherInputMasks(pWin)) &&
128505b261ecSmrg	(wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
128605b261ecSmrg    {
128705b261ecSmrg	int evcount = 1;
128805b261ecSmrg	deviceStateNotify *ev, *sev;
128905b261ecSmrg	deviceKeyStateNotify *kev;
129005b261ecSmrg	deviceButtonStateNotify *bev;
129105b261ecSmrg
129205b261ecSmrg	KeyClassPtr k;
129305b261ecSmrg	ButtonClassPtr b;
129405b261ecSmrg	ValuatorClassPtr v;
129505b261ecSmrg	int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
129605b261ecSmrg
129705b261ecSmrg	if ((b = dev->button) != NULL) {
129805b261ecSmrg	    nbuttons = b->numButtons;
129905b261ecSmrg	    if (nbuttons > 32)
130005b261ecSmrg		evcount++;
130105b261ecSmrg	}
130205b261ecSmrg	if ((k = dev->key) != NULL) {
13036747b715Smrg	    nkeys = k->xkbInfo->desc->max_key_code -
13046747b715Smrg                    k->xkbInfo->desc->min_key_code;
130505b261ecSmrg	    if (nkeys > 32)
130605b261ecSmrg		evcount++;
130705b261ecSmrg	    if (nbuttons > 0) {
130805b261ecSmrg		evcount++;
130905b261ecSmrg	    }
131005b261ecSmrg	}
131105b261ecSmrg	if ((v = dev->valuator) != NULL) {
131205b261ecSmrg	    nval = v->numAxes;
131305b261ecSmrg
131405b261ecSmrg	    if (nval > 3)
131505b261ecSmrg		evcount++;
131605b261ecSmrg	    if (nval > 6) {
131705b261ecSmrg		if (!(k && b))
131805b261ecSmrg		    evcount++;
131905b261ecSmrg		if (nval > 9)
132005b261ecSmrg		    evcount += ((nval - 7) / 3);
132105b261ecSmrg	    }
132205b261ecSmrg	}
132305b261ecSmrg
13246747b715Smrg	sev = ev = (deviceStateNotify *) malloc(evcount * sizeof(xEvent));
132505b261ecSmrg	FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
132605b261ecSmrg
132705b261ecSmrg	if (b != NULL) {
132805b261ecSmrg	    FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
132905b261ecSmrg	    first += 3;
133005b261ecSmrg	    nval -= 3;
133105b261ecSmrg	    if (nbuttons > 32) {
133205b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
133305b261ecSmrg		bev = (deviceButtonStateNotify *) ev++;
133405b261ecSmrg		bev->type = DeviceButtonStateNotify;
133505b261ecSmrg		bev->deviceid = dev->id;
13364642e01fSmrg		memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
133705b261ecSmrg	    }
133805b261ecSmrg	    if (nval > 0) {
133905b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
134005b261ecSmrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
134105b261ecSmrg		first += 3;
134205b261ecSmrg		nval -= 3;
134305b261ecSmrg	    }
134405b261ecSmrg	}
134505b261ecSmrg
134605b261ecSmrg	if (k != NULL) {
134705b261ecSmrg	    FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
134805b261ecSmrg	    first += 3;
134905b261ecSmrg	    nval -= 3;
135005b261ecSmrg	    if (nkeys > 32) {
135105b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
135205b261ecSmrg		kev = (deviceKeyStateNotify *) ev++;
135305b261ecSmrg		kev->type = DeviceKeyStateNotify;
135405b261ecSmrg		kev->deviceid = dev->id;
135505b261ecSmrg		memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
135605b261ecSmrg	    }
135705b261ecSmrg	    if (nval > 0) {
135805b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
135905b261ecSmrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
136005b261ecSmrg		first += 3;
136105b261ecSmrg		nval -= 3;
136205b261ecSmrg	    }
136305b261ecSmrg	}
136405b261ecSmrg
136505b261ecSmrg	while (nval > 0) {
136605b261ecSmrg	    FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
136705b261ecSmrg	    first += 3;
136805b261ecSmrg	    nval -= 3;
136905b261ecSmrg	    if (nval > 0) {
137005b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
137105b261ecSmrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
137205b261ecSmrg		first += 3;
137305b261ecSmrg		nval -= 3;
137405b261ecSmrg	    }
137505b261ecSmrg	}
137605b261ecSmrg
13776747b715Smrg	DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
13786747b715Smrg				    DeviceStateNotifyMask, NullGrab);
13796747b715Smrg	free(sev);
138005b261ecSmrg    }
138105b261ecSmrg}
138205b261ecSmrg
138305b261ecSmrgint
13846747b715SmrgCheckGrabValues(ClientPtr client, GrabParameters* param)
138505b261ecSmrg{
13866747b715Smrg    if (param->grabtype != GRABTYPE_CORE &&
13876747b715Smrg        param->grabtype != GRABTYPE_XI &&
13886747b715Smrg        param->grabtype != GRABTYPE_XI2)
13896747b715Smrg    {
13906747b715Smrg        ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
13916747b715Smrg        return BadImplementation;
13926747b715Smrg    }
139305b261ecSmrg
13946747b715Smrg    if ((param->this_device_mode != GrabModeSync) &&
13956747b715Smrg	(param->this_device_mode != GrabModeAsync)) {
13966747b715Smrg	client->errorValue = param->this_device_mode;
139705b261ecSmrg	return BadValue;
139805b261ecSmrg    }
13996747b715Smrg    if ((param->other_devices_mode != GrabModeSync) &&
14006747b715Smrg	(param->other_devices_mode != GrabModeAsync)) {
14016747b715Smrg	client->errorValue = param->other_devices_mode;
140205b261ecSmrg	return BadValue;
140305b261ecSmrg    }
14046747b715Smrg
14056747b715Smrg    if (param->grabtype != GRABTYPE_XI2 && (param->modifiers != AnyModifier) &&
14066747b715Smrg        (param->modifiers & ~AllModifiersMask)) {
14076747b715Smrg	client->errorValue = param->modifiers;
140805b261ecSmrg	return BadValue;
140905b261ecSmrg    }
14106747b715Smrg
14116747b715Smrg    if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
14126747b715Smrg	client->errorValue = param->ownerEvents;
141305b261ecSmrg	return BadValue;
141405b261ecSmrg    }
14156747b715Smrg    return Success;
14166747b715Smrg}
14176747b715Smrg
14186747b715Smrgint
14196747b715SmrgGrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
14206747b715Smrg           int button, GrabParameters *param, GrabType grabtype,
14216747b715Smrg	   GrabMask *mask)
14226747b715Smrg{
14236747b715Smrg    WindowPtr pWin, confineTo;
14246747b715Smrg    CursorPtr cursor;
14256747b715Smrg    GrabPtr grab;
14266747b715Smrg    int rc, type = -1;
14276747b715Smrg    Mask access_mode = DixGrabAccess;
14286747b715Smrg
14296747b715Smrg    rc = CheckGrabValues(client, param);
143005b261ecSmrg    if (rc != Success)
143105b261ecSmrg	return rc;
14326747b715Smrg    if (param->confineTo == None)
143305b261ecSmrg	confineTo = NullWindow;
143405b261ecSmrg    else {
14356747b715Smrg	rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess);
143605b261ecSmrg	if (rc != Success)
143705b261ecSmrg	    return rc;
143805b261ecSmrg    }
14396747b715Smrg    if (param->cursor == None)
144005b261ecSmrg	cursor = NullCursor;
144105b261ecSmrg    else {
14426747b715Smrg	rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
14436747b715Smrg				     RT_CURSOR, client, DixUseAccess);
14444642e01fSmrg	if (rc != Success)
14454642e01fSmrg	{
14466747b715Smrg	    client->errorValue = param->cursor;
14476747b715Smrg	    return rc;
144805b261ecSmrg	}
14494642e01fSmrg	access_mode |= DixForceAccess;
145005b261ecSmrg    }
14516747b715Smrg    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
14524642e01fSmrg	access_mode |= DixFreezeAccess;
14534642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
14546747b715Smrg    if (rc != Success)
14556747b715Smrg	return rc;
14566747b715Smrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
14574642e01fSmrg    if (rc != Success)
14584642e01fSmrg	return rc;
145905b261ecSmrg
14606747b715Smrg    if (grabtype == GRABTYPE_XI)
14616747b715Smrg        type = DeviceButtonPress;
14626747b715Smrg    else if (grabtype == GRABTYPE_XI2)
14636747b715Smrg        type = XI_ButtonPress;
14646747b715Smrg
14656747b715Smrg    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
14666747b715Smrg                      mask, param, type, button, confineTo, cursor);
146705b261ecSmrg    if (!grab)
146805b261ecSmrg	return BadAlloc;
14694642e01fSmrg    return AddPassiveGrabToList(client, grab);
147005b261ecSmrg}
147105b261ecSmrg
14726747b715Smrg/**
14736747b715Smrg * Grab the given key. If grabtype is GRABTYPE_XI, the key is a keycode. If
14746747b715Smrg * grabtype is GRABTYPE_XI2, the key is a keysym.
14756747b715Smrg */
147605b261ecSmrgint
14776747b715SmrgGrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
14786747b715Smrg        int key, GrabParameters *param, GrabType grabtype, GrabMask *mask)
147905b261ecSmrg{
148005b261ecSmrg    WindowPtr pWin;
148105b261ecSmrg    GrabPtr grab;
148205b261ecSmrg    KeyClassPtr k = dev->key;
14834642e01fSmrg    Mask access_mode = DixGrabAccess;
14846747b715Smrg    int rc, type = -1;
148505b261ecSmrg
14866747b715Smrg    rc = CheckGrabValues(client, param);
14876747b715Smrg    if (rc != Success)
14886747b715Smrg        return rc;
148905b261ecSmrg    if (k == NULL)
149005b261ecSmrg	return BadMatch;
14916747b715Smrg    if (grabtype == GRABTYPE_XI)
14926747b715Smrg    {
14936747b715Smrg        if ((key > k->xkbInfo->desc->max_key_code ||
14946747b715Smrg                    key < k->xkbInfo->desc->min_key_code)
14956747b715Smrg                && (key != AnyKey)) {
14966747b715Smrg            client->errorValue = key;
14976747b715Smrg            return BadValue;
14986747b715Smrg        }
14996747b715Smrg        type = DeviceKeyPress;
15006747b715Smrg    } else if (grabtype == GRABTYPE_XI2)
15016747b715Smrg        type = XI_KeyPress;
15026747b715Smrg
15036747b715Smrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
15044642e01fSmrg    if (rc != Success)
15054642e01fSmrg	return rc;
15066747b715Smrg    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
15074642e01fSmrg	access_mode |= DixFreezeAccess;
15084642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
150905b261ecSmrg    if (rc != Success)
151005b261ecSmrg	return rc;
151105b261ecSmrg
15126747b715Smrg    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
15136747b715Smrg                      mask, param, type, key, NULL, NULL);
151405b261ecSmrg    if (!grab)
151505b261ecSmrg	return BadAlloc;
15164642e01fSmrg    return AddPassiveGrabToList(client, grab);
151705b261ecSmrg}
151805b261ecSmrg
15196747b715Smrg/* Enter/FocusIn grab */
15206747b715Smrgint
15216747b715SmrgGrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
15226747b715Smrg           GrabParameters *param, GrabMask *mask)
15236747b715Smrg{
15246747b715Smrg    WindowPtr pWin;
15256747b715Smrg    CursorPtr cursor;
15266747b715Smrg    GrabPtr grab;
15276747b715Smrg    Mask access_mode = DixGrabAccess;
15286747b715Smrg    int rc;
15296747b715Smrg
15306747b715Smrg    rc = CheckGrabValues(client, param);
15316747b715Smrg    if (rc != Success)
15326747b715Smrg        return rc;
15336747b715Smrg
15346747b715Smrg    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
15356747b715Smrg    if (rc != Success)
15366747b715Smrg	return rc;
15376747b715Smrg    if (param->cursor == None)
15386747b715Smrg	cursor = NullCursor;
15396747b715Smrg    else {
15406747b715Smrg	rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
15416747b715Smrg				     RT_CURSOR, client, DixUseAccess);
15426747b715Smrg	if (rc != Success)
15436747b715Smrg	{
15446747b715Smrg	    client->errorValue = param->cursor;
15456747b715Smrg	    return rc;
15466747b715Smrg	}
15476747b715Smrg	access_mode |= DixForceAccess;
15486747b715Smrg    }
15496747b715Smrg    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
15506747b715Smrg	access_mode |= DixFreezeAccess;
15516747b715Smrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
15526747b715Smrg    if (rc != Success)
15536747b715Smrg	return rc;
15546747b715Smrg
15556747b715Smrg    grab = CreateGrab(client->index, dev, dev, pWin, GRABTYPE_XI2,
15566747b715Smrg                      mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn,
15576747b715Smrg                      0, NULL, cursor);
15586747b715Smrg
15596747b715Smrg    if (!grab)
15606747b715Smrg        return BadAlloc;
15616747b715Smrg
15626747b715Smrg    return AddPassiveGrabToList(client, grab);
15636747b715Smrg}
15646747b715Smrg
156505b261ecSmrgint
156605b261ecSmrgSelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
15676747b715Smrg		Mask mask, Mask exclusivemasks)
156805b261ecSmrg{
156905b261ecSmrg    int mskidx = dev->id;
157005b261ecSmrg    int i, ret;
157105b261ecSmrg    Mask check;
157205b261ecSmrg    InputClientsPtr others;
157305b261ecSmrg
157405b261ecSmrg    check = (mask & exclusivemasks);
157505b261ecSmrg    if (wOtherInputMasks(pWin)) {
157605b261ecSmrg	if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {	/* It is illegal for two different
157705b261ecSmrg									 * clients to select on any of the
157805b261ecSmrg									 * events for maskcheck. However,
157905b261ecSmrg									 * it is OK, for some client to
158005b261ecSmrg									 * continue selecting on one of those
158105b261ecSmrg									 * events.  */
158205b261ecSmrg	    for (others = wOtherInputMasks(pWin)->inputClients; others;
158305b261ecSmrg		 others = others->next) {
158405b261ecSmrg		if (!SameClient(others, client) && (check &
158505b261ecSmrg						    others->mask[mskidx]))
158605b261ecSmrg		    return BadAccess;
158705b261ecSmrg	    }
158805b261ecSmrg	}
158905b261ecSmrg	for (others = wOtherInputMasks(pWin)->inputClients; others;
159005b261ecSmrg	     others = others->next) {
159105b261ecSmrg	    if (SameClient(others, client)) {
159205b261ecSmrg		check = others->mask[mskidx];
159305b261ecSmrg		others->mask[mskidx] = mask;
159405b261ecSmrg		if (mask == 0) {
159505b261ecSmrg		    for (i = 0; i < EMASKSIZE; i++)
159605b261ecSmrg			if (i != mskidx && others->mask[i] != 0)
159705b261ecSmrg			    break;
159805b261ecSmrg		    if (i == EMASKSIZE) {
159905b261ecSmrg			RecalculateDeviceDeliverableEvents(pWin);
160005b261ecSmrg			if (ShouldFreeInputMasks(pWin, FALSE))
160105b261ecSmrg			    FreeResource(others->resource, RT_NONE);
160205b261ecSmrg			return Success;
160305b261ecSmrg		    }
160405b261ecSmrg		}
160505b261ecSmrg		goto maskSet;
160605b261ecSmrg	    }
160705b261ecSmrg	}
160805b261ecSmrg    }
160905b261ecSmrg    check = 0;
161005b261ecSmrg    if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
161105b261ecSmrg	return ret;
161205b261ecSmrg  maskSet:
161305b261ecSmrg    if (dev->valuator)
161405b261ecSmrg	if ((dev->valuator->motionHintWindow == pWin) &&
161505b261ecSmrg	    (mask & DevicePointerMotionHintMask) &&
16164642e01fSmrg	    !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
161705b261ecSmrg	    dev->valuator->motionHintWindow = NullWindow;
161805b261ecSmrg    RecalculateDeviceDeliverableEvents(pWin);
161905b261ecSmrg    return Success;
162005b261ecSmrg}
162105b261ecSmrg
162205b261ecSmrgint
162305b261ecSmrgAddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
162405b261ecSmrg{
162505b261ecSmrg    InputClientsPtr others;
162605b261ecSmrg
162705b261ecSmrg    if (!pWin->optional && !MakeWindowOptional(pWin))
162805b261ecSmrg	return BadAlloc;
16296747b715Smrg    others = calloc(1, sizeof(InputClients));
163005b261ecSmrg    if (!others)
163105b261ecSmrg	return BadAlloc;
163205b261ecSmrg    if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
163305b261ecSmrg	return BadAlloc;
163405b261ecSmrg    others->mask[mskidx] = mask;
163505b261ecSmrg    others->resource = FakeClientID(client->index);
163605b261ecSmrg    others->next = pWin->optional->inputMasks->inputClients;
163705b261ecSmrg    pWin->optional->inputMasks->inputClients = others;
163805b261ecSmrg    if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
163905b261ecSmrg	return BadAlloc;
164005b261ecSmrg    return Success;
164105b261ecSmrg}
164205b261ecSmrg
164305b261ecSmrgstatic Bool
164405b261ecSmrgMakeInputMasks(WindowPtr pWin)
164505b261ecSmrg{
164605b261ecSmrg    struct _OtherInputMasks *imasks;
164705b261ecSmrg
16486747b715Smrg    imasks = calloc(1, sizeof(struct _OtherInputMasks));
164905b261ecSmrg    if (!imasks)
165005b261ecSmrg	return FALSE;
165105b261ecSmrg    pWin->optional->inputMasks = imasks;
165205b261ecSmrg    return TRUE;
165305b261ecSmrg}
165405b261ecSmrg
165505b261ecSmrgvoid
165605b261ecSmrgRecalculateDeviceDeliverableEvents(WindowPtr pWin)
165705b261ecSmrg{
165805b261ecSmrg    InputClientsPtr others;
165905b261ecSmrg    struct _OtherInputMasks *inputMasks;	/* default: NULL */
166005b261ecSmrg    WindowPtr pChild, tmp;
16616747b715Smrg    int i, j;
166205b261ecSmrg
166305b261ecSmrg    pChild = pWin;
166405b261ecSmrg    while (1) {
166505b261ecSmrg	if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
16666747b715Smrg            for (i = 0; i < EMASKSIZE; i++)
16676747b715Smrg                memset(inputMasks->xi2mask[i], 0, sizeof(inputMasks->xi2mask[i]));
166805b261ecSmrg	    for (others = inputMasks->inputClients; others;
166905b261ecSmrg		 others = others->next) {
167005b261ecSmrg		for (i = 0; i < EMASKSIZE; i++)
167105b261ecSmrg		    inputMasks->inputEvents[i] |= others->mask[i];
16726747b715Smrg                for (i = 0; i < EMASKSIZE; i++)
16736747b715Smrg                    for (j = 0; j < XI2MASKSIZE; j++)
16746747b715Smrg                        inputMasks->xi2mask[i][j] |= others->xi2mask[i][j];
167505b261ecSmrg	    }
167605b261ecSmrg	    for (i = 0; i < EMASKSIZE; i++)
167705b261ecSmrg		inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
167805b261ecSmrg	    for (tmp = pChild->parent; tmp; tmp = tmp->parent)
167905b261ecSmrg		if (wOtherInputMasks(tmp))
168005b261ecSmrg		    for (i = 0; i < EMASKSIZE; i++)
168105b261ecSmrg			inputMasks->deliverableEvents[i] |=
168205b261ecSmrg			    (wOtherInputMasks(tmp)->deliverableEvents[i]
168305b261ecSmrg			     & ~inputMasks->
168405b261ecSmrg			     dontPropagateMask[i] & PropagateMask[i]);
168505b261ecSmrg	}
168605b261ecSmrg	if (pChild->firstChild) {
168705b261ecSmrg	    pChild = pChild->firstChild;
168805b261ecSmrg	    continue;
168905b261ecSmrg	}
169005b261ecSmrg	while (!pChild->nextSib && (pChild != pWin))
169105b261ecSmrg	    pChild = pChild->parent;
169205b261ecSmrg	if (pChild == pWin)
169305b261ecSmrg	    break;
169405b261ecSmrg	pChild = pChild->nextSib;
169505b261ecSmrg    }
169605b261ecSmrg}
169705b261ecSmrg
169805b261ecSmrgint
169905b261ecSmrgInputClientGone(WindowPtr pWin, XID id)
170005b261ecSmrg{
170105b261ecSmrg    InputClientsPtr other, prev;
170205b261ecSmrg
170305b261ecSmrg    if (!wOtherInputMasks(pWin))
17046747b715Smrg	return Success;
170505b261ecSmrg    prev = 0;
170605b261ecSmrg    for (other = wOtherInputMasks(pWin)->inputClients; other;
170705b261ecSmrg	 other = other->next) {
170805b261ecSmrg	if (other->resource == id) {
170905b261ecSmrg	    if (prev) {
171005b261ecSmrg		prev->next = other->next;
17116747b715Smrg		free(other);
171205b261ecSmrg	    } else if (!(other->next)) {
171305b261ecSmrg		if (ShouldFreeInputMasks(pWin, TRUE)) {
171405b261ecSmrg		    wOtherInputMasks(pWin)->inputClients = other->next;
17156747b715Smrg		    free(wOtherInputMasks(pWin));
171605b261ecSmrg		    pWin->optional->inputMasks = (OtherInputMasks *) NULL;
171705b261ecSmrg		    CheckWindowOptionalNeed(pWin);
17186747b715Smrg		    free(other);
171905b261ecSmrg		} else {
172005b261ecSmrg		    other->resource = FakeClientID(0);
172105b261ecSmrg		    if (!AddResource(other->resource, RT_INPUTCLIENT,
172205b261ecSmrg				     (pointer) pWin))
172305b261ecSmrg			return BadAlloc;
172405b261ecSmrg		}
172505b261ecSmrg	    } else {
172605b261ecSmrg		wOtherInputMasks(pWin)->inputClients = other->next;
17276747b715Smrg		free(other);
172805b261ecSmrg	    }
172905b261ecSmrg	    RecalculateDeviceDeliverableEvents(pWin);
17306747b715Smrg	    return Success;
173105b261ecSmrg	}
173205b261ecSmrg	prev = other;
173305b261ecSmrg    }
173405b261ecSmrg    FatalError("client not on device event list");
173505b261ecSmrg}
173605b261ecSmrg
173705b261ecSmrgint
173805b261ecSmrgSendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
173905b261ecSmrg	  xEvent * ev, Mask mask, int count)
174005b261ecSmrg{
174105b261ecSmrg    WindowPtr pWin;
174205b261ecSmrg    WindowPtr effectiveFocus = NullWindow;	/* only set if dest==InputFocus */
17434642e01fSmrg    WindowPtr spriteWin = GetSpriteWindow(d);
174405b261ecSmrg
174505b261ecSmrg    if (dest == PointerWindow)
174605b261ecSmrg	pWin = spriteWin;
174705b261ecSmrg    else if (dest == InputFocus) {
174805b261ecSmrg	WindowPtr inputFocus;
174905b261ecSmrg
175005b261ecSmrg	if (!d->focus)
175105b261ecSmrg	    inputFocus = spriteWin;
175205b261ecSmrg	else
175305b261ecSmrg	    inputFocus = d->focus->win;
175405b261ecSmrg
175505b261ecSmrg	if (inputFocus == FollowKeyboardWin)
175605b261ecSmrg	    inputFocus = inputInfo.keyboard->focus->win;
175705b261ecSmrg
175805b261ecSmrg	if (inputFocus == NoneWin)
175905b261ecSmrg	    return Success;
176005b261ecSmrg
176105b261ecSmrg	/* If the input focus is PointerRootWin, send the event to where
176205b261ecSmrg	 * the pointer is if possible, then perhaps propogate up to root. */
176305b261ecSmrg	if (inputFocus == PointerRootWin)
17644642e01fSmrg	    inputFocus = GetCurrentRootWindow(d);
176505b261ecSmrg
176605b261ecSmrg	if (IsParent(inputFocus, spriteWin)) {
176705b261ecSmrg	    effectiveFocus = inputFocus;
176805b261ecSmrg	    pWin = spriteWin;
176905b261ecSmrg	} else
177005b261ecSmrg	    effectiveFocus = pWin = inputFocus;
177105b261ecSmrg    } else
17724642e01fSmrg	dixLookupWindow(&pWin, dest, client, DixSendAccess);
177305b261ecSmrg    if (!pWin)
177405b261ecSmrg	return BadWindow;
177505b261ecSmrg    if ((propagate != xFalse) && (propagate != xTrue)) {
177605b261ecSmrg	client->errorValue = propagate;
177705b261ecSmrg	return BadValue;
177805b261ecSmrg    }
177905b261ecSmrg    ev->u.u.type |= 0x80;
178005b261ecSmrg    if (propagate) {
178105b261ecSmrg	for (; pWin; pWin = pWin->parent) {
17826747b715Smrg	    if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
178305b261ecSmrg		return Success;
178405b261ecSmrg	    if (pWin == effectiveFocus)
178505b261ecSmrg		return Success;
178605b261ecSmrg	    if (wOtherInputMasks(pWin))
178705b261ecSmrg		mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
178805b261ecSmrg	    if (!mask)
178905b261ecSmrg		break;
179005b261ecSmrg	}
17914642e01fSmrg    } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
17926747b715Smrg	DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
179305b261ecSmrg    return Success;
179405b261ecSmrg}
179505b261ecSmrg
179605b261ecSmrgint
179705b261ecSmrgSetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
179805b261ecSmrg{
179905b261ecSmrg    int i;
180005b261ecSmrg    ButtonClassPtr b = dev->button;
180105b261ecSmrg
180205b261ecSmrg    if (b == NULL)
180305b261ecSmrg	return BadMatch;
180405b261ecSmrg
180505b261ecSmrg    if (nElts != b->numButtons) {
180605b261ecSmrg	client->errorValue = nElts;
180705b261ecSmrg	return BadValue;
180805b261ecSmrg    }
180905b261ecSmrg    if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
181005b261ecSmrg	return BadValue;
181105b261ecSmrg    for (i = 0; i < nElts; i++)
181205b261ecSmrg	if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
181305b261ecSmrg	    return MappingBusy;
181405b261ecSmrg    for (i = 0; i < nElts; i++)
181505b261ecSmrg	b->map[i + 1] = map[i];
181605b261ecSmrg    return Success;
181705b261ecSmrg}
181805b261ecSmrg
181905b261ecSmrgint
182005b261ecSmrgChangeKeyMapping(ClientPtr client,
182105b261ecSmrg		 DeviceIntPtr dev,
182205b261ecSmrg		 unsigned len,
182305b261ecSmrg		 int type,
182405b261ecSmrg		 KeyCode firstKeyCode,
182505b261ecSmrg		 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
182605b261ecSmrg{
182705b261ecSmrg    KeySymsRec keysyms;
182805b261ecSmrg    KeyClassPtr k = dev->key;
182905b261ecSmrg
183005b261ecSmrg    if (k == NULL)
18316747b715Smrg	return BadMatch;
183205b261ecSmrg
183305b261ecSmrg    if (len != (keyCodes * keySymsPerKeyCode))
183405b261ecSmrg	return BadLength;
183505b261ecSmrg
18366747b715Smrg    if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
18376747b715Smrg	(firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
183805b261ecSmrg	client->errorValue = firstKeyCode;
183905b261ecSmrg	return BadValue;
184005b261ecSmrg    }
184105b261ecSmrg    if (keySymsPerKeyCode == 0) {
184205b261ecSmrg	client->errorValue = 0;
184305b261ecSmrg	return BadValue;
184405b261ecSmrg    }
184505b261ecSmrg    keysyms.minKeyCode = firstKeyCode;
184605b261ecSmrg    keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
184705b261ecSmrg    keysyms.mapWidth = keySymsPerKeyCode;
184805b261ecSmrg    keysyms.map = map;
18496747b715Smrg
18506747b715Smrg    XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
18516747b715Smrg                          serverClient);
18526747b715Smrg
18536747b715Smrg    return Success;
185405b261ecSmrg}
185505b261ecSmrg
185605b261ecSmrgstatic void
185705b261ecSmrgDeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
185805b261ecSmrg{
185905b261ecSmrg    WindowPtr parent;
186005b261ecSmrg
186105b261ecSmrg    /* Deactivate any grabs performed on this window, before making
186205b261ecSmrg     * any input focus changes.
186305b261ecSmrg     * Deactivating a device grab should cause focus events. */
186405b261ecSmrg
18654642e01fSmrg    if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
18664642e01fSmrg	(*dev->deviceGrab.DeactivateGrab) (dev);
186705b261ecSmrg
18684642e01fSmrg    /* If the focus window is a root window (ie. has no parent)
186905b261ecSmrg     * then don't delete the focus from it. */
187005b261ecSmrg
187105b261ecSmrg    if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
187205b261ecSmrg	int focusEventMode = NotifyNormal;
187305b261ecSmrg
187405b261ecSmrg	/* If a grab is in progress, then alter the mode of focus events. */
187505b261ecSmrg
18764642e01fSmrg	if (dev->deviceGrab.grab)
187705b261ecSmrg	    focusEventMode = NotifyWhileGrabbed;
187805b261ecSmrg
187905b261ecSmrg	switch (dev->focus->revert) {
188005b261ecSmrg	case RevertToNone:
18816747b715Smrg	    if (!ActivateFocusInGrab(dev, pWin, NoneWin))
18826747b715Smrg		DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
188305b261ecSmrg	    dev->focus->win = NoneWin;
188405b261ecSmrg	    dev->focus->traceGood = 0;
188505b261ecSmrg	    break;
188605b261ecSmrg	case RevertToParent:
188705b261ecSmrg	    parent = pWin;
188805b261ecSmrg	    do {
188905b261ecSmrg		parent = parent->parent;
189005b261ecSmrg		dev->focus->traceGood--;
189105b261ecSmrg	    }
189205b261ecSmrg	    while (!parent->realized);
18936747b715Smrg	    if (!ActivateFocusInGrab(dev, pWin, parent))
18946747b715Smrg		DoFocusEvents(dev, pWin, parent, focusEventMode);
189505b261ecSmrg	    dev->focus->win = parent;
189605b261ecSmrg	    dev->focus->revert = RevertToNone;
189705b261ecSmrg	    break;
189805b261ecSmrg	case RevertToPointerRoot:
18996747b715Smrg	    if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
19006747b715Smrg		DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
190105b261ecSmrg	    dev->focus->win = PointerRootWin;
190205b261ecSmrg	    dev->focus->traceGood = 0;
190305b261ecSmrg	    break;
190405b261ecSmrg	case RevertToFollowKeyboard:
19056747b715Smrg            {
19066747b715Smrg                DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
19076747b715Smrg                if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
19086747b715Smrg                    kbd = inputInfo.keyboard;
19096747b715Smrg	    if (kbd->focus->win) {
19106747b715Smrg		if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
19116747b715Smrg		    DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
191205b261ecSmrg		dev->focus->win = FollowKeyboardWin;
191305b261ecSmrg		dev->focus->traceGood = 0;
191405b261ecSmrg	    } else {
19156747b715Smrg                if (!ActivateFocusInGrab(dev, pWin, NoneWin))
19166747b715Smrg                    DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
191705b261ecSmrg		dev->focus->win = NoneWin;
191805b261ecSmrg		dev->focus->traceGood = 0;
191905b261ecSmrg	    }
19206747b715Smrg            }
192105b261ecSmrg	    break;
192205b261ecSmrg	}
192305b261ecSmrg    }
192405b261ecSmrg
192505b261ecSmrg    if (dev->valuator)
192605b261ecSmrg	if (dev->valuator->motionHintWindow == pWin)
192705b261ecSmrg	    dev->valuator->motionHintWindow = NullWindow;
192805b261ecSmrg}
192905b261ecSmrg
193005b261ecSmrgvoid
193105b261ecSmrgDeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
193205b261ecSmrg{
193305b261ecSmrg    int i;
193405b261ecSmrg    DeviceIntPtr dev;
193505b261ecSmrg    InputClientsPtr ic;
193605b261ecSmrg    struct _OtherInputMasks *inputMasks;
193705b261ecSmrg
193805b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
193905b261ecSmrg	DeleteDeviceFromAnyExtEvents(pWin, dev);
194005b261ecSmrg    }
194105b261ecSmrg
194205b261ecSmrg    for (dev = inputInfo.off_devices; dev; dev = dev->next)
194305b261ecSmrg	DeleteDeviceFromAnyExtEvents(pWin, dev);
194405b261ecSmrg
194505b261ecSmrg    if (freeResources)
194605b261ecSmrg	while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
194705b261ecSmrg	    ic = inputMasks->inputClients;
194805b261ecSmrg	    for (i = 0; i < EMASKSIZE; i++)
194905b261ecSmrg		inputMasks->dontPropagateMask[i] = 0;
195005b261ecSmrg	    FreeResource(ic->resource, RT_NONE);
195105b261ecSmrg	}
195205b261ecSmrg}
195305b261ecSmrg
195405b261ecSmrgint
195505b261ecSmrgMaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
195605b261ecSmrg{
195705b261ecSmrg    DeviceIntPtr dev;
195805b261ecSmrg
19594642e01fSmrg    dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
19604642e01fSmrg		    DixReadAccess);
196105b261ecSmrg    if (!dev)
196205b261ecSmrg        return 0;
196305b261ecSmrg
196405b261ecSmrg    if (pEvents->type == DeviceMotionNotify) {
196505b261ecSmrg	if (mask & DevicePointerMotionHintMask) {
196605b261ecSmrg	    if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
196705b261ecSmrg		return 1;	/* don't send, but pretend we did */
196805b261ecSmrg	    }
196905b261ecSmrg	    pEvents->detail = NotifyHint;
197005b261ecSmrg	} else {
197105b261ecSmrg	    pEvents->detail = NotifyNormal;
197205b261ecSmrg	}
197305b261ecSmrg    }
19746747b715Smrg    return 0;
197505b261ecSmrg}
197605b261ecSmrg
197705b261ecSmrgvoid
197805b261ecSmrgCheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
197905b261ecSmrg			     deviceKeyButtonPointer * xE, GrabPtr grab,
198005b261ecSmrg			     ClientPtr client, Mask deliveryMask)
198105b261ecSmrg{
198205b261ecSmrg    DeviceIntPtr dev;
198305b261ecSmrg
19844642e01fSmrg    dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
19856747b715Smrg		    DixGrabAccess);
198605b261ecSmrg    if (!dev)
198705b261ecSmrg        return;
198805b261ecSmrg
198905b261ecSmrg    if (type == DeviceMotionNotify)
199005b261ecSmrg	dev->valuator->motionHintWindow = pWin;
199105b261ecSmrg    else if ((type == DeviceButtonPress) && (!grab) &&
199205b261ecSmrg	     (deliveryMask & DeviceButtonGrabMask)) {
199305b261ecSmrg	GrabRec tempGrab;
199405b261ecSmrg
199505b261ecSmrg	tempGrab.device = dev;
199605b261ecSmrg	tempGrab.resource = client->clientAsMask;
199705b261ecSmrg	tempGrab.window = pWin;
199805b261ecSmrg	tempGrab.ownerEvents =
199905b261ecSmrg	    (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
200005b261ecSmrg	tempGrab.eventMask = deliveryMask;
200105b261ecSmrg	tempGrab.keyboardMode = GrabModeAsync;
200205b261ecSmrg	tempGrab.pointerMode = GrabModeAsync;
200305b261ecSmrg	tempGrab.confineTo = NullWindow;
200405b261ecSmrg	tempGrab.cursor = NullCursor;
20054642e01fSmrg        tempGrab.next = NULL;
20064642e01fSmrg	(*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
200705b261ecSmrg    }
200805b261ecSmrg}
200905b261ecSmrg
201005b261ecSmrgstatic Mask
201105b261ecSmrgDeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
201205b261ecSmrg{
201305b261ecSmrg    InputClientsPtr other;
201405b261ecSmrg
201505b261ecSmrg    if (!wOtherInputMasks(pWin))
201605b261ecSmrg	return 0;
201705b261ecSmrg    for (other = wOtherInputMasks(pWin)->inputClients; other;
201805b261ecSmrg	 other = other->next) {
201905b261ecSmrg	if (SameClient(other, client))
202005b261ecSmrg	    return other->mask[dev->id];
202105b261ecSmrg    }
202205b261ecSmrg    return 0;
202305b261ecSmrg}
202405b261ecSmrg
202505b261ecSmrgvoid
202605b261ecSmrgMaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
202705b261ecSmrg{
202805b261ecSmrg    WindowPtr pWin;
20294642e01fSmrg    GrabPtr grab = dev->deviceGrab.grab;
203005b261ecSmrg
203105b261ecSmrg    pWin = dev->valuator->motionHintWindow;
203205b261ecSmrg
203305b261ecSmrg    if ((grab && SameClient(grab, client) &&
203405b261ecSmrg	 ((grab->eventMask & DevicePointerMotionHintMask) ||
203505b261ecSmrg	  (grab->ownerEvents &&
203605b261ecSmrg	   (DeviceEventMaskForClient(dev, pWin, client) &
203705b261ecSmrg	    DevicePointerMotionHintMask)))) ||
203805b261ecSmrg	(!grab &&
203905b261ecSmrg	 (DeviceEventMaskForClient(dev, pWin, client) &
204005b261ecSmrg	  DevicePointerMotionHintMask)))
204105b261ecSmrg	dev->valuator->motionHintWindow = NullWindow;
204205b261ecSmrg}
204305b261ecSmrg
204405b261ecSmrgint
204505b261ecSmrgDeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
204605b261ecSmrg			     int maskndx)
204705b261ecSmrg{
204805b261ecSmrg    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
204905b261ecSmrg
205005b261ecSmrg    if (mask & ~PropagateMask[maskndx]) {
205105b261ecSmrg	client->errorValue = mask;
205205b261ecSmrg	return BadValue;
205305b261ecSmrg    }
205405b261ecSmrg
205505b261ecSmrg    if (mask == 0) {
205605b261ecSmrg	if (inputMasks)
205705b261ecSmrg	    inputMasks->dontPropagateMask[maskndx] = mask;
205805b261ecSmrg    } else {
205905b261ecSmrg	if (!inputMasks)
206005b261ecSmrg	    AddExtensionClient(pWin, client, 0, 0);
206105b261ecSmrg	inputMasks = wOtherInputMasks(pWin);
206205b261ecSmrg	inputMasks->dontPropagateMask[maskndx] = mask;
206305b261ecSmrg    }
206405b261ecSmrg    RecalculateDeviceDeliverableEvents(pWin);
206505b261ecSmrg    if (ShouldFreeInputMasks(pWin, FALSE))
206605b261ecSmrg	FreeResource(inputMasks->inputClients->resource, RT_NONE);
206705b261ecSmrg    return Success;
206805b261ecSmrg}
206905b261ecSmrg
20704642e01fSmrgBool
207105b261ecSmrgShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
207205b261ecSmrg{
207305b261ecSmrg    int i;
207405b261ecSmrg    Mask allInputEventMasks = 0;
207505b261ecSmrg    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
207605b261ecSmrg
207705b261ecSmrg    for (i = 0; i < EMASKSIZE; i++)
207805b261ecSmrg	allInputEventMasks |= inputMasks->dontPropagateMask[i];
207905b261ecSmrg    if (!ignoreSelectedEvents)
208005b261ecSmrg	for (i = 0; i < EMASKSIZE; i++)
208105b261ecSmrg	    allInputEventMasks |= inputMasks->inputEvents[i];
208205b261ecSmrg    if (allInputEventMasks == 0)
208305b261ecSmrg	return TRUE;
208405b261ecSmrg    else
208505b261ecSmrg	return FALSE;
208605b261ecSmrg}
208705b261ecSmrg
208805b261ecSmrg/***********************************************************************
208905b261ecSmrg *
209005b261ecSmrg * Walk through the window tree, finding all clients that want to know
209105b261ecSmrg * about the Event.
209205b261ecSmrg *
209305b261ecSmrg */
209405b261ecSmrg
209505b261ecSmrgstatic void
209605b261ecSmrgFindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
209705b261ecSmrg                       xEvent * ev, int count)
209805b261ecSmrg{
209905b261ecSmrg    WindowPtr p2;
210005b261ecSmrg
210105b261ecSmrg    while (p1) {
210205b261ecSmrg        p2 = p1->firstChild;
21036747b715Smrg        DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
210405b261ecSmrg        FindInterestedChildren(dev, p2, mask, ev, count);
210505b261ecSmrg        p1 = p1->nextSib;
210605b261ecSmrg    }
210705b261ecSmrg}
210805b261ecSmrg
210905b261ecSmrg/***********************************************************************
211005b261ecSmrg *
211105b261ecSmrg * Send an event to interested clients in all windows on all screens.
211205b261ecSmrg *
211305b261ecSmrg */
211405b261ecSmrg
211505b261ecSmrgvoid
211605b261ecSmrgSendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
211705b261ecSmrg{
211805b261ecSmrg    int i;
211905b261ecSmrg    WindowPtr pWin, p1;
212005b261ecSmrg
212105b261ecSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
21226747b715Smrg        pWin = screenInfo.screens[i]->root;
21234642e01fSmrg        if (!pWin)
21244642e01fSmrg            continue;
21256747b715Smrg        DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
212605b261ecSmrg        p1 = pWin->firstChild;
212705b261ecSmrg        FindInterestedChildren(dev, p1, mask, ev, count);
212805b261ecSmrg    }
212905b261ecSmrg}
21304642e01fSmrg
21316747b715Smrg/**
21326747b715Smrg * Set the XI2 mask for the given client on the given window.
21336747b715Smrg * @param dev The device to set the mask for.
21346747b715Smrg * @param win The window to set the mask on.
21356747b715Smrg * @param client The client setting the mask.
21366747b715Smrg * @param len Number of bytes in mask.
21376747b715Smrg * @param mask Event mask in the form of (1 << eventtype)
21386747b715Smrg */
21396747b715Smrgint
21406747b715SmrgXISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
21416747b715Smrg               unsigned int len, unsigned char* mask)
21426747b715Smrg{
21436747b715Smrg    OtherInputMasks *masks;
21446747b715Smrg    InputClientsPtr others = NULL;
21456747b715Smrg
21466747b715Smrg    masks = wOtherInputMasks(win);
21476747b715Smrg    if (masks)
21486747b715Smrg    {
21496747b715Smrg	for (others = wOtherInputMasks(win)->inputClients; others;
21506747b715Smrg	     others = others->next) {
21516747b715Smrg	    if (SameClient(others, client)) {
21526747b715Smrg                memset(others->xi2mask[dev->id], 0,
21536747b715Smrg                       sizeof(others->xi2mask[dev->id]));
21546747b715Smrg                break;
21556747b715Smrg            }
21566747b715Smrg        }
21576747b715Smrg    }
21586747b715Smrg
21596747b715Smrg    len = min(len, sizeof(others->xi2mask[dev->id]));
21606747b715Smrg
21616747b715Smrg    if (len && !others)
21626747b715Smrg    {
21636747b715Smrg        if (AddExtensionClient(win, client, 0, 0) != Success)
21646747b715Smrg            return BadAlloc;
21656747b715Smrg        others= wOtherInputMasks(win)->inputClients;
21666747b715Smrg    }
21676747b715Smrg
21686747b715Smrg    if (others)
21696747b715Smrg        memset(others->xi2mask[dev->id], 0, sizeof(others->xi2mask[dev->id]));
21706747b715Smrg
21716747b715Smrg    if (len)
21726747b715Smrg        memcpy(others->xi2mask[dev->id], mask, len);
21736747b715Smrg
21746747b715Smrg    RecalculateDeviceDeliverableEvents(win);
21756747b715Smrg
21766747b715Smrg    return Success;
21776747b715Smrg}
2178