xkbActions.c revision 6747b715
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#include <X11/X.h>
3405b261ecSmrg#include <X11/Xproto.h>
3505b261ecSmrg#include <X11/keysym.h>
3605b261ecSmrg#include "misc.h"
3705b261ecSmrg#include "inputstr.h"
3805b261ecSmrg#include "exevents.h"
396747b715Smrg#include "eventstr.h"
4005b261ecSmrg#include <xkbsrv.h>
4105b261ecSmrg#include "xkb.h"
4205b261ecSmrg#include <ctype.h>
436747b715Smrg#include "mi.h"
446747b715Smrg#include "mipointer.h"
4505b261ecSmrg#define EXTENSION_EVENT_BASE 64
4605b261ecSmrg
476747b715SmrgDevPrivateKeyRec xkbDevicePrivateKeyRec;
486747b715Smrg
496747b715Smrgvoid XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button);
506747b715Smrgstatic void XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y);
5105b261ecSmrg
5205b261ecSmrgvoid
5305b261ecSmrgxkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc,
5405b261ecSmrg                   pointer data)
5505b261ecSmrg{
5605b261ecSmrg    xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device);
5705b261ecSmrg    ProcessInputProc backupproc;
5805b261ecSmrg    if(xkbPrivPtr->unwrapProc)
5905b261ecSmrg	xkbPrivPtr->unwrapProc = NULL;
6005b261ecSmrg
6105b261ecSmrg    UNWRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr, backupproc);
6205b261ecSmrg    proc(device,data);
6305b261ecSmrg    COND_WRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr,
6405b261ecSmrg				 backupproc,xkbUnwrapProc);
6505b261ecSmrg}
6605b261ecSmrg
676747b715SmrgBool
686747b715SmrgXkbInitPrivates(void)
696747b715Smrg{
706747b715Smrg    return dixRegisterPrivateKey(&xkbDevicePrivateKeyRec, PRIVATE_DEVICE, 0);
716747b715Smrg}
7205b261ecSmrg
7305b261ecSmrgvoid
7405b261ecSmrgXkbSetExtension(DeviceIntPtr device, ProcessInputProc proc)
7505b261ecSmrg{
7605b261ecSmrg    xkbDeviceInfoPtr xkbPrivPtr;
7705b261ecSmrg
786747b715Smrg    xkbPrivPtr = (xkbDeviceInfoPtr) calloc(1, sizeof(xkbDeviceInfoRec));
7905b261ecSmrg    if (!xkbPrivPtr)
8005b261ecSmrg	return;
8105b261ecSmrg    xkbPrivPtr->unwrapProc = NULL;
8205b261ecSmrg
834642e01fSmrg    dixSetPrivate(&device->devPrivates, xkbDevicePrivateKey, xkbPrivPtr);
8405b261ecSmrg    WRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, proc, xkbUnwrapProc);
8505b261ecSmrg}
8605b261ecSmrg
8705b261ecSmrg/***====================================================================***/
8805b261ecSmrg
8905b261ecSmrgstatic XkbAction
9005b261ecSmrg_FixUpAction(XkbDescPtr xkb,XkbAction *act)
9105b261ecSmrg{
9205b261ecSmrgstatic XkbAction	fake;
9305b261ecSmrg
9405b261ecSmrg    if (XkbIsPtrAction(act)&&(!(xkb->ctrls->enabled_ctrls&XkbMouseKeysMask))) {
9505b261ecSmrg	fake.type = XkbSA_NoAction;
9605b261ecSmrg	return fake;
9705b261ecSmrg    }
9805b261ecSmrg    if (xkb->ctrls->enabled_ctrls&XkbStickyKeysMask) {
9905b261ecSmrg	if (act->any.type==XkbSA_SetMods) {
10005b261ecSmrg	    fake.mods.type = XkbSA_LatchMods;
10105b261ecSmrg	    fake.mods.mask = act->mods.mask;
10205b261ecSmrg	    if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask))
10305b261ecSmrg		 fake.mods.flags= XkbSA_ClearLocks|XkbSA_LatchToLock;
10405b261ecSmrg	    else fake.mods.flags= XkbSA_ClearLocks;
10505b261ecSmrg	    return fake;
10605b261ecSmrg	}
10705b261ecSmrg	if (act->any.type==XkbSA_SetGroup) {
10805b261ecSmrg	    fake.group.type = XkbSA_LatchGroup;
10905b261ecSmrg	    if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask))
11005b261ecSmrg		 fake.group.flags= XkbSA_ClearLocks|XkbSA_LatchToLock;
11105b261ecSmrg	    else fake.group.flags= XkbSA_ClearLocks;
11205b261ecSmrg	    XkbSASetGroup(&fake.group,XkbSAGroup(&act->group));
11305b261ecSmrg	    return fake;
11405b261ecSmrg	}
11505b261ecSmrg    }
11605b261ecSmrg    return *act;
11705b261ecSmrg}
11805b261ecSmrg
11905b261ecSmrgstatic XkbAction
12005b261ecSmrgXkbGetKeyAction(XkbSrvInfoPtr xkbi,XkbStatePtr xkbState,CARD8 key)
12105b261ecSmrg{
12205b261ecSmrgint			effectiveGroup;
12305b261ecSmrgint			col;
12405b261ecSmrgXkbDescPtr		xkb;
12505b261ecSmrgXkbKeyTypePtr		type;
12605b261ecSmrgXkbAction *		pActs;
12705b261ecSmrgstatic XkbAction 	fake;
12805b261ecSmrg
12905b261ecSmrg    xkb= xkbi->desc;
13005b261ecSmrg    if (!XkbKeyHasActions(xkb,key) || !XkbKeycodeInRange(xkb,key)) {
13105b261ecSmrg	fake.type = XkbSA_NoAction;
13205b261ecSmrg	return fake;
13305b261ecSmrg    }
13405b261ecSmrg    pActs= XkbKeyActionsPtr(xkb,key);
13505b261ecSmrg    col= 0;
1366747b715Smrg
1376747b715Smrg    effectiveGroup = XkbGetEffectiveGroup(xkbi, xkbState, key);
1386747b715Smrg    if (effectiveGroup != XkbGroup1Index)
1396747b715Smrg        col += (effectiveGroup * XkbKeyGroupsWidth(xkb, key));
1406747b715Smrg
14105b261ecSmrg    type= XkbKeyKeyType(xkb,key,effectiveGroup);
14205b261ecSmrg    if (type->map!=NULL) {
14305b261ecSmrg	register unsigned		i,mods;
14405b261ecSmrg	register XkbKTMapEntryPtr	entry;
14505b261ecSmrg	mods= xkbState->mods&type->mods.mask;
14605b261ecSmrg	for (entry= type->map,i=0;i<type->map_count;i++,entry++) {
14705b261ecSmrg	    if ((entry->active)&&(entry->mods.mask==mods)) {
14805b261ecSmrg		col+= entry->level;
14905b261ecSmrg		break;
15005b261ecSmrg	    }
15105b261ecSmrg	}
15205b261ecSmrg    }
15305b261ecSmrg    if (pActs[col].any.type==XkbSA_NoAction)
15405b261ecSmrg	return pActs[col];
15505b261ecSmrg    fake= _FixUpAction(xkb,&pActs[col]);
15605b261ecSmrg    return fake;
15705b261ecSmrg}
15805b261ecSmrg
15905b261ecSmrgstatic XkbAction
16005b261ecSmrgXkbGetButtonAction(DeviceIntPtr kbd,DeviceIntPtr dev,int button)
16105b261ecSmrg{
16205b261ecSmrgXkbAction fake;
16305b261ecSmrg   if ((dev->button)&&(dev->button->xkb_acts)) {
16405b261ecSmrg	if (dev->button->xkb_acts[button-1].any.type!=XkbSA_NoAction) {
16505b261ecSmrg	    fake= _FixUpAction(kbd->key->xkbInfo->desc,
16605b261ecSmrg					&dev->button->xkb_acts[button-1]);
16705b261ecSmrg	    return fake;
16805b261ecSmrg	}
16905b261ecSmrg   }
17005b261ecSmrg   fake.any.type= XkbSA_NoAction;
17105b261ecSmrg   return fake;
17205b261ecSmrg}
17305b261ecSmrg
17405b261ecSmrg/***====================================================================***/
17505b261ecSmrg
17605b261ecSmrg#define	SYNTHETIC_KEYCODE	1
17705b261ecSmrg#define	BTN_ACT_FLAG		0x100
17805b261ecSmrg
17905b261ecSmrgstatic int
18005b261ecSmrg_XkbFilterSetState(	XkbSrvInfoPtr	xkbi,
18105b261ecSmrg			XkbFilterPtr	filter,
18205b261ecSmrg			unsigned	keycode,
18305b261ecSmrg			XkbAction *pAction)
18405b261ecSmrg{
18505b261ecSmrg    if (filter->keycode==0) {		/* initial press */
18605b261ecSmrg	filter->keycode = keycode;
18705b261ecSmrg	filter->active = 1;
18805b261ecSmrg	filter->filterOthers = ((pAction->mods.mask&XkbSA_ClearLocks)!=0);
18905b261ecSmrg	filter->priv = 0;
19005b261ecSmrg	filter->filter = _XkbFilterSetState;
19105b261ecSmrg	if (pAction->type==XkbSA_SetMods) {
19205b261ecSmrg	    filter->upAction = *pAction;
19305b261ecSmrg	    xkbi->setMods= pAction->mods.mask;
19405b261ecSmrg	}
19505b261ecSmrg	else {
19605b261ecSmrg	    xkbi->groupChange = XkbSAGroup(&pAction->group);
19705b261ecSmrg	    if (pAction->group.flags&XkbSA_GroupAbsolute)
19805b261ecSmrg		xkbi->groupChange-= xkbi->state.base_group;
19905b261ecSmrg	    filter->upAction= *pAction;
20005b261ecSmrg	    XkbSASetGroup(&filter->upAction.group,xkbi->groupChange);
20105b261ecSmrg	}
20205b261ecSmrg    }
20305b261ecSmrg    else if (filter->keycode==keycode) {
20405b261ecSmrg	if (filter->upAction.type==XkbSA_SetMods) {
20505b261ecSmrg	    xkbi->clearMods = filter->upAction.mods.mask;
20605b261ecSmrg	    if (filter->upAction.mods.flags&XkbSA_ClearLocks) {
20705b261ecSmrg		xkbi->state.locked_mods&= ~filter->upAction.mods.mask;
20805b261ecSmrg	    }
20905b261ecSmrg	}
21005b261ecSmrg	else {
21105b261ecSmrg	    if (filter->upAction.group.flags&XkbSA_ClearLocks) {
21205b261ecSmrg		xkbi->state.locked_group = 0;
21305b261ecSmrg	    }
21405b261ecSmrg	    xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
21505b261ecSmrg	}
21605b261ecSmrg	filter->active = 0;
21705b261ecSmrg    }
21805b261ecSmrg    else {
21905b261ecSmrg	filter->upAction.mods.flags&= ~XkbSA_ClearLocks;
22005b261ecSmrg	filter->filterOthers = 0;
22105b261ecSmrg    }
22205b261ecSmrg    return 1;
22305b261ecSmrg}
22405b261ecSmrg
22505b261ecSmrg#define	LATCH_KEY_DOWN	1
22605b261ecSmrg#define	LATCH_PENDING	2
22705b261ecSmrg#define	NO_LATCH	3
22805b261ecSmrg
22905b261ecSmrgstatic int
23005b261ecSmrg_XkbFilterLatchState(	XkbSrvInfoPtr	xkbi,
23105b261ecSmrg			XkbFilterPtr	filter,
23205b261ecSmrg			unsigned	keycode,
23305b261ecSmrg			XkbAction *	pAction)
23405b261ecSmrg{
23505b261ecSmrg
23605b261ecSmrg    if (filter->keycode==0) {			/* initial press */
23705b261ecSmrg	filter->keycode = keycode;
23805b261ecSmrg	filter->active = 1;
23905b261ecSmrg	filter->filterOthers = 1;
24005b261ecSmrg	filter->priv = LATCH_KEY_DOWN;
24105b261ecSmrg	filter->filter = _XkbFilterLatchState;
24205b261ecSmrg	if (pAction->type==XkbSA_LatchMods) {
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 ( pAction && (filter->priv==LATCH_PENDING) ) {
25505b261ecSmrg	if (((1<<pAction->type)&XkbSA_BreakLatch)!=0) {
25605b261ecSmrg	    filter->active = 0;
25705b261ecSmrg	    if (filter->upAction.type==XkbSA_LatchMods)
25805b261ecSmrg		 xkbi->state.latched_mods&= ~filter->upAction.mods.mask;
25905b261ecSmrg	    else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group);
26005b261ecSmrg	}
26105b261ecSmrg	else if ((pAction->type==filter->upAction.type)&&
26205b261ecSmrg		 (pAction->mods.flags==filter->upAction.mods.flags)&&
26305b261ecSmrg		 (pAction->mods.mask==filter->upAction.mods.mask)) {
26405b261ecSmrg	    if (filter->upAction.mods.flags&XkbSA_LatchToLock) {
26505b261ecSmrg		XkbControlsPtr ctrls= xkbi->desc->ctrls;
26605b261ecSmrg		if (filter->upAction.type==XkbSA_LatchMods)
26705b261ecSmrg		     pAction->mods.type= XkbSA_LockMods;
26805b261ecSmrg		else pAction->group.type= XkbSA_LockGroup;
26905b261ecSmrg		if (XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask)&&
27005b261ecSmrg		    		(ctrls->enabled_ctrls&XkbStickyKeysMask)) {
27105b261ecSmrg		    XkbDDXAccessXBeep(xkbi->device,_BEEP_STICKY_LOCK,
27205b261ecSmrg						XkbStickyKeysMask);
27305b261ecSmrg		}
27405b261ecSmrg	    }
27505b261ecSmrg	    else {
27605b261ecSmrg		if (filter->upAction.type==XkbSA_LatchMods)
27705b261ecSmrg		     pAction->mods.type= XkbSA_SetMods;
27805b261ecSmrg		else pAction->group.type= XkbSA_SetGroup;
27905b261ecSmrg	    }
28005b261ecSmrg	    if (filter->upAction.type==XkbSA_LatchMods)
28105b261ecSmrg		 xkbi->state.latched_mods&= ~filter->upAction.mods.mask;
28205b261ecSmrg	    else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group);
28305b261ecSmrg	    filter->active = 0;
28405b261ecSmrg	}
28505b261ecSmrg    }
28605b261ecSmrg    else if (filter->keycode==keycode) {	/* release */
28705b261ecSmrg	XkbControlsPtr	ctrls= xkbi->desc->ctrls;
28805b261ecSmrg	int		needBeep;
28905b261ecSmrg	int		beepType= _BEEP_NONE;
29005b261ecSmrg
29105b261ecSmrg	needBeep= ((ctrls->enabled_ctrls&XkbStickyKeysMask)&&
29205b261ecSmrg			XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask));
29305b261ecSmrg	if (filter->upAction.type==XkbSA_LatchMods) {
29405b261ecSmrg	    xkbi->clearMods = filter->upAction.mods.mask;
29505b261ecSmrg	    if ((filter->upAction.mods.flags&XkbSA_ClearLocks)&&
29605b261ecSmrg		 (xkbi->clearMods&xkbi->state.locked_mods)==xkbi->clearMods) {
29705b261ecSmrg		xkbi->state.locked_mods&= ~xkbi->clearMods;
29805b261ecSmrg		filter->priv= NO_LATCH;
29905b261ecSmrg		beepType= _BEEP_STICKY_UNLOCK;
30005b261ecSmrg	    }
30105b261ecSmrg	}
30205b261ecSmrg	else {
30305b261ecSmrg	    xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
30405b261ecSmrg	    if ((filter->upAction.group.flags&XkbSA_ClearLocks)&&
30505b261ecSmrg						(xkbi->state.locked_group)) {
30605b261ecSmrg		xkbi->state.locked_group = 0;
30705b261ecSmrg		filter->priv = NO_LATCH;
30805b261ecSmrg		beepType= _BEEP_STICKY_UNLOCK;
30905b261ecSmrg	    }
31005b261ecSmrg	}
31105b261ecSmrg	if (filter->priv==NO_LATCH) {
31205b261ecSmrg	    filter->active= 0;
31305b261ecSmrg	}
31405b261ecSmrg	else {
31505b261ecSmrg	    filter->priv= LATCH_PENDING;
31605b261ecSmrg	    if (filter->upAction.type==XkbSA_LatchMods) {
31705b261ecSmrg		xkbi->state.latched_mods |= filter->upAction.mods.mask;
31805b261ecSmrg		needBeep = xkbi->state.latched_mods ? needBeep : 0;
31905b261ecSmrg		xkbi->state.latched_mods |= filter->upAction.mods.mask;
32005b261ecSmrg	    }
32105b261ecSmrg	    else {
32205b261ecSmrg		xkbi->state.latched_group+= XkbSAGroup(&filter->upAction.group);
32305b261ecSmrg	    }
32405b261ecSmrg	    if (needBeep && (beepType==_BEEP_NONE))
32505b261ecSmrg		beepType= _BEEP_STICKY_LATCH;
32605b261ecSmrg	}
32705b261ecSmrg	if (needBeep && (beepType!=_BEEP_NONE))
32805b261ecSmrg	    XkbDDXAccessXBeep(xkbi->device,beepType,XkbStickyKeysMask);
32905b261ecSmrg    }
33005b261ecSmrg    else if (filter->priv==LATCH_KEY_DOWN) {
33105b261ecSmrg	filter->priv= NO_LATCH;
33205b261ecSmrg	filter->filterOthers = 0;
33305b261ecSmrg    }
33405b261ecSmrg    return 1;
33505b261ecSmrg}
33605b261ecSmrg
33705b261ecSmrgstatic int
33805b261ecSmrg_XkbFilterLockState(	XkbSrvInfoPtr	xkbi,
33905b261ecSmrg			XkbFilterPtr	filter,
34005b261ecSmrg			unsigned	keycode,
34105b261ecSmrg			XkbAction *	pAction)
34205b261ecSmrg{
34305b261ecSmrg    if (pAction&&(pAction->type==XkbSA_LockGroup)) {
34405b261ecSmrg	if (pAction->group.flags&XkbSA_GroupAbsolute)
34505b261ecSmrg	     xkbi->state.locked_group= XkbSAGroup(&pAction->group);
34605b261ecSmrg	else xkbi->state.locked_group+= XkbSAGroup(&pAction->group);
34705b261ecSmrg	return 1;
34805b261ecSmrg    }
34905b261ecSmrg    if (filter->keycode==0) {		/* initial press */
35005b261ecSmrg	filter->keycode = keycode;
35105b261ecSmrg	filter->active = 1;
35205b261ecSmrg	filter->filterOthers = 0;
35305b261ecSmrg	filter->priv = 0;
35405b261ecSmrg	filter->filter = _XkbFilterLockState;
35505b261ecSmrg	filter->upAction = *pAction;
35605b261ecSmrg	xkbi->state.locked_mods^= pAction->mods.mask;
35705b261ecSmrg	xkbi->setMods = pAction->mods.mask;
35805b261ecSmrg    }
35905b261ecSmrg    else if (filter->keycode==keycode) {
36005b261ecSmrg	filter->active = 0;
36105b261ecSmrg	xkbi->clearMods = filter->upAction.mods.mask;
36205b261ecSmrg    }
36305b261ecSmrg    return 1;
36405b261ecSmrg}
36505b261ecSmrg
36605b261ecSmrg#define	ISO_KEY_DOWN		0
36705b261ecSmrg#define	NO_ISO_LOCK		1
36805b261ecSmrg
36905b261ecSmrgstatic int
37005b261ecSmrg_XkbFilterISOLock(	XkbSrvInfoPtr	xkbi,
37105b261ecSmrg			XkbFilterPtr	filter,
37205b261ecSmrg			unsigned	keycode,
37305b261ecSmrg			XkbAction *	pAction)
37405b261ecSmrg{
37505b261ecSmrg
37605b261ecSmrg    if (filter->keycode==0) {		/* initial press */
37705b261ecSmrg	CARD8	flags= pAction->iso.flags;
37805b261ecSmrg
37905b261ecSmrg	filter->keycode = keycode;
38005b261ecSmrg	filter->active = 1;
38105b261ecSmrg	filter->filterOthers = 1;
38205b261ecSmrg	filter->priv = ISO_KEY_DOWN;
38305b261ecSmrg	filter->upAction = *pAction;
38405b261ecSmrg	filter->filter = _XkbFilterISOLock;
38505b261ecSmrg	if (flags&XkbSA_ISODfltIsGroup) {
38605b261ecSmrg	    xkbi->groupChange = XkbSAGroup(&pAction->iso);
38705b261ecSmrg	    xkbi->setMods = 0;
38805b261ecSmrg	}
38905b261ecSmrg	else {
39005b261ecSmrg	    xkbi->setMods = pAction->iso.mask;
39105b261ecSmrg	    xkbi->groupChange = 0;
39205b261ecSmrg	}
39305b261ecSmrg	if ((!(flags&XkbSA_ISONoAffectMods))&&(xkbi->state.base_mods)) {
39405b261ecSmrg	    filter->priv= NO_ISO_LOCK;
39505b261ecSmrg	    xkbi->state.locked_mods^= xkbi->state.base_mods;
39605b261ecSmrg	}
39705b261ecSmrg	if ((!(flags&XkbSA_ISONoAffectGroup))&&(xkbi->state.base_group)) {
39805b261ecSmrg/* 6/22/93 (ef) -- lock groups if group key is down first */
39905b261ecSmrg	}
40005b261ecSmrg	if (!(flags&XkbSA_ISONoAffectPtr)) {
40105b261ecSmrg/* 6/22/93 (ef) -- lock mouse buttons if they're down */
40205b261ecSmrg	}
40305b261ecSmrg    }
40405b261ecSmrg    else if (filter->keycode==keycode) {
40505b261ecSmrg	CARD8	flags= filter->upAction.iso.flags;
40605b261ecSmrg
40705b261ecSmrg	if (flags&XkbSA_ISODfltIsGroup) {
40805b261ecSmrg	    xkbi->groupChange = -XkbSAGroup(&filter->upAction.iso);
40905b261ecSmrg	    xkbi->clearMods = 0;
41005b261ecSmrg	    if (filter->priv==ISO_KEY_DOWN)
41105b261ecSmrg		xkbi->state.locked_group+= XkbSAGroup(&filter->upAction.iso);
41205b261ecSmrg	}
41305b261ecSmrg	else {
41405b261ecSmrg	    xkbi->clearMods= filter->upAction.iso.mask;
41505b261ecSmrg	    xkbi->groupChange= 0;
41605b261ecSmrg	    if (filter->priv==ISO_KEY_DOWN)
41705b261ecSmrg		xkbi->state.locked_mods^= filter->upAction.iso.mask;
41805b261ecSmrg	}
41905b261ecSmrg	filter->active = 0;
42005b261ecSmrg    }
42105b261ecSmrg    else if (pAction) {
42205b261ecSmrg	CARD8	flags= filter->upAction.iso.flags;
42305b261ecSmrg
42405b261ecSmrg	switch (pAction->type) {
42505b261ecSmrg	    case XkbSA_SetMods: case XkbSA_LatchMods:
42605b261ecSmrg		if (!(flags&XkbSA_ISONoAffectMods)) {
42705b261ecSmrg		    pAction->type= XkbSA_LockMods;
42805b261ecSmrg		    filter->priv= NO_ISO_LOCK;
42905b261ecSmrg		}
43005b261ecSmrg		break;
43105b261ecSmrg	    case XkbSA_SetGroup: case XkbSA_LatchGroup:
43205b261ecSmrg		if (!(flags&XkbSA_ISONoAffectGroup)) {
43305b261ecSmrg		    pAction->type= XkbSA_LockGroup;
43405b261ecSmrg		    filter->priv= NO_ISO_LOCK;
43505b261ecSmrg		}
43605b261ecSmrg		break;
43705b261ecSmrg	    case XkbSA_PtrBtn:
43805b261ecSmrg		if (!(flags&XkbSA_ISONoAffectPtr)) {
43905b261ecSmrg		     pAction->type= XkbSA_LockPtrBtn;
44005b261ecSmrg		     filter->priv= NO_ISO_LOCK;
44105b261ecSmrg		}
44205b261ecSmrg		break;
44305b261ecSmrg	    case XkbSA_SetControls:
44405b261ecSmrg		if (!(flags&XkbSA_ISONoAffectCtrls)) {
44505b261ecSmrg		    pAction->type= XkbSA_LockControls;
44605b261ecSmrg		    filter->priv= NO_ISO_LOCK;
44705b261ecSmrg		}
44805b261ecSmrg		break;
44905b261ecSmrg	}
45005b261ecSmrg    }
45105b261ecSmrg    return 1;
45205b261ecSmrg}
45305b261ecSmrg
45405b261ecSmrg
45505b261ecSmrgstatic CARD32
45605b261ecSmrg_XkbPtrAccelExpire(OsTimerPtr timer,CARD32 now,pointer arg)
45705b261ecSmrg{
45805b261ecSmrgXkbSrvInfoPtr	xkbi= (XkbSrvInfoPtr)arg;
45905b261ecSmrgXkbControlsPtr	ctrls= xkbi->desc->ctrls;
46005b261ecSmrgint		dx,dy;
46105b261ecSmrg
46205b261ecSmrg    if (xkbi->mouseKey==0)
46305b261ecSmrg	return 0;
46405b261ecSmrg
46505b261ecSmrg    if (xkbi->mouseKeysAccel) {
46605b261ecSmrg	if ((xkbi->mouseKeysCounter)<ctrls->mk_time_to_max) {
46705b261ecSmrg	    double step;
46805b261ecSmrg	    xkbi->mouseKeysCounter++;
46905b261ecSmrg	    step= xkbi->mouseKeysCurveFactor*
47005b261ecSmrg		 pow((double)xkbi->mouseKeysCounter,xkbi->mouseKeysCurve);
47105b261ecSmrg	    if (xkbi->mouseKeysDX<0)
47205b261ecSmrg		 dx= floor( ((double)xkbi->mouseKeysDX)*step );
47305b261ecSmrg	    else dx=  ceil( ((double)xkbi->mouseKeysDX)*step );
47405b261ecSmrg	    if (xkbi->mouseKeysDY<0)
47505b261ecSmrg		 dy= floor( ((double)xkbi->mouseKeysDY)*step );
47605b261ecSmrg	    else dy=  ceil( ((double)xkbi->mouseKeysDY)*step );
47705b261ecSmrg	}
47805b261ecSmrg	else {
47905b261ecSmrg	    dx= xkbi->mouseKeysDX*ctrls->mk_max_speed;
48005b261ecSmrg	    dy= xkbi->mouseKeysDY*ctrls->mk_max_speed;
48105b261ecSmrg	}
48205b261ecSmrg	if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteX)
48305b261ecSmrg	    dx= xkbi->mouseKeysDX;
48405b261ecSmrg	if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteY)
48505b261ecSmrg	    dy= xkbi->mouseKeysDY;
48605b261ecSmrg    }
48705b261ecSmrg    else {
48805b261ecSmrg	dx= xkbi->mouseKeysDX;
48905b261ecSmrg	dy= xkbi->mouseKeysDY;
49005b261ecSmrg    }
4916747b715Smrg    XkbFakePointerMotion(xkbi->device, xkbi->mouseKeysFlags,dx,dy);
49205b261ecSmrg    return xkbi->desc->ctrls->mk_interval;
49305b261ecSmrg}
49405b261ecSmrg
49505b261ecSmrgstatic int
49605b261ecSmrg_XkbFilterPointerMove(	XkbSrvInfoPtr	xkbi,
49705b261ecSmrg			XkbFilterPtr	filter,
49805b261ecSmrg			unsigned	keycode,
49905b261ecSmrg			XkbAction *	pAction)
50005b261ecSmrg{
50105b261ecSmrgint	x,y;
50205b261ecSmrgBool	accel;
50305b261ecSmrg
50405b261ecSmrg    if (filter->keycode==0) {		/* initial press */
50505b261ecSmrg	filter->keycode = keycode;
50605b261ecSmrg	filter->active = 1;
50705b261ecSmrg	filter->filterOthers = 0;
50805b261ecSmrg	filter->priv=0;
50905b261ecSmrg	filter->filter = _XkbFilterPointerMove;
51005b261ecSmrg	filter->upAction= *pAction;
51105b261ecSmrg	xkbi->mouseKeysCounter= 0;
51205b261ecSmrg	xkbi->mouseKey= keycode;
51305b261ecSmrg	accel= ((pAction->ptr.flags&XkbSA_NoAcceleration)==0);
51405b261ecSmrg	x= XkbPtrActionX(&pAction->ptr);
51505b261ecSmrg	y= XkbPtrActionY(&pAction->ptr);
5166747b715Smrg	XkbFakePointerMotion(xkbi->device, pAction->ptr.flags,x,y);
51705b261ecSmrg	AccessXCancelRepeatKey(xkbi,keycode);
51805b261ecSmrg	xkbi->mouseKeysAccel= accel&&
51905b261ecSmrg		(xkbi->desc->ctrls->enabled_ctrls&XkbMouseKeysAccelMask);
52005b261ecSmrg	xkbi->mouseKeysFlags= pAction->ptr.flags;
52105b261ecSmrg	xkbi->mouseKeysDX= XkbPtrActionX(&pAction->ptr);
52205b261ecSmrg	xkbi->mouseKeysDY= XkbPtrActionY(&pAction->ptr);
52305b261ecSmrg	xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0,
52405b261ecSmrg				xkbi->desc->ctrls->mk_delay,
52505b261ecSmrg				_XkbPtrAccelExpire,(pointer)xkbi);
52605b261ecSmrg    }
52705b261ecSmrg    else if (filter->keycode==keycode) {
52805b261ecSmrg	filter->active = 0;
52905b261ecSmrg	if (xkbi->mouseKey==keycode) {
53005b261ecSmrg	    xkbi->mouseKey= 0;
53105b261ecSmrg	    xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0, 0,
53205b261ecSmrg							NULL, NULL);
53305b261ecSmrg	}
53405b261ecSmrg    }
53505b261ecSmrg    return 0;
53605b261ecSmrg}
53705b261ecSmrg
53805b261ecSmrgstatic int
53905b261ecSmrg_XkbFilterPointerBtn(	XkbSrvInfoPtr	xkbi,
54005b261ecSmrg			XkbFilterPtr	filter,
54105b261ecSmrg			unsigned	keycode,
54205b261ecSmrg			XkbAction *	pAction)
54305b261ecSmrg{
54405b261ecSmrg    if (filter->keycode==0) {		/* initial press */
54505b261ecSmrg	int	button= pAction->btn.button;
54605b261ecSmrg
54705b261ecSmrg	if (button==XkbSA_UseDfltButton)
54805b261ecSmrg	    button = xkbi->desc->ctrls->mk_dflt_btn;
54905b261ecSmrg
55005b261ecSmrg	filter->keycode = keycode;
55105b261ecSmrg	filter->active = 1;
55205b261ecSmrg	filter->filterOthers = 0;
55305b261ecSmrg	filter->priv=0;
55405b261ecSmrg	filter->filter = _XkbFilterPointerBtn;
55505b261ecSmrg	filter->upAction= *pAction;
55605b261ecSmrg	filter->upAction.btn.button= button;
55705b261ecSmrg	switch (pAction->type) {
55805b261ecSmrg	    case XkbSA_LockPtrBtn:
55905b261ecSmrg		if (((xkbi->lockedPtrButtons&(1<<button))==0)&&
56005b261ecSmrg			((pAction->btn.flags&XkbSA_LockNoLock)==0)) {
56105b261ecSmrg		    xkbi->lockedPtrButtons|= (1<<button);
56205b261ecSmrg		    AccessXCancelRepeatKey(xkbi,keycode);
5636747b715Smrg		    XkbFakeDeviceButton(xkbi->device, 1, button);
56405b261ecSmrg		    filter->upAction.type= XkbSA_NoAction;
56505b261ecSmrg		}
56605b261ecSmrg		break;
56705b261ecSmrg	    case XkbSA_PtrBtn:
56805b261ecSmrg		{
56905b261ecSmrg		    register int i,nClicks;
57005b261ecSmrg		    AccessXCancelRepeatKey(xkbi,keycode);
57105b261ecSmrg		    if (pAction->btn.count>0) {
57205b261ecSmrg			nClicks= pAction->btn.count;
57305b261ecSmrg			for (i=0;i<nClicks;i++) {
5746747b715Smrg			    XkbFakeDeviceButton(xkbi->device, 1, button);
5756747b715Smrg			    XkbFakeDeviceButton(xkbi->device, 0, button);
57605b261ecSmrg			}
57705b261ecSmrg			filter->upAction.type= XkbSA_NoAction;
57805b261ecSmrg		    }
5796747b715Smrg		    else XkbFakeDeviceButton(xkbi->device, 1, button);
58005b261ecSmrg		}
58105b261ecSmrg		break;
58205b261ecSmrg	    case XkbSA_SetPtrDflt:
58305b261ecSmrg		{
58405b261ecSmrg		    XkbControlsPtr	ctrls= xkbi->desc->ctrls;
58505b261ecSmrg		    XkbControlsRec	old;
58605b261ecSmrg		    xkbControlsNotify	cn;
58705b261ecSmrg
58805b261ecSmrg		    old= *ctrls;
58905b261ecSmrg		    AccessXCancelRepeatKey(xkbi,keycode);
59005b261ecSmrg		    switch (pAction->dflt.affect) {
59105b261ecSmrg			case XkbSA_AffectDfltBtn:
59205b261ecSmrg			    if (pAction->dflt.flags&XkbSA_DfltBtnAbsolute)
59305b261ecSmrg				ctrls->mk_dflt_btn=
59405b261ecSmrg					XkbSAPtrDfltValue(&pAction->dflt);
59505b261ecSmrg			    else {
59605b261ecSmrg				ctrls->mk_dflt_btn+=
59705b261ecSmrg					XkbSAPtrDfltValue(&pAction->dflt);
59805b261ecSmrg				if (ctrls->mk_dflt_btn>5)
59905b261ecSmrg				    ctrls->mk_dflt_btn= 5;
60005b261ecSmrg				else if (ctrls->mk_dflt_btn<1)
60105b261ecSmrg				    ctrls->mk_dflt_btn= 1;
60205b261ecSmrg			    }
60305b261ecSmrg			    break;
60405b261ecSmrg			default:
60505b261ecSmrg			    ErrorF(
60605b261ecSmrg		"Attempt to change unknown pointer default (%d) ignored\n",
60705b261ecSmrg							pAction->dflt.affect);
60805b261ecSmrg			    break;
60905b261ecSmrg		    }
61005b261ecSmrg		    if (XkbComputeControlsNotify(xkbi->device,
61105b261ecSmrg						&old,xkbi->desc->ctrls,
6126747b715Smrg						&cn,FALSE)) {
61305b261ecSmrg			cn.keycode = keycode;
61405b261ecSmrg                        /* XXX: what about DeviceKeyPress? */
61505b261ecSmrg			cn.eventType = KeyPress;
61605b261ecSmrg			cn.requestMajor = 0;
61705b261ecSmrg			cn.requestMinor = 0;
61805b261ecSmrg			XkbSendControlsNotify(xkbi->device,&cn);
61905b261ecSmrg		    }
62005b261ecSmrg		}
62105b261ecSmrg		break;
62205b261ecSmrg	}
62305b261ecSmrg    }
62405b261ecSmrg    else if (filter->keycode==keycode) {
62505b261ecSmrg	int	button= filter->upAction.btn.button;
62605b261ecSmrg
62705b261ecSmrg	switch (filter->upAction.type) {
62805b261ecSmrg	    case XkbSA_LockPtrBtn:
62905b261ecSmrg		if (((filter->upAction.btn.flags&XkbSA_LockNoUnlock)!=0)||
63005b261ecSmrg				((xkbi->lockedPtrButtons&(1<<button))==0)) {
63105b261ecSmrg		    break;
63205b261ecSmrg		}
63305b261ecSmrg		xkbi->lockedPtrButtons&= ~(1<<button);
6346747b715Smrg
6356747b715Smrg		if (IsMaster(xkbi->device))
6366747b715Smrg		{
6376747b715Smrg		    XkbMergeLockedPtrBtns(xkbi->device);
6386747b715Smrg                    /* One SD still has lock set, don't post event */
6396747b715Smrg		    if ((xkbi->lockedPtrButtons & (1 << button)) != 0)
6406747b715Smrg			break;
6416747b715Smrg		}
6426747b715Smrg
6436747b715Smrg		/* fallthrough */
64405b261ecSmrg	    case XkbSA_PtrBtn:
6456747b715Smrg		XkbFakeDeviceButton(xkbi->device, 0, button);
64605b261ecSmrg		break;
64705b261ecSmrg	}
64805b261ecSmrg	filter->active = 0;
64905b261ecSmrg    }
65005b261ecSmrg    return 0;
65105b261ecSmrg}
65205b261ecSmrg
65305b261ecSmrgstatic int
65405b261ecSmrg_XkbFilterControls(	XkbSrvInfoPtr	xkbi,
65505b261ecSmrg			XkbFilterPtr	filter,
65605b261ecSmrg			unsigned	keycode,
65705b261ecSmrg			XkbAction *	pAction)
65805b261ecSmrg{
65905b261ecSmrgXkbControlsRec		old;
66005b261ecSmrgXkbControlsPtr		ctrls;
66105b261ecSmrgDeviceIntPtr		kbd;
66205b261ecSmrgunsigned int		change;
66305b261ecSmrgXkbEventCauseRec	cause;
66405b261ecSmrg
66505b261ecSmrg    kbd= xkbi->device;
66605b261ecSmrg    ctrls= xkbi->desc->ctrls;
66705b261ecSmrg    old= *ctrls;
66805b261ecSmrg    if (filter->keycode==0) {		/* initial press */
66905b261ecSmrg	filter->keycode = keycode;
67005b261ecSmrg	filter->active = 1;
67105b261ecSmrg	filter->filterOthers = 0;
67205b261ecSmrg	change= XkbActionCtrls(&pAction->ctrls);
67305b261ecSmrg	filter->priv = change;
67405b261ecSmrg	filter->filter = _XkbFilterControls;
67505b261ecSmrg	filter->upAction = *pAction;
67605b261ecSmrg
67705b261ecSmrg	if (pAction->type==XkbSA_LockControls) {
67805b261ecSmrg	    filter->priv= (ctrls->enabled_ctrls&change);
67905b261ecSmrg	    change&= ~ctrls->enabled_ctrls;
68005b261ecSmrg	}
68105b261ecSmrg
68205b261ecSmrg	if (change) {
68305b261ecSmrg	    xkbControlsNotify	cn;
68405b261ecSmrg	    XkbSrvLedInfoPtr	sli;
68505b261ecSmrg
68605b261ecSmrg	    ctrls->enabled_ctrls|= change;
6876747b715Smrg	    if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,FALSE)) {
68805b261ecSmrg		cn.keycode = keycode;
68905b261ecSmrg                /* XXX: what about DeviceKeyPress? */
69005b261ecSmrg		cn.eventType = KeyPress;
69105b261ecSmrg		cn.requestMajor = 0;
69205b261ecSmrg		cn.requestMinor = 0;
69305b261ecSmrg		XkbSendControlsNotify(kbd,&cn);
69405b261ecSmrg	    }
69505b261ecSmrg
69605b261ecSmrg	    XkbSetCauseKey(&cause,keycode,KeyPress);
69705b261ecSmrg
69805b261ecSmrg	    /* If sticky keys were disabled, clear all locks and latches */
69905b261ecSmrg	    if ((old.enabled_ctrls&XkbStickyKeysMask)&&
70005b261ecSmrg		(!(ctrls->enabled_ctrls&XkbStickyKeysMask))) {
7016747b715Smrg		XkbClearAllLatchesAndLocks(kbd,xkbi,FALSE,&cause);
70205b261ecSmrg    	    }
70305b261ecSmrg	    sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
7046747b715Smrg	    XkbUpdateIndicators(kbd,sli->usesControls,TRUE,NULL,&cause);
70505b261ecSmrg	    if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask))
70605b261ecSmrg		XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_ON,change);
70705b261ecSmrg	}
70805b261ecSmrg    }
70905b261ecSmrg    else if (filter->keycode==keycode) {
71005b261ecSmrg	change= filter->priv;
71105b261ecSmrg	if (change) {
71205b261ecSmrg	    xkbControlsNotify 	cn;
71305b261ecSmrg	    XkbSrvLedInfoPtr	sli;
71405b261ecSmrg
71505b261ecSmrg	    ctrls->enabled_ctrls&= ~change;
7166747b715Smrg	    if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,FALSE)) {
71705b261ecSmrg		cn.keycode = keycode;
71805b261ecSmrg		cn.eventType = KeyRelease;
71905b261ecSmrg		cn.requestMajor = 0;
72005b261ecSmrg		cn.requestMinor = 0;
72105b261ecSmrg		XkbSendControlsNotify(kbd,&cn);
72205b261ecSmrg	    }
72305b261ecSmrg
72405b261ecSmrg	    XkbSetCauseKey(&cause,keycode,KeyRelease);
72505b261ecSmrg	    /* If sticky keys were disabled, clear all locks and latches */
72605b261ecSmrg	    if ((old.enabled_ctrls&XkbStickyKeysMask)&&
72705b261ecSmrg		(!(ctrls->enabled_ctrls&XkbStickyKeysMask))) {
7286747b715Smrg		XkbClearAllLatchesAndLocks(kbd,xkbi,FALSE,&cause);
72905b261ecSmrg    	    }
73005b261ecSmrg	    sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
7316747b715Smrg	    XkbUpdateIndicators(kbd,sli->usesControls,TRUE,NULL,&cause);
73205b261ecSmrg	    if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask))
73305b261ecSmrg		XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_OFF,change);
73405b261ecSmrg	}
73505b261ecSmrg	filter->keycode= 0;
73605b261ecSmrg	filter->active= 0;
73705b261ecSmrg    }
73805b261ecSmrg    return 1;
73905b261ecSmrg}
74005b261ecSmrg
74105b261ecSmrgstatic int
74205b261ecSmrg_XkbFilterActionMessage(XkbSrvInfoPtr	xkbi,
74305b261ecSmrg			XkbFilterPtr	filter,
74405b261ecSmrg			unsigned	keycode,
74505b261ecSmrg			XkbAction *	pAction)
74605b261ecSmrg{
74705b261ecSmrgXkbMessageAction *	pMsg;
74805b261ecSmrgDeviceIntPtr		kbd;
74905b261ecSmrg
75005b261ecSmrg    kbd= xkbi->device;
75105b261ecSmrg    if (filter->keycode==0) {		/* initial press */
75205b261ecSmrg	pMsg= &pAction->msg;
75305b261ecSmrg	if ((pMsg->flags&XkbSA_MessageOnRelease)||
75405b261ecSmrg	    ((pMsg->flags&XkbSA_MessageGenKeyEvent)==0)) {
75505b261ecSmrg	    filter->keycode = keycode;
75605b261ecSmrg	    filter->active = 1;
75705b261ecSmrg	    filter->filterOthers = 0;
75805b261ecSmrg	    filter->priv = 0;
75905b261ecSmrg	    filter->filter = _XkbFilterActionMessage;
76005b261ecSmrg	    filter->upAction = *pAction;
76105b261ecSmrg	}
76205b261ecSmrg	if (pMsg->flags&XkbSA_MessageOnPress)  {
76305b261ecSmrg	    xkbActionMessage	msg;
76405b261ecSmrg
76505b261ecSmrg	    msg.keycode= keycode;
76605b261ecSmrg	    msg.press= 1;
76705b261ecSmrg	    msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0);
76805b261ecSmrg	    memcpy((char *)msg.message,
76905b261ecSmrg				(char *)pMsg->message,XkbActionMessageLength);
77005b261ecSmrg	    XkbSendActionMessage(kbd,&msg);
77105b261ecSmrg	}
77205b261ecSmrg	return ((pAction->msg.flags&XkbSA_MessageGenKeyEvent)!=0);
77305b261ecSmrg    }
77405b261ecSmrg    else if (filter->keycode==keycode) {
77505b261ecSmrg	pMsg= &filter->upAction.msg;
77605b261ecSmrg	if (pMsg->flags&XkbSA_MessageOnRelease) {
77705b261ecSmrg	    xkbActionMessage	msg;
77805b261ecSmrg
77905b261ecSmrg	    msg.keycode= keycode;
78005b261ecSmrg	    msg.press= 0;
78105b261ecSmrg	    msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0);
78205b261ecSmrg	    memcpy((char *)msg.message,(char *)pMsg->message,
78305b261ecSmrg						XkbActionMessageLength);
78405b261ecSmrg	    XkbSendActionMessage(kbd,&msg);
78505b261ecSmrg	}
78605b261ecSmrg	filter->keycode= 0;
78705b261ecSmrg	filter->active= 0;
78805b261ecSmrg	return ((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0);
78905b261ecSmrg    }
79005b261ecSmrg    return 0;
79105b261ecSmrg}
79205b261ecSmrg
79305b261ecSmrgstatic int
79405b261ecSmrg_XkbFilterRedirectKey(	XkbSrvInfoPtr	xkbi,
79505b261ecSmrg			XkbFilterPtr	filter,
79605b261ecSmrg			unsigned	keycode,
79705b261ecSmrg			XkbAction *	pAction)
79805b261ecSmrg{
7996747b715SmrgDeviceEvent	ev;
80005b261ecSmrgint		x,y;
80105b261ecSmrgXkbStateRec	old;
8026747b715Smrgunsigned	mods,mask;
80305b261ecSmrgxkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device);
80405b261ecSmrgProcessInputProc backupproc;
80505b261ecSmrg
80605b261ecSmrg    /* never actually used uninitialised, but gcc isn't smart enough
80705b261ecSmrg     * to work that out. */
80805b261ecSmrg    memset(&old, 0, sizeof(old));
8096747b715Smrg    memset(&ev, 0, sizeof(ev));
81005b261ecSmrg
81105b261ecSmrg    if ((filter->keycode!=0)&&(filter->keycode!=keycode))
81205b261ecSmrg	return 1;
81305b261ecSmrg
8146747b715Smrg    GetSpritePosition(xkbi->device, &x,&y);
8156747b715Smrg    ev.header = ET_Internal;
8166747b715Smrg    ev.length = sizeof(DeviceEvent);
8176747b715Smrg    ev.time = GetTimeInMillis();
8186747b715Smrg    ev.root_x = x;
8196747b715Smrg    ev.root_y = y;
82005b261ecSmrg
82105b261ecSmrg    if (filter->keycode==0) {		/* initial press */
82205b261ecSmrg	if ((pAction->redirect.new_key<xkbi->desc->min_key_code)||
82305b261ecSmrg	    (pAction->redirect.new_key>xkbi->desc->max_key_code)) {
82405b261ecSmrg	    return 1;
82505b261ecSmrg	}
82605b261ecSmrg	filter->keycode = keycode;
82705b261ecSmrg	filter->active = 1;
82805b261ecSmrg	filter->filterOthers = 0;
82905b261ecSmrg	filter->priv = 0;
83005b261ecSmrg	filter->filter = _XkbFilterRedirectKey;
83105b261ecSmrg	filter->upAction = *pAction;
83205b261ecSmrg
8336747b715Smrg        ev.type = ET_KeyPress;
8346747b715Smrg        ev.detail.key = pAction->redirect.new_key;
83505b261ecSmrg
83605b261ecSmrg        mask= XkbSARedirectVModsMask(&pAction->redirect);
83705b261ecSmrg        mods= XkbSARedirectVMods(&pAction->redirect);
83805b261ecSmrg        if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask);
83905b261ecSmrg        if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods);
84005b261ecSmrg        mask|= pAction->redirect.mods_mask;
84105b261ecSmrg        mods|= pAction->redirect.mods;
84205b261ecSmrg
84305b261ecSmrg	if ( mask || mods ) {
84405b261ecSmrg	    old= xkbi->state;
84505b261ecSmrg	    xkbi->state.base_mods&= ~mask;
84605b261ecSmrg	    xkbi->state.base_mods|= (mods&mask);
84705b261ecSmrg	    xkbi->state.latched_mods&= ~mask;
84805b261ecSmrg	    xkbi->state.latched_mods|= (mods&mask);
84905b261ecSmrg	    xkbi->state.locked_mods&= ~mask;
85005b261ecSmrg	    xkbi->state.locked_mods|= (mods&mask);
85105b261ecSmrg	    XkbComputeDerivedState(xkbi);
85205b261ecSmrg	}
85305b261ecSmrg
85405b261ecSmrg	UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
8556747b715Smrg	xkbi->device->public.processInputProc((InternalEvent*)&ev, xkbi->device);
85605b261ecSmrg	COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
85705b261ecSmrg				     backupproc,xkbUnwrapProc);
85805b261ecSmrg
8596747b715Smrg	if ( mask || mods )
86005b261ecSmrg	    xkbi->state= old;
86105b261ecSmrg    }
86205b261ecSmrg    else if (filter->keycode==keycode) {
86305b261ecSmrg
8646747b715Smrg        ev.type = ET_KeyRelease;
8656747b715Smrg        ev.detail.key = filter->upAction.redirect.new_key;
86605b261ecSmrg
86705b261ecSmrg        mask= XkbSARedirectVModsMask(&filter->upAction.redirect);
86805b261ecSmrg        mods= XkbSARedirectVMods(&filter->upAction.redirect);
86905b261ecSmrg        if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask);
87005b261ecSmrg        if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods);
87105b261ecSmrg        mask|= filter->upAction.redirect.mods_mask;
87205b261ecSmrg        mods|= filter->upAction.redirect.mods;
87305b261ecSmrg
87405b261ecSmrg	if ( mask || mods ) {
87505b261ecSmrg	    old= xkbi->state;
87605b261ecSmrg	    xkbi->state.base_mods&= ~mask;
87705b261ecSmrg	    xkbi->state.base_mods|= (mods&mask);
87805b261ecSmrg	    xkbi->state.latched_mods&= ~mask;
87905b261ecSmrg	    xkbi->state.latched_mods|= (mods&mask);
88005b261ecSmrg	    xkbi->state.locked_mods&= ~mask;
88105b261ecSmrg	    xkbi->state.locked_mods|= (mods&mask);
88205b261ecSmrg	    XkbComputeDerivedState(xkbi);
88305b261ecSmrg	}
88405b261ecSmrg
88505b261ecSmrg	UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
8866747b715Smrg	xkbi->device->public.processInputProc((InternalEvent*)&ev, xkbi->device);
88705b261ecSmrg	COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
88805b261ecSmrg				     backupproc,xkbUnwrapProc);
88905b261ecSmrg
8906747b715Smrg	if ( mask || mods )
89105b261ecSmrg	    xkbi->state= old;
89205b261ecSmrg
89305b261ecSmrg	filter->keycode= 0;
89405b261ecSmrg	filter->active= 0;
89505b261ecSmrg    }
89605b261ecSmrg    return 0;
89705b261ecSmrg}
89805b261ecSmrg
89905b261ecSmrgstatic int
90005b261ecSmrg_XkbFilterSwitchScreen(	XkbSrvInfoPtr	xkbi,
90105b261ecSmrg			XkbFilterPtr	filter,
90205b261ecSmrg			unsigned	keycode,
90305b261ecSmrg			XkbAction *	pAction)
90405b261ecSmrg{
90505b261ecSmrg    DeviceIntPtr dev = xkbi->device;
90605b261ecSmrg    if (dev == inputInfo.keyboard)
90705b261ecSmrg        return 0;
90805b261ecSmrg
90905b261ecSmrg    if (filter->keycode==0) {		/* initial press */
91005b261ecSmrg	filter->keycode = keycode;
91105b261ecSmrg	filter->active = 1;
91205b261ecSmrg	filter->filterOthers = 0;
91305b261ecSmrg	filter->filter = _XkbFilterSwitchScreen;
91405b261ecSmrg	AccessXCancelRepeatKey(xkbi, keycode);
91505b261ecSmrg	XkbDDXSwitchScreen(dev,keycode,pAction);
91605b261ecSmrg        return 0;
91705b261ecSmrg    }
91805b261ecSmrg    else if (filter->keycode==keycode) {
91905b261ecSmrg	filter->active= 0;
92005b261ecSmrg        return 0;
92105b261ecSmrg    }
92205b261ecSmrg    return 1;
92305b261ecSmrg}
92405b261ecSmrg
92505b261ecSmrgstatic int
92605b261ecSmrg_XkbFilterXF86Private(	XkbSrvInfoPtr	xkbi,
92705b261ecSmrg			XkbFilterPtr	filter,
92805b261ecSmrg			unsigned	keycode,
92905b261ecSmrg			XkbAction *	pAction)
93005b261ecSmrg{
93105b261ecSmrg    DeviceIntPtr dev = xkbi->device;
93205b261ecSmrg    if (dev == inputInfo.keyboard)
93305b261ecSmrg        return 0;
93405b261ecSmrg
93505b261ecSmrg    if (filter->keycode==0) {		/* initial press */
93605b261ecSmrg	filter->keycode = keycode;
93705b261ecSmrg	filter->active = 1;
93805b261ecSmrg	filter->filterOthers = 0;
93905b261ecSmrg	filter->filter = _XkbFilterXF86Private;
94005b261ecSmrg	XkbDDXPrivate(dev,keycode,pAction);
94105b261ecSmrg        return 0;
94205b261ecSmrg    }
94305b261ecSmrg    else if (filter->keycode==keycode) {
94405b261ecSmrg	filter->active= 0;
94505b261ecSmrg        return 0;
94605b261ecSmrg    }
94705b261ecSmrg    return 1;
94805b261ecSmrg}
94905b261ecSmrg
95005b261ecSmrg
95105b261ecSmrgstatic int
95205b261ecSmrg_XkbFilterDeviceBtn(	XkbSrvInfoPtr	xkbi,
95305b261ecSmrg			XkbFilterPtr	filter,
95405b261ecSmrg			unsigned	keycode,
95505b261ecSmrg			XkbAction *	pAction)
95605b261ecSmrg{
95705b261ecSmrgDeviceIntPtr	dev;
95805b261ecSmrgint		button;
95905b261ecSmrg
9604642e01fSmrg    if (xkbi->device == inputInfo.keyboard)
96105b261ecSmrg        return 0;
96205b261ecSmrg
96305b261ecSmrg    if (filter->keycode==0) {		/* initial press */
9644642e01fSmrg	_XkbLookupButtonDevice(&dev, pAction->devbtn.device, serverClient,
9654642e01fSmrg			       DixUnknownAccess, &button);
9666747b715Smrg	if (!dev || !dev->public.on)
96705b261ecSmrg	    return 1;
96805b261ecSmrg
96905b261ecSmrg	button= pAction->devbtn.button;
97005b261ecSmrg	if ((button<1)||(button>dev->button->numButtons))
97105b261ecSmrg	    return 1;
97205b261ecSmrg
97305b261ecSmrg	filter->keycode = keycode;
97405b261ecSmrg	filter->active = 1;
97505b261ecSmrg	filter->filterOthers = 0;
97605b261ecSmrg	filter->priv=0;
97705b261ecSmrg	filter->filter = _XkbFilterDeviceBtn;
97805b261ecSmrg	filter->upAction= *pAction;
97905b261ecSmrg	switch (pAction->type) {
98005b261ecSmrg	    case XkbSA_LockDeviceBtn:
98105b261ecSmrg		if ((pAction->devbtn.flags&XkbSA_LockNoLock)||
9824642e01fSmrg		    BitIsOn(dev->button->down, button))
98305b261ecSmrg		    return 0;
9846747b715Smrg		XkbFakeDeviceButton(dev,TRUE,button);
98505b261ecSmrg		filter->upAction.type= XkbSA_NoAction;
98605b261ecSmrg		break;
98705b261ecSmrg	    case XkbSA_DeviceBtn:
98805b261ecSmrg		if (pAction->devbtn.count>0) {
98905b261ecSmrg		    int nClicks,i;
99005b261ecSmrg		    nClicks= pAction->btn.count;
99105b261ecSmrg		    for (i=0;i<nClicks;i++) {
9926747b715Smrg			XkbFakeDeviceButton(dev,TRUE,button);
9936747b715Smrg			XkbFakeDeviceButton(dev,FALSE,button);
99405b261ecSmrg		    }
99505b261ecSmrg		    filter->upAction.type= XkbSA_NoAction;
99605b261ecSmrg		}
9976747b715Smrg		else XkbFakeDeviceButton(dev,TRUE,button);
99805b261ecSmrg		break;
99905b261ecSmrg	}
100005b261ecSmrg    }
100105b261ecSmrg    else if (filter->keycode==keycode) {
100205b261ecSmrg	int	button;
100305b261ecSmrg
100405b261ecSmrg	filter->active= 0;
10054642e01fSmrg	_XkbLookupButtonDevice(&dev, filter->upAction.devbtn.device,
10064642e01fSmrg			       serverClient, DixUnknownAccess, &button);
10076747b715Smrg	if (!dev || !dev->public.on)
100805b261ecSmrg	    return 1;
100905b261ecSmrg
101005b261ecSmrg	button= filter->upAction.btn.button;
101105b261ecSmrg	switch (filter->upAction.type) {
101205b261ecSmrg	    case XkbSA_LockDeviceBtn:
101305b261ecSmrg		if ((filter->upAction.devbtn.flags&XkbSA_LockNoUnlock)||
10144642e01fSmrg		    !BitIsOn(dev->button->down, button))
101505b261ecSmrg		    return 0;
10166747b715Smrg		XkbFakeDeviceButton(dev,FALSE,button);
101705b261ecSmrg		break;
101805b261ecSmrg	    case XkbSA_DeviceBtn:
10196747b715Smrg		XkbFakeDeviceButton(dev,FALSE,button);
102005b261ecSmrg		break;
102105b261ecSmrg	}
102205b261ecSmrg	filter->active = 0;
102305b261ecSmrg    }
102405b261ecSmrg    return 0;
102505b261ecSmrg}
102605b261ecSmrg
102705b261ecSmrgstatic XkbFilterPtr
102805b261ecSmrg_XkbNextFreeFilter(
102905b261ecSmrg	XkbSrvInfoPtr xkbi
103005b261ecSmrg)
103105b261ecSmrg{
103205b261ecSmrgregister int	i;
103305b261ecSmrg
103405b261ecSmrg    if (xkbi->szFilters==0) {
103505b261ecSmrg	xkbi->szFilters = 4;
10366747b715Smrg	xkbi->filters = calloc(xkbi->szFilters, sizeof(XkbFilterRec));
103705b261ecSmrg	/* 6/21/93 (ef) -- XXX! deal with allocation failure */
103805b261ecSmrg    }
103905b261ecSmrg    for (i=0;i<xkbi->szFilters;i++) {
104005b261ecSmrg	if (!xkbi->filters[i].active) {
104105b261ecSmrg	    xkbi->filters[i].keycode = 0;
104205b261ecSmrg	    return &xkbi->filters[i];
104305b261ecSmrg	}
104405b261ecSmrg    }
104505b261ecSmrg    xkbi->szFilters*=2;
10466747b715Smrg    xkbi->filters= realloc(xkbi->filters,
10476747b715Smrg                            xkbi->szFilters * sizeof(XkbFilterRec));
104805b261ecSmrg    /* 6/21/93 (ef) -- XXX! deal with allocation failure */
10496747b715Smrg    memset(&xkbi->filters[xkbi->szFilters/2], 0,
105005b261ecSmrg            (xkbi->szFilters/2)*sizeof(XkbFilterRec));
105105b261ecSmrg    return &xkbi->filters[xkbi->szFilters/2];
105205b261ecSmrg}
105305b261ecSmrg
105405b261ecSmrgstatic int
105505b261ecSmrg_XkbApplyFilters(XkbSrvInfoPtr xkbi,unsigned kc,XkbAction *pAction)
105605b261ecSmrg{
105705b261ecSmrgregister int	i,send;
105805b261ecSmrg
105905b261ecSmrg    send= 1;
106005b261ecSmrg    for (i=0;i<xkbi->szFilters;i++) {
106105b261ecSmrg	if ((xkbi->filters[i].active)&&(xkbi->filters[i].filter))
106205b261ecSmrg	    send= ((*xkbi->filters[i].filter)(xkbi,&xkbi->filters[i],kc,pAction)
106305b261ecSmrg                    && send);
106405b261ecSmrg    }
106505b261ecSmrg    return send;
106605b261ecSmrg}
106705b261ecSmrg
106805b261ecSmrgvoid
10696747b715SmrgXkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent* event)
107005b261ecSmrg{
107105b261ecSmrgint		key,bit,i;
107205b261ecSmrgXkbSrvInfoPtr	xkbi;
107305b261ecSmrgKeyClassPtr	keyc;
107405b261ecSmrgint		changed,sendEvent;
107505b261ecSmrgBool		genStateNotify;
107605b261ecSmrgXkbAction	act;
107705b261ecSmrgXkbFilterPtr	filter;
107805b261ecSmrgBool		keyEvent;
107905b261ecSmrgBool		pressEvent;
108005b261ecSmrgProcessInputProc backupproc;
108105b261ecSmrg
108205b261ecSmrgxkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
108305b261ecSmrg
108405b261ecSmrg    keyc= kbd->key;
108505b261ecSmrg    xkbi= keyc->xkbInfo;
10866747b715Smrg    key= event->detail.key;
108705b261ecSmrg    /* The state may change, so if we're not in the middle of sending a state
108805b261ecSmrg     * notify, prepare for it */
108905b261ecSmrg    if ((xkbi->flags&_XkbStateNotifyInProgress)==0) {
10906747b715Smrg	xkbi->prev_state = xkbi->state;
109105b261ecSmrg	xkbi->flags|= _XkbStateNotifyInProgress;
10926747b715Smrg	genStateNotify= TRUE;
109305b261ecSmrg    }
10946747b715Smrg    else genStateNotify= FALSE;
109505b261ecSmrg
109605b261ecSmrg    xkbi->clearMods = xkbi->setMods = 0;
109705b261ecSmrg    xkbi->groupChange = 0;
109805b261ecSmrg
109905b261ecSmrg    sendEvent = 1;
11006747b715Smrg    keyEvent= ((event->type == ET_KeyPress) || (event->type == ET_KeyRelease));
11016747b715Smrg    pressEvent= ((event->type == ET_KeyPress)|| (event->type == ET_ButtonPress));
110205b261ecSmrg
110305b261ecSmrg    if (pressEvent) {
110405b261ecSmrg	if (keyEvent)
110505b261ecSmrg	    act = XkbGetKeyAction(xkbi,&xkbi->state,key);
110605b261ecSmrg	else {
110705b261ecSmrg	    act = XkbGetButtonAction(kbd,dev,key);
110805b261ecSmrg	    key|= BTN_ACT_FLAG;
110905b261ecSmrg	}
111005b261ecSmrg	sendEvent = _XkbApplyFilters(xkbi,key,&act);
111105b261ecSmrg	if (sendEvent) {
111205b261ecSmrg	    switch (act.type) {
111305b261ecSmrg		case XkbSA_SetMods:
111405b261ecSmrg		case XkbSA_SetGroup:
111505b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
111605b261ecSmrg		    sendEvent = _XkbFilterSetState(xkbi,filter,key,&act);
111705b261ecSmrg		    break;
111805b261ecSmrg		case XkbSA_LatchMods:
111905b261ecSmrg		case XkbSA_LatchGroup:
112005b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
112105b261ecSmrg		    sendEvent=_XkbFilterLatchState(xkbi,filter,key,&act);
112205b261ecSmrg		    break;
112305b261ecSmrg		case XkbSA_LockMods:
112405b261ecSmrg		case XkbSA_LockGroup:
112505b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
112605b261ecSmrg		    sendEvent=_XkbFilterLockState(xkbi,filter,key,&act);
112705b261ecSmrg		    break;
112805b261ecSmrg		case XkbSA_ISOLock:
112905b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
113005b261ecSmrg		    sendEvent=_XkbFilterISOLock(xkbi,filter,key,&act);
113105b261ecSmrg		    break;
113205b261ecSmrg		case XkbSA_MovePtr:
113305b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
113405b261ecSmrg		    sendEvent= _XkbFilterPointerMove(xkbi,filter,key,&act);
113505b261ecSmrg		    break;
113605b261ecSmrg		case XkbSA_PtrBtn:
113705b261ecSmrg		case XkbSA_LockPtrBtn:
113805b261ecSmrg		case XkbSA_SetPtrDflt:
113905b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
114005b261ecSmrg		    sendEvent= _XkbFilterPointerBtn(xkbi,filter,key,&act);
114105b261ecSmrg		    break;
114205b261ecSmrg		case XkbSA_Terminate:
114305b261ecSmrg		    sendEvent= XkbDDXTerminateServer(dev,key,&act);
114405b261ecSmrg		    break;
114505b261ecSmrg		case XkbSA_SwitchScreen:
114605b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
114705b261ecSmrg		    sendEvent=_XkbFilterSwitchScreen(xkbi,filter,key,&act);
114805b261ecSmrg		    break;
114905b261ecSmrg		case XkbSA_SetControls:
115005b261ecSmrg		case XkbSA_LockControls:
115105b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
115205b261ecSmrg		    sendEvent=_XkbFilterControls(xkbi,filter,key,&act);
115305b261ecSmrg		    break;
115405b261ecSmrg		case XkbSA_ActionMessage:
115505b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
115605b261ecSmrg		    sendEvent=_XkbFilterActionMessage(xkbi,filter,key,&act);
115705b261ecSmrg		    break;
115805b261ecSmrg		case XkbSA_RedirectKey:
115905b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
116005b261ecSmrg		    sendEvent= _XkbFilterRedirectKey(xkbi,filter,key,&act);
116105b261ecSmrg		    break;
116205b261ecSmrg		case XkbSA_DeviceBtn:
116305b261ecSmrg		case XkbSA_LockDeviceBtn:
116405b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
116505b261ecSmrg		    sendEvent= _XkbFilterDeviceBtn(xkbi,filter,key,&act);
116605b261ecSmrg		    break;
116705b261ecSmrg		case XkbSA_XFree86Private:
116805b261ecSmrg		    filter = _XkbNextFreeFilter(xkbi);
116905b261ecSmrg		    sendEvent= _XkbFilterXF86Private(xkbi,filter,key,&act);
117005b261ecSmrg		    break;
117105b261ecSmrg	    }
117205b261ecSmrg	}
117305b261ecSmrg    }
117405b261ecSmrg    else {
117505b261ecSmrg	if (!keyEvent)
117605b261ecSmrg	    key|= BTN_ACT_FLAG;
117705b261ecSmrg	sendEvent = _XkbApplyFilters(xkbi,key,NULL);
117805b261ecSmrg    }
117905b261ecSmrg
118005b261ecSmrg    if (xkbi->groupChange!=0)
118105b261ecSmrg	xkbi->state.base_group+= xkbi->groupChange;
118205b261ecSmrg    if (xkbi->setMods) {
118305b261ecSmrg	for (i=0,bit=1; xkbi->setMods; i++,bit<<=1 ) {
118405b261ecSmrg	    if (xkbi->setMods&bit) {
118505b261ecSmrg		keyc->modifierKeyCount[i]++;
118605b261ecSmrg		xkbi->state.base_mods|= bit;
118705b261ecSmrg		xkbi->setMods&= ~bit;
118805b261ecSmrg	    }
118905b261ecSmrg	}
119005b261ecSmrg    }
119105b261ecSmrg    if (xkbi->clearMods) {
119205b261ecSmrg	for (i=0,bit=1; xkbi->clearMods; i++,bit<<=1 ) {
119305b261ecSmrg	    if (xkbi->clearMods&bit) {
119405b261ecSmrg		keyc->modifierKeyCount[i]--;
119505b261ecSmrg		if (keyc->modifierKeyCount[i]<=0) {
119605b261ecSmrg		    xkbi->state.base_mods&= ~bit;
119705b261ecSmrg		    keyc->modifierKeyCount[i] = 0;
119805b261ecSmrg		}
119905b261ecSmrg		xkbi->clearMods&= ~bit;
120005b261ecSmrg	    }
120105b261ecSmrg	}
120205b261ecSmrg    }
120305b261ecSmrg
120405b261ecSmrg    if (sendEvent) {
12054642e01fSmrg        DeviceIntPtr tmpdev;
12066747b715Smrg	if (keyEvent)
12074642e01fSmrg            tmpdev = dev;
12086747b715Smrg        else
12094642e01fSmrg            tmpdev = GetPairedDevice(dev);
121005b261ecSmrg
12114642e01fSmrg        UNWRAP_PROCESS_INPUT_PROC(tmpdev,xkbPrivPtr, backupproc);
12126747b715Smrg        dev->public.processInputProc((InternalEvent*)event, tmpdev);
12134642e01fSmrg        COND_WRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr,
121405b261ecSmrg                                     backupproc,xkbUnwrapProc);
121505b261ecSmrg    }
121605b261ecSmrg    else if (keyEvent) {
12176747b715Smrg	FixKeyState(event, dev);
121805b261ecSmrg    }
121905b261ecSmrg
122005b261ecSmrg    XkbComputeDerivedState(xkbi);
12216747b715Smrg    changed = XkbStateChangedFlags(&xkbi->prev_state,&xkbi->state);
122205b261ecSmrg    if (genStateNotify) {
122305b261ecSmrg	if (changed) {
122405b261ecSmrg	    xkbStateNotify	sn;
122505b261ecSmrg	    sn.keycode= key;
12266747b715Smrg	    sn.eventType= event->type;
122705b261ecSmrg	    sn.requestMajor = sn.requestMinor = 0;
122805b261ecSmrg	    sn.changed= changed;
122905b261ecSmrg	    XkbSendStateNotify(dev,&sn);
123005b261ecSmrg	}
123105b261ecSmrg	xkbi->flags&= ~_XkbStateNotifyInProgress;
123205b261ecSmrg    }
12336747b715Smrg    changed= XkbIndicatorsToUpdate(dev,changed,FALSE);
123405b261ecSmrg    if (changed) {
123505b261ecSmrg	XkbEventCauseRec	cause;
12366747b715Smrg	XkbSetCauseKey(&cause, key, event->type);
12376747b715Smrg	XkbUpdateIndicators(dev,changed,FALSE,NULL,&cause);
123805b261ecSmrg    }
123905b261ecSmrg    return;
124005b261ecSmrg}
124105b261ecSmrg
124205b261ecSmrgint
124305b261ecSmrgXkbLatchModifiers(DeviceIntPtr pXDev,CARD8 mask,CARD8 latches)
124405b261ecSmrg{
124505b261ecSmrgXkbSrvInfoPtr	xkbi;
124605b261ecSmrgXkbFilterPtr	filter;
124705b261ecSmrgXkbAction	act;
124805b261ecSmrgunsigned	clear;
124905b261ecSmrg
125005b261ecSmrg    if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) {
125105b261ecSmrg	xkbi = pXDev->key->xkbInfo;
125205b261ecSmrg	clear= (mask&(~latches));
125305b261ecSmrg	xkbi->state.latched_mods&= ~clear;
125405b261ecSmrg	/* Clear any pending latch to locks.
125505b261ecSmrg	 */
125605b261ecSmrg	act.type = XkbSA_NoAction;
125705b261ecSmrg	_XkbApplyFilters(xkbi,SYNTHETIC_KEYCODE,&act);
125805b261ecSmrg	act.type = XkbSA_LatchMods;
125905b261ecSmrg	act.mods.flags = 0;
126005b261ecSmrg	act.mods.mask  = mask&latches;
126105b261ecSmrg	filter = _XkbNextFreeFilter(xkbi);
126205b261ecSmrg	_XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act);
126305b261ecSmrg	_XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL);
126405b261ecSmrg	return Success;
126505b261ecSmrg    }
126605b261ecSmrg    return BadValue;
126705b261ecSmrg}
126805b261ecSmrg
126905b261ecSmrgint
127005b261ecSmrgXkbLatchGroup(DeviceIntPtr pXDev,int group)
127105b261ecSmrg{
127205b261ecSmrgXkbSrvInfoPtr	xkbi;
127305b261ecSmrgXkbFilterPtr	filter;
127405b261ecSmrgXkbAction	act;
127505b261ecSmrg
127605b261ecSmrg    if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) {
127705b261ecSmrg	xkbi = pXDev->key->xkbInfo;
127805b261ecSmrg	act.type = XkbSA_LatchGroup;
127905b261ecSmrg	act.group.flags = 0;
128005b261ecSmrg	XkbSASetGroup(&act.group,group);
128105b261ecSmrg	filter = _XkbNextFreeFilter(xkbi);
128205b261ecSmrg	_XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act);
128305b261ecSmrg	_XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL);
128405b261ecSmrg	return Success;
128505b261ecSmrg    }
128605b261ecSmrg    return BadValue;
128705b261ecSmrg}
128805b261ecSmrg
128905b261ecSmrg/***====================================================================***/
129005b261ecSmrg
129105b261ecSmrgvoid
129205b261ecSmrgXkbClearAllLatchesAndLocks(	DeviceIntPtr		dev,
129305b261ecSmrg				XkbSrvInfoPtr		xkbi,
129405b261ecSmrg				Bool			genEv,
129505b261ecSmrg				XkbEventCausePtr	cause)
129605b261ecSmrg{
129705b261ecSmrgXkbStateRec	os;
129805b261ecSmrgxkbStateNotify	sn;
129905b261ecSmrg
130005b261ecSmrg    sn.changed= 0;
130105b261ecSmrg    os= xkbi->state;
130205b261ecSmrg    if (os.latched_mods) { /* clear all latches */
130305b261ecSmrg	XkbLatchModifiers(dev,~0,0);
130405b261ecSmrg	sn.changed|= XkbModifierLatchMask;
130505b261ecSmrg    }
130605b261ecSmrg    if (os.latched_group) {
130705b261ecSmrg	XkbLatchGroup(dev,0);
130805b261ecSmrg	sn.changed|= XkbGroupLatchMask;
130905b261ecSmrg    }
131005b261ecSmrg    if (os.locked_mods) {
131105b261ecSmrg	xkbi->state.locked_mods= 0;
131205b261ecSmrg	sn.changed|= XkbModifierLockMask;
131305b261ecSmrg    }
131405b261ecSmrg    if (os.locked_group) {
131505b261ecSmrg	xkbi->state.locked_group= 0;
131605b261ecSmrg	sn.changed|= XkbGroupLockMask;
131705b261ecSmrg    }
131805b261ecSmrg    if ( genEv && sn.changed) {
131905b261ecSmrg	CARD32 	changed;
132005b261ecSmrg
132105b261ecSmrg	XkbComputeDerivedState(xkbi);
132205b261ecSmrg	sn.keycode= 		cause->kc;
132305b261ecSmrg	sn.eventType=		cause->event;
132405b261ecSmrg	sn.requestMajor= 	cause->mjr;
132505b261ecSmrg	sn.requestMinor= 	cause->mnr;
132605b261ecSmrg	sn.changed= XkbStateChangedFlags(&os,&xkbi->state);
132705b261ecSmrg	XkbSendStateNotify(dev,&sn);
13286747b715Smrg	changed= XkbIndicatorsToUpdate(dev,sn.changed,FALSE);
132905b261ecSmrg	if (changed) {
13306747b715Smrg	    XkbUpdateIndicators(dev,changed,TRUE,NULL,cause);
133105b261ecSmrg	}
133205b261ecSmrg    }
133305b261ecSmrg    return;
133405b261ecSmrg}
133505b261ecSmrg
13366747b715Smrg/*
13376747b715Smrg * The event is injected into the event processing, not the EQ. Thus,
13386747b715Smrg * ensure that we restore the master after the event sequence to the
13396747b715Smrg * original set of classes. Otherwise, the master remains on the XTEST
13406747b715Smrg * classes and drops events that don't fit into the XTEST layout (e.g.
13416747b715Smrg * events with more than 2 valuators).
13426747b715Smrg *
13436747b715Smrg * FIXME: EQ injection in the processing stage is not designed for, so this
13446747b715Smrg * is a rather awkward hack. The event list returned by GetPointerEvents()
13456747b715Smrg * and friends is always prefixed with a DCE if the last _posted_ device was
13466747b715Smrg * different. For normal events, this sequence then resets the master during
13476747b715Smrg * the processing stage. Since we inject the PointerKey events in the
13486747b715Smrg * processing stage though, we need to manually reset to restore the
13496747b715Smrg * previous order, because the events already in the EQ must be sent for the
13506747b715Smrg * right device.
13516747b715Smrg * So we post-fix the event list we get from GPE with a DCE back to the
13526747b715Smrg * previous slave device.
13536747b715Smrg *
13546747b715Smrg * First one on drinking island wins!
13556747b715Smrg */
13566747b715Smrgstatic void
13576747b715SmrgInjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags, int num_valuators, int *valuators)
13586747b715Smrg{
13596747b715Smrg    ScreenPtr           pScreen;
13606747b715Smrg    EventListPtr        events;
13616747b715Smrg    int                 nevents, i;
13626747b715Smrg    DeviceIntPtr        ptr, mpointer, lastSlave = NULL;
13636747b715Smrg    Bool                saveWait;
13646747b715Smrg
13656747b715Smrg    if (IsMaster(dev)) {
13666747b715Smrg        mpointer = GetMaster(dev, MASTER_POINTER);
13676747b715Smrg        lastSlave = mpointer->u.lastSlave;
13686747b715Smrg        ptr = GetXTestDevice(mpointer);
13696747b715Smrg    } else if (!dev->u.master)
13706747b715Smrg        ptr = dev;
13716747b715Smrg    else
13726747b715Smrg        return;
13736747b715Smrg
13746747b715Smrg
13756747b715Smrg    events = InitEventList(GetMaximumEventsNum() + 1);
13766747b715Smrg    OsBlockSignals();
13776747b715Smrg    pScreen = miPointerGetScreen(ptr);
13786747b715Smrg    saveWait = miPointerSetWaitForUpdate(pScreen, FALSE);
13796747b715Smrg    nevents = GetPointerEvents(events, ptr, type, button, flags, 0,
13806747b715Smrg                               num_valuators, valuators);
13816747b715Smrg    if (IsMaster(dev) && (lastSlave && lastSlave != ptr))
13826747b715Smrg        UpdateFromMaster(&events[nevents], lastSlave, DEVCHANGE_POINTER_EVENT, &nevents);
13836747b715Smrg    miPointerSetWaitForUpdate(pScreen, saveWait);
13846747b715Smrg    OsReleaseSignals();
13856747b715Smrg
13866747b715Smrg    for (i = 0; i < nevents; i++)
13876747b715Smrg        mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL);
13886747b715Smrg
13896747b715Smrg    FreeEventList(events, GetMaximumEventsNum());
13906747b715Smrg
13916747b715Smrg}
13926747b715Smrg
13936747b715Smrgstatic void
13946747b715SmrgXkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y)
13956747b715Smrg{
13966747b715Smrg    int                 gpe_flags = 0;
13976747b715Smrg
13986747b715Smrg    /* ignore attached SDs */
13996747b715Smrg    if (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) != NULL)
14006747b715Smrg        return;
14016747b715Smrg
14026747b715Smrg    if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY)
14036747b715Smrg        gpe_flags = POINTER_ABSOLUTE;
14046747b715Smrg    else
14056747b715Smrg        gpe_flags = POINTER_RELATIVE;
14066747b715Smrg
14076747b715Smrg    InjectPointerKeyEvents(dev, MotionNotify, 0, gpe_flags, 2, (int[]){x, y});
14086747b715Smrg}
14096747b715Smrg
14106747b715Smrgvoid
14116747b715SmrgXkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
14126747b715Smrg{
14136747b715Smrg    DeviceIntPtr        ptr;
14146747b715Smrg    int                 down;
14156747b715Smrg
14166747b715Smrg    /* If dev is a slave device, and the SD is attached, do nothing. If we'd
14176747b715Smrg     * post through the attached master pointer we'd get duplicate events.
14186747b715Smrg     *
14196747b715Smrg     * if dev is a master keyboard, post through the XTEST device
14206747b715Smrg     *
14216747b715Smrg     * if dev is a floating slave, post through the device itself.
14226747b715Smrg     */
14236747b715Smrg
14246747b715Smrg    if (IsMaster(dev)) {
14256747b715Smrg        DeviceIntPtr mpointer = GetMaster(dev, MASTER_POINTER);
14266747b715Smrg        ptr = GetXTestDevice(mpointer);
14276747b715Smrg    } else if (!dev->u.master)
14286747b715Smrg        ptr = dev;
14296747b715Smrg    else
14306747b715Smrg        return;
14316747b715Smrg
14326747b715Smrg    down = button_is_down(ptr, button, BUTTON_PROCESSED);
14336747b715Smrg    if (press == down)
14346747b715Smrg        return;
14356747b715Smrg
14366747b715Smrg    InjectPointerKeyEvents(dev, press ? ButtonPress : ButtonRelease,
14376747b715Smrg                           button, 0, 0, NULL);
14386747b715Smrg}
1439