diff options
Diffstat (limited to 'xorg-server/xkb/xkbAccessX.c')
-rw-r--r-- | xorg-server/xkb/xkbAccessX.c | 1546 |
1 files changed, 773 insertions, 773 deletions
diff --git a/xorg-server/xkb/xkbAccessX.c b/xorg-server/xkb/xkbAccessX.c index 12fe2a1f5..7c6f0bed6 100644 --- a/xorg-server/xkb/xkbAccessX.c +++ b/xorg-server/xkb/xkbAccessX.c @@ -1,773 +1,773 @@ -/************************************************************ -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 "exglobals.h" -#include <X11/extensions/XIproto.h> -#include "inputstr.h" -#include "eventstr.h" -#include <xkbsrv.h> -#if !defined(WIN32) -#include <sys/time.h> -#endif - -int XkbDfltRepeatDelay= 660; -int XkbDfltRepeatInterval= 40; - -#define DFLT_TIMEOUT_CTRLS (XkbAX_KRGMask|XkbStickyKeysMask|XkbMouseKeysMask) -#define DFLT_TIMEOUT_OPTS (XkbAX_IndicatorFBMask) - -unsigned short XkbDfltAccessXTimeout= 120; -unsigned int XkbDfltAccessXTimeoutMask= DFLT_TIMEOUT_CTRLS; -static unsigned int XkbDfltAccessXTimeoutValues= 0; -static unsigned int XkbDfltAccessXTimeoutOptionsMask= DFLT_TIMEOUT_OPTS; -static unsigned int XkbDfltAccessXTimeoutOptionsValues= 0; -unsigned int XkbDfltAccessXFeedback= XkbAccessXFeedbackMask; -unsigned short XkbDfltAccessXOptions= XkbAX_AllOptionsMask & ~(XkbAX_IndicatorFBMask|XkbAX_SKReleaseFBMask|XkbAX_SKRejectFBMask); - -void -AccessXComputeCurveFactor(XkbSrvInfoPtr xkbi,XkbControlsPtr ctrls) -{ - xkbi->mouseKeysCurve= 1.0+(((double)ctrls->mk_curve)*0.001); - xkbi->mouseKeysCurveFactor= ( ((double)ctrls->mk_max_speed)/ - pow((double)ctrls->mk_time_to_max,xkbi->mouseKeysCurve)); - return; -} - -void -AccessXInit(DeviceIntPtr keybd) -{ -XkbSrvInfoPtr xkbi = keybd->key->xkbInfo; -XkbControlsPtr ctrls = xkbi->desc->ctrls; - - xkbi->shiftKeyCount= 0; - xkbi->mouseKeysCounter= 0; - xkbi->inactiveKey= 0; - xkbi->slowKey= 0; - xkbi->repeatKey= 0; - xkbi->krgTimerActive= _OFF_TIMER; - xkbi->beepType= _BEEP_NONE; - xkbi->beepCount= 0; - xkbi->mouseKeyTimer= NULL; - xkbi->slowKeysTimer= NULL; - xkbi->bounceKeysTimer= NULL; - xkbi->repeatKeyTimer= NULL; - xkbi->krgTimer= NULL; - xkbi->beepTimer= NULL; - ctrls->repeat_delay = XkbDfltRepeatDelay; - ctrls->repeat_interval = XkbDfltRepeatInterval; - ctrls->debounce_delay = 300; - ctrls->slow_keys_delay = 300; - ctrls->mk_delay = 160; - ctrls->mk_interval = 40; - ctrls->mk_time_to_max = 30; - ctrls->mk_max_speed = 30; - ctrls->mk_curve = 500; - ctrls->mk_dflt_btn = 1; - ctrls->ax_timeout = XkbDfltAccessXTimeout; - ctrls->axt_ctrls_mask = XkbDfltAccessXTimeoutMask; - ctrls->axt_ctrls_values = XkbDfltAccessXTimeoutValues; - ctrls->axt_opts_mask = XkbDfltAccessXTimeoutOptionsMask; - ctrls->axt_opts_values = XkbDfltAccessXTimeoutOptionsValues; - if (XkbDfltAccessXTimeout) - ctrls->enabled_ctrls |= XkbAccessXTimeoutMask; - else - ctrls->enabled_ctrls &= ~XkbAccessXTimeoutMask; - ctrls->enabled_ctrls |= XkbDfltAccessXFeedback; - ctrls->ax_options = XkbDfltAccessXOptions; - AccessXComputeCurveFactor(xkbi,ctrls); - return; -} - -/************************************************************************/ -/* */ -/* AccessXKeyboardEvent */ -/* */ -/* Generate a synthetic keyboard event. */ -/* */ -/************************************************************************/ -static void -AccessXKeyboardEvent(DeviceIntPtr keybd, - int type, - BYTE keyCode, - Bool isRepeat) -{ - DeviceEvent event; - memset(&event, 0, sizeof(DeviceEvent)); - event.header = ET_Internal; - event.type = type; - event.detail.key = keyCode; - event.time = GetTimeInMillis(); - event.length = sizeof(DeviceEvent); - event.key_repeat = isRepeat; - event.sourceid = keybd->id; - event.deviceid = keybd->id; - - if (xkbDebugFlags&0x8) { - DebugF("[xkb] AXKE: Key %d %s\n", keyCode, - (event.type == ET_KeyPress ? "down" : "up")); - } - - XkbProcessKeyboardEvent(&event, keybd); - return; -} /* AccessXKeyboardEvent */ - -/************************************************************************/ -/* */ -/* AccessXKRGTurnOn */ -/* */ -/* Turn the keyboard response group on. */ -/* */ -/************************************************************************/ -static void -AccessXKRGTurnOn(DeviceIntPtr dev,CARD16 KRGControl,xkbControlsNotify *pCN) -{ -XkbSrvInfoPtr xkbi = dev->key->xkbInfo; -XkbControlsPtr ctrls = xkbi->desc->ctrls; -XkbControlsRec old; -XkbEventCauseRec cause; -XkbSrvLedInfoPtr sli; - - old= *ctrls; - ctrls->enabled_ctrls |= (KRGControl&XkbAX_KRGMask); - if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE)) - XkbSendControlsNotify(dev,pCN); - cause.kc= pCN->keycode; - cause.event= pCN->eventType; - cause.mjr= pCN->requestMajor; - cause.mnr= pCN->requestMinor; - sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); - XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause); - if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) - XkbDDXAccessXBeep(dev,_BEEP_FEATURE_ON,KRGControl); - return; - -} /* AccessXKRGTurnOn */ - -/************************************************************************/ -/* */ -/* AccessXKRGTurnOff */ -/* */ -/* Turn the keyboard response group off. */ -/* */ -/************************************************************************/ -static void -AccessXKRGTurnOff(DeviceIntPtr dev,xkbControlsNotify *pCN) -{ -XkbSrvInfoPtr xkbi = dev->key->xkbInfo; -XkbControlsPtr ctrls = xkbi->desc->ctrls; -XkbControlsRec old; -XkbEventCauseRec cause; -XkbSrvLedInfoPtr sli; - - old = *ctrls; - ctrls->enabled_ctrls &= ~XkbAX_KRGMask; - if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE)) - XkbSendControlsNotify(dev,pCN); - cause.kc= pCN->keycode; - cause.event= pCN->eventType; - cause.mjr= pCN->requestMajor; - cause.mnr= pCN->requestMinor; - sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); - XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause); - if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) { - unsigned changes= old.enabled_ctrls^ctrls->enabled_ctrls; - XkbDDXAccessXBeep(dev,_BEEP_FEATURE_OFF,changes); - } - return; - -} /* AccessXKRGTurnOff */ - -/************************************************************************/ -/* */ -/* AccessXStickyKeysTurnOn */ -/* */ -/* Turn StickyKeys on. */ -/* */ -/************************************************************************/ -static void -AccessXStickyKeysTurnOn(DeviceIntPtr dev,xkbControlsNotify *pCN) -{ -XkbSrvInfoPtr xkbi = dev->key->xkbInfo; -XkbControlsPtr ctrls = xkbi->desc->ctrls; -XkbControlsRec old; -XkbEventCauseRec cause; -XkbSrvLedInfoPtr sli; - - old = *ctrls; - ctrls->enabled_ctrls |= XkbStickyKeysMask; - xkbi->shiftKeyCount = 0; - if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE)) - XkbSendControlsNotify(dev,pCN); - cause.kc= pCN->keycode; - cause.event= pCN->eventType; - cause.mjr= pCN->requestMajor; - cause.mnr= pCN->requestMinor; - sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); - XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause); - if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) { - XkbDDXAccessXBeep(dev,_BEEP_FEATURE_ON,XkbStickyKeysMask); - } - return; - -} /* AccessXStickyKeysTurnOn */ - -/************************************************************************/ -/* */ -/* AccessXStickyKeysTurnOff */ -/* */ -/* Turn StickyKeys off. */ -/* */ -/************************************************************************/ -static void -AccessXStickyKeysTurnOff(DeviceIntPtr dev,xkbControlsNotify *pCN) -{ -XkbSrvInfoPtr xkbi = dev->key->xkbInfo; -XkbControlsPtr ctrls = xkbi->desc->ctrls; -XkbControlsRec old; -XkbEventCauseRec cause; -XkbSrvLedInfoPtr sli; - - old = *ctrls; - ctrls->enabled_ctrls &= ~XkbStickyKeysMask; - xkbi->shiftKeyCount = 0; - if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE)) - XkbSendControlsNotify(dev,pCN); - - cause.kc= pCN->keycode; - cause.event= pCN->eventType; - cause.mjr= pCN->requestMajor; - cause.mnr= pCN->requestMinor; - sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); - XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause); - if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) { - XkbDDXAccessXBeep(dev,_BEEP_FEATURE_OFF,XkbStickyKeysMask); - } -#ifndef NO_CLEAR_LATCHES_FOR_STICKY_KEYS_OFF - XkbClearAllLatchesAndLocks(dev,xkbi,FALSE,&cause); -#endif - return; -} /* AccessXStickyKeysTurnOff */ - -static CARD32 -AccessXKRGExpire(OsTimerPtr timer,CARD32 now,pointer arg) -{ -XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo; -xkbControlsNotify cn; - - if (xkbi->krgTimerActive==_KRG_WARN_TIMER) { - XkbDDXAccessXBeep((DeviceIntPtr)arg,_BEEP_SLOW_WARN,XkbStickyKeysMask); - xkbi->krgTimerActive= _KRG_TIMER; - return 4000; - } - xkbi->krgTimerActive= _OFF_TIMER; - cn.keycode = 0; - cn.eventType = 0; - cn.requestMajor = 0; - cn.requestMinor = 0; - if (xkbi->desc->ctrls->enabled_ctrls&XkbSlowKeysMask) - AccessXKRGTurnOff((DeviceIntPtr)arg,&cn); - else AccessXKRGTurnOn((DeviceIntPtr)arg,XkbSlowKeysMask,&cn); - return 0; -} - -static CARD32 -AccessXRepeatKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg) -{ -DeviceIntPtr dev = (DeviceIntPtr) arg; -XkbSrvInfoPtr xkbi = dev->key->xkbInfo; - - if (xkbi->repeatKey == 0) - return 0; - - AccessXKeyboardEvent(dev, ET_KeyPress, xkbi->repeatKey, TRUE); - - return xkbi->desc->ctrls->repeat_interval; -} - -void -AccessXCancelRepeatKey(XkbSrvInfoPtr xkbi,KeyCode key) -{ - if (xkbi->repeatKey==key) - xkbi->repeatKey= 0; - return; -} - -static CARD32 -AccessXSlowKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg) -{ -DeviceIntPtr keybd; -XkbSrvInfoPtr xkbi; -XkbDescPtr xkb; -XkbControlsPtr ctrls; - - keybd= (DeviceIntPtr)arg; - xkbi= keybd->key->xkbInfo; - xkb= xkbi->desc; - ctrls= xkb->ctrls; - if (xkbi->slowKey!=0) { - xkbAccessXNotify ev; - KeySym *sym= XkbKeySymsPtr(xkb,xkbi->slowKey); - ev.detail= XkbAXN_SKAccept; - ev.keycode= xkbi->slowKey; - ev.slowKeysDelay= ctrls->slow_keys_delay; - ev.debounceDelay= ctrls->debounce_delay; - XkbSendAccessXNotify(keybd,&ev); - if (XkbAX_NeedFeedback(ctrls,XkbAX_SKAcceptFBMask)) - XkbDDXAccessXBeep(keybd,_BEEP_SLOW_ACCEPT,XkbSlowKeysMask); - AccessXKeyboardEvent(keybd, ET_KeyPress,xkbi->slowKey,FALSE); - /* check for magic sequences */ - if ((ctrls->enabled_ctrls&XkbAccessXKeysMask) && - ((sym[0]==XK_Shift_R)||(sym[0]==XK_Shift_L))) - xkbi->shiftKeyCount++; - - /* Start repeating if necessary. Stop autorepeating if the user - * presses a non-modifier key that doesn't autorepeat. - */ - if (keybd->kbdfeed->ctrl.autoRepeat && - ((xkbi->slowKey != xkbi->mouseKey) || (!xkbi->mouseKeysAccel)) && - (ctrls->enabled_ctrls&XkbRepeatKeysMask)) { - if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats,xkbi->slowKey)) { - xkbi->repeatKey = xkbi->slowKey; - xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer, - 0, ctrls->repeat_delay, - AccessXRepeatKeyExpire, (pointer)keybd); - } - } - } - return 0; -} - -static CARD32 -AccessXBounceKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg) -{ -XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo; - - xkbi->inactiveKey= 0; - return 0; -} - -static CARD32 -AccessXTimeoutExpire(OsTimerPtr timer,CARD32 now,pointer arg) -{ -DeviceIntPtr dev = (DeviceIntPtr)arg; -XkbSrvInfoPtr xkbi= dev->key->xkbInfo; -XkbControlsPtr ctrls= xkbi->desc->ctrls; -XkbControlsRec old; -xkbControlsNotify cn; -XkbEventCauseRec cause; -XkbSrvLedInfoPtr sli; - - if (xkbi->lastPtrEventTime) { - unsigned timeToWait = (ctrls->ax_timeout*1000); - unsigned timeElapsed = (now-xkbi->lastPtrEventTime); - - if (timeToWait > timeElapsed) - return timeToWait - timeElapsed; - } - old= *ctrls; - xkbi->shiftKeyCount= 0; - ctrls->enabled_ctrls&= ~ctrls->axt_ctrls_mask; - ctrls->enabled_ctrls|= - (ctrls->axt_ctrls_values&ctrls->axt_ctrls_mask); - if (ctrls->axt_opts_mask) { - ctrls->ax_options&= ~ctrls->axt_opts_mask; - ctrls->ax_options|= (ctrls->axt_opts_values&ctrls->axt_opts_mask); - } - if (XkbComputeControlsNotify(dev,&old,ctrls,&cn,FALSE)) { - cn.keycode = 0; - cn.eventType = 0; - cn.requestMajor = 0; - cn.requestMinor = 0; - XkbSendControlsNotify(dev,&cn); - } - XkbSetCauseUnknown(&cause); - sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); - XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause); - if (ctrls->ax_options!=old.ax_options) { - unsigned set,cleared,bell; - set= ctrls->ax_options&(~old.ax_options); - cleared= (~ctrls->ax_options)&old.ax_options; - if (set && cleared) bell= _BEEP_FEATURE_CHANGE; - else if (set) bell= _BEEP_FEATURE_ON; - else bell= _BEEP_FEATURE_OFF; - XkbDDXAccessXBeep(dev,bell,XkbAccessXTimeoutMask); - } - xkbi->krgTimerActive= _OFF_TIMER; - return 0; -} - - -/************************************************************************/ -/* */ -/* AccessXFilterPressEvent */ -/* */ -/* Filter events before they get any further if SlowKeys is turned on. */ -/* In addition, this routine handles the ever so popular magic key */ -/* acts for turning various accessibility features on/off. */ -/* */ -/* Returns TRUE if this routine has discarded the event. */ -/* Returns FALSE if the event needs further processing. */ -/* */ -/************************************************************************/ -Bool -AccessXFilterPressEvent( DeviceEvent* event, - DeviceIntPtr keybd) -{ -XkbSrvInfoPtr xkbi = keybd->key->xkbInfo; -XkbControlsPtr ctrls = xkbi->desc->ctrls; -Bool ignoreKeyEvent = FALSE; -KeyCode key = event->detail.key; -KeySym * sym = XkbKeySymsPtr(xkbi->desc,key); - - if (ctrls->enabled_ctrls&XkbAccessXKeysMask) { - /* check for magic sequences */ - if ((sym[0]==XK_Shift_R)||(sym[0]==XK_Shift_L)) { - if (XkbAX_NeedFeedback(ctrls,XkbAX_SlowWarnFBMask)) { - xkbi->krgTimerActive = _KRG_WARN_TIMER; - xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 4000, - AccessXKRGExpire, (pointer)keybd); - } - else { - xkbi->krgTimerActive = _KRG_TIMER; - xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 8000, - AccessXKRGExpire, (pointer)keybd); - } - if (!(ctrls->enabled_ctrls & XkbSlowKeysMask)) { - CARD32 now= GetTimeInMillis(); - if ((now-xkbi->lastShiftEventTime)>15000) - xkbi->shiftKeyCount= 1; - else xkbi->shiftKeyCount++; - xkbi->lastShiftEventTime= now; - } - } - else { - if (xkbi->krgTimerActive) { - xkbi->krgTimer= TimerSet(xkbi->krgTimer,0, 0, NULL, NULL); - xkbi->krgTimerActive= _OFF_TIMER; - } - } - } - - /* Don't transmit the KeyPress if SlowKeys is turned on; - * The wakeup handler will synthesize one for us if the user - * has held the key long enough. - */ - if (ctrls->enabled_ctrls & XkbSlowKeysMask) { - xkbAccessXNotify ev; - /* If key was already pressed, ignore subsequent press events - * from the server's autorepeat - */ - if(xkbi->slowKey == key) - return TRUE; - ev.detail= XkbAXN_SKPress; - ev.keycode= key; - ev.slowKeysDelay= ctrls->slow_keys_delay; - ev.debounceDelay= ctrls->debounce_delay; - XkbSendAccessXNotify(keybd,&ev); - if (XkbAX_NeedFeedback(ctrls,XkbAX_SKPressFBMask)) - XkbDDXAccessXBeep(keybd,_BEEP_SLOW_PRESS,XkbSlowKeysMask); - xkbi->slowKey= key; - xkbi->slowKeysTimer = TimerSet(xkbi->slowKeysTimer, - 0, ctrls->slow_keys_delay, - AccessXSlowKeyExpire, (pointer)keybd); - ignoreKeyEvent = TRUE; - } - - /* Don't transmit the KeyPress if BounceKeys is turned on - * and the user pressed the same key within a given time period - * from the last release. - */ - else if ((ctrls->enabled_ctrls & XkbBounceKeysMask) && - (key == xkbi->inactiveKey)) { - if (XkbAX_NeedFeedback(ctrls,XkbAX_BKRejectFBMask)) - XkbDDXAccessXBeep(keybd,_BEEP_BOUNCE_REJECT,XkbBounceKeysMask); - ignoreKeyEvent = TRUE; - } - - /* Start repeating if necessary. Stop autorepeating if the user - * presses a non-modifier key that doesn't autorepeat. - */ - if (XkbDDXUsesSoftRepeat(keybd)) { - if ((keybd->kbdfeed->ctrl.autoRepeat) && - ((ctrls->enabled_ctrls&(XkbSlowKeysMask|XkbRepeatKeysMask))== - XkbRepeatKeysMask)) { - if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats,key)) { - if (xkbDebugFlags&0x10) - DebugF("Starting software autorepeat...\n"); - if (xkbi->repeatKey == key) - ignoreKeyEvent = TRUE; - else { - xkbi->repeatKey = key; - xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer, - 0, ctrls->repeat_delay, - AccessXRepeatKeyExpire, (pointer)keybd); - } - } - } - } - - /* Check for two keys being pressed at the same time. This section - * essentially says the following: - * - * If StickyKeys is on, and a modifier is currently being held down, - * and one of the following is true: the current key is not a modifier - * or the currentKey is a modifier, but not the only modifier being - * held down, turn StickyKeys off if the TwoKeys off ctrl is set. - */ - if ((ctrls->enabled_ctrls & XkbStickyKeysMask) && - (xkbi->state.base_mods!=0) && - (XkbAX_NeedOption(ctrls,XkbAX_TwoKeysMask))) { - xkbControlsNotify cn; - cn.keycode = key; - cn.eventType = KeyPress; - cn.requestMajor = 0; - cn.requestMinor = 0; - AccessXStickyKeysTurnOff(keybd,&cn); - } - - if (!ignoreKeyEvent) - XkbProcessKeyboardEvent(event, keybd); - return ignoreKeyEvent; -} /* AccessXFilterPressEvent */ - -/************************************************************************/ -/* */ -/* AccessXFilterReleaseEvent */ -/* */ -/* Filter events before they get any further if SlowKeys is turned on. */ -/* In addition, this routine handles the ever so popular magic key */ -/* acts for turning various accessibility features on/off. */ -/* */ -/* Returns TRUE if this routine has discarded the event. */ -/* Returns FALSE if the event needs further processing. */ -/* */ -/************************************************************************/ -Bool -AccessXFilterReleaseEvent( DeviceEvent* event, - DeviceIntPtr keybd) -{ -XkbSrvInfoPtr xkbi = keybd->key->xkbInfo; -XkbControlsPtr ctrls = xkbi->desc->ctrls; -KeyCode key = event->detail.key; -Bool ignoreKeyEvent = FALSE; - - /* Don't transmit the KeyRelease if BounceKeys is on and - * this is the release of a key that was ignored due to - * BounceKeys. - */ - if (ctrls->enabled_ctrls & XkbBounceKeysMask) { - if ((key!=xkbi->mouseKey)&&(!BitIsOn(keybd->key->down,key))) - ignoreKeyEvent = TRUE; - xkbi->inactiveKey= key; - xkbi->bounceKeysTimer= TimerSet(xkbi->bounceKeysTimer, 0, - ctrls->debounce_delay, - AccessXBounceKeyExpire, (pointer)keybd); - } - - /* Don't transmit the KeyRelease if SlowKeys is turned on and - * the user didn't hold the key long enough. We know we passed - * the key if the down bit was set by CoreProcessKeyboadEvent. - */ - if (ctrls->enabled_ctrls & XkbSlowKeysMask) { - xkbAccessXNotify ev; - unsigned beep_type; - ev.keycode= key; - ev.slowKeysDelay= ctrls->slow_keys_delay; - ev.debounceDelay= ctrls->debounce_delay; - if (BitIsOn(keybd->key->down,key) || (xkbi->mouseKey == key)) { - ev.detail= XkbAXN_SKRelease; - beep_type= _BEEP_SLOW_RELEASE; - } - else { - ev.detail= XkbAXN_SKReject; - beep_type= _BEEP_SLOW_REJECT; - ignoreKeyEvent = TRUE; - } - XkbSendAccessXNotify(keybd,&ev); - if (XkbAX_NeedFeedback(ctrls,XkbAX_SKRejectFBMask)) { - XkbDDXAccessXBeep(keybd,beep_type,XkbSlowKeysMask); - } - if (xkbi->slowKey==key) - xkbi->slowKey= 0; - } - - /* Stop Repeating if the user releases the key that is currently - * repeating. - */ - if (xkbi->repeatKey==key) { - xkbi->repeatKey= 0; - } - - if ((ctrls->enabled_ctrls&XkbAccessXTimeoutMask)&&(ctrls->ax_timeout>0)) { - xkbi->lastPtrEventTime= 0; - xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, - ctrls->ax_timeout*1000, - AccessXTimeoutExpire, (pointer)keybd); - xkbi->krgTimerActive= _ALL_TIMEOUT_TIMER; - } - else if (xkbi->krgTimerActive!=_OFF_TIMER) { - xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 0, NULL, NULL); - xkbi->krgTimerActive= _OFF_TIMER; - } - - /* Keep track of how many times the Shift key has been pressed. - * If it has been pressed and released 5 times in a row, toggle - * the state of StickyKeys. - */ - if ((!ignoreKeyEvent)&&(xkbi->shiftKeyCount)) { - KeySym *pSym= XkbKeySymsPtr(xkbi->desc,key); - if ((pSym[0]!=XK_Shift_L)&&(pSym[0]!=XK_Shift_R)) { - xkbi->shiftKeyCount= 0; - } - else if (xkbi->shiftKeyCount>=5) { - xkbControlsNotify cn; - cn.keycode = key; - cn.eventType = KeyPress; - cn.requestMajor = 0; - cn.requestMinor = 0; - if (ctrls->enabled_ctrls & XkbStickyKeysMask) - AccessXStickyKeysTurnOff(keybd,&cn); - else - AccessXStickyKeysTurnOn(keybd,&cn); - xkbi->shiftKeyCount= 0; - } - } - - if (!ignoreKeyEvent) - XkbProcessKeyboardEvent(event, keybd); - return ignoreKeyEvent; - -} /* AccessXFilterReleaseEvent */ - -/************************************************************************/ -/* */ -/* ProcessPointerEvent */ -/* */ -/* This routine merely sets the shiftKeyCount and clears the keyboard */ -/* response group timer (if necessary) on a mouse event. This is so */ -/* multiple shifts with just the mouse and shift-drags with the mouse */ -/* don't accidentally turn on StickyKeys or the Keyboard Response Group.*/ -/* */ -/************************************************************************/ -extern int xkbDevicePrivateIndex; -extern void xkbUnwrapProc(DeviceIntPtr, DeviceHandleProc, pointer); -void -ProcessPointerEvent( InternalEvent *ev, - DeviceIntPtr mouse) -{ -DeviceIntPtr dev; -XkbSrvInfoPtr xkbi = NULL; -unsigned changed = 0; -ProcessInputProc backupproc; -xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(mouse); -DeviceEvent *event = &ev->device_event; - - dev = IsFloating(mouse) ? mouse : GetMaster(mouse, MASTER_KEYBOARD); - - if (dev && dev->key) - { - xkbi = dev->key->xkbInfo; - xkbi->shiftKeyCount = 0; - xkbi->lastPtrEventTime= event->time; - } - - if (event->type == ET_ButtonPress) { - changed |= XkbPointerButtonMask; - } - else if (event->type == ET_ButtonRelease) { - if (xkbi) { - xkbi->lockedPtrButtons&= ~(1 << (event->detail.key & 0x7)); - - if (IsMaster(dev)) - { - DeviceIntPtr source; - int rc; - rc = dixLookupDevice(&source, event->sourceid, serverClient, DixWriteAccess); - if (rc != Success) - ErrorF("[xkb] bad sourceid '%d' on button release event.\n", event->sourceid); - else if (!IsXTestDevice(source, GetMaster(dev, MASTER_POINTER))) - XkbFakeDeviceButton(dev, FALSE, event->detail.key); - } - } - - changed |= XkbPointerButtonMask; - } - - UNWRAP_PROCESS_INPUT_PROC(mouse, xkbPrivPtr, backupproc); - mouse->public.processInputProc(ev, mouse); - COND_WRAP_PROCESS_INPUT_PROC(mouse, xkbPrivPtr, - backupproc, xkbUnwrapProc); - - if (!xkbi) - return; - - xkbi->state.ptr_buttons = (mouse->button) ? mouse->button->state : 0; - - /* clear any latched modifiers */ - if ( xkbi->state.latched_mods && (event->type == ET_ButtonRelease) ) { - unsigned changed_leds; - XkbStateRec oldState; - XkbSrvLedInfoPtr sli; - - sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); - oldState= xkbi->state; - XkbLatchModifiers(dev,0xFF,0x00); - - XkbComputeDerivedState(xkbi); - changed |= XkbStateChangedFlags(&oldState,&xkbi->state); - if (changed&sli->usedComponents) { - changed_leds= XkbIndicatorsToUpdate(dev,changed,FALSE); - if (changed_leds) { - XkbEventCauseRec cause; - XkbSetCauseKey(&cause,(event->detail.key & 0x7), event->type); - XkbUpdateIndicators(dev,changed_leds,TRUE,NULL,&cause); - } - } - } - - if (((xkbi->flags&_XkbStateNotifyInProgress)==0)&&(changed!=0)) { - xkbStateNotify sn; - sn.keycode= event->detail.key; - sn.eventType= event->type; - sn.requestMajor = sn.requestMinor = 0; - sn.changed= changed; - XkbSendStateNotify(dev,&sn); - } - -} /* ProcessPointerEvent */ - - - - +/************************************************************
+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 "exglobals.h"
+#include <X11/extensions/XIproto.h>
+#include "inputstr.h"
+#include "eventstr.h"
+#include <xkbsrv.h>
+#if !defined(WIN32)
+#include <sys/time.h>
+#endif
+
+int XkbDfltRepeatDelay= 660;
+int XkbDfltRepeatInterval= 40;
+
+#define DFLT_TIMEOUT_CTRLS (XkbAX_KRGMask|XkbStickyKeysMask|XkbMouseKeysMask)
+#define DFLT_TIMEOUT_OPTS (XkbAX_IndicatorFBMask)
+
+unsigned short XkbDfltAccessXTimeout= 120;
+unsigned int XkbDfltAccessXTimeoutMask= DFLT_TIMEOUT_CTRLS;
+static unsigned int XkbDfltAccessXTimeoutValues= 0;
+static unsigned int XkbDfltAccessXTimeoutOptionsMask= DFLT_TIMEOUT_OPTS;
+static unsigned int XkbDfltAccessXTimeoutOptionsValues= 0;
+unsigned int XkbDfltAccessXFeedback= XkbAccessXFeedbackMask;
+unsigned short XkbDfltAccessXOptions= XkbAX_AllOptionsMask & ~(XkbAX_IndicatorFBMask|XkbAX_SKReleaseFBMask|XkbAX_SKRejectFBMask);
+
+void
+AccessXComputeCurveFactor(XkbSrvInfoPtr xkbi,XkbControlsPtr ctrls)
+{
+ xkbi->mouseKeysCurve= 1.0+(((double)ctrls->mk_curve)*0.001);
+ xkbi->mouseKeysCurveFactor= ( ((double)ctrls->mk_max_speed)/
+ pow((double)ctrls->mk_time_to_max,xkbi->mouseKeysCurve));
+ return;
+}
+
+void
+AccessXInit(DeviceIntPtr keybd)
+{
+XkbSrvInfoPtr xkbi = keybd->key->xkbInfo;
+XkbControlsPtr ctrls = xkbi->desc->ctrls;
+
+ xkbi->shiftKeyCount= 0;
+ xkbi->mouseKeysCounter= 0;
+ xkbi->inactiveKey= 0;
+ xkbi->slowKey= 0;
+ xkbi->repeatKey= 0;
+ xkbi->krgTimerActive= _OFF_TIMER;
+ xkbi->beepType= _BEEP_NONE;
+ xkbi->beepCount= 0;
+ xkbi->mouseKeyTimer= NULL;
+ xkbi->slowKeysTimer= NULL;
+ xkbi->bounceKeysTimer= NULL;
+ xkbi->repeatKeyTimer= NULL;
+ xkbi->krgTimer= NULL;
+ xkbi->beepTimer= NULL;
+ ctrls->repeat_delay = XkbDfltRepeatDelay;
+ ctrls->repeat_interval = XkbDfltRepeatInterval;
+ ctrls->debounce_delay = 300;
+ ctrls->slow_keys_delay = 300;
+ ctrls->mk_delay = 160;
+ ctrls->mk_interval = 40;
+ ctrls->mk_time_to_max = 30;
+ ctrls->mk_max_speed = 30;
+ ctrls->mk_curve = 500;
+ ctrls->mk_dflt_btn = 1;
+ ctrls->ax_timeout = XkbDfltAccessXTimeout;
+ ctrls->axt_ctrls_mask = XkbDfltAccessXTimeoutMask;
+ ctrls->axt_ctrls_values = XkbDfltAccessXTimeoutValues;
+ ctrls->axt_opts_mask = XkbDfltAccessXTimeoutOptionsMask;
+ ctrls->axt_opts_values = XkbDfltAccessXTimeoutOptionsValues;
+ if (XkbDfltAccessXTimeout)
+ ctrls->enabled_ctrls |= XkbAccessXTimeoutMask;
+ else
+ ctrls->enabled_ctrls &= ~XkbAccessXTimeoutMask;
+ ctrls->enabled_ctrls |= XkbDfltAccessXFeedback;
+ ctrls->ax_options = XkbDfltAccessXOptions;
+ AccessXComputeCurveFactor(xkbi,ctrls);
+ return;
+}
+
+/************************************************************************/
+/* */
+/* AccessXKeyboardEvent */
+/* */
+/* Generate a synthetic keyboard event. */
+/* */
+/************************************************************************/
+static void
+AccessXKeyboardEvent(DeviceIntPtr keybd,
+ int type,
+ BYTE keyCode,
+ Bool isRepeat)
+{
+ DeviceEvent event;
+ memset(&event, 0, sizeof(DeviceEvent));
+ event.header = ET_Internal;
+ event.type = type;
+ event.detail.key = keyCode;
+ event.time = GetTimeInMillis();
+ event.length = sizeof(DeviceEvent);
+ event.key_repeat = isRepeat;
+ event.sourceid = keybd->id;
+ event.deviceid = keybd->id;
+
+ if (xkbDebugFlags&0x8) {
+ DebugF("[xkb] AXKE: Key %d %s\n", keyCode,
+ (event.type == ET_KeyPress ? "down" : "up"));
+ }
+
+ XkbProcessKeyboardEvent(&event, keybd);
+ return;
+} /* AccessXKeyboardEvent */
+
+/************************************************************************/
+/* */
+/* AccessXKRGTurnOn */
+/* */
+/* Turn the keyboard response group on. */
+/* */
+/************************************************************************/
+static void
+AccessXKRGTurnOn(DeviceIntPtr dev,CARD16 KRGControl,xkbControlsNotify *pCN)
+{
+XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
+XkbControlsPtr ctrls = xkbi->desc->ctrls;
+XkbControlsRec old;
+XkbEventCauseRec cause;
+XkbSrvLedInfoPtr sli;
+
+ old= *ctrls;
+ ctrls->enabled_ctrls |= (KRGControl&XkbAX_KRGMask);
+ if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE))
+ XkbSendControlsNotify(dev,pCN);
+ cause.kc= pCN->keycode;
+ cause.event= pCN->eventType;
+ cause.mjr= pCN->requestMajor;
+ cause.mnr= pCN->requestMinor;
+ sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
+ XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause);
+ if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask))
+ XkbDDXAccessXBeep(dev,_BEEP_FEATURE_ON,KRGControl);
+ return;
+
+} /* AccessXKRGTurnOn */
+
+/************************************************************************/
+/* */
+/* AccessXKRGTurnOff */
+/* */
+/* Turn the keyboard response group off. */
+/* */
+/************************************************************************/
+static void
+AccessXKRGTurnOff(DeviceIntPtr dev,xkbControlsNotify *pCN)
+{
+XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
+XkbControlsPtr ctrls = xkbi->desc->ctrls;
+XkbControlsRec old;
+XkbEventCauseRec cause;
+XkbSrvLedInfoPtr sli;
+
+ old = *ctrls;
+ ctrls->enabled_ctrls &= ~XkbAX_KRGMask;
+ if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE))
+ XkbSendControlsNotify(dev,pCN);
+ cause.kc= pCN->keycode;
+ cause.event= pCN->eventType;
+ cause.mjr= pCN->requestMajor;
+ cause.mnr= pCN->requestMinor;
+ sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
+ XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause);
+ if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) {
+ unsigned changes= old.enabled_ctrls^ctrls->enabled_ctrls;
+ XkbDDXAccessXBeep(dev,_BEEP_FEATURE_OFF,changes);
+ }
+ return;
+
+} /* AccessXKRGTurnOff */
+
+/************************************************************************/
+/* */
+/* AccessXStickyKeysTurnOn */
+/* */
+/* Turn StickyKeys on. */
+/* */
+/************************************************************************/
+static void
+AccessXStickyKeysTurnOn(DeviceIntPtr dev,xkbControlsNotify *pCN)
+{
+XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
+XkbControlsPtr ctrls = xkbi->desc->ctrls;
+XkbControlsRec old;
+XkbEventCauseRec cause;
+XkbSrvLedInfoPtr sli;
+
+ old = *ctrls;
+ ctrls->enabled_ctrls |= XkbStickyKeysMask;
+ xkbi->shiftKeyCount = 0;
+ if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE))
+ XkbSendControlsNotify(dev,pCN);
+ cause.kc= pCN->keycode;
+ cause.event= pCN->eventType;
+ cause.mjr= pCN->requestMajor;
+ cause.mnr= pCN->requestMinor;
+ sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
+ XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause);
+ if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) {
+ XkbDDXAccessXBeep(dev,_BEEP_FEATURE_ON,XkbStickyKeysMask);
+ }
+ return;
+
+} /* AccessXStickyKeysTurnOn */
+
+/************************************************************************/
+/* */
+/* AccessXStickyKeysTurnOff */
+/* */
+/* Turn StickyKeys off. */
+/* */
+/************************************************************************/
+static void
+AccessXStickyKeysTurnOff(DeviceIntPtr dev,xkbControlsNotify *pCN)
+{
+XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
+XkbControlsPtr ctrls = xkbi->desc->ctrls;
+XkbControlsRec old;
+XkbEventCauseRec cause;
+XkbSrvLedInfoPtr sli;
+
+ old = *ctrls;
+ ctrls->enabled_ctrls &= ~XkbStickyKeysMask;
+ xkbi->shiftKeyCount = 0;
+ if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE))
+ XkbSendControlsNotify(dev,pCN);
+
+ cause.kc= pCN->keycode;
+ cause.event= pCN->eventType;
+ cause.mjr= pCN->requestMajor;
+ cause.mnr= pCN->requestMinor;
+ sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
+ XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause);
+ if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) {
+ XkbDDXAccessXBeep(dev,_BEEP_FEATURE_OFF,XkbStickyKeysMask);
+ }
+#ifndef NO_CLEAR_LATCHES_FOR_STICKY_KEYS_OFF
+ XkbClearAllLatchesAndLocks(dev,xkbi,FALSE,&cause);
+#endif
+ return;
+} /* AccessXStickyKeysTurnOff */
+
+static CARD32
+AccessXKRGExpire(OsTimerPtr timer,CARD32 now,pointer arg)
+{
+XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo;
+xkbControlsNotify cn;
+
+ if (xkbi->krgTimerActive==_KRG_WARN_TIMER) {
+ XkbDDXAccessXBeep((DeviceIntPtr)arg,_BEEP_SLOW_WARN,XkbStickyKeysMask);
+ xkbi->krgTimerActive= _KRG_TIMER;
+ return 4000;
+ }
+ xkbi->krgTimerActive= _OFF_TIMER;
+ cn.keycode = 0;
+ cn.eventType = 0;
+ cn.requestMajor = 0;
+ cn.requestMinor = 0;
+ if (xkbi->desc->ctrls->enabled_ctrls&XkbSlowKeysMask)
+ AccessXKRGTurnOff((DeviceIntPtr)arg,&cn);
+ else AccessXKRGTurnOn((DeviceIntPtr)arg,XkbSlowKeysMask,&cn);
+ return 0;
+}
+
+static CARD32
+AccessXRepeatKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg)
+{
+DeviceIntPtr dev = (DeviceIntPtr) arg;
+XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
+
+ if (xkbi->repeatKey == 0)
+ return 0;
+
+ AccessXKeyboardEvent(dev, ET_KeyPress, xkbi->repeatKey, TRUE);
+
+ return xkbi->desc->ctrls->repeat_interval;
+}
+
+void
+AccessXCancelRepeatKey(XkbSrvInfoPtr xkbi,KeyCode key)
+{
+ if (xkbi->repeatKey==key)
+ xkbi->repeatKey= 0;
+ return;
+}
+
+static CARD32
+AccessXSlowKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg)
+{
+DeviceIntPtr keybd;
+XkbSrvInfoPtr xkbi;
+XkbDescPtr xkb;
+XkbControlsPtr ctrls;
+
+ keybd= (DeviceIntPtr)arg;
+ xkbi= keybd->key->xkbInfo;
+ xkb= xkbi->desc;
+ ctrls= xkb->ctrls;
+ if (xkbi->slowKey!=0) {
+ xkbAccessXNotify ev;
+ KeySym *sym= XkbKeySymsPtr(xkb,xkbi->slowKey);
+ ev.detail= XkbAXN_SKAccept;
+ ev.keycode= xkbi->slowKey;
+ ev.slowKeysDelay= ctrls->slow_keys_delay;
+ ev.debounceDelay= ctrls->debounce_delay;
+ XkbSendAccessXNotify(keybd,&ev);
+ if (XkbAX_NeedFeedback(ctrls,XkbAX_SKAcceptFBMask))
+ XkbDDXAccessXBeep(keybd,_BEEP_SLOW_ACCEPT,XkbSlowKeysMask);
+ AccessXKeyboardEvent(keybd, ET_KeyPress,xkbi->slowKey,FALSE);
+ /* check for magic sequences */
+ if ((ctrls->enabled_ctrls&XkbAccessXKeysMask) &&
+ ((sym[0]==XK_Shift_R)||(sym[0]==XK_Shift_L)))
+ xkbi->shiftKeyCount++;
+
+ /* Start repeating if necessary. Stop autorepeating if the user
+ * presses a non-modifier key that doesn't autorepeat.
+ */
+ if (keybd->kbdfeed->ctrl.autoRepeat &&
+ ((xkbi->slowKey != xkbi->mouseKey) || (!xkbi->mouseKeysAccel)) &&
+ (ctrls->enabled_ctrls&XkbRepeatKeysMask)) {
+ if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats,xkbi->slowKey)) {
+ xkbi->repeatKey = xkbi->slowKey;
+ xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer,
+ 0, ctrls->repeat_delay,
+ AccessXRepeatKeyExpire, (pointer)keybd);
+ }
+ }
+ }
+ return 0;
+}
+
+static CARD32
+AccessXBounceKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg)
+{
+XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo;
+
+ xkbi->inactiveKey= 0;
+ return 0;
+}
+
+static CARD32
+AccessXTimeoutExpire(OsTimerPtr timer,CARD32 now,pointer arg)
+{
+DeviceIntPtr dev = (DeviceIntPtr)arg;
+XkbSrvInfoPtr xkbi= dev->key->xkbInfo;
+XkbControlsPtr ctrls= xkbi->desc->ctrls;
+XkbControlsRec old;
+xkbControlsNotify cn;
+XkbEventCauseRec cause;
+XkbSrvLedInfoPtr sli;
+
+ if (xkbi->lastPtrEventTime) {
+ unsigned timeToWait = (ctrls->ax_timeout*1000);
+ unsigned timeElapsed = (now-xkbi->lastPtrEventTime);
+
+ if (timeToWait > timeElapsed)
+ return timeToWait - timeElapsed;
+ }
+ old= *ctrls;
+ xkbi->shiftKeyCount= 0;
+ ctrls->enabled_ctrls&= ~ctrls->axt_ctrls_mask;
+ ctrls->enabled_ctrls|=
+ (ctrls->axt_ctrls_values&ctrls->axt_ctrls_mask);
+ if (ctrls->axt_opts_mask) {
+ ctrls->ax_options&= ~ctrls->axt_opts_mask;
+ ctrls->ax_options|= (ctrls->axt_opts_values&ctrls->axt_opts_mask);
+ }
+ if (XkbComputeControlsNotify(dev,&old,ctrls,&cn,FALSE)) {
+ cn.keycode = 0;
+ cn.eventType = 0;
+ cn.requestMajor = 0;
+ cn.requestMinor = 0;
+ XkbSendControlsNotify(dev,&cn);
+ }
+ XkbSetCauseUnknown(&cause);
+ sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
+ XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause);
+ if (ctrls->ax_options!=old.ax_options) {
+ unsigned set,cleared,bell;
+ set= ctrls->ax_options&(~old.ax_options);
+ cleared= (~ctrls->ax_options)&old.ax_options;
+ if (set && cleared) bell= _BEEP_FEATURE_CHANGE;
+ else if (set) bell= _BEEP_FEATURE_ON;
+ else bell= _BEEP_FEATURE_OFF;
+ XkbDDXAccessXBeep(dev,bell,XkbAccessXTimeoutMask);
+ }
+ xkbi->krgTimerActive= _OFF_TIMER;
+ return 0;
+}
+
+
+/************************************************************************/
+/* */
+/* AccessXFilterPressEvent */
+/* */
+/* Filter events before they get any further if SlowKeys is turned on. */
+/* In addition, this routine handles the ever so popular magic key */
+/* acts for turning various accessibility features on/off. */
+/* */
+/* Returns TRUE if this routine has discarded the event. */
+/* Returns FALSE if the event needs further processing. */
+/* */
+/************************************************************************/
+Bool
+AccessXFilterPressEvent( DeviceEvent* event,
+ DeviceIntPtr keybd)
+{
+XkbSrvInfoPtr xkbi = keybd->key->xkbInfo;
+XkbControlsPtr ctrls = xkbi->desc->ctrls;
+Bool ignoreKeyEvent = FALSE;
+KeyCode key = event->detail.key;
+KeySym * sym = XkbKeySymsPtr(xkbi->desc,key);
+
+ if (ctrls->enabled_ctrls&XkbAccessXKeysMask) {
+ /* check for magic sequences */
+ if ((sym[0]==XK_Shift_R)||(sym[0]==XK_Shift_L)) {
+ if (XkbAX_NeedFeedback(ctrls,XkbAX_SlowWarnFBMask)) {
+ xkbi->krgTimerActive = _KRG_WARN_TIMER;
+ xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 4000,
+ AccessXKRGExpire, (pointer)keybd);
+ }
+ else {
+ xkbi->krgTimerActive = _KRG_TIMER;
+ xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 8000,
+ AccessXKRGExpire, (pointer)keybd);
+ }
+ if (!(ctrls->enabled_ctrls & XkbSlowKeysMask)) {
+ CARD32 now= GetTimeInMillis();
+ if ((now-xkbi->lastShiftEventTime)>15000)
+ xkbi->shiftKeyCount= 1;
+ else xkbi->shiftKeyCount++;
+ xkbi->lastShiftEventTime= now;
+ }
+ }
+ else {
+ if (xkbi->krgTimerActive) {
+ xkbi->krgTimer= TimerSet(xkbi->krgTimer,0, 0, NULL, NULL);
+ xkbi->krgTimerActive= _OFF_TIMER;
+ }
+ }
+ }
+
+ /* Don't transmit the KeyPress if SlowKeys is turned on;
+ * The wakeup handler will synthesize one for us if the user
+ * has held the key long enough.
+ */
+ if (ctrls->enabled_ctrls & XkbSlowKeysMask) {
+ xkbAccessXNotify ev;
+ /* If key was already pressed, ignore subsequent press events
+ * from the server's autorepeat
+ */
+ if(xkbi->slowKey == key)
+ return TRUE;
+ ev.detail= XkbAXN_SKPress;
+ ev.keycode= key;
+ ev.slowKeysDelay= ctrls->slow_keys_delay;
+ ev.debounceDelay= ctrls->debounce_delay;
+ XkbSendAccessXNotify(keybd,&ev);
+ if (XkbAX_NeedFeedback(ctrls,XkbAX_SKPressFBMask))
+ XkbDDXAccessXBeep(keybd,_BEEP_SLOW_PRESS,XkbSlowKeysMask);
+ xkbi->slowKey= key;
+ xkbi->slowKeysTimer = TimerSet(xkbi->slowKeysTimer,
+ 0, ctrls->slow_keys_delay,
+ AccessXSlowKeyExpire, (pointer)keybd);
+ ignoreKeyEvent = TRUE;
+ }
+
+ /* Don't transmit the KeyPress if BounceKeys is turned on
+ * and the user pressed the same key within a given time period
+ * from the last release.
+ */
+ else if ((ctrls->enabled_ctrls & XkbBounceKeysMask) &&
+ (key == xkbi->inactiveKey)) {
+ if (XkbAX_NeedFeedback(ctrls,XkbAX_BKRejectFBMask))
+ XkbDDXAccessXBeep(keybd,_BEEP_BOUNCE_REJECT,XkbBounceKeysMask);
+ ignoreKeyEvent = TRUE;
+ }
+
+ /* Start repeating if necessary. Stop autorepeating if the user
+ * presses a non-modifier key that doesn't autorepeat.
+ */
+ if (XkbDDXUsesSoftRepeat(keybd)) {
+ if ((keybd->kbdfeed->ctrl.autoRepeat) &&
+ ((ctrls->enabled_ctrls&(XkbSlowKeysMask|XkbRepeatKeysMask))==
+ XkbRepeatKeysMask)) {
+ if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats,key)) {
+ if (xkbDebugFlags&0x10)
+ DebugF("Starting software autorepeat...\n");
+ if (xkbi->repeatKey == key)
+ ignoreKeyEvent = TRUE;
+ else {
+ xkbi->repeatKey = key;
+ xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer,
+ 0, ctrls->repeat_delay,
+ AccessXRepeatKeyExpire, (pointer)keybd);
+ }
+ }
+ }
+ }
+
+ /* Check for two keys being pressed at the same time. This section
+ * essentially says the following:
+ *
+ * If StickyKeys is on, and a modifier is currently being held down,
+ * and one of the following is true: the current key is not a modifier
+ * or the currentKey is a modifier, but not the only modifier being
+ * held down, turn StickyKeys off if the TwoKeys off ctrl is set.
+ */
+ if ((ctrls->enabled_ctrls & XkbStickyKeysMask) &&
+ (xkbi->state.base_mods!=0) &&
+ (XkbAX_NeedOption(ctrls,XkbAX_TwoKeysMask))) {
+ xkbControlsNotify cn;
+ cn.keycode = key;
+ cn.eventType = KeyPress;
+ cn.requestMajor = 0;
+ cn.requestMinor = 0;
+ AccessXStickyKeysTurnOff(keybd,&cn);
+ }
+
+ if (!ignoreKeyEvent)
+ XkbProcessKeyboardEvent(event, keybd);
+ return ignoreKeyEvent;
+} /* AccessXFilterPressEvent */
+
+/************************************************************************/
+/* */
+/* AccessXFilterReleaseEvent */
+/* */
+/* Filter events before they get any further if SlowKeys is turned on. */
+/* In addition, this routine handles the ever so popular magic key */
+/* acts for turning various accessibility features on/off. */
+/* */
+/* Returns TRUE if this routine has discarded the event. */
+/* Returns FALSE if the event needs further processing. */
+/* */
+/************************************************************************/
+Bool
+AccessXFilterReleaseEvent( DeviceEvent* event,
+ DeviceIntPtr keybd)
+{
+XkbSrvInfoPtr xkbi = keybd->key->xkbInfo;
+XkbControlsPtr ctrls = xkbi->desc->ctrls;
+KeyCode key = event->detail.key;
+Bool ignoreKeyEvent = FALSE;
+
+ /* Don't transmit the KeyRelease if BounceKeys is on and
+ * this is the release of a key that was ignored due to
+ * BounceKeys.
+ */
+ if (ctrls->enabled_ctrls & XkbBounceKeysMask) {
+ if ((key!=xkbi->mouseKey)&&(!BitIsOn(keybd->key->down,key)))
+ ignoreKeyEvent = TRUE;
+ xkbi->inactiveKey= key;
+ xkbi->bounceKeysTimer= TimerSet(xkbi->bounceKeysTimer, 0,
+ ctrls->debounce_delay,
+ AccessXBounceKeyExpire, (pointer)keybd);
+ }
+
+ /* Don't transmit the KeyRelease if SlowKeys is turned on and
+ * the user didn't hold the key long enough. We know we passed
+ * the key if the down bit was set by CoreProcessKeyboadEvent.
+ */
+ if (ctrls->enabled_ctrls & XkbSlowKeysMask) {
+ xkbAccessXNotify ev;
+ unsigned beep_type;
+ ev.keycode= key;
+ ev.slowKeysDelay= ctrls->slow_keys_delay;
+ ev.debounceDelay= ctrls->debounce_delay;
+ if (BitIsOn(keybd->key->down,key) || (xkbi->mouseKey == key)) {
+ ev.detail= XkbAXN_SKRelease;
+ beep_type= _BEEP_SLOW_RELEASE;
+ }
+ else {
+ ev.detail= XkbAXN_SKReject;
+ beep_type= _BEEP_SLOW_REJECT;
+ ignoreKeyEvent = TRUE;
+ }
+ XkbSendAccessXNotify(keybd,&ev);
+ if (XkbAX_NeedFeedback(ctrls,XkbAX_SKRejectFBMask)) {
+ XkbDDXAccessXBeep(keybd,beep_type,XkbSlowKeysMask);
+ }
+ if (xkbi->slowKey==key)
+ xkbi->slowKey= 0;
+ }
+
+ /* Stop Repeating if the user releases the key that is currently
+ * repeating.
+ */
+ if (xkbi->repeatKey==key) {
+ xkbi->repeatKey= 0;
+ }
+
+ if ((ctrls->enabled_ctrls&XkbAccessXTimeoutMask)&&(ctrls->ax_timeout>0)) {
+ xkbi->lastPtrEventTime= 0;
+ xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0,
+ ctrls->ax_timeout*1000,
+ AccessXTimeoutExpire, (pointer)keybd);
+ xkbi->krgTimerActive= _ALL_TIMEOUT_TIMER;
+ }
+ else if (xkbi->krgTimerActive!=_OFF_TIMER) {
+ xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 0, NULL, NULL);
+ xkbi->krgTimerActive= _OFF_TIMER;
+ }
+
+ /* Keep track of how many times the Shift key has been pressed.
+ * If it has been pressed and released 5 times in a row, toggle
+ * the state of StickyKeys.
+ */
+ if ((!ignoreKeyEvent)&&(xkbi->shiftKeyCount)) {
+ KeySym *pSym= XkbKeySymsPtr(xkbi->desc,key);
+ if ((pSym[0]!=XK_Shift_L)&&(pSym[0]!=XK_Shift_R)) {
+ xkbi->shiftKeyCount= 0;
+ }
+ else if (xkbi->shiftKeyCount>=5) {
+ xkbControlsNotify cn;
+ cn.keycode = key;
+ cn.eventType = KeyPress;
+ cn.requestMajor = 0;
+ cn.requestMinor = 0;
+ if (ctrls->enabled_ctrls & XkbStickyKeysMask)
+ AccessXStickyKeysTurnOff(keybd,&cn);
+ else
+ AccessXStickyKeysTurnOn(keybd,&cn);
+ xkbi->shiftKeyCount= 0;
+ }
+ }
+
+ if (!ignoreKeyEvent)
+ XkbProcessKeyboardEvent(event, keybd);
+ return ignoreKeyEvent;
+
+} /* AccessXFilterReleaseEvent */
+
+/************************************************************************/
+/* */
+/* ProcessPointerEvent */
+/* */
+/* This routine merely sets the shiftKeyCount and clears the keyboard */
+/* response group timer (if necessary) on a mouse event. This is so */
+/* multiple shifts with just the mouse and shift-drags with the mouse */
+/* don't accidentally turn on StickyKeys or the Keyboard Response Group.*/
+/* */
+/************************************************************************/
+extern int xkbDevicePrivateIndex;
+extern void xkbUnwrapProc(DeviceIntPtr, DeviceHandleProc, pointer);
+void
+ProcessPointerEvent( InternalEvent *ev,
+ DeviceIntPtr mouse)
+{
+DeviceIntPtr dev;
+XkbSrvInfoPtr xkbi = NULL;
+unsigned changed = 0;
+ProcessInputProc backupproc;
+xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(mouse);
+DeviceEvent *event = &ev->device_event;
+
+ dev = IsFloating(mouse) ? mouse : GetMaster(mouse, MASTER_KEYBOARD);
+
+ if (dev && dev->key)
+ {
+ xkbi = dev->key->xkbInfo;
+ xkbi->shiftKeyCount = 0;
+ xkbi->lastPtrEventTime= event->time;
+ }
+
+ if (event->type == ET_ButtonPress) {
+ changed |= XkbPointerButtonMask;
+ }
+ else if (event->type == ET_ButtonRelease) {
+ if (xkbi) {
+ xkbi->lockedPtrButtons&= ~(1 << (event->detail.key & 0x7));
+
+ if (IsMaster(dev))
+ {
+ DeviceIntPtr source;
+ int rc;
+ rc = dixLookupDevice(&source, event->sourceid, serverClient, DixWriteAccess);
+ if (rc != Success)
+ ErrorF("[xkb] bad sourceid '%d' on button release event.\n", event->sourceid);
+ else if (!IsXTestDevice(source, GetMaster(dev, MASTER_POINTER)))
+ XkbFakeDeviceButton(dev, FALSE, event->detail.key);
+ }
+ }
+
+ changed |= XkbPointerButtonMask;
+ }
+
+ UNWRAP_PROCESS_INPUT_PROC(mouse, xkbPrivPtr, backupproc);
+ mouse->public.processInputProc(ev, mouse);
+ COND_WRAP_PROCESS_INPUT_PROC(mouse, xkbPrivPtr,
+ backupproc, xkbUnwrapProc);
+
+ if (!xkbi)
+ return;
+
+ xkbi->state.ptr_buttons = (mouse->button) ? mouse->button->state : 0;
+
+ /* clear any latched modifiers */
+ if ( xkbi->state.latched_mods && (event->type == ET_ButtonRelease) ) {
+ unsigned changed_leds;
+ XkbStateRec oldState;
+ XkbSrvLedInfoPtr sli;
+
+ sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
+ oldState= xkbi->state;
+ XkbLatchModifiers(dev,0xFF,0x00);
+
+ XkbComputeDerivedState(xkbi);
+ changed |= XkbStateChangedFlags(&oldState,&xkbi->state);
+ if (changed&sli->usedComponents) {
+ changed_leds= XkbIndicatorsToUpdate(dev,changed,FALSE);
+ if (changed_leds) {
+ XkbEventCauseRec cause;
+ XkbSetCauseKey(&cause,(event->detail.key & 0x7), event->type);
+ XkbUpdateIndicators(dev,changed_leds,TRUE,NULL,&cause);
+ }
+ }
+ }
+
+ if (((xkbi->flags&_XkbStateNotifyInProgress)==0)&&(changed!=0)) {
+ xkbStateNotify sn;
+ sn.keycode= event->detail.key;
+ sn.eventType= event->type;
+ sn.requestMajor = sn.requestMinor = 0;
+ sn.changed= changed;
+ XkbSendStateNotify(dev,&sn);
+ }
+
+} /* ProcessPointerEvent */
+
+
+
+
|