1/************************************************************ 2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 3 4Permission to use, copy, modify, and distribute this 5software and its documentation for any purpose and without 6fee is hereby granted, provided that the above copyright 7notice appear in all copies and that both that copyright 8notice and this permission notice appear in supporting 9documentation, and that the name of Silicon Graphics not be 10used in advertising or publicity pertaining to distribution 11of the software without specific prior written permission. 12Silicon Graphics makes no representation about the suitability 13of this software for any purpose. It is provided "as is" 14without any express or implied warranty. 15 16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 25********************************************************/ 26 27#ifdef HAVE_DIX_CONFIG_H 28#include <dix-config.h> 29#endif 30 31#include <stdio.h> 32#include <math.h> 33#include <X11/X.h> 34#include <X11/Xproto.h> 35#include <X11/keysym.h> 36#include "exglobals.h" 37#include <X11/extensions/XIproto.h> 38#include "inputstr.h" 39#include "eventstr.h" 40#include <xkbsrv.h> 41#if !defined(WIN32) 42#include <sys/time.h> 43#endif 44 45int XkbDfltRepeatDelay= 660; 46int XkbDfltRepeatInterval= 40; 47 48#define DFLT_TIMEOUT_CTRLS (XkbAX_KRGMask|XkbStickyKeysMask|XkbMouseKeysMask) 49#define DFLT_TIMEOUT_OPTS (XkbAX_IndicatorFBMask) 50 51unsigned short XkbDfltAccessXTimeout= 120; 52unsigned int XkbDfltAccessXTimeoutMask= DFLT_TIMEOUT_CTRLS; 53static unsigned int XkbDfltAccessXTimeoutValues= 0; 54static unsigned int XkbDfltAccessXTimeoutOptionsMask= DFLT_TIMEOUT_OPTS; 55static unsigned int XkbDfltAccessXTimeoutOptionsValues= 0; 56unsigned int XkbDfltAccessXFeedback= XkbAccessXFeedbackMask; 57unsigned short XkbDfltAccessXOptions= XkbAX_AllOptionsMask & ~(XkbAX_IndicatorFBMask|XkbAX_SKReleaseFBMask|XkbAX_SKRejectFBMask); 58 59void 60AccessXComputeCurveFactor(XkbSrvInfoPtr xkbi,XkbControlsPtr ctrls) 61{ 62 xkbi->mouseKeysCurve= 1.0+(((double)ctrls->mk_curve)*0.001); 63 xkbi->mouseKeysCurveFactor= ( ((double)ctrls->mk_max_speed)/ 64 pow((double)ctrls->mk_time_to_max,xkbi->mouseKeysCurve)); 65 return; 66} 67 68void 69AccessXInit(DeviceIntPtr keybd) 70{ 71XkbSrvInfoPtr xkbi = keybd->key->xkbInfo; 72XkbControlsPtr ctrls = xkbi->desc->ctrls; 73 74 xkbi->shiftKeyCount= 0; 75 xkbi->mouseKeysCounter= 0; 76 xkbi->inactiveKey= 0; 77 xkbi->slowKey= 0; 78 xkbi->repeatKey= 0; 79 xkbi->krgTimerActive= _OFF_TIMER; 80 xkbi->beepType= _BEEP_NONE; 81 xkbi->beepCount= 0; 82 xkbi->mouseKeyTimer= NULL; 83 xkbi->slowKeysTimer= NULL; 84 xkbi->bounceKeysTimer= NULL; 85 xkbi->repeatKeyTimer= NULL; 86 xkbi->krgTimer= NULL; 87 xkbi->beepTimer= NULL; 88 ctrls->repeat_delay = XkbDfltRepeatDelay; 89 ctrls->repeat_interval = XkbDfltRepeatInterval; 90 ctrls->debounce_delay = 300; 91 ctrls->slow_keys_delay = 300; 92 ctrls->mk_delay = 160; 93 ctrls->mk_interval = 40; 94 ctrls->mk_time_to_max = 30; 95 ctrls->mk_max_speed = 30; 96 ctrls->mk_curve = 500; 97 ctrls->mk_dflt_btn = 1; 98 ctrls->ax_timeout = XkbDfltAccessXTimeout; 99 ctrls->axt_ctrls_mask = XkbDfltAccessXTimeoutMask; 100 ctrls->axt_ctrls_values = XkbDfltAccessXTimeoutValues; 101 ctrls->axt_opts_mask = XkbDfltAccessXTimeoutOptionsMask; 102 ctrls->axt_opts_values = XkbDfltAccessXTimeoutOptionsValues; 103 if (XkbDfltAccessXTimeout) 104 ctrls->enabled_ctrls |= XkbAccessXTimeoutMask; 105 else 106 ctrls->enabled_ctrls &= ~XkbAccessXTimeoutMask; 107 ctrls->enabled_ctrls |= XkbDfltAccessXFeedback; 108 ctrls->ax_options = XkbDfltAccessXOptions; 109 AccessXComputeCurveFactor(xkbi,ctrls); 110 return; 111} 112 113/************************************************************************/ 114/* */ 115/* AccessXKeyboardEvent */ 116/* */ 117/* Generate a synthetic keyboard event. */ 118/* */ 119/************************************************************************/ 120static void 121AccessXKeyboardEvent(DeviceIntPtr keybd, 122 int type, 123 BYTE keyCode, 124 Bool isRepeat) 125{ 126 DeviceEvent event; 127 memset(&event, 0, sizeof(DeviceEvent)); 128 event.header = ET_Internal; 129 event.type = type; 130 event.detail.key = keyCode; 131 event.time = GetTimeInMillis(); 132 event.length = sizeof(DeviceEvent); 133 event.key_repeat = isRepeat; 134 event.sourceid = keybd->id; 135 event.deviceid = keybd->id; 136 137 if (xkbDebugFlags&0x8) { 138 DebugF("[xkb] AXKE: Key %d %s\n", keyCode, 139 (event.type == ET_KeyPress ? "down" : "up")); 140 } 141 142 XkbProcessKeyboardEvent(&event, keybd); 143 return; 144} /* AccessXKeyboardEvent */ 145 146/************************************************************************/ 147/* */ 148/* AccessXKRGTurnOn */ 149/* */ 150/* Turn the keyboard response group on. */ 151/* */ 152/************************************************************************/ 153static void 154AccessXKRGTurnOn(DeviceIntPtr dev,CARD16 KRGControl,xkbControlsNotify *pCN) 155{ 156XkbSrvInfoPtr xkbi = dev->key->xkbInfo; 157XkbControlsPtr ctrls = xkbi->desc->ctrls; 158XkbControlsRec old; 159XkbEventCauseRec cause; 160XkbSrvLedInfoPtr sli; 161 162 old= *ctrls; 163 ctrls->enabled_ctrls |= (KRGControl&XkbAX_KRGMask); 164 if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE)) 165 XkbSendControlsNotify(dev,pCN); 166 cause.kc= pCN->keycode; 167 cause.event= pCN->eventType; 168 cause.mjr= pCN->requestMajor; 169 cause.mnr= pCN->requestMinor; 170 sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); 171 XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause); 172 if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) 173 XkbDDXAccessXBeep(dev,_BEEP_FEATURE_ON,KRGControl); 174 return; 175 176} /* AccessXKRGTurnOn */ 177 178/************************************************************************/ 179/* */ 180/* AccessXKRGTurnOff */ 181/* */ 182/* Turn the keyboard response group off. */ 183/* */ 184/************************************************************************/ 185static void 186AccessXKRGTurnOff(DeviceIntPtr dev,xkbControlsNotify *pCN) 187{ 188XkbSrvInfoPtr xkbi = dev->key->xkbInfo; 189XkbControlsPtr ctrls = xkbi->desc->ctrls; 190XkbControlsRec old; 191XkbEventCauseRec cause; 192XkbSrvLedInfoPtr sli; 193 194 old = *ctrls; 195 ctrls->enabled_ctrls &= ~XkbAX_KRGMask; 196 if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE)) 197 XkbSendControlsNotify(dev,pCN); 198 cause.kc= pCN->keycode; 199 cause.event= pCN->eventType; 200 cause.mjr= pCN->requestMajor; 201 cause.mnr= pCN->requestMinor; 202 sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); 203 XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause); 204 if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) { 205 unsigned changes= old.enabled_ctrls^ctrls->enabled_ctrls; 206 XkbDDXAccessXBeep(dev,_BEEP_FEATURE_OFF,changes); 207 } 208 return; 209 210} /* AccessXKRGTurnOff */ 211 212/************************************************************************/ 213/* */ 214/* AccessXStickyKeysTurnOn */ 215/* */ 216/* Turn StickyKeys on. */ 217/* */ 218/************************************************************************/ 219static void 220AccessXStickyKeysTurnOn(DeviceIntPtr dev,xkbControlsNotify *pCN) 221{ 222XkbSrvInfoPtr xkbi = dev->key->xkbInfo; 223XkbControlsPtr ctrls = xkbi->desc->ctrls; 224XkbControlsRec old; 225XkbEventCauseRec cause; 226XkbSrvLedInfoPtr sli; 227 228 old = *ctrls; 229 ctrls->enabled_ctrls |= XkbStickyKeysMask; 230 xkbi->shiftKeyCount = 0; 231 if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE)) 232 XkbSendControlsNotify(dev,pCN); 233 cause.kc= pCN->keycode; 234 cause.event= pCN->eventType; 235 cause.mjr= pCN->requestMajor; 236 cause.mnr= pCN->requestMinor; 237 sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); 238 XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause); 239 if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) { 240 XkbDDXAccessXBeep(dev,_BEEP_FEATURE_ON,XkbStickyKeysMask); 241 } 242 return; 243 244} /* AccessXStickyKeysTurnOn */ 245 246/************************************************************************/ 247/* */ 248/* AccessXStickyKeysTurnOff */ 249/* */ 250/* Turn StickyKeys off. */ 251/* */ 252/************************************************************************/ 253static void 254AccessXStickyKeysTurnOff(DeviceIntPtr dev,xkbControlsNotify *pCN) 255{ 256XkbSrvInfoPtr xkbi = dev->key->xkbInfo; 257XkbControlsPtr ctrls = xkbi->desc->ctrls; 258XkbControlsRec old; 259XkbEventCauseRec cause; 260XkbSrvLedInfoPtr sli; 261 262 old = *ctrls; 263 ctrls->enabled_ctrls &= ~XkbStickyKeysMask; 264 xkbi->shiftKeyCount = 0; 265 if (XkbComputeControlsNotify(dev,&old,ctrls,pCN,FALSE)) 266 XkbSendControlsNotify(dev,pCN); 267 268 cause.kc= pCN->keycode; 269 cause.event= pCN->eventType; 270 cause.mjr= pCN->requestMajor; 271 cause.mnr= pCN->requestMinor; 272 sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); 273 XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause); 274 if (XkbAX_NeedFeedback(ctrls,XkbAX_FeatureFBMask)) { 275 XkbDDXAccessXBeep(dev,_BEEP_FEATURE_OFF,XkbStickyKeysMask); 276 } 277#ifndef NO_CLEAR_LATCHES_FOR_STICKY_KEYS_OFF 278 XkbClearAllLatchesAndLocks(dev,xkbi,FALSE,&cause); 279#endif 280 return; 281} /* AccessXStickyKeysTurnOff */ 282 283static CARD32 284AccessXKRGExpire(OsTimerPtr timer,CARD32 now,pointer arg) 285{ 286XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo; 287xkbControlsNotify cn; 288 289 if (xkbi->krgTimerActive==_KRG_WARN_TIMER) { 290 XkbDDXAccessXBeep((DeviceIntPtr)arg,_BEEP_SLOW_WARN,XkbStickyKeysMask); 291 xkbi->krgTimerActive= _KRG_TIMER; 292 return 4000; 293 } 294 xkbi->krgTimerActive= _OFF_TIMER; 295 cn.keycode = 0; 296 cn.eventType = 0; 297 cn.requestMajor = 0; 298 cn.requestMinor = 0; 299 if (xkbi->desc->ctrls->enabled_ctrls&XkbSlowKeysMask) 300 AccessXKRGTurnOff((DeviceIntPtr)arg,&cn); 301 else AccessXKRGTurnOn((DeviceIntPtr)arg,XkbSlowKeysMask,&cn); 302 return 0; 303} 304 305static CARD32 306AccessXRepeatKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg) 307{ 308DeviceIntPtr dev = (DeviceIntPtr) arg; 309XkbSrvInfoPtr xkbi = dev->key->xkbInfo; 310 311 if (xkbi->repeatKey == 0) 312 return 0; 313 314 AccessXKeyboardEvent(dev, ET_KeyPress, xkbi->repeatKey, TRUE); 315 316 return xkbi->desc->ctrls->repeat_interval; 317} 318 319void 320AccessXCancelRepeatKey(XkbSrvInfoPtr xkbi,KeyCode key) 321{ 322 if (xkbi->repeatKey==key) 323 xkbi->repeatKey= 0; 324 return; 325} 326 327static CARD32 328AccessXSlowKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg) 329{ 330DeviceIntPtr keybd; 331XkbSrvInfoPtr xkbi; 332XkbDescPtr xkb; 333XkbControlsPtr ctrls; 334 335 keybd= (DeviceIntPtr)arg; 336 xkbi= keybd->key->xkbInfo; 337 xkb= xkbi->desc; 338 ctrls= xkb->ctrls; 339 if (xkbi->slowKey!=0) { 340 xkbAccessXNotify ev; 341 KeySym *sym= XkbKeySymsPtr(xkb,xkbi->slowKey); 342 ev.detail= XkbAXN_SKAccept; 343 ev.keycode= xkbi->slowKey; 344 ev.slowKeysDelay= ctrls->slow_keys_delay; 345 ev.debounceDelay= ctrls->debounce_delay; 346 XkbSendAccessXNotify(keybd,&ev); 347 if (XkbAX_NeedFeedback(ctrls,XkbAX_SKAcceptFBMask)) 348 XkbDDXAccessXBeep(keybd,_BEEP_SLOW_ACCEPT,XkbSlowKeysMask); 349 AccessXKeyboardEvent(keybd, ET_KeyPress,xkbi->slowKey,FALSE); 350 /* check for magic sequences */ 351 if ((ctrls->enabled_ctrls&XkbAccessXKeysMask) && 352 ((sym[0]==XK_Shift_R)||(sym[0]==XK_Shift_L))) 353 xkbi->shiftKeyCount++; 354 355 /* Start repeating if necessary. Stop autorepeating if the user 356 * presses a non-modifier key that doesn't autorepeat. 357 */ 358 if (keybd->kbdfeed->ctrl.autoRepeat && 359 ((xkbi->slowKey != xkbi->mouseKey) || (!xkbi->mouseKeysAccel)) && 360 (ctrls->enabled_ctrls&XkbRepeatKeysMask)) { 361 if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats,xkbi->slowKey)) { 362 xkbi->repeatKey = xkbi->slowKey; 363 xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer, 364 0, ctrls->repeat_delay, 365 AccessXRepeatKeyExpire, (pointer)keybd); 366 } 367 } 368 } 369 return 0; 370} 371 372static CARD32 373AccessXBounceKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg) 374{ 375XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo; 376 377 xkbi->inactiveKey= 0; 378 return 0; 379} 380 381static CARD32 382AccessXTimeoutExpire(OsTimerPtr timer,CARD32 now,pointer arg) 383{ 384DeviceIntPtr dev = (DeviceIntPtr)arg; 385XkbSrvInfoPtr xkbi= dev->key->xkbInfo; 386XkbControlsPtr ctrls= xkbi->desc->ctrls; 387XkbControlsRec old; 388xkbControlsNotify cn; 389XkbEventCauseRec cause; 390XkbSrvLedInfoPtr sli; 391 392 if (xkbi->lastPtrEventTime) { 393 unsigned timeToWait = (ctrls->ax_timeout*1000); 394 unsigned timeElapsed = (now-xkbi->lastPtrEventTime); 395 396 if (timeToWait > timeElapsed) 397 return timeToWait - timeElapsed; 398 } 399 old= *ctrls; 400 xkbi->shiftKeyCount= 0; 401 ctrls->enabled_ctrls&= ~ctrls->axt_ctrls_mask; 402 ctrls->enabled_ctrls|= 403 (ctrls->axt_ctrls_values&ctrls->axt_ctrls_mask); 404 if (ctrls->axt_opts_mask) { 405 ctrls->ax_options&= ~ctrls->axt_opts_mask; 406 ctrls->ax_options|= (ctrls->axt_opts_values&ctrls->axt_opts_mask); 407 } 408 if (XkbComputeControlsNotify(dev,&old,ctrls,&cn,FALSE)) { 409 cn.keycode = 0; 410 cn.eventType = 0; 411 cn.requestMajor = 0; 412 cn.requestMinor = 0; 413 XkbSendControlsNotify(dev,&cn); 414 } 415 XkbSetCauseUnknown(&cause); 416 sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); 417 XkbUpdateIndicators(dev,sli->usesControls,TRUE,NULL,&cause); 418 if (ctrls->ax_options!=old.ax_options) { 419 unsigned set,cleared,bell; 420 set= ctrls->ax_options&(~old.ax_options); 421 cleared= (~ctrls->ax_options)&old.ax_options; 422 if (set && cleared) bell= _BEEP_FEATURE_CHANGE; 423 else if (set) bell= _BEEP_FEATURE_ON; 424 else bell= _BEEP_FEATURE_OFF; 425 XkbDDXAccessXBeep(dev,bell,XkbAccessXTimeoutMask); 426 } 427 xkbi->krgTimerActive= _OFF_TIMER; 428 return 0; 429} 430 431 432/************************************************************************/ 433/* */ 434/* AccessXFilterPressEvent */ 435/* */ 436/* Filter events before they get any further if SlowKeys is turned on. */ 437/* In addition, this routine handles the ever so popular magic key */ 438/* acts for turning various accessibility features on/off. */ 439/* */ 440/* Returns TRUE if this routine has discarded the event. */ 441/* Returns FALSE if the event needs further processing. */ 442/* */ 443/************************************************************************/ 444Bool 445AccessXFilterPressEvent( DeviceEvent* event, 446 DeviceIntPtr keybd) 447{ 448XkbSrvInfoPtr xkbi = keybd->key->xkbInfo; 449XkbControlsPtr ctrls = xkbi->desc->ctrls; 450Bool ignoreKeyEvent = FALSE; 451KeyCode key = event->detail.key; 452KeySym * sym = XkbKeySymsPtr(xkbi->desc,key); 453 454 if (ctrls->enabled_ctrls&XkbAccessXKeysMask) { 455 /* check for magic sequences */ 456 if ((sym[0]==XK_Shift_R)||(sym[0]==XK_Shift_L)) { 457 if (XkbAX_NeedFeedback(ctrls,XkbAX_SlowWarnFBMask)) { 458 xkbi->krgTimerActive = _KRG_WARN_TIMER; 459 xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 4000, 460 AccessXKRGExpire, (pointer)keybd); 461 } 462 else { 463 xkbi->krgTimerActive = _KRG_TIMER; 464 xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 8000, 465 AccessXKRGExpire, (pointer)keybd); 466 } 467 if (!(ctrls->enabled_ctrls & XkbSlowKeysMask)) { 468 CARD32 now= GetTimeInMillis(); 469 if ((now-xkbi->lastShiftEventTime)>15000) 470 xkbi->shiftKeyCount= 1; 471 else xkbi->shiftKeyCount++; 472 xkbi->lastShiftEventTime= now; 473 } 474 } 475 else { 476 if (xkbi->krgTimerActive) { 477 xkbi->krgTimer= TimerSet(xkbi->krgTimer,0, 0, NULL, NULL); 478 xkbi->krgTimerActive= _OFF_TIMER; 479 } 480 } 481 } 482 483 /* Don't transmit the KeyPress if SlowKeys is turned on; 484 * The wakeup handler will synthesize one for us if the user 485 * has held the key long enough. 486 */ 487 if (ctrls->enabled_ctrls & XkbSlowKeysMask) { 488 xkbAccessXNotify ev; 489 /* If key was already pressed, ignore subsequent press events 490 * from the server's autorepeat 491 */ 492 if(xkbi->slowKey == key) 493 return TRUE; 494 ev.detail= XkbAXN_SKPress; 495 ev.keycode= key; 496 ev.slowKeysDelay= ctrls->slow_keys_delay; 497 ev.debounceDelay= ctrls->debounce_delay; 498 XkbSendAccessXNotify(keybd,&ev); 499 if (XkbAX_NeedFeedback(ctrls,XkbAX_SKPressFBMask)) 500 XkbDDXAccessXBeep(keybd,_BEEP_SLOW_PRESS,XkbSlowKeysMask); 501 xkbi->slowKey= key; 502 xkbi->slowKeysTimer = TimerSet(xkbi->slowKeysTimer, 503 0, ctrls->slow_keys_delay, 504 AccessXSlowKeyExpire, (pointer)keybd); 505 ignoreKeyEvent = TRUE; 506 } 507 508 /* Don't transmit the KeyPress if BounceKeys is turned on 509 * and the user pressed the same key within a given time period 510 * from the last release. 511 */ 512 else if ((ctrls->enabled_ctrls & XkbBounceKeysMask) && 513 (key == xkbi->inactiveKey)) { 514 if (XkbAX_NeedFeedback(ctrls,XkbAX_BKRejectFBMask)) 515 XkbDDXAccessXBeep(keybd,_BEEP_BOUNCE_REJECT,XkbBounceKeysMask); 516 ignoreKeyEvent = TRUE; 517 } 518 519 /* Start repeating if necessary. Stop autorepeating if the user 520 * presses a non-modifier key that doesn't autorepeat. 521 */ 522 if (XkbDDXUsesSoftRepeat(keybd)) { 523 if ((keybd->kbdfeed->ctrl.autoRepeat) && 524 ((ctrls->enabled_ctrls&(XkbSlowKeysMask|XkbRepeatKeysMask))== 525 XkbRepeatKeysMask)) { 526 if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats,key)) { 527 if (xkbDebugFlags&0x10) 528 DebugF("Starting software autorepeat...\n"); 529 if (xkbi->repeatKey == key) 530 ignoreKeyEvent = TRUE; 531 else { 532 xkbi->repeatKey = key; 533 xkbi->repeatKeyTimer= TimerSet(xkbi->repeatKeyTimer, 534 0, ctrls->repeat_delay, 535 AccessXRepeatKeyExpire, (pointer)keybd); 536 } 537 } 538 } 539 } 540 541 /* Check for two keys being pressed at the same time. This section 542 * essentially says the following: 543 * 544 * If StickyKeys is on, and a modifier is currently being held down, 545 * and one of the following is true: the current key is not a modifier 546 * or the currentKey is a modifier, but not the only modifier being 547 * held down, turn StickyKeys off if the TwoKeys off ctrl is set. 548 */ 549 if ((ctrls->enabled_ctrls & XkbStickyKeysMask) && 550 (xkbi->state.base_mods!=0) && 551 (XkbAX_NeedOption(ctrls,XkbAX_TwoKeysMask))) { 552 xkbControlsNotify cn; 553 cn.keycode = key; 554 cn.eventType = KeyPress; 555 cn.requestMajor = 0; 556 cn.requestMinor = 0; 557 AccessXStickyKeysTurnOff(keybd,&cn); 558 } 559 560 if (!ignoreKeyEvent) 561 XkbProcessKeyboardEvent(event, keybd); 562 return ignoreKeyEvent; 563} /* AccessXFilterPressEvent */ 564 565/************************************************************************/ 566/* */ 567/* AccessXFilterReleaseEvent */ 568/* */ 569/* Filter events before they get any further if SlowKeys is turned on. */ 570/* In addition, this routine handles the ever so popular magic key */ 571/* acts for turning various accessibility features on/off. */ 572/* */ 573/* Returns TRUE if this routine has discarded the event. */ 574/* Returns FALSE if the event needs further processing. */ 575/* */ 576/************************************************************************/ 577Bool 578AccessXFilterReleaseEvent( DeviceEvent* event, 579 DeviceIntPtr keybd) 580{ 581XkbSrvInfoPtr xkbi = keybd->key->xkbInfo; 582XkbControlsPtr ctrls = xkbi->desc->ctrls; 583KeyCode key = event->detail.key; 584Bool ignoreKeyEvent = FALSE; 585 586 /* Don't transmit the KeyRelease if BounceKeys is on and 587 * this is the release of a key that was ignored due to 588 * BounceKeys. 589 */ 590 if (ctrls->enabled_ctrls & XkbBounceKeysMask) { 591 if ((key!=xkbi->mouseKey)&&(!BitIsOn(keybd->key->down,key))) 592 ignoreKeyEvent = TRUE; 593 xkbi->inactiveKey= key; 594 xkbi->bounceKeysTimer= TimerSet(xkbi->bounceKeysTimer, 0, 595 ctrls->debounce_delay, 596 AccessXBounceKeyExpire, (pointer)keybd); 597 } 598 599 /* Don't transmit the KeyRelease if SlowKeys is turned on and 600 * the user didn't hold the key long enough. We know we passed 601 * the key if the down bit was set by CoreProcessKeyboadEvent. 602 */ 603 if (ctrls->enabled_ctrls & XkbSlowKeysMask) { 604 xkbAccessXNotify ev; 605 unsigned beep_type; 606 ev.keycode= key; 607 ev.slowKeysDelay= ctrls->slow_keys_delay; 608 ev.debounceDelay= ctrls->debounce_delay; 609 if (BitIsOn(keybd->key->down,key) || (xkbi->mouseKey == key)) { 610 ev.detail= XkbAXN_SKRelease; 611 beep_type= _BEEP_SLOW_RELEASE; 612 } 613 else { 614 ev.detail= XkbAXN_SKReject; 615 beep_type= _BEEP_SLOW_REJECT; 616 ignoreKeyEvent = TRUE; 617 } 618 XkbSendAccessXNotify(keybd,&ev); 619 if (XkbAX_NeedFeedback(ctrls,XkbAX_SKRejectFBMask)) { 620 XkbDDXAccessXBeep(keybd,beep_type,XkbSlowKeysMask); 621 } 622 if (xkbi->slowKey==key) 623 xkbi->slowKey= 0; 624 } 625 626 /* Stop Repeating if the user releases the key that is currently 627 * repeating. 628 */ 629 if (xkbi->repeatKey==key) { 630 xkbi->repeatKey= 0; 631 } 632 633 if ((ctrls->enabled_ctrls&XkbAccessXTimeoutMask)&&(ctrls->ax_timeout>0)) { 634 xkbi->lastPtrEventTime= 0; 635 xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 636 ctrls->ax_timeout*1000, 637 AccessXTimeoutExpire, (pointer)keybd); 638 xkbi->krgTimerActive= _ALL_TIMEOUT_TIMER; 639 } 640 else if (xkbi->krgTimerActive!=_OFF_TIMER) { 641 xkbi->krgTimer= TimerSet(xkbi->krgTimer, 0, 0, NULL, NULL); 642 xkbi->krgTimerActive= _OFF_TIMER; 643 } 644 645 /* Keep track of how many times the Shift key has been pressed. 646 * If it has been pressed and released 5 times in a row, toggle 647 * the state of StickyKeys. 648 */ 649 if ((!ignoreKeyEvent)&&(xkbi->shiftKeyCount)) { 650 KeySym *pSym= XkbKeySymsPtr(xkbi->desc,key); 651 if ((pSym[0]!=XK_Shift_L)&&(pSym[0]!=XK_Shift_R)) { 652 xkbi->shiftKeyCount= 0; 653 } 654 else if (xkbi->shiftKeyCount>=5) { 655 xkbControlsNotify cn; 656 cn.keycode = key; 657 cn.eventType = KeyPress; 658 cn.requestMajor = 0; 659 cn.requestMinor = 0; 660 if (ctrls->enabled_ctrls & XkbStickyKeysMask) 661 AccessXStickyKeysTurnOff(keybd,&cn); 662 else 663 AccessXStickyKeysTurnOn(keybd,&cn); 664 xkbi->shiftKeyCount= 0; 665 } 666 } 667 668 if (!ignoreKeyEvent) 669 XkbProcessKeyboardEvent(event, keybd); 670 return ignoreKeyEvent; 671 672} /* AccessXFilterReleaseEvent */ 673 674/************************************************************************/ 675/* */ 676/* ProcessPointerEvent */ 677/* */ 678/* This routine merely sets the shiftKeyCount and clears the keyboard */ 679/* response group timer (if necessary) on a mouse event. This is so */ 680/* multiple shifts with just the mouse and shift-drags with the mouse */ 681/* don't accidentally turn on StickyKeys or the Keyboard Response Group.*/ 682/* */ 683/************************************************************************/ 684extern int xkbDevicePrivateIndex; 685extern void xkbUnwrapProc(DeviceIntPtr, DeviceHandleProc, pointer); 686void 687ProcessPointerEvent( InternalEvent *ev, 688 DeviceIntPtr mouse) 689{ 690DeviceIntPtr dev; 691XkbSrvInfoPtr xkbi = NULL; 692unsigned changed = 0; 693ProcessInputProc backupproc; 694xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(mouse); 695DeviceEvent *event = &ev->device_event; 696 697 dev = (IsMaster(mouse) || mouse->u.master) ? GetMaster(mouse, MASTER_KEYBOARD) : mouse; 698 699 if (dev && dev->key) 700 { 701 xkbi = dev->key->xkbInfo; 702 xkbi->shiftKeyCount = 0; 703 xkbi->lastPtrEventTime= event->time; 704 } 705 706 if (event->type == ET_ButtonPress) { 707 changed |= XkbPointerButtonMask; 708 } 709 else if (event->type == ET_ButtonRelease) { 710 if (xkbi) { 711 xkbi->lockedPtrButtons&= ~(1 << (event->detail.key & 0x7)); 712 713 if (IsMaster(dev)) 714 { 715 DeviceIntPtr source; 716 int rc; 717 rc = dixLookupDevice(&source, event->sourceid, serverClient, DixWriteAccess); 718 if (rc != Success) 719 ErrorF("[xkb] bad sourceid '%d' on button release event.\n", event->sourceid); 720 else if (!IsXTestDevice(source, GetMaster(dev, MASTER_POINTER))) 721 XkbFakeDeviceButton(dev, FALSE, event->detail.key); 722 } 723 } 724 725 changed |= XkbPointerButtonMask; 726 } 727 728 UNWRAP_PROCESS_INPUT_PROC(mouse, xkbPrivPtr, backupproc); 729 mouse->public.processInputProc(ev, mouse); 730 COND_WRAP_PROCESS_INPUT_PROC(mouse, xkbPrivPtr, 731 backupproc, xkbUnwrapProc); 732 733 if (!xkbi) 734 return; 735 736 xkbi->state.ptr_buttons = (mouse->button) ? mouse->button->state : 0; 737 738 /* clear any latched modifiers */ 739 if ( xkbi->state.latched_mods && (event->type == ET_ButtonRelease) ) { 740 unsigned changed_leds; 741 XkbStateRec oldState; 742 XkbSrvLedInfoPtr sli; 743 744 sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); 745 oldState= xkbi->state; 746 XkbLatchModifiers(dev,0xFF,0x00); 747 748 XkbComputeDerivedState(xkbi); 749 changed |= XkbStateChangedFlags(&oldState,&xkbi->state); 750 if (changed&sli->usedComponents) { 751 changed_leds= XkbIndicatorsToUpdate(dev,changed,FALSE); 752 if (changed_leds) { 753 XkbEventCauseRec cause; 754 XkbSetCauseKey(&cause,(event->detail.key & 0x7), event->type); 755 XkbUpdateIndicators(dev,changed_leds,TRUE,NULL,&cause); 756 } 757 } 758 } 759 760 if (((xkbi->flags&_XkbStateNotifyInProgress)==0)&&(changed!=0)) { 761 xkbStateNotify sn; 762 sn.keycode= event->detail.key; 763 sn.eventType= event->type; 764 sn.requestMajor = sn.requestMinor = 0; 765 sn.changed= changed; 766 XkbSendStateNotify(dev,&sn); 767 } 768 769} /* ProcessPointerEvent */ 770 771 772 773 774