xkbActions.c revision 4642e01f
105b261ecSmrg/************************************************************
205b261ecSmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
305b261ecSmrg
405b261ecSmrgPermission to use, copy, modify, and distribute this
505b261ecSmrgsoftware and its documentation for any purpose and without
605b261ecSmrgfee is hereby granted, provided that the above copyright
705b261ecSmrgnotice appear in all copies and that both that copyright
805b261ecSmrgnotice and this permission notice appear in supporting
905b261ecSmrgdocumentation, and that the name of Silicon Graphics not be
1005b261ecSmrgused in advertising or publicity pertaining to distribution
1105b261ecSmrgof the software without specific prior written permission.
1205b261ecSmrgSilicon Graphics makes no representation about the suitability
1305b261ecSmrgof this software for any purpose. It is provided "as is"
1405b261ecSmrgwithout any express or implied warranty.
1505b261ecSmrg
1605b261ecSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1705b261ecSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1805b261ecSmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
1905b261ecSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
2005b261ecSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2105b261ecSmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
2205b261ecSmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
2305b261ecSmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
2405b261ecSmrg
2505b261ecSmrg********************************************************/
2605b261ecSmrg
2705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2805b261ecSmrg#include <dix-config.h>
2905b261ecSmrg#endif
3005b261ecSmrg
3105b261ecSmrg#include <stdio.h>
3205b261ecSmrg#include <math.h>
3305b261ecSmrg#define NEED_EVENTS 1
3405b261ecSmrg#include <X11/X.h>
3505b261ecSmrg#include <X11/Xproto.h>
3605b261ecSmrg#include <X11/keysym.h>
3705b261ecSmrg#include "misc.h"
3805b261ecSmrg#include "inputstr.h"
3905b261ecSmrg#include "exevents.h"
4005b261ecSmrg#include <xkbsrv.h>
4105b261ecSmrg#include "xkb.h"
4205b261ecSmrg#include <ctype.h>
4305b261ecSmrg#define EXTENSION_EVENT_BASE 64
4405b261ecSmrg
454642e01fSmrgstatic int xkbDevicePrivateKeyIndex;
464642e01fSmrgDevPrivateKey xkbDevicePrivateKey = &xkbDevicePrivateKeyIndex;
4705b261ecSmrg
4805b261ecSmrgvoid
4905b261ecSmrgxkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc,
5005b261ecSmrg                   pointer data)
5105b261ecSmrg{
5205b261ecSmrg    xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device);
5305b261ecSmrg    ProcessInputProc backupproc;
5405b261ecSmrg    if(xkbPrivPtr->unwrapProc)
5505b261ecSmrg	xkbPrivPtr->unwrapProc = NULL;
5605b261ecSmrg
5705b261ecSmrg    UNWRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr, backupproc);
5805b261ecSmrg    proc(device,data);
5905b261ecSmrg    COND_WRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr,
6005b261ecSmrg				 backupproc,xkbUnwrapProc);
6105b261ecSmrg}
6205b261ecSmrg
6305b261ecSmrg
6405b261ecSmrgvoid
6505b261ecSmrgXkbSetExtension(DeviceIntPtr device, ProcessInputProc proc)
6605b261ecSmrg{
6705b261ecSmrg    xkbDeviceInfoPtr xkbPrivPtr;
6805b261ecSmrg
6905b261ecSmrg    xkbPrivPtr = (xkbDeviceInfoPtr) xcalloc(1, sizeof(xkbDeviceInfoRec));
7005b261ecSmrg    if (!xkbPrivPtr)
7105b261ecSmrg	return;
7205b261ecSmrg    xkbPrivPtr->unwrapProc = NULL;
7305b261ecSmrg
744642e01fSmrg    dixSetPrivate(&device->devPrivates, xkbDevicePrivateKey, xkbPrivPtr);
7505b261ecSmrg    WRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, proc, xkbUnwrapProc);
7605b261ecSmrg}
7705b261ecSmrg
7805b261ecSmrgextern	void	ProcessOtherEvent(
7905b261ecSmrg    xEvent *		/* xE */,
8005b261ecSmrg    DeviceIntPtr 	/* dev */,
8105b261ecSmrg    int 		/* count */
8205b261ecSmrg);
8305b261ecSmrg
8405b261ecSmrg/***====================================================================***/
8505b261ecSmrg
8605b261ecSmrgstatic XkbAction
8705b261ecSmrg_FixUpAction(XkbDescPtr xkb,XkbAction *act)
8805b261ecSmrg{
8905b261ecSmrgstatic XkbAction	fake;
9005b261ecSmrg
9105b261ecSmrg    if (XkbIsPtrAction(act)&&(!(xkb->ctrls->enabled_ctrls&XkbMouseKeysMask))) {
9205b261ecSmrg	fake.type = XkbSA_NoAction;
9305b261ecSmrg	return fake;
9405b261ecSmrg    }
9505b261ecSmrg    if (XkbDisableLockActions) {
9605b261ecSmrg	switch (act->type) {
9705b261ecSmrg	    case XkbSA_LockMods:
9805b261ecSmrg		fake.mods.type  = XkbSA_SetMods;
9905b261ecSmrg		fake.mods.flags = 0;
10005b261ecSmrg		fake.mods.mask  = act->mods.mask;
10105b261ecSmrg		return fake;
10205b261ecSmrg	    case XkbSA_LatchMods:
10305b261ecSmrg		fake.mods.type  = XkbSA_SetMods;
10405b261ecSmrg		fake.mods.flags = 0;
10505b261ecSmrg		fake.mods.mask  = act->mods.mask;
10605b261ecSmrg		return fake;
10705b261ecSmrg	    case XkbSA_ISOLock:
10805b261ecSmrg		if (act->iso.flags&XkbSA_ISODfltIsGroup) {
10905b261ecSmrg		     fake.group.type = XkbSA_SetGroup;
11005b261ecSmrg		     fake.group.flags = act->iso.flags&XkbSA_GroupAbsolute;
11105b261ecSmrg		     XkbSASetGroup(&fake.group,XkbSAGroup(&act->iso));
11205b261ecSmrg		}
11305b261ecSmrg		else {
11405b261ecSmrg		     fake.mods.type  = XkbSA_SetMods;
11505b261ecSmrg		     fake.mods.flags = 0;
11605b261ecSmrg		     fake.mods.mask  = act->iso.mask;
11705b261ecSmrg		}
11805b261ecSmrg		return fake;
11905b261ecSmrg	    case XkbSA_LockGroup:
12005b261ecSmrg	    case XkbSA_LatchGroup:
12105b261ecSmrg		/* We want everything from the latch/lock action except the
12205b261ecSmrg		 * type should be changed to set.
12305b261ecSmrg		 */
12405b261ecSmrg		fake = *act;
12505b261ecSmrg		fake.group.type = XkbSA_SetGroup;
12605b261ecSmrg		return fake;
12705b261ecSmrg	}
12805b261ecSmrg    }
12905b261ecSmrg    else
13005b261ecSmrg    if (xkb->ctrls->enabled_ctrls&XkbStickyKeysMask) {
13105b261ecSmrg	if (act->any.type==XkbSA_SetMods) {
13205b261ecSmrg	    fake.mods.type = XkbSA_LatchMods;
13305b261ecSmrg	    fake.mods.mask = act->mods.mask;
13405b261ecSmrg	    if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask))
13505b261ecSmrg		 fake.mods.flags= XkbSA_ClearLocks|XkbSA_LatchToLock;
13605b261ecSmrg	    else fake.mods.flags= XkbSA_ClearLocks;
13705b261ecSmrg	    return fake;
13805b261ecSmrg	}
13905b261ecSmrg	if (act->any.type==XkbSA_SetGroup) {
14005b261ecSmrg	    fake.group.type = XkbSA_LatchGroup;
14105b261ecSmrg	    if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask))
14205b261ecSmrg		 fake.group.flags= XkbSA_ClearLocks|XkbSA_LatchToLock;
14305b261ecSmrg	    else fake.group.flags= XkbSA_ClearLocks;
14405b261ecSmrg	    XkbSASetGroup(&fake.group,XkbSAGroup(&act->group));
14505b261ecSmrg	    return fake;
14605b261ecSmrg	}
14705b261ecSmrg    }
14805b261ecSmrg    return *act;
14905b261ecSmrg}
15005b261ecSmrg
15105b261ecSmrgstatic XkbAction
15205b261ecSmrgXkbGetKeyAction(XkbSrvInfoPtr xkbi,XkbStatePtr xkbState,CARD8 key)
15305b261ecSmrg{
15405b261ecSmrgint			effectiveGroup;
15505b261ecSmrgint			col;
15605b261ecSmrgXkbDescPtr		xkb;
15705b261ecSmrgXkbKeyTypePtr		type;
15805b261ecSmrgXkbAction *		pActs;
15905b261ecSmrgstatic XkbAction 	fake;
16005b261ecSmrg
16105b261ecSmrg    xkb= xkbi->desc;
16205b261ecSmrg    if (!XkbKeyHasActions(xkb,key) || !XkbKeycodeInRange(xkb,key)) {
16305b261ecSmrg	fake.type = XkbSA_NoAction;
16405b261ecSmrg	return fake;
16505b261ecSmrg    }
16605b261ecSmrg    pActs= XkbKeyActionsPtr(xkb,key);
16705b261ecSmrg    col= 0;
16805b261ecSmrg    effectiveGroup= xkbState->group;
16905b261ecSmrg    if (effectiveGroup!=XkbGroup1Index) {
17005b261ecSmrg	if (XkbKeyNumGroups(xkb,key)>(unsigned)1) {
17105b261ecSmrg	    if (effectiveGroup>=XkbKeyNumGroups(xkb,key)) {
17205b261ecSmrg		unsigned gi= XkbKeyGroupInfo(xkb,key);
17305b261ecSmrg		switch (XkbOutOfRangeGroupAction(gi)) {
17405b261ecSmrg		    default:
17505b261ecSmrg		    case XkbWrapIntoRange:
17605b261ecSmrg			effectiveGroup %= XkbKeyNumGroups(xkb,key);
17705b261ecSmrg			break;
17805b261ecSmrg		    case XkbClampIntoRange:
17905b261ecSmrg			effectiveGroup = XkbKeyNumGroups(xkb,key)-1;
18005b261ecSmrg			break;
18105b261ecSmrg		    case XkbRedirectIntoRange:
18205b261ecSmrg			effectiveGroup= XkbOutOfRangeGroupInfo(gi);
18305b261ecSmrg			if (effectiveGroup>=XkbKeyNumGroups(xkb,key))
18405b261ecSmrg			    effectiveGroup= 0;
18505b261ecSmrg			break;
18605b261ecSmrg		}
18705b261ecSmrg	    }
18805b261ecSmrg	}
18905b261ecSmrg	else effectiveGroup= XkbGroup1Index;
19005b261ecSmrg	col+= (effectiveGroup*XkbKeyGroupsWidth(xkb,key));
19105b261ecSmrg    }
19205b261ecSmrg    type= XkbKeyKeyType(xkb,key,effectiveGroup);
19305b261ecSmrg    if (type->map!=NULL) {
19405b261ecSmrg	register unsigned		i,mods;
19505b261ecSmrg	register XkbKTMapEntryPtr	entry;
19605b261ecSmrg	mods= xkbState->mods&type->mods.mask;
19705b261ecSmrg	for (entry= type->map,i=0;i<type->map_count;i++,entry++) {
19805b261ecSmrg	    if ((entry->active)&&(entry->mods.mask==mods)) {
19905b261ecSmrg		col+= entry->level;
20005b261ecSmrg		break;
20105b261ecSmrg	    }
20205b261ecSmrg	}
20305b261ecSmrg    }
20405b261ecSmrg    if (pActs[col].any.type==XkbSA_NoAction)
20505b261ecSmrg	return pActs[col];
20605b261ecSmrg    fake= _FixUpAction(xkb,&pActs[col]);
20705b261ecSmrg    return fake;
20805b261ecSmrg}
20905b261ecSmrg
21005b261ecSmrgstatic XkbAction
21105b261ecSmrgXkbGetButtonAction(DeviceIntPtr kbd,DeviceIntPtr dev,int button)
21205b261ecSmrg{
21305b261ecSmrgXkbAction fake;
21405b261ecSmrg   if ((dev->button)&&(dev->button->xkb_acts)) {
21505b261ecSmrg	if (dev->button->xkb_acts[button-1].any.type!=XkbSA_NoAction) {
21605b261ecSmrg	    fake= _FixUpAction(kbd->key->xkbInfo->desc,
21705b261ecSmrg					&dev->button->xkb_acts[button-1]);
21805b261ecSmrg	    return fake;
21905b261ecSmrg	}
22005b261ecSmrg   }
22105b261ecSmrg   fake.any.type= XkbSA_NoAction;
22205b261ecSmrg   return fake;
22305b261ecSmrg}
22405b261ecSmrg
22505b261ecSmrg/***====================================================================***/
22605b261ecSmrg
22705b261ecSmrg#define	SYNTHETIC_KEYCODE	1
22805b261ecSmrg#define	BTN_ACT_FLAG		0x100
22905b261ecSmrg
23005b261ecSmrgstatic int
23105b261ecSmrg_XkbFilterSetState(	XkbSrvInfoPtr	xkbi,
23205b261ecSmrg			XkbFilterPtr	filter,
23305b261ecSmrg			unsigned	keycode,
23405b261ecSmrg			XkbAction *pAction)
23505b261ecSmrg{
23605b261ecSmrg    if (filter->keycode==0) {		/* initial press */
23705b261ecSmrg	filter->keycode = keycode;
23805b261ecSmrg	filter->active = 1;
23905b261ecSmrg	filter->filterOthers = ((pAction->mods.mask&XkbSA_ClearLocks)!=0);
24005b261ecSmrg	filter->priv = 0;
24105b261ecSmrg	filter->filter = _XkbFilterSetState;
24205b261ecSmrg	if (pAction->type==XkbSA_SetMods) {
24305b261ecSmrg	    filter->upAction = *pAction;
24405b261ecSmrg	    xkbi->setMods= pAction->mods.mask;
24505b261ecSmrg	}
24605b261ecSmrg	else {
24705b261ecSmrg	    xkbi->groupChange = XkbSAGroup(&pAction->group);
24805b261ecSmrg	    if (pAction->group.flags&XkbSA_GroupAbsolute)
24905b261ecSmrg		xkbi->groupChange-= xkbi->state.base_group;
25005b261ecSmrg	    filter->upAction= *pAction;
25105b261ecSmrg	    XkbSASetGroup(&filter->upAction.group,xkbi->groupChange);
25205b261ecSmrg	}
25305b261ecSmrg    }
25405b261ecSmrg    else if (filter->keycode==keycode) {
25505b261ecSmrg	if (filter->upAction.type==XkbSA_SetMods) {
25605b261ecSmrg	    xkbi->clearMods = filter->upAction.mods.mask;
25705b261ecSmrg	    if (filter->upAction.mods.flags&XkbSA_ClearLocks) {
25805b261ecSmrg		xkbi->state.locked_mods&= ~filter->upAction.mods.mask;
25905b261ecSmrg	    }
26005b261ecSmrg	}
26105b261ecSmrg	else {
26205b261ecSmrg	    if (filter->upAction.group.flags&XkbSA_ClearLocks) {
26305b261ecSmrg		xkbi->state.locked_group = 0;
26405b261ecSmrg	    }
26505b261ecSmrg	    xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
26605b261ecSmrg	}
26705b261ecSmrg	filter->active = 0;
26805b261ecSmrg    }
26905b261ecSmrg    else {
27005b261ecSmrg	filter->upAction.mods.flags&= ~XkbSA_ClearLocks;
27105b261ecSmrg	filter->filterOthers = 0;
27205b261ecSmrg    }
27305b261ecSmrg    return 1;
27405b261ecSmrg}
27505b261ecSmrg
27605b261ecSmrg#define	LATCH_KEY_DOWN	1
27705b261ecSmrg#define	LATCH_PENDING	2
27805b261ecSmrg#define	NO_LATCH	3
27905b261ecSmrg
28005b261ecSmrgstatic int
28105b261ecSmrg_XkbFilterLatchState(	XkbSrvInfoPtr	xkbi,
28205b261ecSmrg			XkbFilterPtr	filter,
28305b261ecSmrg			unsigned	keycode,
28405b261ecSmrg			XkbAction *	pAction)
28505b261ecSmrg{
28605b261ecSmrg
28705b261ecSmrg    if (filter->keycode==0) {			/* initial press */
28805b261ecSmrg	filter->keycode = keycode;
28905b261ecSmrg	filter->active = 1;
29005b261ecSmrg	filter->filterOthers = 1;
29105b261ecSmrg	filter->priv = LATCH_KEY_DOWN;
29205b261ecSmrg	filter->filter = _XkbFilterLatchState;
29305b261ecSmrg	if (pAction->type==XkbSA_LatchMods) {
29405b261ecSmrg	    filter->upAction = *pAction;
29505b261ecSmrg	    xkbi->setMods = pAction->mods.mask;
29605b261ecSmrg	}
29705b261ecSmrg	else {
29805b261ecSmrg	    xkbi->groupChange = XkbSAGroup(&pAction->group);
29905b261ecSmrg	    if (pAction->group.flags&XkbSA_GroupAbsolute)
30005b261ecSmrg		 xkbi->groupChange-= xkbi->state.base_group;
30105b261ecSmrg	    filter->upAction= *pAction;
30205b261ecSmrg	    XkbSASetGroup(&filter->upAction.group,xkbi->groupChange);
30305b261ecSmrg	}
30405b261ecSmrg    }
30505b261ecSmrg    else if ( pAction && (filter->priv==LATCH_PENDING) ) {
30605b261ecSmrg	if (((1<<pAction->type)&XkbSA_BreakLatch)!=0) {
30705b261ecSmrg	    filter->active = 0;
30805b261ecSmrg	    if (filter->upAction.type==XkbSA_LatchMods)
30905b261ecSmrg		 xkbi->state.latched_mods&= ~filter->upAction.mods.mask;
31005b261ecSmrg	    else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group);
31105b261ecSmrg	}
31205b261ecSmrg	else if ((pAction->type==filter->upAction.type)&&
31305b261ecSmrg		 (pAction->mods.flags==filter->upAction.mods.flags)&&
31405b261ecSmrg		 (pAction->mods.mask==filter->upAction.mods.mask)) {
31505b261ecSmrg	    if (filter->upAction.mods.flags&XkbSA_LatchToLock) {
31605b261ecSmrg		XkbControlsPtr ctrls= xkbi->desc->ctrls;
31705b261ecSmrg		if (filter->upAction.type==XkbSA_LatchMods)
31805b261ecSmrg		     pAction->mods.type= XkbSA_LockMods;
31905b261ecSmrg		else pAction->group.type= XkbSA_LockGroup;
32005b261ecSmrg		if (XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask)&&
32105b261ecSmrg		    		(ctrls->enabled_ctrls&XkbStickyKeysMask)) {
32205b261ecSmrg		    XkbDDXAccessXBeep(xkbi->device,_BEEP_STICKY_LOCK,
32305b261ecSmrg						XkbStickyKeysMask);
32405b261ecSmrg		}
32505b261ecSmrg	    }
32605b261ecSmrg	    else {
32705b261ecSmrg		if (filter->upAction.type==XkbSA_LatchMods)
32805b261ecSmrg		     pAction->mods.type= XkbSA_SetMods;
32905b261ecSmrg		else pAction->group.type= XkbSA_SetGroup;
33005b261ecSmrg	    }
33105b261ecSmrg	    if (filter->upAction.type==XkbSA_LatchMods)
33205b261ecSmrg		 xkbi->state.latched_mods&= ~filter->upAction.mods.mask;
33305b261ecSmrg	    else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group);
33405b261ecSmrg	    filter->active = 0;
33505b261ecSmrg	}
33605b261ecSmrg    }
33705b261ecSmrg    else if (filter->keycode==keycode) {	/* release */
33805b261ecSmrg	XkbControlsPtr	ctrls= xkbi->desc->ctrls;
33905b261ecSmrg	int		needBeep;
34005b261ecSmrg	int		beepType= _BEEP_NONE;
34105b261ecSmrg
34205b261ecSmrg	needBeep= ((ctrls->enabled_ctrls&XkbStickyKeysMask)&&
34305b261ecSmrg			XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask));
34405b261ecSmrg	if (filter->upAction.type==XkbSA_LatchMods) {
34505b261ecSmrg	    xkbi->clearMods = filter->upAction.mods.mask;
34605b261ecSmrg	    if ((filter->upAction.mods.flags&XkbSA_ClearLocks)&&
34705b261ecSmrg		 (xkbi->clearMods&xkbi->state.locked_mods)==xkbi->clearMods) {
34805b261ecSmrg		xkbi->state.locked_mods&= ~xkbi->clearMods;
34905b261ecSmrg		filter->priv= NO_LATCH;
35005b261ecSmrg		beepType= _BEEP_STICKY_UNLOCK;
35105b261ecSmrg	    }
35205b261ecSmrg	}
35305b261ecSmrg	else {
35405b261ecSmrg	    xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
35505b261ecSmrg	    if ((filter->upAction.group.flags&XkbSA_ClearLocks)&&
35605b261ecSmrg						(xkbi->state.locked_group)) {
35705b261ecSmrg		xkbi->state.locked_group = 0;
35805b261ecSmrg		filter->priv = NO_LATCH;
35905b261ecSmrg		beepType= _BEEP_STICKY_UNLOCK;
36005b261ecSmrg	    }
36105b261ecSmrg	}
36205b261ecSmrg	if (filter->priv==NO_LATCH) {
36305b261ecSmrg	    filter->active= 0;
36405b261ecSmrg	}
36505b261ecSmrg	else {
36605b261ecSmrg	    filter->priv= LATCH_PENDING;
36705b261ecSmrg	    if (filter->upAction.type==XkbSA_LatchMods) {
36805b261ecSmrg		xkbi->state.latched_mods |= filter->upAction.mods.mask;
36905b261ecSmrg		needBeep = xkbi->state.latched_mods ? needBeep : 0;
37005b261ecSmrg		xkbi->state.latched_mods |= filter->upAction.mods.mask;
37105b261ecSmrg	    }
37205b261ecSmrg	    else {
37305b261ecSmrg		xkbi->state.latched_group+= XkbSAGroup(&filter->upAction.group);
37405b261ecSmrg	    }
37505b261ecSmrg	    if (needBeep && (beepType==_BEEP_NONE))
37605b261ecSmrg		beepType= _BEEP_STICKY_LATCH;
37705b261ecSmrg	}
37805b261ecSmrg	if (needBeep && (beepType!=_BEEP_NONE))
37905b261ecSmrg	    XkbDDXAccessXBeep(xkbi->device,beepType,XkbStickyKeysMask);
38005b261ecSmrg    }
38105b261ecSmrg    else if (filter->priv==LATCH_KEY_DOWN) {
38205b261ecSmrg	filter->priv= NO_LATCH;
38305b261ecSmrg	filter->filterOthers = 0;
38405b261ecSmrg    }
38505b261ecSmrg    return 1;
38605b261ecSmrg}
38705b261ecSmrg
38805b261ecSmrgstatic int
38905b261ecSmrg_XkbFilterLockState(	XkbSrvInfoPtr	xkbi,
39005b261ecSmrg			XkbFilterPtr	filter,
39105b261ecSmrg			unsigned	keycode,
39205b261ecSmrg			XkbAction *	pAction)
39305b261ecSmrg{
39405b261ecSmrg    if (pAction&&(pAction->type==XkbSA_LockGroup)) {
39505b261ecSmrg	if (pAction->group.flags&XkbSA_GroupAbsolute)
39605b261ecSmrg	     xkbi->state.locked_group= XkbSAGroup(&pAction->group);
39705b261ecSmrg	else xkbi->state.locked_group+= XkbSAGroup(&pAction->group);
39805b261ecSmrg	return 1;
39905b261ecSmrg    }
40005b261ecSmrg    if (filter->keycode==0) {		/* initial press */
40105b261ecSmrg	filter->keycode = keycode;
40205b261ecSmrg	filter->active = 1;
40305b261ecSmrg	filter->filterOthers = 0;
40405b261ecSmrg	filter->priv = 0;
40505b261ecSmrg	filter->filter = _XkbFilterLockState;
40605b261ecSmrg	filter->upAction = *pAction;
40705b261ecSmrg	xkbi->state.locked_mods^= pAction->mods.mask;
40805b261ecSmrg	xkbi->setMods = pAction->mods.mask;
40905b261ecSmrg    }
41005b261ecSmrg    else if (filter->keycode==keycode) {
41105b261ecSmrg	filter->active = 0;
41205b261ecSmrg	xkbi->clearMods = filter->upAction.mods.mask;
41305b261ecSmrg    }
41405b261ecSmrg    return 1;
41505b261ecSmrg}
41605b261ecSmrg
41705b261ecSmrg#define	ISO_KEY_DOWN		0
41805b261ecSmrg#define	NO_ISO_LOCK		1
41905b261ecSmrg
42005b261ecSmrgstatic int
42105b261ecSmrg_XkbFilterISOLock(	XkbSrvInfoPtr	xkbi,
42205b261ecSmrg			XkbFilterPtr	filter,
42305b261ecSmrg			unsigned	keycode,
42405b261ecSmrg			XkbAction *	pAction)
42505b261ecSmrg{
42605b261ecSmrg
42705b261ecSmrg    if (filter->keycode==0) {		/* initial press */
42805b261ecSmrg	CARD8	flags= pAction->iso.flags;
42905b261ecSmrg
43005b261ecSmrg	filter->keycode = keycode;
43105b261ecSmrg	filter->active = 1;
43205b261ecSmrg	filter->filterOthers = 1;
43305b261ecSmrg	filter->priv = ISO_KEY_DOWN;
43405b261ecSmrg	filter->upAction = *pAction;
43505b261ecSmrg	filter->filter = _XkbFilterISOLock;
43605b261ecSmrg	if (flags&XkbSA_ISODfltIsGroup) {
43705b261ecSmrg	    xkbi->groupChange = XkbSAGroup(&pAction->iso);
43805b261ecSmrg	    xkbi->setMods = 0;
43905b261ecSmrg	}
44005b261ecSmrg	else {
44105b261ecSmrg	    xkbi->setMods = pAction->iso.mask;
44205b261ecSmrg	    xkbi->groupChange = 0;
44305b261ecSmrg	}
44405b261ecSmrg	if ((!(flags&XkbSA_ISONoAffectMods))&&(xkbi->state.base_mods)) {
44505b261ecSmrg	    filter->priv= NO_ISO_LOCK;
44605b261ecSmrg	    xkbi->state.locked_mods^= xkbi->state.base_mods;
44705b261ecSmrg	}
44805b261ecSmrg	if ((!(flags&XkbSA_ISONoAffectGroup))&&(xkbi->state.base_group)) {
44905b261ecSmrg/* 6/22/93 (ef) -- lock groups if group key is down first */
45005b261ecSmrg	}
45105b261ecSmrg	if (!(flags&XkbSA_ISONoAffectPtr)) {
45205b261ecSmrg/* 6/22/93 (ef) -- lock mouse buttons if they're down */
45305b261ecSmrg	}
45405b261ecSmrg    }
45505b261ecSmrg    else if (filter->keycode==keycode) {
45605b261ecSmrg	CARD8	flags= filter->upAction.iso.flags;
45705b261ecSmrg
45805b261ecSmrg	if (flags&XkbSA_ISODfltIsGroup) {
45905b261ecSmrg	    xkbi->groupChange = -XkbSAGroup(&filter->upAction.iso);
46005b261ecSmrg	    xkbi->clearMods = 0;
46105b261ecSmrg	    if (filter->priv==ISO_KEY_DOWN)
46205b261ecSmrg		xkbi->state.locked_group+= XkbSAGroup(&filter->upAction.iso);
46305b261ecSmrg	}
46405b261ecSmrg	else {
46505b261ecSmrg	    xkbi->clearMods= filter->upAction.iso.mask;
46605b261ecSmrg	    xkbi->groupChange= 0;
46705b261ecSmrg	    if (filter->priv==ISO_KEY_DOWN)
46805b261ecSmrg		xkbi->state.locked_mods^= filter->upAction.iso.mask;
46905b261ecSmrg	}
47005b261ecSmrg	filter->active = 0;
47105b261ecSmrg    }
47205b261ecSmrg    else if (pAction) {
47305b261ecSmrg	CARD8	flags= filter->upAction.iso.flags;
47405b261ecSmrg
47505b261ecSmrg	switch (pAction->type) {
47605b261ecSmrg	    case XkbSA_SetMods: case XkbSA_LatchMods:
47705b261ecSmrg		if (!(flags&XkbSA_ISONoAffectMods)) {
47805b261ecSmrg		    pAction->type= XkbSA_LockMods;
47905b261ecSmrg		    filter->priv= NO_ISO_LOCK;
48005b261ecSmrg		}
48105b261ecSmrg		break;
48205b261ecSmrg	    case XkbSA_SetGroup: case XkbSA_LatchGroup:
48305b261ecSmrg		if (!(flags&XkbSA_ISONoAffectGroup)) {
48405b261ecSmrg		    pAction->type= XkbSA_LockGroup;
48505b261ecSmrg		    filter->priv= NO_ISO_LOCK;
48605b261ecSmrg		}
48705b261ecSmrg		break;
48805b261ecSmrg	    case XkbSA_PtrBtn:
48905b261ecSmrg		if (!(flags&XkbSA_ISONoAffectPtr)) {
49005b261ecSmrg		     pAction->type= XkbSA_LockPtrBtn;
49105b261ecSmrg		     filter->priv= NO_ISO_LOCK;
49205b261ecSmrg		}
49305b261ecSmrg		break;
49405b261ecSmrg	    case XkbSA_SetControls:
49505b261ecSmrg		if (!(flags&XkbSA_ISONoAffectCtrls)) {
49605b261ecSmrg		    pAction->type= XkbSA_LockControls;
49705b261ecSmrg		    filter->priv= NO_ISO_LOCK;
49805b261ecSmrg		}
49905b261ecSmrg		break;
50005b261ecSmrg	}
50105b261ecSmrg    }
50205b261ecSmrg    return 1;
50305b261ecSmrg}
50405b261ecSmrg
50505b261ecSmrg
50605b261ecSmrgstatic CARD32
50705b261ecSmrg_XkbPtrAccelExpire(OsTimerPtr timer,CARD32 now,pointer arg)
50805b261ecSmrg{
50905b261ecSmrgXkbSrvInfoPtr	xkbi= (XkbSrvInfoPtr)arg;
51005b261ecSmrgXkbControlsPtr	ctrls= xkbi->desc->ctrls;
51105b261ecSmrgint		dx,dy;
51205b261ecSmrg
51305b261ecSmrg    if (xkbi->mouseKey==0)
51405b261ecSmrg	return 0;
51505b261ecSmrg
51605b261ecSmrg    if (xkbi->mouseKeysAccel) {
51705b261ecSmrg	if ((xkbi->mouseKeysCounter)<ctrls->mk_time_to_max) {
51805b261ecSmrg	    double step;
51905b261ecSmrg	    xkbi->mouseKeysCounter++;
52005b261ecSmrg	    step= xkbi->mouseKeysCurveFactor*
52105b261ecSmrg		 pow((double)xkbi->mouseKeysCounter,xkbi->mouseKeysCurve);
52205b261ecSmrg	    if (xkbi->mouseKeysDX<0)
52305b261ecSmrg		 dx= floor( ((double)xkbi->mouseKeysDX)*step );
52405b261ecSmrg	    else dx=  ceil( ((double)xkbi->mouseKeysDX)*step );
52505b261ecSmrg	    if (xkbi->mouseKeysDY<0)
52605b261ecSmrg		 dy= floor( ((double)xkbi->mouseKeysDY)*step );
52705b261ecSmrg	    else dy=  ceil( ((double)xkbi->mouseKeysDY)*step );
52805b261ecSmrg	}
52905b261ecSmrg	else {
53005b261ecSmrg	    dx= xkbi->mouseKeysDX*ctrls->mk_max_speed;
53105b261ecSmrg	    dy= xkbi->mouseKeysDY*ctrls->mk_max_speed;
53205b261ecSmrg	}
53305b261ecSmrg	if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteX)
53405b261ecSmrg	    dx= xkbi->mouseKeysDX;
53505b261ecSmrg	if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteY)
53605b261ecSmrg	    dy= xkbi->mouseKeysDY;
53705b261ecSmrg    }
53805b261ecSmrg    else {
53905b261ecSmrg	dx= xkbi->mouseKeysDX;
54005b261ecSmrg	dy= xkbi->mouseKeysDY;
54105b261ecSmrg    }
54205b261ecSmrg    XkbDDXFakePointerMotion(xkbi->mouseKeysFlags,dx,dy);
54305b261ecSmrg    return xkbi->desc->ctrls->mk_interval;
54405b261ecSmrg}
54505b261ecSmrg
54605b261ecSmrgstatic int
54705b261ecSmrg_XkbFilterPointerMove(	XkbSrvInfoPtr	xkbi,
54805b261ecSmrg			XkbFilterPtr	filter,
54905b261ecSmrg			unsigned	keycode,
55005b261ecSmrg			XkbAction *	pAction)
55105b261ecSmrg{
55205b261ecSmrgint	x,y;
55305b261ecSmrgBool	accel;
55405b261ecSmrg
55505b261ecSmrg    if (xkbi->device == inputInfo.keyboard)
55605b261ecSmrg        return 0;
55705b261ecSmrg
55805b261ecSmrg    if (filter->keycode==0) {		/* initial press */
55905b261ecSmrg	filter->keycode = keycode;
56005b261ecSmrg	filter->active = 1;
56105b261ecSmrg	filter->filterOthers = 0;
56205b261ecSmrg	filter->priv=0;
56305b261ecSmrg	filter->filter = _XkbFilterPointerMove;
56405b261ecSmrg	filter->upAction= *pAction;
56505b261ecSmrg	xkbi->mouseKeysCounter= 0;
56605b261ecSmrg	xkbi->mouseKey= keycode;
56705b261ecSmrg	accel= ((pAction->ptr.flags&XkbSA_NoAcceleration)==0);
56805b261ecSmrg	x= XkbPtrActionX(&pAction->ptr);
56905b261ecSmrg	y= XkbPtrActionY(&pAction->ptr);
57005b261ecSmrg	XkbDDXFakePointerMotion(pAction->ptr.flags,x,y);
57105b261ecSmrg	AccessXCancelRepeatKey(xkbi,keycode);
57205b261ecSmrg	xkbi->mouseKeysAccel= accel&&
57305b261ecSmrg		(xkbi->desc->ctrls->enabled_ctrls&XkbMouseKeysAccelMask);
57405b261ecSmrg	xkbi->mouseKeysFlags= pAction->ptr.flags;
57505b261ecSmrg	xkbi->mouseKeysDX= XkbPtrActionX(&pAction->ptr);
57605b261ecSmrg	xkbi->mouseKeysDY= XkbPtrActionY(&pAction->ptr);
57705b261ecSmrg	xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0,
57805b261ecSmrg				xkbi->desc->ctrls->mk_delay,
57905b261ecSmrg				_XkbPtrAccelExpire,(pointer)xkbi);
58005b261ecSmrg    }
58105b261ecSmrg    else if (filter->keycode==keycode) {
58205b261ecSmrg	filter->active = 0;
58305b261ecSmrg	if (xkbi->mouseKey==keycode) {
58405b261ecSmrg	    xkbi->mouseKey= 0;
58505b261ecSmrg	    xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0, 0,
58605b261ecSmrg							NULL, NULL);
58705b261ecSmrg	}
58805b261ecSmrg    }
58905b261ecSmrg    return 0;
59005b261ecSmrg}
59105b261ecSmrg
59205b261ecSmrgstatic int
59305b261ecSmrg_XkbFilterPointerBtn(	XkbSrvInfoPtr	xkbi,
59405b261ecSmrg			XkbFilterPtr	filter,
59505b261ecSmrg			unsigned	keycode,
59605b261ecSmrg			XkbAction *	pAction)
59705b261ecSmrg{
59805b261ecSmrg    if (filter->keycode==0) {		/* initial press */
59905b261ecSmrg	int	button= pAction->btn.button;
60005b261ecSmrg
60105b261ecSmrg	if (button==XkbSA_UseDfltButton)
60205b261ecSmrg	    button = xkbi->desc->ctrls->mk_dflt_btn;
60305b261ecSmrg
60405b261ecSmrg	filter->keycode = keycode;
60505b261ecSmrg	filter->active = 1;
60605b261ecSmrg	filter->filterOthers = 0;
60705b261ecSmrg	filter->priv=0;
60805b261ecSmrg	filter->filter = _XkbFilterPointerBtn;
60905b261ecSmrg	filter->upAction= *pAction;
61005b261ecSmrg	filter->upAction.btn.button= button;
61105b261ecSmrg	switch (pAction->type) {
61205b261ecSmrg	    case XkbSA_LockPtrBtn:
61305b261ecSmrg		if (((xkbi->lockedPtrButtons&(1<<button))==0)&&
61405b261ecSmrg			((pAction->btn.flags&XkbSA_LockNoLock)==0)) {
61505b261ecSmrg		    xkbi->lockedPtrButtons|= (1<<button);
61605b261ecSmrg		    AccessXCancelRepeatKey(xkbi,keycode);
6174642e01fSmrg		    XkbDDXFakeDeviceButton(xkbi->device, 1, button);
61805b261ecSmrg		    filter->upAction.type= XkbSA_NoAction;
61905b261ecSmrg		}
62005b261ecSmrg		break;
62105b261ecSmrg	    case XkbSA_PtrBtn:
62205b261ecSmrg		{
62305b261ecSmrg		    register int i,nClicks;
62405b261ecSmrg		    AccessXCancelRepeatKey(xkbi,keycode);
62505b261ecSmrg		    if (pAction->btn.count>0) {
62605b261ecSmrg			nClicks= pAction->btn.count;
62705b261ecSmrg			for (i=0;i<nClicks;i++) {
6284642e01fSmrg			    XkbDDXFakeDeviceButton(xkbi->device, 1, button);
6294642e01fSmrg			    XkbDDXFakeDeviceButton(xkbi->device, 0, button);
63005b261ecSmrg			}
63105b261ecSmrg			filter->upAction.type= XkbSA_NoAction;
63205b261ecSmrg		    }
6334642e01fSmrg		    else XkbDDXFakeDeviceButton(xkbi->device, 1, button);
63405b261ecSmrg		}
63505b261ecSmrg		break;
63605b261ecSmrg	    case XkbSA_SetPtrDflt:
63705b261ecSmrg		{
63805b261ecSmrg		    XkbControlsPtr	ctrls= xkbi->desc->ctrls;
63905b261ecSmrg		    XkbControlsRec	old;
64005b261ecSmrg		    xkbControlsNotify	cn;
64105b261ecSmrg
64205b261ecSmrg		    old= *ctrls;
64305b261ecSmrg		    AccessXCancelRepeatKey(xkbi,keycode);
64405b261ecSmrg		    switch (pAction->dflt.affect) {
64505b261ecSmrg			case XkbSA_AffectDfltBtn:
64605b261ecSmrg			    if (pAction->dflt.flags&XkbSA_DfltBtnAbsolute)
64705b261ecSmrg				ctrls->mk_dflt_btn=
64805b261ecSmrg					XkbSAPtrDfltValue(&pAction->dflt);
64905b261ecSmrg			    else {
65005b261ecSmrg				ctrls->mk_dflt_btn+=
65105b261ecSmrg					XkbSAPtrDfltValue(&pAction->dflt);
65205b261ecSmrg				if (ctrls->mk_dflt_btn>5)
65305b261ecSmrg				    ctrls->mk_dflt_btn= 5;
65405b261ecSmrg				else if (ctrls->mk_dflt_btn<1)
65505b261ecSmrg				    ctrls->mk_dflt_btn= 1;
65605b261ecSmrg			    }
65705b261ecSmrg			    break;
65805b261ecSmrg			default:
65905b261ecSmrg			    ErrorF(
66005b261ecSmrg		"Attempt to change unknown pointer default (%d) ignored\n",
66105b261ecSmrg							pAction->dflt.affect);
66205b261ecSmrg			    break;
66305b261ecSmrg		    }
66405b261ecSmrg		    if (XkbComputeControlsNotify(xkbi->device,
66505b261ecSmrg						&old,xkbi->desc->ctrls,
66605b261ecSmrg						&cn,False)) {
66705b261ecSmrg			cn.keycode = keycode;
66805b261ecSmrg                        /* XXX: what about DeviceKeyPress? */
66905b261ecSmrg			cn.eventType = KeyPress;
67005b261ecSmrg			cn.requestMajor = 0;
67105b261ecSmrg			cn.requestMinor = 0;
67205b261ecSmrg			XkbSendControlsNotify(xkbi->device,&cn);
67305b261ecSmrg		    }
67405b261ecSmrg		}
67505b261ecSmrg		break;
67605b261ecSmrg	}
67705b261ecSmrg    }
67805b261ecSmrg    else if (filter->keycode==keycode) {
67905b261ecSmrg	int	button= filter->upAction.btn.button;
68005b261ecSmrg
68105b261ecSmrg	switch (filter->upAction.type) {
68205b261ecSmrg	    case XkbSA_LockPtrBtn:
68305b261ecSmrg		if (((filter->upAction.btn.flags&XkbSA_LockNoUnlock)!=0)||
68405b261ecSmrg				((xkbi->lockedPtrButtons&(1<<button))==0)) {
68505b261ecSmrg		    break;
68605b261ecSmrg		}
68705b261ecSmrg		xkbi->lockedPtrButtons&= ~(1<<button);
68805b261ecSmrg	    case XkbSA_PtrBtn:
6894642e01fSmrg		XkbDDXFakeDeviceButton(xkbi->device, 0, button);
69005b261ecSmrg		break;
69105b261ecSmrg	}
69205b261ecSmrg	filter->active = 0;
69305b261ecSmrg    }
69405b261ecSmrg    return 0;
69505b261ecSmrg}
69605b261ecSmrg
69705b261ecSmrgstatic int
69805b261ecSmrg_XkbFilterControls(	XkbSrvInfoPtr	xkbi,
69905b261ecSmrg			XkbFilterPtr	filter,
70005b261ecSmrg			unsigned	keycode,
70105b261ecSmrg			XkbAction *	pAction)
70205b261ecSmrg{
70305b261ecSmrgXkbControlsRec		old;
70405b261ecSmrgXkbControlsPtr		ctrls;
70505b261ecSmrgDeviceIntPtr		kbd;
70605b261ecSmrgunsigned int		change;
70705b261ecSmrgXkbEventCauseRec	cause;
70805b261ecSmrg
70905b261ecSmrg    kbd= xkbi->device;
71005b261ecSmrg    ctrls= xkbi->desc->ctrls;
71105b261ecSmrg    old= *ctrls;
71205b261ecSmrg    if (filter->keycode==0) {		/* initial press */
71305b261ecSmrg	filter->keycode = keycode;
71405b261ecSmrg	filter->active = 1;
71505b261ecSmrg	filter->filterOthers = 0;
71605b261ecSmrg	change= XkbActionCtrls(&pAction->ctrls);
71705b261ecSmrg	filter->priv = change;
71805b261ecSmrg	filter->filter = _XkbFilterControls;
71905b261ecSmrg	filter->upAction = *pAction;
72005b261ecSmrg
72105b261ecSmrg	if (pAction->type==XkbSA_LockControls) {
72205b261ecSmrg	    filter->priv= (ctrls->enabled_ctrls&change);
72305b261ecSmrg	    change&= ~ctrls->enabled_ctrls;
72405b261ecSmrg	}
72505b261ecSmrg
72605b261ecSmrg	if (change) {
72705b261ecSmrg	    xkbControlsNotify	cn;
72805b261ecSmrg	    XkbSrvLedInfoPtr	sli;
72905b261ecSmrg
73005b261ecSmrg	    ctrls->enabled_ctrls|= change;
73105b261ecSmrg	    if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,False)) {
73205b261ecSmrg		cn.keycode = keycode;
73305b261ecSmrg                /* XXX: what about DeviceKeyPress? */
73405b261ecSmrg		cn.eventType = KeyPress;
73505b261ecSmrg		cn.requestMajor = 0;
73605b261ecSmrg		cn.requestMinor = 0;
73705b261ecSmrg		XkbSendControlsNotify(kbd,&cn);
73805b261ecSmrg	    }
73905b261ecSmrg
74005b261ecSmrg	    XkbSetCauseKey(&cause,keycode,KeyPress);
74105b261ecSmrg
74205b261ecSmrg	    /* If sticky keys were disabled, clear all locks and latches */
74305b261ecSmrg	    if ((old.enabled_ctrls&XkbStickyKeysMask)&&
74405b261ecSmrg		(!(ctrls->enabled_ctrls&XkbStickyKeysMask))) {
74505b261ecSmrg		XkbClearAllLatchesAndLocks(kbd,xkbi,False,&cause);
74605b261ecSmrg    	    }
74705b261ecSmrg	    sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
74805b261ecSmrg	    XkbUpdateIndicators(kbd,sli->usesControls,True,NULL,&cause);
74905b261ecSmrg	    if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask))
75005b261ecSmrg		XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_ON,change);
75105b261ecSmrg	}
75205b261ecSmrg    }
75305b261ecSmrg    else if (filter->keycode==keycode) {
75405b261ecSmrg	change= filter->priv;
75505b261ecSmrg	if (change) {
75605b261ecSmrg	    xkbControlsNotify 	cn;
75705b261ecSmrg	    XkbSrvLedInfoPtr	sli;
75805b261ecSmrg
75905b261ecSmrg	    ctrls->enabled_ctrls&= ~change;
76005b261ecSmrg	    if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,False)) {
76105b261ecSmrg		cn.keycode = keycode;
76205b261ecSmrg		cn.eventType = KeyRelease;
76305b261ecSmrg		cn.requestMajor = 0;
76405b261ecSmrg		cn.requestMinor = 0;
76505b261ecSmrg		XkbSendControlsNotify(kbd,&cn);
76605b261ecSmrg	    }
76705b261ecSmrg
76805b261ecSmrg	    XkbSetCauseKey(&cause,keycode,KeyRelease);
76905b261ecSmrg	    /* If sticky keys were disabled, clear all locks and latches */
77005b261ecSmrg	    if ((old.enabled_ctrls&XkbStickyKeysMask)&&
77105b261ecSmrg		(!(ctrls->enabled_ctrls&XkbStickyKeysMask))) {
77205b261ecSmrg		XkbClearAllLatchesAndLocks(kbd,xkbi,False,&cause);
77305b261ecSmrg    	    }
77405b261ecSmrg	    sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
77505b261ecSmrg	    XkbUpdateIndicators(kbd,sli->usesControls,True,NULL,&cause);
77605b261ecSmrg	    if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask))
77705b261ecSmrg		XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_OFF,change);
77805b261ecSmrg	}
77905b261ecSmrg	filter->keycode= 0;
78005b261ecSmrg	filter->active= 0;
78105b261ecSmrg    }
78205b261ecSmrg    return 1;
78305b261ecSmrg}
78405b261ecSmrg
78505b261ecSmrgstatic int
78605b261ecSmrg_XkbFilterActionMessage(XkbSrvInfoPtr	xkbi,
78705b261ecSmrg			XkbFilterPtr	filter,
78805b261ecSmrg			unsigned	keycode,
78905b261ecSmrg			XkbAction *	pAction)
79005b261ecSmrg{
79105b261ecSmrgXkbMessageAction *	pMsg;
79205b261ecSmrgDeviceIntPtr		kbd;
79305b261ecSmrg
79405b261ecSmrg    kbd= xkbi->device;
79505b261ecSmrg    if (filter->keycode==0) {		/* initial press */
79605b261ecSmrg	pMsg= &pAction->msg;
79705b261ecSmrg	if ((pMsg->flags&XkbSA_MessageOnRelease)||
79805b261ecSmrg	    ((pMsg->flags&XkbSA_MessageGenKeyEvent)==0)) {
79905b261ecSmrg	    filter->keycode = keycode;
80005b261ecSmrg	    filter->active = 1;
80105b261ecSmrg	    filter->filterOthers = 0;
80205b261ecSmrg	    filter->priv = 0;
80305b261ecSmrg	    filter->filter = _XkbFilterActionMessage;
80405b261ecSmrg	    filter->upAction = *pAction;
80505b261ecSmrg	}
80605b261ecSmrg	if (pMsg->flags&XkbSA_MessageOnPress)  {
80705b261ecSmrg	    xkbActionMessage	msg;
80805b261ecSmrg
80905b261ecSmrg	    msg.keycode= keycode;
81005b261ecSmrg	    msg.press= 1;
81105b261ecSmrg	    msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0);
81205b261ecSmrg	    memcpy((char *)msg.message,
81305b261ecSmrg				(char *)pMsg->message,XkbActionMessageLength);
81405b261ecSmrg	    XkbSendActionMessage(kbd,&msg);
81505b261ecSmrg	}
81605b261ecSmrg	return ((pAction->msg.flags&XkbSA_MessageGenKeyEvent)!=0);
81705b261ecSmrg    }
81805b261ecSmrg    else if (filter->keycode==keycode) {
81905b261ecSmrg	pMsg= &filter->upAction.msg;
82005b261ecSmrg	if (pMsg->flags&XkbSA_MessageOnRelease) {
82105b261ecSmrg	    xkbActionMessage	msg;
82205b261ecSmrg
82305b261ecSmrg	    msg.keycode= keycode;
82405b261ecSmrg	    msg.press= 0;
82505b261ecSmrg	    msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0);
82605b261ecSmrg	    memcpy((char *)msg.message,(char *)pMsg->message,
82705b261ecSmrg						XkbActionMessageLength);
82805b261ecSmrg	    XkbSendActionMessage(kbd,&msg);
82905b261ecSmrg	}
83005b261ecSmrg	filter->keycode= 0;
83105b261ecSmrg	filter->active= 0;
83205b261ecSmrg	return ((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0);
83305b261ecSmrg    }
83405b261ecSmrg    return 0;
83505b261ecSmrg}
83605b261ecSmrg
83705b261ecSmrgstatic int
83805b261ecSmrg_XkbFilterRedirectKey(	XkbSrvInfoPtr	xkbi,
83905b261ecSmrg			XkbFilterPtr	filter,
84005b261ecSmrg			unsigned	keycode,
84105b261ecSmrg			XkbAction *	pAction)
84205b261ecSmrg{
8434642e01fSmrgunsigned	realMods = 0;
84405b261ecSmrgxEvent 		ev;
84505b261ecSmrgint		x,y;
84605b261ecSmrgXkbStateRec	old;
84705b261ecSmrgunsigned	mods,mask,oldCoreState = 0,oldCorePrevState = 0;
84805b261ecSmrgxkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device);
84905b261ecSmrgProcessInputProc backupproc;
85005b261ecSmrg
85105b261ecSmrg    /* never actually used uninitialised, but gcc isn't smart enough
85205b261ecSmrg     * to work that out. */
85305b261ecSmrg    memset(&old, 0, sizeof(old));
85405b261ecSmrg
85505b261ecSmrg    if ((filter->keycode!=0)&&(filter->keycode!=keycode))
85605b261ecSmrg	return 1;
85705b261ecSmrg
8584642e01fSmrg    GetSpritePosition(inputInfo.pointer, &x,&y);
85905b261ecSmrg    ev.u.keyButtonPointer.time = GetTimeInMillis();
86005b261ecSmrg    ev.u.keyButtonPointer.rootX = x;
86105b261ecSmrg    ev.u.keyButtonPointer.rootY = y;
86205b261ecSmrg
86305b261ecSmrg    if (filter->keycode==0) {		/* initial press */
86405b261ecSmrg	if ((pAction->redirect.new_key<xkbi->desc->min_key_code)||
86505b261ecSmrg	    (pAction->redirect.new_key>xkbi->desc->max_key_code)) {
86605b261ecSmrg	    return 1;
86705b261ecSmrg	}
86805b261ecSmrg	filter->keycode = keycode;
86905b261ecSmrg	filter->active = 1;
87005b261ecSmrg	filter->filterOthers = 0;
87105b261ecSmrg	filter->priv = 0;
87205b261ecSmrg	filter->filter = _XkbFilterRedirectKey;
87305b261ecSmrg	filter->upAction = *pAction;
87405b261ecSmrg
87505b261ecSmrg        /* XXX: what about DeviceKeyPress */
87605b261ecSmrg	ev.u.u.type = KeyPress;
87705b261ecSmrg	ev.u.u.detail = pAction->redirect.new_key;
87805b261ecSmrg
87905b261ecSmrg        mask= XkbSARedirectVModsMask(&pAction->redirect);
88005b261ecSmrg        mods= XkbSARedirectVMods(&pAction->redirect);
88105b261ecSmrg        if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask);
88205b261ecSmrg        if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods);
88305b261ecSmrg        mask|= pAction->redirect.mods_mask;
88405b261ecSmrg        mods|= pAction->redirect.mods;
88505b261ecSmrg
88605b261ecSmrg	if ( mask || mods ) {
88705b261ecSmrg	    old= xkbi->state;
88805b261ecSmrg	    oldCoreState= xkbi->device->key->state;
88905b261ecSmrg	    oldCorePrevState= xkbi->device->key->prev_state;
89005b261ecSmrg	    xkbi->state.base_mods&= ~mask;
89105b261ecSmrg	    xkbi->state.base_mods|= (mods&mask);
89205b261ecSmrg	    xkbi->state.latched_mods&= ~mask;
89305b261ecSmrg	    xkbi->state.latched_mods|= (mods&mask);
89405b261ecSmrg	    xkbi->state.locked_mods&= ~mask;
89505b261ecSmrg	    xkbi->state.locked_mods|= (mods&mask);
89605b261ecSmrg	    XkbComputeDerivedState(xkbi);
89705b261ecSmrg	    xkbi->device->key->state= xkbi->device->key->prev_state=
89805b261ecSmrg							xkbi->state.mods;
89905b261ecSmrg	}
90005b261ecSmrg
90105b261ecSmrg	realMods = xkbi->device->key->modifierMap[ev.u.u.detail];
90205b261ecSmrg	xkbi->device->key->modifierMap[ev.u.u.detail] = 0;
90305b261ecSmrg	UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
90405b261ecSmrg	xkbi->device->public.processInputProc(&ev,xkbi->device,1);
90505b261ecSmrg	COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
90605b261ecSmrg				     backupproc,xkbUnwrapProc);
90705b261ecSmrg	xkbi->device->key->modifierMap[ev.u.u.detail] = realMods;
90805b261ecSmrg
90905b261ecSmrg	if ( mask || mods ) {
91005b261ecSmrg	    xkbi->device->key->state= oldCoreState;
91105b261ecSmrg	    xkbi->device->key->prev_state= oldCorePrevState;
91205b261ecSmrg	    xkbi->state= old;
91305b261ecSmrg	}
91405b261ecSmrg    }
91505b261ecSmrg    else if (filter->keycode==keycode) {
91605b261ecSmrg
91705b261ecSmrg        /* XXX: what about DeviceKeyRelease */
91805b261ecSmrg	ev.u.u.type = KeyRelease;
91905b261ecSmrg	ev.u.u.detail = filter->upAction.redirect.new_key;
92005b261ecSmrg
92105b261ecSmrg        mask= XkbSARedirectVModsMask(&filter->upAction.redirect);
92205b261ecSmrg        mods= XkbSARedirectVMods(&filter->upAction.redirect);
92305b261ecSmrg        if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask);
92405b261ecSmrg        if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods);
92505b261ecSmrg        mask|= filter->upAction.redirect.mods_mask;
92605b261ecSmrg        mods|= filter->upAction.redirect.mods;
92705b261ecSmrg
92805b261ecSmrg	if ( mask || mods ) {
92905b261ecSmrg	    old= xkbi->state;
93005b261ecSmrg	    oldCoreState= xkbi->device->key->state;
93105b261ecSmrg	    oldCorePrevState= xkbi->device->key->prev_state;
93205b261ecSmrg	    xkbi->state.base_mods&= ~mask;
93305b261ecSmrg	    xkbi->state.base_mods|= (mods&mask);
93405b261ecSmrg	    xkbi->state.latched_mods&= ~mask;
93505b261ecSmrg	    xkbi->state.latched_mods|= (mods&mask);
93605b261ecSmrg	    xkbi->state.locked_mods&= ~mask;
93705b261ecSmrg	    xkbi->state.locked_mods|= (mods&mask);
93805b261ecSmrg	    XkbComputeDerivedState(xkbi);
93905b261ecSmrg	    xkbi->device->key->state= xkbi->device->key->prev_state=
94005b261ecSmrg							xkbi->state.mods;
94105b261ecSmrg	}
94205b261ecSmrg
94305b261ecSmrg	realMods = xkbi->device->key->modifierMap[ev.u.u.detail];
94405b261ecSmrg	xkbi->device->key->modifierMap[ev.u.u.detail] = 0;
94505b261ecSmrg	UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
94605b261ecSmrg	xkbi->device->public.processInputProc(&ev,xkbi->device,1);
94705b261ecSmrg	COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
94805b261ecSmrg				     backupproc,xkbUnwrapProc);
94905b261ecSmrg	xkbi->device->key->modifierMap[ev.u.u.detail] = realMods;
95005b261ecSmrg
95105b261ecSmrg	if ( mask || mods ) {
95205b261ecSmrg	    xkbi->device->key->state= oldCoreState;
95305b261ecSmrg	    xkbi->device->key->prev_state= oldCorePrevState;
95405b261ecSmrg	    xkbi->state= old;
95505b261ecSmrg	}
95605b261ecSmrg
95705b261ecSmrg	filter->keycode= 0;
95805b261ecSmrg	filter->active= 0;
95905b261ecSmrg    }
96005b261ecSmrg    return 0;
96105b261ecSmrg}
96205b261ecSmrg
96305b261ecSmrgstatic int
96405b261ecSmrg_XkbFilterSwitchScreen(	XkbSrvInfoPtr	xkbi,
96505b261ecSmrg			XkbFilterPtr	filter,
96605b261ecSmrg			unsigned	keycode,
96705b261ecSmrg			XkbAction *	pAction)
96805b261ecSmrg{
96905b261ecSmrg    DeviceIntPtr dev = xkbi->device;
97005b261ecSmrg    if (dev == inputInfo.keyboard)
97105b261ecSmrg        return 0;
97205b261ecSmrg
97305b261ecSmrg    if (filter->keycode==0) {		/* initial press */
97405b261ecSmrg	filter->keycode = keycode;
97505b261ecSmrg	filter->active = 1;
97605b261ecSmrg	filter->filterOthers = 0;
97705b261ecSmrg	filter->filter = _XkbFilterSwitchScreen;
97805b261ecSmrg	AccessXCancelRepeatKey(xkbi, keycode);
97905b261ecSmrg	XkbDDXSwitchScreen(dev,keycode,pAction);
98005b261ecSmrg        return 0;
98105b261ecSmrg    }
98205b261ecSmrg    else if (filter->keycode==keycode) {
98305b261ecSmrg	filter->active= 0;
98405b261ecSmrg        return 0;
98505b261ecSmrg    }
98605b261ecSmrg    return 1;
98705b261ecSmrg}
98805b261ecSmrg
98905b261ecSmrgstatic int
99005b261ecSmrg_XkbFilterXF86Private(	XkbSrvInfoPtr	xkbi,
99105b261ecSmrg			XkbFilterPtr	filter,
99205b261ecSmrg			unsigned	keycode,
99305b261ecSmrg			XkbAction *	pAction)
99405b261ecSmrg{
99505b261ecSmrg    DeviceIntPtr dev = xkbi->device;
99605b261ecSmrg    if (dev == inputInfo.keyboard)
99705b261ecSmrg        return 0;
99805b261ecSmrg
99905b261ecSmrg    if (filter->keycode==0) {		/* initial press */
100005b261ecSmrg	filter->keycode = keycode;
100105b261ecSmrg	filter->active = 1;
100205b261ecSmrg	filter->filterOthers = 0;
100305b261ecSmrg	filter->filter = _XkbFilterXF86Private;
100405b261ecSmrg	XkbDDXPrivate(dev,keycode,pAction);
100505b261ecSmrg        return 0;
100605b261ecSmrg    }
100705b261ecSmrg    else if (filter->keycode==keycode) {
100805b261ecSmrg	filter->active= 0;
100905b261ecSmrg        return 0;
101005b261ecSmrg    }
101105b261ecSmrg    return 1;
101205b261ecSmrg}
101305b261ecSmrg
101405b261ecSmrg
101505b261ecSmrgstatic int
101605b261ecSmrg_XkbFilterDeviceBtn(	XkbSrvInfoPtr	xkbi,
101705b261ecSmrg			XkbFilterPtr	filter,
101805b261ecSmrg			unsigned	keycode,
101905b261ecSmrg			XkbAction *	pAction)
102005b261ecSmrg{
102105b261ecSmrgDeviceIntPtr	dev;
102205b261ecSmrgint		button;
102305b261ecSmrg
10244642e01fSmrg    if (xkbi->device == inputInfo.keyboard)
102505b261ecSmrg        return 0;
102605b261ecSmrg
102705b261ecSmrg    if (filter->keycode==0) {		/* initial press */
10284642e01fSmrg	_XkbLookupButtonDevice(&dev, pAction->devbtn.device, serverClient,
10294642e01fSmrg			       DixUnknownAccess, &button);
10304642e01fSmrg	if (!dev || !dev->public.on || dev == inputInfo.pointer)
103105b261ecSmrg	    return 1;
103205b261ecSmrg
103305b261ecSmrg	button= pAction->devbtn.button;
103405b261ecSmrg	if ((button<1)||(button>dev->button->numButtons))
103505b261ecSmrg	    return 1;
103605b261ecSmrg
103705b261ecSmrg	filter->keycode = keycode;
103805b261ecSmrg	filter->active = 1;
103905b261ecSmrg	filter->filterOthers = 0;
104005b261ecSmrg	filter->priv=0;
104105b261ecSmrg	filter->filter = _XkbFilterDeviceBtn;
104205b261ecSmrg	filter->upAction= *pAction;
104305b261ecSmrg	switch (pAction->type) {
104405b261ecSmrg	    case XkbSA_LockDeviceBtn:
104505b261ecSmrg		if ((pAction->devbtn.flags&XkbSA_LockNoLock)||
10464642e01fSmrg		    BitIsOn(dev->button->down, button))
104705b261ecSmrg		    return 0;
104805b261ecSmrg		XkbDDXFakeDeviceButton(dev,True,button);
104905b261ecSmrg		filter->upAction.type= XkbSA_NoAction;
105005b261ecSmrg		break;
105105b261ecSmrg	    case XkbSA_DeviceBtn:
105205b261ecSmrg		if (pAction->devbtn.count>0) {
105305b261ecSmrg		    int nClicks,i;
105405b261ecSmrg		    nClicks= pAction->btn.count;
105505b261ecSmrg		    for (i=0;i<nClicks;i++) {
105605b261ecSmrg			XkbDDXFakeDeviceButton(dev,True,button);
105705b261ecSmrg			XkbDDXFakeDeviceButton(dev,False,button);
105805b261ecSmrg		    }
105905b261ecSmrg		    filter->upAction.type= XkbSA_NoAction;
106005b261ecSmrg		}
106105b261ecSmrg		else XkbDDXFakeDeviceButton(dev,True,button);
106205b261ecSmrg		break;
106305b261ecSmrg	}
106405b261ecSmrg    }
106505b261ecSmrg    else if (filter->keycode==keycode) {
106605b261ecSmrg	int	button;
106705b261ecSmrg
106805b261ecSmrg	filter->active= 0;
10694642e01fSmrg	_XkbLookupButtonDevice(&dev, filter->upAction.devbtn.device,
10704642e01fSmrg			       serverClient, DixUnknownAccess, &button);
10714642e01fSmrg	if (!dev || !dev->public.on || dev == inputInfo.pointer)
107205b261ecSmrg	    return 1;
107305b261ecSmrg
107405b261ecSmrg	button= filter->upAction.btn.button;
107505b261ecSmrg	switch (filter->upAction.type) {
107605b261ecSmrg	    case XkbSA_LockDeviceBtn:
107705b261ecSmrg		if ((filter->upAction.devbtn.flags&XkbSA_LockNoUnlock)||
10784642e01fSmrg		    !BitIsOn(dev->button->down, button))
107905b261ecSmrg		    return 0;
108005b261ecSmrg		XkbDDXFakeDeviceButton(dev,False,button);
108105b261ecSmrg		break;
108205b261ecSmrg	    case XkbSA_DeviceBtn:
108305b261ecSmrg		XkbDDXFakeDeviceButton(dev,False,button);
108405b261ecSmrg		break;
108505b261ecSmrg	}
108605b261ecSmrg	filter->active = 0;
108705b261ecSmrg    }
108805b261ecSmrg    return 0;
108905b261ecSmrg}
109005b261ecSmrg
109105b261ecSmrgstatic XkbFilterPtr
109205b261ecSmrg_XkbNextFreeFilter(
109305b261ecSmrg	XkbSrvInfoPtr xkbi
109405b261ecSmrg)
109505b261ecSmrg{
109605b261ecSmrgregister int	i;
109705b261ecSmrg
109805b261ecSmrg    if (xkbi->szFilters==0) {
109905b261ecSmrg	xkbi->szFilters = 4;
110005b261ecSmrg	xkbi->filters = _XkbTypedCalloc(xkbi->szFilters,XkbFilterRec);
110105b261ecSmrg	/* 6/21/93 (ef) -- XXX! deal with allocation failure */
110205b261ecSmrg    }
110305b261ecSmrg    for (i=0;i<xkbi->szFilters;i++) {
110405b261ecSmrg	if (!xkbi->filters[i].active) {
110505b261ecSmrg	    xkbi->filters[i].keycode = 0;
110605b261ecSmrg	    return &xkbi->filters[i];
110705b261ecSmrg	}
110805b261ecSmrg    }
110905b261ecSmrg    xkbi->szFilters*=2;
111005b261ecSmrg    xkbi->filters= _XkbTypedRealloc(xkbi->filters,
111105b261ecSmrg                                    xkbi->szFilters,
111205b261ecSmrg                                    XkbFilterRec);
111305b261ecSmrg    /* 6/21/93 (ef) -- XXX! deal with allocation failure */
111405b261ecSmrg    bzero(&xkbi->filters[xkbi->szFilters/2],
111505b261ecSmrg            (xkbi->szFilters/2)*sizeof(XkbFilterRec));
111605b261ecSmrg    return &xkbi->filters[xkbi->szFilters/2];
111705b261ecSmrg}
111805b261ecSmrg
111905b261ecSmrgstatic int
112005b261ecSmrg_XkbApplyFilters(XkbSrvInfoPtr xkbi,unsigned kc,XkbAction *pAction)
112105b261ecSmrg{
112205b261ecSmrgregister int	i,send;
112305b261ecSmrg
112405b261ecSmrg    send= 1;
112505b261ecSmrg    for (i=0;i<xkbi->szFilters;i++) {
112605b261ecSmrg	if ((xkbi->filters[i].active)&&(xkbi->filters[i].filter))
112705b261ecSmrg	    send= ((*xkbi->filters[i].filter)(xkbi,&xkbi->filters[i],kc,pAction)
112805b261ecSmrg                    && send);
112905b261ecSmrg    }
113005b261ecSmrg    return send;
113105b261ecSmrg}
113205b261ecSmrg
113305b261ecSmrgvoid
113405b261ecSmrgXkbHandleActions(DeviceIntPtr dev,DeviceIntPtr kbd,xEvent *xE,int count)
113505b261ecSmrg{
113605b261ecSmrgint		key,bit,i;
11374642e01fSmrgCARD8		realMods = 0;
113805b261ecSmrgXkbSrvInfoPtr	xkbi;
113905b261ecSmrgKeyClassPtr	keyc;
114005b261ecSmrgint		changed,sendEvent;
114105b261ecSmrgBool		genStateNotify;
114205b261ecSmrgXkbStateRec	oldState;
114305b261ecSmrgXkbAction	act;
114405b261ecSmrgXkbFilterPtr	filter;
114505b261ecSmrgBool		keyEvent;
114605b261ecSmrgBool		pressEvent;
114705b261ecSmrgProcessInputProc backupproc;
114805b261ecSmrg
114905b261ecSmrgxkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
115005b261ecSmrg
115105b261ecSmrg    keyc= kbd->key;
115205b261ecSmrg    xkbi= keyc->xkbInfo;
115305b261ecSmrg    key= xE->u.u.detail;
115405b261ecSmrg    /* The state may change, so if we're not in the middle of sending a state
115505b261ecSmrg     * notify, prepare for it */
115605b261ecSmrg    if ((xkbi->flags&_XkbStateNotifyInProgress)==0) {
115705b261ecSmrg	oldState= xkbi->state;
115805b261ecSmrg	xkbi->flags|= _XkbStateNotifyInProgress;
115905b261ecSmrg	genStateNotify= True;
116005b261ecSmrg    }
116105b261ecSmrg    else genStateNotify= False;
116205b261ecSmrg
116305b261ecSmrg    xkbi->clearMods = xkbi->setMods = 0;
116405b261ecSmrg    xkbi->groupChange = 0;
116505b261ecSmrg
116605b261ecSmrg    sendEvent = 1;
116705b261ecSmrg    keyEvent= ((xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress)||
116805b261ecSmrg		(xE->u.u.type==KeyRelease)||(xE->u.u.type==DeviceKeyRelease));
116905b261ecSmrg    pressEvent= (xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress)||
117005b261ecSmrg		 (xE->u.u.type==ButtonPress)||(xE->u.u.type==DeviceButtonPress);
117105b261ecSmrg
117205b261ecSmrg    if (pressEvent) {
117305b261ecSmrg	if (keyEvent)
117405b261ecSmrg	    act = XkbGetKeyAction(xkbi,&xkbi->state,key);
117505b261ecSmrg	else {
117605b261ecSmrg	    act = XkbGetButtonAction(kbd,dev,key);
117705b261ecSmrg	    key|= BTN_ACT_FLAG;
117805b261ecSmrg	}
117905b261ecSmrg	sendEvent = _XkbApplyFilters(xkbi,key,&act);
118005b261ecSmrg	if (sendEvent) {
118105b261ecSmrg	    switch (act.type) {
118205b261ecSmrg		case XkbSA_SetMods:
118305b261ecSmrg		case XkbSA_SetGroup:
118405b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
118505b261ecSmrg		    sendEvent = _XkbFilterSetState(xkbi,filter,key,&act);
118605b261ecSmrg		    break;
118705b261ecSmrg		case XkbSA_LatchMods:
118805b261ecSmrg		case XkbSA_LatchGroup:
118905b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
119005b261ecSmrg		    sendEvent=_XkbFilterLatchState(xkbi,filter,key,&act);
119105b261ecSmrg		    break;
119205b261ecSmrg		case XkbSA_LockMods:
119305b261ecSmrg		case XkbSA_LockGroup:
119405b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
119505b261ecSmrg		    sendEvent=_XkbFilterLockState(xkbi,filter,key,&act);
119605b261ecSmrg		    break;
119705b261ecSmrg		case XkbSA_ISOLock:
119805b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
119905b261ecSmrg		    sendEvent=_XkbFilterISOLock(xkbi,filter,key,&act);
120005b261ecSmrg		    break;
120105b261ecSmrg		case XkbSA_MovePtr:
120205b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
120305b261ecSmrg		    sendEvent= _XkbFilterPointerMove(xkbi,filter,key,&act);
120405b261ecSmrg		    break;
120505b261ecSmrg		case XkbSA_PtrBtn:
120605b261ecSmrg		case XkbSA_LockPtrBtn:
120705b261ecSmrg		case XkbSA_SetPtrDflt:
120805b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
120905b261ecSmrg		    sendEvent= _XkbFilterPointerBtn(xkbi,filter,key,&act);
121005b261ecSmrg		    break;
121105b261ecSmrg		case XkbSA_Terminate:
121205b261ecSmrg		    sendEvent= XkbDDXTerminateServer(dev,key,&act);
121305b261ecSmrg		    break;
121405b261ecSmrg		case XkbSA_SwitchScreen:
121505b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
121605b261ecSmrg		    sendEvent=_XkbFilterSwitchScreen(xkbi,filter,key,&act);
121705b261ecSmrg		    break;
121805b261ecSmrg		case XkbSA_SetControls:
121905b261ecSmrg		case XkbSA_LockControls:
122005b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
122105b261ecSmrg		    sendEvent=_XkbFilterControls(xkbi,filter,key,&act);
122205b261ecSmrg		    break;
122305b261ecSmrg		case XkbSA_ActionMessage:
122405b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
122505b261ecSmrg		    sendEvent=_XkbFilterActionMessage(xkbi,filter,key,&act);
122605b261ecSmrg		    break;
122705b261ecSmrg		case XkbSA_RedirectKey:
122805b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
122905b261ecSmrg		    sendEvent= _XkbFilterRedirectKey(xkbi,filter,key,&act);
123005b261ecSmrg		    break;
123105b261ecSmrg		case XkbSA_DeviceBtn:
123205b261ecSmrg		case XkbSA_LockDeviceBtn:
123305b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
123405b261ecSmrg		    sendEvent= _XkbFilterDeviceBtn(xkbi,filter,key,&act);
123505b261ecSmrg		    break;
123605b261ecSmrg		case XkbSA_XFree86Private:
123705b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
123805b261ecSmrg		    sendEvent= _XkbFilterXF86Private(xkbi,filter,key,&act);
123905b261ecSmrg		    break;
124005b261ecSmrg	    }
124105b261ecSmrg	}
124205b261ecSmrg    }
124305b261ecSmrg    else {
124405b261ecSmrg	if (!keyEvent)
124505b261ecSmrg	    key|= BTN_ACT_FLAG;
124605b261ecSmrg	sendEvent = _XkbApplyFilters(xkbi,key,NULL);
124705b261ecSmrg    }
124805b261ecSmrg
124905b261ecSmrg    if (xkbi->groupChange!=0)
125005b261ecSmrg	xkbi->state.base_group+= xkbi->groupChange;
125105b261ecSmrg    if (xkbi->setMods) {
125205b261ecSmrg	for (i=0,bit=1; xkbi->setMods; i++,bit<<=1 ) {
125305b261ecSmrg	    if (xkbi->setMods&bit) {
125405b261ecSmrg		keyc->modifierKeyCount[i]++;
125505b261ecSmrg		xkbi->state.base_mods|= bit;
125605b261ecSmrg		xkbi->setMods&= ~bit;
125705b261ecSmrg	    }
125805b261ecSmrg	}
125905b261ecSmrg    }
126005b261ecSmrg    if (xkbi->clearMods) {
126105b261ecSmrg	for (i=0,bit=1; xkbi->clearMods; i++,bit<<=1 ) {
126205b261ecSmrg	    if (xkbi->clearMods&bit) {
126305b261ecSmrg		keyc->modifierKeyCount[i]--;
126405b261ecSmrg		if (keyc->modifierKeyCount[i]<=0) {
126505b261ecSmrg		    xkbi->state.base_mods&= ~bit;
126605b261ecSmrg		    keyc->modifierKeyCount[i] = 0;
126705b261ecSmrg		}
126805b261ecSmrg		xkbi->clearMods&= ~bit;
126905b261ecSmrg	    }
127005b261ecSmrg	}
127105b261ecSmrg    }
127205b261ecSmrg
127305b261ecSmrg    if (sendEvent) {
12744642e01fSmrg        DeviceIntPtr tmpdev;
127505b261ecSmrg	if (keyEvent) {
127605b261ecSmrg	    realMods = keyc->modifierMap[key];
127705b261ecSmrg	    keyc->modifierMap[key] = 0;
12784642e01fSmrg            tmpdev = dev;
12794642e01fSmrg        } else
12804642e01fSmrg            tmpdev = GetPairedDevice(dev);
128105b261ecSmrg
12824642e01fSmrg        UNWRAP_PROCESS_INPUT_PROC(tmpdev,xkbPrivPtr, backupproc);
12834642e01fSmrg        dev->public.processInputProc(xE,tmpdev,count);
12844642e01fSmrg        COND_WRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr,
128505b261ecSmrg                                     backupproc,xkbUnwrapProc);
128605b261ecSmrg        if (keyEvent)
128705b261ecSmrg	    keyc->modifierMap[key] = realMods;
128805b261ecSmrg    }
128905b261ecSmrg    else if (keyEvent) {
129005b261ecSmrg	FixKeyState(xE,dev);
129105b261ecSmrg    }
129205b261ecSmrg
129305b261ecSmrg    xkbi->prev_state= oldState;
129405b261ecSmrg    XkbComputeDerivedState(xkbi);
129505b261ecSmrg    keyc->prev_state= keyc->state;
129605b261ecSmrg    keyc->state= XkbStateFieldFromRec(&xkbi->state);
129705b261ecSmrg    changed = XkbStateChangedFlags(&oldState,&xkbi->state);
129805b261ecSmrg    if (genStateNotify) {
129905b261ecSmrg	if (changed) {
130005b261ecSmrg	    xkbStateNotify	sn;
130105b261ecSmrg	    sn.keycode= key;
130205b261ecSmrg	    sn.eventType= xE->u.u.type;
130305b261ecSmrg	    sn.requestMajor = sn.requestMinor = 0;
130405b261ecSmrg	    sn.changed= changed;
130505b261ecSmrg	    XkbSendStateNotify(dev,&sn);
130605b261ecSmrg	}
130705b261ecSmrg	xkbi->flags&= ~_XkbStateNotifyInProgress;
130805b261ecSmrg    }
130905b261ecSmrg    changed= XkbIndicatorsToUpdate(dev,changed,False);
131005b261ecSmrg    if (changed) {
131105b261ecSmrg	XkbEventCauseRec	cause;
131205b261ecSmrg	XkbSetCauseKey(&cause,key,xE->u.u.type);
131305b261ecSmrg	XkbUpdateIndicators(dev,changed,False,NULL,&cause);
131405b261ecSmrg    }
131505b261ecSmrg    return;
131605b261ecSmrg}
131705b261ecSmrg
131805b261ecSmrgint
131905b261ecSmrgXkbLatchModifiers(DeviceIntPtr pXDev,CARD8 mask,CARD8 latches)
132005b261ecSmrg{
132105b261ecSmrgXkbSrvInfoPtr	xkbi;
132205b261ecSmrgXkbFilterPtr	filter;
132305b261ecSmrgXkbAction	act;
132405b261ecSmrgunsigned	clear;
132505b261ecSmrg
132605b261ecSmrg    if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) {
132705b261ecSmrg	xkbi = pXDev->key->xkbInfo;
132805b261ecSmrg	clear= (mask&(~latches));
132905b261ecSmrg	xkbi->state.latched_mods&= ~clear;
133005b261ecSmrg	/* Clear any pending latch to locks.
133105b261ecSmrg	 */
133205b261ecSmrg	act.type = XkbSA_NoAction;
133305b261ecSmrg	_XkbApplyFilters(xkbi,SYNTHETIC_KEYCODE,&act);
133405b261ecSmrg	act.type = XkbSA_LatchMods;
133505b261ecSmrg	act.mods.flags = 0;
133605b261ecSmrg	act.mods.mask  = mask&latches;
133705b261ecSmrg	filter = _XkbNextFreeFilter(xkbi);
133805b261ecSmrg	_XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act);
133905b261ecSmrg	_XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL);
134005b261ecSmrg	return Success;
134105b261ecSmrg    }
134205b261ecSmrg    return BadValue;
134305b261ecSmrg}
134405b261ecSmrg
134505b261ecSmrgint
134605b261ecSmrgXkbLatchGroup(DeviceIntPtr pXDev,int group)
134705b261ecSmrg{
134805b261ecSmrgXkbSrvInfoPtr	xkbi;
134905b261ecSmrgXkbFilterPtr	filter;
135005b261ecSmrgXkbAction	act;
135105b261ecSmrg
135205b261ecSmrg    if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) {
135305b261ecSmrg	xkbi = pXDev->key->xkbInfo;
135405b261ecSmrg	act.type = XkbSA_LatchGroup;
135505b261ecSmrg	act.group.flags = 0;
135605b261ecSmrg	XkbSASetGroup(&act.group,group);
135705b261ecSmrg	filter = _XkbNextFreeFilter(xkbi);
135805b261ecSmrg	_XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act);
135905b261ecSmrg	_XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL);
136005b261ecSmrg	return Success;
136105b261ecSmrg    }
136205b261ecSmrg    return BadValue;
136305b261ecSmrg}
136405b261ecSmrg
136505b261ecSmrg/***====================================================================***/
136605b261ecSmrg
136705b261ecSmrgvoid
136805b261ecSmrgXkbClearAllLatchesAndLocks(	DeviceIntPtr		dev,
136905b261ecSmrg				XkbSrvInfoPtr		xkbi,
137005b261ecSmrg				Bool			genEv,
137105b261ecSmrg				XkbEventCausePtr	cause)
137205b261ecSmrg{
137305b261ecSmrgXkbStateRec	os;
137405b261ecSmrgxkbStateNotify	sn;
137505b261ecSmrg
137605b261ecSmrg    sn.changed= 0;
137705b261ecSmrg    os= xkbi->state;
137805b261ecSmrg    if (os.latched_mods) { /* clear all latches */
137905b261ecSmrg	XkbLatchModifiers(dev,~0,0);
138005b261ecSmrg	sn.changed|= XkbModifierLatchMask;
138105b261ecSmrg    }
138205b261ecSmrg    if (os.latched_group) {
138305b261ecSmrg	XkbLatchGroup(dev,0);
138405b261ecSmrg	sn.changed|= XkbGroupLatchMask;
138505b261ecSmrg    }
138605b261ecSmrg    if (os.locked_mods) {
138705b261ecSmrg	xkbi->state.locked_mods= 0;
138805b261ecSmrg	sn.changed|= XkbModifierLockMask;
138905b261ecSmrg    }
139005b261ecSmrg    if (os.locked_group) {
139105b261ecSmrg	xkbi->state.locked_group= 0;
139205b261ecSmrg	sn.changed|= XkbGroupLockMask;
139305b261ecSmrg    }
139405b261ecSmrg    if ( genEv && sn.changed) {
139505b261ecSmrg	CARD32 	changed;
139605b261ecSmrg
139705b261ecSmrg	XkbComputeDerivedState(xkbi);
139805b261ecSmrg	sn.keycode= 		cause->kc;
139905b261ecSmrg	sn.eventType=		cause->event;
140005b261ecSmrg	sn.requestMajor= 	cause->mjr;
140105b261ecSmrg	sn.requestMinor= 	cause->mnr;
140205b261ecSmrg	sn.changed= XkbStateChangedFlags(&os,&xkbi->state);
140305b261ecSmrg	XkbSendStateNotify(dev,&sn);
140405b261ecSmrg	changed= XkbIndicatorsToUpdate(dev,sn.changed,False);
140505b261ecSmrg	if (changed) {
140605b261ecSmrg	    XkbUpdateIndicators(dev,changed,True,NULL,cause);
140705b261ecSmrg	}
140805b261ecSmrg    }
140905b261ecSmrg    return;
141005b261ecSmrg}
141105b261ecSmrg
1412