First import
[xorg_rtime.git] / xorg-server-1.4 / xkb / xkbAccessX.c
blob2954a0c0ebb88f4bba2123c7e717fc3d81cf8cf9
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>
29 #endif
31 #include <stdio.h>
32 #include <math.h>
33 #ifdef __QNX__
34 #include <limits.h>
35 #endif
36 #define NEED_EVENTS 1
37 #include <X11/X.h>
38 #include <X11/Xproto.h>
39 #include <X11/keysym.h>
40 #include "inputstr.h"
41 #include <xkbsrv.h>
42 #if !defined(WIN32) && !defined(Lynx)
43 #include <sys/time.h>
44 #endif
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);
61 void
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));
67 return;
70 void
71 AccessXInit(DeviceIntPtr keybd)
73 XkbSrvInfoPtr xkbi = keybd->key->xkbInfo;
74 XkbControlsPtr ctrls = xkbi->desc->ctrls;
76 xkbi->shiftKeyCount= 0;
77 xkbi->mouseKeysCounter= 0;
78 xkbi->inactiveKey= 0;
79 xkbi->slowKey= 0;
80 xkbi->repeatKey= 0;
81 xkbi->krgTimerActive= _OFF_TIMER;
82 xkbi->beepType= _BEEP_NONE;
83 xkbi->beepCount= 0;
84 xkbi->mouseKeyTimer= NULL;
85 xkbi->slowKeysTimer= NULL;
86 xkbi->bounceKeysTimer= NULL;
87 xkbi->repeatKeyTimer= NULL;
88 xkbi->krgTimer= 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;
107 else
108 ctrls->enabled_ctrls &= ~XkbAccessXTimeoutMask;
109 ctrls->enabled_ctrls |= XkbDfltAccessXFeedback;
110 ctrls->ax_options = XkbDfltAccessXOptions;
111 AccessXComputeCurveFactor(xkbi,ctrls);
112 return;
115 /************************************************************************/
116 /* */
117 /* AccessXKeyboardEvent */
118 /* */
119 /* Generate a synthetic keyboard event. */
120 /* */
121 /************************************************************************/
122 static void
123 AccessXKeyboardEvent(DeviceIntPtr keybd,
124 BYTE type,
125 BYTE keyCode,
126 Bool isRepeat)
128 xEvent xE;
130 xE.u.u.type = type;
131 xE.u.u.detail = keyCode;
132 xE.u.keyButtonPointer.time = GetTimeInMillis();
133 #ifdef DEBUG
134 if (xkbDebugFlags&0x8) {
135 ErrorF("AXKE: Key %d %s\n",keyCode,(xE.u.u.type==KeyPress?"down":"up"));
137 #endif
139 if (_XkbIsPressEvent(type))
140 XkbDDXKeyClick(keybd,keyCode,TRUE);
141 else if (isRepeat)
142 XkbLastRepeatEvent= (pointer)&xE;
143 XkbProcessKeyboardEvent(&xE,keybd,1L);
144 XkbLastRepeatEvent= NULL;
145 return;
147 } /* AccessXKeyboardEvent */
149 /************************************************************************/
150 /* */
151 /* AccessXKRGTurnOn */
152 /* */
153 /* Turn the keyboard response group on. */
154 /* */
155 /************************************************************************/
156 static void
157 AccessXKRGTurnOn(DeviceIntPtr dev,CARD16 KRGControl,xkbControlsNotify *pCN)
159 XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
160 XkbControlsPtr ctrls = xkbi->desc->ctrls;
161 XkbControlsRec old;
162 XkbEventCauseRec cause;
163 XkbSrvLedInfoPtr sli;
165 old= *ctrls;
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);
177 return;
179 } /* AccessXKRGTurnOn */
181 /************************************************************************/
182 /* */
183 /* AccessXKRGTurnOff */
184 /* */
185 /* Turn the keyboard response group off. */
186 /* */
187 /************************************************************************/
188 static void
189 AccessXKRGTurnOff(DeviceIntPtr dev,xkbControlsNotify *pCN)
191 XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
192 XkbControlsPtr ctrls = xkbi->desc->ctrls;
193 XkbControlsRec old;
194 XkbEventCauseRec cause;
195 XkbSrvLedInfoPtr sli;
197 old = *ctrls;
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);
211 return;
213 } /* AccessXKRGTurnOff */
215 /************************************************************************/
216 /* */
217 /* AccessXStickyKeysTurnOn */
218 /* */
219 /* Turn StickyKeys on. */
220 /* */
221 /************************************************************************/
222 static void
223 AccessXStickyKeysTurnOn(DeviceIntPtr dev,xkbControlsNotify *pCN)
225 XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
226 XkbControlsPtr ctrls = xkbi->desc->ctrls;
227 XkbControlsRec old;
228 XkbEventCauseRec cause;
229 XkbSrvLedInfoPtr sli;
231 old = *ctrls;
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);
245 return;
247 } /* AccessXStickyKeysTurnOn */
249 /************************************************************************/
250 /* */
251 /* AccessXStickyKeysTurnOff */
252 /* */
253 /* Turn StickyKeys off. */
254 /* */
255 /************************************************************************/
256 static void
257 AccessXStickyKeysTurnOff(DeviceIntPtr dev,xkbControlsNotify *pCN)
259 XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
260 XkbControlsPtr ctrls = xkbi->desc->ctrls;
261 XkbControlsRec old;
262 XkbEventCauseRec cause;
263 XkbSrvLedInfoPtr sli;
265 old = *ctrls;
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);
282 #endif
283 return;
284 } /* AccessXStickyKeysTurnOff */
286 static CARD32
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;
295 return 4000;
297 xkbi->krgTimerActive= _OFF_TIMER;
298 cn.keycode = 0;
299 cn.eventType = 0;
300 cn.requestMajor = 0;
301 cn.requestMinor = 0;
302 if (xkbi->desc->ctrls->enabled_ctrls&XkbSlowKeysMask)
303 AccessXKRGTurnOff((DeviceIntPtr)arg,&cn);
304 else AccessXKRGTurnOn((DeviceIntPtr)arg,XkbSlowKeysMask,&cn);
305 return 0;
308 static CARD32
309 AccessXRepeatKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg)
311 XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo;
312 KeyCode key;
314 if (xkbi->repeatKey==0)
315 return 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;
322 void
323 AccessXCancelRepeatKey(XkbSrvInfoPtr xkbi,KeyCode key)
325 if (xkbi->repeatKey==key)
326 xkbi->repeatKey= 0;
327 return;
330 static CARD32
331 AccessXSlowKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg)
333 DeviceIntPtr keybd;
334 XkbSrvInfoPtr xkbi;
335 XkbDescPtr xkb;
336 XkbControlsPtr ctrls;
338 keybd= (DeviceIntPtr)arg;
339 xkbi= keybd->key->xkbInfo;
340 xkb= xkbi->desc;
341 ctrls= xkb->ctrls;
342 if (xkbi->slowKey!=0) {
343 xkbAccessXNotify ev;
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);
372 return 0;
375 static CARD32
376 AccessXBounceKeyExpire(OsTimerPtr timer,CARD32 now,pointer arg)
378 XkbSrvInfoPtr xkbi= ((DeviceIntPtr)arg)->key->xkbInfo;
380 xkbi->inactiveKey= 0;
381 return 0;
384 static CARD32
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;
390 XkbControlsRec old;
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);
402 old= *ctrls;
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)) {
412 cn.keycode = 0;
413 cn.eventType = 0;
414 cn.requestMajor = 0;
415 cn.requestMinor = 0;
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;
431 return 0;
435 /************************************************************************/
436 /* */
437 /* AccessXFilterPressEvent */
438 /* */
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. */
442 /* */
443 /* Returns TRUE if this routine has discarded the event. */
444 /* Returns FALSE if the event needs further processing. */
445 /* */
446 /************************************************************************/
447 Bool
448 AccessXFilterPressEvent( register xEvent * xE,
449 register DeviceIntPtr keybd,
450 int count)
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);
466 else {
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;
479 else {
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) {
492 xkbAccessXNotify ev;
493 /* If key was already pressed, ignore subsequent press events
494 * from the server's autorepeat
496 if(xkbi->slowKey == key)
497 return TRUE;
498 ev.detail= XkbAXN_SKPress;
499 ev.keycode= key;
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);
505 xkbi->slowKey= key;
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)) {
531 #ifdef DEBUG
532 if (xkbDebugFlags&0x10)
533 ErrorF("Starting software autorepeat...\n");
534 #endif
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;
555 cn.keycode = key;
556 cn.eventType = KeyPress;
557 cn.requestMajor = 0;
558 cn.requestMinor = 0;
559 AccessXStickyKeysTurnOff(keybd,&cn);
562 if (!ignoreKeyEvent)
563 XkbProcessKeyboardEvent(xE,keybd,count);
564 return ignoreKeyEvent;
565 } /* AccessXFilterPressEvent */
567 /************************************************************************/
568 /* */
569 /* AccessXFilterReleaseEvent */
570 /* */
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. */
574 /* */
575 /* Returns TRUE if this routine has discarded the event. */
576 /* Returns FALSE if the event needs further processing. */
577 /* */
578 /************************************************************************/
579 Bool
580 AccessXFilterReleaseEvent( register xEvent * xE,
581 register DeviceIntPtr keybd,
582 int count)
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
591 * BounceKeys.
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) {
607 xkbAccessXNotify ev;
608 unsigned beep_type;
609 ev.keycode= key;
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;
616 else {
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)
626 xkbi->slowKey= 0;
629 /* Stop Repeating if the user releases the key that is currently
630 * repeating.
632 if (xkbi->repeatKey==key) {
633 xkbi->repeatKey= 0;
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;
659 cn.keycode = key;
660 cn.eventType = KeyPress;
661 cn.requestMajor = 0;
662 cn.requestMinor = 0;
663 if (ctrls->enabled_ctrls & XkbStickyKeysMask)
664 AccessXStickyKeysTurnOff(keybd,&cn);
665 else
666 AccessXStickyKeysTurnOn(keybd,&cn);
667 xkbi->shiftKeyCount= 0;
671 if (!ignoreKeyEvent)
672 XkbProcessKeyboardEvent(xE,keybd,count);
673 return ignoreKeyEvent;
675 } /* AccessXFilterReleaseEvent */
677 /************************************************************************/
678 /* */
679 /* ProcessPointerEvent */
680 /* */
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.*/
685 /* */
686 /************************************************************************/
687 void
688 ProcessPointerEvent( register xEvent * xE,
689 register DeviceIntPtr mouse,
690 int count)
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);
724 if (changed_leds) {
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)) {
734 xkbStateNotify sn;
735 sn.keycode= xE->u.u.detail;
736 sn.eventType= xE->u.u.type;
737 sn.requestMajor = sn.requestMinor = 0;
738 sn.changed= changed;
739 XkbSendStateNotify(dev,&sn);
742 } /* ProcessPointerEvent */