1 /************************************************************
2 Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 ********************************************************/
27 #ifdef HAVE_DIX_CONFIG_H
28 #include <dix-config.h>
38 #include <X11/Xproto.h>
39 #include <X11/keysym.h>
42 #if !defined(WIN32) && !defined(Lynx)
46 _X_EXPORT
int XkbDfltRepeatDelay
= 660;
47 _X_EXPORT
int XkbDfltRepeatInterval
= 40;
48 pointer XkbLastRepeatEvent
= NULL
;
50 #define DFLT_TIMEOUT_CTRLS (XkbAX_KRGMask|XkbStickyKeysMask|XkbMouseKeysMask)
51 #define DFLT_TIMEOUT_OPTS (XkbAX_IndicatorFBMask)
53 unsigned short XkbDfltAccessXTimeout
= 120;
54 unsigned int XkbDfltAccessXTimeoutMask
= DFLT_TIMEOUT_CTRLS
;
55 static unsigned int XkbDfltAccessXTimeoutValues
= 0;
56 static unsigned int XkbDfltAccessXTimeoutOptionsMask
= DFLT_TIMEOUT_OPTS
;
57 static unsigned int XkbDfltAccessXTimeoutOptionsValues
= 0;
58 unsigned int XkbDfltAccessXFeedback
= XkbAccessXFeedbackMask
;
59 unsigned short XkbDfltAccessXOptions
= XkbAX_AllOptionsMask
& ~(XkbAX_IndicatorFBMask
|XkbAX_SKReleaseFBMask
|XkbAX_SKRejectFBMask
);
62 AccessXComputeCurveFactor(XkbSrvInfoPtr xkbi
,XkbControlsPtr ctrls
)
64 xkbi
->mouseKeysCurve
= 1.0+(((double)ctrls
->mk_curve
)*0.001);
65 xkbi
->mouseKeysCurveFactor
= ( ((double)ctrls
->mk_max_speed
)/
66 pow((double)ctrls
->mk_time_to_max
,xkbi
->mouseKeysCurve
));
71 AccessXInit(DeviceIntPtr keybd
)
73 XkbSrvInfoPtr xkbi
= keybd
->key
->xkbInfo
;
74 XkbControlsPtr ctrls
= xkbi
->desc
->ctrls
;
76 xkbi
->shiftKeyCount
= 0;
77 xkbi
->mouseKeysCounter
= 0;
81 xkbi
->krgTimerActive
= _OFF_TIMER
;
82 xkbi
->beepType
= _BEEP_NONE
;
84 xkbi
->mouseKeyTimer
= NULL
;
85 xkbi
->slowKeysTimer
= NULL
;
86 xkbi
->bounceKeysTimer
= NULL
;
87 xkbi
->repeatKeyTimer
= NULL
;
89 xkbi
->beepTimer
= NULL
;
90 ctrls
->repeat_delay
= XkbDfltRepeatDelay
;
91 ctrls
->repeat_interval
= XkbDfltRepeatInterval
;
92 ctrls
->debounce_delay
= 300;
93 ctrls
->slow_keys_delay
= 300;
94 ctrls
->mk_delay
= 160;
95 ctrls
->mk_interval
= 40;
96 ctrls
->mk_time_to_max
= 30;
97 ctrls
->mk_max_speed
= 30;
98 ctrls
->mk_curve
= 500;
99 ctrls
->mk_dflt_btn
= 1;
100 ctrls
->ax_timeout
= XkbDfltAccessXTimeout
;
101 ctrls
->axt_ctrls_mask
= XkbDfltAccessXTimeoutMask
;
102 ctrls
->axt_ctrls_values
= XkbDfltAccessXTimeoutValues
;
103 ctrls
->axt_opts_mask
= XkbDfltAccessXTimeoutOptionsMask
;
104 ctrls
->axt_opts_values
= XkbDfltAccessXTimeoutOptionsValues
;
105 if (XkbDfltAccessXTimeout
)
106 ctrls
->enabled_ctrls
|= XkbAccessXTimeoutMask
;
108 ctrls
->enabled_ctrls
&= ~XkbAccessXTimeoutMask
;
109 ctrls
->enabled_ctrls
|= XkbDfltAccessXFeedback
;
110 ctrls
->ax_options
= XkbDfltAccessXOptions
;
111 AccessXComputeCurveFactor(xkbi
,ctrls
);
115 /************************************************************************/
117 /* AccessXKeyboardEvent */
119 /* Generate a synthetic keyboard event. */
121 /************************************************************************/
123 AccessXKeyboardEvent(DeviceIntPtr keybd
,
131 xE
.u
.u
.detail
= keyCode
;
132 xE
.u
.keyButtonPointer
.time
= GetTimeInMillis();
134 if (xkbDebugFlags
&0x8) {
135 ErrorF("AXKE: Key %d %s\n",keyCode
,(xE
.u
.u
.type
==KeyPress
?"down":"up"));
139 if (_XkbIsPressEvent(type
))
140 XkbDDXKeyClick(keybd
,keyCode
,TRUE
);
142 XkbLastRepeatEvent
= (pointer
)&xE
;
143 XkbProcessKeyboardEvent(&xE
,keybd
,1L);
144 XkbLastRepeatEvent
= NULL
;
147 } /* AccessXKeyboardEvent */
149 /************************************************************************/
151 /* AccessXKRGTurnOn */
153 /* Turn the keyboard response group on. */
155 /************************************************************************/
157 AccessXKRGTurnOn(DeviceIntPtr dev
,CARD16 KRGControl
,xkbControlsNotify
*pCN
)
159 XkbSrvInfoPtr xkbi
= dev
->key
->xkbInfo
;
160 XkbControlsPtr ctrls
= xkbi
->desc
->ctrls
;
162 XkbEventCauseRec cause
;
163 XkbSrvLedInfoPtr sli
;
166 ctrls
->enabled_ctrls
|= (KRGControl
&XkbAX_KRGMask
);
167 if (XkbComputeControlsNotify(dev
,&old
,ctrls
,pCN
,False
))
168 XkbSendControlsNotify(dev
,pCN
);
169 cause
.kc
= pCN
->keycode
;
170 cause
.event
= pCN
->eventType
;
171 cause
.mjr
= pCN
->requestMajor
;
172 cause
.mnr
= pCN
->requestMinor
;
173 sli
= XkbFindSrvLedInfo(dev
,XkbDfltXIClass
,XkbDfltXIId
,0);
174 XkbUpdateIndicators(dev
,sli
->usesControls
,True
,NULL
,&cause
);
175 if (XkbAX_NeedFeedback(ctrls
,XkbAX_FeatureFBMask
))
176 XkbDDXAccessXBeep(dev
,_BEEP_FEATURE_ON
,KRGControl
);
179 } /* AccessXKRGTurnOn */
181 /************************************************************************/
183 /* AccessXKRGTurnOff */
185 /* Turn the keyboard response group off. */
187 /************************************************************************/
189 AccessXKRGTurnOff(DeviceIntPtr dev
,xkbControlsNotify
*pCN
)
191 XkbSrvInfoPtr xkbi
= dev
->key
->xkbInfo
;
192 XkbControlsPtr ctrls
= xkbi
->desc
->ctrls
;
194 XkbEventCauseRec cause
;
195 XkbSrvLedInfoPtr sli
;
198 ctrls
->enabled_ctrls
&= ~XkbAX_KRGMask
;
199 if (XkbComputeControlsNotify(dev
,&old
,ctrls
,pCN
,False
))
200 XkbSendControlsNotify(dev
,pCN
);
201 cause
.kc
= pCN
->keycode
;
202 cause
.event
= pCN
->eventType
;
203 cause
.mjr
= pCN
->requestMajor
;
204 cause
.mnr
= pCN
->requestMinor
;
205 sli
= XkbFindSrvLedInfo(dev
,XkbDfltXIClass
,XkbDfltXIId
,0);
206 XkbUpdateIndicators(dev
,sli
->usesControls
,True
,NULL
,&cause
);
207 if (XkbAX_NeedFeedback(ctrls
,XkbAX_FeatureFBMask
)) {
208 unsigned changes
= old
.enabled_ctrls
^ctrls
->enabled_ctrls
;
209 XkbDDXAccessXBeep(dev
,_BEEP_FEATURE_OFF
,changes
);
213 } /* AccessXKRGTurnOff */
215 /************************************************************************/
217 /* AccessXStickyKeysTurnOn */
219 /* Turn StickyKeys on. */
221 /************************************************************************/
223 AccessXStickyKeysTurnOn(DeviceIntPtr dev
,xkbControlsNotify
*pCN
)
225 XkbSrvInfoPtr xkbi
= dev
->key
->xkbInfo
;
226 XkbControlsPtr ctrls
= xkbi
->desc
->ctrls
;
228 XkbEventCauseRec cause
;
229 XkbSrvLedInfoPtr sli
;
232 ctrls
->enabled_ctrls
|= XkbStickyKeysMask
;
233 xkbi
->shiftKeyCount
= 0;
234 if (XkbComputeControlsNotify(dev
,&old
,ctrls
,pCN
,False
))
235 XkbSendControlsNotify(dev
,pCN
);
236 cause
.kc
= pCN
->keycode
;
237 cause
.event
= pCN
->eventType
;
238 cause
.mjr
= pCN
->requestMajor
;
239 cause
.mnr
= pCN
->requestMinor
;
240 sli
= XkbFindSrvLedInfo(dev
,XkbDfltXIClass
,XkbDfltXIId
,0);
241 XkbUpdateIndicators(dev
,sli
->usesControls
,True
,NULL
,&cause
);
242 if (XkbAX_NeedFeedback(ctrls
,XkbAX_FeatureFBMask
)) {
243 XkbDDXAccessXBeep(dev
,_BEEP_FEATURE_ON
,XkbStickyKeysMask
);
247 } /* AccessXStickyKeysTurnOn */
249 /************************************************************************/
251 /* AccessXStickyKeysTurnOff */
253 /* Turn StickyKeys off. */
255 /************************************************************************/
257 AccessXStickyKeysTurnOff(DeviceIntPtr dev
,xkbControlsNotify
*pCN
)
259 XkbSrvInfoPtr xkbi
= dev
->key
->xkbInfo
;
260 XkbControlsPtr ctrls
= xkbi
->desc
->ctrls
;
262 XkbEventCauseRec cause
;
263 XkbSrvLedInfoPtr sli
;
266 ctrls
->enabled_ctrls
&= ~XkbStickyKeysMask
;
267 xkbi
->shiftKeyCount
= 0;
268 if (XkbComputeControlsNotify(dev
,&old
,ctrls
,pCN
,False
))
269 XkbSendControlsNotify(dev
,pCN
);
271 cause
.kc
= pCN
->keycode
;
272 cause
.event
= pCN
->eventType
;
273 cause
.mjr
= pCN
->requestMajor
;
274 cause
.mnr
= pCN
->requestMinor
;
275 sli
= XkbFindSrvLedInfo(dev
,XkbDfltXIClass
,XkbDfltXIId
,0);
276 XkbUpdateIndicators(dev
,sli
->usesControls
,True
,NULL
,&cause
);
277 if (XkbAX_NeedFeedback(ctrls
,XkbAX_FeatureFBMask
)) {
278 XkbDDXAccessXBeep(dev
,_BEEP_FEATURE_OFF
,XkbStickyKeysMask
);
280 #ifndef NO_CLEAR_LATCHES_FOR_STICKY_KEYS_OFF
281 XkbClearAllLatchesAndLocks(dev
,xkbi
,False
,&cause
);
284 } /* AccessXStickyKeysTurnOff */
287 AccessXKRGExpire(OsTimerPtr timer
,CARD32 now
,pointer arg
)
289 XkbSrvInfoPtr xkbi
= ((DeviceIntPtr
)arg
)->key
->xkbInfo
;
290 xkbControlsNotify cn
;
292 if (xkbi
->krgTimerActive
==_KRG_WARN_TIMER
) {
293 XkbDDXAccessXBeep((DeviceIntPtr
)arg
,_BEEP_SLOW_WARN
,XkbStickyKeysMask
);
294 xkbi
->krgTimerActive
= _KRG_TIMER
;
297 xkbi
->krgTimerActive
= _OFF_TIMER
;
302 if (xkbi
->desc
->ctrls
->enabled_ctrls
&XkbSlowKeysMask
)
303 AccessXKRGTurnOff((DeviceIntPtr
)arg
,&cn
);
304 else AccessXKRGTurnOn((DeviceIntPtr
)arg
,XkbSlowKeysMask
,&cn
);
309 AccessXRepeatKeyExpire(OsTimerPtr timer
,CARD32 now
,pointer arg
)
311 XkbSrvInfoPtr xkbi
= ((DeviceIntPtr
)arg
)->key
->xkbInfo
;
314 if (xkbi
->repeatKey
==0)
316 key
= xkbi
->repeatKey
;
317 AccessXKeyboardEvent((DeviceIntPtr
)arg
,KeyRelease
,key
,True
);
318 AccessXKeyboardEvent((DeviceIntPtr
)arg
,KeyPress
,key
,True
);
319 return xkbi
->desc
->ctrls
->repeat_interval
;
323 AccessXCancelRepeatKey(XkbSrvInfoPtr xkbi
,KeyCode key
)
325 if (xkbi
->repeatKey
==key
)
331 AccessXSlowKeyExpire(OsTimerPtr timer
,CARD32 now
,pointer arg
)
336 XkbControlsPtr ctrls
;
338 keybd
= (DeviceIntPtr
)arg
;
339 xkbi
= keybd
->key
->xkbInfo
;
342 if (xkbi
->slowKey
!=0) {
344 KeySym
*sym
= XkbKeySymsPtr(xkb
,xkbi
->slowKey
);
345 ev
.detail
= XkbAXN_SKAccept
;
346 ev
.keycode
= xkbi
->slowKey
;
347 ev
.slowKeysDelay
= ctrls
->slow_keys_delay
;
348 ev
.debounceDelay
= ctrls
->debounce_delay
;
349 XkbSendAccessXNotify(keybd
,&ev
);
350 if (XkbAX_NeedFeedback(ctrls
,XkbAX_SKAcceptFBMask
))
351 XkbDDXAccessXBeep(keybd
,_BEEP_SLOW_ACCEPT
,XkbSlowKeysMask
);
352 AccessXKeyboardEvent(keybd
,KeyPress
,xkbi
->slowKey
,False
);
353 /* check for magic sequences */
354 if ((ctrls
->enabled_ctrls
&XkbAccessXKeysMask
) &&
355 ((sym
[0]==XK_Shift_R
)||(sym
[0]==XK_Shift_L
)))
356 xkbi
->shiftKeyCount
++;
358 /* Start repeating if necessary. Stop autorepeating if the user
359 * presses a non-modifier key that doesn't autorepeat.
361 if (keybd
->kbdfeed
->ctrl
.autoRepeat
&&
362 ((xkbi
->slowKey
!= xkbi
->mouseKey
) || (!xkbi
->mouseKeysAccel
)) &&
363 (ctrls
->enabled_ctrls
&XkbRepeatKeysMask
)) {
364 if (BitIsOn(keybd
->kbdfeed
->ctrl
.autoRepeats
,xkbi
->slowKey
)) {
365 xkbi
->repeatKey
= xkbi
->slowKey
;
366 xkbi
->repeatKeyTimer
= TimerSet(xkbi
->repeatKeyTimer
,
367 0, ctrls
->repeat_delay
,
368 AccessXRepeatKeyExpire
, (pointer
)keybd
);
376 AccessXBounceKeyExpire(OsTimerPtr timer
,CARD32 now
,pointer arg
)
378 XkbSrvInfoPtr xkbi
= ((DeviceIntPtr
)arg
)->key
->xkbInfo
;
380 xkbi
->inactiveKey
= 0;
385 AccessXTimeoutExpire(OsTimerPtr timer
,CARD32 now
,pointer arg
)
387 DeviceIntPtr dev
= (DeviceIntPtr
)arg
;
388 XkbSrvInfoPtr xkbi
= dev
->key
->xkbInfo
;
389 XkbControlsPtr ctrls
= xkbi
->desc
->ctrls
;
391 xkbControlsNotify cn
;
392 XkbEventCauseRec cause
;
393 XkbSrvLedInfoPtr sli
;
395 if (xkbi
->lastPtrEventTime
) {
396 unsigned timeToWait
= (ctrls
->ax_timeout
*1000);
397 unsigned timeElapsed
= (now
-xkbi
->lastPtrEventTime
);
399 if (timeToWait
> timeElapsed
)
400 return (timeToWait
- timeElapsed
);
403 xkbi
->shiftKeyCount
= 0;
404 ctrls
->enabled_ctrls
&= ~ctrls
->axt_ctrls_mask
;
405 ctrls
->enabled_ctrls
|=
406 (ctrls
->axt_ctrls_values
&ctrls
->axt_ctrls_mask
);
407 if (ctrls
->axt_opts_mask
) {
408 ctrls
->ax_options
&= ~ctrls
->axt_opts_mask
;
409 ctrls
->ax_options
|= (ctrls
->axt_opts_values
&ctrls
->axt_opts_mask
);
411 if (XkbComputeControlsNotify(dev
,&old
,ctrls
,&cn
,False
)) {
416 XkbSendControlsNotify(dev
,&cn
);
418 XkbSetCauseUnknown(&cause
);
419 sli
= XkbFindSrvLedInfo(dev
,XkbDfltXIClass
,XkbDfltXIId
,0);
420 XkbUpdateIndicators(dev
,sli
->usesControls
,True
,NULL
,&cause
);
421 if (ctrls
->ax_options
!=old
.ax_options
) {
422 unsigned set
,cleared
,bell
;
423 set
= ctrls
->ax_options
&(~old
.ax_options
);
424 cleared
= (~ctrls
->ax_options
)&old
.ax_options
;
425 if (set
&& cleared
) bell
= _BEEP_FEATURE_CHANGE
;
426 else if (set
) bell
= _BEEP_FEATURE_ON
;
427 else bell
= _BEEP_FEATURE_OFF
;
428 XkbDDXAccessXBeep(dev
,bell
,XkbAccessXTimeoutMask
);
430 xkbi
->krgTimerActive
= _OFF_TIMER
;
435 /************************************************************************/
437 /* AccessXFilterPressEvent */
439 /* Filter events before they get any further if SlowKeys is turned on. */
440 /* In addition, this routine handles the ever so popular magic key */
441 /* acts for turning various accessibility features on/off. */
443 /* Returns TRUE if this routine has discarded the event. */
444 /* Returns FALSE if the event needs further processing. */
446 /************************************************************************/
448 AccessXFilterPressEvent( register xEvent
* xE
,
449 register DeviceIntPtr keybd
,
452 XkbSrvInfoPtr xkbi
= keybd
->key
->xkbInfo
;
453 XkbControlsPtr ctrls
= xkbi
->desc
->ctrls
;
454 Bool ignoreKeyEvent
= FALSE
;
455 KeyCode key
= xE
->u
.u
.detail
;
456 KeySym
* sym
= XkbKeySymsPtr(xkbi
->desc
,key
);
458 if (ctrls
->enabled_ctrls
&XkbAccessXKeysMask
) {
459 /* check for magic sequences */
460 if ((sym
[0]==XK_Shift_R
)||(sym
[0]==XK_Shift_L
)) {
461 if (XkbAX_NeedFeedback(ctrls
,XkbAX_SlowWarnFBMask
)) {
462 xkbi
->krgTimerActive
= _KRG_WARN_TIMER
;
463 xkbi
->krgTimer
= TimerSet(xkbi
->krgTimer
, 0, 4000,
464 AccessXKRGExpire
, (pointer
)keybd
);
467 xkbi
->krgTimerActive
= _KRG_TIMER
;
468 xkbi
->krgTimer
= TimerSet(xkbi
->krgTimer
, 0, 8000,
469 AccessXKRGExpire
, (pointer
)keybd
);
471 if (!(ctrls
->enabled_ctrls
& XkbSlowKeysMask
)) {
472 CARD32 now
= GetTimeInMillis();
473 if ((now
-xkbi
->lastShiftEventTime
)>15000)
474 xkbi
->shiftKeyCount
= 1;
475 else xkbi
->shiftKeyCount
++;
476 xkbi
->lastShiftEventTime
= now
;
480 if (xkbi
->krgTimerActive
) {
481 xkbi
->krgTimer
= TimerSet(xkbi
->krgTimer
,0, 0, NULL
, NULL
);
482 xkbi
->krgTimerActive
= _OFF_TIMER
;
487 /* Don't transmit the KeyPress if SlowKeys is turned on;
488 * The wakeup handler will synthesize one for us if the user
489 * has held the key long enough.
491 if (ctrls
->enabled_ctrls
& XkbSlowKeysMask
) {
493 /* If key was already pressed, ignore subsequent press events
494 * from the server's autorepeat
496 if(xkbi
->slowKey
== key
)
498 ev
.detail
= XkbAXN_SKPress
;
500 ev
.slowKeysDelay
= ctrls
->slow_keys_delay
;
501 ev
.debounceDelay
= ctrls
->debounce_delay
;
502 XkbSendAccessXNotify(keybd
,&ev
);
503 if (XkbAX_NeedFeedback(ctrls
,XkbAX_SKPressFBMask
))
504 XkbDDXAccessXBeep(keybd
,_BEEP_SLOW_PRESS
,XkbSlowKeysMask
);
506 xkbi
->slowKeysTimer
= TimerSet(xkbi
->slowKeysTimer
,
507 0, ctrls
->slow_keys_delay
,
508 AccessXSlowKeyExpire
, (pointer
)keybd
);
509 ignoreKeyEvent
= TRUE
;
512 /* Don't transmit the KeyPress if BounceKeys is turned on
513 * and the user pressed the same key within a given time period
514 * from the last release.
516 else if ((ctrls
->enabled_ctrls
& XkbBounceKeysMask
) &&
517 (key
== xkbi
->inactiveKey
)) {
518 if (XkbAX_NeedFeedback(ctrls
,XkbAX_BKRejectFBMask
))
519 XkbDDXAccessXBeep(keybd
,_BEEP_BOUNCE_REJECT
,XkbBounceKeysMask
);
520 ignoreKeyEvent
= TRUE
;
523 /* Start repeating if necessary. Stop autorepeating if the user
524 * presses a non-modifier key that doesn't autorepeat.
526 if (XkbDDXUsesSoftRepeat(keybd
)) {
527 if ((keybd
->kbdfeed
->ctrl
.autoRepeat
) &&
528 ((ctrls
->enabled_ctrls
&(XkbSlowKeysMask
|XkbRepeatKeysMask
))==
529 XkbRepeatKeysMask
)) {
530 if (BitIsOn(keybd
->kbdfeed
->ctrl
.autoRepeats
,key
)) {
532 if (xkbDebugFlags
&0x10)
533 ErrorF("Starting software autorepeat...\n");
535 xkbi
->repeatKey
= key
;
536 xkbi
->repeatKeyTimer
= TimerSet(xkbi
->repeatKeyTimer
,
537 0, ctrls
->repeat_delay
,
538 AccessXRepeatKeyExpire
, (pointer
)keybd
);
543 /* Check for two keys being pressed at the same time. This section
544 * essentially says the following:
546 * If StickyKeys is on, and a modifier is currently being held down,
547 * and one of the following is true: the current key is not a modifier
548 * or the currentKey is a modifier, but not the only modifier being
549 * held down, turn StickyKeys off if the TwoKeys off ctrl is set.
551 if ((ctrls
->enabled_ctrls
& XkbStickyKeysMask
) &&
552 (xkbi
->state
.base_mods
!=0) &&
553 (XkbAX_NeedOption(ctrls
,XkbAX_TwoKeysMask
))) {
554 xkbControlsNotify cn
;
556 cn
.eventType
= KeyPress
;
559 AccessXStickyKeysTurnOff(keybd
,&cn
);
563 XkbProcessKeyboardEvent(xE
,keybd
,count
);
564 return ignoreKeyEvent
;
565 } /* AccessXFilterPressEvent */
567 /************************************************************************/
569 /* AccessXFilterReleaseEvent */
571 /* Filter events before they get any further if SlowKeys is turned on. */
572 /* In addition, this routine handles the ever so popular magic key */
573 /* acts for turning various accessibility features on/off. */
575 /* Returns TRUE if this routine has discarded the event. */
576 /* Returns FALSE if the event needs further processing. */
578 /************************************************************************/
580 AccessXFilterReleaseEvent( register xEvent
* xE
,
581 register DeviceIntPtr keybd
,
584 XkbSrvInfoPtr xkbi
= keybd
->key
->xkbInfo
;
585 XkbControlsPtr ctrls
= xkbi
->desc
->ctrls
;
586 KeyCode key
= xE
->u
.u
.detail
;
587 Bool ignoreKeyEvent
= FALSE
;
589 /* Don't transmit the KeyRelease if BounceKeys is on and
590 * this is the release of a key that was ignored due to
593 if (ctrls
->enabled_ctrls
& XkbBounceKeysMask
) {
594 if ((key
!=xkbi
->mouseKey
)&&(!BitIsOn(keybd
->key
->down
,key
)))
595 ignoreKeyEvent
= TRUE
;
596 xkbi
->inactiveKey
= key
;
597 xkbi
->bounceKeysTimer
= TimerSet(xkbi
->bounceKeysTimer
, 0,
598 ctrls
->debounce_delay
,
599 AccessXBounceKeyExpire
, (pointer
)keybd
);
602 /* Don't transmit the KeyRelease if SlowKeys is turned on and
603 * the user didn't hold the key long enough. We know we passed
604 * the key if the down bit was set by CoreProcessKeyboadEvent.
606 if (ctrls
->enabled_ctrls
& XkbSlowKeysMask
) {
610 ev
.slowKeysDelay
= ctrls
->slow_keys_delay
;
611 ev
.debounceDelay
= ctrls
->debounce_delay
;
612 if (BitIsOn(keybd
->key
->down
,key
) | (xkbi
->mouseKey
== key
)) {
613 ev
.detail
= XkbAXN_SKRelease
;
614 beep_type
= _BEEP_SLOW_RELEASE
;
617 ev
.detail
= XkbAXN_SKReject
;
618 beep_type
= _BEEP_SLOW_REJECT
;
619 ignoreKeyEvent
= TRUE
;
621 XkbSendAccessXNotify(keybd
,&ev
);
622 if (XkbAX_NeedFeedback(ctrls
,XkbAX_SKRejectFBMask
)) {
623 XkbDDXAccessXBeep(keybd
,beep_type
,XkbSlowKeysMask
);
625 if (xkbi
->slowKey
==key
)
629 /* Stop Repeating if the user releases the key that is currently
632 if (xkbi
->repeatKey
==key
) {
636 if ((ctrls
->enabled_ctrls
&XkbAccessXTimeoutMask
)&&(ctrls
->ax_timeout
>0)) {
637 xkbi
->lastPtrEventTime
= 0;
638 xkbi
->krgTimer
= TimerSet(xkbi
->krgTimer
, 0,
639 ctrls
->ax_timeout
*1000,
640 AccessXTimeoutExpire
, (pointer
)keybd
);
641 xkbi
->krgTimerActive
= _ALL_TIMEOUT_TIMER
;
643 else if (xkbi
->krgTimerActive
!=_OFF_TIMER
) {
644 xkbi
->krgTimer
= TimerSet(xkbi
->krgTimer
, 0, 0, NULL
, NULL
);
645 xkbi
->krgTimerActive
= _OFF_TIMER
;
648 /* Keep track of how many times the Shift key has been pressed.
649 * If it has been pressed and released 5 times in a row, toggle
650 * the state of StickyKeys.
652 if ((!ignoreKeyEvent
)&&(xkbi
->shiftKeyCount
)) {
653 KeySym
*pSym
= XkbKeySymsPtr(xkbi
->desc
,key
);
654 if ((pSym
[0]!=XK_Shift_L
)&&(pSym
[0]!=XK_Shift_R
)) {
655 xkbi
->shiftKeyCount
= 0;
657 else if (xkbi
->shiftKeyCount
>=5) {
658 xkbControlsNotify cn
;
660 cn
.eventType
= KeyPress
;
663 if (ctrls
->enabled_ctrls
& XkbStickyKeysMask
)
664 AccessXStickyKeysTurnOff(keybd
,&cn
);
666 AccessXStickyKeysTurnOn(keybd
,&cn
);
667 xkbi
->shiftKeyCount
= 0;
672 XkbProcessKeyboardEvent(xE
,keybd
,count
);
673 return ignoreKeyEvent
;
675 } /* AccessXFilterReleaseEvent */
677 /************************************************************************/
679 /* ProcessPointerEvent */
681 /* This routine merely sets the shiftKeyCount and clears the keyboard */
682 /* response group timer (if necessary) on a mouse event. This is so */
683 /* multiple shifts with just the mouse and shift-drags with the mouse */
684 /* don't accidentally turn on StickyKeys or the Keyboard Response Group.*/
686 /************************************************************************/
688 ProcessPointerEvent( register xEvent
* xE
,
689 register DeviceIntPtr mouse
,
692 DeviceIntPtr dev
= (DeviceIntPtr
)LookupKeyboardDevice();
693 XkbSrvInfoPtr xkbi
= dev
->key
->xkbInfo
;
694 unsigned changed
= 0;
696 xkbi
->shiftKeyCount
= 0;
697 xkbi
->lastPtrEventTime
= xE
->u
.keyButtonPointer
.time
;
699 if (xE
->u
.u
.type
==ButtonPress
) {
700 changed
|= XkbPointerButtonMask
;
702 else if (xE
->u
.u
.type
==ButtonRelease
) {
703 xkbi
->lockedPtrButtons
&= ~(1<<(xE
->u
.u
.detail
&0x7));
704 changed
|= XkbPointerButtonMask
;
706 CoreProcessPointerEvent(xE
,mouse
,count
);
708 xkbi
->state
.ptr_buttons
= mouse
->button
->state
;
710 /* clear any latched modifiers */
711 if ( xkbi
->state
.latched_mods
&& (xE
->u
.u
.type
==ButtonRelease
) ) {
712 unsigned changed_leds
;
713 XkbStateRec oldState
;
714 XkbSrvLedInfoPtr sli
;
716 sli
= XkbFindSrvLedInfo(dev
,XkbDfltXIClass
,XkbDfltXIId
,0);
717 oldState
= xkbi
->state
;
718 XkbLatchModifiers(dev
,0xFF,0x00);
720 XkbComputeDerivedState(xkbi
);
721 changed
|= XkbStateChangedFlags(&oldState
,&xkbi
->state
);
722 if (changed
&sli
->usedComponents
) {
723 changed_leds
= XkbIndicatorsToUpdate(dev
,changed
,False
);
725 XkbEventCauseRec cause
;
726 XkbSetCauseKey(&cause
,(xE
->u
.u
.detail
&0x7),xE
->u
.u
.type
);
727 XkbUpdateIndicators(dev
,changed_leds
,True
,NULL
,&cause
);
730 dev
->key
->state
= XkbStateFieldFromRec(&xkbi
->state
);
733 if (((xkbi
->flags
&_XkbStateNotifyInProgress
)==0)&&(changed
!=0)) {
735 sn
.keycode
= xE
->u
.u
.detail
;
736 sn
.eventType
= xE
->u
.u
.type
;
737 sn
.requestMajor
= sn
.requestMinor
= 0;
739 XkbSendStateNotify(dev
,&sn
);
742 } /* ProcessPointerEvent */