exevents.c revision 4642e01f
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#define	 NEED_EVENTS
5605b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
5705b261ecSmrg#include <dix-config.h>
5805b261ecSmrg#endif
5905b261ecSmrg
6005b261ecSmrg#include <X11/X.h>
6105b261ecSmrg#include <X11/Xproto.h>
6205b261ecSmrg#include <X11/extensions/XI.h>
6305b261ecSmrg#include <X11/extensions/XIproto.h>
644642e01fSmrg#include <X11/extensions/geproto.h>
6505b261ecSmrg#include "inputstr.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"
7705b261ecSmrg
7805b261ecSmrg#ifdef XKB
794642e01fSmrg#include <X11/extensions/XKBproto.h>
8005b261ecSmrg#include "xkbsrv.h"
814642e01fSmrgextern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies);
8205b261ecSmrg#endif
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#define Motion_Filter(class) (DevicePointerMotionMask | \
9105b261ecSmrg			      (class)->state | (class)->motionMask)
9205b261ecSmrg
934642e01fSmrgBool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
9405b261ecSmrg				 Bool	/* ignoreSelectedEvents */
9505b261ecSmrg    );
9605b261ecSmrgstatic Bool MakeInputMasks(WindowPtr	/* pWin */
9705b261ecSmrg    );
9805b261ecSmrg
994642e01fSmrg/* Used to sture classes currently not in use by an MD */
1004642e01fSmrgextern DevPrivateKey UnusedClassesPrivateKey;
1014642e01fSmrg
10205b261ecSmrg
10305b261ecSmrgvoid
10405b261ecSmrgRegisterOtherDevice(DeviceIntPtr device)
10505b261ecSmrg{
10605b261ecSmrg    device->public.processInputProc = ProcessOtherEvent;
10705b261ecSmrg    device->public.realInputProc = ProcessOtherEvent;
10805b261ecSmrg}
10905b261ecSmrg
1104642e01fSmrgBool
1114642e01fSmrgIsPointerEvent(xEvent* xE)
1124642e01fSmrg{
1134642e01fSmrg    switch(xE->u.u.type)
1144642e01fSmrg    {
1154642e01fSmrg        case ButtonPress:
1164642e01fSmrg        case ButtonRelease:
1174642e01fSmrg        case MotionNotify:
1184642e01fSmrg        case EnterNotify:
1194642e01fSmrg        case LeaveNotify:
1204642e01fSmrg            return TRUE;
1214642e01fSmrg        default:
1224642e01fSmrg            if (xE->u.u.type == DeviceButtonPress ||
1234642e01fSmrg                xE->u.u.type == DeviceButtonRelease ||
1244642e01fSmrg                xE->u.u.type == DeviceMotionNotify ||
1254642e01fSmrg                xE->u.u.type == ProximityIn ||
1264642e01fSmrg                xE->u.u.type == ProximityOut)
1274642e01fSmrg            {
1284642e01fSmrg                return TRUE;
1294642e01fSmrg            }
1304642e01fSmrg    }
1314642e01fSmrg    return FALSE;
1324642e01fSmrg}
1334642e01fSmrg
1344642e01fSmrg/**
1354642e01fSmrg * @return the device matching the deviceid of the device set in the event, or
1364642e01fSmrg * NULL if the event is not an XInput event.
1374642e01fSmrg */
1384642e01fSmrgDeviceIntPtr
1394642e01fSmrgXIGetDevice(xEvent* xE)
14005b261ecSmrg{
1414642e01fSmrg    DeviceIntPtr pDev = NULL;
1424642e01fSmrg
1434642e01fSmrg    if (xE->u.u.type == DeviceButtonPress ||
1444642e01fSmrg        xE->u.u.type == DeviceButtonRelease ||
1454642e01fSmrg        xE->u.u.type == DeviceMotionNotify ||
1464642e01fSmrg        xE->u.u.type == ProximityIn ||
1474642e01fSmrg        xE->u.u.type == ProximityOut ||
1484642e01fSmrg        xE->u.u.type == DevicePropertyNotify)
1494642e01fSmrg    {
1504642e01fSmrg        int rc;
1514642e01fSmrg        int id;
1524642e01fSmrg
1534642e01fSmrg        id = ((deviceKeyButtonPointer*)xE)->deviceid & ~MORE_EVENTS;
1544642e01fSmrg
1554642e01fSmrg        rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
1564642e01fSmrg        if (rc != Success)
1574642e01fSmrg            ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
1584642e01fSmrg    }
1594642e01fSmrg    return pDev;
1604642e01fSmrg}
1614642e01fSmrg
1624642e01fSmrg
1634642e01fSmrg/**
1644642e01fSmrg * Copy the device->key into master->key and send a mapping notify to the
1654642e01fSmrg * clients if appropriate.
1664642e01fSmrg * master->key needs to be allocated by the caller.
1674642e01fSmrg *
1684642e01fSmrg * Device is the slave device. If it is attached to a master device, we may
1694642e01fSmrg * need to send a mapping notify to the client because it causes the MD
1704642e01fSmrg * to change state.
1714642e01fSmrg *
1724642e01fSmrg * Mapping notify needs to be sent in the following cases:
1734642e01fSmrg *      - different slave device on same master
1744642e01fSmrg *      - different master
1754642e01fSmrg *
1764642e01fSmrg * XXX: They way how the code is we also send a map notify if the slave device
1774642e01fSmrg * stays the same, but the master changes. This isn't really necessary though.
1784642e01fSmrg *
1794642e01fSmrg * XXX: this gives you funny behaviour with the ClientPointer. When a
1804642e01fSmrg * MappingNotify is sent to the client, the client usually responds with a
1814642e01fSmrg * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
1824642e01fSmrg * mapping, regardless of which keyboard sent the last mapping notify request.
1834642e01fSmrg * So depending on the CP setting, your keyboard may change layout in each
1844642e01fSmrg * app...
1854642e01fSmrg *
1864642e01fSmrg * This code is basically the old SwitchCoreKeyboard.
1874642e01fSmrg */
1884642e01fSmrg
1894642e01fSmrgvoid
1904642e01fSmrgCopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
1914642e01fSmrg{
1924642e01fSmrg    static DeviceIntPtr lastMapNotifyDevice = NULL;
1934642e01fSmrg    KeyClassPtr mk, dk; /* master, device */
1944642e01fSmrg    BOOL sendNotify = FALSE;
19505b261ecSmrg    int i;
1964642e01fSmrg
1974642e01fSmrg    if (device == master)
1984642e01fSmrg        return;
1994642e01fSmrg
2004642e01fSmrg    dk = device->key;
2014642e01fSmrg    mk = master->key;
2024642e01fSmrg
2034642e01fSmrg    if (device != dixLookupPrivate(&master->devPrivates,
2044642e01fSmrg                                   CoreDevicePrivateKey)) {
2054642e01fSmrg        memcpy(mk->modifierMap, dk->modifierMap, MAP_LENGTH);
2064642e01fSmrg
2074642e01fSmrg        if (dk->maxKeysPerModifier)
2084642e01fSmrg        {
2094642e01fSmrg            mk->modifierKeyMap = xrealloc(mk->modifierKeyMap,
2104642e01fSmrg                                          8 * dk->maxKeysPerModifier);
2114642e01fSmrg            if (!mk->modifierKeyMap)
2124642e01fSmrg                FatalError("[Xi] no memory for class shift.\n");
2134642e01fSmrg            memcpy(mk->modifierKeyMap, dk->modifierKeyMap,
2144642e01fSmrg                    (8 * dk->maxKeysPerModifier));
2154642e01fSmrg        } else
2164642e01fSmrg        {
2174642e01fSmrg            xfree(mk->modifierKeyMap);
2184642e01fSmrg            mk->modifierKeyMap = NULL;
21905b261ecSmrg        }
22005b261ecSmrg
2214642e01fSmrg        mk->maxKeysPerModifier = dk->maxKeysPerModifier;
2224642e01fSmrg        mk->curKeySyms.minKeyCode = dk->curKeySyms.minKeyCode;
2234642e01fSmrg        mk->curKeySyms.maxKeyCode = dk->curKeySyms.maxKeyCode;
2244642e01fSmrg        SetKeySymsMap(&mk->curKeySyms, &dk->curKeySyms);
2254642e01fSmrg
2264642e01fSmrg        /*
2274642e01fSmrg         * Copy state from the extended keyboard to core.  If you omit this,
2284642e01fSmrg         * holding Ctrl on keyboard one, and pressing Q on keyboard two, will
2294642e01fSmrg         * cause your app to quit.  This feels wrong to me, hence the below
2304642e01fSmrg         * code.
2314642e01fSmrg         *
2324642e01fSmrg         * XXX: If you synthesise core modifier events, the state will get
2334642e01fSmrg         *      clobbered here.  You'll have to work out something sensible
2344642e01fSmrg         *      to fix that.  Good luck.
2354642e01fSmrg         */
2364642e01fSmrg
2374642e01fSmrg#define KEYBOARD_MASK (ShiftMask | LockMask | ControlMask | Mod1Mask | \
2384642e01fSmrg        Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)
2394642e01fSmrg        mk->state &= ~(KEYBOARD_MASK);
2404642e01fSmrg        mk->state |= (dk->state & KEYBOARD_MASK);
2414642e01fSmrg#undef KEYBOARD_MASK
2424642e01fSmrg        for (i = 0; i < 8; i++)
2434642e01fSmrg            mk->modifierKeyCount[i] = dk->modifierKeyCount[i];
2444642e01fSmrg
2454642e01fSmrg#ifdef XKB
2464642e01fSmrg        if (!noXkbExtension && dk->xkbInfo && dk->xkbInfo->desc) {
2474642e01fSmrg            if (!mk->xkbInfo || !mk->xkbInfo->desc)
2484642e01fSmrg            {
2494642e01fSmrg                XkbInitDevice(master);
2504642e01fSmrg                XkbFinishDeviceInit(master);
2514642e01fSmrg            }
2524642e01fSmrg            if (!XkbCopyKeymap(dk->xkbInfo->desc, mk->xkbInfo->desc, True))
2534642e01fSmrg                FatalError("Couldn't pivot keymap from device to core!\n");
2544642e01fSmrg        }
2554642e01fSmrg#endif
2564642e01fSmrg
2574642e01fSmrg        dixSetPrivate(&master->devPrivates, CoreDevicePrivateKey, device);
2584642e01fSmrg        sendNotify = TRUE;
2594642e01fSmrg    } else if (lastMapNotifyDevice != master)
2604642e01fSmrg        sendNotify = TRUE;
2614642e01fSmrg
2624642e01fSmrg    if (sendNotify)
2634642e01fSmrg    {
2644642e01fSmrg        SendMappingNotify(master, MappingKeyboard,
2654642e01fSmrg                           mk->curKeySyms.minKeyCode,
2664642e01fSmrg                          (mk->curKeySyms.maxKeyCode -
2674642e01fSmrg                           mk->curKeySyms.minKeyCode),
2684642e01fSmrg                          serverClient);
2694642e01fSmrg        lastMapNotifyDevice = master;
27005b261ecSmrg    }
2714642e01fSmrg}
27205b261ecSmrg
2734642e01fSmrg/**
2744642e01fSmrg * Copies the feedback classes from device "from" into device "to". Classes
2754642e01fSmrg * are duplicated (not just flipping the pointers). All feedback classes are
2764642e01fSmrg * linked lists, the full list is duplicated.
2774642e01fSmrg */
2784642e01fSmrgstatic void
2794642e01fSmrgDeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
2804642e01fSmrg{
2814642e01fSmrg    ClassesPtr classes;
2824642e01fSmrg
2834642e01fSmrg    if (from->kbdfeed)
2844642e01fSmrg    {
2854642e01fSmrg        KbdFeedbackPtr *k, it;
2864642e01fSmrg
2874642e01fSmrg        if (!to->kbdfeed)
2884642e01fSmrg        {
2894642e01fSmrg            classes = dixLookupPrivate(&to->devPrivates,
2904642e01fSmrg                                       UnusedClassesPrivateKey);
2914642e01fSmrg            to->kbdfeed = classes->kbdfeed;
2924642e01fSmrg        }
2934642e01fSmrg
2944642e01fSmrg        k = &to->kbdfeed;
2954642e01fSmrg        for(it = from->kbdfeed; it; it = it->next)
2964642e01fSmrg        {
2974642e01fSmrg            if (!(*k))
2984642e01fSmrg            {
2994642e01fSmrg                *k = xcalloc(1, sizeof(KbdFeedbackClassRec));
3004642e01fSmrg                if (!*k)
3014642e01fSmrg                {
3024642e01fSmrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
3034642e01fSmrg                    return;
3044642e01fSmrg                }
3054642e01fSmrg            }
3064642e01fSmrg            (*k)->BellProc = it->BellProc;
3074642e01fSmrg            (*k)->CtrlProc = it->CtrlProc;
3084642e01fSmrg            (*k)->ctrl     = it->ctrl;
3094642e01fSmrg#ifdef XKB
3104642e01fSmrg            if ((*k)->xkb_sli)
3114642e01fSmrg                XkbFreeSrvLedInfo((*k)->xkb_sli);
3124642e01fSmrg            (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
3134642e01fSmrg#endif
3144642e01fSmrg
3154642e01fSmrg            k = &(*k)->next;
3164642e01fSmrg        }
3174642e01fSmrg    } else if (to->kbdfeed && !from->kbdfeed)
3184642e01fSmrg    {
3194642e01fSmrg        ClassesPtr classes;
3204642e01fSmrg        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
3214642e01fSmrg        classes->kbdfeed = to->kbdfeed;
3224642e01fSmrg        to->kbdfeed      = NULL;
3234642e01fSmrg    }
3244642e01fSmrg
3254642e01fSmrg    if (from->ptrfeed)
3264642e01fSmrg    {
3274642e01fSmrg        PtrFeedbackPtr *p, it;
3284642e01fSmrg        if (!to->ptrfeed)
3294642e01fSmrg        {
3304642e01fSmrg            classes = dixLookupPrivate(&to->devPrivates,
3314642e01fSmrg                                       UnusedClassesPrivateKey);
3324642e01fSmrg            to->ptrfeed = classes->ptrfeed;
3334642e01fSmrg        }
3344642e01fSmrg
3354642e01fSmrg        p = &to->ptrfeed;
3364642e01fSmrg        for (it = from->ptrfeed; it; it = it->next)
3374642e01fSmrg        {
3384642e01fSmrg            if (!(*p))
3394642e01fSmrg            {
3404642e01fSmrg                *p = xcalloc(1, sizeof(PtrFeedbackClassRec));
3414642e01fSmrg                if (!*p)
3424642e01fSmrg                {
3434642e01fSmrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
3444642e01fSmrg                    return;
3454642e01fSmrg                }
3464642e01fSmrg            }
3474642e01fSmrg            (*p)->CtrlProc = it->CtrlProc;
3484642e01fSmrg            (*p)->ctrl     = it->ctrl;
3494642e01fSmrg
3504642e01fSmrg            p = &(*p)->next;
3514642e01fSmrg        }
3524642e01fSmrg    } else if (to->ptrfeed && !from->ptrfeed)
3534642e01fSmrg    {
3544642e01fSmrg        ClassesPtr classes;
3554642e01fSmrg        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
3564642e01fSmrg        classes->ptrfeed = to->ptrfeed;
3574642e01fSmrg        to->ptrfeed      = NULL;
35805b261ecSmrg    }
3594642e01fSmrg
3604642e01fSmrg    if (from->intfeed)
3614642e01fSmrg    {
3624642e01fSmrg        IntegerFeedbackPtr *i, it;
3634642e01fSmrg
3644642e01fSmrg        if (!to->intfeed)
3654642e01fSmrg        {
3664642e01fSmrg            classes = dixLookupPrivate(&to->devPrivates,
3674642e01fSmrg                                       UnusedClassesPrivateKey);
3684642e01fSmrg            to->intfeed = classes->intfeed;
3694642e01fSmrg        }
3704642e01fSmrg
3714642e01fSmrg        i = &to->intfeed;
3724642e01fSmrg        for (it = from->intfeed; it; it = it->next)
3734642e01fSmrg        {
3744642e01fSmrg            if (!(*i))
3754642e01fSmrg            {
3764642e01fSmrg                *i = xcalloc(1, sizeof(IntegerFeedbackClassRec));
3774642e01fSmrg                if (!(*i))
3784642e01fSmrg                {
3794642e01fSmrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
3804642e01fSmrg                    return;
3814642e01fSmrg                }
3824642e01fSmrg            }
3834642e01fSmrg            (*i)->CtrlProc = it->CtrlProc;
3844642e01fSmrg            (*i)->ctrl     = it->ctrl;
3854642e01fSmrg
3864642e01fSmrg            i = &(*i)->next;
3874642e01fSmrg        }
3884642e01fSmrg    } else if (to->intfeed && !from->intfeed)
3894642e01fSmrg    {
3904642e01fSmrg        ClassesPtr classes;
3914642e01fSmrg        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
3924642e01fSmrg        classes->intfeed = to->intfeed;
3934642e01fSmrg        to->intfeed      = NULL;
3944642e01fSmrg    }
3954642e01fSmrg
3964642e01fSmrg    if (from->stringfeed)
3974642e01fSmrg    {
3984642e01fSmrg        StringFeedbackPtr *s, it;
3994642e01fSmrg
4004642e01fSmrg        if (!to->stringfeed)
4014642e01fSmrg        {
4024642e01fSmrg            classes = dixLookupPrivate(&to->devPrivates,
4034642e01fSmrg                                       UnusedClassesPrivateKey);
4044642e01fSmrg            to->stringfeed = classes->stringfeed;
4054642e01fSmrg        }
4064642e01fSmrg
4074642e01fSmrg        s = &to->stringfeed;
4084642e01fSmrg        for (it = from->stringfeed; it; it = it->next)
4094642e01fSmrg        {
4104642e01fSmrg            if (!(*s))
4114642e01fSmrg            {
4124642e01fSmrg                *s = xcalloc(1, sizeof(StringFeedbackClassRec));
4134642e01fSmrg                if (!(*s))
4144642e01fSmrg                {
4154642e01fSmrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
4164642e01fSmrg                    return;
4174642e01fSmrg                }
4184642e01fSmrg            }
4194642e01fSmrg            (*s)->CtrlProc = it->CtrlProc;
4204642e01fSmrg            (*s)->ctrl     = it->ctrl;
4214642e01fSmrg
4224642e01fSmrg            s = &(*s)->next;
4234642e01fSmrg        }
4244642e01fSmrg    } else if (to->stringfeed && !from->stringfeed)
4254642e01fSmrg    {
4264642e01fSmrg        ClassesPtr classes;
4274642e01fSmrg        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
4284642e01fSmrg        classes->stringfeed = to->stringfeed;
4294642e01fSmrg        to->stringfeed      = NULL;
4304642e01fSmrg    }
4314642e01fSmrg
4324642e01fSmrg    if (from->bell)
4334642e01fSmrg    {
4344642e01fSmrg        BellFeedbackPtr *b, it;
4354642e01fSmrg
4364642e01fSmrg        if (!to->bell)
4374642e01fSmrg        {
4384642e01fSmrg            classes = dixLookupPrivate(&to->devPrivates,
4394642e01fSmrg                                       UnusedClassesPrivateKey);
4404642e01fSmrg            to->bell = classes->bell;
4414642e01fSmrg        }
4424642e01fSmrg
4434642e01fSmrg        b = &to->bell;
4444642e01fSmrg        for (it = from->bell; it; it = it->next)
4454642e01fSmrg        {
4464642e01fSmrg            if (!(*b))
4474642e01fSmrg            {
4484642e01fSmrg                *b = xcalloc(1, sizeof(BellFeedbackClassRec));
4494642e01fSmrg                if (!(*b))
4504642e01fSmrg                {
4514642e01fSmrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
4524642e01fSmrg                    return;
4534642e01fSmrg                }
4544642e01fSmrg            }
4554642e01fSmrg            (*b)->BellProc = it->BellProc;
4564642e01fSmrg            (*b)->CtrlProc = it->CtrlProc;
4574642e01fSmrg            (*b)->ctrl     = it->ctrl;
4584642e01fSmrg
4594642e01fSmrg            b = &(*b)->next;
4604642e01fSmrg        }
4614642e01fSmrg    } else if (to->bell && !from->bell)
4624642e01fSmrg    {
4634642e01fSmrg        ClassesPtr classes;
4644642e01fSmrg        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
4654642e01fSmrg        classes->bell = to->bell;
4664642e01fSmrg        to->bell      = NULL;
4674642e01fSmrg    }
4684642e01fSmrg
4694642e01fSmrg    if (from->leds)
4704642e01fSmrg    {
4714642e01fSmrg        LedFeedbackPtr *l, it;
4724642e01fSmrg
4734642e01fSmrg        if (!to->leds)
4744642e01fSmrg        {
4754642e01fSmrg            classes = dixLookupPrivate(&to->devPrivates,
4764642e01fSmrg                                       UnusedClassesPrivateKey);
4774642e01fSmrg            to->leds = classes->leds;
4784642e01fSmrg        }
4794642e01fSmrg
4804642e01fSmrg        l = &to->leds;
4814642e01fSmrg        for (it = from->leds; it; it = it->next)
4824642e01fSmrg        {
4834642e01fSmrg            if (!(*l))
4844642e01fSmrg            {
4854642e01fSmrg                *l = xcalloc(1, sizeof(LedFeedbackClassRec));
4864642e01fSmrg                if (!(*l))
4874642e01fSmrg                {
4884642e01fSmrg                    ErrorF("[Xi] Cannot alloc memory for class copy.");
4894642e01fSmrg                    return;
4904642e01fSmrg                }
4914642e01fSmrg            }
4924642e01fSmrg            (*l)->CtrlProc = it->CtrlProc;
4934642e01fSmrg            (*l)->ctrl     = it->ctrl;
4944642e01fSmrg#ifdef XKB
4954642e01fSmrg            if ((*l)->xkb_sli)
4964642e01fSmrg                XkbFreeSrvLedInfo((*l)->xkb_sli);
4974642e01fSmrg            (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
4984642e01fSmrg#endif
4994642e01fSmrg
5004642e01fSmrg            l = &(*l)->next;
5014642e01fSmrg        }
5024642e01fSmrg    } else if (to->leds && !from->leds)
5034642e01fSmrg    {
5044642e01fSmrg        ClassesPtr classes;
5054642e01fSmrg        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
5064642e01fSmrg        classes->leds = to->leds;
5074642e01fSmrg        to->leds      = NULL;
5084642e01fSmrg    }
5094642e01fSmrg}
5104642e01fSmrg
5114642e01fSmrg/**
5124642e01fSmrg * Copies the CONTENT of the classes of device from into the classes in device
5134642e01fSmrg * to. From and to are identical after finishing.
5144642e01fSmrg *
5154642e01fSmrg * If to does not have classes from currenly has, the classes are stored in
5164642e01fSmrg * to's devPrivates system. Later, we recover it again from there if needed.
5174642e01fSmrg * Saves a few memory allocations.
5184642e01fSmrg */
5194642e01fSmrg
5204642e01fSmrgvoid
5214642e01fSmrgDeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
5224642e01fSmrg{
5234642e01fSmrg    ClassesPtr classes;
5244642e01fSmrg
5254642e01fSmrg    /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
5264642e01fSmrg     * kbdfeed to be set up properly, so let's do the feedback classes first.
5274642e01fSmrg     */
5284642e01fSmrg    DeepCopyFeedbackClasses(from, to);
5294642e01fSmrg
5304642e01fSmrg    if (from->key)
5314642e01fSmrg    {
5324642e01fSmrg        KeyCode             *oldModKeyMap;
5334642e01fSmrg        KeySym              *oldMap;
5344642e01fSmrg#ifdef XKB
5354642e01fSmrg        struct _XkbSrvInfo  *oldXkbInfo;
5364642e01fSmrg#endif
5374642e01fSmrg        if (!to->key)
5384642e01fSmrg        {
5394642e01fSmrg            classes = dixLookupPrivate(&to->devPrivates,
5404642e01fSmrg                                       UnusedClassesPrivateKey);
5414642e01fSmrg            to->key = classes->key;
5424642e01fSmrg            if (!to->key)
5434642e01fSmrg            {
5444642e01fSmrg                to->key = xcalloc(1, sizeof(KeyClassRec));
5454642e01fSmrg                if (!to->key)
5464642e01fSmrg                    FatalError("[Xi] no memory for class shift.\n");
5474642e01fSmrg            } else
5484642e01fSmrg                classes->key = NULL;
5494642e01fSmrg        }
5504642e01fSmrg
5514642e01fSmrg        oldModKeyMap    = to->key->modifierKeyMap;
5524642e01fSmrg        oldMap          = to->key->curKeySyms.map;
5534642e01fSmrg#ifdef XKB
5544642e01fSmrg        oldXkbInfo      = to->key->xkbInfo;
5554642e01fSmrg#endif
5564642e01fSmrg
5574642e01fSmrg        if (!oldMap) /* newly created key struct */
5584642e01fSmrg        {
5594642e01fSmrg            int bytes = (to->key->curKeySyms.maxKeyCode -
5604642e01fSmrg                         to->key->curKeySyms.minKeyCode + 1) *
5614642e01fSmrg                         to->key->curKeySyms.mapWidth;
5624642e01fSmrg            oldMap = (KeySym *)xcalloc(sizeof(KeySym), bytes);
5634642e01fSmrg            memcpy(oldMap, from->key->curKeySyms.map, bytes);
5644642e01fSmrg        }
5654642e01fSmrg
5664642e01fSmrg        to->key->modifierKeyMap = oldModKeyMap;
5674642e01fSmrg        to->key->curKeySyms.map = oldMap;
5684642e01fSmrg#ifdef XKB
5694642e01fSmrg        to->key->xkbInfo        = oldXkbInfo;
5704642e01fSmrg#endif
5714642e01fSmrg
5724642e01fSmrg        CopyKeyClass(from, to);
5734642e01fSmrg    } else if (to->key && !from->key)
5744642e01fSmrg    {
5754642e01fSmrg        ClassesPtr classes;
5764642e01fSmrg        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
5774642e01fSmrg        classes->key = to->key;
5784642e01fSmrg        to->key      = NULL;
5794642e01fSmrg    }
5804642e01fSmrg
5814642e01fSmrg    if (from->valuator)
5824642e01fSmrg    {
5834642e01fSmrg        ValuatorClassPtr v;
5844642e01fSmrg        if (!to->valuator)
5854642e01fSmrg        {
5864642e01fSmrg            classes = dixLookupPrivate(&to->devPrivates,
5874642e01fSmrg                                       UnusedClassesPrivateKey);
5884642e01fSmrg            to->valuator = classes->valuator;
5894642e01fSmrg            if (to->valuator)
5904642e01fSmrg                classes->valuator = NULL;
5914642e01fSmrg        }
5924642e01fSmrg
5934642e01fSmrg        to->valuator = xrealloc(to->valuator, sizeof(ValuatorClassRec) +
5944642e01fSmrg                from->valuator->numAxes * sizeof(AxisInfo) +
5954642e01fSmrg                from->valuator->numAxes * sizeof(unsigned int));
5964642e01fSmrg        v = to->valuator;
5974642e01fSmrg        if (!v)
5984642e01fSmrg            FatalError("[Xi] no memory for class shift.\n");
5994642e01fSmrg
6004642e01fSmrg        v->numAxes = from->valuator->numAxes;
6014642e01fSmrg        v->axes = (AxisInfoPtr)&v[1];
6024642e01fSmrg        memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
6034642e01fSmrg
6044642e01fSmrg        v->axisVal = (int*)(v->axes + from->valuator->numAxes);
6054642e01fSmrg    } else if (to->valuator && !from->valuator)
6064642e01fSmrg    {
6074642e01fSmrg        ClassesPtr classes;
6084642e01fSmrg        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
6094642e01fSmrg        classes->valuator = to->valuator;
6104642e01fSmrg        to->valuator      = NULL;
6114642e01fSmrg    }
6124642e01fSmrg
6134642e01fSmrg    if (from->button)
6144642e01fSmrg    {
6154642e01fSmrg        if (!to->button)
6164642e01fSmrg        {
6174642e01fSmrg            classes = dixLookupPrivate(&to->devPrivates,
6184642e01fSmrg                                       UnusedClassesPrivateKey);
6194642e01fSmrg            to->button = classes->button;
6204642e01fSmrg            if (!to->button)
6214642e01fSmrg            {
6224642e01fSmrg                to->button = xcalloc(1, sizeof(ButtonClassRec));
6234642e01fSmrg                if (!to->button)
6244642e01fSmrg                    FatalError("[Xi] no memory for class shift.\n");
6254642e01fSmrg            } else
6264642e01fSmrg                classes->button = NULL;
6274642e01fSmrg        }
6284642e01fSmrg
6294642e01fSmrg#ifdef XKB
6304642e01fSmrg        if (from->button->xkb_acts)
6314642e01fSmrg        {
6324642e01fSmrg            if (!to->button->xkb_acts)
6334642e01fSmrg            {
6344642e01fSmrg                to->button->xkb_acts = xcalloc(1, sizeof(XkbAction));
6354642e01fSmrg                if (!to->button->xkb_acts)
6364642e01fSmrg                    FatalError("[Xi] not enough memory for xkb_acts.\n");
6374642e01fSmrg            }
6384642e01fSmrg            memcpy(to->button->xkb_acts, from->button->xkb_acts,
6394642e01fSmrg                    sizeof(XkbAction));
6404642e01fSmrg        } else
6414642e01fSmrg            xfree(to->button->xkb_acts);
6424642e01fSmrg#endif
6434642e01fSmrg    } else if (to->button && !from->button)
6444642e01fSmrg    {
6454642e01fSmrg        ClassesPtr classes;
6464642e01fSmrg        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
6474642e01fSmrg        classes->button = to->button;
6484642e01fSmrg        to->button      = NULL;
6494642e01fSmrg    }
6504642e01fSmrg
6514642e01fSmrg
6524642e01fSmrg    /* We can't just copy over the focus class. When an app sets the focus,
6534642e01fSmrg     * it'll do so on the master device. Copying the SDs focus means losing
6544642e01fSmrg     * the focus.
6554642e01fSmrg     * So we only copy the focus class if the device didn't have one,
6564642e01fSmrg     * otherwise we leave it as it is.
6574642e01fSmrg     */
6584642e01fSmrg    if (from->focus)
6594642e01fSmrg    {
6604642e01fSmrg        if (!to->focus)
6614642e01fSmrg        {
6624642e01fSmrg            WindowPtr *oldTrace;
6634642e01fSmrg
6644642e01fSmrg            classes = dixLookupPrivate(&to->devPrivates,
6654642e01fSmrg                                       UnusedClassesPrivateKey);
6664642e01fSmrg            to->focus = classes->focus;
6674642e01fSmrg            if (!to->focus)
6684642e01fSmrg            {
6694642e01fSmrg                to->focus = xcalloc(1, sizeof(FocusClassRec));
6704642e01fSmrg                if (!to->focus)
6714642e01fSmrg                    FatalError("[Xi] no memory for class shift.\n");
6724642e01fSmrg            } else
6734642e01fSmrg                classes->focus = NULL;
6744642e01fSmrg
6754642e01fSmrg            oldTrace = to->focus->trace;
6764642e01fSmrg            memcpy(to->focus, from->focus, sizeof(FocusClassRec));
6774642e01fSmrg            to->focus->trace = xrealloc(oldTrace,
6784642e01fSmrg                                  to->focus->traceSize * sizeof(WindowPtr));
6794642e01fSmrg            if (!to->focus->trace && to->focus->traceSize)
6804642e01fSmrg                FatalError("[Xi] no memory for trace.\n");
6814642e01fSmrg            memcpy(to->focus->trace, from->focus->trace,
6824642e01fSmrg                    from->focus->traceSize * sizeof(WindowPtr));
6834642e01fSmrg        }
6844642e01fSmrg    } else if (to->focus)
6854642e01fSmrg    {
6864642e01fSmrg        ClassesPtr classes;
6874642e01fSmrg        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
6884642e01fSmrg        classes->focus = to->focus;
6894642e01fSmrg        to->focus      = NULL;
6904642e01fSmrg    }
6914642e01fSmrg
6924642e01fSmrg    if (from->proximity)
6934642e01fSmrg    {
6944642e01fSmrg        if (!to->proximity)
6954642e01fSmrg        {
6964642e01fSmrg            classes = dixLookupPrivate(&to->devPrivates,
6974642e01fSmrg                                       UnusedClassesPrivateKey);
6984642e01fSmrg            to->proximity = classes->proximity;
6994642e01fSmrg            if (!to->proximity)
7004642e01fSmrg            {
7014642e01fSmrg                to->proximity = xcalloc(1, sizeof(ProximityClassRec));
7024642e01fSmrg                if (!to->proximity)
7034642e01fSmrg                    FatalError("[Xi] no memory for class shift.\n");
7044642e01fSmrg            } else
7054642e01fSmrg                classes->proximity = NULL;
7064642e01fSmrg        }
7074642e01fSmrg        memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
7084642e01fSmrg    } else if (to->proximity)
7094642e01fSmrg    {
7104642e01fSmrg        ClassesPtr classes;
7114642e01fSmrg        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
7124642e01fSmrg        classes->proximity = to->proximity;
7134642e01fSmrg        to->proximity      = NULL;
7144642e01fSmrg    }
7154642e01fSmrg
7164642e01fSmrg    if (from->absolute)
7174642e01fSmrg    {
7184642e01fSmrg        if (!to->absolute)
7194642e01fSmrg        {
7204642e01fSmrg            classes = dixLookupPrivate(&to->devPrivates,
7214642e01fSmrg                                       UnusedClassesPrivateKey);
7224642e01fSmrg            to->absolute = classes->absolute;
7234642e01fSmrg            if (!to->absolute)
7244642e01fSmrg            {
7254642e01fSmrg                to->absolute = xcalloc(1, sizeof(AbsoluteClassRec));
7264642e01fSmrg                if (!to->absolute)
7274642e01fSmrg                    FatalError("[Xi] no memory for class shift.\n");
7284642e01fSmrg            } else
7294642e01fSmrg                classes->absolute = NULL;
7304642e01fSmrg        }
7314642e01fSmrg        memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec));
7324642e01fSmrg    } else if (to->absolute)
7334642e01fSmrg    {
7344642e01fSmrg        ClassesPtr classes;
7354642e01fSmrg        classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
7364642e01fSmrg        classes->absolute = to->absolute;
7374642e01fSmrg        to->absolute      = NULL;
7384642e01fSmrg    }
7394642e01fSmrg}
7404642e01fSmrg
7414642e01fSmrg
7424642e01fSmrg/**
7434642e01fSmrg * Update the device state according to the data in the event.
7444642e01fSmrg *
7454642e01fSmrg * return values are
7464642e01fSmrg *   DEFAULT ... process as normal
7474642e01fSmrg *   DONT_PROCESS ... return immediately from caller
7484642e01fSmrg *   IS_REPEAT .. event is a repeat event.
7494642e01fSmrg */
7504642e01fSmrg#define DEFAULT 0
7514642e01fSmrg#define DONT_PROCESS 1
7524642e01fSmrg#define IS_REPEAT 2
7534642e01fSmrgint
7544642e01fSmrgUpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count)
7554642e01fSmrg{
7564642e01fSmrg    int i;
7574642e01fSmrg    int key = 0,
7584642e01fSmrg        bit = 0;
7594642e01fSmrg
7604642e01fSmrg    KeyClassPtr k       = NULL;
7614642e01fSmrg    ButtonClassPtr b    = NULL;
7624642e01fSmrg    ValuatorClassPtr v  = NULL;
7634642e01fSmrg    deviceValuator *xV  = (deviceValuator *) xE;
7644642e01fSmrg    BYTE *kptr          = NULL;
7654642e01fSmrg    CARD16 modifiers    = 0,
7664642e01fSmrg           mask         = 0;
7674642e01fSmrg
7684642e01fSmrg    /* currently no other generic event modifies the device */
7694642e01fSmrg    if (xE->u.u.type == GenericEvent)
7704642e01fSmrg        return DEFAULT;
7714642e01fSmrg
7724642e01fSmrg    k = device->key;
7734642e01fSmrg    v = device->valuator;
7744642e01fSmrg    b = device->button;
7754642e01fSmrg
7764642e01fSmrg
7774642e01fSmrg    if (xE->u.u.type != DeviceValuator)
7784642e01fSmrg    {
7794642e01fSmrg        key = xE->u.u.detail;
7804642e01fSmrg        bit = 1 << (key & 7);
7814642e01fSmrg    }
7824642e01fSmrg
7834642e01fSmrg    /* Update device axis */
7844642e01fSmrg    /* Don't update valuators for the VCP, it never sends XI events anyway */
7854642e01fSmrg    for (i = 1; !device->isMaster && i < count; i++) {
78605b261ecSmrg	if ((++xV)->type == DeviceValuator) {
78705b261ecSmrg	    int *axisvals;
7884642e01fSmrg            int first = xV->first_valuator;
7894642e01fSmrg            BOOL change = FALSE;
79005b261ecSmrg
7914642e01fSmrg
7924642e01fSmrg	    if (xV->num_valuators &&
7934642e01fSmrg                (!v || (xV->num_valuators &&
7944642e01fSmrg                      (first + xV->num_valuators > v->numAxes))))
79505b261ecSmrg		FatalError("Bad valuators reported for device %s\n",
7964642e01fSmrg			   device->name);
79705b261ecSmrg	    if (v && v->axisVal) {
7984642e01fSmrg                /* v->axisVal is always in absolute coordinates. Only the
7994642e01fSmrg                 * delivery mode changes.
8004642e01fSmrg                 * If device is mode Absolute
8014642e01fSmrg                 *     dev = event
8024642e01fSmrg                 * If device is mode Relative
8034642e01fSmrg                 *      swap = (event - device)
8044642e01fSmrg                 *      dev = event
8054642e01fSmrg                 *      event = delta
8064642e01fSmrg                 */
8074642e01fSmrg                int delta;
8084642e01fSmrg                axisvals = v->axisVal;
8094642e01fSmrg                if (v->mode == Relative) /* device reports relative */
8104642e01fSmrg                    change = TRUE;
8114642e01fSmrg
8124642e01fSmrg                switch (xV->num_valuators) {
8134642e01fSmrg                    case 6:
8144642e01fSmrg                        if (change) delta = xV->valuator5 - *(axisvals + first + 5);
8154642e01fSmrg                        *(axisvals + first + 5) = xV->valuator5;
8164642e01fSmrg                        if (change) xV->valuator5 = delta;
8174642e01fSmrg                    case 5:
8184642e01fSmrg                        if (change) delta = xV->valuator4 - *(axisvals + first + 4);
8194642e01fSmrg                        *(axisvals + first + 4) = xV->valuator4;
8204642e01fSmrg                        if (change) xV->valuator4 = delta;
8214642e01fSmrg                    case 4:
8224642e01fSmrg                        if (change) delta = xV->valuator3 - *(axisvals + first + 3);
8234642e01fSmrg                        *(axisvals + first + 3) = xV->valuator3;
8244642e01fSmrg                        if (change) xV->valuator3 = delta;
8254642e01fSmrg                    case 3:
8264642e01fSmrg                        if (change) delta = xV->valuator2 - *(axisvals + first + 2);
8274642e01fSmrg                        *(axisvals + first + 2) = xV->valuator2;
8284642e01fSmrg                        if (change) xV->valuator2 = delta;
8294642e01fSmrg                    case 2:
8304642e01fSmrg                        if (change) delta = xV->valuator1 - *(axisvals + first + 1);
8314642e01fSmrg                        *(axisvals + first + 1) = xV->valuator1;
8324642e01fSmrg                        if (change) xV->valuator1 = delta;
8334642e01fSmrg                    case 1:
8344642e01fSmrg                        if (change) delta = xV->valuator0 - *(axisvals + first);
8354642e01fSmrg                        *(axisvals + first) = xV->valuator0;
8364642e01fSmrg                        if (change) xV->valuator0 = delta;
8374642e01fSmrg                    case 0:
8384642e01fSmrg                    default:
8394642e01fSmrg                        break;
8404642e01fSmrg                }
84105b261ecSmrg	    }
84205b261ecSmrg	}
8434642e01fSmrg    }
84405b261ecSmrg
84505b261ecSmrg    if (xE->u.u.type == DeviceKeyPress) {
84605b261ecSmrg        if (!k)
8474642e01fSmrg            return DONT_PROCESS;
84805b261ecSmrg
84905b261ecSmrg	modifiers = k->modifierMap[key];
85005b261ecSmrg	kptr = &k->down[key >> 3];
85105b261ecSmrg	if (*kptr & bit) {	/* allow ddx to generate multiple downs */
8524642e01fSmrg	    return IS_REPEAT;
85305b261ecSmrg	}
8544642e01fSmrg	if (device->valuator)
8554642e01fSmrg	    device->valuator->motionHintWindow = NullWindow;
85605b261ecSmrg	*kptr |= bit;
85705b261ecSmrg	k->prev_state = k->state;
85805b261ecSmrg	for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
85905b261ecSmrg	    if (mask & modifiers) {
86005b261ecSmrg		/* This key affects modifier "i" */
86105b261ecSmrg		k->modifierKeyCount[i]++;
86205b261ecSmrg		k->state |= mask;
86305b261ecSmrg		modifiers &= ~mask;
86405b261ecSmrg	    }
86505b261ecSmrg	}
86605b261ecSmrg    } else if (xE->u.u.type == DeviceKeyRelease) {
86705b261ecSmrg        if (!k)
8684642e01fSmrg            return DONT_PROCESS;
86905b261ecSmrg
87005b261ecSmrg	kptr = &k->down[key >> 3];
87105b261ecSmrg	if (!(*kptr & bit))	/* guard against duplicates */
8724642e01fSmrg	    return DONT_PROCESS;
87305b261ecSmrg	modifiers = k->modifierMap[key];
8744642e01fSmrg	if (device->valuator)
8754642e01fSmrg	    device->valuator->motionHintWindow = NullWindow;
87605b261ecSmrg	*kptr &= ~bit;
87705b261ecSmrg	k->prev_state = k->state;
87805b261ecSmrg	for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
87905b261ecSmrg	    if (mask & modifiers) {
88005b261ecSmrg		/* This key affects modifier "i" */
88105b261ecSmrg		if (--k->modifierKeyCount[i] <= 0) {
88205b261ecSmrg		    k->modifierKeyCount[i] = 0;
88305b261ecSmrg		    k->state &= ~mask;
88405b261ecSmrg		}
88505b261ecSmrg		modifiers &= ~mask;
88605b261ecSmrg	    }
88705b261ecSmrg	}
88805b261ecSmrg    } else if (xE->u.u.type == DeviceButtonPress) {
88905b261ecSmrg        if (!b)
8904642e01fSmrg            return DONT_PROCESS;
8914642e01fSmrg
8924642e01fSmrg        kptr = &b->down[key >> 3];
8934642e01fSmrg        if ((*kptr & bit) != 0)
8944642e01fSmrg            return DONT_PROCESS;
8954642e01fSmrg        *kptr |= bit;
8964642e01fSmrg	if (device->valuator)
8974642e01fSmrg	    device->valuator->motionHintWindow = NullWindow;
8984642e01fSmrg        if (!b->map[key])
8994642e01fSmrg            return DONT_PROCESS;
9004642e01fSmrg        b->buttonsDown++;
90105b261ecSmrg	b->motionMask = DeviceButtonMotionMask;
9024642e01fSmrg        if (b->map[key] <= 5)
9034642e01fSmrg	    b->state |= (Button1Mask >> 1) << b->map[key];
9044642e01fSmrg	SetMaskForEvent(device->id, Motion_Filter(b), DeviceMotionNotify);
90505b261ecSmrg    } else if (xE->u.u.type == DeviceButtonRelease) {
90605b261ecSmrg        if (!b)
9074642e01fSmrg            return DONT_PROCESS;
9084642e01fSmrg
9094642e01fSmrg        kptr = &b->down[key>>3];
9104642e01fSmrg        if (!(*kptr & bit))
9114642e01fSmrg            return DONT_PROCESS;
9124642e01fSmrg        if (device->isMaster) {
9134642e01fSmrg            DeviceIntPtr sd;
9144642e01fSmrg
9154642e01fSmrg            /*
9164642e01fSmrg             * Leave the button down if any slave has the
9174642e01fSmrg             * button still down. Note that this depends on the
9184642e01fSmrg             * event being delivered through the slave first
9194642e01fSmrg             */
9204642e01fSmrg            for (sd = inputInfo.devices; sd; sd = sd->next) {
9214642e01fSmrg                if (sd->isMaster || sd->u.master != device)
9224642e01fSmrg                    continue;
9234642e01fSmrg                if ((sd->button->down[key>>3] & bit) != 0)
9244642e01fSmrg                    return DONT_PROCESS;
9254642e01fSmrg            }
9264642e01fSmrg        }
9274642e01fSmrg        *kptr &= ~bit;
9284642e01fSmrg	if (device->valuator)
9294642e01fSmrg	    device->valuator->motionHintWindow = NullWindow;
9304642e01fSmrg        if (!b->map[key])
9314642e01fSmrg            return DONT_PROCESS;
93205b261ecSmrg        if (b->buttonsDown >= 1 && !--b->buttonsDown)
93305b261ecSmrg	    b->motionMask = 0;
9344642e01fSmrg	if (b->map[key] <= 5)
9354642e01fSmrg	    b->state &= ~((Button1Mask >> 1) << b->map[key]);
9364642e01fSmrg	SetMaskForEvent(device->id, Motion_Filter(b), DeviceMotionNotify);
93705b261ecSmrg    } else if (xE->u.u.type == ProximityIn)
9384642e01fSmrg	device->valuator->mode &= ~OutOfProximity;
93905b261ecSmrg    else if (xE->u.u.type == ProximityOut)
9404642e01fSmrg	device->valuator->mode |= OutOfProximity;
9414642e01fSmrg
9424642e01fSmrg    return DEFAULT;
9434642e01fSmrg}
9444642e01fSmrg
9454642e01fSmrg/**
9464642e01fSmrg * Main device event processing function.
9474642e01fSmrg * Called from when processing the events from the event queue.
9484642e01fSmrg *
9494642e01fSmrg */
9504642e01fSmrgvoid
9514642e01fSmrgProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
9524642e01fSmrg{
9534642e01fSmrg    int i;
9544642e01fSmrg    CARD16 modifiers;
9554642e01fSmrg    GrabPtr grab = device->deviceGrab.grab;
9564642e01fSmrg    Bool deactivateDeviceGrab = FALSE;
9574642e01fSmrg    int key = 0, rootX, rootY;
9584642e01fSmrg    ButtonClassPtr b;
9594642e01fSmrg    KeyClassPtr k;
9604642e01fSmrg    ValuatorClassPtr v;
9614642e01fSmrg    deviceValuator *xV  = (deviceValuator *) xE;
9624642e01fSmrg    int ret = 0;
9634642e01fSmrg    int state;
9644642e01fSmrg    DeviceIntPtr mouse = NULL, kbd = NULL;
9654642e01fSmrg
9664642e01fSmrg    if (IsPointerDevice(device))
9674642e01fSmrg    {
9684642e01fSmrg        kbd = GetPairedDevice(device);
9694642e01fSmrg        mouse = device;
9704642e01fSmrg        if (!kbd->key) /* can happen with floating SDs */
9714642e01fSmrg            kbd = NULL;
9724642e01fSmrg    } else
9734642e01fSmrg    {
9744642e01fSmrg        mouse = GetPairedDevice(device);
9754642e01fSmrg        kbd = device;
9764642e01fSmrg        if (!mouse->valuator || !mouse->button) /* may be float. SDs */
9774642e01fSmrg            mouse = NULL;
9784642e01fSmrg    }
9794642e01fSmrg
9804642e01fSmrg    /* State needs to be assembled BEFORE the device is updated. */
9814642e01fSmrg    state = (kbd) ? kbd->key->state : 0;
9824642e01fSmrg    state |= (mouse) ? (mouse->button->state) : 0;
9834642e01fSmrg
9844642e01fSmrg    ret = UpdateDeviceState(device, xE, count);
9854642e01fSmrg    if (ret == DONT_PROCESS)
9864642e01fSmrg        return;
9874642e01fSmrg
9884642e01fSmrg    v = device->valuator;
9894642e01fSmrg    b = device->button;
9904642e01fSmrg    k = device->key;
9914642e01fSmrg
9924642e01fSmrg    if (device->isMaster)
9934642e01fSmrg        CheckMotion(xE, device);
9944642e01fSmrg
9954642e01fSmrg    if (xE->u.u.type != DeviceValuator && xE->u.u.type != GenericEvent) {
9964642e01fSmrg	GetSpritePosition(device, &rootX, &rootY);
9974642e01fSmrg	xE->u.keyButtonPointer.rootX = rootX;
9984642e01fSmrg	xE->u.keyButtonPointer.rootY = rootY;
9994642e01fSmrg	NoticeEventTime(xE);
10004642e01fSmrg
10014642e01fSmrg        xE->u.keyButtonPointer.state = state;
10024642e01fSmrg
10034642e01fSmrg        key = xE->u.u.detail;
10044642e01fSmrg    }
10054642e01fSmrg    if (DeviceEventCallback) {
10064642e01fSmrg	DeviceEventInfoRec eventinfo;
10074642e01fSmrg
10084642e01fSmrg	eventinfo.events = (xEventPtr) xE;
10094642e01fSmrg	eventinfo.count = count;
10104642e01fSmrg	CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
10114642e01fSmrg    }
10124642e01fSmrg
10134642e01fSmrg    /* Valuator event handling */
10144642e01fSmrg    /* Don't care about valuators for the VCP, it never sends XI events */
10154642e01fSmrg
10164642e01fSmrg    for (i = 1; !device->isMaster && i < count; i++) {
10174642e01fSmrg	if ((++xV)->type == DeviceValuator) {
10184642e01fSmrg	    int first = xV->first_valuator;
10194642e01fSmrg	    if (xV->num_valuators
10204642e01fSmrg		&& (!v
10214642e01fSmrg		    || (xV->num_valuators
10224642e01fSmrg			&& (first + xV->num_valuators > v->numAxes))))
10234642e01fSmrg		FatalError("Bad valuators reported for device %s\n",
10244642e01fSmrg			   device->name);
10254642e01fSmrg	    xV->device_state = 0;
10264642e01fSmrg	    if (k)
10274642e01fSmrg		xV->device_state |= k->state;
10284642e01fSmrg	    if (b)
10294642e01fSmrg		xV->device_state |= b->state;
10304642e01fSmrg	}
10314642e01fSmrg    }
10324642e01fSmrg
10334642e01fSmrg    if (xE->u.u.type == DeviceKeyPress) {
10344642e01fSmrg        if (ret == IS_REPEAT) {	/* allow ddx to generate multiple downs */
10354642e01fSmrg            modifiers = k->modifierMap[key];
10364642e01fSmrg	    if (!modifiers) {
10374642e01fSmrg		xE->u.u.type = DeviceKeyRelease;
10384642e01fSmrg		ProcessOtherEvent(xE, device, count);
10394642e01fSmrg		xE->u.u.type = DeviceKeyPress;
10404642e01fSmrg		/* release can have side effects, don't fall through */
10414642e01fSmrg		ProcessOtherEvent(xE, device, count);
10424642e01fSmrg	    }
10434642e01fSmrg	    return;
10444642e01fSmrg	}
10454642e01fSmrg	if (!grab && CheckDeviceGrabs(device, xE, 0, count)) {
10464642e01fSmrg	    device->deviceGrab.activatingKey = key;
10474642e01fSmrg	    return;
10484642e01fSmrg	}
10494642e01fSmrg    } else if (xE->u.u.type == DeviceKeyRelease) {
10504642e01fSmrg	if (device->deviceGrab.fromPassiveGrab &&
10514642e01fSmrg            (key == device->deviceGrab.activatingKey))
10524642e01fSmrg	    deactivateDeviceGrab = TRUE;
10534642e01fSmrg    } else if (xE->u.u.type == DeviceButtonPress) {
10544642e01fSmrg	xE->u.u.detail = b->map[key];
10554642e01fSmrg	if (xE->u.u.detail == 0) {
10564642e01fSmrg	    xE->u.u.detail = key;
10574642e01fSmrg	    return;
10584642e01fSmrg	}
10594642e01fSmrg        if (!grab && CheckDeviceGrabs(device, xE, 0, count))
10604642e01fSmrg        {
10614642e01fSmrg            /* if a passive grab was activated, the event has been sent
10624642e01fSmrg             * already */
10634642e01fSmrg            return;
10644642e01fSmrg        }
10654642e01fSmrg
10664642e01fSmrg    } else if (xE->u.u.type == DeviceButtonRelease) {
10674642e01fSmrg	xE->u.u.detail = b->map[key];
10684642e01fSmrg	if (xE->u.u.detail == 0) {
10694642e01fSmrg	    xE->u.u.detail = key;
10704642e01fSmrg	    return;
10714642e01fSmrg	}
10724642e01fSmrg        if (!b->buttonsDown && device->deviceGrab.fromPassiveGrab)
10734642e01fSmrg            deactivateDeviceGrab = TRUE;
10744642e01fSmrg    }
107505b261ecSmrg
107605b261ecSmrg    if (grab)
10774642e01fSmrg        DeliverGrabbedEvent(xE, device, deactivateDeviceGrab, count);
10784642e01fSmrg    else if (device->focus && !IsPointerEvent(xE))
10794642e01fSmrg	DeliverFocusedEvent(device, xE, GetSpriteWindow(device), count);
108005b261ecSmrg    else
10814642e01fSmrg	DeliverDeviceEvents(GetSpriteWindow(device), xE, NullGrab, NullWindow,
10824642e01fSmrg			    device, count);
108305b261ecSmrg
108405b261ecSmrg    if (deactivateDeviceGrab == TRUE)
10854642e01fSmrg	(*device->deviceGrab.DeactivateGrab) (device);
10864642e01fSmrg    xE->u.u.detail = key;
108705b261ecSmrg}
108805b261ecSmrg
108905b261ecSmrg_X_EXPORT int
109005b261ecSmrgInitProximityClassDeviceStruct(DeviceIntPtr dev)
109105b261ecSmrg{
109205b261ecSmrg    ProximityClassPtr proxc;
109305b261ecSmrg
109405b261ecSmrg    proxc = (ProximityClassPtr) xalloc(sizeof(ProximityClassRec));
109505b261ecSmrg    if (!proxc)
109605b261ecSmrg	return FALSE;
109705b261ecSmrg    dev->proximity = proxc;
109805b261ecSmrg    return TRUE;
109905b261ecSmrg}
110005b261ecSmrg
11014642e01fSmrg/**
11024642e01fSmrg * Initialise the device's valuators. The memory must already be allocated,
11034642e01fSmrg * this function merely inits the matching axis (specified through axnum) to
11044642e01fSmrg * sane values.
11054642e01fSmrg *
11064642e01fSmrg * It is a condition that (minval < maxval).
11074642e01fSmrg *
11084642e01fSmrg * @see InitValuatorClassDeviceStruct
11094642e01fSmrg */
111005b261ecSmrg_X_EXPORT void
111105b261ecSmrgInitValuatorAxisStruct(DeviceIntPtr dev, int axnum, int minval, int maxval,
111205b261ecSmrg		       int resolution, int min_res, int max_res)
111305b261ecSmrg{
111405b261ecSmrg    AxisInfoPtr ax;
11154642e01fSmrg
11164642e01fSmrg    if (!dev || !dev->valuator || minval > maxval)
111705b261ecSmrg        return;
111805b261ecSmrg
111905b261ecSmrg    ax = dev->valuator->axes + axnum;
112005b261ecSmrg
112105b261ecSmrg    ax->min_value = minval;
112205b261ecSmrg    ax->max_value = maxval;
112305b261ecSmrg    ax->resolution = resolution;
112405b261ecSmrg    ax->min_resolution = min_res;
112505b261ecSmrg    ax->max_resolution = max_res;
112605b261ecSmrg}
112705b261ecSmrg
112805b261ecSmrgstatic void
112905b261ecSmrgFixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
113005b261ecSmrg		     ButtonClassPtr b, ValuatorClassPtr v, int first)
113105b261ecSmrg{
113205b261ecSmrg    ev->type = DeviceStateNotify;
113305b261ecSmrg    ev->deviceid = dev->id;
113405b261ecSmrg    ev->time = currentTime.milliseconds;
113505b261ecSmrg    ev->classes_reported = 0;
113605b261ecSmrg    ev->num_keys = 0;
113705b261ecSmrg    ev->num_buttons = 0;
113805b261ecSmrg    ev->num_valuators = 0;
113905b261ecSmrg
114005b261ecSmrg    if (b) {
114105b261ecSmrg	ev->classes_reported |= (1 << ButtonClass);
114205b261ecSmrg	ev->num_buttons = b->numButtons;
11434642e01fSmrg	memcpy((char*)ev->buttons, (char*)b->down, 4);
114405b261ecSmrg    } else if (k) {
114505b261ecSmrg	ev->classes_reported |= (1 << KeyClass);
114605b261ecSmrg	ev->num_keys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode;
114705b261ecSmrg	memmove((char *)&ev->keys[0], (char *)k->down, 4);
114805b261ecSmrg    }
114905b261ecSmrg    if (v) {
115005b261ecSmrg	int nval = v->numAxes - first;
115105b261ecSmrg
115205b261ecSmrg	ev->classes_reported |= (1 << ValuatorClass);
115305b261ecSmrg	ev->classes_reported |= (dev->valuator->mode << ModeBitsShift);
115405b261ecSmrg	ev->num_valuators = nval < 3 ? nval : 3;
115505b261ecSmrg	switch (ev->num_valuators) {
115605b261ecSmrg	case 3:
115705b261ecSmrg	    ev->valuator2 = v->axisVal[first + 2];
115805b261ecSmrg	case 2:
115905b261ecSmrg	    ev->valuator1 = v->axisVal[first + 1];
116005b261ecSmrg	case 1:
116105b261ecSmrg	    ev->valuator0 = v->axisVal[first];
116205b261ecSmrg	    break;
116305b261ecSmrg	}
116405b261ecSmrg    }
116505b261ecSmrg}
116605b261ecSmrg
116705b261ecSmrgstatic void
116805b261ecSmrgFixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
116905b261ecSmrg		  int first)
117005b261ecSmrg{
117105b261ecSmrg    int nval = v->numAxes - first;
117205b261ecSmrg
117305b261ecSmrg    ev->type = DeviceValuator;
117405b261ecSmrg    ev->deviceid = dev->id;
117505b261ecSmrg    ev->num_valuators = nval < 3 ? nval : 3;
117605b261ecSmrg    ev->first_valuator = first;
117705b261ecSmrg    switch (ev->num_valuators) {
117805b261ecSmrg    case 3:
117905b261ecSmrg	ev->valuator2 = v->axisVal[first + 2];
118005b261ecSmrg    case 2:
118105b261ecSmrg	ev->valuator1 = v->axisVal[first + 1];
118205b261ecSmrg    case 1:
118305b261ecSmrg	ev->valuator0 = v->axisVal[first];
118405b261ecSmrg	break;
118505b261ecSmrg    }
118605b261ecSmrg    first += ev->num_valuators;
118705b261ecSmrg}
118805b261ecSmrg
118905b261ecSmrgvoid
119005b261ecSmrgDeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
119105b261ecSmrg		 WindowPtr pWin)
119205b261ecSmrg{
119305b261ecSmrg    deviceFocus event;
119405b261ecSmrg
119505b261ecSmrg    if (type == FocusIn)
119605b261ecSmrg	type = DeviceFocusIn;
119705b261ecSmrg    else
119805b261ecSmrg	type = DeviceFocusOut;
119905b261ecSmrg
120005b261ecSmrg    event.deviceid = dev->id;
120105b261ecSmrg    event.mode = mode;
120205b261ecSmrg    event.type = type;
120305b261ecSmrg    event.detail = detail;
120405b261ecSmrg    event.window = pWin->drawable.id;
120505b261ecSmrg    event.time = currentTime.milliseconds;
120605b261ecSmrg
12074642e01fSmrg    (void)DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
120805b261ecSmrg				DeviceFocusChangeMask, NullGrab, dev->id);
120905b261ecSmrg
121005b261ecSmrg    if ((type == DeviceFocusIn) &&
121105b261ecSmrg	(wOtherInputMasks(pWin)) &&
121205b261ecSmrg	(wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
121305b261ecSmrg    {
121405b261ecSmrg	int evcount = 1;
121505b261ecSmrg	deviceStateNotify *ev, *sev;
121605b261ecSmrg	deviceKeyStateNotify *kev;
121705b261ecSmrg	deviceButtonStateNotify *bev;
121805b261ecSmrg
121905b261ecSmrg	KeyClassPtr k;
122005b261ecSmrg	ButtonClassPtr b;
122105b261ecSmrg	ValuatorClassPtr v;
122205b261ecSmrg	int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
122305b261ecSmrg
122405b261ecSmrg	if ((b = dev->button) != NULL) {
122505b261ecSmrg	    nbuttons = b->numButtons;
122605b261ecSmrg	    if (nbuttons > 32)
122705b261ecSmrg		evcount++;
122805b261ecSmrg	}
122905b261ecSmrg	if ((k = dev->key) != NULL) {
123005b261ecSmrg	    nkeys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode;
123105b261ecSmrg	    if (nkeys > 32)
123205b261ecSmrg		evcount++;
123305b261ecSmrg	    if (nbuttons > 0) {
123405b261ecSmrg		evcount++;
123505b261ecSmrg	    }
123605b261ecSmrg	}
123705b261ecSmrg	if ((v = dev->valuator) != NULL) {
123805b261ecSmrg	    nval = v->numAxes;
123905b261ecSmrg
124005b261ecSmrg	    if (nval > 3)
124105b261ecSmrg		evcount++;
124205b261ecSmrg	    if (nval > 6) {
124305b261ecSmrg		if (!(k && b))
124405b261ecSmrg		    evcount++;
124505b261ecSmrg		if (nval > 9)
124605b261ecSmrg		    evcount += ((nval - 7) / 3);
124705b261ecSmrg	    }
124805b261ecSmrg	}
124905b261ecSmrg
125005b261ecSmrg	sev = ev = (deviceStateNotify *) xalloc(evcount * sizeof(xEvent));
125105b261ecSmrg	FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
125205b261ecSmrg
125305b261ecSmrg	if (b != NULL) {
125405b261ecSmrg	    FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
125505b261ecSmrg	    first += 3;
125605b261ecSmrg	    nval -= 3;
125705b261ecSmrg	    if (nbuttons > 32) {
125805b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
125905b261ecSmrg		bev = (deviceButtonStateNotify *) ev++;
126005b261ecSmrg		bev->type = DeviceButtonStateNotify;
126105b261ecSmrg		bev->deviceid = dev->id;
12624642e01fSmrg		memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
126305b261ecSmrg	    }
126405b261ecSmrg	    if (nval > 0) {
126505b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
126605b261ecSmrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
126705b261ecSmrg		first += 3;
126805b261ecSmrg		nval -= 3;
126905b261ecSmrg	    }
127005b261ecSmrg	}
127105b261ecSmrg
127205b261ecSmrg	if (k != NULL) {
127305b261ecSmrg	    FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
127405b261ecSmrg	    first += 3;
127505b261ecSmrg	    nval -= 3;
127605b261ecSmrg	    if (nkeys > 32) {
127705b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
127805b261ecSmrg		kev = (deviceKeyStateNotify *) ev++;
127905b261ecSmrg		kev->type = DeviceKeyStateNotify;
128005b261ecSmrg		kev->deviceid = dev->id;
128105b261ecSmrg		memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
128205b261ecSmrg	    }
128305b261ecSmrg	    if (nval > 0) {
128405b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
128505b261ecSmrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
128605b261ecSmrg		first += 3;
128705b261ecSmrg		nval -= 3;
128805b261ecSmrg	    }
128905b261ecSmrg	}
129005b261ecSmrg
129105b261ecSmrg	while (nval > 0) {
129205b261ecSmrg	    FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
129305b261ecSmrg	    first += 3;
129405b261ecSmrg	    nval -= 3;
129505b261ecSmrg	    if (nval > 0) {
129605b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
129705b261ecSmrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
129805b261ecSmrg		first += 3;
129905b261ecSmrg		nval -= 3;
130005b261ecSmrg	    }
130105b261ecSmrg	}
130205b261ecSmrg
13034642e01fSmrg	(void)DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
130405b261ecSmrg				    DeviceStateNotifyMask, NullGrab, dev->id);
130505b261ecSmrg	xfree(sev);
130605b261ecSmrg    }
130705b261ecSmrg}
130805b261ecSmrg
130905b261ecSmrgint
131005b261ecSmrgGrabButton(ClientPtr client, DeviceIntPtr dev, BYTE this_device_mode,
131105b261ecSmrg	   BYTE other_devices_mode, CARD16 modifiers,
131205b261ecSmrg	   DeviceIntPtr modifier_device, CARD8 button, Window grabWindow,
131305b261ecSmrg	   BOOL ownerEvents, Cursor rcursor, Window rconfineTo, Mask eventMask)
131405b261ecSmrg{
131505b261ecSmrg    WindowPtr pWin, confineTo;
131605b261ecSmrg    CursorPtr cursor;
131705b261ecSmrg    GrabPtr grab;
13184642e01fSmrg    Mask access_mode = DixGrabAccess;
131905b261ecSmrg    int rc;
132005b261ecSmrg
132105b261ecSmrg    if ((this_device_mode != GrabModeSync) &&
132205b261ecSmrg	(this_device_mode != GrabModeAsync)) {
132305b261ecSmrg	client->errorValue = this_device_mode;
132405b261ecSmrg	return BadValue;
132505b261ecSmrg    }
132605b261ecSmrg    if ((other_devices_mode != GrabModeSync) &&
132705b261ecSmrg	(other_devices_mode != GrabModeAsync)) {
132805b261ecSmrg	client->errorValue = other_devices_mode;
132905b261ecSmrg	return BadValue;
133005b261ecSmrg    }
133105b261ecSmrg    if ((modifiers != AnyModifier) && (modifiers & ~AllModifiersMask)) {
133205b261ecSmrg	client->errorValue = modifiers;
133305b261ecSmrg	return BadValue;
133405b261ecSmrg    }
133505b261ecSmrg    if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) {
133605b261ecSmrg	client->errorValue = ownerEvents;
133705b261ecSmrg	return BadValue;
133805b261ecSmrg    }
13394642e01fSmrg    rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
134005b261ecSmrg    if (rc != Success)
134105b261ecSmrg	return rc;
134205b261ecSmrg    if (rconfineTo == None)
134305b261ecSmrg	confineTo = NullWindow;
134405b261ecSmrg    else {
13454642e01fSmrg	rc = dixLookupWindow(&confineTo, rconfineTo, client, DixSetAttrAccess);
134605b261ecSmrg	if (rc != Success)
134705b261ecSmrg	    return rc;
134805b261ecSmrg    }
134905b261ecSmrg    if (rcursor == None)
135005b261ecSmrg	cursor = NullCursor;
135105b261ecSmrg    else {
13524642e01fSmrg	rc = dixLookupResource((pointer *)&cursor, rcursor, RT_CURSOR,
13534642e01fSmrg			       client, DixUseAccess);
13544642e01fSmrg	if (rc != Success)
13554642e01fSmrg	{
135605b261ecSmrg	    client->errorValue = rcursor;
13574642e01fSmrg	    return (rc == BadValue) ? BadCursor : rc;
135805b261ecSmrg	}
13594642e01fSmrg	access_mode |= DixForceAccess;
136005b261ecSmrg    }
13614642e01fSmrg    if (this_device_mode == GrabModeSync || other_devices_mode == GrabModeSync)
13624642e01fSmrg	access_mode |= DixFreezeAccess;
13634642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
13644642e01fSmrg    if (rc != Success)
13654642e01fSmrg	return rc;
136605b261ecSmrg
136705b261ecSmrg    grab = CreateGrab(client->index, dev, pWin, eventMask,
136805b261ecSmrg		      (Bool) ownerEvents, (Bool) this_device_mode,
136905b261ecSmrg		      (Bool) other_devices_mode, modifier_device, modifiers,
137005b261ecSmrg		      DeviceButtonPress, button, confineTo, cursor);
137105b261ecSmrg    if (!grab)
137205b261ecSmrg	return BadAlloc;
13734642e01fSmrg    return AddPassiveGrabToList(client, grab);
137405b261ecSmrg}
137505b261ecSmrg
137605b261ecSmrgint
137705b261ecSmrgGrabKey(ClientPtr client, DeviceIntPtr dev, BYTE this_device_mode,
137805b261ecSmrg	BYTE other_devices_mode, CARD16 modifiers,
137905b261ecSmrg	DeviceIntPtr modifier_device, CARD8 key, Window grabWindow,
138005b261ecSmrg	BOOL ownerEvents, Mask mask)
138105b261ecSmrg{
138205b261ecSmrg    WindowPtr pWin;
138305b261ecSmrg    GrabPtr grab;
138405b261ecSmrg    KeyClassPtr k = dev->key;
13854642e01fSmrg    Mask access_mode = DixGrabAccess;
138605b261ecSmrg    int rc;
138705b261ecSmrg
138805b261ecSmrg    if (k == NULL)
138905b261ecSmrg	return BadMatch;
139005b261ecSmrg    if ((other_devices_mode != GrabModeSync) &&
139105b261ecSmrg	(other_devices_mode != GrabModeAsync)) {
139205b261ecSmrg	client->errorValue = other_devices_mode;
139305b261ecSmrg	return BadValue;
139405b261ecSmrg    }
139505b261ecSmrg    if ((this_device_mode != GrabModeSync) &&
139605b261ecSmrg	(this_device_mode != GrabModeAsync)) {
139705b261ecSmrg	client->errorValue = this_device_mode;
139805b261ecSmrg	return BadValue;
139905b261ecSmrg    }
140005b261ecSmrg    if (((key > k->curKeySyms.maxKeyCode) || (key < k->curKeySyms.minKeyCode))
140105b261ecSmrg	&& (key != AnyKey)) {
140205b261ecSmrg	client->errorValue = key;
140305b261ecSmrg	return BadValue;
140405b261ecSmrg    }
140505b261ecSmrg    if ((modifiers != AnyModifier) && (modifiers & ~AllModifiersMask)) {
140605b261ecSmrg	client->errorValue = modifiers;
140705b261ecSmrg	return BadValue;
140805b261ecSmrg    }
140905b261ecSmrg    if ((ownerEvents != xTrue) && (ownerEvents != xFalse)) {
141005b261ecSmrg	client->errorValue = ownerEvents;
141105b261ecSmrg	return BadValue;
141205b261ecSmrg    }
14134642e01fSmrg    rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
14144642e01fSmrg    if (rc != Success)
14154642e01fSmrg	return rc;
14164642e01fSmrg    if (this_device_mode == GrabModeSync || other_devices_mode == GrabModeSync)
14174642e01fSmrg	access_mode |= DixFreezeAccess;
14184642e01fSmrg    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
141905b261ecSmrg    if (rc != Success)
142005b261ecSmrg	return rc;
142105b261ecSmrg
142205b261ecSmrg    grab = CreateGrab(client->index, dev, pWin,
142305b261ecSmrg		      mask, ownerEvents, this_device_mode, other_devices_mode,
142405b261ecSmrg		      modifier_device, modifiers, DeviceKeyPress, key,
142505b261ecSmrg		      NullWindow, NullCursor);
142605b261ecSmrg    if (!grab)
142705b261ecSmrg	return BadAlloc;
14284642e01fSmrg    return AddPassiveGrabToList(client, grab);
142905b261ecSmrg}
143005b261ecSmrg
143105b261ecSmrgint
143205b261ecSmrgSelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
143305b261ecSmrg		Mask mask, Mask exclusivemasks, Mask validmasks)
143405b261ecSmrg{
143505b261ecSmrg    int mskidx = dev->id;
143605b261ecSmrg    int i, ret;
143705b261ecSmrg    Mask check;
143805b261ecSmrg    InputClientsPtr others;
143905b261ecSmrg
144005b261ecSmrg    if (mask & ~validmasks) {
144105b261ecSmrg	client->errorValue = mask;
144205b261ecSmrg	return BadValue;
144305b261ecSmrg    }
144405b261ecSmrg    check = (mask & exclusivemasks);
144505b261ecSmrg    if (wOtherInputMasks(pWin)) {
144605b261ecSmrg	if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {	/* It is illegal for two different
144705b261ecSmrg									 * clients to select on any of the
144805b261ecSmrg									 * events for maskcheck. However,
144905b261ecSmrg									 * it is OK, for some client to
145005b261ecSmrg									 * continue selecting on one of those
145105b261ecSmrg									 * events.  */
145205b261ecSmrg	    for (others = wOtherInputMasks(pWin)->inputClients; others;
145305b261ecSmrg		 others = others->next) {
145405b261ecSmrg		if (!SameClient(others, client) && (check &
145505b261ecSmrg						    others->mask[mskidx]))
145605b261ecSmrg		    return BadAccess;
145705b261ecSmrg	    }
145805b261ecSmrg	}
145905b261ecSmrg	for (others = wOtherInputMasks(pWin)->inputClients; others;
146005b261ecSmrg	     others = others->next) {
146105b261ecSmrg	    if (SameClient(others, client)) {
146205b261ecSmrg		check = others->mask[mskidx];
146305b261ecSmrg		others->mask[mskidx] = mask;
146405b261ecSmrg		if (mask == 0) {
146505b261ecSmrg		    for (i = 0; i < EMASKSIZE; i++)
146605b261ecSmrg			if (i != mskidx && others->mask[i] != 0)
146705b261ecSmrg			    break;
146805b261ecSmrg		    if (i == EMASKSIZE) {
146905b261ecSmrg			RecalculateDeviceDeliverableEvents(pWin);
147005b261ecSmrg			if (ShouldFreeInputMasks(pWin, FALSE))
147105b261ecSmrg			    FreeResource(others->resource, RT_NONE);
147205b261ecSmrg			return Success;
147305b261ecSmrg		    }
147405b261ecSmrg		}
147505b261ecSmrg		goto maskSet;
147605b261ecSmrg	    }
147705b261ecSmrg	}
147805b261ecSmrg    }
147905b261ecSmrg    check = 0;
148005b261ecSmrg    if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
148105b261ecSmrg	return ret;
148205b261ecSmrg  maskSet:
148305b261ecSmrg    if (dev->valuator)
148405b261ecSmrg	if ((dev->valuator->motionHintWindow == pWin) &&
148505b261ecSmrg	    (mask & DevicePointerMotionHintMask) &&
14864642e01fSmrg	    !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
148705b261ecSmrg	    dev->valuator->motionHintWindow = NullWindow;
148805b261ecSmrg    RecalculateDeviceDeliverableEvents(pWin);
148905b261ecSmrg    return Success;
149005b261ecSmrg}
149105b261ecSmrg
149205b261ecSmrgint
149305b261ecSmrgAddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
149405b261ecSmrg{
149505b261ecSmrg    InputClientsPtr others;
149605b261ecSmrg
149705b261ecSmrg    if (!pWin->optional && !MakeWindowOptional(pWin))
149805b261ecSmrg	return BadAlloc;
14994642e01fSmrg    others = xcalloc(1, sizeof(InputClients));
150005b261ecSmrg    if (!others)
150105b261ecSmrg	return BadAlloc;
150205b261ecSmrg    if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
150305b261ecSmrg	return BadAlloc;
150405b261ecSmrg    others->mask[mskidx] = mask;
150505b261ecSmrg    others->resource = FakeClientID(client->index);
150605b261ecSmrg    others->next = pWin->optional->inputMasks->inputClients;
150705b261ecSmrg    pWin->optional->inputMasks->inputClients = others;
150805b261ecSmrg    if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
150905b261ecSmrg	return BadAlloc;
151005b261ecSmrg    return Success;
151105b261ecSmrg}
151205b261ecSmrg
151305b261ecSmrgstatic Bool
151405b261ecSmrgMakeInputMasks(WindowPtr pWin)
151505b261ecSmrg{
151605b261ecSmrg    struct _OtherInputMasks *imasks;
151705b261ecSmrg
15184642e01fSmrg    imasks = xcalloc(1, sizeof(struct _OtherInputMasks));
151905b261ecSmrg    if (!imasks)
152005b261ecSmrg	return FALSE;
152105b261ecSmrg    pWin->optional->inputMasks = imasks;
152205b261ecSmrg    return TRUE;
152305b261ecSmrg}
152405b261ecSmrg
152505b261ecSmrgvoid
152605b261ecSmrgRecalculateDeviceDeliverableEvents(WindowPtr pWin)
152705b261ecSmrg{
152805b261ecSmrg    InputClientsPtr others;
152905b261ecSmrg    struct _OtherInputMasks *inputMasks;	/* default: NULL */
153005b261ecSmrg    WindowPtr pChild, tmp;
153105b261ecSmrg    int i;
153205b261ecSmrg
153305b261ecSmrg    pChild = pWin;
153405b261ecSmrg    while (1) {
153505b261ecSmrg	if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
153605b261ecSmrg	    for (others = inputMasks->inputClients; others;
153705b261ecSmrg		 others = others->next) {
153805b261ecSmrg		for (i = 0; i < EMASKSIZE; i++)
153905b261ecSmrg		    inputMasks->inputEvents[i] |= others->mask[i];
154005b261ecSmrg	    }
154105b261ecSmrg	    for (i = 0; i < EMASKSIZE; i++)
154205b261ecSmrg		inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
154305b261ecSmrg	    for (tmp = pChild->parent; tmp; tmp = tmp->parent)
154405b261ecSmrg		if (wOtherInputMasks(tmp))
154505b261ecSmrg		    for (i = 0; i < EMASKSIZE; i++)
154605b261ecSmrg			inputMasks->deliverableEvents[i] |=
154705b261ecSmrg			    (wOtherInputMasks(tmp)->deliverableEvents[i]
154805b261ecSmrg			     & ~inputMasks->
154905b261ecSmrg			     dontPropagateMask[i] & PropagateMask[i]);
155005b261ecSmrg	}
155105b261ecSmrg	if (pChild->firstChild) {
155205b261ecSmrg	    pChild = pChild->firstChild;
155305b261ecSmrg	    continue;
155405b261ecSmrg	}
155505b261ecSmrg	while (!pChild->nextSib && (pChild != pWin))
155605b261ecSmrg	    pChild = pChild->parent;
155705b261ecSmrg	if (pChild == pWin)
155805b261ecSmrg	    break;
155905b261ecSmrg	pChild = pChild->nextSib;
156005b261ecSmrg    }
156105b261ecSmrg}
156205b261ecSmrg
156305b261ecSmrgint
156405b261ecSmrgInputClientGone(WindowPtr pWin, XID id)
156505b261ecSmrg{
156605b261ecSmrg    InputClientsPtr other, prev;
156705b261ecSmrg
156805b261ecSmrg    if (!wOtherInputMasks(pWin))
156905b261ecSmrg	return (Success);
157005b261ecSmrg    prev = 0;
157105b261ecSmrg    for (other = wOtherInputMasks(pWin)->inputClients; other;
157205b261ecSmrg	 other = other->next) {
157305b261ecSmrg	if (other->resource == id) {
157405b261ecSmrg	    if (prev) {
157505b261ecSmrg		prev->next = other->next;
157605b261ecSmrg		xfree(other);
157705b261ecSmrg	    } else if (!(other->next)) {
157805b261ecSmrg		if (ShouldFreeInputMasks(pWin, TRUE)) {
157905b261ecSmrg		    wOtherInputMasks(pWin)->inputClients = other->next;
158005b261ecSmrg		    xfree(wOtherInputMasks(pWin));
158105b261ecSmrg		    pWin->optional->inputMasks = (OtherInputMasks *) NULL;
158205b261ecSmrg		    CheckWindowOptionalNeed(pWin);
158305b261ecSmrg		    xfree(other);
158405b261ecSmrg		} else {
158505b261ecSmrg		    other->resource = FakeClientID(0);
158605b261ecSmrg		    if (!AddResource(other->resource, RT_INPUTCLIENT,
158705b261ecSmrg				     (pointer) pWin))
158805b261ecSmrg			return BadAlloc;
158905b261ecSmrg		}
159005b261ecSmrg	    } else {
159105b261ecSmrg		wOtherInputMasks(pWin)->inputClients = other->next;
159205b261ecSmrg		xfree(other);
159305b261ecSmrg	    }
159405b261ecSmrg	    RecalculateDeviceDeliverableEvents(pWin);
159505b261ecSmrg	    return (Success);
159605b261ecSmrg	}
159705b261ecSmrg	prev = other;
159805b261ecSmrg    }
159905b261ecSmrg    FatalError("client not on device event list");
160005b261ecSmrg}
160105b261ecSmrg
160205b261ecSmrgint
160305b261ecSmrgSendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
160405b261ecSmrg	  xEvent * ev, Mask mask, int count)
160505b261ecSmrg{
160605b261ecSmrg    WindowPtr pWin;
160705b261ecSmrg    WindowPtr effectiveFocus = NullWindow;	/* only set if dest==InputFocus */
16084642e01fSmrg    WindowPtr spriteWin = GetSpriteWindow(d);
160905b261ecSmrg
161005b261ecSmrg    if (dest == PointerWindow)
161105b261ecSmrg	pWin = spriteWin;
161205b261ecSmrg    else if (dest == InputFocus) {
161305b261ecSmrg	WindowPtr inputFocus;
161405b261ecSmrg
161505b261ecSmrg	if (!d->focus)
161605b261ecSmrg	    inputFocus = spriteWin;
161705b261ecSmrg	else
161805b261ecSmrg	    inputFocus = d->focus->win;
161905b261ecSmrg
162005b261ecSmrg	if (inputFocus == FollowKeyboardWin)
162105b261ecSmrg	    inputFocus = inputInfo.keyboard->focus->win;
162205b261ecSmrg
162305b261ecSmrg	if (inputFocus == NoneWin)
162405b261ecSmrg	    return Success;
162505b261ecSmrg
162605b261ecSmrg	/* If the input focus is PointerRootWin, send the event to where
162705b261ecSmrg	 * the pointer is if possible, then perhaps propogate up to root. */
162805b261ecSmrg	if (inputFocus == PointerRootWin)
16294642e01fSmrg	    inputFocus = GetCurrentRootWindow(d);
163005b261ecSmrg
163105b261ecSmrg	if (IsParent(inputFocus, spriteWin)) {
163205b261ecSmrg	    effectiveFocus = inputFocus;
163305b261ecSmrg	    pWin = spriteWin;
163405b261ecSmrg	} else
163505b261ecSmrg	    effectiveFocus = pWin = inputFocus;
163605b261ecSmrg    } else
16374642e01fSmrg	dixLookupWindow(&pWin, dest, client, DixSendAccess);
163805b261ecSmrg    if (!pWin)
163905b261ecSmrg	return BadWindow;
164005b261ecSmrg    if ((propagate != xFalse) && (propagate != xTrue)) {
164105b261ecSmrg	client->errorValue = propagate;
164205b261ecSmrg	return BadValue;
164305b261ecSmrg    }
164405b261ecSmrg    ev->u.u.type |= 0x80;
164505b261ecSmrg    if (propagate) {
164605b261ecSmrg	for (; pWin; pWin = pWin->parent) {
16474642e01fSmrg	    if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab, d->id))
164805b261ecSmrg		return Success;
164905b261ecSmrg	    if (pWin == effectiveFocus)
165005b261ecSmrg		return Success;
165105b261ecSmrg	    if (wOtherInputMasks(pWin))
165205b261ecSmrg		mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
165305b261ecSmrg	    if (!mask)
165405b261ecSmrg		break;
165505b261ecSmrg	}
16564642e01fSmrg    } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
16574642e01fSmrg	(void)(DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab, d->id));
165805b261ecSmrg    return Success;
165905b261ecSmrg}
166005b261ecSmrg
166105b261ecSmrgint
166205b261ecSmrgSetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
166305b261ecSmrg{
166405b261ecSmrg    int i;
166505b261ecSmrg    ButtonClassPtr b = dev->button;
166605b261ecSmrg
166705b261ecSmrg    if (b == NULL)
166805b261ecSmrg	return BadMatch;
166905b261ecSmrg
167005b261ecSmrg    if (nElts != b->numButtons) {
167105b261ecSmrg	client->errorValue = nElts;
167205b261ecSmrg	return BadValue;
167305b261ecSmrg    }
167405b261ecSmrg    if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
167505b261ecSmrg	return BadValue;
167605b261ecSmrg    for (i = 0; i < nElts; i++)
167705b261ecSmrg	if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
167805b261ecSmrg	    return MappingBusy;
167905b261ecSmrg    for (i = 0; i < nElts; i++)
168005b261ecSmrg	b->map[i + 1] = map[i];
168105b261ecSmrg    return Success;
168205b261ecSmrg}
168305b261ecSmrg
168405b261ecSmrgint
168505b261ecSmrgSetModifierMapping(ClientPtr client, DeviceIntPtr dev, int len, int rlen,
168605b261ecSmrg		   int numKeyPerModifier, KeyCode * inputMap, KeyClassPtr * k)
168705b261ecSmrg{
168805b261ecSmrg    KeyCode *map = NULL;
168905b261ecSmrg    int inputMapLen;
169005b261ecSmrg    int i;
169105b261ecSmrg
169205b261ecSmrg    *k = dev->key;
169305b261ecSmrg    if (*k == NULL)
169405b261ecSmrg	return BadMatch;
169505b261ecSmrg    if (len != ((numKeyPerModifier << 1) + rlen))
169605b261ecSmrg	return BadLength;
169705b261ecSmrg
169805b261ecSmrg    inputMapLen = 8 * numKeyPerModifier;
169905b261ecSmrg
170005b261ecSmrg    /*
170105b261ecSmrg     *  Now enforce the restriction that "all of the non-zero keycodes must be
170205b261ecSmrg     *  in the range specified by min-keycode and max-keycode in the
170305b261ecSmrg     *  connection setup (else a Value error)"
170405b261ecSmrg     */
170505b261ecSmrg    i = inputMapLen;
170605b261ecSmrg    while (i--) {
170705b261ecSmrg	if (inputMap[i]
170805b261ecSmrg	    && (inputMap[i] < (*k)->curKeySyms.minKeyCode
170905b261ecSmrg		|| inputMap[i] > (*k)->curKeySyms.maxKeyCode)) {
171005b261ecSmrg	    client->errorValue = inputMap[i];
171105b261ecSmrg	    return -1;	/* BadValue collides with MappingFailed */
171205b261ecSmrg	}
171305b261ecSmrg    }
171405b261ecSmrg
171505b261ecSmrg    /*
171605b261ecSmrg     *  Now enforce the restriction that none of the old or new
171705b261ecSmrg     *  modifier keys may be down while we change the mapping,  and
171805b261ecSmrg     *  that the DDX layer likes the choice.
171905b261ecSmrg     */
172005b261ecSmrg    if (!AllModifierKeysAreUp(dev, (*k)->modifierKeyMap,
172105b261ecSmrg			      (int)(*k)->maxKeysPerModifier, inputMap,
172205b261ecSmrg			      (int)numKeyPerModifier)
172305b261ecSmrg	|| !AllModifierKeysAreUp(dev, inputMap, (int)numKeyPerModifier,
172405b261ecSmrg				 (*k)->modifierKeyMap,
172505b261ecSmrg				 (int)(*k)->maxKeysPerModifier)) {
172605b261ecSmrg	return MappingBusy;
172705b261ecSmrg    } else {
172805b261ecSmrg	for (i = 0; i < inputMapLen; i++) {
172905b261ecSmrg	    if (inputMap[i] && !LegalModifier(inputMap[i], dev)) {
173005b261ecSmrg		return MappingFailed;
173105b261ecSmrg	    }
173205b261ecSmrg	}
173305b261ecSmrg    }
173405b261ecSmrg
173505b261ecSmrg    /*
173605b261ecSmrg     *  Now build the keyboard's modifier bitmap from the
173705b261ecSmrg     *  list of keycodes.
173805b261ecSmrg     */
173905b261ecSmrg    if (inputMapLen) {
174005b261ecSmrg	map = (KeyCode *) xalloc(inputMapLen);
174105b261ecSmrg	if (!map)
174205b261ecSmrg	    return BadAlloc;
174305b261ecSmrg    }
174405b261ecSmrg    if ((*k)->modifierKeyMap)
174505b261ecSmrg	xfree((*k)->modifierKeyMap);
174605b261ecSmrg    if (inputMapLen) {
174705b261ecSmrg	(*k)->modifierKeyMap = map;
174805b261ecSmrg	memmove((char *)(*k)->modifierKeyMap, (char *)inputMap, inputMapLen);
174905b261ecSmrg    } else
175005b261ecSmrg	(*k)->modifierKeyMap = NULL;
175105b261ecSmrg
175205b261ecSmrg    (*k)->maxKeysPerModifier = numKeyPerModifier;
175305b261ecSmrg    for (i = 0; i < MAP_LENGTH; i++)
175405b261ecSmrg	(*k)->modifierMap[i] = 0;
175505b261ecSmrg    for (i = 0; i < inputMapLen; i++)
175605b261ecSmrg	if (inputMap[i]) {
175705b261ecSmrg	    (*k)->modifierMap[inputMap[i]]
175805b261ecSmrg		|= (1 << (i / (*k)->maxKeysPerModifier));
175905b261ecSmrg	}
176005b261ecSmrg
176105b261ecSmrg    return (MappingSuccess);
176205b261ecSmrg}
176305b261ecSmrg
176405b261ecSmrgvoid
176505b261ecSmrgSendDeviceMappingNotify(ClientPtr client, CARD8 request,
176605b261ecSmrg			KeyCode firstKeyCode, CARD8 count, DeviceIntPtr dev)
176705b261ecSmrg{
176805b261ecSmrg    xEvent event;
176905b261ecSmrg    deviceMappingNotify *ev = (deviceMappingNotify *) & event;
177005b261ecSmrg
177105b261ecSmrg    ev->type = DeviceMappingNotify;
177205b261ecSmrg    ev->request = request;
177305b261ecSmrg    ev->deviceid = dev->id;
177405b261ecSmrg    ev->time = currentTime.milliseconds;
177505b261ecSmrg    if (request == MappingKeyboard) {
177605b261ecSmrg	ev->firstKeyCode = firstKeyCode;
177705b261ecSmrg	ev->count = count;
177805b261ecSmrg    }
177905b261ecSmrg
178005b261ecSmrg#ifdef XKB
17814642e01fSmrg    if (!noXkbExtension && (request == MappingKeyboard ||
17824642e01fSmrg                            request == MappingModifier))
178305b261ecSmrg        XkbApplyMappingChange(dev, request, firstKeyCode, count, client);
178405b261ecSmrg#endif
178505b261ecSmrg
178605b261ecSmrg    SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) ev, 1);
178705b261ecSmrg}
178805b261ecSmrg
178905b261ecSmrgint
179005b261ecSmrgChangeKeyMapping(ClientPtr client,
179105b261ecSmrg		 DeviceIntPtr dev,
179205b261ecSmrg		 unsigned len,
179305b261ecSmrg		 int type,
179405b261ecSmrg		 KeyCode firstKeyCode,
179505b261ecSmrg		 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
179605b261ecSmrg{
179705b261ecSmrg    KeySymsRec keysyms;
179805b261ecSmrg    KeyClassPtr k = dev->key;
179905b261ecSmrg
180005b261ecSmrg    if (k == NULL)
180105b261ecSmrg	return (BadMatch);
180205b261ecSmrg
180305b261ecSmrg    if (len != (keyCodes * keySymsPerKeyCode))
180405b261ecSmrg	return BadLength;
180505b261ecSmrg
180605b261ecSmrg    if ((firstKeyCode < k->curKeySyms.minKeyCode) ||
180705b261ecSmrg	(firstKeyCode + keyCodes - 1 > k->curKeySyms.maxKeyCode)) {
180805b261ecSmrg	client->errorValue = firstKeyCode;
180905b261ecSmrg	return BadValue;
181005b261ecSmrg    }
181105b261ecSmrg    if (keySymsPerKeyCode == 0) {
181205b261ecSmrg	client->errorValue = 0;
181305b261ecSmrg	return BadValue;
181405b261ecSmrg    }
181505b261ecSmrg    keysyms.minKeyCode = firstKeyCode;
181605b261ecSmrg    keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
181705b261ecSmrg    keysyms.mapWidth = keySymsPerKeyCode;
181805b261ecSmrg    keysyms.map = map;
181905b261ecSmrg    if (!SetKeySymsMap(&k->curKeySyms, &keysyms))
182005b261ecSmrg	return BadAlloc;
182105b261ecSmrg    SendDeviceMappingNotify(client, MappingKeyboard, firstKeyCode, keyCodes, dev);
182205b261ecSmrg    return client->noClientException;
182305b261ecSmrg}
182405b261ecSmrg
182505b261ecSmrgstatic void
182605b261ecSmrgDeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
182705b261ecSmrg{
182805b261ecSmrg    WindowPtr parent;
182905b261ecSmrg
183005b261ecSmrg    /* Deactivate any grabs performed on this window, before making
183105b261ecSmrg     * any input focus changes.
183205b261ecSmrg     * Deactivating a device grab should cause focus events. */
183305b261ecSmrg
18344642e01fSmrg    if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
18354642e01fSmrg	(*dev->deviceGrab.DeactivateGrab) (dev);
183605b261ecSmrg
18374642e01fSmrg    /* If the focus window is a root window (ie. has no parent)
183805b261ecSmrg     * then don't delete the focus from it. */
183905b261ecSmrg
184005b261ecSmrg    if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
184105b261ecSmrg	int focusEventMode = NotifyNormal;
184205b261ecSmrg
184305b261ecSmrg	/* If a grab is in progress, then alter the mode of focus events. */
184405b261ecSmrg
18454642e01fSmrg	if (dev->deviceGrab.grab)
184605b261ecSmrg	    focusEventMode = NotifyWhileGrabbed;
184705b261ecSmrg
184805b261ecSmrg	switch (dev->focus->revert) {
184905b261ecSmrg	case RevertToNone:
185005b261ecSmrg	    DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
185105b261ecSmrg	    dev->focus->win = NoneWin;
185205b261ecSmrg	    dev->focus->traceGood = 0;
185305b261ecSmrg	    break;
185405b261ecSmrg	case RevertToParent:
185505b261ecSmrg	    parent = pWin;
185605b261ecSmrg	    do {
185705b261ecSmrg		parent = parent->parent;
185805b261ecSmrg		dev->focus->traceGood--;
185905b261ecSmrg	    }
186005b261ecSmrg	    while (!parent->realized);
186105b261ecSmrg	    DoFocusEvents(dev, pWin, parent, focusEventMode);
186205b261ecSmrg	    dev->focus->win = parent;
186305b261ecSmrg	    dev->focus->revert = RevertToNone;
186405b261ecSmrg	    break;
186505b261ecSmrg	case RevertToPointerRoot:
186605b261ecSmrg	    DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
186705b261ecSmrg	    dev->focus->win = PointerRootWin;
186805b261ecSmrg	    dev->focus->traceGood = 0;
186905b261ecSmrg	    break;
187005b261ecSmrg	case RevertToFollowKeyboard:
187105b261ecSmrg	    if (inputInfo.keyboard->focus->win) {
187205b261ecSmrg		DoFocusEvents(dev, pWin, inputInfo.keyboard->focus->win,
187305b261ecSmrg			      focusEventMode);
187405b261ecSmrg		dev->focus->win = FollowKeyboardWin;
187505b261ecSmrg		dev->focus->traceGood = 0;
187605b261ecSmrg	    } else {
187705b261ecSmrg		DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
187805b261ecSmrg		dev->focus->win = NoneWin;
187905b261ecSmrg		dev->focus->traceGood = 0;
188005b261ecSmrg	    }
188105b261ecSmrg	    break;
188205b261ecSmrg	}
188305b261ecSmrg    }
188405b261ecSmrg
188505b261ecSmrg    if (dev->valuator)
188605b261ecSmrg	if (dev->valuator->motionHintWindow == pWin)
188705b261ecSmrg	    dev->valuator->motionHintWindow = NullWindow;
188805b261ecSmrg}
188905b261ecSmrg
189005b261ecSmrgvoid
189105b261ecSmrgDeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
189205b261ecSmrg{
189305b261ecSmrg    int i;
189405b261ecSmrg    DeviceIntPtr dev;
189505b261ecSmrg    InputClientsPtr ic;
189605b261ecSmrg    struct _OtherInputMasks *inputMasks;
189705b261ecSmrg
189805b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
189905b261ecSmrg	if (dev == inputInfo.pointer || dev == inputInfo.keyboard)
190005b261ecSmrg	    continue;
190105b261ecSmrg	DeleteDeviceFromAnyExtEvents(pWin, dev);
190205b261ecSmrg    }
190305b261ecSmrg
190405b261ecSmrg    for (dev = inputInfo.off_devices; dev; dev = dev->next)
190505b261ecSmrg	DeleteDeviceFromAnyExtEvents(pWin, dev);
190605b261ecSmrg
190705b261ecSmrg    if (freeResources)
190805b261ecSmrg	while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
190905b261ecSmrg	    ic = inputMasks->inputClients;
191005b261ecSmrg	    for (i = 0; i < EMASKSIZE; i++)
191105b261ecSmrg		inputMasks->dontPropagateMask[i] = 0;
191205b261ecSmrg	    FreeResource(ic->resource, RT_NONE);
191305b261ecSmrg	}
191405b261ecSmrg}
191505b261ecSmrg
191605b261ecSmrgint
191705b261ecSmrgMaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
191805b261ecSmrg{
191905b261ecSmrg    DeviceIntPtr dev;
192005b261ecSmrg
19214642e01fSmrg    dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
19224642e01fSmrg		    DixReadAccess);
192305b261ecSmrg    if (!dev)
192405b261ecSmrg        return 0;
192505b261ecSmrg
192605b261ecSmrg    if (pEvents->type == DeviceMotionNotify) {
192705b261ecSmrg	if (mask & DevicePointerMotionHintMask) {
192805b261ecSmrg	    if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
192905b261ecSmrg		return 1;	/* don't send, but pretend we did */
193005b261ecSmrg	    }
193105b261ecSmrg	    pEvents->detail = NotifyHint;
193205b261ecSmrg	} else {
193305b261ecSmrg	    pEvents->detail = NotifyNormal;
193405b261ecSmrg	}
193505b261ecSmrg    }
193605b261ecSmrg    return (0);
193705b261ecSmrg}
193805b261ecSmrg
193905b261ecSmrgvoid
194005b261ecSmrgCheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
194105b261ecSmrg			     deviceKeyButtonPointer * xE, GrabPtr grab,
194205b261ecSmrg			     ClientPtr client, Mask deliveryMask)
194305b261ecSmrg{
194405b261ecSmrg    DeviceIntPtr dev;
194505b261ecSmrg
19464642e01fSmrg    dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
19474642e01fSmrg		    DixReadAccess);
194805b261ecSmrg    if (!dev)
194905b261ecSmrg        return;
195005b261ecSmrg
195105b261ecSmrg    if (type == DeviceMotionNotify)
195205b261ecSmrg	dev->valuator->motionHintWindow = pWin;
195305b261ecSmrg    else if ((type == DeviceButtonPress) && (!grab) &&
195405b261ecSmrg	     (deliveryMask & DeviceButtonGrabMask)) {
195505b261ecSmrg	GrabRec tempGrab;
195605b261ecSmrg
195705b261ecSmrg	tempGrab.device = dev;
195805b261ecSmrg	tempGrab.resource = client->clientAsMask;
195905b261ecSmrg	tempGrab.window = pWin;
196005b261ecSmrg	tempGrab.ownerEvents =
196105b261ecSmrg	    (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
196205b261ecSmrg	tempGrab.eventMask = deliveryMask;
196305b261ecSmrg	tempGrab.keyboardMode = GrabModeAsync;
196405b261ecSmrg	tempGrab.pointerMode = GrabModeAsync;
196505b261ecSmrg	tempGrab.confineTo = NullWindow;
196605b261ecSmrg	tempGrab.cursor = NullCursor;
19674642e01fSmrg        tempGrab.genericMasks = NULL;
19684642e01fSmrg        tempGrab.next = NULL;
19694642e01fSmrg	(*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
197005b261ecSmrg    }
197105b261ecSmrg}
197205b261ecSmrg
197305b261ecSmrgstatic Mask
197405b261ecSmrgDeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
197505b261ecSmrg{
197605b261ecSmrg    InputClientsPtr other;
197705b261ecSmrg
197805b261ecSmrg    if (!wOtherInputMasks(pWin))
197905b261ecSmrg	return 0;
198005b261ecSmrg    for (other = wOtherInputMasks(pWin)->inputClients; other;
198105b261ecSmrg	 other = other->next) {
198205b261ecSmrg	if (SameClient(other, client))
198305b261ecSmrg	    return other->mask[dev->id];
198405b261ecSmrg    }
198505b261ecSmrg    return 0;
198605b261ecSmrg}
198705b261ecSmrg
198805b261ecSmrgvoid
198905b261ecSmrgMaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
199005b261ecSmrg{
199105b261ecSmrg    WindowPtr pWin;
19924642e01fSmrg    GrabPtr grab = dev->deviceGrab.grab;
199305b261ecSmrg
199405b261ecSmrg    pWin = dev->valuator->motionHintWindow;
199505b261ecSmrg
199605b261ecSmrg    if ((grab && SameClient(grab, client) &&
199705b261ecSmrg	 ((grab->eventMask & DevicePointerMotionHintMask) ||
199805b261ecSmrg	  (grab->ownerEvents &&
199905b261ecSmrg	   (DeviceEventMaskForClient(dev, pWin, client) &
200005b261ecSmrg	    DevicePointerMotionHintMask)))) ||
200105b261ecSmrg	(!grab &&
200205b261ecSmrg	 (DeviceEventMaskForClient(dev, pWin, client) &
200305b261ecSmrg	  DevicePointerMotionHintMask)))
200405b261ecSmrg	dev->valuator->motionHintWindow = NullWindow;
200505b261ecSmrg}
200605b261ecSmrg
200705b261ecSmrgint
200805b261ecSmrgDeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
200905b261ecSmrg			     int maskndx)
201005b261ecSmrg{
201105b261ecSmrg    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
201205b261ecSmrg
201305b261ecSmrg    if (mask & ~PropagateMask[maskndx]) {
201405b261ecSmrg	client->errorValue = mask;
201505b261ecSmrg	return BadValue;
201605b261ecSmrg    }
201705b261ecSmrg
201805b261ecSmrg    if (mask == 0) {
201905b261ecSmrg	if (inputMasks)
202005b261ecSmrg	    inputMasks->dontPropagateMask[maskndx] = mask;
202105b261ecSmrg    } else {
202205b261ecSmrg	if (!inputMasks)
202305b261ecSmrg	    AddExtensionClient(pWin, client, 0, 0);
202405b261ecSmrg	inputMasks = wOtherInputMasks(pWin);
202505b261ecSmrg	inputMasks->dontPropagateMask[maskndx] = mask;
202605b261ecSmrg    }
202705b261ecSmrg    RecalculateDeviceDeliverableEvents(pWin);
202805b261ecSmrg    if (ShouldFreeInputMasks(pWin, FALSE))
202905b261ecSmrg	FreeResource(inputMasks->inputClients->resource, RT_NONE);
203005b261ecSmrg    return Success;
203105b261ecSmrg}
203205b261ecSmrg
20334642e01fSmrgBool
203405b261ecSmrgShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
203505b261ecSmrg{
203605b261ecSmrg    int i;
203705b261ecSmrg    Mask allInputEventMasks = 0;
203805b261ecSmrg    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
203905b261ecSmrg
204005b261ecSmrg    for (i = 0; i < EMASKSIZE; i++)
204105b261ecSmrg	allInputEventMasks |= inputMasks->dontPropagateMask[i];
204205b261ecSmrg    if (!ignoreSelectedEvents)
204305b261ecSmrg	for (i = 0; i < EMASKSIZE; i++)
204405b261ecSmrg	    allInputEventMasks |= inputMasks->inputEvents[i];
204505b261ecSmrg    if (allInputEventMasks == 0)
204605b261ecSmrg	return TRUE;
204705b261ecSmrg    else
204805b261ecSmrg	return FALSE;
204905b261ecSmrg}
205005b261ecSmrg
205105b261ecSmrg/***********************************************************************
205205b261ecSmrg *
205305b261ecSmrg * Walk through the window tree, finding all clients that want to know
205405b261ecSmrg * about the Event.
205505b261ecSmrg *
205605b261ecSmrg */
205705b261ecSmrg
205805b261ecSmrgstatic void
205905b261ecSmrgFindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
206005b261ecSmrg                       xEvent * ev, int count)
206105b261ecSmrg{
206205b261ecSmrg    WindowPtr p2;
206305b261ecSmrg
206405b261ecSmrg    while (p1) {
206505b261ecSmrg        p2 = p1->firstChild;
20664642e01fSmrg        (void)DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab, dev->id);
206705b261ecSmrg        FindInterestedChildren(dev, p2, mask, ev, count);
206805b261ecSmrg        p1 = p1->nextSib;
206905b261ecSmrg    }
207005b261ecSmrg}
207105b261ecSmrg
207205b261ecSmrg/***********************************************************************
207305b261ecSmrg *
207405b261ecSmrg * Send an event to interested clients in all windows on all screens.
207505b261ecSmrg *
207605b261ecSmrg */
207705b261ecSmrg
207805b261ecSmrgvoid
207905b261ecSmrgSendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
208005b261ecSmrg{
208105b261ecSmrg    int i;
208205b261ecSmrg    WindowPtr pWin, p1;
208305b261ecSmrg
208405b261ecSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
208505b261ecSmrg        pWin = WindowTable[i];
20864642e01fSmrg        if (!pWin)
20874642e01fSmrg            continue;
20884642e01fSmrg        (void)DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab, dev->id);
208905b261ecSmrg        p1 = pWin->firstChild;
209005b261ecSmrg        FindInterestedChildren(dev, p1, mask, ev, count);
209105b261ecSmrg    }
209205b261ecSmrg}
20934642e01fSmrg
2094