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 7c6f0bed6..12fe2a1f5 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 */ + + + + |