aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/xkb/xkbActions.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/xkb/xkbActions.c')
-rw-r--r--xorg-server/xkb/xkbActions.c2638
1 files changed, 1319 insertions, 1319 deletions
diff --git a/xorg-server/xkb/xkbActions.c b/xorg-server/xkb/xkbActions.c
index b0ab427b6..49c1de21b 100644
--- a/xorg-server/xkb/xkbActions.c
+++ b/xorg-server/xkb/xkbActions.c
@@ -1,1319 +1,1319 @@
-/************************************************************
-Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
-
-Permission to use, copy, modify, and distribute this
-software and its documentation for any purpose and without
-fee is hereby granted, provided that the above copyright
-notice appear in all copies and that both that copyright
-notice and this permission notice appear in supporting
-documentation, and that the name of Silicon Graphics not be
-used in advertising or publicity pertaining to distribution
-of the software without specific prior written permission.
-Silicon Graphics makes no representation about the suitability
-of this software for any purpose. It is provided "as is"
-without any express or implied warranty.
-
-SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
-GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
-DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
-THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-********************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stdio.h>
-#include <math.h>
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <X11/keysym.h>
-#include "misc.h"
-#include "inputstr.h"
-#include "exevents.h"
-#include "eventstr.h"
-#include <xkbsrv.h>
-#include "xkb.h"
-#include <ctype.h>
-#define EXTENSION_EVENT_BASE 64
-
-static int xkbDevicePrivateKeyIndex;
-DevPrivateKey xkbDevicePrivateKey = &xkbDevicePrivateKeyIndex;
-
-void
-xkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc,
- pointer data)
-{
- xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device);
- ProcessInputProc backupproc;
- if(xkbPrivPtr->unwrapProc)
- xkbPrivPtr->unwrapProc = NULL;
-
- UNWRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr, backupproc);
- proc(device,data);
- COND_WRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr,
- backupproc,xkbUnwrapProc);
-}
-
-
-void
-XkbSetExtension(DeviceIntPtr device, ProcessInputProc proc)
-{
- xkbDeviceInfoPtr xkbPrivPtr;
-
- xkbPrivPtr = (xkbDeviceInfoPtr) xcalloc(1, sizeof(xkbDeviceInfoRec));
- if (!xkbPrivPtr)
- return;
- xkbPrivPtr->unwrapProc = NULL;
-
- dixSetPrivate(&device->devPrivates, xkbDevicePrivateKey, xkbPrivPtr);
- WRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, proc, xkbUnwrapProc);
-}
-
-/***====================================================================***/
-
-static XkbAction
-_FixUpAction(XkbDescPtr xkb,XkbAction *act)
-{
-static XkbAction fake;
-
- if (XkbIsPtrAction(act)&&(!(xkb->ctrls->enabled_ctrls&XkbMouseKeysMask))) {
- fake.type = XkbSA_NoAction;
- return fake;
- }
- if (xkb->ctrls->enabled_ctrls&XkbStickyKeysMask) {
- if (act->any.type==XkbSA_SetMods) {
- fake.mods.type = XkbSA_LatchMods;
- fake.mods.mask = act->mods.mask;
- if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask))
- fake.mods.flags= XkbSA_ClearLocks|XkbSA_LatchToLock;
- else fake.mods.flags= XkbSA_ClearLocks;
- return fake;
- }
- if (act->any.type==XkbSA_SetGroup) {
- fake.group.type = XkbSA_LatchGroup;
- if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask))
- fake.group.flags= XkbSA_ClearLocks|XkbSA_LatchToLock;
- else fake.group.flags= XkbSA_ClearLocks;
- XkbSASetGroup(&fake.group,XkbSAGroup(&act->group));
- return fake;
- }
- }
- return *act;
-}
-
-static XkbAction
-XkbGetKeyAction(XkbSrvInfoPtr xkbi,XkbStatePtr xkbState,CARD8 key)
-{
-int effectiveGroup;
-int col;
-XkbDescPtr xkb;
-XkbKeyTypePtr type;
-XkbAction * pActs;
-static XkbAction fake;
-
- xkb= xkbi->desc;
- if (!XkbKeyHasActions(xkb,key) || !XkbKeycodeInRange(xkb,key)) {
- fake.type = XkbSA_NoAction;
- return fake;
- }
- pActs= XkbKeyActionsPtr(xkb,key);
- col= 0;
-
- effectiveGroup = XkbGetEffectiveGroup(xkbi, xkbState, key);
- if (effectiveGroup != XkbGroup1Index)
- col += (effectiveGroup * XkbKeyGroupsWidth(xkb, key));
-
- type= XkbKeyKeyType(xkb,key,effectiveGroup);
- if (type->map!=NULL) {
- register unsigned i,mods;
- register XkbKTMapEntryPtr entry;
- mods= xkbState->mods&type->mods.mask;
- for (entry= type->map,i=0;i<type->map_count;i++,entry++) {
- if ((entry->active)&&(entry->mods.mask==mods)) {
- col+= entry->level;
- break;
- }
- }
- }
- if (pActs[col].any.type==XkbSA_NoAction)
- return pActs[col];
- fake= _FixUpAction(xkb,&pActs[col]);
- return fake;
-}
-
-static XkbAction
-XkbGetButtonAction(DeviceIntPtr kbd,DeviceIntPtr dev,int button)
-{
-XkbAction fake;
- if ((dev->button)&&(dev->button->xkb_acts)) {
- if (dev->button->xkb_acts[button-1].any.type!=XkbSA_NoAction) {
- fake= _FixUpAction(kbd->key->xkbInfo->desc,
- &dev->button->xkb_acts[button-1]);
- return fake;
- }
- }
- fake.any.type= XkbSA_NoAction;
- return fake;
-}
-
-/***====================================================================***/
-
-#define SYNTHETIC_KEYCODE 1
-#define BTN_ACT_FLAG 0x100
-
-static int
-_XkbFilterSetState( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction *pAction)
-{
- if (filter->keycode==0) { /* initial press */
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = ((pAction->mods.mask&XkbSA_ClearLocks)!=0);
- filter->priv = 0;
- filter->filter = _XkbFilterSetState;
- if (pAction->type==XkbSA_SetMods) {
- filter->upAction = *pAction;
- xkbi->setMods= pAction->mods.mask;
- }
- else {
- xkbi->groupChange = XkbSAGroup(&pAction->group);
- if (pAction->group.flags&XkbSA_GroupAbsolute)
- xkbi->groupChange-= xkbi->state.base_group;
- filter->upAction= *pAction;
- XkbSASetGroup(&filter->upAction.group,xkbi->groupChange);
- }
- }
- else if (filter->keycode==keycode) {
- if (filter->upAction.type==XkbSA_SetMods) {
- xkbi->clearMods = filter->upAction.mods.mask;
- if (filter->upAction.mods.flags&XkbSA_ClearLocks) {
- xkbi->state.locked_mods&= ~filter->upAction.mods.mask;
- }
- }
- else {
- if (filter->upAction.group.flags&XkbSA_ClearLocks) {
- xkbi->state.locked_group = 0;
- }
- xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
- }
- filter->active = 0;
- }
- else {
- filter->upAction.mods.flags&= ~XkbSA_ClearLocks;
- filter->filterOthers = 0;
- }
- return 1;
-}
-
-#define LATCH_KEY_DOWN 1
-#define LATCH_PENDING 2
-#define NO_LATCH 3
-
-static int
-_XkbFilterLatchState( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
-
- if (filter->keycode==0) { /* initial press */
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 1;
- filter->priv = LATCH_KEY_DOWN;
- filter->filter = _XkbFilterLatchState;
- if (pAction->type==XkbSA_LatchMods) {
- filter->upAction = *pAction;
- xkbi->setMods = pAction->mods.mask;
- }
- else {
- xkbi->groupChange = XkbSAGroup(&pAction->group);
- if (pAction->group.flags&XkbSA_GroupAbsolute)
- xkbi->groupChange-= xkbi->state.base_group;
- filter->upAction= *pAction;
- XkbSASetGroup(&filter->upAction.group,xkbi->groupChange);
- }
- }
- else if ( pAction && (filter->priv==LATCH_PENDING) ) {
- if (((1<<pAction->type)&XkbSA_BreakLatch)!=0) {
- filter->active = 0;
- if (filter->upAction.type==XkbSA_LatchMods)
- xkbi->state.latched_mods&= ~filter->upAction.mods.mask;
- else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group);
- }
- else if ((pAction->type==filter->upAction.type)&&
- (pAction->mods.flags==filter->upAction.mods.flags)&&
- (pAction->mods.mask==filter->upAction.mods.mask)) {
- if (filter->upAction.mods.flags&XkbSA_LatchToLock) {
- XkbControlsPtr ctrls= xkbi->desc->ctrls;
- if (filter->upAction.type==XkbSA_LatchMods)
- pAction->mods.type= XkbSA_LockMods;
- else pAction->group.type= XkbSA_LockGroup;
- if (XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask)&&
- (ctrls->enabled_ctrls&XkbStickyKeysMask)) {
- XkbDDXAccessXBeep(xkbi->device,_BEEP_STICKY_LOCK,
- XkbStickyKeysMask);
- }
- }
- else {
- if (filter->upAction.type==XkbSA_LatchMods)
- pAction->mods.type= XkbSA_SetMods;
- else pAction->group.type= XkbSA_SetGroup;
- }
- if (filter->upAction.type==XkbSA_LatchMods)
- xkbi->state.latched_mods&= ~filter->upAction.mods.mask;
- else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group);
- filter->active = 0;
- }
- }
- else if (filter->keycode==keycode) { /* release */
- XkbControlsPtr ctrls= xkbi->desc->ctrls;
- int needBeep;
- int beepType= _BEEP_NONE;
-
- needBeep= ((ctrls->enabled_ctrls&XkbStickyKeysMask)&&
- XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask));
- if (filter->upAction.type==XkbSA_LatchMods) {
- xkbi->clearMods = filter->upAction.mods.mask;
- if ((filter->upAction.mods.flags&XkbSA_ClearLocks)&&
- (xkbi->clearMods&xkbi->state.locked_mods)==xkbi->clearMods) {
- xkbi->state.locked_mods&= ~xkbi->clearMods;
- filter->priv= NO_LATCH;
- beepType= _BEEP_STICKY_UNLOCK;
- }
- }
- else {
- xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
- if ((filter->upAction.group.flags&XkbSA_ClearLocks)&&
- (xkbi->state.locked_group)) {
- xkbi->state.locked_group = 0;
- filter->priv = NO_LATCH;
- beepType= _BEEP_STICKY_UNLOCK;
- }
- }
- if (filter->priv==NO_LATCH) {
- filter->active= 0;
- }
- else {
- filter->priv= LATCH_PENDING;
- if (filter->upAction.type==XkbSA_LatchMods) {
- xkbi->state.latched_mods |= filter->upAction.mods.mask;
- needBeep = xkbi->state.latched_mods ? needBeep : 0;
- xkbi->state.latched_mods |= filter->upAction.mods.mask;
- }
- else {
- xkbi->state.latched_group+= XkbSAGroup(&filter->upAction.group);
- }
- if (needBeep && (beepType==_BEEP_NONE))
- beepType= _BEEP_STICKY_LATCH;
- }
- if (needBeep && (beepType!=_BEEP_NONE))
- XkbDDXAccessXBeep(xkbi->device,beepType,XkbStickyKeysMask);
- }
- else if (filter->priv==LATCH_KEY_DOWN) {
- filter->priv= NO_LATCH;
- filter->filterOthers = 0;
- }
- return 1;
-}
-
-static int
-_XkbFilterLockState( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
- if (pAction&&(pAction->type==XkbSA_LockGroup)) {
- if (pAction->group.flags&XkbSA_GroupAbsolute)
- xkbi->state.locked_group= XkbSAGroup(&pAction->group);
- else xkbi->state.locked_group+= XkbSAGroup(&pAction->group);
- return 1;
- }
- if (filter->keycode==0) { /* initial press */
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 0;
- filter->priv = 0;
- filter->filter = _XkbFilterLockState;
- filter->upAction = *pAction;
- xkbi->state.locked_mods^= pAction->mods.mask;
- xkbi->setMods = pAction->mods.mask;
- }
- else if (filter->keycode==keycode) {
- filter->active = 0;
- xkbi->clearMods = filter->upAction.mods.mask;
- }
- return 1;
-}
-
-#define ISO_KEY_DOWN 0
-#define NO_ISO_LOCK 1
-
-static int
-_XkbFilterISOLock( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
-
- if (filter->keycode==0) { /* initial press */
- CARD8 flags= pAction->iso.flags;
-
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 1;
- filter->priv = ISO_KEY_DOWN;
- filter->upAction = *pAction;
- filter->filter = _XkbFilterISOLock;
- if (flags&XkbSA_ISODfltIsGroup) {
- xkbi->groupChange = XkbSAGroup(&pAction->iso);
- xkbi->setMods = 0;
- }
- else {
- xkbi->setMods = pAction->iso.mask;
- xkbi->groupChange = 0;
- }
- if ((!(flags&XkbSA_ISONoAffectMods))&&(xkbi->state.base_mods)) {
- filter->priv= NO_ISO_LOCK;
- xkbi->state.locked_mods^= xkbi->state.base_mods;
- }
- if ((!(flags&XkbSA_ISONoAffectGroup))&&(xkbi->state.base_group)) {
-/* 6/22/93 (ef) -- lock groups if group key is down first */
- }
- if (!(flags&XkbSA_ISONoAffectPtr)) {
-/* 6/22/93 (ef) -- lock mouse buttons if they're down */
- }
- }
- else if (filter->keycode==keycode) {
- CARD8 flags= filter->upAction.iso.flags;
-
- if (flags&XkbSA_ISODfltIsGroup) {
- xkbi->groupChange = -XkbSAGroup(&filter->upAction.iso);
- xkbi->clearMods = 0;
- if (filter->priv==ISO_KEY_DOWN)
- xkbi->state.locked_group+= XkbSAGroup(&filter->upAction.iso);
- }
- else {
- xkbi->clearMods= filter->upAction.iso.mask;
- xkbi->groupChange= 0;
- if (filter->priv==ISO_KEY_DOWN)
- xkbi->state.locked_mods^= filter->upAction.iso.mask;
- }
- filter->active = 0;
- }
- else if (pAction) {
- CARD8 flags= filter->upAction.iso.flags;
-
- switch (pAction->type) {
- case XkbSA_SetMods: case XkbSA_LatchMods:
- if (!(flags&XkbSA_ISONoAffectMods)) {
- pAction->type= XkbSA_LockMods;
- filter->priv= NO_ISO_LOCK;
- }
- break;
- case XkbSA_SetGroup: case XkbSA_LatchGroup:
- if (!(flags&XkbSA_ISONoAffectGroup)) {
- pAction->type= XkbSA_LockGroup;
- filter->priv= NO_ISO_LOCK;
- }
- break;
- case XkbSA_PtrBtn:
- if (!(flags&XkbSA_ISONoAffectPtr)) {
- pAction->type= XkbSA_LockPtrBtn;
- filter->priv= NO_ISO_LOCK;
- }
- break;
- case XkbSA_SetControls:
- if (!(flags&XkbSA_ISONoAffectCtrls)) {
- pAction->type= XkbSA_LockControls;
- filter->priv= NO_ISO_LOCK;
- }
- break;
- }
- }
- return 1;
-}
-
-
-static CARD32
-_XkbPtrAccelExpire(OsTimerPtr timer,CARD32 now,pointer arg)
-{
-XkbSrvInfoPtr xkbi= (XkbSrvInfoPtr)arg;
-XkbControlsPtr ctrls= xkbi->desc->ctrls;
-int dx,dy;
-
- if (xkbi->mouseKey==0)
- return 0;
-
- if (xkbi->mouseKeysAccel) {
- if ((xkbi->mouseKeysCounter)<ctrls->mk_time_to_max) {
- double step;
- xkbi->mouseKeysCounter++;
- step= xkbi->mouseKeysCurveFactor*
- pow((double)xkbi->mouseKeysCounter,xkbi->mouseKeysCurve);
- if (xkbi->mouseKeysDX<0)
- dx= floor( ((double)xkbi->mouseKeysDX)*step );
- else dx= ceil( ((double)xkbi->mouseKeysDX)*step );
- if (xkbi->mouseKeysDY<0)
- dy= floor( ((double)xkbi->mouseKeysDY)*step );
- else dy= ceil( ((double)xkbi->mouseKeysDY)*step );
- }
- else {
- dx= xkbi->mouseKeysDX*ctrls->mk_max_speed;
- dy= xkbi->mouseKeysDY*ctrls->mk_max_speed;
- }
- if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteX)
- dx= xkbi->mouseKeysDX;
- if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteY)
- dy= xkbi->mouseKeysDY;
- }
- else {
- dx= xkbi->mouseKeysDX;
- dy= xkbi->mouseKeysDY;
- }
- XkbDDXFakePointerMotion(xkbi->mouseKeysFlags,dx,dy);
- return xkbi->desc->ctrls->mk_interval;
-}
-
-static int
-_XkbFilterPointerMove( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
-int x,y;
-Bool accel;
-
- if (xkbi->device == inputInfo.keyboard)
- return 0;
-
- if (filter->keycode==0) { /* initial press */
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 0;
- filter->priv=0;
- filter->filter = _XkbFilterPointerMove;
- filter->upAction= *pAction;
- xkbi->mouseKeysCounter= 0;
- xkbi->mouseKey= keycode;
- accel= ((pAction->ptr.flags&XkbSA_NoAcceleration)==0);
- x= XkbPtrActionX(&pAction->ptr);
- y= XkbPtrActionY(&pAction->ptr);
- XkbDDXFakePointerMotion(pAction->ptr.flags,x,y);
- AccessXCancelRepeatKey(xkbi,keycode);
- xkbi->mouseKeysAccel= accel&&
- (xkbi->desc->ctrls->enabled_ctrls&XkbMouseKeysAccelMask);
- xkbi->mouseKeysFlags= pAction->ptr.flags;
- xkbi->mouseKeysDX= XkbPtrActionX(&pAction->ptr);
- xkbi->mouseKeysDY= XkbPtrActionY(&pAction->ptr);
- xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0,
- xkbi->desc->ctrls->mk_delay,
- _XkbPtrAccelExpire,(pointer)xkbi);
- }
- else if (filter->keycode==keycode) {
- filter->active = 0;
- if (xkbi->mouseKey==keycode) {
- xkbi->mouseKey= 0;
- xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0, 0,
- NULL, NULL);
- }
- }
- return 0;
-}
-
-static int
-_XkbFilterPointerBtn( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
- if (filter->keycode==0) { /* initial press */
- int button= pAction->btn.button;
-
- if (button==XkbSA_UseDfltButton)
- button = xkbi->desc->ctrls->mk_dflt_btn;
-
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 0;
- filter->priv=0;
- filter->filter = _XkbFilterPointerBtn;
- filter->upAction= *pAction;
- filter->upAction.btn.button= button;
- switch (pAction->type) {
- case XkbSA_LockPtrBtn:
- if (((xkbi->lockedPtrButtons&(1<<button))==0)&&
- ((pAction->btn.flags&XkbSA_LockNoLock)==0)) {
- xkbi->lockedPtrButtons|= (1<<button);
- AccessXCancelRepeatKey(xkbi,keycode);
- XkbDDXFakeDeviceButton(xkbi->device, 1, button);
- filter->upAction.type= XkbSA_NoAction;
- }
- break;
- case XkbSA_PtrBtn:
- {
- register int i,nClicks;
- AccessXCancelRepeatKey(xkbi,keycode);
- if (pAction->btn.count>0) {
- nClicks= pAction->btn.count;
- for (i=0;i<nClicks;i++) {
- XkbDDXFakeDeviceButton(xkbi->device, 1, button);
- XkbDDXFakeDeviceButton(xkbi->device, 0, button);
- }
- filter->upAction.type= XkbSA_NoAction;
- }
- else XkbDDXFakeDeviceButton(xkbi->device, 1, button);
- }
- break;
- case XkbSA_SetPtrDflt:
- {
- XkbControlsPtr ctrls= xkbi->desc->ctrls;
- XkbControlsRec old;
- xkbControlsNotify cn;
-
- old= *ctrls;
- AccessXCancelRepeatKey(xkbi,keycode);
- switch (pAction->dflt.affect) {
- case XkbSA_AffectDfltBtn:
- if (pAction->dflt.flags&XkbSA_DfltBtnAbsolute)
- ctrls->mk_dflt_btn=
- XkbSAPtrDfltValue(&pAction->dflt);
- else {
- ctrls->mk_dflt_btn+=
- XkbSAPtrDfltValue(&pAction->dflt);
- if (ctrls->mk_dflt_btn>5)
- ctrls->mk_dflt_btn= 5;
- else if (ctrls->mk_dflt_btn<1)
- ctrls->mk_dflt_btn= 1;
- }
- break;
- default:
- ErrorF(
- "Attempt to change unknown pointer default (%d) ignored\n",
- pAction->dflt.affect);
- break;
- }
- if (XkbComputeControlsNotify(xkbi->device,
- &old,xkbi->desc->ctrls,
- &cn,False)) {
- cn.keycode = keycode;
- /* XXX: what about DeviceKeyPress? */
- cn.eventType = KeyPress;
- cn.requestMajor = 0;
- cn.requestMinor = 0;
- XkbSendControlsNotify(xkbi->device,&cn);
- }
- }
- break;
- }
- }
- else if (filter->keycode==keycode) {
- int button= filter->upAction.btn.button;
-
- switch (filter->upAction.type) {
- case XkbSA_LockPtrBtn:
- if (((filter->upAction.btn.flags&XkbSA_LockNoUnlock)!=0)||
- ((xkbi->lockedPtrButtons&(1<<button))==0)) {
- break;
- }
- xkbi->lockedPtrButtons&= ~(1<<button);
- case XkbSA_PtrBtn:
- XkbDDXFakeDeviceButton(xkbi->device, 0, button);
- break;
- }
- filter->active = 0;
- }
- return 0;
-}
-
-static int
-_XkbFilterControls( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
-XkbControlsRec old;
-XkbControlsPtr ctrls;
-DeviceIntPtr kbd;
-unsigned int change;
-XkbEventCauseRec cause;
-
- kbd= xkbi->device;
- ctrls= xkbi->desc->ctrls;
- old= *ctrls;
- if (filter->keycode==0) { /* initial press */
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 0;
- change= XkbActionCtrls(&pAction->ctrls);
- filter->priv = change;
- filter->filter = _XkbFilterControls;
- filter->upAction = *pAction;
-
- if (pAction->type==XkbSA_LockControls) {
- filter->priv= (ctrls->enabled_ctrls&change);
- change&= ~ctrls->enabled_ctrls;
- }
-
- if (change) {
- xkbControlsNotify cn;
- XkbSrvLedInfoPtr sli;
-
- ctrls->enabled_ctrls|= change;
- if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,False)) {
- cn.keycode = keycode;
- /* XXX: what about DeviceKeyPress? */
- cn.eventType = KeyPress;
- cn.requestMajor = 0;
- cn.requestMinor = 0;
- XkbSendControlsNotify(kbd,&cn);
- }
-
- XkbSetCauseKey(&cause,keycode,KeyPress);
-
- /* If sticky keys were disabled, clear all locks and latches */
- if ((old.enabled_ctrls&XkbStickyKeysMask)&&
- (!(ctrls->enabled_ctrls&XkbStickyKeysMask))) {
- XkbClearAllLatchesAndLocks(kbd,xkbi,False,&cause);
- }
- sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
- XkbUpdateIndicators(kbd,sli->usesControls,True,NULL,&cause);
- if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask))
- XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_ON,change);
- }
- }
- else if (filter->keycode==keycode) {
- change= filter->priv;
- if (change) {
- xkbControlsNotify cn;
- XkbSrvLedInfoPtr sli;
-
- ctrls->enabled_ctrls&= ~change;
- if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,False)) {
- cn.keycode = keycode;
- cn.eventType = KeyRelease;
- cn.requestMajor = 0;
- cn.requestMinor = 0;
- XkbSendControlsNotify(kbd,&cn);
- }
-
- XkbSetCauseKey(&cause,keycode,KeyRelease);
- /* If sticky keys were disabled, clear all locks and latches */
- if ((old.enabled_ctrls&XkbStickyKeysMask)&&
- (!(ctrls->enabled_ctrls&XkbStickyKeysMask))) {
- XkbClearAllLatchesAndLocks(kbd,xkbi,False,&cause);
- }
- sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
- XkbUpdateIndicators(kbd,sli->usesControls,True,NULL,&cause);
- if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask))
- XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_OFF,change);
- }
- filter->keycode= 0;
- filter->active= 0;
- }
- return 1;
-}
-
-static int
-_XkbFilterActionMessage(XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
-XkbMessageAction * pMsg;
-DeviceIntPtr kbd;
-
- kbd= xkbi->device;
- if (filter->keycode==0) { /* initial press */
- pMsg= &pAction->msg;
- if ((pMsg->flags&XkbSA_MessageOnRelease)||
- ((pMsg->flags&XkbSA_MessageGenKeyEvent)==0)) {
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 0;
- filter->priv = 0;
- filter->filter = _XkbFilterActionMessage;
- filter->upAction = *pAction;
- }
- if (pMsg->flags&XkbSA_MessageOnPress) {
- xkbActionMessage msg;
-
- msg.keycode= keycode;
- msg.press= 1;
- msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0);
- memcpy((char *)msg.message,
- (char *)pMsg->message,XkbActionMessageLength);
- XkbSendActionMessage(kbd,&msg);
- }
- return ((pAction->msg.flags&XkbSA_MessageGenKeyEvent)!=0);
- }
- else if (filter->keycode==keycode) {
- pMsg= &filter->upAction.msg;
- if (pMsg->flags&XkbSA_MessageOnRelease) {
- xkbActionMessage msg;
-
- msg.keycode= keycode;
- msg.press= 0;
- msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0);
- memcpy((char *)msg.message,(char *)pMsg->message,
- XkbActionMessageLength);
- XkbSendActionMessage(kbd,&msg);
- }
- filter->keycode= 0;
- filter->active= 0;
- return ((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0);
- }
- return 0;
-}
-
-static int
-_XkbFilterRedirectKey( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
-DeviceEvent ev;
-int x,y;
-XkbStateRec old;
-unsigned mods,mask;
-xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device);
-ProcessInputProc backupproc;
-
- /* never actually used uninitialised, but gcc isn't smart enough
- * to work that out. */
- memset(&old, 0, sizeof(old));
-
- if ((filter->keycode!=0)&&(filter->keycode!=keycode))
- return 1;
-
- GetSpritePosition(xkbi->device, &x,&y);
- ev.header = ET_Internal;
- ev.length = sizeof(DeviceEvent);
- ev.time = GetTimeInMillis();
- ev.root_x = x;
- ev.root_y = y;
-
- if (filter->keycode==0) { /* initial press */
- if ((pAction->redirect.new_key<xkbi->desc->min_key_code)||
- (pAction->redirect.new_key>xkbi->desc->max_key_code)) {
- return 1;
- }
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 0;
- filter->priv = 0;
- filter->filter = _XkbFilterRedirectKey;
- filter->upAction = *pAction;
-
- ev.type = ET_KeyPress;
- ev.detail.key = pAction->redirect.new_key;
-
- mask= XkbSARedirectVModsMask(&pAction->redirect);
- mods= XkbSARedirectVMods(&pAction->redirect);
- if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask);
- if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods);
- mask|= pAction->redirect.mods_mask;
- mods|= pAction->redirect.mods;
-
- if ( mask || mods ) {
- old= xkbi->state;
- xkbi->state.base_mods&= ~mask;
- xkbi->state.base_mods|= (mods&mask);
- xkbi->state.latched_mods&= ~mask;
- xkbi->state.latched_mods|= (mods&mask);
- xkbi->state.locked_mods&= ~mask;
- xkbi->state.locked_mods|= (mods&mask);
- XkbComputeDerivedState(xkbi);
- }
-
- UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
- xkbi->device->public.processInputProc((InternalEvent*)&ev, xkbi->device);
- COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
- backupproc,xkbUnwrapProc);
-
- if ( mask || mods )
- xkbi->state= old;
- }
- else if (filter->keycode==keycode) {
-
- ev.type = ET_KeyRelease;
- ev.detail.key = filter->upAction.redirect.new_key;
-
- mask= XkbSARedirectVModsMask(&filter->upAction.redirect);
- mods= XkbSARedirectVMods(&filter->upAction.redirect);
- if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask);
- if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods);
- mask|= filter->upAction.redirect.mods_mask;
- mods|= filter->upAction.redirect.mods;
-
- if ( mask || mods ) {
- old= xkbi->state;
- xkbi->state.base_mods&= ~mask;
- xkbi->state.base_mods|= (mods&mask);
- xkbi->state.latched_mods&= ~mask;
- xkbi->state.latched_mods|= (mods&mask);
- xkbi->state.locked_mods&= ~mask;
- xkbi->state.locked_mods|= (mods&mask);
- XkbComputeDerivedState(xkbi);
- }
-
- UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
- xkbi->device->public.processInputProc((InternalEvent*)&ev, xkbi->device);
- COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
- backupproc,xkbUnwrapProc);
-
- if ( mask || mods )
- xkbi->state= old;
-
- filter->keycode= 0;
- filter->active= 0;
- }
- return 0;
-}
-
-static int
-_XkbFilterSwitchScreen( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
- DeviceIntPtr dev = xkbi->device;
- if (dev == inputInfo.keyboard)
- return 0;
-
- if (filter->keycode==0) { /* initial press */
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 0;
- filter->filter = _XkbFilterSwitchScreen;
- AccessXCancelRepeatKey(xkbi, keycode);
- XkbDDXSwitchScreen(dev,keycode,pAction);
- return 0;
- }
- else if (filter->keycode==keycode) {
- filter->active= 0;
- return 0;
- }
- return 1;
-}
-
-static int
-_XkbFilterXF86Private( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
- DeviceIntPtr dev = xkbi->device;
- if (dev == inputInfo.keyboard)
- return 0;
-
- if (filter->keycode==0) { /* initial press */
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 0;
- filter->filter = _XkbFilterXF86Private;
- XkbDDXPrivate(dev,keycode,pAction);
- return 0;
- }
- else if (filter->keycode==keycode) {
- filter->active= 0;
- return 0;
- }
- return 1;
-}
-
-
-static int
-_XkbFilterDeviceBtn( XkbSrvInfoPtr xkbi,
- XkbFilterPtr filter,
- unsigned keycode,
- XkbAction * pAction)
-{
-DeviceIntPtr dev;
-int button;
-
- if (xkbi->device == inputInfo.keyboard)
- return 0;
-
- if (filter->keycode==0) { /* initial press */
- _XkbLookupButtonDevice(&dev, pAction->devbtn.device, serverClient,
- DixUnknownAccess, &button);
- if (!dev || !dev->public.on)
- return 1;
-
- button= pAction->devbtn.button;
- if ((button<1)||(button>dev->button->numButtons))
- return 1;
-
- filter->keycode = keycode;
- filter->active = 1;
- filter->filterOthers = 0;
- filter->priv=0;
- filter->filter = _XkbFilterDeviceBtn;
- filter->upAction= *pAction;
- switch (pAction->type) {
- case XkbSA_LockDeviceBtn:
- if ((pAction->devbtn.flags&XkbSA_LockNoLock)||
- BitIsOn(dev->button->down, button))
- return 0;
- XkbDDXFakeDeviceButton(dev,True,button);
- filter->upAction.type= XkbSA_NoAction;
- break;
- case XkbSA_DeviceBtn:
- if (pAction->devbtn.count>0) {
- int nClicks,i;
- nClicks= pAction->btn.count;
- for (i=0;i<nClicks;i++) {
- XkbDDXFakeDeviceButton(dev,True,button);
- XkbDDXFakeDeviceButton(dev,False,button);
- }
- filter->upAction.type= XkbSA_NoAction;
- }
- else XkbDDXFakeDeviceButton(dev,True,button);
- break;
- }
- }
- else if (filter->keycode==keycode) {
- int button;
-
- filter->active= 0;
- _XkbLookupButtonDevice(&dev, filter->upAction.devbtn.device,
- serverClient, DixUnknownAccess, &button);
- if (!dev || !dev->public.on)
- return 1;
-
- button= filter->upAction.btn.button;
- switch (filter->upAction.type) {
- case XkbSA_LockDeviceBtn:
- if ((filter->upAction.devbtn.flags&XkbSA_LockNoUnlock)||
- !BitIsOn(dev->button->down, button))
- return 0;
- XkbDDXFakeDeviceButton(dev,False,button);
- break;
- case XkbSA_DeviceBtn:
- XkbDDXFakeDeviceButton(dev,False,button);
- break;
- }
- filter->active = 0;
- }
- return 0;
-}
-
-static XkbFilterPtr
-_XkbNextFreeFilter(
- XkbSrvInfoPtr xkbi
-)
-{
-register int i;
-
- if (xkbi->szFilters==0) {
- xkbi->szFilters = 4;
- xkbi->filters = _XkbTypedCalloc(xkbi->szFilters,XkbFilterRec);
- /* 6/21/93 (ef) -- XXX! deal with allocation failure */
- }
- for (i=0;i<xkbi->szFilters;i++) {
- if (!xkbi->filters[i].active) {
- xkbi->filters[i].keycode = 0;
- return &xkbi->filters[i];
- }
- }
- xkbi->szFilters*=2;
- xkbi->filters= _XkbTypedRealloc(xkbi->filters,
- xkbi->szFilters,
- XkbFilterRec);
- /* 6/21/93 (ef) -- XXX! deal with allocation failure */
- bzero(&xkbi->filters[xkbi->szFilters/2],
- (xkbi->szFilters/2)*sizeof(XkbFilterRec));
- return &xkbi->filters[xkbi->szFilters/2];
-}
-
-static int
-_XkbApplyFilters(XkbSrvInfoPtr xkbi,unsigned kc,XkbAction *pAction)
-{
-register int i,send;
-
- send= 1;
- for (i=0;i<xkbi->szFilters;i++) {
- if ((xkbi->filters[i].active)&&(xkbi->filters[i].filter))
- send= ((*xkbi->filters[i].filter)(xkbi,&xkbi->filters[i],kc,pAction)
- && send);
- }
- return send;
-}
-
-void
-XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent* event)
-{
-int key,bit,i;
-XkbSrvInfoPtr xkbi;
-KeyClassPtr keyc;
-int changed,sendEvent;
-Bool genStateNotify;
-XkbAction act;
-XkbFilterPtr filter;
-Bool keyEvent;
-Bool pressEvent;
-ProcessInputProc backupproc;
-
-xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
-
- keyc= kbd->key;
- xkbi= keyc->xkbInfo;
- key= event->detail.key;
- /* The state may change, so if we're not in the middle of sending a state
- * notify, prepare for it */
- if ((xkbi->flags&_XkbStateNotifyInProgress)==0) {
- xkbi->prev_state = xkbi->state;
- xkbi->flags|= _XkbStateNotifyInProgress;
- genStateNotify= True;
- }
- else genStateNotify= False;
-
- xkbi->clearMods = xkbi->setMods = 0;
- xkbi->groupChange = 0;
-
- sendEvent = 1;
- keyEvent= ((event->type == ET_KeyPress) || (event->type == ET_KeyRelease));
- pressEvent= ((event->type == ET_KeyPress)|| (event->type == ET_ButtonPress));
-
- if (pressEvent) {
- if (keyEvent)
- act = XkbGetKeyAction(xkbi,&xkbi->state,key);
- else {
- act = XkbGetButtonAction(kbd,dev,key);
- key|= BTN_ACT_FLAG;
- }
- sendEvent = _XkbApplyFilters(xkbi,key,&act);
- if (sendEvent) {
- switch (act.type) {
- case XkbSA_SetMods:
- case XkbSA_SetGroup:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent = _XkbFilterSetState(xkbi,filter,key,&act);
- break;
- case XkbSA_LatchMods:
- case XkbSA_LatchGroup:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent=_XkbFilterLatchState(xkbi,filter,key,&act);
- break;
- case XkbSA_LockMods:
- case XkbSA_LockGroup:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent=_XkbFilterLockState(xkbi,filter,key,&act);
- break;
- case XkbSA_ISOLock:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent=_XkbFilterISOLock(xkbi,filter,key,&act);
- break;
- case XkbSA_MovePtr:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent= _XkbFilterPointerMove(xkbi,filter,key,&act);
- break;
- case XkbSA_PtrBtn:
- case XkbSA_LockPtrBtn:
- case XkbSA_SetPtrDflt:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent= _XkbFilterPointerBtn(xkbi,filter,key,&act);
- break;
- case XkbSA_Terminate:
- sendEvent= XkbDDXTerminateServer(dev,key,&act);
- break;
- case XkbSA_SwitchScreen:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent=_XkbFilterSwitchScreen(xkbi,filter,key,&act);
- break;
- case XkbSA_SetControls:
- case XkbSA_LockControls:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent=_XkbFilterControls(xkbi,filter,key,&act);
- break;
- case XkbSA_ActionMessage:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent=_XkbFilterActionMessage(xkbi,filter,key,&act);
- break;
- case XkbSA_RedirectKey:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent= _XkbFilterRedirectKey(xkbi,filter,key,&act);
- break;
- case XkbSA_DeviceBtn:
- case XkbSA_LockDeviceBtn:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent= _XkbFilterDeviceBtn(xkbi,filter,key,&act);
- break;
- case XkbSA_XFree86Private:
- filter = _XkbNextFreeFilter(xkbi);
- sendEvent= _XkbFilterXF86Private(xkbi,filter,key,&act);
- break;
- }
- }
- }
- else {
- if (!keyEvent)
- key|= BTN_ACT_FLAG;
- sendEvent = _XkbApplyFilters(xkbi,key,NULL);
- }
-
- if (xkbi->groupChange!=0)
- xkbi->state.base_group+= xkbi->groupChange;
- if (xkbi->setMods) {
- for (i=0,bit=1; xkbi->setMods; i++,bit<<=1 ) {
- if (xkbi->setMods&bit) {
- keyc->modifierKeyCount[i]++;
- xkbi->state.base_mods|= bit;
- xkbi->setMods&= ~bit;
- }
- }
- }
- if (xkbi->clearMods) {
- for (i=0,bit=1; xkbi->clearMods; i++,bit<<=1 ) {
- if (xkbi->clearMods&bit) {
- keyc->modifierKeyCount[i]--;
- if (keyc->modifierKeyCount[i]<=0) {
- xkbi->state.base_mods&= ~bit;
- keyc->modifierKeyCount[i] = 0;
- }
- xkbi->clearMods&= ~bit;
- }
- }
- }
-
- if (sendEvent) {
- DeviceIntPtr tmpdev;
- if (keyEvent)
- tmpdev = dev;
- else
- tmpdev = GetPairedDevice(dev);
-
- UNWRAP_PROCESS_INPUT_PROC(tmpdev,xkbPrivPtr, backupproc);
- dev->public.processInputProc((InternalEvent*)event, tmpdev);
- COND_WRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr,
- backupproc,xkbUnwrapProc);
- }
- else if (keyEvent) {
- FixKeyState(event, dev);
- }
-
- XkbComputeDerivedState(xkbi);
- changed = XkbStateChangedFlags(&xkbi->prev_state,&xkbi->state);
- if (genStateNotify) {
- if (changed) {
- xkbStateNotify sn;
- sn.keycode= key;
- sn.eventType= event->type;
- sn.requestMajor = sn.requestMinor = 0;
- sn.changed= changed;
- XkbSendStateNotify(dev,&sn);
- }
- xkbi->flags&= ~_XkbStateNotifyInProgress;
- }
- changed= XkbIndicatorsToUpdate(dev,changed,False);
- if (changed) {
- XkbEventCauseRec cause;
- XkbSetCauseKey(&cause, key, event->type);
- XkbUpdateIndicators(dev,changed,False,NULL,&cause);
- }
- return;
-}
-
-int
-XkbLatchModifiers(DeviceIntPtr pXDev,CARD8 mask,CARD8 latches)
-{
-XkbSrvInfoPtr xkbi;
-XkbFilterPtr filter;
-XkbAction act;
-unsigned clear;
-
- if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) {
- xkbi = pXDev->key->xkbInfo;
- clear= (mask&(~latches));
- xkbi->state.latched_mods&= ~clear;
- /* Clear any pending latch to locks.
- */
- act.type = XkbSA_NoAction;
- _XkbApplyFilters(xkbi,SYNTHETIC_KEYCODE,&act);
- act.type = XkbSA_LatchMods;
- act.mods.flags = 0;
- act.mods.mask = mask&latches;
- filter = _XkbNextFreeFilter(xkbi);
- _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act);
- _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL);
- return Success;
- }
- return BadValue;
-}
-
-int
-XkbLatchGroup(DeviceIntPtr pXDev,int group)
-{
-XkbSrvInfoPtr xkbi;
-XkbFilterPtr filter;
-XkbAction act;
-
- if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) {
- xkbi = pXDev->key->xkbInfo;
- act.type = XkbSA_LatchGroup;
- act.group.flags = 0;
- XkbSASetGroup(&act.group,group);
- filter = _XkbNextFreeFilter(xkbi);
- _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act);
- _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL);
- return Success;
- }
- return BadValue;
-}
-
-/***====================================================================***/
-
-void
-XkbClearAllLatchesAndLocks( DeviceIntPtr dev,
- XkbSrvInfoPtr xkbi,
- Bool genEv,
- XkbEventCausePtr cause)
-{
-XkbStateRec os;
-xkbStateNotify sn;
-
- sn.changed= 0;
- os= xkbi->state;
- if (os.latched_mods) { /* clear all latches */
- XkbLatchModifiers(dev,~0,0);
- sn.changed|= XkbModifierLatchMask;
- }
- if (os.latched_group) {
- XkbLatchGroup(dev,0);
- sn.changed|= XkbGroupLatchMask;
- }
- if (os.locked_mods) {
- xkbi->state.locked_mods= 0;
- sn.changed|= XkbModifierLockMask;
- }
- if (os.locked_group) {
- xkbi->state.locked_group= 0;
- sn.changed|= XkbGroupLockMask;
- }
- if ( genEv && sn.changed) {
- CARD32 changed;
-
- XkbComputeDerivedState(xkbi);
- sn.keycode= cause->kc;
- sn.eventType= cause->event;
- sn.requestMajor= cause->mjr;
- sn.requestMinor= cause->mnr;
- sn.changed= XkbStateChangedFlags(&os,&xkbi->state);
- XkbSendStateNotify(dev,&sn);
- changed= XkbIndicatorsToUpdate(dev,sn.changed,False);
- if (changed) {
- XkbUpdateIndicators(dev,changed,True,NULL,cause);
- }
- }
- return;
-}
-
+/************************************************************
+Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
+
+Permission to use, copy, modify, and distribute this
+software and its documentation for any purpose and without
+fee is hereby granted, provided that the above copyright
+notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting
+documentation, and that the name of Silicon Graphics not be
+used in advertising or publicity pertaining to distribution
+of the software without specific prior written permission.
+Silicon Graphics makes no representation about the suitability
+of this software for any purpose. It is provided "as is"
+without any express or implied warranty.
+
+SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
+THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+********************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/keysym.h>
+#include "misc.h"
+#include "inputstr.h"
+#include "exevents.h"
+#include "eventstr.h"
+#include <xkbsrv.h>
+#include "xkb.h"
+#include <ctype.h>
+#define EXTENSION_EVENT_BASE 64
+
+static int xkbDevicePrivateKeyIndex;
+DevPrivateKey xkbDevicePrivateKey = &xkbDevicePrivateKeyIndex;
+
+void
+xkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc,
+ pointer data)
+{
+ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device);
+ ProcessInputProc backupproc;
+ if(xkbPrivPtr->unwrapProc)
+ xkbPrivPtr->unwrapProc = NULL;
+
+ UNWRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr, backupproc);
+ proc(device,data);
+ COND_WRAP_PROCESS_INPUT_PROC(device,xkbPrivPtr,
+ backupproc,xkbUnwrapProc);
+}
+
+
+void
+XkbSetExtension(DeviceIntPtr device, ProcessInputProc proc)
+{
+ xkbDeviceInfoPtr xkbPrivPtr;
+
+ xkbPrivPtr = (xkbDeviceInfoPtr) xcalloc(1, sizeof(xkbDeviceInfoRec));
+ if (!xkbPrivPtr)
+ return;
+ xkbPrivPtr->unwrapProc = NULL;
+
+ dixSetPrivate(&device->devPrivates, xkbDevicePrivateKey, xkbPrivPtr);
+ WRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, proc, xkbUnwrapProc);
+}
+
+/***====================================================================***/
+
+static XkbAction
+_FixUpAction(XkbDescPtr xkb,XkbAction *act)
+{
+static XkbAction fake;
+
+ if (XkbIsPtrAction(act)&&(!(xkb->ctrls->enabled_ctrls&XkbMouseKeysMask))) {
+ fake.type = XkbSA_NoAction;
+ return fake;
+ }
+ if (xkb->ctrls->enabled_ctrls&XkbStickyKeysMask) {
+ if (act->any.type==XkbSA_SetMods) {
+ fake.mods.type = XkbSA_LatchMods;
+ fake.mods.mask = act->mods.mask;
+ if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask))
+ fake.mods.flags= XkbSA_ClearLocks|XkbSA_LatchToLock;
+ else fake.mods.flags= XkbSA_ClearLocks;
+ return fake;
+ }
+ if (act->any.type==XkbSA_SetGroup) {
+ fake.group.type = XkbSA_LatchGroup;
+ if (XkbAX_NeedOption(xkb->ctrls,XkbAX_LatchToLockMask))
+ fake.group.flags= XkbSA_ClearLocks|XkbSA_LatchToLock;
+ else fake.group.flags= XkbSA_ClearLocks;
+ XkbSASetGroup(&fake.group,XkbSAGroup(&act->group));
+ return fake;
+ }
+ }
+ return *act;
+}
+
+static XkbAction
+XkbGetKeyAction(XkbSrvInfoPtr xkbi,XkbStatePtr xkbState,CARD8 key)
+{
+int effectiveGroup;
+int col;
+XkbDescPtr xkb;
+XkbKeyTypePtr type;
+XkbAction * pActs;
+static XkbAction fake;
+
+ xkb= xkbi->desc;
+ if (!XkbKeyHasActions(xkb,key) || !XkbKeycodeInRange(xkb,key)) {
+ fake.type = XkbSA_NoAction;
+ return fake;
+ }
+ pActs= XkbKeyActionsPtr(xkb,key);
+ col= 0;
+
+ effectiveGroup = XkbGetEffectiveGroup(xkbi, xkbState, key);
+ if (effectiveGroup != XkbGroup1Index)
+ col += (effectiveGroup * XkbKeyGroupsWidth(xkb, key));
+
+ type= XkbKeyKeyType(xkb,key,effectiveGroup);
+ if (type->map!=NULL) {
+ register unsigned i,mods;
+ register XkbKTMapEntryPtr entry;
+ mods= xkbState->mods&type->mods.mask;
+ for (entry= type->map,i=0;i<type->map_count;i++,entry++) {
+ if ((entry->active)&&(entry->mods.mask==mods)) {
+ col+= entry->level;
+ break;
+ }
+ }
+ }
+ if (pActs[col].any.type==XkbSA_NoAction)
+ return pActs[col];
+ fake= _FixUpAction(xkb,&pActs[col]);
+ return fake;
+}
+
+static XkbAction
+XkbGetButtonAction(DeviceIntPtr kbd,DeviceIntPtr dev,int button)
+{
+XkbAction fake;
+ if ((dev->button)&&(dev->button->xkb_acts)) {
+ if (dev->button->xkb_acts[button-1].any.type!=XkbSA_NoAction) {
+ fake= _FixUpAction(kbd->key->xkbInfo->desc,
+ &dev->button->xkb_acts[button-1]);
+ return fake;
+ }
+ }
+ fake.any.type= XkbSA_NoAction;
+ return fake;
+}
+
+/***====================================================================***/
+
+#define SYNTHETIC_KEYCODE 1
+#define BTN_ACT_FLAG 0x100
+
+static int
+_XkbFilterSetState( XkbSrvInfoPtr xkbi,
+ XkbFilterPtr filter,
+ unsigned keycode,
+ XkbAction *pAction)
+{
+ if (filter->keycode==0) { /* initial press */
+ filter->keycode = keycode;
+ filter->active = 1;
+ filter->filterOthers = ((pAction->mods.mask&XkbSA_ClearLocks)!=0);
+ filter->priv = 0;
+ filter->filter = _XkbFilterSetState;
+ if (pAction->type==XkbSA_SetMods) {
+ filter->upAction = *pAction;
+ xkbi->setMods= pAction->mods.mask;
+ }
+ else {
+ xkbi->groupChange = XkbSAGroup(&pAction->group);
+ if (pAction->group.flags&XkbSA_GroupAbsolute)
+ xkbi->groupChange-= xkbi->state.base_group;
+ filter->upAction= *pAction;
+ XkbSASetGroup(&filter->upAction.group,xkbi->groupChange);
+ }
+ }
+ else if (filter->keycode==keycode) {
+ if (filter->upAction.type==XkbSA_SetMods) {
+ xkbi->clearMods = filter->upAction.mods.mask;
+ if (filter->upAction.mods.flags&XkbSA_ClearLocks) {
+ xkbi->state.locked_mods&= ~filter->upAction.mods.mask;
+ }
+ }
+ else {
+ if (filter->upAction.group.flags&XkbSA_ClearLocks) {
+ xkbi->state.locked_group = 0;
+ }
+ xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
+ }
+ filter->active = 0;
+ }
+ else {
+ filter->upAction.mods.flags&= ~XkbSA_ClearLocks;
+ filter->filterOthers = 0;
+ }
+ return 1;
+}
+
+#define LATCH_KEY_DOWN 1
+#define LATCH_PENDING 2
+#define NO_LATCH 3
+
+static int
+_XkbFilterLatchState( XkbSrvInfoPtr xkbi,
+ XkbFilterPtr filter,
+ unsigned keycode,
+ XkbAction * pAction)
+{
+
+ if (filter->keycode==0) { /* initial press */
+ filter->keycode = keycode;
+ filter->active = 1;
+ filter->filterOthers = 1;
+ filter->priv = LATCH_KEY_DOWN;
+ filter->filter = _XkbFilterLatchState;
+ if (pAction->type==XkbSA_LatchMods) {
+ filter->upAction = *pAction;
+ xkbi->setMods = pAction->mods.mask;
+ }
+ else {
+ xkbi->groupChange = XkbSAGroup(&pAction->group);
+ if (pAction->group.flags&XkbSA_GroupAbsolute)
+ xkbi->groupChange-= xkbi->state.base_group;
+ filter->upAction= *pAction;
+ XkbSASetGroup(&filter->upAction.group,xkbi->groupChange);
+ }
+ }
+ else if ( pAction && (filter->priv==LATCH_PENDING) ) {
+ if (((1<<pAction->type)&XkbSA_BreakLatch)!=0) {
+ filter->active = 0;
+ if (filter->upAction.type==XkbSA_LatchMods)
+ xkbi->state.latched_mods&= ~filter->upAction.mods.mask;
+ else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group);
+ }
+ else if ((pAction->type==filter->upAction.type)&&
+ (pAction->mods.flags==filter->upAction.mods.flags)&&
+ (pAction->mods.mask==filter->upAction.mods.mask)) {
+ if (filter->upAction.mods.flags&XkbSA_LatchToLock) {
+ XkbControlsPtr ctrls= xkbi->desc->ctrls;
+ if (filter->upAction.type==XkbSA_LatchMods)
+ pAction->mods.type= XkbSA_LockMods;
+ else pAction->group.type= XkbSA_LockGroup;
+ if (XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask)&&
+ (ctrls->enabled_ctrls&XkbStickyKeysMask)) {
+ XkbDDXAccessXBeep(xkbi->device,_BEEP_STICKY_LOCK,
+ XkbStickyKeysMask);
+ }
+ }
+ else {
+ if (filter->upAction.type==XkbSA_LatchMods)
+ pAction->mods.type= XkbSA_SetMods;
+ else pAction->group.type= XkbSA_SetGroup;
+ }
+ if (filter->upAction.type==XkbSA_LatchMods)
+ xkbi->state.latched_mods&= ~filter->upAction.mods.mask;
+ else xkbi->state.latched_group-=XkbSAGroup(&filter->upAction.group);
+ filter->active = 0;
+ }
+ }
+ else if (filter->keycode==keycode) { /* release */
+ XkbControlsPtr ctrls= xkbi->desc->ctrls;
+ int needBeep;
+ int beepType= _BEEP_NONE;
+
+ needBeep= ((ctrls->enabled_ctrls&XkbStickyKeysMask)&&
+ XkbAX_NeedFeedback(ctrls,XkbAX_StickyKeysFBMask));
+ if (filter->upAction.type==XkbSA_LatchMods) {
+ xkbi->clearMods = filter->upAction.mods.mask;
+ if ((filter->upAction.mods.flags&XkbSA_ClearLocks)&&
+ (xkbi->clearMods&xkbi->state.locked_mods)==xkbi->clearMods) {
+ xkbi->state.locked_mods&= ~xkbi->clearMods;
+ filter->priv= NO_LATCH;
+ beepType= _BEEP_STICKY_UNLOCK;
+ }
+ }
+ else {
+ xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
+ if ((filter->upAction.group.flags&XkbSA_ClearLocks)&&
+ (xkbi->state.locked_group)) {
+ xkbi->state.locked_group = 0;
+ filter->priv = NO_LATCH;
+ beepType= _BEEP_STICKY_UNLOCK;
+ }
+ }
+ if (filter->priv==NO_LATCH) {
+ filter->active= 0;
+ }
+ else {
+ filter->priv= LATCH_PENDING;
+ if (filter->upAction.type==XkbSA_LatchMods) {
+ xkbi->state.latched_mods |= filter->upAction.mods.mask;
+ needBeep = xkbi->state.latched_mods ? needBeep : 0;
+ xkbi->state.latched_mods |= filter->upAction.mods.mask;
+ }
+ else {
+ xkbi->state.latched_group+= XkbSAGroup(&filter->upAction.group);
+ }
+ if (needBeep && (beepType==_BEEP_NONE))
+ beepType= _BEEP_STICKY_LATCH;
+ }
+ if (needBeep && (beepType!=_BEEP_NONE))
+ XkbDDXAccessXBeep(xkbi->device,beepType,XkbStickyKeysMask);
+ }
+ else if (filter->priv==LATCH_KEY_DOWN) {
+ filter->priv= NO_LATCH;
+ filter->filterOthers = 0;
+ }
+ return 1;
+}
+
+static int
+_XkbFilterLockState( XkbSrvInfoPtr xkbi,
+ XkbFilterPtr filter,
+ unsigned keycode,
+ XkbAction * pAction)
+{
+ if (pAction&&(pAction->type==XkbSA_LockGroup)) {
+ if (pAction->group.flags&XkbSA_GroupAbsolute)
+ xkbi->state.locked_group= XkbSAGroup(&pAction->group);
+ else xkbi->state.locked_group+= XkbSAGroup(&pAction->group);
+ return 1;
+ }
+ if (filter->keycode==0) { /* initial press */
+ filter->keycode = keycode;
+ filter->active = 1;
+ filter->filterOthers = 0;
+ filter->priv = 0;
+ filter->filter = _XkbFilterLockState;
+ filter->upAction = *pAction;
+ xkbi->state.locked_mods^= pAction->mods.mask;
+ xkbi->setMods = pAction->mods.mask;
+ }
+ else if (filter->keycode==keycode) {
+ filter->active = 0;
+ xkbi->clearMods = filter->upAction.mods.mask;
+ }
+ return 1;
+}
+
+#define ISO_KEY_DOWN 0
+#define NO_ISO_LOCK 1
+
+static int
+_XkbFilterISOLock( XkbSrvInfoPtr xkbi,
+ XkbFilterPtr filter,
+ unsigned keycode,
+ XkbAction * pAction)
+{
+
+ if (filter->keycode==0) { /* initial press */
+ CARD8 flags= pAction->iso.flags;
+
+ filter->keycode = keycode;
+ filter->active = 1;
+ filter->filterOthers = 1;
+ filter->priv = ISO_KEY_DOWN;
+ filter->upAction = *pAction;
+ filter->filter = _XkbFilterISOLock;
+ if (flags&XkbSA_ISODfltIsGroup) {
+ xkbi->groupChange = XkbSAGroup(&pAction->iso);
+ xkbi->setMods = 0;
+ }
+ else {
+ xkbi->setMods = pAction->iso.mask;
+ xkbi->groupChange = 0;
+ }
+ if ((!(flags&XkbSA_ISONoAffectMods))&&(xkbi->state.base_mods)) {
+ filter->priv= NO_ISO_LOCK;
+ xkbi->state.locked_mods^= xkbi->state.base_mods;
+ }
+ if ((!(flags&XkbSA_ISONoAffectGroup))&&(xkbi->state.base_group)) {
+/* 6/22/93 (ef) -- lock groups if group key is down first */
+ }
+ if (!(flags&XkbSA_ISONoAffectPtr)) {
+/* 6/22/93 (ef) -- lock mouse buttons if they're down */
+ }
+ }
+ else if (filter->keycode==keycode) {
+ CARD8 flags= filter->upAction.iso.flags;
+
+ if (flags&XkbSA_ISODfltIsGroup) {
+ xkbi->groupChange = -XkbSAGroup(&filter->upAction.iso);
+ xkbi->clearMods = 0;
+ if (filter->priv==ISO_KEY_DOWN)
+ xkbi->state.locked_group+= XkbSAGroup(&filter->upAction.iso);
+ }
+ else {
+ xkbi->clearMods= filter->upAction.iso.mask;
+ xkbi->groupChange= 0;
+ if (filter->priv==ISO_KEY_DOWN)
+ xkbi->state.locked_mods^= filter->upAction.iso.mask;
+ }
+ filter->active = 0;
+ }
+ else if (pAction) {
+ CARD8 flags= filter->upAction.iso.flags;
+
+ switch (pAction->type) {
+ case XkbSA_SetMods: case XkbSA_LatchMods:
+ if (!(flags&XkbSA_ISONoAffectMods)) {
+ pAction->type= XkbSA_LockMods;
+ filter->priv= NO_ISO_LOCK;
+ }
+ break;
+ case XkbSA_SetGroup: case XkbSA_LatchGroup:
+ if (!(flags&XkbSA_ISONoAffectGroup)) {
+ pAction->type= XkbSA_LockGroup;
+ filter->priv= NO_ISO_LOCK;
+ }
+ break;
+ case XkbSA_PtrBtn:
+ if (!(flags&XkbSA_ISONoAffectPtr)) {
+ pAction->type= XkbSA_LockPtrBtn;
+ filter->priv= NO_ISO_LOCK;
+ }
+ break;
+ case XkbSA_SetControls:
+ if (!(flags&XkbSA_ISONoAffectCtrls)) {
+ pAction->type= XkbSA_LockControls;
+ filter->priv= NO_ISO_LOCK;
+ }
+ break;
+ }
+ }
+ return 1;
+}
+
+
+static CARD32
+_XkbPtrAccelExpire(OsTimerPtr timer,CARD32 now,pointer arg)
+{
+XkbSrvInfoPtr xkbi= (XkbSrvInfoPtr)arg;
+XkbControlsPtr ctrls= xkbi->desc->ctrls;
+int dx,dy;
+
+ if (xkbi->mouseKey==0)
+ return 0;
+
+ if (xkbi->mouseKeysAccel) {
+ if ((xkbi->mouseKeysCounter)<ctrls->mk_time_to_max) {
+ double step;
+ xkbi->mouseKeysCounter++;
+ step= xkbi->mouseKeysCurveFactor*
+ pow((double)xkbi->mouseKeysCounter,xkbi->mouseKeysCurve);
+ if (xkbi->mouseKeysDX<0)
+ dx= floor( ((double)xkbi->mouseKeysDX)*step );
+ else dx= ceil( ((double)xkbi->mouseKeysDX)*step );
+ if (xkbi->mouseKeysDY<0)
+ dy= floor( ((double)xkbi->mouseKeysDY)*step );
+ else dy= ceil( ((double)xkbi->mouseKeysDY)*step );
+ }
+ else {
+ dx= xkbi->mouseKeysDX*ctrls->mk_max_speed;
+ dy= xkbi->mouseKeysDY*ctrls->mk_max_speed;
+ }
+ if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteX)
+ dx= xkbi->mouseKeysDX;
+ if (xkbi->mouseKeysFlags&XkbSA_MoveAbsoluteY)
+ dy= xkbi->mouseKeysDY;
+ }
+ else {
+ dx= xkbi->mouseKeysDX;
+ dy= xkbi->mouseKeysDY;
+ }
+ XkbDDXFakePointerMotion(xkbi->mouseKeysFlags,dx,dy);
+ return xkbi->desc->ctrls->mk_interval;
+}
+
+static int
+_XkbFilterPointerMove( XkbSrvInfoPtr xkbi,
+ XkbFilterPtr filter,
+ unsigned keycode,
+ XkbAction * pAction)
+{
+int x,y;
+Bool accel;
+
+ if (xkbi->device == inputInfo.keyboard)
+ return 0;
+
+ if (filter->keycode==0) { /* initial press */
+ filter->keycode = keycode;
+ filter->active = 1;
+ filter->filterOthers = 0;
+ filter->priv=0;
+ filter->filter = _XkbFilterPointerMove;
+ filter->upAction= *pAction;
+ xkbi->mouseKeysCounter= 0;
+ xkbi->mouseKey= keycode;
+ accel= ((pAction->ptr.flags&XkbSA_NoAcceleration)==0);
+ x= XkbPtrActionX(&pAction->ptr);
+ y= XkbPtrActionY(&pAction->ptr);
+ XkbDDXFakePointerMotion(pAction->ptr.flags,x,y);
+ AccessXCancelRepeatKey(xkbi,keycode);
+ xkbi->mouseKeysAccel= accel&&
+ (xkbi->desc->ctrls->enabled_ctrls&XkbMouseKeysAccelMask);
+ xkbi->mouseKeysFlags= pAction->ptr.flags;
+ xkbi->mouseKeysDX= XkbPtrActionX(&pAction->ptr);
+ xkbi->mouseKeysDY= XkbPtrActionY(&pAction->ptr);
+ xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0,
+ xkbi->desc->ctrls->mk_delay,
+ _XkbPtrAccelExpire,(pointer)xkbi);
+ }
+ else if (filter->keycode==keycode) {
+ filter->active = 0;
+ if (xkbi->mouseKey==keycode) {
+ xkbi->mouseKey= 0;
+ xkbi->mouseKeyTimer= TimerSet(xkbi->mouseKeyTimer, 0, 0,
+ NULL, NULL);
+ }
+ }
+ return 0;
+}
+
+static int
+_XkbFilterPointerBtn( XkbSrvInfoPtr xkbi,
+ XkbFilterPtr filter,
+ unsigned keycode,
+ XkbAction * pAction)
+{
+ if (filter->keycode==0) { /* initial press */
+ int button= pAction->btn.button;
+
+ if (button==XkbSA_UseDfltButton)
+ button = xkbi->desc->ctrls->mk_dflt_btn;
+
+ filter->keycode = keycode;
+ filter->active = 1;
+ filter->filterOthers = 0;
+ filter->priv=0;
+ filter->filter = _XkbFilterPointerBtn;
+ filter->upAction= *pAction;
+ filter->upAction.btn.button= button;
+ switch (pAction->type) {
+ case XkbSA_LockPtrBtn:
+ if (((xkbi->lockedPtrButtons&(1<<button))==0)&&
+ ((pAction->btn.flags&XkbSA_LockNoLock)==0)) {
+ xkbi->lockedPtrButtons|= (1<<button);
+ AccessXCancelRepeatKey(xkbi,keycode);
+ XkbDDXFakeDeviceButton(xkbi->device, 1, button);
+ filter->upAction.type= XkbSA_NoAction;
+ }
+ break;
+ case XkbSA_PtrBtn:
+ {
+ register int i,nClicks;
+ AccessXCancelRepeatKey(xkbi,keycode);
+ if (pAction->btn.count>0) {
+ nClicks= pAction->btn.count;
+ for (i=0;i<nClicks;i++) {
+ XkbDDXFakeDeviceButton(xkbi->device, 1, button);
+ XkbDDXFakeDeviceButton(xkbi->device, 0, button);
+ }
+ filter->upAction.type= XkbSA_NoAction;
+ }
+ else XkbDDXFakeDeviceButton(xkbi->device, 1, button);
+ }
+ break;
+ case XkbSA_SetPtrDflt:
+ {
+ XkbControlsPtr ctrls= xkbi->desc->ctrls;
+ XkbControlsRec old;
+ xkbControlsNotify cn;
+
+ old= *ctrls;
+ AccessXCancelRepeatKey(xkbi,keycode);
+ switch (pAction->dflt.affect) {
+ case XkbSA_AffectDfltBtn:
+ if (pAction->dflt.flags&XkbSA_DfltBtnAbsolute)
+ ctrls->mk_dflt_btn=
+ XkbSAPtrDfltValue(&pAction->dflt);
+ else {
+ ctrls->mk_dflt_btn+=
+ XkbSAPtrDfltValue(&pAction->dflt);
+ if (ctrls->mk_dflt_btn>5)
+ ctrls->mk_dflt_btn= 5;
+ else if (ctrls->mk_dflt_btn<1)
+ ctrls->mk_dflt_btn= 1;
+ }
+ break;
+ default:
+ ErrorF(
+ "Attempt to change unknown pointer default (%d) ignored\n",
+ pAction->dflt.affect);
+ break;
+ }
+ if (XkbComputeControlsNotify(xkbi->device,
+ &old,xkbi->desc->ctrls,
+ &cn,False)) {
+ cn.keycode = keycode;
+ /* XXX: what about DeviceKeyPress? */
+ cn.eventType = KeyPress;
+ cn.requestMajor = 0;
+ cn.requestMinor = 0;
+ XkbSendControlsNotify(xkbi->device,&cn);
+ }
+ }
+ break;
+ }
+ }
+ else if (filter->keycode==keycode) {
+ int button= filter->upAction.btn.button;
+
+ switch (filter->upAction.type) {
+ case XkbSA_LockPtrBtn:
+ if (((filter->upAction.btn.flags&XkbSA_LockNoUnlock)!=0)||
+ ((xkbi->lockedPtrButtons&(1<<button))==0)) {
+ break;
+ }
+ xkbi->lockedPtrButtons&= ~(1<<button);
+ case XkbSA_PtrBtn:
+ XkbDDXFakeDeviceButton(xkbi->device, 0, button);
+ break;
+ }
+ filter->active = 0;
+ }
+ return 0;
+}
+
+static int
+_XkbFilterControls( XkbSrvInfoPtr xkbi,
+ XkbFilterPtr filter,
+ unsigned keycode,
+ XkbAction * pAction)
+{
+XkbControlsRec old;
+XkbControlsPtr ctrls;
+DeviceIntPtr kbd;
+unsigned int change;
+XkbEventCauseRec cause;
+
+ kbd= xkbi->device;
+ ctrls= xkbi->desc->ctrls;
+ old= *ctrls;
+ if (filter->keycode==0) { /* initial press */
+ filter->keycode = keycode;
+ filter->active = 1;
+ filter->filterOthers = 0;
+ change= XkbActionCtrls(&pAction->ctrls);
+ filter->priv = change;
+ filter->filter = _XkbFilterControls;
+ filter->upAction = *pAction;
+
+ if (pAction->type==XkbSA_LockControls) {
+ filter->priv= (ctrls->enabled_ctrls&change);
+ change&= ~ctrls->enabled_ctrls;
+ }
+
+ if (change) {
+ xkbControlsNotify cn;
+ XkbSrvLedInfoPtr sli;
+
+ ctrls->enabled_ctrls|= change;
+ if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,False)) {
+ cn.keycode = keycode;
+ /* XXX: what about DeviceKeyPress? */
+ cn.eventType = KeyPress;
+ cn.requestMajor = 0;
+ cn.requestMinor = 0;
+ XkbSendControlsNotify(kbd,&cn);
+ }
+
+ XkbSetCauseKey(&cause,keycode,KeyPress);
+
+ /* If sticky keys were disabled, clear all locks and latches */
+ if ((old.enabled_ctrls&XkbStickyKeysMask)&&
+ (!(ctrls->enabled_ctrls&XkbStickyKeysMask))) {
+ XkbClearAllLatchesAndLocks(kbd,xkbi,False,&cause);
+ }
+ sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
+ XkbUpdateIndicators(kbd,sli->usesControls,True,NULL,&cause);
+ if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask))
+ XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_ON,change);
+ }
+ }
+ else if (filter->keycode==keycode) {
+ change= filter->priv;
+ if (change) {
+ xkbControlsNotify cn;
+ XkbSrvLedInfoPtr sli;
+
+ ctrls->enabled_ctrls&= ~change;
+ if (XkbComputeControlsNotify(kbd,&old,ctrls,&cn,False)) {
+ cn.keycode = keycode;
+ cn.eventType = KeyRelease;
+ cn.requestMajor = 0;
+ cn.requestMinor = 0;
+ XkbSendControlsNotify(kbd,&cn);
+ }
+
+ XkbSetCauseKey(&cause,keycode,KeyRelease);
+ /* If sticky keys were disabled, clear all locks and latches */
+ if ((old.enabled_ctrls&XkbStickyKeysMask)&&
+ (!(ctrls->enabled_ctrls&XkbStickyKeysMask))) {
+ XkbClearAllLatchesAndLocks(kbd,xkbi,False,&cause);
+ }
+ sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
+ XkbUpdateIndicators(kbd,sli->usesControls,True,NULL,&cause);
+ if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask))
+ XkbDDXAccessXBeep(kbd,_BEEP_FEATURE_OFF,change);
+ }
+ filter->keycode= 0;
+ filter->active= 0;
+ }
+ return 1;
+}
+
+static int
+_XkbFilterActionMessage(XkbSrvInfoPtr xkbi,
+ XkbFilterPtr filter,
+ unsigned keycode,
+ XkbAction * pAction)
+{
+XkbMessageAction * pMsg;
+DeviceIntPtr kbd;
+
+ kbd= xkbi->device;
+ if (filter->keycode==0) { /* initial press */
+ pMsg= &pAction->msg;
+ if ((pMsg->flags&XkbSA_MessageOnRelease)||
+ ((pMsg->flags&XkbSA_MessageGenKeyEvent)==0)) {
+ filter->keycode = keycode;
+ filter->active = 1;
+ filter->filterOthers = 0;
+ filter->priv = 0;
+ filter->filter = _XkbFilterActionMessage;
+ filter->upAction = *pAction;
+ }
+ if (pMsg->flags&XkbSA_MessageOnPress) {
+ xkbActionMessage msg;
+
+ msg.keycode= keycode;
+ msg.press= 1;
+ msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0);
+ memcpy((char *)msg.message,
+ (char *)pMsg->message,XkbActionMessageLength);
+ XkbSendActionMessage(kbd,&msg);
+ }
+ return ((pAction->msg.flags&XkbSA_MessageGenKeyEvent)!=0);
+ }
+ else if (filter->keycode==keycode) {
+ pMsg= &filter->upAction.msg;
+ if (pMsg->flags&XkbSA_MessageOnRelease) {
+ xkbActionMessage msg;
+
+ msg.keycode= keycode;
+ msg.press= 0;
+ msg.keyEventFollows=((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0);
+ memcpy((char *)msg.message,(char *)pMsg->message,
+ XkbActionMessageLength);
+ XkbSendActionMessage(kbd,&msg);
+ }
+ filter->keycode= 0;
+ filter->active= 0;
+ return ((pMsg->flags&XkbSA_MessageGenKeyEvent)!=0);
+ }
+ return 0;
+}
+
+static int
+_XkbFilterRedirectKey( XkbSrvInfoPtr xkbi,
+ XkbFilterPtr filter,
+ unsigned keycode,
+ XkbAction * pAction)
+{
+DeviceEvent ev;
+int x,y;
+XkbStateRec old;
+unsigned mods,mask;
+xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device);
+ProcessInputProc backupproc;
+
+ /* never actually used uninitialised, but gcc isn't smart enough
+ * to work that out. */
+ memset(&old, 0, sizeof(old));
+
+ if ((filter->keycode!=0)&&(filter->keycode!=keycode))
+ return 1;
+
+ GetSpritePosition(xkbi->device, &x,&y);
+ ev.header = ET_Internal;
+ ev.length = sizeof(DeviceEvent);
+ ev.time = GetTimeInMillis();
+ ev.root_x = x;
+ ev.root_y = y;
+
+ if (filter->keycode==0) { /* initial press */
+ if ((pAction->redirect.new_key<xkbi->desc->min_key_code)||
+ (pAction->redirect.new_key>xkbi->desc->max_key_code)) {
+ return 1;
+ }
+ filter->keycode = keycode;
+ filter->active = 1;
+ filter->filterOthers = 0;
+ filter->priv = 0;
+ filter->filter = _XkbFilterRedirectKey;
+ filter->upAction = *pAction;
+
+ ev.type = ET_KeyPress;
+ ev.detail.key = pAction->redirect.new_key;
+
+ mask= XkbSARedirectVModsMask(&pAction->redirect);
+ mods= XkbSARedirectVMods(&pAction->redirect);
+ if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask);
+ if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods);
+ mask|= pAction->redirect.mods_mask;
+ mods|= pAction->redirect.mods;
+
+ if ( mask || mods ) {
+ old= xkbi->state;
+ xkbi->state.base_mods&= ~mask;
+ xkbi->state.base_mods|= (mods&mask);
+ xkbi->state.latched_mods&= ~mask;
+ xkbi->state.latched_mods|= (mods&mask);
+ xkbi->state.locked_mods&= ~mask;
+ xkbi->state.locked_mods|= (mods&mask);
+ XkbComputeDerivedState(xkbi);
+ }
+
+ UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
+ xkbi->device->public.processInputProc((InternalEvent*)&ev, xkbi->device);
+ COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
+ backupproc,xkbUnwrapProc);
+
+ if ( mask || mods )
+ xkbi->state= old;
+ }
+ else if (filter->keycode==keycode) {
+
+ ev.type = ET_KeyRelease;
+ ev.detail.key = filter->upAction.redirect.new_key;
+
+ mask= XkbSARedirectVModsMask(&filter->upAction.redirect);
+ mods= XkbSARedirectVMods(&filter->upAction.redirect);
+ if (mask) XkbVirtualModsToReal(xkbi->desc,mask,&mask);
+ if (mods) XkbVirtualModsToReal(xkbi->desc,mods,&mods);
+ mask|= filter->upAction.redirect.mods_mask;
+ mods|= filter->upAction.redirect.mods;
+
+ if ( mask || mods ) {
+ old= xkbi->state;
+ xkbi->state.base_mods&= ~mask;
+ xkbi->state.base_mods|= (mods&mask);
+ xkbi->state.latched_mods&= ~mask;
+ xkbi->state.latched_mods|= (mods&mask);
+ xkbi->state.locked_mods&= ~mask;
+ xkbi->state.locked_mods|= (mods&mask);
+ XkbComputeDerivedState(xkbi);
+ }
+
+ UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
+ xkbi->device->public.processInputProc((InternalEvent*)&ev, xkbi->device);
+ COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
+ backupproc,xkbUnwrapProc);
+
+ if ( mask || mods )
+ xkbi->state= old;
+
+ filter->keycode= 0;
+ filter->active= 0;
+ }
+ return 0;
+}
+
+static int
+_XkbFilterSwitchScreen( XkbSrvInfoPtr xkbi,
+ XkbFilterPtr filter,
+ unsigned keycode,
+ XkbAction * pAction)
+{
+ DeviceIntPtr dev = xkbi->device;
+ if (dev == inputInfo.keyboard)
+ return 0;
+
+ if (filter->keycode==0) { /* initial press */
+ filter->keycode = keycode;
+ filter->active = 1;
+ filter->filterOthers = 0;
+ filter->filter = _XkbFilterSwitchScreen;
+ AccessXCancelRepeatKey(xkbi, keycode);
+ XkbDDXSwitchScreen(dev,keycode,pAction);
+ return 0;
+ }
+ else if (filter->keycode==keycode) {
+ filter->active= 0;
+ return 0;
+ }
+ return 1;
+}
+
+static int
+_XkbFilterXF86Private( XkbSrvInfoPtr xkbi,
+ XkbFilterPtr filter,
+ unsigned keycode,
+ XkbAction * pAction)
+{
+ DeviceIntPtr dev = xkbi->device;
+ if (dev == inputInfo.keyboard)
+ return 0;
+
+ if (filter->keycode==0) { /* initial press */
+ filter->keycode = keycode;
+ filter->active = 1;
+ filter->filterOthers = 0;
+ filter->filter = _XkbFilterXF86Private;
+ XkbDDXPrivate(dev,keycode,pAction);
+ return 0;
+ }
+ else if (filter->keycode==keycode) {
+ filter->active= 0;
+ return 0;
+ }
+ return 1;
+}
+
+
+static int
+_XkbFilterDeviceBtn( XkbSrvInfoPtr xkbi,
+ XkbFilterPtr filter,
+ unsigned keycode,
+ XkbAction * pAction)
+{
+DeviceIntPtr dev;
+int button;
+
+ if (filter->keycode==0) { /* initial press */
+ _XkbLookupButtonDevice(&dev, pAction->devbtn.device, serverClient,
+ DixUnknownAccess, &button);
+ if (!dev || !dev->public.on)
+ return 1;
+
+ if (xkbi->device == inputInfo.keyboard)
+ return 0;
+
+ button= pAction->devbtn.button;
+ if ((button<1)||(button>dev->button->numButtons))
+ return 1;
+
+ filter->keycode = keycode;
+ filter->active = 1;
+ filter->filterOthers = 0;
+ filter->priv=0;
+ filter->filter = _XkbFilterDeviceBtn;
+ filter->upAction= *pAction;
+ switch (pAction->type) {
+ case XkbSA_LockDeviceBtn:
+ if ((pAction->devbtn.flags&XkbSA_LockNoLock)||
+ BitIsOn(dev->button->down, button))
+ return 0;
+ XkbDDXFakeDeviceButton(dev,True,button);
+ filter->upAction.type= XkbSA_NoAction;
+ break;
+ case XkbSA_DeviceBtn:
+ if (pAction->devbtn.count>0) {
+ int nClicks,i;
+ nClicks= pAction->btn.count;
+ for (i=0;i<nClicks;i++) {
+ XkbDDXFakeDeviceButton(dev,True,button);
+ XkbDDXFakeDeviceButton(dev,False,button);
+ }
+ filter->upAction.type= XkbSA_NoAction;
+ }
+ else XkbDDXFakeDeviceButton(dev,True,button);
+ break;
+ }
+ }
+ else if (filter->keycode==keycode) {
+ int button;
+
+ filter->active= 0;
+ _XkbLookupButtonDevice(&dev, filter->upAction.devbtn.device,
+ serverClient, DixUnknownAccess, &button);
+ if (!dev || !dev->public.on)
+ return 1;
+
+ button= filter->upAction.btn.button;
+ switch (filter->upAction.type) {
+ case XkbSA_LockDeviceBtn:
+ if ((filter->upAction.devbtn.flags&XkbSA_LockNoUnlock)||
+ !BitIsOn(dev->button->down, button))
+ return 0;
+ XkbDDXFakeDeviceButton(dev,False,button);
+ break;
+ case XkbSA_DeviceBtn:
+ XkbDDXFakeDeviceButton(dev,False,button);
+ break;
+ }
+ filter->active = 0;
+ }
+ return 0;
+}
+
+static XkbFilterPtr
+_XkbNextFreeFilter(
+ XkbSrvInfoPtr xkbi
+)
+{
+register int i;
+
+ if (xkbi->szFilters==0) {
+ xkbi->szFilters = 4;
+ xkbi->filters = _XkbTypedCalloc(xkbi->szFilters,XkbFilterRec);
+ /* 6/21/93 (ef) -- XXX! deal with allocation failure */
+ }
+ for (i=0;i<xkbi->szFilters;i++) {
+ if (!xkbi->filters[i].active) {
+ xkbi->filters[i].keycode = 0;
+ return &xkbi->filters[i];
+ }
+ }
+ xkbi->szFilters*=2;
+ xkbi->filters= _XkbTypedRealloc(xkbi->filters,
+ xkbi->szFilters,
+ XkbFilterRec);
+ /* 6/21/93 (ef) -- XXX! deal with allocation failure */
+ bzero(&xkbi->filters[xkbi->szFilters/2],
+ (xkbi->szFilters/2)*sizeof(XkbFilterRec));
+ return &xkbi->filters[xkbi->szFilters/2];
+}
+
+static int
+_XkbApplyFilters(XkbSrvInfoPtr xkbi,unsigned kc,XkbAction *pAction)
+{
+register int i,send;
+
+ send= 1;
+ for (i=0;i<xkbi->szFilters;i++) {
+ if ((xkbi->filters[i].active)&&(xkbi->filters[i].filter))
+ send= ((*xkbi->filters[i].filter)(xkbi,&xkbi->filters[i],kc,pAction)
+ && send);
+ }
+ return send;
+}
+
+void
+XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent* event)
+{
+int key,bit,i;
+XkbSrvInfoPtr xkbi;
+KeyClassPtr keyc;
+int changed,sendEvent;
+Bool genStateNotify;
+XkbAction act;
+XkbFilterPtr filter;
+Bool keyEvent;
+Bool pressEvent;
+ProcessInputProc backupproc;
+
+xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
+
+ keyc= kbd->key;
+ xkbi= keyc->xkbInfo;
+ key= event->detail.key;
+ /* The state may change, so if we're not in the middle of sending a state
+ * notify, prepare for it */
+ if ((xkbi->flags&_XkbStateNotifyInProgress)==0) {
+ xkbi->prev_state = xkbi->state;
+ xkbi->flags|= _XkbStateNotifyInProgress;
+ genStateNotify= True;
+ }
+ else genStateNotify= False;
+
+ xkbi->clearMods = xkbi->setMods = 0;
+ xkbi->groupChange = 0;
+
+ sendEvent = 1;
+ keyEvent= ((event->type == ET_KeyPress) || (event->type == ET_KeyRelease));
+ pressEvent= ((event->type == ET_KeyPress)|| (event->type == ET_ButtonPress));
+
+ if (pressEvent) {
+ if (keyEvent)
+ act = XkbGetKeyAction(xkbi,&xkbi->state,key);
+ else {
+ act = XkbGetButtonAction(kbd,dev,key);
+ key|= BTN_ACT_FLAG;
+ }
+ sendEvent = _XkbApplyFilters(xkbi,key,&act);
+ if (sendEvent) {
+ switch (act.type) {
+ case XkbSA_SetMods:
+ case XkbSA_SetGroup:
+ filter = _XkbNextFreeFilter(xkbi);
+ sendEvent = _XkbFilterSetState(xkbi,filter,key,&act);
+ break;
+ case XkbSA_LatchMods:
+ case XkbSA_LatchGroup:
+ filter = _XkbNextFreeFilter(xkbi);
+ sendEvent=_XkbFilterLatchState(xkbi,filter,key,&act);
+ break;
+ case XkbSA_LockMods:
+ case XkbSA_LockGroup:
+ filter = _XkbNextFreeFilter(xkbi);
+ sendEvent=_XkbFilterLockState(xkbi,filter,key,&act);
+ break;
+ case XkbSA_ISOLock:
+ filter = _XkbNextFreeFilter(xkbi);
+ sendEvent=_XkbFilterISOLock(xkbi,filter,key,&act);
+ break;
+ case XkbSA_MovePtr:
+ filter = _XkbNextFreeFilter(xkbi);
+ sendEvent= _XkbFilterPointerMove(xkbi,filter,key,&act);
+ break;
+ case XkbSA_PtrBtn:
+ case XkbSA_LockPtrBtn:
+ case XkbSA_SetPtrDflt:
+ filter = _XkbNextFreeFilter(xkbi);
+ sendEvent= _XkbFilterPointerBtn(xkbi,filter,key,&act);
+ break;
+ case XkbSA_Terminate:
+ sendEvent= XkbDDXTerminateServer(dev,key,&act);
+ break;
+ case XkbSA_SwitchScreen:
+ filter = _XkbNextFreeFilter(xkbi);
+ sendEvent=_XkbFilterSwitchScreen(xkbi,filter,key,&act);
+ break;
+ case XkbSA_SetControls:
+ case XkbSA_LockControls:
+ filter = _XkbNextFreeFilter(xkbi);
+ sendEvent=_XkbFilterControls(xkbi,filter,key,&act);
+ break;
+ case XkbSA_ActionMessage:
+ filter = _XkbNextFreeFilter(xkbi);
+ sendEvent=_XkbFilterActionMessage(xkbi,filter,key,&act);
+ break;
+ case XkbSA_RedirectKey:
+ filter = _XkbNextFreeFilter(xkbi);
+ sendEvent= _XkbFilterRedirectKey(xkbi,filter,key,&act);
+ break;
+ case XkbSA_DeviceBtn:
+ case XkbSA_LockDeviceBtn:
+ filter = _XkbNextFreeFilter(xkbi);
+ sendEvent= _XkbFilterDeviceBtn(xkbi,filter,key,&act);
+ break;
+ case XkbSA_XFree86Private:
+ filter = _XkbNextFreeFilter(xkbi);
+ sendEvent= _XkbFilterXF86Private(xkbi,filter,key,&act);
+ break;
+ }
+ }
+ }
+ else {
+ if (!keyEvent)
+ key|= BTN_ACT_FLAG;
+ sendEvent = _XkbApplyFilters(xkbi,key,NULL);
+ }
+
+ if (xkbi->groupChange!=0)
+ xkbi->state.base_group+= xkbi->groupChange;
+ if (xkbi->setMods) {
+ for (i=0,bit=1; xkbi->setMods; i++,bit<<=1 ) {
+ if (xkbi->setMods&bit) {
+ keyc->modifierKeyCount[i]++;
+ xkbi->state.base_mods|= bit;
+ xkbi->setMods&= ~bit;
+ }
+ }
+ }
+ if (xkbi->clearMods) {
+ for (i=0,bit=1; xkbi->clearMods; i++,bit<<=1 ) {
+ if (xkbi->clearMods&bit) {
+ keyc->modifierKeyCount[i]--;
+ if (keyc->modifierKeyCount[i]<=0) {
+ xkbi->state.base_mods&= ~bit;
+ keyc->modifierKeyCount[i] = 0;
+ }
+ xkbi->clearMods&= ~bit;
+ }
+ }
+ }
+
+ if (sendEvent) {
+ DeviceIntPtr tmpdev;
+ if (keyEvent)
+ tmpdev = dev;
+ else
+ tmpdev = GetPairedDevice(dev);
+
+ UNWRAP_PROCESS_INPUT_PROC(tmpdev,xkbPrivPtr, backupproc);
+ dev->public.processInputProc((InternalEvent*)event, tmpdev);
+ COND_WRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr,
+ backupproc,xkbUnwrapProc);
+ }
+ else if (keyEvent) {
+ FixKeyState(event, dev);
+ }
+
+ XkbComputeDerivedState(xkbi);
+ changed = XkbStateChangedFlags(&xkbi->prev_state,&xkbi->state);
+ if (genStateNotify) {
+ if (changed) {
+ xkbStateNotify sn;
+ sn.keycode= key;
+ sn.eventType= event->type;
+ sn.requestMajor = sn.requestMinor = 0;
+ sn.changed= changed;
+ XkbSendStateNotify(dev,&sn);
+ }
+ xkbi->flags&= ~_XkbStateNotifyInProgress;
+ }
+ changed= XkbIndicatorsToUpdate(dev,changed,False);
+ if (changed) {
+ XkbEventCauseRec cause;
+ XkbSetCauseKey(&cause, key, event->type);
+ XkbUpdateIndicators(dev,changed,False,NULL,&cause);
+ }
+ return;
+}
+
+int
+XkbLatchModifiers(DeviceIntPtr pXDev,CARD8 mask,CARD8 latches)
+{
+XkbSrvInfoPtr xkbi;
+XkbFilterPtr filter;
+XkbAction act;
+unsigned clear;
+
+ if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) {
+ xkbi = pXDev->key->xkbInfo;
+ clear= (mask&(~latches));
+ xkbi->state.latched_mods&= ~clear;
+ /* Clear any pending latch to locks.
+ */
+ act.type = XkbSA_NoAction;
+ _XkbApplyFilters(xkbi,SYNTHETIC_KEYCODE,&act);
+ act.type = XkbSA_LatchMods;
+ act.mods.flags = 0;
+ act.mods.mask = mask&latches;
+ filter = _XkbNextFreeFilter(xkbi);
+ _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act);
+ _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL);
+ return Success;
+ }
+ return BadValue;
+}
+
+int
+XkbLatchGroup(DeviceIntPtr pXDev,int group)
+{
+XkbSrvInfoPtr xkbi;
+XkbFilterPtr filter;
+XkbAction act;
+
+ if ( pXDev && pXDev->key && pXDev->key->xkbInfo ) {
+ xkbi = pXDev->key->xkbInfo;
+ act.type = XkbSA_LatchGroup;
+ act.group.flags = 0;
+ XkbSASetGroup(&act.group,group);
+ filter = _XkbNextFreeFilter(xkbi);
+ _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,&act);
+ _XkbFilterLatchState(xkbi,filter,SYNTHETIC_KEYCODE,(XkbAction *)NULL);
+ return Success;
+ }
+ return BadValue;
+}
+
+/***====================================================================***/
+
+void
+XkbClearAllLatchesAndLocks( DeviceIntPtr dev,
+ XkbSrvInfoPtr xkbi,
+ Bool genEv,
+ XkbEventCausePtr cause)
+{
+XkbStateRec os;
+xkbStateNotify sn;
+
+ sn.changed= 0;
+ os= xkbi->state;
+ if (os.latched_mods) { /* clear all latches */
+ XkbLatchModifiers(dev,~0,0);
+ sn.changed|= XkbModifierLatchMask;
+ }
+ if (os.latched_group) {
+ XkbLatchGroup(dev,0);
+ sn.changed|= XkbGroupLatchMask;
+ }
+ if (os.locked_mods) {
+ xkbi->state.locked_mods= 0;
+ sn.changed|= XkbModifierLockMask;
+ }
+ if (os.locked_group) {
+ xkbi->state.locked_group= 0;
+ sn.changed|= XkbGroupLockMask;
+ }
+ if ( genEv && sn.changed) {
+ CARD32 changed;
+
+ XkbComputeDerivedState(xkbi);
+ sn.keycode= cause->kc;
+ sn.eventType= cause->event;
+ sn.requestMajor= cause->mjr;
+ sn.requestMinor= cause->mnr;
+ sn.changed= XkbStateChangedFlags(&os,&xkbi->state);
+ XkbSendStateNotify(dev,&sn);
+ changed= XkbIndicatorsToUpdate(dev,sn.changed,False);
+ if (changed) {
+ XkbUpdateIndicators(dev,changed,True,NULL,cause);
+ }
+ }
+ return;
+}
+