exevents.c revision 05b261ec
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>
6405b261ecSmrg#include "inputstr.h"
6505b261ecSmrg#include "windowstr.h"
6605b261ecSmrg#include "miscstruct.h"
6705b261ecSmrg#include "region.h"
6805b261ecSmrg#include "exevents.h"
6905b261ecSmrg#include "extnsionst.h"
7005b261ecSmrg#include "extinit.h"	/* LookupDeviceIntRec */
7105b261ecSmrg#include "exglobals.h"
7205b261ecSmrg#include "dixevents.h"	/* DeliverFocusedEvent */
7305b261ecSmrg#include "dixgrabs.h"	/* CreateGrab() */
7405b261ecSmrg#include "scrnintstr.h"
7505b261ecSmrg
7605b261ecSmrg#ifdef XKB
7705b261ecSmrg#include "xkbsrv.h"
7805b261ecSmrg#endif
7905b261ecSmrg
8005b261ecSmrg#define WID(w) ((w) ? ((w)->drawable.id) : 0)
8105b261ecSmrg#define AllModifiersMask ( \
8205b261ecSmrg	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
8305b261ecSmrg	Mod3Mask | Mod4Mask | Mod5Mask )
8405b261ecSmrg#define AllButtonsMask ( \
8505b261ecSmrg	Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
8605b261ecSmrg#define Motion_Filter(class) (DevicePointerMotionMask | \
8705b261ecSmrg			      (class)->state | (class)->motionMask)
8805b261ecSmrg
8905b261ecSmrgstatic Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
9005b261ecSmrg				 Bool	/* ignoreSelectedEvents */
9105b261ecSmrg    );
9205b261ecSmrgstatic Bool MakeInputMasks(WindowPtr	/* pWin */
9305b261ecSmrg    );
9405b261ecSmrg
9505b261ecSmrg/**************************************************************************
9605b261ecSmrg *
9705b261ecSmrg * Procedures for extension device event routing.
9805b261ecSmrg *
9905b261ecSmrg */
10005b261ecSmrg
10105b261ecSmrgvoid
10205b261ecSmrgRegisterOtherDevice(DeviceIntPtr device)
10305b261ecSmrg{
10405b261ecSmrg    device->public.processInputProc = ProcessOtherEvent;
10505b261ecSmrg    device->public.realInputProc = ProcessOtherEvent;
10605b261ecSmrg    (device)->ActivateGrab = ActivateKeyboardGrab;
10705b261ecSmrg    (device)->DeactivateGrab = DeactivateKeyboardGrab;
10805b261ecSmrg}
10905b261ecSmrg
11005b261ecSmrg /*ARGSUSED*/ void
11105b261ecSmrgProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
11205b261ecSmrg{
11305b261ecSmrg    BYTE *kptr;
11405b261ecSmrg    int i;
11505b261ecSmrg    CARD16 modifiers;
11605b261ecSmrg    CARD16 mask;
11705b261ecSmrg    GrabPtr grab = other->grab;
11805b261ecSmrg    Bool deactivateDeviceGrab = FALSE;
11905b261ecSmrg    int key = 0, bit = 0, rootX, rootY;
12005b261ecSmrg    ButtonClassPtr b = other->button;
12105b261ecSmrg    KeyClassPtr k = other->key;
12205b261ecSmrg    ValuatorClassPtr v = other->valuator;
12305b261ecSmrg    deviceValuator *xV = (deviceValuator *) xE;
12405b261ecSmrg
12505b261ecSmrg    if (xE->u.u.type != DeviceValuator) {
12605b261ecSmrg        /* Other types already have root{X,Y} filled in. */
12705b261ecSmrg        if (xE->u.u.type == DeviceKeyPress ||
12805b261ecSmrg            xE->u.u.type == DeviceKeyRelease) {
12905b261ecSmrg	    GetSpritePosition(&rootX, &rootY);
13005b261ecSmrg	    xE->u.keyButtonPointer.rootX = rootX;
13105b261ecSmrg	    xE->u.keyButtonPointer.rootY = rootY;
13205b261ecSmrg        }
13305b261ecSmrg
13405b261ecSmrg	key = xE->u.u.detail;
13505b261ecSmrg	NoticeEventTime(xE);
13605b261ecSmrg	xE->u.keyButtonPointer.state = inputInfo.keyboard->key->state |
13705b261ecSmrg	    inputInfo.pointer->button->state;
13805b261ecSmrg	bit = 1 << (key & 7);
13905b261ecSmrg    }
14005b261ecSmrg    if (DeviceEventCallback) {
14105b261ecSmrg	DeviceEventInfoRec eventinfo;
14205b261ecSmrg
14305b261ecSmrg	eventinfo.events = (xEventPtr) xE;
14405b261ecSmrg	eventinfo.count = count;
14505b261ecSmrg	CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
14605b261ecSmrg    }
14705b261ecSmrg    for (i = 1; i < count; i++)
14805b261ecSmrg	if ((++xV)->type == DeviceValuator) {
14905b261ecSmrg	    int first = xV->first_valuator;
15005b261ecSmrg	    int *axisvals;
15105b261ecSmrg
15205b261ecSmrg	    if (xV->num_valuators
15305b261ecSmrg		&& (!v
15405b261ecSmrg		    || (xV->num_valuators
15505b261ecSmrg			&& (first + xV->num_valuators > v->numAxes))))
15605b261ecSmrg		FatalError("Bad valuators reported for device %s\n",
15705b261ecSmrg			   other->name);
15805b261ecSmrg	    xV->device_state = 0;
15905b261ecSmrg	    if (k)
16005b261ecSmrg		xV->device_state |= k->state;
16105b261ecSmrg	    if (b)
16205b261ecSmrg		xV->device_state |= b->state;
16305b261ecSmrg	    if (v && v->axisVal) {
16405b261ecSmrg		axisvals = v->axisVal;
16505b261ecSmrg		switch (xV->num_valuators) {
16605b261ecSmrg		case 6:
16705b261ecSmrg		    *(axisvals + first + 5) = xV->valuator5;
16805b261ecSmrg		case 5:
16905b261ecSmrg		    *(axisvals + first + 4) = xV->valuator4;
17005b261ecSmrg		case 4:
17105b261ecSmrg		    *(axisvals + first + 3) = xV->valuator3;
17205b261ecSmrg		case 3:
17305b261ecSmrg		    *(axisvals + first + 2) = xV->valuator2;
17405b261ecSmrg		case 2:
17505b261ecSmrg		    *(axisvals + first + 1) = xV->valuator1;
17605b261ecSmrg		case 1:
17705b261ecSmrg		    *(axisvals + first) = xV->valuator0;
17805b261ecSmrg		case 0:
17905b261ecSmrg		default:
18005b261ecSmrg		    break;
18105b261ecSmrg		}
18205b261ecSmrg	    }
18305b261ecSmrg	}
18405b261ecSmrg
18505b261ecSmrg    if (xE->u.u.type == DeviceKeyPress) {
18605b261ecSmrg        if (!k)
18705b261ecSmrg            return;
18805b261ecSmrg
18905b261ecSmrg	modifiers = k->modifierMap[key];
19005b261ecSmrg	kptr = &k->down[key >> 3];
19105b261ecSmrg	if (*kptr & bit) {	/* allow ddx to generate multiple downs */
19205b261ecSmrg	    if (!modifiers) {
19305b261ecSmrg		xE->u.u.type = DeviceKeyRelease;
19405b261ecSmrg		ProcessOtherEvent(xE, other, count);
19505b261ecSmrg		xE->u.u.type = DeviceKeyPress;
19605b261ecSmrg		/* release can have side effects, don't fall through */
19705b261ecSmrg		ProcessOtherEvent(xE, other, count);
19805b261ecSmrg	    }
19905b261ecSmrg	    return;
20005b261ecSmrg	}
20105b261ecSmrg	if (other->valuator)
20205b261ecSmrg	    other->valuator->motionHintWindow = NullWindow;
20305b261ecSmrg	*kptr |= bit;
20405b261ecSmrg	k->prev_state = k->state;
20505b261ecSmrg	for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
20605b261ecSmrg	    if (mask & modifiers) {
20705b261ecSmrg		/* This key affects modifier "i" */
20805b261ecSmrg		k->modifierKeyCount[i]++;
20905b261ecSmrg		k->state |= mask;
21005b261ecSmrg		modifiers &= ~mask;
21105b261ecSmrg	    }
21205b261ecSmrg	}
21305b261ecSmrg	if (!grab && CheckDeviceGrabs(other, xE, 0, count)) {
21405b261ecSmrg	    other->activatingKey = key;
21505b261ecSmrg	    return;
21605b261ecSmrg	}
21705b261ecSmrg    } else if (xE->u.u.type == DeviceKeyRelease) {
21805b261ecSmrg        if (!k)
21905b261ecSmrg            return;
22005b261ecSmrg
22105b261ecSmrg	kptr = &k->down[key >> 3];
22205b261ecSmrg	if (!(*kptr & bit))	/* guard against duplicates */
22305b261ecSmrg	    return;
22405b261ecSmrg	modifiers = k->modifierMap[key];
22505b261ecSmrg	if (other->valuator)
22605b261ecSmrg	    other->valuator->motionHintWindow = NullWindow;
22705b261ecSmrg	*kptr &= ~bit;
22805b261ecSmrg	k->prev_state = k->state;
22905b261ecSmrg	for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
23005b261ecSmrg	    if (mask & modifiers) {
23105b261ecSmrg		/* This key affects modifier "i" */
23205b261ecSmrg		if (--k->modifierKeyCount[i] <= 0) {
23305b261ecSmrg		    k->modifierKeyCount[i] = 0;
23405b261ecSmrg		    k->state &= ~mask;
23505b261ecSmrg		}
23605b261ecSmrg		modifiers &= ~mask;
23705b261ecSmrg	    }
23805b261ecSmrg	}
23905b261ecSmrg
24005b261ecSmrg	if (other->fromPassiveGrab && (key == other->activatingKey))
24105b261ecSmrg	    deactivateDeviceGrab = TRUE;
24205b261ecSmrg    } else if (xE->u.u.type == DeviceButtonPress) {
24305b261ecSmrg        if (!b)
24405b261ecSmrg            return;
24505b261ecSmrg
24605b261ecSmrg	kptr = &b->down[key >> 3];
24705b261ecSmrg	*kptr |= bit;
24805b261ecSmrg	if (other->valuator)
24905b261ecSmrg	    other->valuator->motionHintWindow = NullWindow;
25005b261ecSmrg	b->buttonsDown++;
25105b261ecSmrg	b->motionMask = DeviceButtonMotionMask;
25205b261ecSmrg	xE->u.u.detail = key;
25305b261ecSmrg	if (xE->u.u.detail == 0)
25405b261ecSmrg	    return;
25505b261ecSmrg	if (xE->u.u.detail <= 5)
25605b261ecSmrg	    b->state |= (Button1Mask >> 1) << xE->u.u.detail;
25705b261ecSmrg	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
25805b261ecSmrg	if (!grab)
25905b261ecSmrg	    if (CheckDeviceGrabs(other, xE, 0, count))
26005b261ecSmrg                /* if a passive grab was activated, the event has been sent
26105b261ecSmrg                 * already */
26205b261ecSmrg                return;
26305b261ecSmrg
26405b261ecSmrg    } else if (xE->u.u.type == DeviceButtonRelease) {
26505b261ecSmrg        if (!b)
26605b261ecSmrg            return;
26705b261ecSmrg
26805b261ecSmrg	kptr = &b->down[key >> 3];
26905b261ecSmrg	*kptr &= ~bit;
27005b261ecSmrg	if (other->valuator)
27105b261ecSmrg	    other->valuator->motionHintWindow = NullWindow;
27205b261ecSmrg        if (b->buttonsDown >= 1 && !--b->buttonsDown)
27305b261ecSmrg	    b->motionMask = 0;
27405b261ecSmrg	xE->u.u.detail = key;
27505b261ecSmrg	if (xE->u.u.detail == 0)
27605b261ecSmrg	    return;
27705b261ecSmrg	if (xE->u.u.detail <= 5)
27805b261ecSmrg	    b->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
27905b261ecSmrg	SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
28005b261ecSmrg	if (!b->state && other->fromPassiveGrab)
28105b261ecSmrg	    deactivateDeviceGrab = TRUE;
28205b261ecSmrg    } else if (xE->u.u.type == ProximityIn)
28305b261ecSmrg	other->valuator->mode &= ~OutOfProximity;
28405b261ecSmrg    else if (xE->u.u.type == ProximityOut)
28505b261ecSmrg	other->valuator->mode |= OutOfProximity;
28605b261ecSmrg
28705b261ecSmrg    if (grab)
28805b261ecSmrg	DeliverGrabbedEvent(xE, other, deactivateDeviceGrab, count);
28905b261ecSmrg    else if (other->focus)
29005b261ecSmrg	DeliverFocusedEvent(other, xE, GetSpriteWindow(), count);
29105b261ecSmrg    else
29205b261ecSmrg	DeliverDeviceEvents(GetSpriteWindow(), xE, NullGrab, NullWindow,
29305b261ecSmrg			    other, count);
29405b261ecSmrg
29505b261ecSmrg    if (deactivateDeviceGrab == TRUE)
29605b261ecSmrg	(*other->DeactivateGrab) (other);
29705b261ecSmrg}
29805b261ecSmrg
29905b261ecSmrg_X_EXPORT int
30005b261ecSmrgInitProximityClassDeviceStruct(DeviceIntPtr dev)
30105b261ecSmrg{
30205b261ecSmrg    ProximityClassPtr proxc;
30305b261ecSmrg
30405b261ecSmrg    proxc = (ProximityClassPtr) xalloc(sizeof(ProximityClassRec));
30505b261ecSmrg    if (!proxc)
30605b261ecSmrg	return FALSE;
30705b261ecSmrg    dev->proximity = proxc;
30805b261ecSmrg    return TRUE;
30905b261ecSmrg}
31005b261ecSmrg
31105b261ecSmrg_X_EXPORT void
31205b261ecSmrgInitValuatorAxisStruct(DeviceIntPtr dev, int axnum, int minval, int maxval,
31305b261ecSmrg		       int resolution, int min_res, int max_res)
31405b261ecSmrg{
31505b261ecSmrg    AxisInfoPtr ax;
31605b261ecSmrg
31705b261ecSmrg    if (!dev || !dev->valuator)
31805b261ecSmrg        return;
31905b261ecSmrg
32005b261ecSmrg    ax = dev->valuator->axes + axnum;
32105b261ecSmrg
32205b261ecSmrg    ax->min_value = minval;
32305b261ecSmrg    ax->max_value = maxval;
32405b261ecSmrg    ax->resolution = resolution;
32505b261ecSmrg    ax->min_resolution = min_res;
32605b261ecSmrg    ax->max_resolution = max_res;
32705b261ecSmrg}
32805b261ecSmrg
32905b261ecSmrgstatic void
33005b261ecSmrgFixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
33105b261ecSmrg		     ButtonClassPtr b, ValuatorClassPtr v, int first)
33205b261ecSmrg{
33305b261ecSmrg    ev->type = DeviceStateNotify;
33405b261ecSmrg    ev->deviceid = dev->id;
33505b261ecSmrg    ev->time = currentTime.milliseconds;
33605b261ecSmrg    ev->classes_reported = 0;
33705b261ecSmrg    ev->num_keys = 0;
33805b261ecSmrg    ev->num_buttons = 0;
33905b261ecSmrg    ev->num_valuators = 0;
34005b261ecSmrg
34105b261ecSmrg    if (b) {
34205b261ecSmrg	ev->classes_reported |= (1 << ButtonClass);
34305b261ecSmrg	ev->num_buttons = b->numButtons;
34405b261ecSmrg	memmove((char *)&ev->buttons[0], (char *)b->down, 4);
34505b261ecSmrg    } else if (k) {
34605b261ecSmrg	ev->classes_reported |= (1 << KeyClass);
34705b261ecSmrg	ev->num_keys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode;
34805b261ecSmrg	memmove((char *)&ev->keys[0], (char *)k->down, 4);
34905b261ecSmrg    }
35005b261ecSmrg    if (v) {
35105b261ecSmrg	int nval = v->numAxes - first;
35205b261ecSmrg
35305b261ecSmrg	ev->classes_reported |= (1 << ValuatorClass);
35405b261ecSmrg	ev->classes_reported |= (dev->valuator->mode << ModeBitsShift);
35505b261ecSmrg	ev->num_valuators = nval < 3 ? nval : 3;
35605b261ecSmrg	switch (ev->num_valuators) {
35705b261ecSmrg	case 3:
35805b261ecSmrg	    ev->valuator2 = v->axisVal[first + 2];
35905b261ecSmrg	case 2:
36005b261ecSmrg	    ev->valuator1 = v->axisVal[first + 1];
36105b261ecSmrg	case 1:
36205b261ecSmrg	    ev->valuator0 = v->axisVal[first];
36305b261ecSmrg	    break;
36405b261ecSmrg	}
36505b261ecSmrg    }
36605b261ecSmrg}
36705b261ecSmrg
36805b261ecSmrgstatic void
36905b261ecSmrgFixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
37005b261ecSmrg		  int first)
37105b261ecSmrg{
37205b261ecSmrg    int nval = v->numAxes - first;
37305b261ecSmrg
37405b261ecSmrg    ev->type = DeviceValuator;
37505b261ecSmrg    ev->deviceid = dev->id;
37605b261ecSmrg    ev->num_valuators = nval < 3 ? nval : 3;
37705b261ecSmrg    ev->first_valuator = first;
37805b261ecSmrg    switch (ev->num_valuators) {
37905b261ecSmrg    case 3:
38005b261ecSmrg	ev->valuator2 = v->axisVal[first + 2];
38105b261ecSmrg    case 2:
38205b261ecSmrg	ev->valuator1 = v->axisVal[first + 1];
38305b261ecSmrg    case 1:
38405b261ecSmrg	ev->valuator0 = v->axisVal[first];
38505b261ecSmrg	break;
38605b261ecSmrg    }
38705b261ecSmrg    first += ev->num_valuators;
38805b261ecSmrg}
38905b261ecSmrg
39005b261ecSmrgvoid
39105b261ecSmrgDeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
39205b261ecSmrg		 WindowPtr pWin)
39305b261ecSmrg{
39405b261ecSmrg    deviceFocus event;
39505b261ecSmrg
39605b261ecSmrg    if (type == FocusIn)
39705b261ecSmrg	type = DeviceFocusIn;
39805b261ecSmrg    else
39905b261ecSmrg	type = DeviceFocusOut;
40005b261ecSmrg
40105b261ecSmrg    event.deviceid = dev->id;
40205b261ecSmrg    event.mode = mode;
40305b261ecSmrg    event.type = type;
40405b261ecSmrg    event.detail = detail;
40505b261ecSmrg    event.window = pWin->drawable.id;
40605b261ecSmrg    event.time = currentTime.milliseconds;
40705b261ecSmrg
40805b261ecSmrg    (void)DeliverEventsToWindow(pWin, (xEvent *) & event, 1,
40905b261ecSmrg				DeviceFocusChangeMask, NullGrab, dev->id);
41005b261ecSmrg
41105b261ecSmrg    if ((type == DeviceFocusIn) &&
41205b261ecSmrg	(wOtherInputMasks(pWin)) &&
41305b261ecSmrg	(wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
41405b261ecSmrg    {
41505b261ecSmrg	int evcount = 1;
41605b261ecSmrg	deviceStateNotify *ev, *sev;
41705b261ecSmrg	deviceKeyStateNotify *kev;
41805b261ecSmrg	deviceButtonStateNotify *bev;
41905b261ecSmrg
42005b261ecSmrg	KeyClassPtr k;
42105b261ecSmrg	ButtonClassPtr b;
42205b261ecSmrg	ValuatorClassPtr v;
42305b261ecSmrg	int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
42405b261ecSmrg
42505b261ecSmrg	if ((b = dev->button) != NULL) {
42605b261ecSmrg	    nbuttons = b->numButtons;
42705b261ecSmrg	    if (nbuttons > 32)
42805b261ecSmrg		evcount++;
42905b261ecSmrg	}
43005b261ecSmrg	if ((k = dev->key) != NULL) {
43105b261ecSmrg	    nkeys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode;
43205b261ecSmrg	    if (nkeys > 32)
43305b261ecSmrg		evcount++;
43405b261ecSmrg	    if (nbuttons > 0) {
43505b261ecSmrg		evcount++;
43605b261ecSmrg	    }
43705b261ecSmrg	}
43805b261ecSmrg	if ((v = dev->valuator) != NULL) {
43905b261ecSmrg	    nval = v->numAxes;
44005b261ecSmrg
44105b261ecSmrg	    if (nval > 3)
44205b261ecSmrg		evcount++;
44305b261ecSmrg	    if (nval > 6) {
44405b261ecSmrg		if (!(k && b))
44505b261ecSmrg		    evcount++;
44605b261ecSmrg		if (nval > 9)
44705b261ecSmrg		    evcount += ((nval - 7) / 3);
44805b261ecSmrg	    }
44905b261ecSmrg	}
45005b261ecSmrg
45105b261ecSmrg	sev = ev = (deviceStateNotify *) xalloc(evcount * sizeof(xEvent));
45205b261ecSmrg	FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
45305b261ecSmrg
45405b261ecSmrg	if (b != NULL) {
45505b261ecSmrg	    FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
45605b261ecSmrg	    first += 3;
45705b261ecSmrg	    nval -= 3;
45805b261ecSmrg	    if (nbuttons > 32) {
45905b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
46005b261ecSmrg		bev = (deviceButtonStateNotify *) ev++;
46105b261ecSmrg		bev->type = DeviceButtonStateNotify;
46205b261ecSmrg		bev->deviceid = dev->id;
46305b261ecSmrg		memmove((char *)&bev->buttons[0], (char *)&b->down[4], 28);
46405b261ecSmrg	    }
46505b261ecSmrg	    if (nval > 0) {
46605b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
46705b261ecSmrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
46805b261ecSmrg		first += 3;
46905b261ecSmrg		nval -= 3;
47005b261ecSmrg	    }
47105b261ecSmrg	}
47205b261ecSmrg
47305b261ecSmrg	if (k != NULL) {
47405b261ecSmrg	    FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
47505b261ecSmrg	    first += 3;
47605b261ecSmrg	    nval -= 3;
47705b261ecSmrg	    if (nkeys > 32) {
47805b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
47905b261ecSmrg		kev = (deviceKeyStateNotify *) ev++;
48005b261ecSmrg		kev->type = DeviceKeyStateNotify;
48105b261ecSmrg		kev->deviceid = dev->id;
48205b261ecSmrg		memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
48305b261ecSmrg	    }
48405b261ecSmrg	    if (nval > 0) {
48505b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
48605b261ecSmrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
48705b261ecSmrg		first += 3;
48805b261ecSmrg		nval -= 3;
48905b261ecSmrg	    }
49005b261ecSmrg	}
49105b261ecSmrg
49205b261ecSmrg	while (nval > 0) {
49305b261ecSmrg	    FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
49405b261ecSmrg	    first += 3;
49505b261ecSmrg	    nval -= 3;
49605b261ecSmrg	    if (nval > 0) {
49705b261ecSmrg		(ev - 1)->deviceid |= MORE_EVENTS;
49805b261ecSmrg		FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
49905b261ecSmrg		first += 3;
50005b261ecSmrg		nval -= 3;
50105b261ecSmrg	    }
50205b261ecSmrg	}
50305b261ecSmrg
50405b261ecSmrg	(void)DeliverEventsToWindow(pWin, (xEvent *) sev, evcount,
50505b261ecSmrg				    DeviceStateNotifyMask, NullGrab, dev->id);
50605b261ecSmrg	xfree(sev);
50705b261ecSmrg    }
50805b261ecSmrg}
50905b261ecSmrg
51005b261ecSmrgint
51105b261ecSmrgGrabButton(ClientPtr client, DeviceIntPtr dev, BYTE this_device_mode,
51205b261ecSmrg	   BYTE other_devices_mode, CARD16 modifiers,
51305b261ecSmrg	   DeviceIntPtr modifier_device, CARD8 button, Window grabWindow,
51405b261ecSmrg	   BOOL ownerEvents, Cursor rcursor, Window rconfineTo, Mask eventMask)
51505b261ecSmrg{
51605b261ecSmrg    WindowPtr pWin, confineTo;
51705b261ecSmrg    CursorPtr cursor;
51805b261ecSmrg    GrabPtr grab;
51905b261ecSmrg    int rc;
52005b261ecSmrg
52105b261ecSmrg    if ((this_device_mode != GrabModeSync) &&
52205b261ecSmrg	(this_device_mode != GrabModeAsync)) {
52305b261ecSmrg	client->errorValue = this_device_mode;
52405b261ecSmrg	return BadValue;
52505b261ecSmrg    }
52605b261ecSmrg    if ((other_devices_mode != GrabModeSync) &&
52705b261ecSmrg	(other_devices_mode != GrabModeAsync)) {
52805b261ecSmrg	client->errorValue = other_devices_mode;
52905b261ecSmrg	return BadValue;
53005b261ecSmrg    }
53105b261ecSmrg    if ((modifiers != AnyModifier) && (modifiers & ~AllModifiersMask)) {
53205b261ecSmrg	client->errorValue = modifiers;
53305b261ecSmrg	return BadValue;
53405b261ecSmrg    }
53505b261ecSmrg    if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) {
53605b261ecSmrg	client->errorValue = ownerEvents;
53705b261ecSmrg	return BadValue;
53805b261ecSmrg    }
53905b261ecSmrg    rc = dixLookupWindow(&pWin, grabWindow, client, DixUnknownAccess);
54005b261ecSmrg    if (rc != Success)
54105b261ecSmrg	return rc;
54205b261ecSmrg    if (rconfineTo == None)
54305b261ecSmrg	confineTo = NullWindow;
54405b261ecSmrg    else {
54505b261ecSmrg	rc = dixLookupWindow(&confineTo, rconfineTo, client, DixUnknownAccess);
54605b261ecSmrg	if (rc != Success)
54705b261ecSmrg	    return rc;
54805b261ecSmrg    }
54905b261ecSmrg    if (rcursor == None)
55005b261ecSmrg	cursor = NullCursor;
55105b261ecSmrg    else {
55205b261ecSmrg	cursor = (CursorPtr) LookupIDByType(rcursor, RT_CURSOR);
55305b261ecSmrg	if (!cursor) {
55405b261ecSmrg	    client->errorValue = rcursor;
55505b261ecSmrg	    return BadCursor;
55605b261ecSmrg	}
55705b261ecSmrg    }
55805b261ecSmrg
55905b261ecSmrg    grab = CreateGrab(client->index, dev, pWin, eventMask,
56005b261ecSmrg		      (Bool) ownerEvents, (Bool) this_device_mode,
56105b261ecSmrg		      (Bool) other_devices_mode, modifier_device, modifiers,
56205b261ecSmrg		      DeviceButtonPress, button, confineTo, cursor);
56305b261ecSmrg    if (!grab)
56405b261ecSmrg	return BadAlloc;
56505b261ecSmrg    return AddPassiveGrabToList(grab);
56605b261ecSmrg}
56705b261ecSmrg
56805b261ecSmrgint
56905b261ecSmrgGrabKey(ClientPtr client, DeviceIntPtr dev, BYTE this_device_mode,
57005b261ecSmrg	BYTE other_devices_mode, CARD16 modifiers,
57105b261ecSmrg	DeviceIntPtr modifier_device, CARD8 key, Window grabWindow,
57205b261ecSmrg	BOOL ownerEvents, Mask mask)
57305b261ecSmrg{
57405b261ecSmrg    WindowPtr pWin;
57505b261ecSmrg    GrabPtr grab;
57605b261ecSmrg    KeyClassPtr k = dev->key;
57705b261ecSmrg    int rc;
57805b261ecSmrg
57905b261ecSmrg    if (k == NULL)
58005b261ecSmrg	return BadMatch;
58105b261ecSmrg    if ((other_devices_mode != GrabModeSync) &&
58205b261ecSmrg	(other_devices_mode != GrabModeAsync)) {
58305b261ecSmrg	client->errorValue = other_devices_mode;
58405b261ecSmrg	return BadValue;
58505b261ecSmrg    }
58605b261ecSmrg    if ((this_device_mode != GrabModeSync) &&
58705b261ecSmrg	(this_device_mode != GrabModeAsync)) {
58805b261ecSmrg	client->errorValue = this_device_mode;
58905b261ecSmrg	return BadValue;
59005b261ecSmrg    }
59105b261ecSmrg    if (((key > k->curKeySyms.maxKeyCode) || (key < k->curKeySyms.minKeyCode))
59205b261ecSmrg	&& (key != AnyKey)) {
59305b261ecSmrg	client->errorValue = key;
59405b261ecSmrg	return BadValue;
59505b261ecSmrg    }
59605b261ecSmrg    if ((modifiers != AnyModifier) && (modifiers & ~AllModifiersMask)) {
59705b261ecSmrg	client->errorValue = modifiers;
59805b261ecSmrg	return BadValue;
59905b261ecSmrg    }
60005b261ecSmrg    if ((ownerEvents != xTrue) && (ownerEvents != xFalse)) {
60105b261ecSmrg	client->errorValue = ownerEvents;
60205b261ecSmrg	return BadValue;
60305b261ecSmrg    }
60405b261ecSmrg    rc = dixLookupWindow(&pWin, grabWindow, client, DixUnknownAccess);
60505b261ecSmrg    if (rc != Success)
60605b261ecSmrg	return rc;
60705b261ecSmrg
60805b261ecSmrg    grab = CreateGrab(client->index, dev, pWin,
60905b261ecSmrg		      mask, ownerEvents, this_device_mode, other_devices_mode,
61005b261ecSmrg		      modifier_device, modifiers, DeviceKeyPress, key,
61105b261ecSmrg		      NullWindow, NullCursor);
61205b261ecSmrg    if (!grab)
61305b261ecSmrg	return BadAlloc;
61405b261ecSmrg    return AddPassiveGrabToList(grab);
61505b261ecSmrg}
61605b261ecSmrg
61705b261ecSmrgint
61805b261ecSmrgSelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
61905b261ecSmrg		Mask mask, Mask exclusivemasks, Mask validmasks)
62005b261ecSmrg{
62105b261ecSmrg    int mskidx = dev->id;
62205b261ecSmrg    int i, ret;
62305b261ecSmrg    Mask check;
62405b261ecSmrg    InputClientsPtr others;
62505b261ecSmrg
62605b261ecSmrg    if (mask & ~validmasks) {
62705b261ecSmrg	client->errorValue = mask;
62805b261ecSmrg	return BadValue;
62905b261ecSmrg    }
63005b261ecSmrg    check = (mask & exclusivemasks);
63105b261ecSmrg    if (wOtherInputMasks(pWin)) {
63205b261ecSmrg	if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {	/* It is illegal for two different
63305b261ecSmrg									 * clients to select on any of the
63405b261ecSmrg									 * events for maskcheck. However,
63505b261ecSmrg									 * it is OK, for some client to
63605b261ecSmrg									 * continue selecting on one of those
63705b261ecSmrg									 * events.  */
63805b261ecSmrg	    for (others = wOtherInputMasks(pWin)->inputClients; others;
63905b261ecSmrg		 others = others->next) {
64005b261ecSmrg		if (!SameClient(others, client) && (check &
64105b261ecSmrg						    others->mask[mskidx]))
64205b261ecSmrg		    return BadAccess;
64305b261ecSmrg	    }
64405b261ecSmrg	}
64505b261ecSmrg	for (others = wOtherInputMasks(pWin)->inputClients; others;
64605b261ecSmrg	     others = others->next) {
64705b261ecSmrg	    if (SameClient(others, client)) {
64805b261ecSmrg		check = others->mask[mskidx];
64905b261ecSmrg		others->mask[mskidx] = mask;
65005b261ecSmrg		if (mask == 0) {
65105b261ecSmrg		    for (i = 0; i < EMASKSIZE; i++)
65205b261ecSmrg			if (i != mskidx && others->mask[i] != 0)
65305b261ecSmrg			    break;
65405b261ecSmrg		    if (i == EMASKSIZE) {
65505b261ecSmrg			RecalculateDeviceDeliverableEvents(pWin);
65605b261ecSmrg			if (ShouldFreeInputMasks(pWin, FALSE))
65705b261ecSmrg			    FreeResource(others->resource, RT_NONE);
65805b261ecSmrg			return Success;
65905b261ecSmrg		    }
66005b261ecSmrg		}
66105b261ecSmrg		goto maskSet;
66205b261ecSmrg	    }
66305b261ecSmrg	}
66405b261ecSmrg    }
66505b261ecSmrg    check = 0;
66605b261ecSmrg    if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
66705b261ecSmrg	return ret;
66805b261ecSmrg  maskSet:
66905b261ecSmrg    if (dev->valuator)
67005b261ecSmrg	if ((dev->valuator->motionHintWindow == pWin) &&
67105b261ecSmrg	    (mask & DevicePointerMotionHintMask) &&
67205b261ecSmrg	    !(check & DevicePointerMotionHintMask) && !dev->grab)
67305b261ecSmrg	    dev->valuator->motionHintWindow = NullWindow;
67405b261ecSmrg    RecalculateDeviceDeliverableEvents(pWin);
67505b261ecSmrg    return Success;
67605b261ecSmrg}
67705b261ecSmrg
67805b261ecSmrgint
67905b261ecSmrgAddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
68005b261ecSmrg{
68105b261ecSmrg    InputClientsPtr others;
68205b261ecSmrg
68305b261ecSmrg    if (!pWin->optional && !MakeWindowOptional(pWin))
68405b261ecSmrg	return BadAlloc;
68505b261ecSmrg    others = (InputClients *) xalloc(sizeof(InputClients));
68605b261ecSmrg    if (!others)
68705b261ecSmrg	return BadAlloc;
68805b261ecSmrg    if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
68905b261ecSmrg	return BadAlloc;
69005b261ecSmrg    bzero((char *)&others->mask[0], sizeof(Mask) * EMASKSIZE);
69105b261ecSmrg    others->mask[mskidx] = mask;
69205b261ecSmrg    others->resource = FakeClientID(client->index);
69305b261ecSmrg    others->next = pWin->optional->inputMasks->inputClients;
69405b261ecSmrg    pWin->optional->inputMasks->inputClients = others;
69505b261ecSmrg    if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
69605b261ecSmrg	return BadAlloc;
69705b261ecSmrg    return Success;
69805b261ecSmrg}
69905b261ecSmrg
70005b261ecSmrgstatic Bool
70105b261ecSmrgMakeInputMasks(WindowPtr pWin)
70205b261ecSmrg{
70305b261ecSmrg    struct _OtherInputMasks *imasks;
70405b261ecSmrg
70505b261ecSmrg    imasks = (struct _OtherInputMasks *)
70605b261ecSmrg	xalloc(sizeof(struct _OtherInputMasks));
70705b261ecSmrg    if (!imasks)
70805b261ecSmrg	return FALSE;
70905b261ecSmrg    bzero((char *)imasks, sizeof(struct _OtherInputMasks));
71005b261ecSmrg    pWin->optional->inputMasks = imasks;
71105b261ecSmrg    return TRUE;
71205b261ecSmrg}
71305b261ecSmrg
71405b261ecSmrgvoid
71505b261ecSmrgRecalculateDeviceDeliverableEvents(WindowPtr pWin)
71605b261ecSmrg{
71705b261ecSmrg    InputClientsPtr others;
71805b261ecSmrg    struct _OtherInputMasks *inputMasks;	/* default: NULL */
71905b261ecSmrg    WindowPtr pChild, tmp;
72005b261ecSmrg    int i;
72105b261ecSmrg
72205b261ecSmrg    pChild = pWin;
72305b261ecSmrg    while (1) {
72405b261ecSmrg	if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
72505b261ecSmrg	    for (others = inputMasks->inputClients; others;
72605b261ecSmrg		 others = others->next) {
72705b261ecSmrg		for (i = 0; i < EMASKSIZE; i++)
72805b261ecSmrg		    inputMasks->inputEvents[i] |= others->mask[i];
72905b261ecSmrg	    }
73005b261ecSmrg	    for (i = 0; i < EMASKSIZE; i++)
73105b261ecSmrg		inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
73205b261ecSmrg	    for (tmp = pChild->parent; tmp; tmp = tmp->parent)
73305b261ecSmrg		if (wOtherInputMasks(tmp))
73405b261ecSmrg		    for (i = 0; i < EMASKSIZE; i++)
73505b261ecSmrg			inputMasks->deliverableEvents[i] |=
73605b261ecSmrg			    (wOtherInputMasks(tmp)->deliverableEvents[i]
73705b261ecSmrg			     & ~inputMasks->
73805b261ecSmrg			     dontPropagateMask[i] & PropagateMask[i]);
73905b261ecSmrg	}
74005b261ecSmrg	if (pChild->firstChild) {
74105b261ecSmrg	    pChild = pChild->firstChild;
74205b261ecSmrg	    continue;
74305b261ecSmrg	}
74405b261ecSmrg	while (!pChild->nextSib && (pChild != pWin))
74505b261ecSmrg	    pChild = pChild->parent;
74605b261ecSmrg	if (pChild == pWin)
74705b261ecSmrg	    break;
74805b261ecSmrg	pChild = pChild->nextSib;
74905b261ecSmrg    }
75005b261ecSmrg}
75105b261ecSmrg
75205b261ecSmrgint
75305b261ecSmrgInputClientGone(WindowPtr pWin, XID id)
75405b261ecSmrg{
75505b261ecSmrg    InputClientsPtr other, prev;
75605b261ecSmrg
75705b261ecSmrg    if (!wOtherInputMasks(pWin))
75805b261ecSmrg	return (Success);
75905b261ecSmrg    prev = 0;
76005b261ecSmrg    for (other = wOtherInputMasks(pWin)->inputClients; other;
76105b261ecSmrg	 other = other->next) {
76205b261ecSmrg	if (other->resource == id) {
76305b261ecSmrg	    if (prev) {
76405b261ecSmrg		prev->next = other->next;
76505b261ecSmrg		xfree(other);
76605b261ecSmrg	    } else if (!(other->next)) {
76705b261ecSmrg		if (ShouldFreeInputMasks(pWin, TRUE)) {
76805b261ecSmrg		    wOtherInputMasks(pWin)->inputClients = other->next;
76905b261ecSmrg		    xfree(wOtherInputMasks(pWin));
77005b261ecSmrg		    pWin->optional->inputMasks = (OtherInputMasks *) NULL;
77105b261ecSmrg		    CheckWindowOptionalNeed(pWin);
77205b261ecSmrg		    xfree(other);
77305b261ecSmrg		} else {
77405b261ecSmrg		    other->resource = FakeClientID(0);
77505b261ecSmrg		    if (!AddResource(other->resource, RT_INPUTCLIENT,
77605b261ecSmrg				     (pointer) pWin))
77705b261ecSmrg			return BadAlloc;
77805b261ecSmrg		}
77905b261ecSmrg	    } else {
78005b261ecSmrg		wOtherInputMasks(pWin)->inputClients = other->next;
78105b261ecSmrg		xfree(other);
78205b261ecSmrg	    }
78305b261ecSmrg	    RecalculateDeviceDeliverableEvents(pWin);
78405b261ecSmrg	    return (Success);
78505b261ecSmrg	}
78605b261ecSmrg	prev = other;
78705b261ecSmrg    }
78805b261ecSmrg    FatalError("client not on device event list");
78905b261ecSmrg}
79005b261ecSmrg
79105b261ecSmrgint
79205b261ecSmrgSendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
79305b261ecSmrg	  xEvent * ev, Mask mask, int count)
79405b261ecSmrg{
79505b261ecSmrg    WindowPtr pWin;
79605b261ecSmrg    WindowPtr effectiveFocus = NullWindow;	/* only set if dest==InputFocus */
79705b261ecSmrg    WindowPtr spriteWin = GetSpriteWindow();
79805b261ecSmrg
79905b261ecSmrg    if (dest == PointerWindow)
80005b261ecSmrg	pWin = spriteWin;
80105b261ecSmrg    else if (dest == InputFocus) {
80205b261ecSmrg	WindowPtr inputFocus;
80305b261ecSmrg
80405b261ecSmrg	if (!d->focus)
80505b261ecSmrg	    inputFocus = spriteWin;
80605b261ecSmrg	else
80705b261ecSmrg	    inputFocus = d->focus->win;
80805b261ecSmrg
80905b261ecSmrg	if (inputFocus == FollowKeyboardWin)
81005b261ecSmrg	    inputFocus = inputInfo.keyboard->focus->win;
81105b261ecSmrg
81205b261ecSmrg	if (inputFocus == NoneWin)
81305b261ecSmrg	    return Success;
81405b261ecSmrg
81505b261ecSmrg	/* If the input focus is PointerRootWin, send the event to where
81605b261ecSmrg	 * the pointer is if possible, then perhaps propogate up to root. */
81705b261ecSmrg	if (inputFocus == PointerRootWin)
81805b261ecSmrg	    inputFocus = GetCurrentRootWindow();
81905b261ecSmrg
82005b261ecSmrg	if (IsParent(inputFocus, spriteWin)) {
82105b261ecSmrg	    effectiveFocus = inputFocus;
82205b261ecSmrg	    pWin = spriteWin;
82305b261ecSmrg	} else
82405b261ecSmrg	    effectiveFocus = pWin = inputFocus;
82505b261ecSmrg    } else
82605b261ecSmrg	dixLookupWindow(&pWin, dest, client, DixUnknownAccess);
82705b261ecSmrg    if (!pWin)
82805b261ecSmrg	return BadWindow;
82905b261ecSmrg    if ((propagate != xFalse) && (propagate != xTrue)) {
83005b261ecSmrg	client->errorValue = propagate;
83105b261ecSmrg	return BadValue;
83205b261ecSmrg    }
83305b261ecSmrg    ev->u.u.type |= 0x80;
83405b261ecSmrg    if (propagate) {
83505b261ecSmrg	for (; pWin; pWin = pWin->parent) {
83605b261ecSmrg	    if (DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, d->id))
83705b261ecSmrg		return Success;
83805b261ecSmrg	    if (pWin == effectiveFocus)
83905b261ecSmrg		return Success;
84005b261ecSmrg	    if (wOtherInputMasks(pWin))
84105b261ecSmrg		mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
84205b261ecSmrg	    if (!mask)
84305b261ecSmrg		break;
84405b261ecSmrg	}
84505b261ecSmrg    } else
84605b261ecSmrg	(void)(DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, d->id));
84705b261ecSmrg    return Success;
84805b261ecSmrg}
84905b261ecSmrg
85005b261ecSmrgint
85105b261ecSmrgSetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
85205b261ecSmrg{
85305b261ecSmrg    int i;
85405b261ecSmrg    ButtonClassPtr b = dev->button;
85505b261ecSmrg
85605b261ecSmrg    if (b == NULL)
85705b261ecSmrg	return BadMatch;
85805b261ecSmrg
85905b261ecSmrg    if (nElts != b->numButtons) {
86005b261ecSmrg	client->errorValue = nElts;
86105b261ecSmrg	return BadValue;
86205b261ecSmrg    }
86305b261ecSmrg    if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
86405b261ecSmrg	return BadValue;
86505b261ecSmrg    for (i = 0; i < nElts; i++)
86605b261ecSmrg	if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
86705b261ecSmrg	    return MappingBusy;
86805b261ecSmrg    for (i = 0; i < nElts; i++)
86905b261ecSmrg	b->map[i + 1] = map[i];
87005b261ecSmrg    return Success;
87105b261ecSmrg}
87205b261ecSmrg
87305b261ecSmrgint
87405b261ecSmrgSetModifierMapping(ClientPtr client, DeviceIntPtr dev, int len, int rlen,
87505b261ecSmrg		   int numKeyPerModifier, KeyCode * inputMap, KeyClassPtr * k)
87605b261ecSmrg{
87705b261ecSmrg    KeyCode *map = NULL;
87805b261ecSmrg    int inputMapLen;
87905b261ecSmrg    int i;
88005b261ecSmrg
88105b261ecSmrg    *k = dev->key;
88205b261ecSmrg    if (*k == NULL)
88305b261ecSmrg	return BadMatch;
88405b261ecSmrg    if (len != ((numKeyPerModifier << 1) + rlen))
88505b261ecSmrg	return BadLength;
88605b261ecSmrg
88705b261ecSmrg    inputMapLen = 8 * numKeyPerModifier;
88805b261ecSmrg
88905b261ecSmrg    /*
89005b261ecSmrg     *  Now enforce the restriction that "all of the non-zero keycodes must be
89105b261ecSmrg     *  in the range specified by min-keycode and max-keycode in the
89205b261ecSmrg     *  connection setup (else a Value error)"
89305b261ecSmrg     */
89405b261ecSmrg    i = inputMapLen;
89505b261ecSmrg    while (i--) {
89605b261ecSmrg	if (inputMap[i]
89705b261ecSmrg	    && (inputMap[i] < (*k)->curKeySyms.minKeyCode
89805b261ecSmrg		|| inputMap[i] > (*k)->curKeySyms.maxKeyCode)) {
89905b261ecSmrg	    client->errorValue = inputMap[i];
90005b261ecSmrg	    return -1;	/* BadValue collides with MappingFailed */
90105b261ecSmrg	}
90205b261ecSmrg    }
90305b261ecSmrg
90405b261ecSmrg    /*
90505b261ecSmrg     *  Now enforce the restriction that none of the old or new
90605b261ecSmrg     *  modifier keys may be down while we change the mapping,  and
90705b261ecSmrg     *  that the DDX layer likes the choice.
90805b261ecSmrg     */
90905b261ecSmrg    if (!AllModifierKeysAreUp(dev, (*k)->modifierKeyMap,
91005b261ecSmrg			      (int)(*k)->maxKeysPerModifier, inputMap,
91105b261ecSmrg			      (int)numKeyPerModifier)
91205b261ecSmrg	|| !AllModifierKeysAreUp(dev, inputMap, (int)numKeyPerModifier,
91305b261ecSmrg				 (*k)->modifierKeyMap,
91405b261ecSmrg				 (int)(*k)->maxKeysPerModifier)) {
91505b261ecSmrg	return MappingBusy;
91605b261ecSmrg    } else {
91705b261ecSmrg	for (i = 0; i < inputMapLen; i++) {
91805b261ecSmrg	    if (inputMap[i] && !LegalModifier(inputMap[i], dev)) {
91905b261ecSmrg		return MappingFailed;
92005b261ecSmrg	    }
92105b261ecSmrg	}
92205b261ecSmrg    }
92305b261ecSmrg
92405b261ecSmrg    /*
92505b261ecSmrg     *  Now build the keyboard's modifier bitmap from the
92605b261ecSmrg     *  list of keycodes.
92705b261ecSmrg     */
92805b261ecSmrg    if (inputMapLen) {
92905b261ecSmrg	map = (KeyCode *) xalloc(inputMapLen);
93005b261ecSmrg	if (!map)
93105b261ecSmrg	    return BadAlloc;
93205b261ecSmrg    }
93305b261ecSmrg    if ((*k)->modifierKeyMap)
93405b261ecSmrg	xfree((*k)->modifierKeyMap);
93505b261ecSmrg    if (inputMapLen) {
93605b261ecSmrg	(*k)->modifierKeyMap = map;
93705b261ecSmrg	memmove((char *)(*k)->modifierKeyMap, (char *)inputMap, inputMapLen);
93805b261ecSmrg    } else
93905b261ecSmrg	(*k)->modifierKeyMap = NULL;
94005b261ecSmrg
94105b261ecSmrg    (*k)->maxKeysPerModifier = numKeyPerModifier;
94205b261ecSmrg    for (i = 0; i < MAP_LENGTH; i++)
94305b261ecSmrg	(*k)->modifierMap[i] = 0;
94405b261ecSmrg    for (i = 0; i < inputMapLen; i++)
94505b261ecSmrg	if (inputMap[i]) {
94605b261ecSmrg	    (*k)->modifierMap[inputMap[i]]
94705b261ecSmrg		|= (1 << (i / (*k)->maxKeysPerModifier));
94805b261ecSmrg	}
94905b261ecSmrg
95005b261ecSmrg    return (MappingSuccess);
95105b261ecSmrg}
95205b261ecSmrg
95305b261ecSmrgvoid
95405b261ecSmrgSendDeviceMappingNotify(ClientPtr client, CARD8 request,
95505b261ecSmrg			KeyCode firstKeyCode, CARD8 count, DeviceIntPtr dev)
95605b261ecSmrg{
95705b261ecSmrg    xEvent event;
95805b261ecSmrg    deviceMappingNotify *ev = (deviceMappingNotify *) & event;
95905b261ecSmrg
96005b261ecSmrg    ev->type = DeviceMappingNotify;
96105b261ecSmrg    ev->request = request;
96205b261ecSmrg    ev->deviceid = dev->id;
96305b261ecSmrg    ev->time = currentTime.milliseconds;
96405b261ecSmrg    if (request == MappingKeyboard) {
96505b261ecSmrg	ev->firstKeyCode = firstKeyCode;
96605b261ecSmrg	ev->count = count;
96705b261ecSmrg    }
96805b261ecSmrg
96905b261ecSmrg#ifdef XKB
97005b261ecSmrg    if (request == MappingKeyboard || request == MappingModifier)
97105b261ecSmrg        XkbApplyMappingChange(dev, request, firstKeyCode, count, client);
97205b261ecSmrg#endif
97305b261ecSmrg
97405b261ecSmrg    SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) ev, 1);
97505b261ecSmrg}
97605b261ecSmrg
97705b261ecSmrgint
97805b261ecSmrgChangeKeyMapping(ClientPtr client,
97905b261ecSmrg		 DeviceIntPtr dev,
98005b261ecSmrg		 unsigned len,
98105b261ecSmrg		 int type,
98205b261ecSmrg		 KeyCode firstKeyCode,
98305b261ecSmrg		 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
98405b261ecSmrg{
98505b261ecSmrg    KeySymsRec keysyms;
98605b261ecSmrg    KeyClassPtr k = dev->key;
98705b261ecSmrg
98805b261ecSmrg    if (k == NULL)
98905b261ecSmrg	return (BadMatch);
99005b261ecSmrg
99105b261ecSmrg    if (len != (keyCodes * keySymsPerKeyCode))
99205b261ecSmrg	return BadLength;
99305b261ecSmrg
99405b261ecSmrg    if ((firstKeyCode < k->curKeySyms.minKeyCode) ||
99505b261ecSmrg	(firstKeyCode + keyCodes - 1 > k->curKeySyms.maxKeyCode)) {
99605b261ecSmrg	client->errorValue = firstKeyCode;
99705b261ecSmrg	return BadValue;
99805b261ecSmrg    }
99905b261ecSmrg    if (keySymsPerKeyCode == 0) {
100005b261ecSmrg	client->errorValue = 0;
100105b261ecSmrg	return BadValue;
100205b261ecSmrg    }
100305b261ecSmrg    keysyms.minKeyCode = firstKeyCode;
100405b261ecSmrg    keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
100505b261ecSmrg    keysyms.mapWidth = keySymsPerKeyCode;
100605b261ecSmrg    keysyms.map = map;
100705b261ecSmrg    if (!SetKeySymsMap(&k->curKeySyms, &keysyms))
100805b261ecSmrg	return BadAlloc;
100905b261ecSmrg    SendDeviceMappingNotify(client, MappingKeyboard, firstKeyCode, keyCodes, dev);
101005b261ecSmrg    return client->noClientException;
101105b261ecSmrg}
101205b261ecSmrg
101305b261ecSmrgstatic void
101405b261ecSmrgDeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
101505b261ecSmrg{
101605b261ecSmrg    WindowPtr parent;
101705b261ecSmrg
101805b261ecSmrg    /* Deactivate any grabs performed on this window, before making
101905b261ecSmrg     * any input focus changes.
102005b261ecSmrg     * Deactivating a device grab should cause focus events. */
102105b261ecSmrg
102205b261ecSmrg    if (dev->grab && (dev->grab->window == pWin))
102305b261ecSmrg	(*dev->DeactivateGrab) (dev);
102405b261ecSmrg
102505b261ecSmrg    /* If the focus window is a root window (ie. has no parent)
102605b261ecSmrg     * then don't delete the focus from it. */
102705b261ecSmrg
102805b261ecSmrg    if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
102905b261ecSmrg	int focusEventMode = NotifyNormal;
103005b261ecSmrg
103105b261ecSmrg	/* If a grab is in progress, then alter the mode of focus events. */
103205b261ecSmrg
103305b261ecSmrg	if (dev->grab)
103405b261ecSmrg	    focusEventMode = NotifyWhileGrabbed;
103505b261ecSmrg
103605b261ecSmrg	switch (dev->focus->revert) {
103705b261ecSmrg	case RevertToNone:
103805b261ecSmrg	    DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
103905b261ecSmrg	    dev->focus->win = NoneWin;
104005b261ecSmrg	    dev->focus->traceGood = 0;
104105b261ecSmrg	    break;
104205b261ecSmrg	case RevertToParent:
104305b261ecSmrg	    parent = pWin;
104405b261ecSmrg	    do {
104505b261ecSmrg		parent = parent->parent;
104605b261ecSmrg		dev->focus->traceGood--;
104705b261ecSmrg	    }
104805b261ecSmrg	    while (!parent->realized);
104905b261ecSmrg	    DoFocusEvents(dev, pWin, parent, focusEventMode);
105005b261ecSmrg	    dev->focus->win = parent;
105105b261ecSmrg	    dev->focus->revert = RevertToNone;
105205b261ecSmrg	    break;
105305b261ecSmrg	case RevertToPointerRoot:
105405b261ecSmrg	    DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
105505b261ecSmrg	    dev->focus->win = PointerRootWin;
105605b261ecSmrg	    dev->focus->traceGood = 0;
105705b261ecSmrg	    break;
105805b261ecSmrg	case RevertToFollowKeyboard:
105905b261ecSmrg	    if (inputInfo.keyboard->focus->win) {
106005b261ecSmrg		DoFocusEvents(dev, pWin, inputInfo.keyboard->focus->win,
106105b261ecSmrg			      focusEventMode);
106205b261ecSmrg		dev->focus->win = FollowKeyboardWin;
106305b261ecSmrg		dev->focus->traceGood = 0;
106405b261ecSmrg	    } else {
106505b261ecSmrg		DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
106605b261ecSmrg		dev->focus->win = NoneWin;
106705b261ecSmrg		dev->focus->traceGood = 0;
106805b261ecSmrg	    }
106905b261ecSmrg	    break;
107005b261ecSmrg	}
107105b261ecSmrg    }
107205b261ecSmrg
107305b261ecSmrg    if (dev->valuator)
107405b261ecSmrg	if (dev->valuator->motionHintWindow == pWin)
107505b261ecSmrg	    dev->valuator->motionHintWindow = NullWindow;
107605b261ecSmrg}
107705b261ecSmrg
107805b261ecSmrgvoid
107905b261ecSmrgDeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
108005b261ecSmrg{
108105b261ecSmrg    int i;
108205b261ecSmrg    DeviceIntPtr dev;
108305b261ecSmrg    InputClientsPtr ic;
108405b261ecSmrg    struct _OtherInputMasks *inputMasks;
108505b261ecSmrg
108605b261ecSmrg    for (dev = inputInfo.devices; dev; dev = dev->next) {
108705b261ecSmrg	if (dev == inputInfo.pointer || dev == inputInfo.keyboard)
108805b261ecSmrg	    continue;
108905b261ecSmrg	DeleteDeviceFromAnyExtEvents(pWin, dev);
109005b261ecSmrg    }
109105b261ecSmrg
109205b261ecSmrg    for (dev = inputInfo.off_devices; dev; dev = dev->next)
109305b261ecSmrg	DeleteDeviceFromAnyExtEvents(pWin, dev);
109405b261ecSmrg
109505b261ecSmrg    if (freeResources)
109605b261ecSmrg	while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
109705b261ecSmrg	    ic = inputMasks->inputClients;
109805b261ecSmrg	    for (i = 0; i < EMASKSIZE; i++)
109905b261ecSmrg		inputMasks->dontPropagateMask[i] = 0;
110005b261ecSmrg	    FreeResource(ic->resource, RT_NONE);
110105b261ecSmrg	}
110205b261ecSmrg}
110305b261ecSmrg
110405b261ecSmrgint
110505b261ecSmrgMaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
110605b261ecSmrg{
110705b261ecSmrg    DeviceIntPtr dev;
110805b261ecSmrg
110905b261ecSmrg    dev = LookupDeviceIntRec(pEvents->deviceid & DEVICE_BITS);
111005b261ecSmrg    if (!dev)
111105b261ecSmrg        return 0;
111205b261ecSmrg
111305b261ecSmrg    if (pEvents->type == DeviceMotionNotify) {
111405b261ecSmrg	if (mask & DevicePointerMotionHintMask) {
111505b261ecSmrg	    if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
111605b261ecSmrg		return 1;	/* don't send, but pretend we did */
111705b261ecSmrg	    }
111805b261ecSmrg	    pEvents->detail = NotifyHint;
111905b261ecSmrg	} else {
112005b261ecSmrg	    pEvents->detail = NotifyNormal;
112105b261ecSmrg	}
112205b261ecSmrg    }
112305b261ecSmrg    return (0);
112405b261ecSmrg}
112505b261ecSmrg
112605b261ecSmrgvoid
112705b261ecSmrgCheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
112805b261ecSmrg			     deviceKeyButtonPointer * xE, GrabPtr grab,
112905b261ecSmrg			     ClientPtr client, Mask deliveryMask)
113005b261ecSmrg{
113105b261ecSmrg    DeviceIntPtr dev;
113205b261ecSmrg
113305b261ecSmrg    dev = LookupDeviceIntRec(xE->deviceid & DEVICE_BITS);
113405b261ecSmrg    if (!dev)
113505b261ecSmrg        return;
113605b261ecSmrg
113705b261ecSmrg    if (type == DeviceMotionNotify)
113805b261ecSmrg	dev->valuator->motionHintWindow = pWin;
113905b261ecSmrg    else if ((type == DeviceButtonPress) && (!grab) &&
114005b261ecSmrg	     (deliveryMask & DeviceButtonGrabMask)) {
114105b261ecSmrg	GrabRec tempGrab;
114205b261ecSmrg
114305b261ecSmrg	tempGrab.device = dev;
114405b261ecSmrg	tempGrab.resource = client->clientAsMask;
114505b261ecSmrg	tempGrab.window = pWin;
114605b261ecSmrg	tempGrab.ownerEvents =
114705b261ecSmrg	    (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
114805b261ecSmrg	tempGrab.eventMask = deliveryMask;
114905b261ecSmrg	tempGrab.keyboardMode = GrabModeAsync;
115005b261ecSmrg	tempGrab.pointerMode = GrabModeAsync;
115105b261ecSmrg	tempGrab.confineTo = NullWindow;
115205b261ecSmrg	tempGrab.cursor = NullCursor;
115305b261ecSmrg	(*dev->ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
115405b261ecSmrg    }
115505b261ecSmrg}
115605b261ecSmrg
115705b261ecSmrgstatic Mask
115805b261ecSmrgDeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
115905b261ecSmrg{
116005b261ecSmrg    InputClientsPtr other;
116105b261ecSmrg
116205b261ecSmrg    if (!wOtherInputMasks(pWin))
116305b261ecSmrg	return 0;
116405b261ecSmrg    for (other = wOtherInputMasks(pWin)->inputClients; other;
116505b261ecSmrg	 other = other->next) {
116605b261ecSmrg	if (SameClient(other, client))
116705b261ecSmrg	    return other->mask[dev->id];
116805b261ecSmrg    }
116905b261ecSmrg    return 0;
117005b261ecSmrg}
117105b261ecSmrg
117205b261ecSmrgvoid
117305b261ecSmrgMaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
117405b261ecSmrg{
117505b261ecSmrg    WindowPtr pWin;
117605b261ecSmrg    GrabPtr grab = dev->grab;
117705b261ecSmrg
117805b261ecSmrg    pWin = dev->valuator->motionHintWindow;
117905b261ecSmrg
118005b261ecSmrg    if ((grab && SameClient(grab, client) &&
118105b261ecSmrg	 ((grab->eventMask & DevicePointerMotionHintMask) ||
118205b261ecSmrg	  (grab->ownerEvents &&
118305b261ecSmrg	   (DeviceEventMaskForClient(dev, pWin, client) &
118405b261ecSmrg	    DevicePointerMotionHintMask)))) ||
118505b261ecSmrg	(!grab &&
118605b261ecSmrg	 (DeviceEventMaskForClient(dev, pWin, client) &
118705b261ecSmrg	  DevicePointerMotionHintMask)))
118805b261ecSmrg	dev->valuator->motionHintWindow = NullWindow;
118905b261ecSmrg}
119005b261ecSmrg
119105b261ecSmrgint
119205b261ecSmrgDeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
119305b261ecSmrg			     int maskndx)
119405b261ecSmrg{
119505b261ecSmrg    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
119605b261ecSmrg
119705b261ecSmrg    if (mask & ~PropagateMask[maskndx]) {
119805b261ecSmrg	client->errorValue = mask;
119905b261ecSmrg	return BadValue;
120005b261ecSmrg    }
120105b261ecSmrg
120205b261ecSmrg    if (mask == 0) {
120305b261ecSmrg	if (inputMasks)
120405b261ecSmrg	    inputMasks->dontPropagateMask[maskndx] = mask;
120505b261ecSmrg    } else {
120605b261ecSmrg	if (!inputMasks)
120705b261ecSmrg	    AddExtensionClient(pWin, client, 0, 0);
120805b261ecSmrg	inputMasks = wOtherInputMasks(pWin);
120905b261ecSmrg	inputMasks->dontPropagateMask[maskndx] = mask;
121005b261ecSmrg    }
121105b261ecSmrg    RecalculateDeviceDeliverableEvents(pWin);
121205b261ecSmrg    if (ShouldFreeInputMasks(pWin, FALSE))
121305b261ecSmrg	FreeResource(inputMasks->inputClients->resource, RT_NONE);
121405b261ecSmrg    return Success;
121505b261ecSmrg}
121605b261ecSmrg
121705b261ecSmrgstatic Bool
121805b261ecSmrgShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
121905b261ecSmrg{
122005b261ecSmrg    int i;
122105b261ecSmrg    Mask allInputEventMasks = 0;
122205b261ecSmrg    struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
122305b261ecSmrg
122405b261ecSmrg    for (i = 0; i < EMASKSIZE; i++)
122505b261ecSmrg	allInputEventMasks |= inputMasks->dontPropagateMask[i];
122605b261ecSmrg    if (!ignoreSelectedEvents)
122705b261ecSmrg	for (i = 0; i < EMASKSIZE; i++)
122805b261ecSmrg	    allInputEventMasks |= inputMasks->inputEvents[i];
122905b261ecSmrg    if (allInputEventMasks == 0)
123005b261ecSmrg	return TRUE;
123105b261ecSmrg    else
123205b261ecSmrg	return FALSE;
123305b261ecSmrg}
123405b261ecSmrg
123505b261ecSmrg/***********************************************************************
123605b261ecSmrg *
123705b261ecSmrg * Walk through the window tree, finding all clients that want to know
123805b261ecSmrg * about the Event.
123905b261ecSmrg *
124005b261ecSmrg */
124105b261ecSmrg
124205b261ecSmrgstatic void
124305b261ecSmrgFindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
124405b261ecSmrg                       xEvent * ev, int count)
124505b261ecSmrg{
124605b261ecSmrg    WindowPtr p2;
124705b261ecSmrg
124805b261ecSmrg    while (p1) {
124905b261ecSmrg        p2 = p1->firstChild;
125005b261ecSmrg        (void)DeliverEventsToWindow(p1, ev, count, mask, NullGrab, dev->id);
125105b261ecSmrg        FindInterestedChildren(dev, p2, mask, ev, count);
125205b261ecSmrg        p1 = p1->nextSib;
125305b261ecSmrg    }
125405b261ecSmrg}
125505b261ecSmrg
125605b261ecSmrg/***********************************************************************
125705b261ecSmrg *
125805b261ecSmrg * Send an event to interested clients in all windows on all screens.
125905b261ecSmrg *
126005b261ecSmrg */
126105b261ecSmrg
126205b261ecSmrgvoid
126305b261ecSmrgSendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
126405b261ecSmrg{
126505b261ecSmrg    int i;
126605b261ecSmrg    WindowPtr pWin, p1;
126705b261ecSmrg
126805b261ecSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
126905b261ecSmrg        pWin = WindowTable[i];
127005b261ecSmrg        (void)DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, dev->id);
127105b261ecSmrg        p1 = pWin->firstChild;
127205b261ecSmrg        FindInterestedChildren(dev, p1, mask, ev, count);
127305b261ecSmrg    }
127405b261ecSmrg}
1275