2178 lines
		
	
	
		
			62 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			2178 lines
		
	
	
		
			62 KiB
		
	
	
	
		
			C
		
	
	
	
/************************************************************
 | 
						|
 | 
						|
Copyright 1989, 1998  The Open Group
 | 
						|
 | 
						|
Permission to use, copy, modify, distribute, and sell this software and its
 | 
						|
documentation for any purpose is hereby granted without fee, provided that
 | 
						|
the above copyright notice appear in all copies and that both that
 | 
						|
copyright notice and this permission notice appear in supporting
 | 
						|
documentation.
 | 
						|
 | 
						|
The above copyright notice and this permission notice shall be included in
 | 
						|
all copies or substantial portions of the Software.
 | 
						|
 | 
						|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 | 
						|
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 | 
						|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
						|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
						|
 | 
						|
Except as contained in this notice, the name of The Open Group shall not be
 | 
						|
used in advertising or otherwise to promote the sale, use or other dealings
 | 
						|
in this Software without prior written authorization from The Open Group.
 | 
						|
 | 
						|
Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
 | 
						|
 | 
						|
			All Rights Reserved
 | 
						|
 | 
						|
Permission to use, copy, modify, and distribute this software and its
 | 
						|
documentation for any purpose and without fee is hereby granted,
 | 
						|
provided that the above copyright notice appear in all copies and that
 | 
						|
both that copyright notice and this permission notice appear in
 | 
						|
supporting documentation, and that the name of Hewlett-Packard not be
 | 
						|
used in advertising or publicity pertaining to distribution of the
 | 
						|
software without specific, written prior permission.
 | 
						|
 | 
						|
HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 | 
						|
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 | 
						|
HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 | 
						|
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 | 
						|
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 | 
						|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 | 
						|
SOFTWARE.
 | 
						|
 | 
						|
********************************************************/
 | 
						|
 | 
						|
/********************************************************************
 | 
						|
 *
 | 
						|
 *  Routines to register and initialize extension input devices.
 | 
						|
 *  This also contains ProcessOtherEvent, the routine called from DDX
 | 
						|
 *  to route extension events.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include "inputstr.h"
 | 
						|
#include <X11/X.h>
 | 
						|
#include <X11/Xproto.h>
 | 
						|
#include <X11/extensions/XI.h>
 | 
						|
#include <X11/extensions/XIproto.h>
 | 
						|
#include <X11/extensions/XI2proto.h>
 | 
						|
#include <X11/extensions/geproto.h>
 | 
						|
#include "windowstr.h"
 | 
						|
#include "miscstruct.h"
 | 
						|
#include "region.h"
 | 
						|
#include "exevents.h"
 | 
						|
#include "extnsionst.h"
 | 
						|
#include "exglobals.h"
 | 
						|
#include "dixevents.h"	/* DeliverFocusedEvent */
 | 
						|
#include "dixgrabs.h"	/* CreateGrab() */
 | 
						|
#include "scrnintstr.h"
 | 
						|
#include "listdev.h" /* for CopySwapXXXClass */
 | 
						|
#include "xace.h"
 | 
						|
#include "xiquerydevice.h" /* For List*Info */
 | 
						|
#include "eventconvert.h"
 | 
						|
#include "eventstr.h"
 | 
						|
 | 
						|
#include <X11/extensions/XKBproto.h>
 | 
						|
#include "xkbsrv.h"
 | 
						|
 | 
						|
#define WID(w) ((w) ? ((w)->drawable.id) : 0)
 | 
						|
#define AllModifiersMask ( \
 | 
						|
	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
 | 
						|
	Mod3Mask | Mod4Mask | Mod5Mask )
 | 
						|
#define AllButtonsMask ( \
 | 
						|
	Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
 | 
						|
 | 
						|
Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
 | 
						|
				 Bool	/* ignoreSelectedEvents */
 | 
						|
    );
 | 
						|
static Bool MakeInputMasks(WindowPtr	/* pWin */
 | 
						|
    );
 | 
						|
 | 
						|
/*
 | 
						|
 * Only let the given client know of core events which will affect its
 | 
						|
 * interpretation of input events, if the client's ClientPointer (or the
 | 
						|
 * paired keyboard) is the current device.
 | 
						|
 */
 | 
						|
int
 | 
						|
XIShouldNotify(ClientPtr client, DeviceIntPtr dev)
 | 
						|
{
 | 
						|
    DeviceIntPtr current_ptr = PickPointer(client);
 | 
						|
    DeviceIntPtr current_kbd = GetPairedDevice(current_ptr);
 | 
						|
 | 
						|
    if (dev == current_kbd || dev == current_ptr)
 | 
						|
        return 1;
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
RegisterOtherDevice(DeviceIntPtr device)
 | 
						|
{
 | 
						|
    device->public.processInputProc = ProcessOtherEvent;
 | 
						|
    device->public.realInputProc = ProcessOtherEvent;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
IsPointerEvent(InternalEvent* event)
 | 
						|
{
 | 
						|
    switch(event->any.type)
 | 
						|
    {
 | 
						|
        case ET_ButtonPress:
 | 
						|
        case ET_ButtonRelease:
 | 
						|
        case ET_Motion:
 | 
						|
            /* XXX: enter/leave ?? */
 | 
						|
            return TRUE;
 | 
						|
        default:
 | 
						|
            break;
 | 
						|
    }
 | 
						|
    return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * @return the device matching the deviceid of the device set in the event, or
 | 
						|
 * NULL if the event is not an XInput event.
 | 
						|
 */
 | 
						|
DeviceIntPtr
 | 
						|
XIGetDevice(xEvent* xE)
 | 
						|
{
 | 
						|
    DeviceIntPtr pDev = NULL;
 | 
						|
 | 
						|
    if (xE->u.u.type == DeviceButtonPress ||
 | 
						|
        xE->u.u.type == DeviceButtonRelease ||
 | 
						|
        xE->u.u.type == DeviceMotionNotify ||
 | 
						|
        xE->u.u.type == ProximityIn ||
 | 
						|
        xE->u.u.type == ProximityOut ||
 | 
						|
        xE->u.u.type == DevicePropertyNotify)
 | 
						|
    {
 | 
						|
        int rc;
 | 
						|
        int id;
 | 
						|
 | 
						|
        id = ((deviceKeyButtonPointer*)xE)->deviceid & ~MORE_EVENTS;
 | 
						|
 | 
						|
        rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
 | 
						|
        if (rc != Success)
 | 
						|
            ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
 | 
						|
    }
 | 
						|
    return pDev;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Copy the device->key into master->key and send a mapping notify to the
 | 
						|
 * clients if appropriate.
 | 
						|
 * master->key needs to be allocated by the caller.
 | 
						|
 *
 | 
						|
 * Device is the slave device. If it is attached to a master device, we may
 | 
						|
 * need to send a mapping notify to the client because it causes the MD
 | 
						|
 * to change state.
 | 
						|
 *
 | 
						|
 * Mapping notify needs to be sent in the following cases:
 | 
						|
 *      - different slave device on same master
 | 
						|
 *      - different master
 | 
						|
 *
 | 
						|
 * XXX: They way how the code is we also send a map notify if the slave device
 | 
						|
 * stays the same, but the master changes. This isn't really necessary though.
 | 
						|
 *
 | 
						|
 * XXX: this gives you funny behaviour with the ClientPointer. When a
 | 
						|
 * MappingNotify is sent to the client, the client usually responds with a
 | 
						|
 * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
 | 
						|
 * mapping, regardless of which keyboard sent the last mapping notify request.
 | 
						|
 * So depending on the CP setting, your keyboard may change layout in each
 | 
						|
 * app...
 | 
						|
 *
 | 
						|
 * This code is basically the old SwitchCoreKeyboard.
 | 
						|
 */
 | 
						|
 | 
						|
void
 | 
						|
CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
 | 
						|
{
 | 
						|
    KeyClassPtr mk = master->key;
 | 
						|
 | 
						|
    if (device == master)
 | 
						|
        return;
 | 
						|
 | 
						|
    mk->sourceid = device->id;
 | 
						|
 | 
						|
 | 
						|
    if (!XkbCopyDeviceKeymap(master, device))
 | 
						|
        FatalError("Couldn't pivot keymap from device to core!\n");
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Copies the feedback classes from device "from" into device "to". Classes
 | 
						|
 * are duplicated (not just flipping the pointers). All feedback classes are
 | 
						|
 * linked lists, the full list is duplicated.
 | 
						|
 */
 | 
						|
static void
 | 
						|
DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
 | 
						|
{
 | 
						|
    ClassesPtr classes;
 | 
						|
 | 
						|
 | 
						|
    if (from->intfeed)
 | 
						|
    {
 | 
						|
        IntegerFeedbackPtr *i, it;
 | 
						|
 | 
						|
        if (!to->intfeed)
 | 
						|
        {
 | 
						|
            classes = to->unused_classes;
 | 
						|
            to->intfeed = classes->intfeed;
 | 
						|
            classes->intfeed = NULL;
 | 
						|
        }
 | 
						|
 | 
						|
        i = &to->intfeed;
 | 
						|
        for (it = from->intfeed; it; it = it->next)
 | 
						|
        {
 | 
						|
            if (!(*i))
 | 
						|
            {
 | 
						|
                *i = calloc(1, sizeof(IntegerFeedbackClassRec));
 | 
						|
                if (!(*i))
 | 
						|
                {
 | 
						|
                    ErrorF("[Xi] Cannot alloc memory for class copy.");
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            (*i)->CtrlProc = it->CtrlProc;
 | 
						|
            (*i)->ctrl     = it->ctrl;
 | 
						|
 | 
						|
            i = &(*i)->next;
 | 
						|
        }
 | 
						|
    } else if (to->intfeed && !from->intfeed)
 | 
						|
    {
 | 
						|
        ClassesPtr classes;
 | 
						|
        classes = to->unused_classes;
 | 
						|
        classes->intfeed = to->intfeed;
 | 
						|
        to->intfeed      = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (from->stringfeed)
 | 
						|
    {
 | 
						|
        StringFeedbackPtr *s, it;
 | 
						|
 | 
						|
        if (!to->stringfeed)
 | 
						|
        {
 | 
						|
            classes = to->unused_classes;
 | 
						|
            to->stringfeed = classes->stringfeed;
 | 
						|
            classes->stringfeed = NULL;
 | 
						|
        }
 | 
						|
 | 
						|
        s = &to->stringfeed;
 | 
						|
        for (it = from->stringfeed; it; it = it->next)
 | 
						|
        {
 | 
						|
            if (!(*s))
 | 
						|
            {
 | 
						|
                *s = calloc(1, sizeof(StringFeedbackClassRec));
 | 
						|
                if (!(*s))
 | 
						|
                {
 | 
						|
                    ErrorF("[Xi] Cannot alloc memory for class copy.");
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            (*s)->CtrlProc = it->CtrlProc;
 | 
						|
            (*s)->ctrl     = it->ctrl;
 | 
						|
 | 
						|
            s = &(*s)->next;
 | 
						|
        }
 | 
						|
    } else if (to->stringfeed && !from->stringfeed)
 | 
						|
    {
 | 
						|
        ClassesPtr classes;
 | 
						|
        classes = to->unused_classes;
 | 
						|
        classes->stringfeed = to->stringfeed;
 | 
						|
        to->stringfeed      = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (from->bell)
 | 
						|
    {
 | 
						|
        BellFeedbackPtr *b, it;
 | 
						|
 | 
						|
        if (!to->bell)
 | 
						|
        {
 | 
						|
            classes = to->unused_classes;
 | 
						|
            to->bell = classes->bell;
 | 
						|
            classes->bell = NULL;
 | 
						|
        }
 | 
						|
 | 
						|
        b = &to->bell;
 | 
						|
        for (it = from->bell; it; it = it->next)
 | 
						|
        {
 | 
						|
            if (!(*b))
 | 
						|
            {
 | 
						|
                *b = calloc(1, sizeof(BellFeedbackClassRec));
 | 
						|
                if (!(*b))
 | 
						|
                {
 | 
						|
                    ErrorF("[Xi] Cannot alloc memory for class copy.");
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            (*b)->BellProc = it->BellProc;
 | 
						|
            (*b)->CtrlProc = it->CtrlProc;
 | 
						|
            (*b)->ctrl     = it->ctrl;
 | 
						|
 | 
						|
            b = &(*b)->next;
 | 
						|
        }
 | 
						|
    } else if (to->bell && !from->bell)
 | 
						|
    {
 | 
						|
        ClassesPtr classes;
 | 
						|
        classes = to->unused_classes;
 | 
						|
        classes->bell = to->bell;
 | 
						|
        to->bell      = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (from->leds)
 | 
						|
    {
 | 
						|
        LedFeedbackPtr *l, it;
 | 
						|
 | 
						|
        if (!to->leds)
 | 
						|
        {
 | 
						|
            classes = to->unused_classes;
 | 
						|
            to->leds = classes->leds;
 | 
						|
            classes->leds = NULL;
 | 
						|
        }
 | 
						|
 | 
						|
        l = &to->leds;
 | 
						|
        for (it = from->leds; it; it = it->next)
 | 
						|
        {
 | 
						|
            if (!(*l))
 | 
						|
            {
 | 
						|
                *l = calloc(1, sizeof(LedFeedbackClassRec));
 | 
						|
                if (!(*l))
 | 
						|
                {
 | 
						|
                    ErrorF("[Xi] Cannot alloc memory for class copy.");
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            (*l)->CtrlProc = it->CtrlProc;
 | 
						|
            (*l)->ctrl     = it->ctrl;
 | 
						|
            if ((*l)->xkb_sli)
 | 
						|
                XkbFreeSrvLedInfo((*l)->xkb_sli);
 | 
						|
            (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
 | 
						|
 | 
						|
            l = &(*l)->next;
 | 
						|
        }
 | 
						|
    } else if (to->leds && !from->leds)
 | 
						|
    {
 | 
						|
        ClassesPtr classes;
 | 
						|
        classes = to->unused_classes;
 | 
						|
        classes->leds = to->leds;
 | 
						|
        to->leds      = NULL;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
 | 
						|
{
 | 
						|
    ClassesPtr classes;
 | 
						|
 | 
						|
    /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
 | 
						|
     * kbdfeed to be set up properly, so let's do the feedback classes first.
 | 
						|
     */
 | 
						|
    if (from->kbdfeed)
 | 
						|
    {
 | 
						|
        KbdFeedbackPtr *k, it;
 | 
						|
 | 
						|
        if (!to->kbdfeed)
 | 
						|
        {
 | 
						|
            classes = to->unused_classes;
 | 
						|
 | 
						|
            to->kbdfeed = classes->kbdfeed;
 | 
						|
            if (!to->kbdfeed)
 | 
						|
                InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
 | 
						|
            classes->kbdfeed = NULL;
 | 
						|
        }
 | 
						|
 | 
						|
        k = &to->kbdfeed;
 | 
						|
        for(it = from->kbdfeed; it; it = it->next)
 | 
						|
        {
 | 
						|
            if (!(*k))
 | 
						|
            {
 | 
						|
                *k = calloc(1, sizeof(KbdFeedbackClassRec));
 | 
						|
                if (!*k)
 | 
						|
                {
 | 
						|
                    ErrorF("[Xi] Cannot alloc memory for class copy.");
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            (*k)->BellProc = it->BellProc;
 | 
						|
            (*k)->CtrlProc = it->CtrlProc;
 | 
						|
            (*k)->ctrl     = it->ctrl;
 | 
						|
            if ((*k)->xkb_sli)
 | 
						|
                XkbFreeSrvLedInfo((*k)->xkb_sli);
 | 
						|
            (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
 | 
						|
 | 
						|
            k = &(*k)->next;
 | 
						|
        }
 | 
						|
    } else if (to->kbdfeed && !from->kbdfeed)
 | 
						|
    {
 | 
						|
        ClassesPtr classes;
 | 
						|
        classes = to->unused_classes;
 | 
						|
        classes->kbdfeed = to->kbdfeed;
 | 
						|
        to->kbdfeed      = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (from->key)
 | 
						|
    {
 | 
						|
        if (!to->key)
 | 
						|
        {
 | 
						|
            classes = to->unused_classes;
 | 
						|
            to->key = classes->key;
 | 
						|
            if (!to->key)
 | 
						|
                InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
 | 
						|
            else
 | 
						|
                classes->key = NULL;
 | 
						|
        }
 | 
						|
 | 
						|
        CopyKeyClass(from, to);
 | 
						|
    } else if (to->key && !from->key)
 | 
						|
    {
 | 
						|
        ClassesPtr classes;
 | 
						|
        classes = to->unused_classes;
 | 
						|
        classes->key = to->key;
 | 
						|
        to->key      = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps
 | 
						|
     * pointer point into the xkbInfo->desc struct.  XkbCopySrvLedInfo
 | 
						|
     * didn't update the pointers so we need to do it manually here.
 | 
						|
     */
 | 
						|
    if (to->kbdfeed)
 | 
						|
    {
 | 
						|
        KbdFeedbackPtr k;
 | 
						|
 | 
						|
        for (k = to->kbdfeed; k; k = k->next)
 | 
						|
        {
 | 
						|
            if (!k->xkb_sli)
 | 
						|
                continue;
 | 
						|
            if (k->xkb_sli->flags & XkbSLI_IsDefault)
 | 
						|
            {
 | 
						|
                k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators;
 | 
						|
                k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* We can't just copy over the focus class. When an app sets the focus,
 | 
						|
     * it'll do so on the master device. Copying the SDs focus means losing
 | 
						|
     * the focus.
 | 
						|
     * So we only copy the focus class if the device didn't have one,
 | 
						|
     * otherwise we leave it as it is.
 | 
						|
     */
 | 
						|
    if (from->focus)
 | 
						|
    {
 | 
						|
        if (!to->focus)
 | 
						|
        {
 | 
						|
            WindowPtr *oldTrace;
 | 
						|
 | 
						|
            classes = to->unused_classes;
 | 
						|
            to->focus = classes->focus;
 | 
						|
            if (!to->focus)
 | 
						|
            {
 | 
						|
                to->focus = calloc(1, sizeof(FocusClassRec));
 | 
						|
                if (!to->focus)
 | 
						|
                    FatalError("[Xi] no memory for class shift.\n");
 | 
						|
            } else
 | 
						|
                classes->focus = NULL;
 | 
						|
 | 
						|
            oldTrace = to->focus->trace;
 | 
						|
            memcpy(to->focus, from->focus, sizeof(FocusClassRec));
 | 
						|
            to->focus->trace = realloc(oldTrace,
 | 
						|
                                  to->focus->traceSize * sizeof(WindowPtr));
 | 
						|
            if (!to->focus->trace && to->focus->traceSize)
 | 
						|
                FatalError("[Xi] no memory for trace.\n");
 | 
						|
            memcpy(to->focus->trace, from->focus->trace,
 | 
						|
                    from->focus->traceSize * sizeof(WindowPtr));
 | 
						|
            to->focus->sourceid = from->id;
 | 
						|
        }
 | 
						|
    } else if (to->focus)
 | 
						|
    {
 | 
						|
        ClassesPtr classes;
 | 
						|
        classes = to->unused_classes;
 | 
						|
        classes->focus = to->focus;
 | 
						|
        to->focus      = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
 | 
						|
{
 | 
						|
    ClassesPtr classes;
 | 
						|
 | 
						|
    /* Feedback classes must be copied first */
 | 
						|
    if (from->ptrfeed)
 | 
						|
    {
 | 
						|
        PtrFeedbackPtr *p, it;
 | 
						|
        if (!to->ptrfeed)
 | 
						|
        {
 | 
						|
            classes = to->unused_classes;
 | 
						|
            to->ptrfeed = classes->ptrfeed;
 | 
						|
            classes->ptrfeed = NULL;
 | 
						|
        }
 | 
						|
 | 
						|
        p = &to->ptrfeed;
 | 
						|
        for (it = from->ptrfeed; it; it = it->next)
 | 
						|
        {
 | 
						|
            if (!(*p))
 | 
						|
            {
 | 
						|
                *p = calloc(1, sizeof(PtrFeedbackClassRec));
 | 
						|
                if (!*p)
 | 
						|
                {
 | 
						|
                    ErrorF("[Xi] Cannot alloc memory for class copy.");
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            (*p)->CtrlProc = it->CtrlProc;
 | 
						|
            (*p)->ctrl     = it->ctrl;
 | 
						|
 | 
						|
            p = &(*p)->next;
 | 
						|
        }
 | 
						|
    } else if (to->ptrfeed && !from->ptrfeed)
 | 
						|
    {
 | 
						|
        ClassesPtr classes;
 | 
						|
        classes = to->unused_classes;
 | 
						|
        classes->ptrfeed = to->ptrfeed;
 | 
						|
        to->ptrfeed      = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (from->valuator)
 | 
						|
    {
 | 
						|
        ValuatorClassPtr v;
 | 
						|
        if (!to->valuator)
 | 
						|
        {
 | 
						|
            classes = to->unused_classes;
 | 
						|
            to->valuator = classes->valuator;
 | 
						|
            if (to->valuator)
 | 
						|
                classes->valuator = NULL;
 | 
						|
        }
 | 
						|
 | 
						|
        to->valuator = realloc(to->valuator, sizeof(ValuatorClassRec) +
 | 
						|
                from->valuator->numAxes * sizeof(AxisInfo) +
 | 
						|
                from->valuator->numAxes * sizeof(double));
 | 
						|
        v = to->valuator;
 | 
						|
        if (!v)
 | 
						|
            FatalError("[Xi] no memory for class shift.\n");
 | 
						|
 | 
						|
        v->numAxes = from->valuator->numAxes;
 | 
						|
        v->axes = (AxisInfoPtr)&v[1];
 | 
						|
        memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
 | 
						|
 | 
						|
        v->axisVal = (double*)(v->axes + from->valuator->numAxes);
 | 
						|
        v->sourceid = from->id;
 | 
						|
        v->mode = from->valuator->mode;
 | 
						|
    } else if (to->valuator && !from->valuator)
 | 
						|
    {
 | 
						|
        ClassesPtr classes;
 | 
						|
        classes = to->unused_classes;
 | 
						|
        classes->valuator = to->valuator;
 | 
						|
        to->valuator      = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (from->button)
 | 
						|
    {
 | 
						|
        if (!to->button)
 | 
						|
        {
 | 
						|
            classes = to->unused_classes;
 | 
						|
            to->button = classes->button;
 | 
						|
            if (!to->button)
 | 
						|
            {
 | 
						|
                to->button = calloc(1, sizeof(ButtonClassRec));
 | 
						|
                if (!to->button)
 | 
						|
                    FatalError("[Xi] no memory for class shift.\n");
 | 
						|
            } else
 | 
						|
                classes->button = NULL;
 | 
						|
        }
 | 
						|
 | 
						|
        if (from->button->xkb_acts)
 | 
						|
        {
 | 
						|
            if (!to->button->xkb_acts)
 | 
						|
            {
 | 
						|
                to->button->xkb_acts = calloc(1, sizeof(XkbAction));
 | 
						|
                if (!to->button->xkb_acts)
 | 
						|
                    FatalError("[Xi] not enough memory for xkb_acts.\n");
 | 
						|
            }
 | 
						|
            memcpy(to->button->xkb_acts, from->button->xkb_acts,
 | 
						|
                    sizeof(XkbAction));
 | 
						|
        } else
 | 
						|
            free(to->button->xkb_acts);
 | 
						|
 | 
						|
         memcpy(to->button->labels, from->button->labels,
 | 
						|
                from->button->numButtons * sizeof(Atom));
 | 
						|
        to->button->sourceid = from->id;
 | 
						|
    } else if (to->button && !from->button)
 | 
						|
    {
 | 
						|
        ClassesPtr classes;
 | 
						|
        classes = to->unused_classes;
 | 
						|
        classes->button = to->button;
 | 
						|
        to->button      = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (from->proximity)
 | 
						|
    {
 | 
						|
        if (!to->proximity)
 | 
						|
        {
 | 
						|
            classes = to->unused_classes;
 | 
						|
            to->proximity = classes->proximity;
 | 
						|
            if (!to->proximity)
 | 
						|
            {
 | 
						|
                to->proximity = calloc(1, sizeof(ProximityClassRec));
 | 
						|
                if (!to->proximity)
 | 
						|
                    FatalError("[Xi] no memory for class shift.\n");
 | 
						|
            } else
 | 
						|
                classes->proximity = NULL;
 | 
						|
        }
 | 
						|
        memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
 | 
						|
        to->proximity->sourceid = from->id;
 | 
						|
    } else if (to->proximity)
 | 
						|
    {
 | 
						|
        ClassesPtr classes;
 | 
						|
        classes = to->unused_classes;
 | 
						|
        classes->proximity = to->proximity;
 | 
						|
        to->proximity      = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (from->absolute)
 | 
						|
    {
 | 
						|
        if (!to->absolute)
 | 
						|
        {
 | 
						|
            classes = to->unused_classes;
 | 
						|
            to->absolute = classes->absolute;
 | 
						|
            if (!to->absolute)
 | 
						|
            {
 | 
						|
                to->absolute = calloc(1, sizeof(AbsoluteClassRec));
 | 
						|
                if (!to->absolute)
 | 
						|
                    FatalError("[Xi] no memory for class shift.\n");
 | 
						|
            } else
 | 
						|
                classes->absolute = NULL;
 | 
						|
        }
 | 
						|
        memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec));
 | 
						|
        to->absolute->sourceid = from->id;
 | 
						|
    } else if (to->absolute)
 | 
						|
    {
 | 
						|
        ClassesPtr classes;
 | 
						|
        classes = to->unused_classes;
 | 
						|
        classes->absolute = to->absolute;
 | 
						|
        to->absolute      = NULL;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Copies the CONTENT of the classes of device from into the classes in device
 | 
						|
 * to. From and to are identical after finishing.
 | 
						|
 *
 | 
						|
 * If to does not have classes from currenly has, the classes are stored in
 | 
						|
 * to's devPrivates system. Later, we recover it again from there if needed.
 | 
						|
 * Saves a few memory allocations.
 | 
						|
 */
 | 
						|
void
 | 
						|
DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dce)
 | 
						|
{
 | 
						|
    /* generic feedback classes, not tied to pointer and/or keyboard */
 | 
						|
    DeepCopyFeedbackClasses(from, to);
 | 
						|
 | 
						|
    if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
 | 
						|
        DeepCopyKeyboardClasses(from, to);
 | 
						|
    if ((dce->flags & DEVCHANGE_POINTER_EVENT))
 | 
						|
        DeepCopyPointerClasses(from, to);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
 * Send an XI2 DeviceChangedEvent to all interested clients.
 | 
						|
 */
 | 
						|
void
 | 
						|
XISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, DeviceChangedEvent *dce)
 | 
						|
{
 | 
						|
    xXIDeviceChangedEvent *dcce;
 | 
						|
    int rc;
 | 
						|
 | 
						|
    rc = EventToXI2((InternalEvent*)dce, (xEvent**)&dcce);
 | 
						|
    if (rc != Success)
 | 
						|
    {
 | 
						|
        ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    /* we don't actually swap if there's a NullClient, swapping is done
 | 
						|
     * later when event is delivered. */
 | 
						|
    SendEventToAllWindows(master, XI_DeviceChangedMask, (xEvent*)dcce, 1);
 | 
						|
    free(dcce);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
 | 
						|
{
 | 
						|
    DeviceIntPtr slave;
 | 
						|
    int rc;
 | 
						|
 | 
						|
    /* For now, we don't have devices that change physically. */
 | 
						|
    if (!IsMaster(device))
 | 
						|
        return;
 | 
						|
 | 
						|
    rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
 | 
						|
 | 
						|
    if (rc != Success)
 | 
						|
        return; /* Device has disappeared */
 | 
						|
 | 
						|
    if (!slave->u.master)
 | 
						|
        return; /* set floating since the event */
 | 
						|
 | 
						|
    if (slave->u.master->id != dce->masterid)
 | 
						|
        return; /* not our slave anymore, don't care */
 | 
						|
 | 
						|
    /* FIXME: we probably need to send a DCE for the new slave now */
 | 
						|
 | 
						|
    device->public.devicePrivate = slave->public.devicePrivate;
 | 
						|
 | 
						|
    /* FIXME: the classes may have changed since we generated the event. */
 | 
						|
    DeepCopyDeviceClasses(slave, device, dce);
 | 
						|
    XISendDeviceChangedEvent(slave, device, dce);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Update the device state according to the data in the event.
 | 
						|
 *
 | 
						|
 * return values are
 | 
						|
 *   DEFAULT ... process as normal
 | 
						|
 *   DONT_PROCESS ... return immediately from caller
 | 
						|
 */
 | 
						|
#define DEFAULT 0
 | 
						|
#define DONT_PROCESS 1
 | 
						|
int
 | 
						|
UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    int key = 0,
 | 
						|
        bit = 0,
 | 
						|
        last_valuator;
 | 
						|
 | 
						|
    KeyClassPtr k       = NULL;
 | 
						|
    ButtonClassPtr b    = NULL;
 | 
						|
    ValuatorClassPtr v  = NULL;
 | 
						|
 | 
						|
    /* This event is always the first we get, before the actual events with
 | 
						|
     * the data. However, the way how the DDX is set up, "device" will
 | 
						|
     * actually be the slave device that caused the event.
 | 
						|
     */
 | 
						|
    switch(event->type)
 | 
						|
    {
 | 
						|
        case ET_DeviceChanged:
 | 
						|
            ChangeMasterDeviceClasses(device, (DeviceChangedEvent*)event);
 | 
						|
            return DONT_PROCESS; /* event has been sent already */
 | 
						|
        case ET_Motion:
 | 
						|
        case ET_ButtonPress:
 | 
						|
        case ET_ButtonRelease:
 | 
						|
        case ET_KeyPress:
 | 
						|
        case ET_KeyRelease:
 | 
						|
        case ET_ProximityIn:
 | 
						|
        case ET_ProximityOut:
 | 
						|
            break;
 | 
						|
        default:
 | 
						|
            /* other events don't update the device */
 | 
						|
            return DEFAULT;
 | 
						|
    }
 | 
						|
 | 
						|
    k = device->key;
 | 
						|
    v = device->valuator;
 | 
						|
    b = device->button;
 | 
						|
 | 
						|
    key = event->detail.key;
 | 
						|
    bit = 1 << (key & 7);
 | 
						|
 | 
						|
    /* Update device axis */
 | 
						|
    /* Check valuators first */
 | 
						|
    last_valuator = -1;
 | 
						|
    for (i = 0; i < MAX_VALUATORS; i++)
 | 
						|
    {
 | 
						|
        if (BitIsOn(&event->valuators.mask, i))
 | 
						|
        {
 | 
						|
            if (!v)
 | 
						|
            {
 | 
						|
                ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
 | 
						|
                        "Ignoring event.\n", device->name);
 | 
						|
                return DONT_PROCESS;
 | 
						|
            } else if (v->numAxes < i)
 | 
						|
            {
 | 
						|
                ErrorF("[Xi] Too many valuators reported for device '%s'. "
 | 
						|
                        "Ignoring event.\n", device->name);
 | 
						|
                return DONT_PROCESS;
 | 
						|
            }
 | 
						|
            last_valuator = i;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    for (i = 0; i <= last_valuator && i < v->numAxes; i++)
 | 
						|
    {
 | 
						|
        if (BitIsOn(&event->valuators.mask, i))
 | 
						|
        {
 | 
						|
            /* XXX: Relative/Absolute mode */
 | 
						|
            v->axisVal[i] = event->valuators.data[i];
 | 
						|
            v->axisVal[i] += (event->valuators.data_frac[i] * 1.0f / (1 << 16) / (1 << 16));
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (event->type == ET_KeyPress) {
 | 
						|
        if (!k)
 | 
						|
            return DONT_PROCESS;
 | 
						|
 | 
						|
	/* don't allow ddx to generate multiple downs, but repeats are okay */
 | 
						|
	if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
 | 
						|
	    return DONT_PROCESS;
 | 
						|
 | 
						|
	if (device->valuator)
 | 
						|
	    device->valuator->motionHintWindow = NullWindow;
 | 
						|
	set_key_down(device, key, KEY_PROCESSED);
 | 
						|
    } else if (event->type == ET_KeyRelease) {
 | 
						|
        if (!k)
 | 
						|
            return DONT_PROCESS;
 | 
						|
 | 
						|
	if (!key_is_down(device, key, KEY_PROCESSED))	/* guard against duplicates */
 | 
						|
	    return DONT_PROCESS;
 | 
						|
	if (device->valuator)
 | 
						|
	    device->valuator->motionHintWindow = NullWindow;
 | 
						|
	set_key_up(device, key, KEY_PROCESSED);
 | 
						|
    } else if (event->type == ET_ButtonPress) {
 | 
						|
        Mask mask;
 | 
						|
        if (!b)
 | 
						|
            return DONT_PROCESS;
 | 
						|
 | 
						|
        if (button_is_down(device, key, BUTTON_PROCESSED))
 | 
						|
            return DONT_PROCESS;
 | 
						|
 | 
						|
        set_button_down(device, key, BUTTON_PROCESSED);
 | 
						|
	if (device->valuator)
 | 
						|
	    device->valuator->motionHintWindow = NullWindow;
 | 
						|
        if (!b->map[key])
 | 
						|
            return DONT_PROCESS;
 | 
						|
        b->buttonsDown++;
 | 
						|
	b->motionMask = DeviceButtonMotionMask;
 | 
						|
        if (b->map[key] <= 5)
 | 
						|
	    b->state |= (Button1Mask >> 1) << b->map[key];
 | 
						|
 | 
						|
        /* Add state and motionMask to the filter for this event */
 | 
						|
        mask = DevicePointerMotionMask | b->state | b->motionMask;
 | 
						|
        SetMaskForEvent(device->id, mask, DeviceMotionNotify);
 | 
						|
        mask = PointerMotionMask | b->state | b->motionMask;
 | 
						|
        SetMaskForEvent(device->id, mask, MotionNotify);
 | 
						|
    } else if (event->type == ET_ButtonRelease) {
 | 
						|
        Mask mask;
 | 
						|
        if (!b)
 | 
						|
            return DONT_PROCESS;
 | 
						|
 | 
						|
        if (!button_is_down(device, key, BUTTON_PROCESSED))
 | 
						|
            return DONT_PROCESS;
 | 
						|
        if (IsMaster(device)) {
 | 
						|
            DeviceIntPtr sd;
 | 
						|
 | 
						|
            /*
 | 
						|
             * Leave the button down if any slave has the
 | 
						|
             * button still down. Note that this depends on the
 | 
						|
             * event being delivered through the slave first
 | 
						|
             */
 | 
						|
            for (sd = inputInfo.devices; sd; sd = sd->next) {
 | 
						|
                if (IsMaster(sd) || sd->u.master != device)
 | 
						|
                    continue;
 | 
						|
                if (!sd->button)
 | 
						|
                    continue;
 | 
						|
                if (button_is_down(sd, key, BUTTON_PROCESSED))
 | 
						|
                    return DONT_PROCESS;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        set_button_up(device, key, BUTTON_PROCESSED);
 | 
						|
	if (device->valuator)
 | 
						|
	    device->valuator->motionHintWindow = NullWindow;
 | 
						|
        if (!b->map[key])
 | 
						|
            return DONT_PROCESS;
 | 
						|
        if (b->buttonsDown >= 1 && !--b->buttonsDown)
 | 
						|
	    b->motionMask = 0;
 | 
						|
	if (b->map[key] <= 5)
 | 
						|
	    b->state &= ~((Button1Mask >> 1) << b->map[key]);
 | 
						|
 | 
						|
        /* Add state and motionMask to the filter for this event */
 | 
						|
        mask = DevicePointerMotionMask | b->state | b->motionMask;
 | 
						|
        SetMaskForEvent(device->id, mask, DeviceMotionNotify);
 | 
						|
        mask = PointerMotionMask | b->state | b->motionMask;
 | 
						|
        SetMaskForEvent(device->id, mask, MotionNotify);
 | 
						|
    } else if (event->type == ET_ProximityIn)
 | 
						|
	device->valuator->mode &= ~OutOfProximity;
 | 
						|
    else if (event->type == ET_ProximityOut)
 | 
						|
	device->valuator->mode |= OutOfProximity;
 | 
						|
 | 
						|
    return DEFAULT;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
ProcessRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
 | 
						|
{
 | 
						|
    GrabPtr grab = device->deviceGrab.grab;
 | 
						|
 | 
						|
    if (grab)
 | 
						|
        DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE);
 | 
						|
    else { /* deliver to all root windows */
 | 
						|
        xEvent *xi;
 | 
						|
        int i;
 | 
						|
 | 
						|
        i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi);
 | 
						|
        if (i != Success)
 | 
						|
        {
 | 
						|
            ErrorF("[Xi] %s: XI2 conversion failed in ProcessRawEvent (%d)\n",
 | 
						|
                    device->name, i);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        for (i = 0; i < screenInfo.numScreens; i++)
 | 
						|
            DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1,
 | 
						|
                                  GetEventFilter(device, xi), NULL);
 | 
						|
        free(xi);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Main device event processing function.
 | 
						|
 * Called from when processing the events from the event queue.
 | 
						|
 *
 | 
						|
 */
 | 
						|
void
 | 
						|
ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
 | 
						|
{
 | 
						|
    GrabPtr grab;
 | 
						|
    Bool deactivateDeviceGrab = FALSE;
 | 
						|
    int key = 0, rootX, rootY;
 | 
						|
    ButtonClassPtr b;
 | 
						|
    KeyClassPtr k;
 | 
						|
    ValuatorClassPtr v;
 | 
						|
    int ret = 0;
 | 
						|
    int state, i;
 | 
						|
    DeviceIntPtr mouse = NULL, kbd = NULL;
 | 
						|
    DeviceEvent *event = &ev->device_event;
 | 
						|
 | 
						|
    CHECKEVENT(ev);
 | 
						|
 | 
						|
    if (ev->any.type == ET_RawKeyPress ||
 | 
						|
        ev->any.type == ET_RawKeyRelease ||
 | 
						|
        ev->any.type == ET_RawButtonPress ||
 | 
						|
        ev->any.type == ET_RawButtonRelease ||
 | 
						|
        ev->any.type == ET_RawMotion)
 | 
						|
    {
 | 
						|
        ProcessRawEvent(&ev->raw_event, device);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    if (IsPointerDevice(device))
 | 
						|
    {
 | 
						|
        kbd = GetPairedDevice(device);
 | 
						|
        mouse = device;
 | 
						|
        if (!kbd->key) /* can happen with floating SDs */
 | 
						|
            kbd = NULL;
 | 
						|
    } else
 | 
						|
    {
 | 
						|
        mouse = GetPairedDevice(device);
 | 
						|
        kbd = device;
 | 
						|
        if (!mouse->valuator || !mouse->button) /* may be float. SDs */
 | 
						|
            mouse = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    /* State needs to be assembled BEFORE the device is updated. */
 | 
						|
    state = (kbd && kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->state) : 0;
 | 
						|
    state |= (mouse && mouse->button) ? (mouse->button->state) : 0;
 | 
						|
 | 
						|
    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
 | 
						|
        if (BitIsOn(mouse->button->down, i))
 | 
						|
            SetBit(event->buttons, i);
 | 
						|
 | 
						|
    if (kbd && kbd->key)
 | 
						|
    {
 | 
						|
        XkbStatePtr state;
 | 
						|
        /* we need the state before the event happens */
 | 
						|
        if (event->type == ET_KeyPress || event->type == ET_KeyRelease)
 | 
						|
            state = &kbd->key->xkbInfo->prev_state;
 | 
						|
        else
 | 
						|
            state = &kbd->key->xkbInfo->state;
 | 
						|
 | 
						|
        event->mods.base = state->base_mods;
 | 
						|
        event->mods.latched = state->latched_mods;
 | 
						|
        event->mods.locked = state->locked_mods;
 | 
						|
        event->mods.effective = state->mods;
 | 
						|
 | 
						|
        event->group.base = state->base_group;
 | 
						|
        event->group.latched = state->latched_group;
 | 
						|
        event->group.locked = state->locked_group;
 | 
						|
        event->group.effective = state->group;
 | 
						|
    }
 | 
						|
 | 
						|
    ret = UpdateDeviceState(device, event);
 | 
						|
    if (ret == DONT_PROCESS)
 | 
						|
        return;
 | 
						|
 | 
						|
    v = device->valuator;
 | 
						|
    b = device->button;
 | 
						|
    k = device->key;
 | 
						|
 | 
						|
    if (IsMaster(device) || !device->u.master)
 | 
						|
        CheckMotion(event, device);
 | 
						|
 | 
						|
    switch (event->type)
 | 
						|
    {
 | 
						|
        case ET_Motion:
 | 
						|
        case ET_ButtonPress:
 | 
						|
        case ET_ButtonRelease:
 | 
						|
        case ET_KeyPress:
 | 
						|
        case ET_KeyRelease:
 | 
						|
        case ET_ProximityIn:
 | 
						|
        case ET_ProximityOut:
 | 
						|
            GetSpritePosition(device, &rootX, &rootY);
 | 
						|
            event->root_x = rootX;
 | 
						|
            event->root_y = rootY;
 | 
						|
            NoticeEventTime((InternalEvent*)event);
 | 
						|
            event->corestate = state;
 | 
						|
            key = event->detail.key;
 | 
						|
            break;
 | 
						|
        default:
 | 
						|
            break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (DeviceEventCallback && !syncEvents.playingEvents) {
 | 
						|
	DeviceEventInfoRec eventinfo;
 | 
						|
	SpritePtr pSprite = device->spriteInfo->sprite;
 | 
						|
 | 
						|
	/* see comment in EnqueueEvents regarding the next three lines */
 | 
						|
	if (ev->any.type == ET_Motion)
 | 
						|
	    ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
 | 
						|
 | 
						|
	eventinfo.device = device;
 | 
						|
	eventinfo.event = ev;
 | 
						|
	CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
 | 
						|
    }
 | 
						|
 | 
						|
    grab = device->deviceGrab.grab;
 | 
						|
 | 
						|
    switch(event->type)
 | 
						|
    {
 | 
						|
        case ET_KeyPress:
 | 
						|
            if (!grab && CheckDeviceGrabs(device, event, 0)) {
 | 
						|
                device->deviceGrab.activatingKey = key;
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            break;
 | 
						|
        case ET_KeyRelease:
 | 
						|
            if (grab && device->deviceGrab.fromPassiveGrab &&
 | 
						|
                (key == device->deviceGrab.activatingKey) &&
 | 
						|
                (device->deviceGrab.grab->type == KeyPress ||
 | 
						|
                 device->deviceGrab.grab->type == DeviceKeyPress ||
 | 
						|
                 device->deviceGrab.grab->type == XI_KeyPress))
 | 
						|
                deactivateDeviceGrab = TRUE;
 | 
						|
            break;
 | 
						|
        case ET_ButtonPress:
 | 
						|
            event->detail.button = b->map[key];
 | 
						|
            if (!event->detail.button) { /* there's no button 0 */
 | 
						|
                event->detail.button = key;
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            if (!grab && CheckDeviceGrabs(device, event, 0))
 | 
						|
            {
 | 
						|
                /* if a passive grab was activated, the event has been sent
 | 
						|
                 * already */
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            break;
 | 
						|
        case ET_ButtonRelease:
 | 
						|
            event->detail.button = b->map[key];
 | 
						|
            if (!event->detail.button) { /* there's no button 0 */
 | 
						|
                event->detail.button = key;
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            if (grab && !b->buttonsDown &&
 | 
						|
                device->deviceGrab.fromPassiveGrab &&
 | 
						|
                (device->deviceGrab.grab->type == ButtonPress ||
 | 
						|
                 device->deviceGrab.grab->type == DeviceButtonPress ||
 | 
						|
                 device->deviceGrab.grab->type == XI_ButtonPress))
 | 
						|
                deactivateDeviceGrab = TRUE;
 | 
						|
        default:
 | 
						|
            break;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    if (grab)
 | 
						|
        DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
 | 
						|
    else if (device->focus && !IsPointerEvent((InternalEvent*)ev))
 | 
						|
        DeliverFocusedEvent(device, (InternalEvent*)event,
 | 
						|
                            GetSpriteWindow(device));
 | 
						|
    else
 | 
						|
        DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event,
 | 
						|
                            NullGrab, NullWindow, device);
 | 
						|
 | 
						|
    if (deactivateDeviceGrab == TRUE)
 | 
						|
	(*device->deviceGrab.DeactivateGrab) (device);
 | 
						|
    event->detail.key = key;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
InitProximityClassDeviceStruct(DeviceIntPtr dev)
 | 
						|
{
 | 
						|
    ProximityClassPtr proxc;
 | 
						|
 | 
						|
    proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
 | 
						|
    if (!proxc)
 | 
						|
	return FALSE;
 | 
						|
    proxc->sourceid = dev->id;
 | 
						|
    dev->proximity = proxc;
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Initialise the device's valuators. The memory must already be allocated,
 | 
						|
 * this function merely inits the matching axis (specified through axnum) to
 | 
						|
 * sane values.
 | 
						|
 *
 | 
						|
 * It is a condition that (minval < maxval).
 | 
						|
 *
 | 
						|
 * @see InitValuatorClassDeviceStruct
 | 
						|
 */
 | 
						|
void
 | 
						|
InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
 | 
						|
		       int resolution, int min_res, int max_res)
 | 
						|
{
 | 
						|
    AxisInfoPtr ax;
 | 
						|
 | 
						|
    if (!dev || !dev->valuator || minval > maxval)
 | 
						|
        return;
 | 
						|
    if (axnum >= dev->valuator->numAxes)
 | 
						|
        return;
 | 
						|
 | 
						|
    ax = dev->valuator->axes + axnum;
 | 
						|
 | 
						|
    ax->min_value = minval;
 | 
						|
    ax->max_value = maxval;
 | 
						|
    ax->resolution = resolution;
 | 
						|
    ax->min_resolution = min_res;
 | 
						|
    ax->max_resolution = max_res;
 | 
						|
    ax->label = label;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
 | 
						|
		     ButtonClassPtr b, ValuatorClassPtr v, int first)
 | 
						|
{
 | 
						|
    ev->type = DeviceStateNotify;
 | 
						|
    ev->deviceid = dev->id;
 | 
						|
    ev->time = currentTime.milliseconds;
 | 
						|
    ev->classes_reported = 0;
 | 
						|
    ev->num_keys = 0;
 | 
						|
    ev->num_buttons = 0;
 | 
						|
    ev->num_valuators = 0;
 | 
						|
 | 
						|
    if (b) {
 | 
						|
	ev->classes_reported |= (1 << ButtonClass);
 | 
						|
	ev->num_buttons = b->numButtons;
 | 
						|
	memcpy((char*)ev->buttons, (char*)b->down, 4);
 | 
						|
    } else if (k) {
 | 
						|
	ev->classes_reported |= (1 << KeyClass);
 | 
						|
	ev->num_keys = k->xkbInfo->desc->max_key_code -
 | 
						|
                       k->xkbInfo->desc->min_key_code;
 | 
						|
	memmove((char *)&ev->keys[0], (char *)k->down, 4);
 | 
						|
    }
 | 
						|
    if (v) {
 | 
						|
	int nval = v->numAxes - first;
 | 
						|
 | 
						|
	ev->classes_reported |= (1 << ValuatorClass);
 | 
						|
	ev->classes_reported |= (dev->valuator->mode << ModeBitsShift);
 | 
						|
	ev->num_valuators = nval < 3 ? nval : 3;
 | 
						|
	switch (ev->num_valuators) {
 | 
						|
	case 3:
 | 
						|
	    ev->valuator2 = v->axisVal[first + 2];
 | 
						|
	case 2:
 | 
						|
	    ev->valuator1 = v->axisVal[first + 1];
 | 
						|
	case 1:
 | 
						|
	    ev->valuator0 = v->axisVal[first];
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
 | 
						|
		  int first)
 | 
						|
{
 | 
						|
    int nval = v->numAxes - first;
 | 
						|
 | 
						|
    ev->type = DeviceValuator;
 | 
						|
    ev->deviceid = dev->id;
 | 
						|
    ev->num_valuators = nval < 3 ? nval : 3;
 | 
						|
    ev->first_valuator = first;
 | 
						|
    switch (ev->num_valuators) {
 | 
						|
    case 3:
 | 
						|
	ev->valuator2 = v->axisVal[first + 2];
 | 
						|
    case 2:
 | 
						|
	ev->valuator1 = v->axisVal[first + 1];
 | 
						|
    case 1:
 | 
						|
	ev->valuator0 = v->axisVal[first];
 | 
						|
	break;
 | 
						|
    }
 | 
						|
    first += ev->num_valuators;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
 | 
						|
		 WindowPtr pWin)
 | 
						|
{
 | 
						|
    deviceFocus event;
 | 
						|
    xXIFocusInEvent *xi2event;
 | 
						|
    DeviceIntPtr mouse;
 | 
						|
    int btlen, len, i;
 | 
						|
 | 
						|
    mouse = (IsMaster(dev) || dev->u.master) ? GetMaster(dev, MASTER_POINTER) : dev;
 | 
						|
 | 
						|
    /* XI 2 event */
 | 
						|
    btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
 | 
						|
    btlen = bytes_to_int32(btlen);
 | 
						|
    len = sizeof(xXIFocusInEvent) + btlen * 4;
 | 
						|
 | 
						|
    xi2event = calloc(1, len);
 | 
						|
    xi2event->type         = GenericEvent;
 | 
						|
    xi2event->extension    = IReqCode;
 | 
						|
    xi2event->evtype       = type;
 | 
						|
    xi2event->length       = bytes_to_int32(len - sizeof(xEvent));
 | 
						|
    xi2event->buttons_len  = btlen;
 | 
						|
    xi2event->detail       = detail;
 | 
						|
    xi2event->time         = currentTime.milliseconds;
 | 
						|
    xi2event->deviceid     = dev->id;
 | 
						|
    xi2event->sourceid     = dev->id; /* a device doesn't change focus by itself */
 | 
						|
    xi2event->mode         = mode;
 | 
						|
    xi2event->root_x       = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
 | 
						|
    xi2event->root_y       = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
 | 
						|
 | 
						|
    for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
 | 
						|
        if (BitIsOn(mouse->button->down, i))
 | 
						|
            SetBit(&xi2event[1], i);
 | 
						|
 | 
						|
    if (dev->key)
 | 
						|
    {
 | 
						|
        xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods;
 | 
						|
        xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods;
 | 
						|
        xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods;
 | 
						|
        xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods;
 | 
						|
 | 
						|
        xi2event->group.base_group = dev->key->xkbInfo->state.base_group;
 | 
						|
        xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group;
 | 
						|
        xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group;
 | 
						|
        xi2event->group.effective_group = dev->key->xkbInfo->state.group;
 | 
						|
    }
 | 
						|
 | 
						|
    FixUpEventFromWindow(dev, (xEvent*)xi2event, pWin, None, FALSE);
 | 
						|
 | 
						|
    DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
 | 
						|
                          GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
 | 
						|
 | 
						|
    free(xi2event);
 | 
						|
 | 
						|
    /* XI 1.x event */
 | 
						|
    event.deviceid = dev->id;
 | 
						|
    event.mode = mode;
 | 
						|
    event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
 | 
						|
    event.detail = detail;
 | 
						|
    event.window = pWin->drawable.id;
 | 
						|
    event.time = currentTime.milliseconds;
 | 
						|
 | 
						|
    DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
 | 
						|
				DeviceFocusChangeMask, NullGrab);
 | 
						|
 | 
						|
    if ((type == DeviceFocusIn) &&
 | 
						|
	(wOtherInputMasks(pWin)) &&
 | 
						|
	(wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
 | 
						|
    {
 | 
						|
	int evcount = 1;
 | 
						|
	deviceStateNotify *ev, *sev;
 | 
						|
	deviceKeyStateNotify *kev;
 | 
						|
	deviceButtonStateNotify *bev;
 | 
						|
 | 
						|
	KeyClassPtr k;
 | 
						|
	ButtonClassPtr b;
 | 
						|
	ValuatorClassPtr v;
 | 
						|
	int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
 | 
						|
 | 
						|
	if ((b = dev->button) != NULL) {
 | 
						|
	    nbuttons = b->numButtons;
 | 
						|
	    if (nbuttons > 32)
 | 
						|
		evcount++;
 | 
						|
	}
 | 
						|
	if ((k = dev->key) != NULL) {
 | 
						|
	    nkeys = k->xkbInfo->desc->max_key_code -
 | 
						|
                    k->xkbInfo->desc->min_key_code;
 | 
						|
	    if (nkeys > 32)
 | 
						|
		evcount++;
 | 
						|
	    if (nbuttons > 0) {
 | 
						|
		evcount++;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	if ((v = dev->valuator) != NULL) {
 | 
						|
	    nval = v->numAxes;
 | 
						|
 | 
						|
	    if (nval > 3)
 | 
						|
		evcount++;
 | 
						|
	    if (nval > 6) {
 | 
						|
		if (!(k && b))
 | 
						|
		    evcount++;
 | 
						|
		if (nval > 9)
 | 
						|
		    evcount += ((nval - 7) / 3);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
	sev = ev = (deviceStateNotify *) malloc(evcount * sizeof(xEvent));
 | 
						|
	FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
 | 
						|
 | 
						|
	if (b != NULL) {
 | 
						|
	    FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
 | 
						|
	    first += 3;
 | 
						|
	    nval -= 3;
 | 
						|
	    if (nbuttons > 32) {
 | 
						|
		(ev - 1)->deviceid |= MORE_EVENTS;
 | 
						|
		bev = (deviceButtonStateNotify *) ev++;
 | 
						|
		bev->type = DeviceButtonStateNotify;
 | 
						|
		bev->deviceid = dev->id;
 | 
						|
		memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
 | 
						|
	    }
 | 
						|
	    if (nval > 0) {
 | 
						|
		(ev - 1)->deviceid |= MORE_EVENTS;
 | 
						|
		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
 | 
						|
		first += 3;
 | 
						|
		nval -= 3;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
	if (k != NULL) {
 | 
						|
	    FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
 | 
						|
	    first += 3;
 | 
						|
	    nval -= 3;
 | 
						|
	    if (nkeys > 32) {
 | 
						|
		(ev - 1)->deviceid |= MORE_EVENTS;
 | 
						|
		kev = (deviceKeyStateNotify *) ev++;
 | 
						|
		kev->type = DeviceKeyStateNotify;
 | 
						|
		kev->deviceid = dev->id;
 | 
						|
		memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
 | 
						|
	    }
 | 
						|
	    if (nval > 0) {
 | 
						|
		(ev - 1)->deviceid |= MORE_EVENTS;
 | 
						|
		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
 | 
						|
		first += 3;
 | 
						|
		nval -= 3;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
	while (nval > 0) {
 | 
						|
	    FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
 | 
						|
	    first += 3;
 | 
						|
	    nval -= 3;
 | 
						|
	    if (nval > 0) {
 | 
						|
		(ev - 1)->deviceid |= MORE_EVENTS;
 | 
						|
		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
 | 
						|
		first += 3;
 | 
						|
		nval -= 3;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
	DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
 | 
						|
				    DeviceStateNotifyMask, NullGrab);
 | 
						|
	free(sev);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
CheckGrabValues(ClientPtr client, GrabParameters* param)
 | 
						|
{
 | 
						|
    if (param->grabtype != GRABTYPE_CORE &&
 | 
						|
        param->grabtype != GRABTYPE_XI &&
 | 
						|
        param->grabtype != GRABTYPE_XI2)
 | 
						|
    {
 | 
						|
        ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
 | 
						|
        return BadImplementation;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((param->this_device_mode != GrabModeSync) &&
 | 
						|
	(param->this_device_mode != GrabModeAsync)) {
 | 
						|
	client->errorValue = param->this_device_mode;
 | 
						|
	return BadValue;
 | 
						|
    }
 | 
						|
    if ((param->other_devices_mode != GrabModeSync) &&
 | 
						|
	(param->other_devices_mode != GrabModeAsync)) {
 | 
						|
	client->errorValue = param->other_devices_mode;
 | 
						|
	return BadValue;
 | 
						|
    }
 | 
						|
 | 
						|
    if (param->grabtype != GRABTYPE_XI2 && (param->modifiers != AnyModifier) &&
 | 
						|
        (param->modifiers & ~AllModifiersMask)) {
 | 
						|
	client->errorValue = param->modifiers;
 | 
						|
	return BadValue;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
 | 
						|
	client->errorValue = param->ownerEvents;
 | 
						|
	return BadValue;
 | 
						|
    }
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
 | 
						|
           int button, GrabParameters *param, GrabType grabtype,
 | 
						|
	   GrabMask *mask)
 | 
						|
{
 | 
						|
    WindowPtr pWin, confineTo;
 | 
						|
    CursorPtr cursor;
 | 
						|
    GrabPtr grab;
 | 
						|
    int rc, type = -1;
 | 
						|
    Mask access_mode = DixGrabAccess;
 | 
						|
 | 
						|
    rc = CheckGrabValues(client, param);
 | 
						|
    if (rc != Success)
 | 
						|
	return rc;
 | 
						|
    if (param->confineTo == None)
 | 
						|
	confineTo = NullWindow;
 | 
						|
    else {
 | 
						|
	rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess);
 | 
						|
	if (rc != Success)
 | 
						|
	    return rc;
 | 
						|
    }
 | 
						|
    if (param->cursor == None)
 | 
						|
	cursor = NullCursor;
 | 
						|
    else {
 | 
						|
	rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
 | 
						|
				     RT_CURSOR, client, DixUseAccess);
 | 
						|
	if (rc != Success)
 | 
						|
	{
 | 
						|
	    client->errorValue = param->cursor;
 | 
						|
	    return rc;
 | 
						|
	}
 | 
						|
	access_mode |= DixForceAccess;
 | 
						|
    }
 | 
						|
    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
 | 
						|
	access_mode |= DixFreezeAccess;
 | 
						|
    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
 | 
						|
    if (rc != Success)
 | 
						|
	return rc;
 | 
						|
    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
 | 
						|
    if (rc != Success)
 | 
						|
	return rc;
 | 
						|
 | 
						|
    if (grabtype == GRABTYPE_XI)
 | 
						|
        type = DeviceButtonPress;
 | 
						|
    else if (grabtype == GRABTYPE_XI2)
 | 
						|
        type = XI_ButtonPress;
 | 
						|
 | 
						|
    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
 | 
						|
                      mask, param, type, button, confineTo, cursor);
 | 
						|
    if (!grab)
 | 
						|
	return BadAlloc;
 | 
						|
    return AddPassiveGrabToList(client, grab);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Grab the given key. If grabtype is GRABTYPE_XI, the key is a keycode. If
 | 
						|
 * grabtype is GRABTYPE_XI2, the key is a keysym.
 | 
						|
 */
 | 
						|
int
 | 
						|
GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
 | 
						|
        int key, GrabParameters *param, GrabType grabtype, GrabMask *mask)
 | 
						|
{
 | 
						|
    WindowPtr pWin;
 | 
						|
    GrabPtr grab;
 | 
						|
    KeyClassPtr k = dev->key;
 | 
						|
    Mask access_mode = DixGrabAccess;
 | 
						|
    int rc, type = -1;
 | 
						|
 | 
						|
    rc = CheckGrabValues(client, param);
 | 
						|
    if (rc != Success)
 | 
						|
        return rc;
 | 
						|
    if (k == NULL)
 | 
						|
	return BadMatch;
 | 
						|
    if (grabtype == GRABTYPE_XI)
 | 
						|
    {
 | 
						|
        if ((key > k->xkbInfo->desc->max_key_code ||
 | 
						|
                    key < k->xkbInfo->desc->min_key_code)
 | 
						|
                && (key != AnyKey)) {
 | 
						|
            client->errorValue = key;
 | 
						|
            return BadValue;
 | 
						|
        }
 | 
						|
        type = DeviceKeyPress;
 | 
						|
    } else if (grabtype == GRABTYPE_XI2)
 | 
						|
        type = XI_KeyPress;
 | 
						|
 | 
						|
    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
 | 
						|
    if (rc != Success)
 | 
						|
	return rc;
 | 
						|
    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
 | 
						|
	access_mode |= DixFreezeAccess;
 | 
						|
    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
 | 
						|
    if (rc != Success)
 | 
						|
	return rc;
 | 
						|
 | 
						|
    grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
 | 
						|
                      mask, param, type, key, NULL, NULL);
 | 
						|
    if (!grab)
 | 
						|
	return BadAlloc;
 | 
						|
    return AddPassiveGrabToList(client, grab);
 | 
						|
}
 | 
						|
 | 
						|
/* Enter/FocusIn grab */
 | 
						|
int
 | 
						|
GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
 | 
						|
           GrabParameters *param, GrabMask *mask)
 | 
						|
{
 | 
						|
    WindowPtr pWin;
 | 
						|
    CursorPtr cursor;
 | 
						|
    GrabPtr grab;
 | 
						|
    Mask access_mode = DixGrabAccess;
 | 
						|
    int rc;
 | 
						|
 | 
						|
    rc = CheckGrabValues(client, param);
 | 
						|
    if (rc != Success)
 | 
						|
        return rc;
 | 
						|
 | 
						|
    rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
 | 
						|
    if (rc != Success)
 | 
						|
	return rc;
 | 
						|
    if (param->cursor == None)
 | 
						|
	cursor = NullCursor;
 | 
						|
    else {
 | 
						|
	rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
 | 
						|
				     RT_CURSOR, client, DixUseAccess);
 | 
						|
	if (rc != Success)
 | 
						|
	{
 | 
						|
	    client->errorValue = param->cursor;
 | 
						|
	    return rc;
 | 
						|
	}
 | 
						|
	access_mode |= DixForceAccess;
 | 
						|
    }
 | 
						|
    if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
 | 
						|
	access_mode |= DixFreezeAccess;
 | 
						|
    rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
 | 
						|
    if (rc != Success)
 | 
						|
	return rc;
 | 
						|
 | 
						|
    grab = CreateGrab(client->index, dev, dev, pWin, GRABTYPE_XI2,
 | 
						|
                      mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn,
 | 
						|
                      0, NULL, cursor);
 | 
						|
 | 
						|
    if (!grab)
 | 
						|
        return BadAlloc;
 | 
						|
 | 
						|
    return AddPassiveGrabToList(client, grab);
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
 | 
						|
		Mask mask, Mask exclusivemasks)
 | 
						|
{
 | 
						|
    int mskidx = dev->id;
 | 
						|
    int i, ret;
 | 
						|
    Mask check;
 | 
						|
    InputClientsPtr others;
 | 
						|
 | 
						|
    check = (mask & exclusivemasks);
 | 
						|
    if (wOtherInputMasks(pWin)) {
 | 
						|
	if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {	/* It is illegal for two different
 | 
						|
									 * clients to select on any of the
 | 
						|
									 * events for maskcheck. However,
 | 
						|
									 * it is OK, for some client to
 | 
						|
									 * continue selecting on one of those
 | 
						|
									 * events.  */
 | 
						|
	    for (others = wOtherInputMasks(pWin)->inputClients; others;
 | 
						|
		 others = others->next) {
 | 
						|
		if (!SameClient(others, client) && (check &
 | 
						|
						    others->mask[mskidx]))
 | 
						|
		    return BadAccess;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	for (others = wOtherInputMasks(pWin)->inputClients; others;
 | 
						|
	     others = others->next) {
 | 
						|
	    if (SameClient(others, client)) {
 | 
						|
		check = others->mask[mskidx];
 | 
						|
		others->mask[mskidx] = mask;
 | 
						|
		if (mask == 0) {
 | 
						|
		    for (i = 0; i < EMASKSIZE; i++)
 | 
						|
			if (i != mskidx && others->mask[i] != 0)
 | 
						|
			    break;
 | 
						|
		    if (i == EMASKSIZE) {
 | 
						|
			RecalculateDeviceDeliverableEvents(pWin);
 | 
						|
			if (ShouldFreeInputMasks(pWin, FALSE))
 | 
						|
			    FreeResource(others->resource, RT_NONE);
 | 
						|
			return Success;
 | 
						|
		    }
 | 
						|
		}
 | 
						|
		goto maskSet;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
    check = 0;
 | 
						|
    if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
 | 
						|
	return ret;
 | 
						|
  maskSet:
 | 
						|
    if (dev->valuator)
 | 
						|
	if ((dev->valuator->motionHintWindow == pWin) &&
 | 
						|
	    (mask & DevicePointerMotionHintMask) &&
 | 
						|
	    !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
 | 
						|
	    dev->valuator->motionHintWindow = NullWindow;
 | 
						|
    RecalculateDeviceDeliverableEvents(pWin);
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
 | 
						|
{
 | 
						|
    InputClientsPtr others;
 | 
						|
 | 
						|
    if (!pWin->optional && !MakeWindowOptional(pWin))
 | 
						|
	return BadAlloc;
 | 
						|
    others = calloc(1, sizeof(InputClients));
 | 
						|
    if (!others)
 | 
						|
	return BadAlloc;
 | 
						|
    if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
 | 
						|
	return BadAlloc;
 | 
						|
    others->mask[mskidx] = mask;
 | 
						|
    others->resource = FakeClientID(client->index);
 | 
						|
    others->next = pWin->optional->inputMasks->inputClients;
 | 
						|
    pWin->optional->inputMasks->inputClients = others;
 | 
						|
    if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
 | 
						|
	return BadAlloc;
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
MakeInputMasks(WindowPtr pWin)
 | 
						|
{
 | 
						|
    struct _OtherInputMasks *imasks;
 | 
						|
 | 
						|
    imasks = calloc(1, sizeof(struct _OtherInputMasks));
 | 
						|
    if (!imasks)
 | 
						|
	return FALSE;
 | 
						|
    pWin->optional->inputMasks = imasks;
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
RecalculateDeviceDeliverableEvents(WindowPtr pWin)
 | 
						|
{
 | 
						|
    InputClientsPtr others;
 | 
						|
    struct _OtherInputMasks *inputMasks;	/* default: NULL */
 | 
						|
    WindowPtr pChild, tmp;
 | 
						|
    int i, j;
 | 
						|
 | 
						|
    pChild = pWin;
 | 
						|
    while (1) {
 | 
						|
	if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
 | 
						|
            for (i = 0; i < EMASKSIZE; i++)
 | 
						|
                memset(inputMasks->xi2mask[i], 0, sizeof(inputMasks->xi2mask[i]));
 | 
						|
	    for (others = inputMasks->inputClients; others;
 | 
						|
		 others = others->next) {
 | 
						|
		for (i = 0; i < EMASKSIZE; i++)
 | 
						|
		    inputMasks->inputEvents[i] |= others->mask[i];
 | 
						|
                for (i = 0; i < EMASKSIZE; i++)
 | 
						|
                    for (j = 0; j < XI2MASKSIZE; j++)
 | 
						|
                        inputMasks->xi2mask[i][j] |= others->xi2mask[i][j];
 | 
						|
	    }
 | 
						|
	    for (i = 0; i < EMASKSIZE; i++)
 | 
						|
		inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
 | 
						|
	    for (tmp = pChild->parent; tmp; tmp = tmp->parent)
 | 
						|
		if (wOtherInputMasks(tmp))
 | 
						|
		    for (i = 0; i < EMASKSIZE; i++)
 | 
						|
			inputMasks->deliverableEvents[i] |=
 | 
						|
			    (wOtherInputMasks(tmp)->deliverableEvents[i]
 | 
						|
			     & ~inputMasks->
 | 
						|
			     dontPropagateMask[i] & PropagateMask[i]);
 | 
						|
	}
 | 
						|
	if (pChild->firstChild) {
 | 
						|
	    pChild = pChild->firstChild;
 | 
						|
	    continue;
 | 
						|
	}
 | 
						|
	while (!pChild->nextSib && (pChild != pWin))
 | 
						|
	    pChild = pChild->parent;
 | 
						|
	if (pChild == pWin)
 | 
						|
	    break;
 | 
						|
	pChild = pChild->nextSib;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
InputClientGone(WindowPtr pWin, XID id)
 | 
						|
{
 | 
						|
    InputClientsPtr other, prev;
 | 
						|
 | 
						|
    if (!wOtherInputMasks(pWin))
 | 
						|
	return Success;
 | 
						|
    prev = 0;
 | 
						|
    for (other = wOtherInputMasks(pWin)->inputClients; other;
 | 
						|
	 other = other->next) {
 | 
						|
	if (other->resource == id) {
 | 
						|
	    if (prev) {
 | 
						|
		prev->next = other->next;
 | 
						|
		free(other);
 | 
						|
	    } else if (!(other->next)) {
 | 
						|
		if (ShouldFreeInputMasks(pWin, TRUE)) {
 | 
						|
		    wOtherInputMasks(pWin)->inputClients = other->next;
 | 
						|
		    free(wOtherInputMasks(pWin));
 | 
						|
		    pWin->optional->inputMasks = (OtherInputMasks *) NULL;
 | 
						|
		    CheckWindowOptionalNeed(pWin);
 | 
						|
		    free(other);
 | 
						|
		} else {
 | 
						|
		    other->resource = FakeClientID(0);
 | 
						|
		    if (!AddResource(other->resource, RT_INPUTCLIENT,
 | 
						|
				     (pointer) pWin))
 | 
						|
			return BadAlloc;
 | 
						|
		}
 | 
						|
	    } else {
 | 
						|
		wOtherInputMasks(pWin)->inputClients = other->next;
 | 
						|
		free(other);
 | 
						|
	    }
 | 
						|
	    RecalculateDeviceDeliverableEvents(pWin);
 | 
						|
	    return Success;
 | 
						|
	}
 | 
						|
	prev = other;
 | 
						|
    }
 | 
						|
    FatalError("client not on device event list");
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
 | 
						|
	  xEvent * ev, Mask mask, int count)
 | 
						|
{
 | 
						|
    WindowPtr pWin;
 | 
						|
    WindowPtr effectiveFocus = NullWindow;	/* only set if dest==InputFocus */
 | 
						|
    WindowPtr spriteWin = GetSpriteWindow(d);
 | 
						|
 | 
						|
    if (dest == PointerWindow)
 | 
						|
	pWin = spriteWin;
 | 
						|
    else if (dest == InputFocus) {
 | 
						|
	WindowPtr inputFocus;
 | 
						|
 | 
						|
	if (!d->focus)
 | 
						|
	    inputFocus = spriteWin;
 | 
						|
	else
 | 
						|
	    inputFocus = d->focus->win;
 | 
						|
 | 
						|
	if (inputFocus == FollowKeyboardWin)
 | 
						|
	    inputFocus = inputInfo.keyboard->focus->win;
 | 
						|
 | 
						|
	if (inputFocus == NoneWin)
 | 
						|
	    return Success;
 | 
						|
 | 
						|
	/* If the input focus is PointerRootWin, send the event to where
 | 
						|
	 * the pointer is if possible, then perhaps propogate up to root. */
 | 
						|
	if (inputFocus == PointerRootWin)
 | 
						|
	    inputFocus = GetCurrentRootWindow(d);
 | 
						|
 | 
						|
	if (IsParent(inputFocus, spriteWin)) {
 | 
						|
	    effectiveFocus = inputFocus;
 | 
						|
	    pWin = spriteWin;
 | 
						|
	} else
 | 
						|
	    effectiveFocus = pWin = inputFocus;
 | 
						|
    } else
 | 
						|
	dixLookupWindow(&pWin, dest, client, DixSendAccess);
 | 
						|
    if (!pWin)
 | 
						|
	return BadWindow;
 | 
						|
    if ((propagate != xFalse) && (propagate != xTrue)) {
 | 
						|
	client->errorValue = propagate;
 | 
						|
	return BadValue;
 | 
						|
    }
 | 
						|
    ev->u.u.type |= 0x80;
 | 
						|
    if (propagate) {
 | 
						|
	for (; pWin; pWin = pWin->parent) {
 | 
						|
	    if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
 | 
						|
		return Success;
 | 
						|
	    if (pWin == effectiveFocus)
 | 
						|
		return Success;
 | 
						|
	    if (wOtherInputMasks(pWin))
 | 
						|
		mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
 | 
						|
	    if (!mask)
 | 
						|
		break;
 | 
						|
	}
 | 
						|
    } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
 | 
						|
	DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    ButtonClassPtr b = dev->button;
 | 
						|
 | 
						|
    if (b == NULL)
 | 
						|
	return BadMatch;
 | 
						|
 | 
						|
    if (nElts != b->numButtons) {
 | 
						|
	client->errorValue = nElts;
 | 
						|
	return BadValue;
 | 
						|
    }
 | 
						|
    if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
 | 
						|
	return BadValue;
 | 
						|
    for (i = 0; i < nElts; i++)
 | 
						|
	if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
 | 
						|
	    return MappingBusy;
 | 
						|
    for (i = 0; i < nElts; i++)
 | 
						|
	b->map[i + 1] = map[i];
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
ChangeKeyMapping(ClientPtr client,
 | 
						|
		 DeviceIntPtr dev,
 | 
						|
		 unsigned len,
 | 
						|
		 int type,
 | 
						|
		 KeyCode firstKeyCode,
 | 
						|
		 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
 | 
						|
{
 | 
						|
    KeySymsRec keysyms;
 | 
						|
    KeyClassPtr k = dev->key;
 | 
						|
 | 
						|
    if (k == NULL)
 | 
						|
	return BadMatch;
 | 
						|
 | 
						|
    if (len != (keyCodes * keySymsPerKeyCode))
 | 
						|
	return BadLength;
 | 
						|
 | 
						|
    if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
 | 
						|
	(firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
 | 
						|
	client->errorValue = firstKeyCode;
 | 
						|
	return BadValue;
 | 
						|
    }
 | 
						|
    if (keySymsPerKeyCode == 0) {
 | 
						|
	client->errorValue = 0;
 | 
						|
	return BadValue;
 | 
						|
    }
 | 
						|
    keysyms.minKeyCode = firstKeyCode;
 | 
						|
    keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
 | 
						|
    keysyms.mapWidth = keySymsPerKeyCode;
 | 
						|
    keysyms.map = map;
 | 
						|
 | 
						|
    XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
 | 
						|
                          serverClient);
 | 
						|
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
 | 
						|
{
 | 
						|
    WindowPtr parent;
 | 
						|
 | 
						|
    /* Deactivate any grabs performed on this window, before making
 | 
						|
     * any input focus changes.
 | 
						|
     * Deactivating a device grab should cause focus events. */
 | 
						|
 | 
						|
    if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
 | 
						|
	(*dev->deviceGrab.DeactivateGrab) (dev);
 | 
						|
 | 
						|
    /* If the focus window is a root window (ie. has no parent)
 | 
						|
     * then don't delete the focus from it. */
 | 
						|
 | 
						|
    if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
 | 
						|
	int focusEventMode = NotifyNormal;
 | 
						|
 | 
						|
	/* If a grab is in progress, then alter the mode of focus events. */
 | 
						|
 | 
						|
	if (dev->deviceGrab.grab)
 | 
						|
	    focusEventMode = NotifyWhileGrabbed;
 | 
						|
 | 
						|
	switch (dev->focus->revert) {
 | 
						|
	case RevertToNone:
 | 
						|
	    if (!ActivateFocusInGrab(dev, pWin, NoneWin))
 | 
						|
		DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
 | 
						|
	    dev->focus->win = NoneWin;
 | 
						|
	    dev->focus->traceGood = 0;
 | 
						|
	    break;
 | 
						|
	case RevertToParent:
 | 
						|
	    parent = pWin;
 | 
						|
	    do {
 | 
						|
		parent = parent->parent;
 | 
						|
		dev->focus->traceGood--;
 | 
						|
	    }
 | 
						|
	    while (!parent->realized);
 | 
						|
	    if (!ActivateFocusInGrab(dev, pWin, parent))
 | 
						|
		DoFocusEvents(dev, pWin, parent, focusEventMode);
 | 
						|
	    dev->focus->win = parent;
 | 
						|
	    dev->focus->revert = RevertToNone;
 | 
						|
	    break;
 | 
						|
	case RevertToPointerRoot:
 | 
						|
	    if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
 | 
						|
		DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
 | 
						|
	    dev->focus->win = PointerRootWin;
 | 
						|
	    dev->focus->traceGood = 0;
 | 
						|
	    break;
 | 
						|
	case RevertToFollowKeyboard:
 | 
						|
            {
 | 
						|
                DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
 | 
						|
                if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
 | 
						|
                    kbd = inputInfo.keyboard;
 | 
						|
	    if (kbd->focus->win) {
 | 
						|
		if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
 | 
						|
		    DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
 | 
						|
		dev->focus->win = FollowKeyboardWin;
 | 
						|
		dev->focus->traceGood = 0;
 | 
						|
	    } else {
 | 
						|
                if (!ActivateFocusInGrab(dev, pWin, NoneWin))
 | 
						|
                    DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
 | 
						|
		dev->focus->win = NoneWin;
 | 
						|
		dev->focus->traceGood = 0;
 | 
						|
	    }
 | 
						|
            }
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    if (dev->valuator)
 | 
						|
	if (dev->valuator->motionHintWindow == pWin)
 | 
						|
	    dev->valuator->motionHintWindow = NullWindow;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    DeviceIntPtr dev;
 | 
						|
    InputClientsPtr ic;
 | 
						|
    struct _OtherInputMasks *inputMasks;
 | 
						|
 | 
						|
    for (dev = inputInfo.devices; dev; dev = dev->next) {
 | 
						|
	DeleteDeviceFromAnyExtEvents(pWin, dev);
 | 
						|
    }
 | 
						|
 | 
						|
    for (dev = inputInfo.off_devices; dev; dev = dev->next)
 | 
						|
	DeleteDeviceFromAnyExtEvents(pWin, dev);
 | 
						|
 | 
						|
    if (freeResources)
 | 
						|
	while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
 | 
						|
	    ic = inputMasks->inputClients;
 | 
						|
	    for (i = 0; i < EMASKSIZE; i++)
 | 
						|
		inputMasks->dontPropagateMask[i] = 0;
 | 
						|
	    FreeResource(ic->resource, RT_NONE);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
 | 
						|
{
 | 
						|
    DeviceIntPtr dev;
 | 
						|
 | 
						|
    dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
 | 
						|
		    DixReadAccess);
 | 
						|
    if (!dev)
 | 
						|
        return 0;
 | 
						|
 | 
						|
    if (pEvents->type == DeviceMotionNotify) {
 | 
						|
	if (mask & DevicePointerMotionHintMask) {
 | 
						|
	    if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
 | 
						|
		return 1;	/* don't send, but pretend we did */
 | 
						|
	    }
 | 
						|
	    pEvents->detail = NotifyHint;
 | 
						|
	} else {
 | 
						|
	    pEvents->detail = NotifyNormal;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
 | 
						|
			     deviceKeyButtonPointer * xE, GrabPtr grab,
 | 
						|
			     ClientPtr client, Mask deliveryMask)
 | 
						|
{
 | 
						|
    DeviceIntPtr dev;
 | 
						|
 | 
						|
    dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
 | 
						|
		    DixGrabAccess);
 | 
						|
    if (!dev)
 | 
						|
        return;
 | 
						|
 | 
						|
    if (type == DeviceMotionNotify)
 | 
						|
	dev->valuator->motionHintWindow = pWin;
 | 
						|
    else if ((type == DeviceButtonPress) && (!grab) &&
 | 
						|
	     (deliveryMask & DeviceButtonGrabMask)) {
 | 
						|
	GrabRec tempGrab;
 | 
						|
 | 
						|
	tempGrab.device = dev;
 | 
						|
	tempGrab.resource = client->clientAsMask;
 | 
						|
	tempGrab.window = pWin;
 | 
						|
	tempGrab.ownerEvents =
 | 
						|
	    (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
 | 
						|
	tempGrab.eventMask = deliveryMask;
 | 
						|
	tempGrab.keyboardMode = GrabModeAsync;
 | 
						|
	tempGrab.pointerMode = GrabModeAsync;
 | 
						|
	tempGrab.confineTo = NullWindow;
 | 
						|
	tempGrab.cursor = NullCursor;
 | 
						|
        tempGrab.next = NULL;
 | 
						|
	(*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static Mask
 | 
						|
DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
 | 
						|
{
 | 
						|
    InputClientsPtr other;
 | 
						|
 | 
						|
    if (!wOtherInputMasks(pWin))
 | 
						|
	return 0;
 | 
						|
    for (other = wOtherInputMasks(pWin)->inputClients; other;
 | 
						|
	 other = other->next) {
 | 
						|
	if (SameClient(other, client))
 | 
						|
	    return other->mask[dev->id];
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
 | 
						|
{
 | 
						|
    WindowPtr pWin;
 | 
						|
    GrabPtr grab = dev->deviceGrab.grab;
 | 
						|
 | 
						|
    pWin = dev->valuator->motionHintWindow;
 | 
						|
 | 
						|
    if ((grab && SameClient(grab, client) &&
 | 
						|
	 ((grab->eventMask & DevicePointerMotionHintMask) ||
 | 
						|
	  (grab->ownerEvents &&
 | 
						|
	   (DeviceEventMaskForClient(dev, pWin, client) &
 | 
						|
	    DevicePointerMotionHintMask)))) ||
 | 
						|
	(!grab &&
 | 
						|
	 (DeviceEventMaskForClient(dev, pWin, client) &
 | 
						|
	  DevicePointerMotionHintMask)))
 | 
						|
	dev->valuator->motionHintWindow = NullWindow;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
 | 
						|
			     int maskndx)
 | 
						|
{
 | 
						|
    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
 | 
						|
 | 
						|
    if (mask & ~PropagateMask[maskndx]) {
 | 
						|
	client->errorValue = mask;
 | 
						|
	return BadValue;
 | 
						|
    }
 | 
						|
 | 
						|
    if (mask == 0) {
 | 
						|
	if (inputMasks)
 | 
						|
	    inputMasks->dontPropagateMask[maskndx] = mask;
 | 
						|
    } else {
 | 
						|
	if (!inputMasks)
 | 
						|
	    AddExtensionClient(pWin, client, 0, 0);
 | 
						|
	inputMasks = wOtherInputMasks(pWin);
 | 
						|
	inputMasks->dontPropagateMask[maskndx] = mask;
 | 
						|
    }
 | 
						|
    RecalculateDeviceDeliverableEvents(pWin);
 | 
						|
    if (ShouldFreeInputMasks(pWin, FALSE))
 | 
						|
	FreeResource(inputMasks->inputClients->resource, RT_NONE);
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    Mask allInputEventMasks = 0;
 | 
						|
    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
 | 
						|
 | 
						|
    for (i = 0; i < EMASKSIZE; i++)
 | 
						|
	allInputEventMasks |= inputMasks->dontPropagateMask[i];
 | 
						|
    if (!ignoreSelectedEvents)
 | 
						|
	for (i = 0; i < EMASKSIZE; i++)
 | 
						|
	    allInputEventMasks |= inputMasks->inputEvents[i];
 | 
						|
    if (allInputEventMasks == 0)
 | 
						|
	return TRUE;
 | 
						|
    else
 | 
						|
	return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
 *
 | 
						|
 * Walk through the window tree, finding all clients that want to know
 | 
						|
 * about the Event.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
static void
 | 
						|
FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
 | 
						|
                       xEvent * ev, int count)
 | 
						|
{
 | 
						|
    WindowPtr p2;
 | 
						|
 | 
						|
    while (p1) {
 | 
						|
        p2 = p1->firstChild;
 | 
						|
        DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
 | 
						|
        FindInterestedChildren(dev, p2, mask, ev, count);
 | 
						|
        p1 = p1->nextSib;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
 *
 | 
						|
 * Send an event to interested clients in all windows on all screens.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
void
 | 
						|
SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    WindowPtr pWin, p1;
 | 
						|
 | 
						|
    for (i = 0; i < screenInfo.numScreens; i++) {
 | 
						|
        pWin = screenInfo.screens[i]->root;
 | 
						|
        if (!pWin)
 | 
						|
            continue;
 | 
						|
        DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
 | 
						|
        p1 = pWin->firstChild;
 | 
						|
        FindInterestedChildren(dev, p1, mask, ev, count);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Set the XI2 mask for the given client on the given window.
 | 
						|
 * @param dev The device to set the mask for.
 | 
						|
 * @param win The window to set the mask on.
 | 
						|
 * @param client The client setting the mask.
 | 
						|
 * @param len Number of bytes in mask.
 | 
						|
 * @param mask Event mask in the form of (1 << eventtype)
 | 
						|
 */
 | 
						|
int
 | 
						|
XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
 | 
						|
               unsigned int len, unsigned char* mask)
 | 
						|
{
 | 
						|
    OtherInputMasks *masks;
 | 
						|
    InputClientsPtr others = NULL;
 | 
						|
 | 
						|
    masks = wOtherInputMasks(win);
 | 
						|
    if (masks)
 | 
						|
    {
 | 
						|
	for (others = wOtherInputMasks(win)->inputClients; others;
 | 
						|
	     others = others->next) {
 | 
						|
	    if (SameClient(others, client)) {
 | 
						|
                memset(others->xi2mask[dev->id], 0,
 | 
						|
                       sizeof(others->xi2mask[dev->id]));
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    len = min(len, sizeof(others->xi2mask[dev->id]));
 | 
						|
 | 
						|
    if (len && !others)
 | 
						|
    {
 | 
						|
        if (AddExtensionClient(win, client, 0, 0) != Success)
 | 
						|
            return BadAlloc;
 | 
						|
        others= wOtherInputMasks(win)->inputClients;
 | 
						|
    }
 | 
						|
 | 
						|
    if (others)
 | 
						|
        memset(others->xi2mask[dev->id], 0, sizeof(others->xi2mask[dev->id]));
 | 
						|
 | 
						|
    if (len)
 | 
						|
        memcpy(others->xi2mask[dev->id], mask, len);
 | 
						|
 | 
						|
    RecalculateDeviceDeliverableEvents(win);
 | 
						|
 | 
						|
    return Success;
 | 
						|
}
 |