Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

access.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: access.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * This module contains the Access Pack functions. 00007 * 00008 * History: 00009 * 11 Feb 93 GregoryW Created. 00010 \***************************************************************************/ 00011 00012 #include "precomp.h" 00013 #pragma hdrstop 00014 00015 CONST ACCESSIBILITYPROC aAccessibilityProc[] = { 00016 HighContrastHotKey, 00017 FilterKeys, 00018 xxxStickyKeys, 00019 MouseKeys, 00020 ToggleKeys, 00021 UtilityManager 00022 }; 00023 00024 typedef struct tagMODBITINFO { 00025 int BitPosition; 00026 BYTE ScanCode; 00027 USHORT Vk; 00028 } MODBITINFO, *PMODBITINFO; 00029 00030 CONST MODBITINFO aModBit[] = 00031 { 00032 { 0x01, SCANCODE_LSHIFT, VK_LSHIFT }, 00033 { 0x02, SCANCODE_RSHIFT, VK_RSHIFT | KBDEXT }, 00034 { 0x04, SCANCODE_CTRL, VK_LCONTROL }, 00035 { 0x08, SCANCODE_CTRL, VK_RCONTROL | KBDEXT }, 00036 { 0x10, SCANCODE_ALT, VK_LMENU }, 00037 { 0x20, SCANCODE_ALT, VK_RMENU | KBDEXT }, 00038 { 0x40, SCANCODE_LWIN, VK_LWIN }, 00039 { 0x80, SCANCODE_RWIN, VK_RWIN | KBDEXT} 00040 }; 00041 00042 /* 00043 * The ausMouseVKey array provides a translation from the virtual key 00044 * value to an index. The index is used to select the appropriate 00045 * routine to process the virtual key, as well as to select extra 00046 * information that is used by this routine during its processing. 00047 */ 00048 CONST USHORT ausMouseVKey[] = { 00049 VK_CLEAR, 00050 VK_PRIOR, 00051 VK_NEXT, 00052 VK_END, 00053 VK_HOME, 00054 VK_LEFT, 00055 VK_UP, 00056 VK_RIGHT, 00057 VK_DOWN, 00058 VK_INSERT, 00059 VK_DELETE, 00060 VK_MULTIPLY, 00061 VK_ADD, 00062 VK_SUBTRACT, 00063 VK_DIVIDE | KBDEXT, 00064 VK_NUMLOCK | KBDEXT 00065 }; 00066 00067 CONST int cMouseVKeys = sizeof(ausMouseVKey) / sizeof(ausMouseVKey[0]); 00068 00069 /* 00070 * aMouseKeyEvent is an array of function pointers. The routine to call 00071 * is selected using the index created by scanning the ausMouseVKey array. 00072 */ 00073 CONST MOUSEPROC aMouseKeyEvent[] = { 00074 xxxMKButtonClick, // Numpad 5 (Clear) 00075 xxxMKMouseMove, // Numpad 9 (PgUp) 00076 xxxMKMouseMove, // Numpad 3 (PgDn) 00077 xxxMKMouseMove, // Numpad 1 (End) 00078 xxxMKMouseMove, // Numpad 7 (Home) 00079 xxxMKMouseMove, // Numpad 4 (Left) 00080 xxxMKMouseMove, // Numpad 8 (Up) 00081 xxxMKMouseMove, // Numpad 6 (Right) 00082 xxxMKMouseMove, // Numpad 2 (Down) 00083 xxxMKButtonSetState, // Numpad 0 (Ins) 00084 xxxMKButtonSetState, // Numpad . (Del) 00085 MKButtonSelect, // Numpad * (Multiply) 00086 xxxMKButtonDoubleClick,// Numpad + (Add) 00087 MKButtonSelect, // Numpad - (Subtract) 00088 MKButtonSelect, // Numpad / (Divide) 00089 xxxMKToggleMouseKeys // Num Lock 00090 }; 00091 00092 /* 00093 * ausMouseKeyData contains useful data for the routines that process 00094 * the virtual mousekeys. This array is indexed using the index created 00095 * by scanning the ausMouseVKey array. 00096 */ 00097 CONST USHORT ausMouseKeyData[] = { 00098 0, // Numpad 5: Click active button 00099 MK_UP | MK_RIGHT, // Numpad 9: Up & Right 00100 MK_DOWN | MK_RIGHT, // Numpad 3: Down & Right 00101 MK_DOWN | MK_LEFT, // Numpad 1: Down & Left 00102 MK_UP | MK_LEFT, // Numpad 7: Up & Left 00103 MK_LEFT, // Numpad 4: Left 00104 MK_UP, // Numpad 8: Up 00105 MK_RIGHT, // Numpad 6: Right 00106 MK_DOWN, // Numpad 2: Down 00107 FALSE, // Numpad 0: Active button down 00108 TRUE, // Numpad .: Active button up 00109 MOUSE_BUTTON_LEFT | MOUSE_BUTTON_RIGHT, // Numpad *: Select both buttons 00110 0, // Numpad +: Double click active button 00111 MOUSE_BUTTON_RIGHT, // Numpad -: Select right button 00112 MOUSE_BUTTON_LEFT, // Numpad /: Select left button 00113 0 00114 }; 00115 00116 __inline void 00117 PostAccessNotification(UINT accessKeyType) 00118 { 00119 if (gspwndLogonNotify != NULL) 00120 { 00121 glinp.ptiLastWoken = GETPTI(gspwndLogonNotify); 00122 00123 _PostMessage(gspwndLogonNotify, WM_LOGONNOTIFY, 00124 LOGON_ACCESSNOTIFY, accessKeyType); 00125 } 00126 } 00127 00128 void PostRitSound(PTERMINAL pTerm, UINT message) { 00129 PostEventMessage( 00130 pTerm->ptiDesktop, 00131 pTerm->ptiDesktop->pq, 00132 QEVENT_RITSOUND, 00133 NULL, 00134 message, 0, 0); 00135 return; 00136 } 00137 00138 void PostAccessibility( LPARAM lParam ) 00139 { 00140 PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm; 00141 00142 PostEventMessage( 00143 pTerm->ptiDesktop, 00144 pTerm->pqDesktop, 00145 QEVENT_RITACCESSIBILITY, 00146 NULL, 00147 0, HSHELL_ACCESSIBILITYSTATE, lParam); 00148 } 00149 00150 /***************************************************************************\ 00151 * AccessProceduresStream 00152 * 00153 * This function controls the order in which the access functions are called. 00154 * All key events pass through this routine. If an access function returns 00155 * FALSE then none of the other access functions in the stream are called. 00156 * This routine is called initially from KeyboardApcProcedure(), but then 00157 * can be called any number of times by the access functions as they process 00158 * the current key event or add more key events. 00159 * 00160 * Return value: 00161 * TRUE All access functions returned TRUE, the key event can be 00162 * processed. 00163 * FALSE An access function returned FALSE, the key event should be 00164 * discarded. 00165 * 00166 * History: 00167 * 11 Feb 93 GregoryW Created. 00168 \***************************************************************************/ 00169 BOOL AccessProceduresStream(PKE pKeyEvent, ULONG ExtraInformation, int dwProcIndex) 00170 { 00171 int index; 00172 00173 CheckCritIn(); 00174 for (index = dwProcIndex; index < ARRAY_SIZE(aAccessibilityProc); index++) { 00175 if (!aAccessibilityProc[index](pKeyEvent, ExtraInformation, index+1)) { 00176 return FALSE; 00177 } 00178 } 00179 00180 return TRUE; 00181 } 00182 00183 00184 /***************************************************************************\ 00185 * FKActivationTimer 00186 * 00187 * If the hot key (right shift key) is held down this routine is called after 00188 * 4, 8, 12 and 16 seconds. This routine is only called at the 12 and 16 00189 * second time points if we're in the process of enabling FilterKeys. If at 00190 * 8 seconds FilterKeys is disabled then this routine will not be called again 00191 * until the hot key is released and then pressed. 00192 * 00193 * This routine is called with the critical section already locked. 00194 * 00195 * Return value: 00196 * 0 00197 * 00198 * History: 00199 * 11 Feb 93 GregoryW Created. 00200 \***************************************************************************/ 00201 VOID FKActivationTimer(PWND pwnd, UINT message, UINT_PTR nID, LPARAM lParam) 00202 { 00203 UINT TimerDelta; 00204 PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm; 00205 00206 CheckCritIn(); 00207 00208 switch (gFilterKeysState) { 00209 00210 case FKFIRSTWARNING: 00211 // 00212 // The audible feedback cannot be disabled for this warning. 00213 // 00214 /*PostEventMessage( 00215 pTerm->ptiDesktop, 00216 pTerm->ptiDesktop->pq, 00217 QEVENT_RITSOUND, 00218 NULL, 00219 RITSOUND_DOBEEP, RITSOUND_HIGHBEEP, 3);*/ 00220 TimerDelta = FKACTIVATIONDELTA; 00221 break; 00222 00223 case FKTOGGLE: 00224 if (TEST_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON)) { 00225 // 00226 // Disable Filter Keys 00227 // 00228 CLEAR_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON); 00229 if (TEST_ACCESSFLAG(FilterKeys, FKF_HOTKEYSOUND)) { 00230 PostRitSound( 00231 pTerm, 00232 RITSOUND_DOWNSIREN); 00233 } 00234 PostAccessibility( ACCESS_FILTERKEYS ); 00235 // 00236 // Stop all timers that are currently running. 00237 // 00238 if (gtmridFKResponse != 0) { 00239 KILLRITTIMER(NULL, gtmridFKResponse); 00240 gtmridFKResponse = 0; 00241 } 00242 if (gtmridFKAcceptanceDelay != 0) { 00243 KILLRITTIMER(NULL, gtmridFKAcceptanceDelay); 00244 gtmridFKAcceptanceDelay = 0; 00245 } 00246 00247 // 00248 // Don't reset activation timer. Emergency levels are only 00249 // activated after enabling Filter Keys. 00250 // 00251 return; 00252 } else { 00253 PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm; 00254 00255 if (TEST_ACCESSFLAG(FilterKeys, FKF_HOTKEYSOUND)) { 00256 PostRitSound( 00257 pTerm, 00258 RITSOUND_UPSIREN); 00259 } 00260 00261 PostAccessNotification(ACCESS_FILTERKEYS); 00262 00263 } 00264 TimerDelta = FKEMERGENCY1DELTA; 00265 break; 00266 00267 case FKFIRSTLEVELEMERGENCY: 00268 // 00269 // First level emergency settings: 00270 // Repeat Rate OFF 00271 // SlowKeys OFF (Acceptance Delay of 0) 00272 // BounceKeys Debounce Time of 1 second 00273 // 00274 if (TEST_ACCESSFLAG(FilterKeys, FKF_HOTKEYSOUND)) { 00275 PostEventMessage( 00276 pTerm->ptiDesktop, 00277 pTerm->ptiDesktop->pq, 00278 QEVENT_RITSOUND, 00279 NULL, 00280 RITSOUND_DOBEEP, RITSOUND_UPSIREN, 2); 00281 } 00282 gFilterKeys.iRepeatMSec = 0; 00283 gFilterKeys.iWaitMSec = 0; 00284 gFilterKeys.iBounceMSec = 1000; 00285 TimerDelta = FKEMERGENCY2DELTA; 00286 break; 00287 00288 case FKSECONDLEVELEMERGENCY: 00289 // 00290 // Second level emergency settings: 00291 // Repeat Rate OFF 00292 // SlowKeys Acceptance Delay of 2 seconds 00293 // BounceKeys OFF (Debounce Time of 0) 00294 // 00295 gFilterKeys.iRepeatMSec = 0; 00296 gFilterKeys.iWaitMSec = 2000; 00297 gFilterKeys.iBounceMSec = 0; 00298 if (TEST_ACCESSFLAG(FilterKeys, FKF_HOTKEYSOUND)) { 00299 PostEventMessage( 00300 pTerm->ptiDesktop, 00301 pTerm->ptiDesktop->pq, 00302 QEVENT_RITSOUND, 00303 NULL, 00304 RITSOUND_DOBEEP, RITSOUND_UPSIREN, 3); 00305 } 00306 return; 00307 break; 00308 00309 default: 00310 return; 00311 } 00312 00313 gFilterKeysState++; 00314 gtmridFKActivation = InternalSetTimer( 00315 NULL, 00316 nID, 00317 TimerDelta, 00318 FKActivationTimer, 00319 TMRF_RIT | TMRF_ONESHOT 00320 ); 00321 return; 00322 00323 DBG_UNREFERENCED_PARAMETER(pwnd); 00324 DBG_UNREFERENCED_PARAMETER(lParam); 00325 DBG_UNREFERENCED_PARAMETER(message); 00326 } 00327 00328 /***************************************************************************\ 00329 * FKBounceKeyTimer 00330 * 00331 * If BounceKeys is active this routine is called after the debounce time 00332 * has expired. Until then, the last key released will not be accepted as 00333 * input if it is pressed again. 00334 * 00335 * Return value: 00336 * 0 00337 * 00338 * History: 00339 * 11 Feb 93 GregoryW Created. 00340 \***************************************************************************/ 00341 VOID FKBounceKeyTimer(PWND pwnd, UINT message, UINT_PTR nID, LPARAM lParam) 00342 { 00343 00344 CheckCritIn(); 00345 // 00346 // All we need to do is clear gBounceVk to allow this key as the 00347 // next keystroke. 00348 // 00349 gBounceVk = 0; 00350 return; 00351 00352 DBG_UNREFERENCED_PARAMETER(pwnd); 00353 DBG_UNREFERENCED_PARAMETER(lParam); 00354 DBG_UNREFERENCED_PARAMETER(nID); 00355 DBG_UNREFERENCED_PARAMETER(message); 00356 00357 } 00358 00359 /***************************************************************************\ 00360 * xxxFKRepeatRateTimer 00361 * 00362 * If FilterKeys is active and a repeat rate is set, this routine controls 00363 * the rate at which the last key pressed repeats. The hardware keyboard 00364 * typematic repeat is ignored in this case. 00365 * 00366 * This routine is called with the critical section already locked. 00367 * 00368 * Return value: 00369 * 0 00370 * 00371 * History: 00372 * 11 Feb 93 GregoryW Created. 00373 \***************************************************************************/ 00374 VOID xxxFKRepeatRateTimer(PWND pwnd, UINT message, UINT_PTR nID, LPARAM lParam) 00375 { 00376 00377 CheckCritIn(); 00378 // 00379 // Repeat after me... 00380 // 00381 if (TEST_ACCESSFLAG(FilterKeys, FKF_CLICKON)) { 00382 PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm; 00383 PostRitSound( 00384 pTerm, 00385 RITSOUND_KEYCLICK); 00386 } 00387 00388 UserAssert(gtmridFKAcceptanceDelay == 0); 00389 00390 gtmridFKResponse = InternalSetTimer( 00391 NULL, 00392 nID, 00393 gFilterKeys.iRepeatMSec, 00394 xxxFKRepeatRateTimer, 00395 TMRF_RIT | TMRF_ONESHOT 00396 ); 00397 if (AccessProceduresStream(gpFKKeyEvent, gFKExtraInformation, gFKNextProcIndex)) { 00398 xxxProcessKeyEvent(gpFKKeyEvent, gFKExtraInformation, FALSE); 00399 } 00400 return; 00401 00402 00403 DBG_UNREFERENCED_PARAMETER(pwnd); 00404 DBG_UNREFERENCED_PARAMETER(lParam); 00405 DBG_UNREFERENCED_PARAMETER(message); 00406 } 00407 00408 /***************************************************************************\ 00409 * xxxFKAcceptanceDelayTimer 00410 * 00411 * If FilterKeys is active and an acceptance delay is set, this routine 00412 * is called after the key has been held down for the acceptance delay 00413 * period. 00414 * 00415 * This routine is called with the critical section already locked. 00416 * 00417 * Return value: 00418 * 0 00419 * 00420 * History: 00421 * 11 Feb 93 GregoryW Created. 00422 \***************************************************************************/ 00423 VOID xxxFKAcceptanceDelayTimer(PWND pwnd, UINT message, UINT_PTR nID, LPARAM lParam) 00424 { 00425 00426 CheckCritIn(); 00427 // 00428 // The key has been held down long enough. Send it on... 00429 // 00430 if (TEST_ACCESSFLAG(FilterKeys, FKF_CLICKON)) { 00431 PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm; 00432 PostRitSound( 00433 pTerm, 00434 RITSOUND_KEYCLICK); 00435 } 00436 00437 if (AccessProceduresStream(gpFKKeyEvent, gFKExtraInformation, gFKNextProcIndex)) { 00438 xxxProcessKeyEvent(gpFKKeyEvent, gFKExtraInformation, FALSE); 00439 } 00440 if (!gFilterKeys.iRepeatMSec) { 00441 // 00442 // gptmrFKAcceptanceDelay needs to be released, but we can't do it while 00443 // in a RIT timer routine. Set a global to indicate that the subsequent 00444 // break of this key should be passed on and the timer freed. 00445 // 00446 SET_ACCF(ACCF_FKMAKECODEPROCESSED); 00447 return; 00448 } 00449 UserAssert(gtmridFKResponse == 0); 00450 if (gFilterKeys.iDelayMSec) { 00451 gtmridFKResponse = InternalSetTimer( 00452 NULL, 00453 nID, 00454 gFilterKeys.iDelayMSec, 00455 xxxFKRepeatRateTimer, 00456 TMRF_RIT | TMRF_ONESHOT 00457 ); 00458 } else { 00459 gtmridFKResponse = InternalSetTimer( 00460 NULL, 00461 nID, 00462 gFilterKeys.iRepeatMSec, 00463 xxxFKRepeatRateTimer, 00464 TMRF_RIT | TMRF_ONESHOT 00465 ); 00466 } 00467 // 00468 // gptmrFKAcceptanceDelay timer structure was reused so set handle to NULL. 00469 // 00470 gtmridFKAcceptanceDelay = 0; 00471 00472 return; 00473 00474 DBG_UNREFERENCED_PARAMETER(lParam); 00475 DBG_UNREFERENCED_PARAMETER(message); 00476 DBG_UNREFERENCED_PARAMETER(pwnd); 00477 } 00478 00479 /***************************************************************************\ 00480 * FilterKeys 00481 * 00482 * History: 00483 * 11 Feb 93 GregoryW Created. 00484 \***************************************************************************/ 00485 BOOL FilterKeys(PKE pKeyEvent, ULONG ExtraInformation, int NextProcIndex) 00486 { 00487 int fBreak; 00488 BYTE Vk; 00489 00490 CheckCritIn(); 00491 Vk = (BYTE)(pKeyEvent->usFlaggedVk & 0xff); 00492 fBreak = pKeyEvent->usFlaggedVk & KBDBREAK; 00493 00494 // 00495 // Check for Filter Keys hot key (right shift key). 00496 // 00497 if (Vk == VK_RSHIFT) { 00498 if (fBreak) { 00499 if (gtmridFKActivation != 0) { 00500 KILLRITTIMER(NULL, gtmridFKActivation); 00501 gtmridFKActivation = 0; 00502 } 00503 gFilterKeysState = FKIDLE; 00504 } else if (ONLYRIGHTSHIFTDOWN(gPhysModifierState)) { 00505 // 00506 // Verify that activation via hotkey is allowed. 00507 // 00508 if (TEST_ACCESSFLAG(FilterKeys, FKF_HOTKEYACTIVE)) { 00509 if ((gtmridFKActivation == 0) && (gFilterKeysState != FKMOUSEMOVE)) { 00510 gFilterKeysState = FKFIRSTWARNING; 00511 gtmridFKActivation = InternalSetTimer( 00512 NULL, 00513 0, 00514 FKFIRSTWARNINGTIME, 00515 FKActivationTimer, 00516 TMRF_RIT | TMRF_ONESHOT 00517 ); 00518 } 00519 } 00520 } 00521 } 00522 00523 // 00524 // If another key is pressed while the hot key is down, kill 00525 // the timer. 00526 // 00527 if ((Vk != VK_RSHIFT) && (gtmridFKActivation != 0)) { 00528 gFilterKeysState = FKIDLE; 00529 KILLRITTIMER(NULL, gtmridFKActivation); 00530 gtmridFKActivation = 0; 00531 } 00532 // 00533 // If Filter Keys not enabled send the key event on. 00534 // 00535 if (!TEST_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON)) { 00536 return TRUE; 00537 } 00538 00539 if (fBreak) { 00540 // 00541 // Kill the current timer and activate bounce key timer (if this is 00542 // a break of the last key down). 00543 // 00544 if (Vk == gLastVkDown) { 00545 KILLRITTIMER(NULL, gtmridFKResponse); 00546 gtmridFKResponse = 0; 00547 00548 gLastVkDown = 0; 00549 if (gtmridFKAcceptanceDelay != 0) { 00550 KILLRITTIMER(NULL, gtmridFKAcceptanceDelay); 00551 gtmridFKAcceptanceDelay = 0; 00552 if (!TEST_ACCF(ACCF_FKMAKECODEPROCESSED)) { 00553 // 00554 // This key was released before accepted. Don't pass on the 00555 // break. 00556 // 00557 return FALSE; 00558 } else { 00559 CLEAR_ACCF(ACCF_FKMAKECODEPROCESSED); 00560 } 00561 } 00562 00563 if (gFilterKeys.iBounceMSec) { 00564 gBounceVk = Vk; 00565 gtmridFKResponse = InternalSetTimer( 00566 NULL, 00567 0, 00568 gFilterKeys.iBounceMSec, 00569 FKBounceKeyTimer, 00570 TMRF_RIT | TMRF_ONESHOT 00571 ); 00572 if (TEST_ACCF(ACCF_IGNOREBREAKCODE)) { 00573 return FALSE; 00574 } 00575 } 00576 } 00577 } else { 00578 // 00579 // Make key processing 00580 // 00581 // First check to see if this is a typematic repeat. If so, we 00582 // can ignore this key event. Our timer will handle any repeats. 00583 // LastVkDown is cleared during processing of the break. 00584 // 00585 if (Vk == gLastVkDown) { 00586 return FALSE; 00587 } 00588 // 00589 // Remember current Virtual Key down for typematic repeat check. 00590 // 00591 gLastVkDown = Vk; 00592 00593 if (gBounceVk) { 00594 // 00595 // BounceKeys is active. If this is a make of the last 00596 // key pressed we ignore it. Only when the BounceKey 00597 // timer expires or another key is pressed will we accept 00598 // this key. 00599 // 00600 if (Vk == gBounceVk) { 00601 // 00602 // Ignore this make event and the subsequent break 00603 // code. BounceKey timer will be reset on break. 00604 // 00605 SET_ACCF(ACCF_IGNOREBREAKCODE); 00606 return FALSE; 00607 } else { 00608 // 00609 // We have a make of a new key. Kill the BounceKey 00610 // timer and clear gBounceVk. 00611 // 00612 UserAssert(gtmridFKResponse); 00613 if (gtmridFKResponse != 0) { 00614 KILLRITTIMER(NULL, gtmridFKResponse); 00615 gtmridFKResponse = 0; 00616 } 00617 gBounceVk = 0; 00618 } 00619 } 00620 CLEAR_ACCF(ACCF_IGNOREBREAKCODE); 00621 00622 // 00623 // Give audible feedback that key was pressed. 00624 // 00625 if (TEST_ACCESSFLAG(FilterKeys, FKF_CLICKON)) { 00626 PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm; 00627 PostRitSound( 00628 pTerm, 00629 RITSOUND_KEYCLICK); 00630 } 00631 00632 // 00633 // If gptmrFKAcceptanceDelay is non-NULL the previous key was 00634 // not held down long enough to be accepted. Kill the current 00635 // timer. A new timer will be started below for the key we're 00636 // processing now. 00637 // 00638 if (gtmridFKAcceptanceDelay != 0) { 00639 KILLRITTIMER(NULL, gtmridFKAcceptanceDelay); 00640 gtmridFKAcceptanceDelay = 0; 00641 } 00642 00643 // 00644 // If gptmrFKResponse is non-NULL a repeat rate timer is active 00645 // on the previous key. Kill the timer as we have a new make key. 00646 // 00647 if (gtmridFKResponse != 0) { 00648 KILLRITTIMER(NULL, gtmridFKResponse); 00649 gtmridFKResponse = 0; 00650 } 00651 00652 // 00653 // Save the current key event for later use if we process an 00654 // acceptance delay or key repeat. 00655 // 00656 *gpFKKeyEvent = *pKeyEvent; 00657 gFKExtraInformation = ExtraInformation; 00658 gFKNextProcIndex = NextProcIndex; 00659 00660 // 00661 // If there is an acceptance delay, set timer and ignore current 00662 // key event. When timer expires, saved key event will be sent. 00663 // 00664 if (gFilterKeys.iWaitMSec) { 00665 gtmridFKAcceptanceDelay = InternalSetTimer( 00666 NULL, 00667 0, 00668 gFilterKeys.iWaitMSec, 00669 xxxFKAcceptanceDelayTimer, 00670 TMRF_RIT | TMRF_ONESHOT 00671 ); 00672 CLEAR_ACCF(ACCF_FKMAKECODEPROCESSED); 00673 return FALSE; 00674 } 00675 // 00676 // No acceptance delay. Before sending this key event on the 00677 // timer routine must be set to either the delay until repeat value 00678 // or the repeat rate value. If repeat rate is 0 then ignore 00679 // delay until repeat. 00680 // 00681 if (!gFilterKeys.iRepeatMSec) { 00682 return TRUE; 00683 } 00684 00685 UserAssert(gtmridFKResponse == 0); 00686 if (gFilterKeys.iDelayMSec) { 00687 gtmridFKResponse = InternalSetTimer( 00688 NULL, 00689 0, 00690 gFilterKeys.iDelayMSec, 00691 xxxFKRepeatRateTimer, 00692 TMRF_RIT | TMRF_ONESHOT 00693 ); 00694 } else { 00695 gtmridFKResponse = InternalSetTimer( 00696 NULL, 00697 0, 00698 gFilterKeys.iRepeatMSec, 00699 xxxFKRepeatRateTimer, 00700 TMRF_RIT | TMRF_ONESHOT 00701 ); 00702 } 00703 } 00704 00705 return TRUE; 00706 } 00707 00708 /***************************************************************************\ 00709 * StopFilterKeysTimers 00710 * 00711 * Called from SystemParametersInfo on SPI_SETFILTERKEYS if FKF_FILTERKEYSON 00712 * is not set. Timers must be stopped if user turns FilterKeys off. 00713 * 00714 * History: 00715 * 18 Jul 94 GregoryW Created. 00716 \***************************************************************************/ 00717 VOID StopFilterKeysTimers(VOID) 00718 { 00719 00720 if (gtmridFKResponse != 0) { 00721 KILLRITTIMER(NULL, gtmridFKResponse); 00722 gtmridFKResponse = 0; 00723 } 00724 if (gtmridFKAcceptanceDelay) { 00725 KILLRITTIMER(NULL, gtmridFKAcceptanceDelay); 00726 gtmridFKAcceptanceDelay = 0; 00727 } 00728 gLastVkDown = 0; 00729 gBounceVk = 0; 00730 } 00731 00732 /***************************************************************************\ 00733 * xxxStickyKeys 00734 * 00735 * History: 00736 * 11 Feb 93 GregoryW Created. 00737 \***************************************************************************/ 00738 BOOL xxxStickyKeys(PKE pKeyEvent, ULONG ExtraInformation, int NextProcIndex) 00739 { 00740 int fBreak; 00741 BYTE NewLockBits, NewLatchBits; 00742 int BitPositions; 00743 BOOL bChange; 00744 PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm; 00745 00746 00747 CheckCritIn(); 00748 fBreak = pKeyEvent->usFlaggedVk & KBDBREAK; 00749 00750 if (gCurrentModifierBit) { 00751 // 00752 // Process modifier key 00753 // 00754 00755 // 00756 // One method of activating StickyKeys is to press either the 00757 // left shift key or the right shift key five times without 00758 // pressing any other keys. We don't want the typematic shift 00759 // (make code) to enable/disable StickyKeys so we perform a 00760 // special test for them. 00761 // 00762 if (!fBreak) { 00763 if (gCurrentModifierBit & gPrevModifierState) { 00764 // 00765 // This is a typematic make of a modifier key. Don't do 00766 // any further processing. Just pass it along. 00767 // 00768 gPrevModifierState = gPhysModifierState; 00769 return TRUE; 00770 } 00771 } 00772 00773 gPrevModifierState = gPhysModifierState; 00774 00775 if (LEFTSHIFTKEY(pKeyEvent->usFlaggedVk) && 00776 ((gPhysModifierState & ~gCurrentModifierBit) == 0)) { 00777 gStickyKeysLeftShiftCount++; 00778 } else { 00779 gStickyKeysLeftShiftCount = 0; 00780 } 00781 if (RIGHTSHIFTKEY(pKeyEvent->usFlaggedVk) && 00782 ((gPhysModifierState & ~gCurrentModifierBit) == 0)) { 00783 gStickyKeysRightShiftCount++; 00784 } else { 00785 gStickyKeysRightShiftCount = 0; 00786 } 00787 00788 // 00789 // Check to see if StickyKeys should be toggled on/off 00790 // 00791 if ((gStickyKeysLeftShiftCount == (TOGGLE_STICKYKEYS_COUNT * 2)) || 00792 (gStickyKeysRightShiftCount == (TOGGLE_STICKYKEYS_COUNT * 2))) { 00793 if (TEST_ACCESSFLAG(StickyKeys, SKF_HOTKEYACTIVE)) { 00794 if (TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON)) { 00795 xxxTurnOffStickyKeys(); 00796 if (TEST_ACCESSFLAG(StickyKeys, SKF_HOTKEYSOUND)) { 00797 PostRitSound( 00798 pTerm, 00799 RITSOUND_DOWNSIREN); 00800 } 00801 } else { 00802 if (TEST_ACCESSFLAG(StickyKeys, SKF_HOTKEYSOUND)) { 00803 PostRitSound( 00804 pTerm, 00805 RITSOUND_UPSIREN); 00806 } 00807 // To make the notification window get the focus 00808 // The same is done other places where WM_LOGONNOTIFY message is 00809 // sent : a-anilk 00810 PostAccessNotification(ACCESS_STICKYKEYS); 00811 00812 } 00813 } 00814 gStickyKeysLeftShiftCount = 0; 00815 gStickyKeysRightShiftCount = 0; 00816 return TRUE; 00817 } 00818 00819 // 00820 // If StickyKeys is enabled process the modifier key, otherwise 00821 // just pass on the modifier key. 00822 // 00823 if (TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON)) { 00824 if (fBreak) { 00825 // 00826 // If either locked or latched bit set for this key then 00827 // don't pass the break on. 00828 // 00829 if (UNION(gLatchBits, gLockBits) & gCurrentModifierBit) { 00830 return FALSE; 00831 } else { 00832 return TRUE; 00833 } 00834 } else{ 00835 if (gPhysModifierState != gCurrentModifierBit) { 00836 // 00837 // More than one modifier key down at the same time. 00838 // This condition may signal sticky keys to turn off. 00839 // The routine xxxTwoKeysDown will return the new value 00840 // of fStickyKeysOn. If sticky keys is turned off 00841 // (return value 0), the key event should be passed 00842 // on without further processing here. 00843 // 00844 if (!xxxTwoKeysDown(NextProcIndex)) { 00845 return TRUE; 00846 } 00847 00848 // 00849 // Modifier states were set to physical state by 00850 // xxxTwoKeysDown. The modifier keys currently in 00851 // the down position will be latched by updating 00852 // gLatchBits. No more processing for this key 00853 // event is needed. 00854 // 00855 bChange = gLockBits || 00856 (gLatchBits != gPhysModifierState); 00857 gLatchBits = gPhysModifierState; 00858 gLockBits = 0; 00859 if (bChange) { 00860 PostAccessibility( ACCESS_STICKYKEYS ); 00861 } 00862 00863 // 00864 // Provide sound feedback, if enabled, before returning. 00865 // 00866 if (TEST_ACCESSFLAG(StickyKeys, SKF_AUDIBLEFEEDBACK)) { 00867 PostRitSound( 00868 pTerm, 00869 RITSOUND_LOWBEEP); 00870 PostRitSound( 00871 pTerm, 00872 RITSOUND_HIGHBEEP); 00873 } 00874 return FALSE; 00875 } 00876 // 00877 // Figure out which bits (Shift, Ctrl or Alt key bits) to 00878 // examine. Also set up default values for NewLatchBits 00879 // and NewLockBits in case they're not set later. 00880 // 00881 // See the depiction of the bit pattern in KeyboardApcProcedure. 00882 // 00883 // Bit 0 -- L SHIFT 00884 // Bit 1 -- R SHIFT 00885 // Bit 2 -- L CTL 00886 // Bit 3 -- R CTL 00887 // Bit 4 -- L ALT 00888 // Bit 5 -- R RLT 00889 // Bit 6 -- L WIN 00890 // Bit 7 -- R WIN 00891 switch(pKeyEvent->usFlaggedVk) { 00892 case VK_LSHIFT: 00893 case VK_RSHIFT: 00894 BitPositions = 0x3; 00895 break; 00896 case VK_LCONTROL: 00897 case VK_RCONTROL: 00898 BitPositions = 0xc; 00899 break; 00900 case VK_LMENU: 00901 case VK_RMENU: 00902 BitPositions = 0x30; 00903 break; 00904 case VK_LWIN: 00905 case VK_RWIN: 00906 BitPositions = 0xc0; 00907 break; 00908 } 00909 NewLatchBits = gLatchBits; 00910 NewLockBits = gLockBits; 00911 00912 // 00913 // If either left or right modifier is locked clear latched 00914 // and locked states and send appropriate break/make messages. 00915 // 00916 if (gLockBits & BitPositions) { 00917 NewLockBits = gLockBits & ~BitPositions; 00918 NewLatchBits = gLatchBits & ~BitPositions; 00919 xxxUpdateModifierState( 00920 NewLockBits | NewLatchBits | gCurrentModifierBit, 00921 NextProcIndex 00922 ); 00923 } else { 00924 // 00925 // If specific lock bit (left or right) not 00926 // previously set then toggle latch bits. 00927 // 00928 if (!(gLockBits & gCurrentModifierBit)) { 00929 NewLatchBits = gLatchBits ^ gCurrentModifierBit; 00930 } 00931 // 00932 // If locked mode (tri-state) enabled then if latch or lock 00933 // bit previously set, toggle lock bit. 00934 // 00935 if (TEST_ACCESSFLAG(StickyKeys, SKF_TRISTATE)) { 00936 if (UNION(gLockBits, gLatchBits) & gCurrentModifierBit) { 00937 NewLockBits = gLockBits ^ gCurrentModifierBit; 00938 } 00939 } 00940 } 00941 00942 // 00943 // Update globals 00944 // 00945 bChange = ((gLatchBits != NewLatchBits) || 00946 (gLockBits != NewLockBits)); 00947 00948 gLatchBits = NewLatchBits; 00949 gLockBits = NewLockBits; 00950 00951 if (bChange) { 00952 PostAccessibility( ACCESS_STICKYKEYS ); 00953 } 00954 // 00955 // Now provide sound feedback if enabled. For the transition 00956 // to LATCH mode issue a low beep then a high beep. For the 00957 // transition to LOCKED mode issue a high beep. For the 00958 // transition out of LOCKED mode (or LATCH mode if tri-state 00959 // not enabled) issue a low beep. 00960 // 00961 if (TEST_ACCESSFLAG(StickyKeys, SKF_AUDIBLEFEEDBACK)) { 00962 if (!(gLockBits & gCurrentModifierBit)) { 00963 PostRitSound( 00964 pTerm, 00965 RITSOUND_LOWBEEP); 00966 } 00967 if ((gLatchBits | gLockBits) & gCurrentModifierBit) { 00968 PostRitSound( 00969 pTerm, 00970 RITSOUND_HIGHBEEP); 00971 } 00972 } 00973 // 00974 // Pass key on if shift bit is set (e.g., if transitioning 00975 // from shift to lock mode don't pass on make). 00976 // 00977 if (gLatchBits & gCurrentModifierBit) { 00978 return TRUE; 00979 } else { 00980 return FALSE; 00981 } 00982 00983 } 00984 } 00985 } else { 00986 // 00987 // Non-shift key processing here... 00988 // 00989 gStickyKeysLeftShiftCount = 0; 00990 gStickyKeysRightShiftCount = 0; 00991 if (!TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON)) { 00992 return TRUE; 00993 } 00994 00995 // 00996 // If no modifier keys are down, or this is a break, pass the key event 00997 // on and clear any latch states. 00998 // 00999 if (!gPhysModifierState || fBreak) { 01000 if (AccessProceduresStream(pKeyEvent, ExtraInformation, NextProcIndex)) { 01001 xxxProcessKeyEvent(pKeyEvent, ExtraInformation, FALSE); 01002 } 01003 xxxUpdateModifierState(gLockBits, NextProcIndex); 01004 01005 bChange = gLatchBits != 0; 01006 gLatchBits = 0; 01007 if (bChange) { 01008 01009 PostAccessibility( ACCESS_STICKYKEYS ); 01010 } 01011 return FALSE; 01012 } else { 01013 // 01014 // This is a make of a non-modifier key and there is a modifier key 01015 // down. Update the states and pass the key event on. 01016 // 01017 xxxTwoKeysDown(NextProcIndex); 01018 return TRUE; 01019 } 01020 } 01021 01022 return TRUE; 01023 } 01024 01025 /***************************************************************************\ 01026 * xxxUpdateModifierState 01027 * 01028 * Starting from the current modifier keys state, send the necessary key 01029 * events (make or break) to end up with the NewModifierState passed in. 01030 * 01031 * Return value: 01032 * None. 01033 * 01034 * History: 01035 * 11 Feb 93 GregoryW Created. 01036 \***************************************************************************/ 01037 VOID xxxUpdateModifierState(int NewModifierState, int NextProcIndex) 01038 { 01039 KE ke; 01040 int CurrentModState; 01041 int CurrentModBit, NewModBit; 01042 int i; 01043 01044 CheckCritIn(); 01045 01046 CurrentModState = gLockBits | gLatchBits; 01047 01048 for (i = 0; i < ARRAY_SIZE(aModBit); i++) { 01049 CurrentModBit = CurrentModState & aModBit[i].BitPosition; 01050 NewModBit = NewModifierState & aModBit[i].BitPosition; 01051 if (CurrentModBit != NewModBit) { 01052 ke.bScanCode = (BYTE)aModBit[i].ScanCode; 01053 ke.usFlaggedVk = aModBit[i].Vk; 01054 if (CurrentModBit) { // if it's currently on, send break 01055 ke.usFlaggedVk |= KBDBREAK; 01056 } 01057 if (AccessProceduresStream(&ke, 0L, NextProcIndex)) { 01058 xxxProcessKeyEvent(&ke, 0L, FALSE); 01059 } 01060 } 01061 } 01062 } 01063 01064 /***************************************************************************\ 01065 * xxxTurnOffStickyKeys 01066 * 01067 * The user either pressed the appropriate key sequence or used the 01068 * access utility to turn StickyKeys off. Update modifier states and 01069 * reset globals. 01070 * 01071 * Return value: 01072 * None. 01073 * 01074 * History: 01075 * 11 Feb 93 GregoryW Created. 01076 \***************************************************************************/ 01077 VOID xxxTurnOffStickyKeys(VOID) 01078 { 01079 INT index; 01080 01081 CheckCritIn(); 01082 01083 for (index = 0; index < ARRAY_SIZE(aAccessibilityProc); index++) { 01084 if (aAccessibilityProc[index] == xxxStickyKeys) { 01085 01086 xxxUpdateModifierState(gPhysModifierState, index+1); 01087 gLockBits = gLatchBits = 0; 01088 CLEAR_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON); 01089 01090 PostAccessibility( ACCESS_STICKYKEYS ); 01091 break; 01092 } 01093 } 01094 } 01095 01096 /***************************************************************************\ 01097 * xxxUnlatchStickyKeys 01098 * 01099 * This routine releases any sticky keys that are latched. This routine 01100 * is called during mouse up event processing. 01101 * 01102 * Return value: 01103 * None. 01104 * 01105 * History: 01106 * 21 Jun 93 GregoryW Created. 01107 \***************************************************************************/ 01108 VOID xxxUnlatchStickyKeys(VOID) 01109 { 01110 INT index; 01111 BOOL bChange; 01112 01113 if (!gLatchBits) { 01114 return; 01115 } 01116 01117 for (index = 0; index < ARRAY_SIZE(aAccessibilityProc); index++) { 01118 if (aAccessibilityProc[index] == xxxStickyKeys) { 01119 xxxUpdateModifierState(gLockBits, index+1); 01120 bChange = gLatchBits != 0; 01121 gLatchBits = 0; 01122 01123 if (bChange) { 01124 01125 PostAccessibility( ACCESS_STICKYKEYS ); 01126 } 01127 break; 01128 } 01129 } 01130 } 01131 01132 01133 /***************************************************************************\ 01134 * xxxHardwareMouseKeyUp 01135 * 01136 * This routine is called during a mouse button up event. If MouseKeys is 01137 * on and the button up event corresponds to a mouse key that's locked down, 01138 * the mouse key must be released. 01139 * 01140 * If StickyKeys is on, all latched keys are released. 01141 * 01142 * Return value: 01143 * None. 01144 * 01145 * History: 01146 * 17 Jun 94 GregoryW Created. 01147 \***************************************************************************/ 01148 01149 VOID xxxHardwareMouseKeyUp(DWORD dwButton) 01150 { 01151 CheckCritIn(); 01152 01153 if (TEST_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON)) { 01154 gwMKButtonState &= ~dwButton; 01155 } 01156 01157 // Not required to post a setting change 01158 //PostAccessibility( SPI_SETMOUSEKEYS ); 01159 01160 if (TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON)) { 01161 xxxUnlatchStickyKeys(); 01162 } 01163 } 01164 01165 01166 /***************************************************************************\ 01167 * xxxTwoKeysDown 01168 * 01169 * Two keys are down simultaneously. Check to see if StickyKeys should be 01170 * turned off. In all cases update the modifier key state to reflect the 01171 * physical key state and clear latched and locked modes. 01172 * 01173 * Return value: 01174 * 1 if StickyKeys is enabled. 01175 * 0 if StickyKeys is disabled. 01176 * 01177 * History: 01178 * 11 Feb 93 GregoryW Created. 01179 \***************************************************************************/ 01180 BOOL xxxTwoKeysDown(int NextProcIndex) 01181 { 01182 PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm; 01183 01184 if (TEST_ACCESSFLAG(StickyKeys, SKF_TWOKEYSOFF)) { 01185 CLEAR_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON); 01186 if (TEST_ACCESSFLAG(StickyKeys, SKF_HOTKEYSOUND)) { 01187 PostRitSound( 01188 pTerm, 01189 RITSOUND_DOWNSIREN); 01190 } 01191 gStickyKeysLeftShiftCount = 0; 01192 gStickyKeysRightShiftCount = 0; 01193 } 01194 xxxUpdateModifierState(gPhysModifierState, NextProcIndex); 01195 gLockBits = gLatchBits = 0; 01196 01197 PostAccessibility( ACCESS_STICKYKEYS ); 01198 01199 return TEST_BOOL_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON); 01200 } 01201 01202 /***************************************************************************\ 01203 * SetGlobalCursorLevel 01204 * 01205 * Set the cursor level of all threads running on the visible 01206 * windowstation. 01207 * 01208 * History: 01209 * 04-17-95 JimA Created. 01210 \***************************************************************************/ 01211 01212 VOID SetGlobalCursorLevel( 01213 INT iCursorLevel) 01214 { 01215 01216 /* 01217 * LATER 01218 * We have other code which assumes that the 01219 * iCursorLevel of a queue is the sum of the iCursorLevel values for the 01220 * threads attached to the queue. But this code, if you set iCursorLevel to 01221 * -1 (to indicate no mouse) will set the queue iCursorLevel to -1, no matter 01222 * how many threads are attached to the queue. This needs to be revisited. 01223 * See the function AttachToQueue. 01224 * FritzS 01225 */ 01226 01227 01228 PDESKTOP pdesk; 01229 PTHREADINFO pti; 01230 PLIST_ENTRY pHead, pEntry; 01231 01232 TAGMSG1(DBGTAG_PNP, "SetGlobalCursorLevel %x", iCursorLevel); 01233 01234 if (grpdeskRitInput) { 01235 for (pdesk = grpdeskRitInput->rpwinstaParent->rpdeskList; 01236 pdesk != NULL; pdesk = pdesk->rpdeskNext) { 01237 01238 pHead = &pdesk->PtiList; 01239 for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink) { 01240 pti = CONTAINING_RECORD(pEntry, THREADINFO, PtiLink); 01241 01242 pti->iCursorLevel = iCursorLevel; 01243 pti->pq->iCursorLevel = iCursorLevel; 01244 } 01245 } 01246 } 01247 01248 /* 01249 * CSRSS doesn't seem to be on the list, so fix it up now. 01250 */ 01251 for (pti = PpiFromProcess(gpepCSRSS)->ptiList; 01252 pti != NULL; pti = pti->ptiSibling) { 01253 if (pti->iCursorLevel != iCursorLevel) { 01254 TAGMSG3(DBGTAG_PNP, "pti %#p has cursorlevel %x, should be %x", 01255 pti, pti->iCursorLevel, iCursorLevel); 01256 } 01257 if (pti->pq->iCursorLevel != iCursorLevel) { 01258 TAGMSG4(DBGTAG_PNP, "pti->pq %#p->%#p has cursorlevel %x, should be %x", 01259 pti, pti->pq, pti->pq->iCursorLevel, iCursorLevel); 01260 } 01261 pti->iCursorLevel = iCursorLevel; 01262 pti->pq->iCursorLevel = iCursorLevel; 01263 } 01264 } 01265 01266 /***************************************************************************\ 01267 * MKShowMouseCursor 01268 * 01269 * If no hardware mouse is installed and MouseKeys is enabled, we need 01270 * to fix up the system metrics, the oem information and the queue 01271 * information. The mouse cursor then gets displayed. 01272 * 01273 * Return value: 01274 * None. 01275 * 01276 * History: 01277 * 11 Feb 93 GregoryW Created. 01278 \***************************************************************************/ 01279 VOID MKShowMouseCursor() 01280 { 01281 TAGMSG1(DBGTAG_PNP, "MKShowMouseCursor (gpDeviceInfoList == %#p)", gpDeviceInfoList); 01282 01283 // 01284 // If TEST_GTERMF(GTERMF_MOUSE) is TRUE then we either have a hardware mouse 01285 // or we're already pretending a mouse is installed. In either case, 01286 // there's nothing to do so just return. 01287 // 01288 if (TEST_GTERMF(GTERMF_MOUSE)) { 01289 TAGMSG0(DBGTAG_PNP, "MKShowMouseCursor just returns"); 01290 return; 01291 } 01292 01293 SET_GTERMF(GTERMF_MOUSE); 01294 SET_ACCF(ACCF_MKVIRTUALMOUSE); 01295 SYSMET(MOUSEPRESENT) = TRUE; 01296 SYSMET(CMOUSEBUTTONS) = 2; 01297 /* 01298 * HACK: CreateQueue() uses oemInfo.fMouse to determine if a mouse is 01299 * present and thus whether to set the iCursorLevel field in the 01300 * THREADINFO structure to 0 or -1. Unfortunately some queues have 01301 * already been created at this point. Since oemInfo.fMouse is 01302 * initialized to FALSE, we need to go back through any queues already 01303 * around and set their iCursorLevel field to the correct value when 01304 * mousekeys is enabled. 01305 */ 01306 SetGlobalCursorLevel(0); 01307 } 01308 01309 /***************************************************************************\ 01310 * MKHideMouseCursor 01311 * 01312 * If no hardware mouse is installed and MouseKeys is disabled, we need 01313 * to fix up the system metrics, the oem information and the queue 01314 * information. The mouse cursor then disappears. 01315 * 01316 * Return value: 01317 * None. 01318 * 01319 * History: 01320 * 11 Feb 93 GregoryW Created. 01321 \***************************************************************************/ 01322 VOID MKHideMouseCursor() 01323 { 01324 TAGMSG1(DBGTAG_PNP, "MKHideMouseCursor (gpDeviceInfoList == %#p)", gpDeviceInfoList); 01325 01326 // 01327 // If a hardware mouse is present we don't need to do anything. 01328 // 01329 if (!TEST_ACCF(ACCF_MKVIRTUALMOUSE)) { 01330 return; 01331 } 01332 01333 CLEAR_ACCF(ACCF_MKVIRTUALMOUSE); 01334 CLEAR_GTERMF(GTERMF_MOUSE); 01335 SYSMET(MOUSEPRESENT) = FALSE; 01336 SYSMET(CMOUSEBUTTONS) = 0; 01337 01338 SetGlobalCursorLevel(-1); 01339 } 01340 01341 /***************************************************************************\ 01342 * xxxMKToggleMouseKeys 01343 * 01344 * This routine is called when the NumLock key is pressed and MouseKeys is 01345 * active. If the left shift key and the left alt key are down then MouseKeys 01346 * is turned off. If just the NumLock key is pressed then we toggle between 01347 * MouseKeys active and the state of the number pad before MouseKeys was 01348 * activated. 01349 * 01350 * Return value: 01351 * TRUE - key should be passed on in the input stream. 01352 * FALSE - key should not be passed on. 01353 * 01354 * History: 01355 \***************************************************************************/ 01356 BOOL xxxMKToggleMouseKeys(USHORT NotUsed) 01357 { 01358 BOOL bRetVal = TRUE; 01359 BOOL bNewPassThrough; 01360 PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm; 01361 01362 01363 // 01364 // If this is a typematic repeat of NumLock we just pass it on. 01365 // 01366 if (TEST_ACCF(ACCF_MKREPEATVK)) { 01367 return bRetVal; 01368 } 01369 // 01370 // This is a make of NumLock. Check for disable sequence. 01371 // 01372 if ((gLockBits | gLatchBits | gPhysModifierState) == MOUSEKEYMODBITS) { 01373 if (TEST_ACCESSFLAG(MouseKeys, MKF_HOTKEYACTIVE)) { 01374 if (!gbMKMouseMode) { 01375 // 01376 // User wants to turn MouseKeys off. If we're currently in 01377 // pass through mode then the NumLock key is in the same state 01378 // (on or off) as it was when the user invoked MouseKeys. We 01379 // want to leave it in that state, so don't pass the NumLock 01380 // key on. 01381 // 01382 bRetVal = FALSE; 01383 } 01384 TurnOffMouseKeys(); 01385 } 01386 return bRetVal; 01387 } 01388 /* 01389 * This is a NumLock with no modifiers. Toggle current state and 01390 * provide audible feedback. 01391 * 01392 * Note -- this test is the reverse of other ones because it tests the 01393 * state of VK_NUMLOCK before the keypress flips the state of NUMLOCK. 01394 * So the code checks for what the state will be. 01395 */ 01396 bNewPassThrough = 01397 #ifdef FE_SB // MouseKeys() 01398 (TestAsyncKeyStateToggle(gNumLockVk) != 0) ^ 01399 #else // FE_SB 01400 (TestAsyncKeyStateToggle(VK_NUMLOCK) != 0) ^ 01401 #endif // FE_SB 01402 (TEST_ACCESSFLAG(MouseKeys, MKF_REPLACENUMBERS) != 0); 01403 01404 01405 if (!bNewPassThrough) { 01406 gbMKMouseMode = TRUE; 01407 PostRitSound( 01408 pTerm, 01409 RITSOUND_HIGHBEEP); 01410 } else { 01411 WORD SaveCurrentActiveButton; 01412 // 01413 // User wants keys to be passed on. Release all buttons currently 01414 // down. 01415 // 01416 gbMKMouseMode = FALSE; 01417 PostRitSound( 01418 pTerm, 01419 RITSOUND_LOWBEEP); 01420 SaveCurrentActiveButton = gwMKCurrentButton; 01421 gwMKCurrentButton = MOUSE_BUTTON_LEFT | MOUSE_BUTTON_RIGHT; 01422 xxxMKButtonSetState(TRUE); 01423 gwMKCurrentButton = SaveCurrentActiveButton; 01424 } 01425 01426 PostAccessibility( ACCESS_MOUSEKEYS ); 01427 01428 return bRetVal; 01429 01430 01431 DBG_UNREFERENCED_PARAMETER(NotUsed); 01432 } 01433 01434 /***************************************************************************\ 01435 * xxxMKButtonClick 01436 * 01437 * Click the active mouse button. 01438 * 01439 * Return value: 01440 * Always FALSE - key should not be passed on. 01441 * 01442 * History: 01443 \***************************************************************************/ 01444 BOOL xxxMKButtonClick(USHORT NotUsed) 01445 { 01446 // 01447 // The button click only happens on initial make of key. If this is a 01448 // typematic repeat we just ignore it. 01449 // 01450 if (TEST_ACCF(ACCF_MKREPEATVK)) { 01451 return FALSE; 01452 } 01453 // 01454 // Ensure active button is UP before the click 01455 // 01456 xxxMKButtonSetState(TRUE); 01457 // 01458 // Now push the button DOWN 01459 // 01460 xxxMKButtonSetState(FALSE); 01461 // 01462 // Now release the button 01463 // 01464 xxxMKButtonSetState(TRUE); 01465 01466 return FALSE; 01467 01468 01469 UNREFERENCED_PARAMETER(NotUsed); 01470 } 01471 01472 01473 /***************************************************************************\ 01474 * xxxMKMoveConstCursorTimer 01475 * 01476 * Timer routine that handles constant speed mouse movement. This routine 01477 * is called 20 times per second and uses information from 01478 * gMouseCursor.bConstantTable[] to determine how many pixels to move the 01479 * mouse cursor on each tick. 01480 * 01481 * Return value: 01482 * None. 01483 * 01484 * History: 01485 \***************************************************************************/ 01486 VOID xxxMKMoveConstCursorTimer(PWND pwnd, UINT message, UINT_PTR nID, LPARAM lParam) 01487 { 01488 LONG MovePixels; 01489 01490 CheckCritIn(); 01491 01492 if (TEST_ACCESSFLAG(MouseKeys, MKF_MODIFIERS)) { 01493 if ((gLockBits | gLatchBits | gPhysModifierState) & LRSHIFT) { 01494 MovePixels = 1; 01495 goto MoveIt; 01496 } 01497 if ((gLockBits | gLatchBits | gPhysModifierState) & LRCONTROL) { 01498 MovePixels = gMouseCursor.bConstantTable[0] * MK_CONTROL_SPEED; 01499 goto MoveIt; 01500 } 01501 } 01502 01503 giMouseMoveTable %= gMouseCursor.bConstantTableLen; 01504 01505 MovePixels = gMouseCursor.bConstantTable[giMouseMoveTable++]; 01506 01507 if (MovePixels == 0) { 01508 return; 01509 } 01510 01511 MoveIt: 01512 // 01513 // We're inside the critical section - leave before calling MoveEvent. 01514 // Set gbMouseMoved to TRUE so RawInputThread wakes up the appropriate 01515 // user thread (if any) to receive this event. 01516 // 01517 LeaveCrit(); 01518 01519 xxxMoveEvent(MovePixels * gMKDeltaX, MovePixels * gMKDeltaY, 0, 0, 0, FALSE); 01520 QueueMouseEvent(0, 0, 0, gptCursorAsync, NtGetTickCount(), FALSE, TRUE); 01521 EnterCrit(); 01522 return; 01523 01524 01525 UNREFERENCED_PARAMETER(pwnd); 01526 UNREFERENCED_PARAMETER(lParam); 01527 UNREFERENCED_PARAMETER(nID); 01528 UNREFERENCED_PARAMETER(message); 01529 } 01530 01531 /***************************************************************************\ 01532 * xxxMKMoveAccelCursorTimer 01533 * 01534 * Timer routine that handles mouse acceleration. It gets called 20 times 01535 * per second and uses information from gMouseCursor.bAccelTable[] to determine 01536 * how many pixels to move the mouse cursor on each tick. 01537 * 01538 * Return value: 01539 * None. 01540 * 01541 * History: 01542 \***************************************************************************/ 01543 VOID xxxMKMoveAccelCursorTimer(PWND pwnd, UINT message, UINT_PTR nID, LPARAM lParam) 01544 { 01545 LONG MovePixels; 01546 01547 CheckCritIn(); 01548 01549 if (TEST_ACCESSFLAG(MouseKeys, MKF_MODIFIERS)) { 01550 if ((gLockBits | gLatchBits | gPhysModifierState) & LRSHIFT) { 01551 MovePixels = 1; 01552 goto MoveIt; 01553 } 01554 if ((gLockBits | gLatchBits | gPhysModifierState) & LRCONTROL) { 01555 MovePixels = gMouseCursor.bConstantTable[0] * MK_CONTROL_SPEED; 01556 goto MoveIt; 01557 } 01558 } 01559 01560 if (giMouseMoveTable < gMouseCursor.bAccelTableLen) { 01561 MovePixels = gMouseCursor.bAccelTable[giMouseMoveTable++]; 01562 } else { 01563 // 01564 // We've reached maximum cruising speed. Switch to constant table. 01565 // 01566 MovePixels = gMouseCursor.bConstantTable[0]; 01567 giMouseMoveTable = 1; 01568 gtmridMKMoveCursor = InternalSetTimer( 01569 NULL, 01570 gtmridMKMoveCursor, 01571 MOUSETIMERRATE, 01572 xxxMKMoveConstCursorTimer, 01573 TMRF_RIT 01574 ); 01575 01576 } 01577 if (MovePixels == 0) { 01578 return; 01579 } 01580 01581 MoveIt: 01582 // 01583 // We're inside the critical section - leave before calling xxxMoveEvent. 01584 // Set gbMouseMoved to TRUE so RawInputThread wakes up the appropriate 01585 // user thread (if any) to receive this event. 01586 // 01587 LeaveCrit(); 01588 xxxMoveEvent(MovePixels * gMKDeltaX, MovePixels * gMKDeltaY, 0, 0, 0, FALSE); 01589 QueueMouseEvent(0, 0, 0, gptCursorAsync, NtGetTickCount(), FALSE, TRUE); 01590 01591 EnterCrit(); 01592 01593 return; 01594 01595 UNREFERENCED_PARAMETER(pwnd); 01596 UNREFERENCED_PARAMETER(message); 01597 UNREFERENCED_PARAMETER(nID); 01598 UNREFERENCED_PARAMETER(lParam); 01599 } 01600 01601 /***************************************************************************\ 01602 * xxxMKMouseMove 01603 * 01604 * Send a mouse move event. A timer routine is set to handle the mouse 01605 * cursor acceleration. The timer will be set on the first make of a 01606 * mouse move key if FilterKeys repeat rate is OFF. Otherwise, the timer 01607 * is set on the first repeat (typematic make) of the mouse move key. 01608 * Once the timer is set the timer routine handles all mouse movement 01609 * until the key is released or a new key is pressed. 01610 * 01611 * Return value: 01612 * Always FALSE - key should not be passed on. 01613 * 01614 * History: 01615 \***************************************************************************/ 01616 BOOL xxxMKMouseMove(USHORT Data) 01617 { 01618 01619 01620 /* 01621 * Let the mouse acceleration timer routine handle repeats. 01622 */ 01623 if (TEST_ACCF(ACCF_MKREPEATVK) && (gtmridMKMoveCursor != 0)) { 01624 return FALSE; 01625 } 01626 01627 01628 gMKDeltaX = (LONG)((CHAR)LOBYTE(Data)); // Force sign extension 01629 gMKDeltaY = (LONG)((CHAR)HIBYTE(Data)); // Force sign extension 01630 01631 LeaveCrit(); 01632 01633 if ((TEST_ACCESSFLAG(MouseKeys, MKF_MODIFIERS) && ((gLockBits | gLatchBits | gPhysModifierState) & LRCONTROL))) { 01634 xxxMoveEvent(gMKDeltaX * MK_CONTROL_SPEED * gMouseCursor.bConstantTable[0], gMKDeltaY * MK_CONTROL_SPEED * gMouseCursor.bConstantTable[0], 0, 0, 0, FALSE); 01635 } else { 01636 xxxMoveEvent(gMKDeltaX, gMKDeltaY, 0, 0, 0, FALSE); 01637 } 01638 01639 QueueMouseEvent(0, 0, 0, gptCursorAsync, NtGetTickCount(), FALSE, TRUE); 01640 01641 EnterCrit(); 01642 01643 /* 01644 * If the repeat rate is zero we'll start the mouse acceleration 01645 * immediately. Otherwise we wait until after the first repeat 01646 * of the mouse movement key. 01647 */ 01648 if (!gFilterKeys.iRepeatMSec || TEST_ACCF(ACCF_MKREPEATVK)) { 01649 giMouseMoveTable = 0; 01650 gtmridMKMoveCursor = InternalSetTimer( 01651 NULL, 01652 gtmridMKMoveCursor, 01653 MOUSETIMERRATE, 01654 (gMouseCursor.bAccelTableLen) ? 01655 xxxMKMoveAccelCursorTimer : 01656 xxxMKMoveConstCursorTimer, 01657 TMRF_RIT 01658 ); 01659 } 01660 return FALSE; 01661 } 01662 01663 /***************************************************************************\ 01664 * xxxMKButtonSetState 01665 * 01666 * Set the active mouse button(s) to the state specified by fButtonUp 01667 * (if fButtonUp is TRUE then the button is released, o.w. the button 01668 * is pressed). 01669 * 01670 * Return value: 01671 * Always FALSE - key should not be passed on. 01672 * 01673 * History: 01674 \***************************************************************************/ 01675 BOOL xxxMKButtonSetState(USHORT fButtonUp) 01676 { 01677 WORD NewButtonState; 01678 01679 CheckCritIn(); 01680 if (fButtonUp) { 01681 NewButtonState = gwMKButtonState & ~gwMKCurrentButton; 01682 } else { 01683 NewButtonState = gwMKButtonState | gwMKCurrentButton; 01684 } 01685 01686 if ((NewButtonState & MOUSE_BUTTON_LEFT) != (gwMKButtonState & MOUSE_BUTTON_LEFT)) { 01687 xxxButtonEvent(MOUSE_BUTTON_LEFT, 01688 gptCursorAsync, 01689 fButtonUp, 01690 NtGetTickCount(), 01691 0L, 01692 FALSE, 01693 FALSE); 01694 } 01695 if ((NewButtonState & MOUSE_BUTTON_RIGHT) != (gwMKButtonState & MOUSE_BUTTON_RIGHT)) { 01696 xxxButtonEvent(MOUSE_BUTTON_RIGHT, 01697 gptCursorAsync, 01698 fButtonUp, 01699 NtGetTickCount(), 01700 0L, 01701 FALSE, 01702 FALSE); 01703 } 01704 gwMKButtonState = NewButtonState; 01705 01706 PostAccessibility( ACCESS_MOUSEKEYS ); 01707 01708 return FALSE; 01709 } 01710 01711 /***************************************************************************\ 01712 * MKButtonSelect 01713 * 01714 * Mark ThisButton as the active mouse button. It's possible to select both 01715 * the left and right mouse buttons as active simultaneously. 01716 * 01717 * Return value: 01718 * Always FALSE - key should not be passed on. 01719 * 01720 * History: 01721 \***************************************************************************/ 01722 BOOL MKButtonSelect(WORD ThisButton) 01723 { 01724 gwMKCurrentButton = ThisButton; 01725 01726 PostAccessibility( ACCESS_MOUSEKEYS ); 01727 return FALSE; 01728 } 01729 01730 /***************************************************************************\ 01731 * xxxMKButtonDoubleClick 01732 * 01733 * Double click the active mouse button. 01734 * 01735 * Return value: 01736 * Always FALSE - key should not be passed on. 01737 * 01738 * History: 01739 \***************************************************************************/ 01740 BOOL xxxMKButtonDoubleClick(USHORT NotUsed) 01741 { 01742 xxxMKButtonClick(0); 01743 xxxMKButtonClick(0); 01744 return FALSE; 01745 01746 UNREFERENCED_PARAMETER(NotUsed); 01747 } 01748 01749 BOOL HighContrastHotKey(PKE pKeyEvent, ULONG ExtraInformation, int NotUsed) { 01750 int CurrentModState; 01751 int fBreak; 01752 BYTE Vk; 01753 01754 01755 CheckCritIn(); 01756 01757 Vk = (BYTE)(pKeyEvent->usFlaggedVk & 0xff); 01758 fBreak = pKeyEvent->usFlaggedVk & KBDBREAK; 01759 CurrentModState = gLockBits | gLatchBits | gPhysModifierState; 01760 01761 if (!TEST_ACCESSFLAG(HighContrast, HCF_HIGHCONTRASTON)) { 01762 if (TEST_ACCESSFLAG(HighContrast, HCF_HOTKEYACTIVE) && Vk == VK_SNAPSHOT && !fBreak && CurrentModState == MOUSEKEYMODBITS) { 01763 01764 if (TEST_ACCESSFLAG(HighContrast, MKF_HOTKEYSOUND)) { 01765 PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm; 01766 PostRitSound( 01767 pTerm, 01768 RITSOUND_UPSIREN); 01769 } 01770 01771 PostAccessNotification(ACCESS_HIGHCONTRAST); 01772 01773 return FALSE; 01774 } 01775 } else { 01776 if (TEST_ACCESSFLAG(HighContrast, HCF_HOTKEYACTIVE) && Vk == VK_SNAPSHOT && !fBreak && CurrentModState == MOUSEKEYMODBITS) { 01777 01778 CLEAR_ACCESSFLAG(HighContrast, HCF_HIGHCONTRASTON); 01779 01780 if (TEST_ACCESSFLAG(HighContrast, MKF_HOTKEYSOUND)) { 01781 PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm; 01782 PostRitSound( 01783 pTerm, 01784 RITSOUND_DOWNSIREN); 01785 } 01786 01787 if (gspwndLogonNotify != NULL) { 01788 01789 _PostMessage(gspwndLogonNotify, WM_LOGONNOTIFY, 01790 LOGON_ACCESSNOTIFY, ACCESS_HIGHCONTRASTOFF); 01791 } 01792 } 01793 } 01794 return TRUE; // send key event to next accessibility routine. 01795 UNREFERENCED_PARAMETER(NotUsed); 01796 UNREFERENCED_PARAMETER(ExtraInformation); 01797 } 01798 01799 01800 /***************************************************************************\ 01801 * MouseKeys 01802 * 01803 * This is the strategy routine that gets called as part of the input stream 01804 * processing. MouseKeys enabling/disabling is handled here. All MouseKeys 01805 * helper routines are called from this routine. 01806 * 01807 * Return value: 01808 * TRUE - key event should be passed on to the next access routine. 01809 * FALSE - key event was processed and should not be passed on. 01810 * 01811 * History: 01812 \***************************************************************************/ 01813 BOOL MouseKeys(PKE pKeyEvent, ULONG ExtraInformation, int NotUsed) 01814 { 01815 int CurrentModState; 01816 int fBreak; 01817 BYTE Vk; 01818 USHORT FlaggedVk; 01819 int i; 01820 01821 CheckCritIn(); 01822 Vk = (BYTE)(pKeyEvent->usFlaggedVk & 0xff); 01823 fBreak = pKeyEvent->usFlaggedVk & KBDBREAK; 01824 CurrentModState = gLockBits | gLatchBits | gPhysModifierState; 01825 01826 if (!TEST_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON)) { 01827 // 01828 // MouseKeys currently disabled. Check for enabling sequence: 01829 // left Shift + left Alt + Num Lock. 01830 // 01831 #ifdef FE_SB // MouseKeys() 01832 if (TEST_ACCESSFLAG(MouseKeys, MKF_HOTKEYACTIVE) && Vk == gNumLockVk && !fBreak && CurrentModState == MOUSEKEYMODBITS) { 01833 #else // FE_SB 01834 if (TEST_ACCESSFLAG(MouseKeys, MKF_HOTKEYACTIVE) && Vk == VK_NUMLOCK && !fBreak && CurrentModState == MOUSEKEYMODBITS) { 01835 #endif // FE_SB 01836 gMKPreviousVk = Vk; 01837 if (TEST_ACCESSFLAG(MouseKeys, MKF_HOTKEYSOUND)) { 01838 PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm; 01839 PostRitSound( 01840 pTerm, 01841 RITSOUND_UPSIREN); 01842 } 01843 PostAccessNotification(ACCESS_MOUSEKEYS); 01844 01845 return FALSE; 01846 } 01847 } else { 01848 // 01849 // Is this a MouseKey key? 01850 // 01851 // 01852 FlaggedVk = Vk | (pKeyEvent->usFlaggedVk & KBDEXT); 01853 for (i = 0; i < cMouseVKeys; i++) { 01854 #ifdef FE_SB // MouseKeys() 01855 if (FlaggedVk == gpusMouseVKey[i]) { 01856 #else // FE_SB 01857 if (FlaggedVk == ausMouseVKey[i]) { 01858 #endif // FE_SB 01859 break; 01860 } 01861 } 01862 01863 if (i == cMouseVKeys) { 01864 return TRUE; // not a mousekey 01865 } 01866 // 01867 // Check to see if we should pass on key events until Num Lock is 01868 // entered. 01869 // 01870 01871 if (!gbMKMouseMode) { 01872 #ifdef FE_SB // MouseKeys() 01873 if (Vk != gNumLockVk) { 01874 #else // FE_SB 01875 if (Vk != VK_NUMLOCK) { 01876 #endif // FE_SB 01877 return TRUE; 01878 } 01879 } 01880 01881 // 01882 // Check for Ctrl-Alt-Numpad Del. Pass key event on if sequence 01883 // detected. 01884 // 01885 if (Vk == VK_DELETE && CurrentModState & LRALT && CurrentModState & LRCONTROL) { 01886 return TRUE; 01887 } 01888 if (fBreak) { 01889 // 01890 // If this is a break of the key that we're accelerating then 01891 // kill the timer. 01892 // 01893 if (gMKPreviousVk == Vk) { 01894 if (gtmridMKMoveCursor != 0) { 01895 KILLRITTIMER(NULL, gtmridMKMoveCursor); 01896 gtmridMKMoveCursor = 0; 01897 } 01898 CLEAR_ACCF(ACCF_MKREPEATVK); 01899 gMKPreviousVk = 0; 01900 } 01901 // 01902 // Pass break of Numlock along. Other mousekeys stop here. 01903 // 01904 #ifdef FE_SB // MouseKeys() 01905 if (Vk == gNumLockVk) { 01906 #else // FE_SB 01907 if (Vk == VK_NUMLOCK) { 01908 #endif // FE_SB 01909 return TRUE; 01910 } else { 01911 return FALSE; 01912 } 01913 } else { 01914 SET_OR_CLEAR_ACCF(ACCF_MKREPEATVK, 01915 (gMKPreviousVk == Vk)); 01916 // 01917 // If this is not a typematic repeat, kill the mouse acceleration 01918 // timer. 01919 // 01920 if ((!TEST_ACCF(ACCF_MKREPEATVK)) && (gtmridMKMoveCursor)) { 01921 KILLRITTIMER(NULL, gtmridMKMoveCursor); 01922 gtmridMKMoveCursor = 0; 01923 } 01924 gMKPreviousVk = Vk; 01925 } 01926 return aMouseKeyEvent[i](ausMouseKeyData[i]); 01927 } 01928 return TRUE; 01929 01930 UNREFERENCED_PARAMETER(NotUsed); 01931 UNREFERENCED_PARAMETER(ExtraInformation); 01932 01933 } 01934 01935 /***************************************************************************\ 01936 * TurnOffMouseKeys 01937 * 01938 * Return value: 01939 * None. 01940 * 01941 * History: 01942 * 11 Feb 93 GregoryW Created. 01943 \***************************************************************************/ 01944 VOID TurnOffMouseKeys(VOID) 01945 { 01946 CLEAR_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON); 01947 // gMKPassThrough = 0; 01948 CLEAR_ACCF(ACCF_MKREPEATVK); 01949 MKHideMouseCursor(); 01950 if (TEST_ACCESSFLAG(MouseKeys, MKF_HOTKEYSOUND)) { 01951 PostRitSound( 01952 grpdeskRitInput->rpwinstaParent->pTerm, 01953 RITSOUND_DOWNSIREN); 01954 } 01955 PostAccessibility( ACCESS_MOUSEKEYS ); 01956 } 01957 01958 01959 /***************************************************************************\ 01960 * CalculateMouseTable 01961 * 01962 * Set mouse table based on time to max speed and max speed. This routine 01963 * is called during user logon (after the registry entries for the access 01964 * features are read). 01965 * 01966 * Return value: 01967 * None. 01968 * 01969 * History: 01970 * Taken from access utility. 01971 * 01972 ****************************************************************************/ 01973 VOID CalculateMouseTable(VOID) 01974 { 01975 long Total_Distance; /* in 1000th of pixel */ 01976 01977 long Accel_Per_Tick; /* in 1000th of pixel/tick */ 01978 long Current_Speed; /* in 1000th of pixel/tick */ 01979 long Max_Speed; /* in 1000th of pixel/tick */ 01980 long Real_Total_Distance; /* in pixels */ 01981 long Real_Delta_Distance; /* in pixels */ 01982 int i; 01983 int Num_Constant_Table,Num_Accel_Table; 01984 01985 01986 Max_Speed = gMouseKeys.iMaxSpeed; 01987 Max_Speed *= 1000 / MOUSETICKS; 01988 01989 Accel_Per_Tick = Max_Speed * 1000 / (gMouseKeys.iTimeToMaxSpeed * MOUSETICKS); 01990 Current_Speed = 0; 01991 Total_Distance = 0; 01992 Real_Total_Distance = 0; 01993 Num_Constant_Table = 0; 01994 Num_Accel_Table = 0; 01995 01996 for(i=0; i<= 255; i++) { 01997 Current_Speed = Current_Speed + Accel_Per_Tick; 01998 if (Current_Speed > Max_Speed) { 01999 Current_Speed = Max_Speed; 02000 } 02001 Total_Distance += Current_Speed; 02002 02003 // 02004 // Calculate how many pixels to move on this tick 02005 // 02006 Real_Delta_Distance = ((Total_Distance - (Real_Total_Distance * 1000)) + 500) / 1000 ; 02007 // 02008 // Calculate total distance moved up to this point 02009 // 02010 Real_Total_Distance = Real_Total_Distance + Real_Delta_Distance; 02011 02012 if ((Current_Speed < Max_Speed) && (Num_Accel_Table < 128)) { 02013 gMouseCursor.bAccelTable[Num_Accel_Table++] = (BYTE)Real_Delta_Distance; 02014 } 02015 02016 if ((Current_Speed == Max_Speed) && (Num_Constant_Table < 128)) { 02017 gMouseCursor.bConstantTable[Num_Constant_Table++] = (BYTE)Real_Delta_Distance; 02018 } 02019 02020 } 02021 gMouseCursor.bAccelTableLen = (BYTE)Num_Accel_Table; 02022 gMouseCursor.bConstantTableLen = (BYTE)Num_Constant_Table; 02023 } 02024 02025 02026 /***************************************************************************\ 02027 * xxxToggleKeysTimer 02028 * 02029 * Enable ToggleKeys if it is currently disabled. Disable ToggleKeys if it 02030 * is currently enabled. 02031 * 02032 * This routine is called only when the NumLock key is held down for 5 seconds. 02033 * 02034 * Return value: 02035 * 0 02036 * 02037 * History: 02038 * 11 Feb 93 GregoryW Created. 02039 \***************************************************************************/ 02040 VOID xxxToggleKeysTimer(PWND pwnd, UINT message, UINT_PTR nID, LPARAM lParam) 02041 { 02042 KE ToggleKeyEvent; 02043 PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm; 02044 02045 CheckCritIn(); 02046 // 02047 // Toggle ToggleKeys and provide audible feedback if appropriate. 02048 // 02049 if (TEST_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON)) { 02050 CLEAR_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON); 02051 if (TEST_ACCESSFLAG(ToggleKeys, TKF_HOTKEYSOUND)) { 02052 PostRitSound( 02053 pTerm, 02054 RITSOUND_DOWNSIREN); 02055 } 02056 } else { 02057 if (TEST_ACCESSFLAG(ToggleKeys, TKF_HOTKEYSOUND)) { 02058 PostRitSound( 02059 pTerm, 02060 RITSOUND_UPSIREN); 02061 } 02062 02063 PostAccessNotification(ACCESS_TOGGLEKEYS); 02064 } 02065 // 02066 // Send a fake break/make combination so state of numlock key remains 02067 // the same as it was before user pressed it to activate/deactivate 02068 // ToggleKeys. 02069 // 02070 ToggleKeyEvent.bScanCode = gTKScanCode; 02071 #ifdef FE_SB // ToggleKeysTimer() 02072 ToggleKeyEvent.usFlaggedVk = gNumLockVk | KBDBREAK; 02073 #else 02074 ToggleKeyEvent.usFlaggedVk = VK_NUMLOCK | KBDBREAK; 02075 #endif // FE_SB 02076 if (AccessProceduresStream(&ToggleKeyEvent, gTKExtraInformation, gTKNextProcIndex)) { 02077 xxxProcessKeyEvent(&ToggleKeyEvent, gTKExtraInformation, FALSE); 02078 } 02079 #ifdef FE_SB // ToggleKeysTimer() 02080 ToggleKeyEvent.usFlaggedVk = gNumLockVk; 02081 #else 02082 ToggleKeyEvent.usFlaggedVk = VK_NUMLOCK; 02083 #endif // FE_SB 02084 if (AccessProceduresStream(&ToggleKeyEvent, gTKExtraInformation, gTKNextProcIndex)) { 02085 xxxProcessKeyEvent(&ToggleKeyEvent, gTKExtraInformation, FALSE); 02086 } 02087 return; 02088 02089 UNREFERENCED_PARAMETER(pwnd); 02090 UNREFERENCED_PARAMETER(message); 02091 UNREFERENCED_PARAMETER(nID); 02092 UNREFERENCED_PARAMETER(lParam); 02093 } 02094 02095 02096 /***************************************************************************\ 02097 * ToggleKeys 02098 * 02099 * This is the strategy routine that gets called as part of the input stream 02100 * processing. Keys of interest are Num Lock, Scroll Lock and Caps Lock. 02101 * 02102 * Return value: 02103 * TRUE - key event should be passed on to the next access routine. 02104 * FALSE - key event was processed and should not be passed on. 02105 * 02106 * History: 02107 \***************************************************************************/ 02108 BOOL ToggleKeys(PKE pKeyEvent, ULONG ExtraInformation, int NextProcIndex) 02109 { 02110 int fBreak; 02111 BYTE Vk; 02112 02113 CheckCritIn(); 02114 Vk = (BYTE)pKeyEvent->usFlaggedVk; 02115 fBreak = pKeyEvent->usFlaggedVk & KBDBREAK; 02116 02117 // 02118 // Check for Numlock key. On the first make set the ToggleKeys timer. 02119 // The timer is killed on the break of the Numlock key. 02120 // 02121 switch (Vk) { 02122 case VK_NUMLOCK: 02123 #ifdef FE_SB // ToggleKeys() 02124 NumLockProc: 02125 #endif // FE_SB 02126 /* 02127 * Don't handle NUMLOCK toggles if the user is doing MouseKey 02128 * toggling. 02129 */ 02130 if ((gLockBits | gLatchBits | gPhysModifierState) == MOUSEKEYMODBITS && 02131 TEST_ACCESSFLAG(MouseKeys, MKF_HOTKEYACTIVE)) { 02132 break; 02133 } 02134 if (fBreak) 02135 { 02136 // 02137 // Only reset gptmrToggleKeys on the break of NumLock. This 02138 // prevents cycling the toggle keys state by continually 02139 // holding down the NumLock key. 02140 // 02141 KILLRITTIMER(NULL, gtmridToggleKeys); 02142 gtmridToggleKeys = 0; 02143 gTKExtraInformation = 0; 02144 gTKScanCode = 0; 02145 } 02146 else 02147 { 02148 if (gtmridToggleKeys == 0 && 02149 TEST_ACCESSFLAG(ToggleKeys, TKF_HOTKEYACTIVE)) 02150 { 02151 02152 // 02153 // Remember key information to be used by timer routine. 02154 // 02155 gTKExtraInformation = ExtraInformation; 02156 gTKScanCode = pKeyEvent->bScanCode; 02157 gTKNextProcIndex = NextProcIndex; 02158 gtmridToggleKeys = InternalSetTimer( 02159 NULL, 02160 0, 02161 TOGGLEKEYTOGGLETIME, 02162 xxxToggleKeysTimer, 02163 TMRF_RIT | TMRF_ONESHOT 02164 ); 02165 } 02166 } 02167 // 02168 // If MouseKeys is on, audible feedback has already occurred for this 02169 // keystroke. Skip the rest of the processing. 02170 // 02171 if (TEST_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON)) { 02172 break; 02173 } 02174 // fall through 02175 02176 case VK_SCROLL: 02177 case VK_CAPITAL: 02178 #ifdef FE_SB // ToggleKeys() 02179 CapitalProc: 02180 #endif // FE_SB 02181 if (TEST_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON) && !fBreak) { 02182 if (!TestAsyncKeyStateDown(Vk)) { 02183 PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm; 02184 if (!TestAsyncKeyStateToggle(Vk)) { 02185 PostRitSound( 02186 pTerm, 02187 RITSOUND_HIGHBEEP); 02188 } else { 02189 PostRitSound( 02190 pTerm, 02191 RITSOUND_LOWBEEP); 02192 } 02193 } 02194 } 02195 break; 02196 02197 default: 02198 #ifdef FE_SB // ToggleKeys() 02199 if (Vk == gNumLockVk) goto NumLockProc; 02200 if (Vk == gOemScrollVk) goto CapitalProc; 02201 #endif // FE_SB 02202 if (gtmridToggleKeys != 0) { 02203 KILLRITTIMER(NULL, gtmridToggleKeys); 02204 } 02205 } 02206 02207 return TRUE; 02208 } 02209 02210 02211 /***************************************************************************\ 02212 * AccessTimeOutTimer 02213 * 02214 * This routine is called if no keyboard activity takes place for the 02215 * user configured amount of time. All access related functions are 02216 * disabled. 02217 * 02218 * This routine is called with the critical section already locked. 02219 * 02220 * Return value: 02221 * 0 02222 * 02223 * History: 02224 \***************************************************************************/ 02225 VOID xxxAccessTimeOutTimer(PWND pwnd, UINT message, UINT_PTR nID, LPARAM lParam) 02226 { 02227 CheckCritIn(); 02228 /* 02229 * The timeout timer will remain on (if so configured) as long as 02230 * TEST_ACCF(ACCF_ACCESSENABLED) is TRUE. This means we might get timeouts when 02231 * only hot keys are enabled, but no features are actually on. Don't 02232 * provide any audible feedback in this case. 02233 */ 02234 if ( TEST_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON) || 02235 TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON) || 02236 TEST_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON) || 02237 TEST_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON) || 02238 TEST_ACCESSFLAG(SoundSentry, SSF_SOUNDSENTRYON) || 02239 TEST_ACCESSFLAG(HighContrast, HCF_HIGHCONTRASTON) || 02240 TEST_ACCF(ACCF_SHOWSOUNDSON)) { 02241 02242 PTERMINAL pTerm = grpdeskRitInput->rpwinstaParent->pTerm; 02243 CLEAR_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON); 02244 xxxTurnOffStickyKeys(); 02245 CLEAR_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON); 02246 CLEAR_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON); 02247 CLEAR_ACCESSFLAG(SoundSentry, SSF_SOUNDSENTRYON); 02248 CLEAR_ACCF(ACCF_SHOWSOUNDSON); 02249 CLEAR_ACCESSFLAG(HighContrast, HCF_HIGHCONTRASTON); 02250 02251 if (gspwndLogonNotify != NULL) { 02252 02253 _PostMessage(gspwndLogonNotify, WM_LOGONNOTIFY, 02254 LOGON_ACCESSNOTIFY, ACCESS_HIGHCONTRASTOFF); 02255 } 02256 02257 if (TEST_ACCESSFLAG(AccessTimeOut, ATF_ONOFFFEEDBACK)) { 02258 PostRitSound( 02259 pTerm, 02260 RITSOUND_DOWNSIREN); 02261 } 02262 PostAccessibility( ACCESS_MOUSEKEYS ); 02263 02264 PostAccessibility( ACCESS_FILTERKEYS ); 02265 02266 PostAccessibility( ACCESS_STICKYKEYS ); 02267 02268 } 02269 SetAccessEnabledFlag(); 02270 return; 02271 02272 02273 UNREFERENCED_PARAMETER(pwnd); 02274 UNREFERENCED_PARAMETER(message); 02275 UNREFERENCED_PARAMETER(nID); 02276 UNREFERENCED_PARAMETER(lParam); 02277 } 02278 02279 /***************************************************************************\ 02280 * AccessTimeOutReset 02281 * 02282 * This routine resets the timeout timer. 02283 * 02284 * Return value: 02285 * 0 02286 * 02287 * History: 02288 \***************************************************************************/ 02289 VOID AccessTimeOutReset() 02290 { 02291 02292 if (gtmridAccessTimeOut != 0) { 02293 KILLRITTIMER(NULL, gtmridAccessTimeOut); 02294 } 02295 if (TEST_ACCESSFLAG(AccessTimeOut, ATF_TIMEOUTON)) { 02296 gtmridAccessTimeOut = InternalSetTimer( 02297 NULL, 02298 0, 02299 (UINT)gAccessTimeOut.iTimeOutMSec, 02300 xxxAccessTimeOutTimer, 02301 TMRF_RIT | TMRF_ONESHOT 02302 ); 02303 } 02304 } 02305 02306 /***************************************************************************\ 02307 * xxxUpdatePerUserAccessPackSettings 02308 * 02309 * Sets the initial access pack features according to the user's profile. 02310 * 02311 * 02-14-93 GregoryW Created. 02312 \***************************************************************************/ 02313 void 02314 xxxUpdatePerUserAccessPackSettings(PUNICODE_STRING pProfileUserName) 02315 { 02316 LUID luidCaller; 02317 NTSTATUS status; 02318 BOOL fSystem = FALSE; 02319 BOOL fRegFilterKeysOn; 02320 BOOL fRegStickyKeysOn; 02321 BOOL fRegMouseKeysOn; 02322 BOOL fRegToggleKeysOn; 02323 BOOL fRegTimeOutOn; 02324 BOOL fRegKeyboardPref; 02325 BOOL fRegScreenReader; 02326 BOOL fRegHighContrastOn; 02327 DWORD dwDefFlags; 02328 UNICODE_STRING usHighContrastScheme; 02329 WCHAR wcHighContrastScheme[MAX_SCHEME_NAME_SIZE]; 02330 02331 status = GetProcessLuid(NULL, &luidCaller); 02332 // 02333 // If we're called in the system context no one is logged on. 02334 // We want to read the current .DEFAULT settings for the access 02335 // features. Later when we're called in the user context (e.g., 02336 // someone has successfully logged on) we check to see if the 02337 // current access state is the same as the default setting. If 02338 // not, the user has enabled/disabled one or more access features 02339 // from the keyboard. These changes will be propagated across 02340 // the logon into the user's intial state (overriding the settings 02341 // in the user's profile). 02342 // 02343 if (RtlEqualLuid(&luidCaller, &luidSystem)) { 02344 fSystem = TRUE; 02345 } 02346 02347 02348 02349 dwDefFlags = FastGetProfileIntW(pProfileUserName, 02350 PMAP_KEYBOARDRESPONSE, 02351 TEXT("Flags"), 02352 0 02353 ); 02354 fRegFilterKeysOn = (dwDefFlags & FKF_FILTERKEYSON) != 0; 02355 02356 dwDefFlags = FastGetProfileIntW(pProfileUserName, 02357 PMAP_STICKYKEYS, 02358 TEXT("Flags"), 02359 0 02360 ); 02361 fRegStickyKeysOn = (dwDefFlags & SKF_STICKYKEYSON) != 0; 02362 02363 dwDefFlags = FastGetProfileIntW(pProfileUserName, 02364 PMAP_MOUSEKEYS, 02365 TEXT("Flags"), 02366 0 02367 ); 02368 fRegMouseKeysOn = (dwDefFlags & MKF_MOUSEKEYSON) != 0; 02369 02370 dwDefFlags = FastGetProfileIntW(pProfileUserName, 02371 PMAP_TOGGLEKEYS, 02372 TEXT("Flags"), 02373 0 02374 ); 02375 fRegToggleKeysOn = (dwDefFlags & TKF_TOGGLEKEYSON) != 0; 02376 02377 fRegKeyboardPref = !!FastGetProfileIntW(pProfileUserName, 02378 PMAP_KEYBOARDPREF, 02379 TEXT("On"), 02380 0 02381 ); 02382 02383 fRegScreenReader = !!FastGetProfileIntW(pProfileUserName, 02384 PMAP_SCREENREADER, 02385 TEXT("On"), 02386 0 02387 ); 02388 02389 dwDefFlags = FastGetProfileIntW(pProfileUserName, 02390 PMAP_TIMEOUT, 02391 TEXT("Flags"), 02392 0 02393 ); 02394 fRegTimeOutOn = (dwDefFlags & ATF_TIMEOUTON) != 0; 02395 02396 dwDefFlags = FastGetProfileIntW(pProfileUserName, 02397 PMAP_HIGHCONTRAST, 02398 TEXT("Flags"), 02399 0 02400 ); 02401 fRegHighContrastOn = (dwDefFlags & HCF_HIGHCONTRASTON) != 0; 02402 02403 if (fSystem) { 02404 // 02405 // We're in system mode (e.g., no one is logged in). Remember 02406 // the .DEFAULT state for comparison during the next user logon 02407 // and set the current state to the .DEFAULT state. 02408 // 02409 if (fRegFilterKeysOn) { 02410 SET_ACCF(ACCF_DEFAULTFILTERKEYSON); 02411 SET_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON); 02412 } else { 02413 CLEAR_ACCF(ACCF_DEFAULTFILTERKEYSON); 02414 CLEAR_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON); 02415 } 02416 02417 // 02418 // If StickyKeys is currently on and we're about to turn it 02419 // off we need to make sure the latch keys and lock keys are 02420 // released. 02421 // 02422 if (TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON) && (fRegFilterKeysOn == 0)) { 02423 xxxTurnOffStickyKeys(); 02424 } 02425 02426 if (fRegStickyKeysOn) { 02427 SET_ACCF(ACCF_DEFAULTSTICKYKEYSON); 02428 SET_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON); 02429 } else { 02430 CLEAR_ACCF(ACCF_DEFAULTSTICKYKEYSON); 02431 CLEAR_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON); 02432 } 02433 02434 if (fRegMouseKeysOn) { 02435 SET_ACCF(ACCF_DEFAULTMOUSEKEYSON); 02436 SET_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON); 02437 } else { 02438 CLEAR_ACCF(ACCF_DEFAULTMOUSEKEYSON); 02439 CLEAR_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON); 02440 } 02441 02442 if (fRegToggleKeysOn) { 02443 SET_ACCF(ACCF_DEFAULTTOGGLEKEYSON); 02444 SET_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON); 02445 } else { 02446 CLEAR_ACCF(ACCF_DEFAULTTOGGLEKEYSON); 02447 CLEAR_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON); 02448 } 02449 02450 if (fRegTimeOutOn) { 02451 SET_ACCF(ACCF_DEFAULTTIMEOUTON); 02452 SET_ACCESSFLAG(AccessTimeOut, ATF_TIMEOUTON); 02453 } else { 02454 CLEAR_ACCF(ACCF_DEFAULTTIMEOUTON); 02455 CLEAR_ACCESSFLAG(AccessTimeOut, ATF_TIMEOUTON); 02456 } 02457 02458 if (fRegKeyboardPref) { 02459 SET_ACCF(ACCF_DEFAULTKEYBOARDPREF); 02460 SET_ACCF(ACCF_KEYBOARDPREF); 02461 gpsi->bKeyboardPref = TRUE; 02462 } else { 02463 CLEAR_ACCF(ACCF_DEFAULTKEYBOARDPREF); 02464 CLEAR_ACCF(ACCF_KEYBOARDPREF); 02465 gpsi->bKeyboardPref = FALSE; 02466 } 02467 02468 if (fRegScreenReader) { 02469 SET_ACCF(ACCF_DEFAULTSCREENREADER); 02470 SET_ACCF(ACCF_SCREENREADER); 02471 } else { 02472 CLEAR_ACCF(ACCF_DEFAULTSCREENREADER); 02473 CLEAR_ACCF(ACCF_SCREENREADER); 02474 } 02475 02476 if (fRegHighContrastOn) { 02477 SET_ACCF(ACCF_DEFAULTHIGHCONTRASTON); 02478 SET_ACCESSFLAG(HighContrast, HCF_HIGHCONTRASTON); 02479 } else { 02480 CLEAR_ACCF(ACCF_DEFAULTHIGHCONTRASTON); 02481 CLEAR_ACCESSFLAG(HighContrast, HCF_HIGHCONTRASTON); 02482 } 02483 } else { 02484 // 02485 // A user has successfully logged on. If the current state is 02486 // different from the default state stored earlier then we know 02487 // the user has modified the state via the keyboard (at the logon 02488 // dialog). This state will override whatever on/off state the 02489 // user has set in their profile. If the current state is the 02490 // same as the default state then the on/off setting from the 02491 // user profile is used. 02492 // 02493 02494 if ( TEST_BOOL_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON) == 02495 TEST_BOOL_ACCF(ACCF_DEFAULTFILTERKEYSON)) { 02496 // 02497 // Current state and default state are the same. Use the 02498 // user's profile setting. 02499 // 02500 02501 SET_OR_CLEAR_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON, fRegFilterKeysOn); 02502 } 02503 02504 if ( TEST_BOOL_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON) == 02505 TEST_BOOL_ACCF(ACCF_DEFAULTSTICKYKEYSON)) { 02506 // 02507 // If StickyKeys is currently on and we're about to turn it 02508 // off we need to make sure the latch keys and lock keys are 02509 // released. 02510 // 02511 if ( TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON) && 02512 (fRegStickyKeysOn == 0)) { 02513 02514 xxxTurnOffStickyKeys(); 02515 } 02516 02517 SET_OR_CLEAR_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON, fRegStickyKeysOn); 02518 } 02519 02520 if ( TEST_BOOL_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON) == 02521 TEST_BOOL_ACCF(ACCF_DEFAULTMOUSEKEYSON)) { 02522 // 02523 // Current state and default state are the same. Use the user's 02524 // profile setting. 02525 // 02526 SET_OR_CLEAR_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON, fRegMouseKeysOn); 02527 } 02528 02529 if ( TEST_BOOL_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON) == 02530 TEST_BOOL_ACCF(ACCF_DEFAULTTOGGLEKEYSON)) { 02531 // 02532 // Current state and default state are the same. Use the user's 02533 // profile setting. 02534 // 02535 SET_OR_CLEAR_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON, fRegToggleKeysOn); 02536 } 02537 02538 if ( TEST_BOOL_ACCESSFLAG(AccessTimeOut, ATF_TIMEOUTON) == 02539 TEST_BOOL_ACCF(ACCF_DEFAULTTIMEOUTON)) { 02540 // 02541 // Current state and default state are the same. Use the user's 02542 // profile setting. 02543 // 02544 SET_OR_CLEAR_ACCESSFLAG(AccessTimeOut, ATF_TIMEOUTON, fRegTimeOutOn); 02545 } 02546 02547 if ( TEST_BOOL_ACCF(ACCF_KEYBOARDPREF) == 02548 TEST_BOOL_ACCF(ACCF_DEFAULTKEYBOARDPREF)) { 02549 // 02550 // Current state and default state are the same. Use the user's 02551 // profile setting. 02552 // 02553 SET_OR_CLEAR_ACCF(ACCF_KEYBOARDPREF, fRegKeyboardPref); 02554 } 02555 02556 if ( TEST_BOOL_ACCF(ACCF_SCREENREADER) == 02557 TEST_BOOL_ACCF(ACCF_DEFAULTSCREENREADER)) { 02558 // 02559 // Current state and default state are the same. Use the user's 02560 // profile setting. 02561 // 02562 SET_OR_CLEAR_ACCF(ACCF_SCREENREADER, fRegScreenReader); 02563 } 02564 02565 if ( TEST_BOOL_ACCESSFLAG(HighContrast, HCF_HIGHCONTRASTON) == 02566 TEST_BOOL_ACCF(ACCF_DEFAULTHIGHCONTRASTON)) { 02567 // 02568 // Current state and default state are the same. Use the user's 02569 // profile setting. 02570 // 02571 SET_OR_CLEAR_ACCESSFLAG(HighContrast, HCF_HIGHCONTRASTON, fRegHighContrastOn); 02572 } 02573 } 02574 02575 // 02576 // Get the default FilterKeys state. 02577 // 02578 // -------- flag --------------- value --------- default ------ 02579 // #define FKF_FILTERKEYSON 0x00000001 0 02580 // #define FKF_AVAILABLE 0x00000002 2 02581 // #define FKF_HOTKEYACTIVE 0x00000004 0 02582 // #define FKF_CONFIRMHOTKEY 0x00000008 0 02583 // #define FKF_HOTKEYSOUND 0x00000010 10 02584 // #define FKF_INDICATOR 0x00000020 0 02585 // #define FKF_CLICKON 0x00000040 40 02586 // ----------------------------------------- total = 0x52 = 82 02587 // 02588 02589 dwDefFlags = FastGetProfileIntW(pProfileUserName, 02590 PMAP_KEYBOARDRESPONSE, 02591 TEXT("Flags"), 02592 82 02593 ); 02594 02595 SET_OR_CLEAR_FLAG( 02596 dwDefFlags, 02597 FKF_FILTERKEYSON, 02598 TEST_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON)); 02599 02600 gFilterKeys.dwFlags = dwDefFlags; 02601 gFilterKeys.iWaitMSec = FastGetProfileIntW(pProfileUserName, 02602 PMAP_KEYBOARDRESPONSE, 02603 TEXT("DelayBeforeAcceptance"), 02604 1000 02605 ); 02606 02607 gFilterKeys.iRepeatMSec = FastGetProfileIntW(pProfileUserName, 02608 PMAP_KEYBOARDRESPONSE, 02609 TEXT("AutoRepeatRate"), 02610 500 02611 ); 02612 02613 gFilterKeys.iDelayMSec = FastGetProfileIntW(pProfileUserName, 02614 PMAP_KEYBOARDRESPONSE, 02615 TEXT("AutoRepeatDelay"), 02616 1000 02617 ); 02618 02619 gFilterKeys.iBounceMSec = FastGetProfileIntW(pProfileUserName, 02620 PMAP_KEYBOARDRESPONSE, 02621 TEXT("BounceTime"), 02622 0 02623 ); 02624 02625 // 02626 // Fill in the SoundSentry state. This release of the 02627 // accessibility features only supports iWindowsEffect. 02628 // 02629 // -------- flag --------------- value --------- default ------ 02630 // #define SSF_SOUNDSENTRYON 0x00000001 0 02631 // #define SSF_AVAILABLE 0x00000002 1 02632 // #define SSF_INDICATOR 0x00000004 0 02633 // ----------------------------------------- total = 0x2 = 2 02634 // 02635 gSoundSentry.dwFlags = FastGetProfileIntW(pProfileUserName, 02636 PMAP_SOUNDSENTRY, 02637 TEXT("Flags"), 02638 2 02639 ); 02640 02641 gSoundSentry.iFSTextEffect = FastGetProfileIntW(pProfileUserName, 02642 PMAP_SOUNDSENTRY, 02643 TEXT("FSTextEffect"), 02644 0 02645 ); 02646 02647 gSoundSentry.iWindowsEffect = FastGetProfileIntW(pProfileUserName, 02648 PMAP_SOUNDSENTRY, 02649 TEXT("WindowsEffect"), 02650 0 02651 ); 02652 02653 /* 02654 * Set ShowSounds flag. 02655 */ 02656 SET_OR_CLEAR_ACCF(ACCF_SHOWSOUNDSON, FastGetProfileIntW(pProfileUserName, 02657 PMAP_SHOWSOUNDS, 02658 TEXT("On"), 02659 0 02660 )); 02661 02662 // 02663 // Get the default StickyKeys state. 02664 // 02665 // -------- flag --------------- value --------- default ------ 02666 // #define SKF_STICKYKEYSON 0x00000001 0 02667 // #define SKF_AVAILABLE 0x00000002 2 02668 // #define SKF_HOTKEYACTIVE 0x00000004 0 02669 // #define SKF_CONFIRMHOTKEY 0x00000008 0 02670 // #define SKF_HOTKEYSOUND 0x00000010 10 02671 // #define SKF_INDICATOR 0x00000020 0 02672 // #define SKF_AUDIBLEFEEDBACK 0x00000040 40 02673 // #define SKF_TRISTATE 0x00000080 80 02674 // #define SKF_TWOKEYSOFF 0x00000100 100 02675 // ----------------------------------------- total = 0x1d2 = 466 02676 // 02677 dwDefFlags = FastGetProfileIntW(pProfileUserName, 02678 PMAP_STICKYKEYS, 02679 TEXT("Flags"), 02680 466 02681 ); 02682 02683 SET_OR_CLEAR_FLAG( 02684 dwDefFlags, 02685 SKF_STICKYKEYSON, 02686 TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON)); 02687 02688 gStickyKeys.dwFlags = dwDefFlags; 02689 02690 // 02691 // Get the default MouseKeys state. 02692 // 02693 // -------- flag --------------- value --------- default ------ 02694 // #define MKF_MOUSEKEYSON 0x00000001 0 02695 // #define MKF_AVAILABLE 0x00000002 2 02696 // #define MKF_HOTKEYACTIVE 0x00000004 0 02697 // #define MKF_CONFIRMHOTKEY 0x00000008 0 02698 // #define MKF_HOTKEYSOUND 0x00000010 10 02699 // #define MKF_INDICATOR 0x00000020 0 02700 // #define MKF_MODIFIERS 0x00000040 0 02701 // #define MKF_REPLACENUMBERS 0x00000080 0 02702 // ----------------------------------------- total = 0x12 = 18 02703 // 02704 dwDefFlags = FastGetProfileIntW(pProfileUserName, 02705 PMAP_MOUSEKEYS, 02706 TEXT("Flags"), 02707 18 02708 ); 02709 02710 SET_OR_CLEAR_FLAG( 02711 dwDefFlags, 02712 MKF_MOUSEKEYSON, 02713 TEST_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON)); 02714 02715 gMouseKeys.dwFlags = dwDefFlags; 02716 gMouseKeys.iMaxSpeed = FastGetProfileIntW(pProfileUserName, 02717 PMAP_MOUSEKEYS, 02718 TEXT("MaximumSpeed"), 02719 40 02720 ); 02721 02722 gMouseKeys.iTimeToMaxSpeed = FastGetProfileIntW(pProfileUserName, 02723 PMAP_MOUSEKEYS, 02724 TEXT("TimeToMaximumSpeed"), 02725 3000 02726 ); 02727 CalculateMouseTable(); 02728 02729 gbMKMouseMode = 02730 #ifdef FE_SB 02731 (TestAsyncKeyStateToggle(gNumLockVk) != 0) ^ 02732 #else // FE_SB 02733 (TestAsyncKeyStateToggle(VK_NUMLOCK) != 0) ^ 02734 #endif // FE_SB 02735 (TEST_ACCESSFLAG(MouseKeys, MKF_REPLACENUMBERS) != 0); 02736 02737 // 02738 // If the system does not have a hardware mouse: 02739 // If MouseKeys is enabled show the mouse cursor, 02740 // o.w. hide the mouse cursor. 02741 // 02742 if (TEST_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON)) { 02743 MKShowMouseCursor(); 02744 } else { 02745 MKHideMouseCursor(); 02746 } 02747 02748 // 02749 // Get the default ToggleKeys state. 02750 // 02751 // -------- flag --------------- value --------- default ------ 02752 // #define TKF_TOGGLEKEYSON 0x00000001 0 02753 // #define TKF_AVAILABLE 0x00000002 2 02754 // #define TKF_HOTKEYACTIVE 0x00000004 0 02755 // #define TKF_CONFIRMHOTKEY 0x00000008 0 02756 // #define TKF_HOTKEYSOUND 0x00000010 10 02757 // #define TKF_INDICATOR 0x00000020 0 02758 // ----------------------------------------- total = 0x12 = 18 02759 // 02760 dwDefFlags = FastGetProfileIntW(pProfileUserName, 02761 PMAP_TOGGLEKEYS, 02762 TEXT("Flags"), 02763 18 02764 ); 02765 02766 SET_OR_CLEAR_FLAG( 02767 dwDefFlags, 02768 TKF_TOGGLEKEYSON, 02769 TEST_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON)); 02770 02771 gToggleKeys.dwFlags = dwDefFlags; 02772 02773 // 02774 // Get the default Timeout state. 02775 // 02776 // -------- flag --------------- value --------- default ------ 02777 // #define ATF_TIMEOUTON 0x00000001 0 02778 // #define ATF_ONOFFFEEDBACK 0x00000002 2 02779 // ----------------------------------------- total = 0x2 = 2 02780 // 02781 dwDefFlags = FastGetProfileIntW(pProfileUserName, 02782 PMAP_TIMEOUT, 02783 TEXT("Flags"), 02784 2 02785 ); 02786 02787 SET_OR_CLEAR_FLAG( 02788 dwDefFlags, 02789 ATF_TIMEOUTON, 02790 TEST_ACCESSFLAG(AccessTimeOut, ATF_TIMEOUTON)); 02791 02792 gAccessTimeOut.dwFlags = dwDefFlags; 02793 02794 #ifdef FE_SB // 02795 if (gpKbdNlsTbl) { 02796 // 02797 // Is there any alternative MouseVKey table in KBDNLSTABLE ? 02798 // 02799 if ((gpKbdNlsTbl->NumOfMouseVKey == cMouseVKeys) && 02800 (gpKbdNlsTbl->pusMouseVKey != NULL)) { 02801 // 02802 // Overwite the pointer. 02803 // 02804 gpusMouseVKey = gpKbdNlsTbl->pusMouseVKey; 02805 } 02806 02807 // 02808 // Is there any remapping flag for VK_NUMLOCK/VK_SCROLL ? 02809 // 02810 if (gpKbdNlsTbl->LayoutInformation & NLSKBD_INFO_ACCESSIBILITY_KEYMAP) { 02811 // 02812 // Overwrite default. 02813 // 02814 gNumLockVk = VK_HOME; 02815 gOemScrollVk = VK_KANA; 02816 } 02817 } 02818 #endif // FE_SB 02819 02820 gAccessTimeOut.iTimeOutMSec = (DWORD)FastGetProfileIntW(pProfileUserName, 02821 PMAP_TIMEOUT, 02822 TEXT("TimeToWait"), 02823 300000 02824 ); // default is 5 minutes 02825 02826 /* 02827 * Get High Contrast state 02828 */ 02829 02830 dwDefFlags = FastGetProfileIntW(pProfileUserName, 02831 PMAP_HIGHCONTRAST, 02832 TEXT("Flags"), 02833 HCF_AVAILABLE | HCF_HOTKEYSOUND | HCF_HOTKEYAVAILABLE 02834 ); 02835 02836 SET_OR_CLEAR_FLAG( 02837 dwDefFlags, 02838 HCF_HIGHCONTRASTON, 02839 TEST_ACCESSFLAG(HighContrast, HCF_HIGHCONTRASTON)); 02840 02841 gHighContrast.dwFlags = dwDefFlags; 02842 02843 /* 02844 * Get scheme -- set up buffer 02845 */ 02846 02847 usHighContrastScheme.Buffer = wcHighContrastScheme; 02848 if (FastGetProfileStringW(pProfileUserName, 02849 PMAP_HIGHCONTRAST, 02850 TEXT("High Contrast Scheme"), 02851 NULL, 02852 wcHighContrastScheme, 02853 MAX_SCHEME_NAME_SIZE 02854 )) { 02855 02856 /* 02857 * copy data 02858 */ 02859 02860 wcscpy(gHighContrastDefaultScheme, usHighContrastScheme.Buffer); 02861 } 02862 02863 02864 AccessTimeOutReset(); 02865 SetAccessEnabledFlag(); 02866 } 02867 02868 02869 /***************************************************************************\ 02870 * SetAccessEnabledFlag 02871 * 02872 * Sets the global flag ACCF_ACCESSENABLED to non-zero if any accessibility 02873 * function is on or hot key activation is enabled. When TEST_ACCF(ACCF_ACCESSENABLED) 02874 * is zero keyboard input is processed directly. When TEST_ACCF(ACCF_ACCESSENABLED) is 02875 * non-zero keyboard input is filtered through AccessProceduresStream(). 02876 * See KeyboardApcProcedure in ntinput.c. 02877 * 02878 * History: 02879 * 01-19-94 GregoryW Created. 02880 \***************************************************************************/ 02881 VOID SetAccessEnabledFlag(VOID) 02882 { 02883 02884 SET_OR_CLEAR_ACCF(ACCF_ACCESSENABLED, 02885 TEST_ACCESSFLAG(FilterKeys, FKF_FILTERKEYSON) || 02886 TEST_ACCESSFLAG(FilterKeys, FKF_HOTKEYACTIVE) || 02887 TEST_ACCESSFLAG(StickyKeys, SKF_STICKYKEYSON) || 02888 TEST_ACCESSFLAG(StickyKeys, SKF_HOTKEYACTIVE) || 02889 TEST_ACCESSFLAG(HighContrast, HCF_HOTKEYACTIVE) || 02890 TEST_ACCESSFLAG(MouseKeys, MKF_MOUSEKEYSON) || 02891 TEST_ACCESSFLAG(MouseKeys, MKF_HOTKEYACTIVE) || 02892 TEST_ACCESSFLAG(ToggleKeys, TKF_TOGGLEKEYSON) || 02893 TEST_ACCESSFLAG(ToggleKeys, TKF_HOTKEYACTIVE) || 02894 TEST_ACCESSFLAG(SoundSentry, SSF_SOUNDSENTRYON)|| 02895 TEST_ACCF(ACCF_SHOWSOUNDSON)); 02896 } 02897 02898 VOID SoundSentryTimer(PWND pwnd, UINT message, UINT_PTR idTimer, LPARAM lParam) 02899 { 02900 TL tlpwndT; 02901 PWND pwndSoundSentry; 02902 02903 if (pwndSoundSentry = RevalidateHwnd(ghwndSoundSentry)) { 02904 ThreadLock(pwndSoundSentry, &tlpwndT); 02905 xxxFlashWindow(pwndSoundSentry, 02906 (TEST_BOOL_ACCF(ACCF_FIRSTTICK) ? FLASHW_ALL : FLASHW_STOP), 02907 0); 02908 ThreadUnlock(&tlpwndT); 02909 } 02910 02911 if (TEST_ACCF(ACCF_FIRSTTICK)) { 02912 gtmridSoundSentry = InternalSetTimer( 02913 NULL, 02914 idTimer, 02915 5, 02916 SoundSentryTimer, 02917 TMRF_RIT | TMRF_ONESHOT 02918 ); 02919 CLEAR_ACCF(ACCF_FIRSTTICK); 02920 } else { 02921 ghwndSoundSentry = NULL; 02922 gtmridSoundSentry = 0; 02923 SET_ACCF(ACCF_FIRSTTICK); 02924 } 02925 02926 return; 02927 02928 UNREFERENCED_PARAMETER(pwnd); 02929 UNREFERENCED_PARAMETER(message); 02930 UNREFERENCED_PARAMETER(lParam); 02931 } 02932 02933 /***************************************************************************\ 02934 * _UserSoundSentryWorker 02935 * 02936 * This is the worker routine that provides the visual feedback requested 02937 * by the user. 02938 * 02939 * History: 02940 * 08-02-93 GregoryW Created. 02941 \***************************************************************************/ 02942 BOOL 02943 _UserSoundSentryWorker(VOID) 02944 { 02945 PWND pwndActive; 02946 TL tlpwndT; 02947 02948 CheckCritIn(); 02949 // 02950 // Check to see if SoundSentry is on. 02951 // 02952 if (!TEST_ACCESSFLAG(SoundSentry, SSF_SOUNDSENTRYON)) { 02953 return TRUE; 02954 } 02955 02956 if ((gpqForeground != NULL) && (gpqForeground->spwndActive != NULL)) { 02957 pwndActive = gpqForeground->spwndActive; 02958 } else { 02959 return TRUE; 02960 } 02961 02962 switch (gSoundSentry.iWindowsEffect) { 02963 02964 case SSWF_NONE: 02965 break; 02966 02967 case SSWF_TITLE: 02968 // 02969 // Flash the active caption bar. 02970 // 02971 if (gtmridSoundSentry) { 02972 break; 02973 } 02974 ThreadLock(pwndActive, &tlpwndT); 02975 xxxFlashWindow(pwndActive, FLASHW_ALL, 0); 02976 ThreadUnlock(&tlpwndT); 02977 02978 ghwndSoundSentry = HWq(pwndActive); 02979 gtmridSoundSentry = InternalSetTimer( 02980 NULL, 02981 0, 02982 100, 02983 SoundSentryTimer, 02984 TMRF_RIT | TMRF_ONESHOT 02985 ); 02986 break; 02987 02988 case SSWF_WINDOW: 02989 { 02990 // 02991 // Flash the active window. 02992 // 02993 HDC hdc; 02994 RECT rc; 02995 02996 hdc = _GetWindowDC(pwndActive); 02997 _GetWindowRect(pwndActive, &rc); 02998 // 02999 // _GetWindowRect returns screen coordinates. First adjust them 03000 // to window (display) coordinates and then map them to logical 03001 // coordinates before calling InvertRect. 03002 // 03003 OffsetRect(&rc, -rc.left, -rc.top); 03004 GreDPtoLP(hdc, (LPPOINT)&rc, 2); 03005 InvertRect(hdc, &rc); 03006 InvertRect(hdc, &rc); 03007 _ReleaseDC(hdc); 03008 break; 03009 } 03010 03011 case SSWF_DISPLAY: 03012 { 03013 // 03014 // Flash the entire display. 03015 // 03016 HDC hdc; 03017 RECT rc; 03018 03019 hdc = _GetDCEx(PWNDDESKTOP(pwndActive), NULL, DCX_WINDOW | DCX_CACHE); 03020 rc.left = rc.top = 0; 03021 rc.right = SYSMET(CXVIRTUALSCREEN); 03022 rc.bottom = SYSMET(CYVIRTUALSCREEN); 03023 InvertRect(hdc, &rc); 03024 InvertRect(hdc, &rc); 03025 _ReleaseDC(hdc); 03026 break; 03027 } 03028 } 03029 03030 return TRUE; 03031 } 03032 03033 /***************************************************************************\ 03034 * UtilityManager 03035 * 03036 * This is the strategy routine that gets called as part of the input stream 03037 * processing. Utility Manager launching happens here. 03038 * 03039 * Return value: 03040 * TRUE - key event should be passed on to the next access routine. 03041 * FALSE - key event was processed and should not be passed on. 03042 * 03043 * History: 10-28-98 a-anilk created 03044 \***************************************************************************/ 03045 BOOL UtilityManager(PKE pKeyEvent, ULONG ExtraInformation, int NotUsed) 03046 { 03047 int CurrentModState; 03048 int fBreak; 03049 BYTE Vk; 03050 03051 03052 CheckCritIn(); 03053 03054 Vk = (BYTE)(pKeyEvent->usFlaggedVk & 0xff); 03055 fBreak = pKeyEvent->usFlaggedVk & KBDBREAK; 03056 CurrentModState = gLockBits | gLatchBits | gPhysModifierState; 03057 03058 // the hot key to launch the utility manager is WinKey + U 03059 if ((Vk == VK_U && !fBreak && (CurrentModState & LRWIN)) ) 03060 { 03061 PostAccessNotification(ACCESS_UTILITYMANAGER); 03062 03063 return FALSE; 03064 } 03065 return TRUE; // send key event to next accessibility routine. 03066 03067 UNREFERENCED_PARAMETER(NotUsed); 03068 UNREFERENCED_PARAMETER(ExtraInformation); 03069 } 03070

Generated on Sat May 15 19:39:12 2004 for test by doxygen 1.3.7