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