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

keyboard.c

Go to the documentation of this file.
00001 /****************************** Module Header ******************************\ 00002 * Module Name: keyboard.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * History: 00007 * 11-11-90 DavidPe Created. 00008 * 13-Feb-1991 mikeke Added Revalidation code (None) 00009 \***************************************************************************/ 00010 00011 #include "precomp.h" 00012 #pragma hdrstop 00013 00014 00015 /***************************************************************************\ 00016 * _GetKeyState (API) 00017 * 00018 * This API returns the up/down and toggle state of the specified VK based 00019 * on the input synchronized keystate in the current queue. The toggle state 00020 * is mainly for 'state' keys like Caps-Lock that are toggled each time you 00021 * press them. 00022 * 00023 * History: 00024 * 11-11-90 DavidPe Created. 00025 \***************************************************************************/ 00026 00027 SHORT _GetKeyState( 00028 int vk) 00029 { 00030 UINT wKeyState; 00031 PTHREADINFO pti; 00032 00033 if ((UINT)vk >= CVKKEYSTATE) { 00034 RIPERR1(ERROR_INVALID_PARAMETER, 00035 RIP_WARNING, 00036 "Invalid parameter \"vk\" (%ld) to _GetKeyState", 00037 vk); 00038 00039 return 0; 00040 } 00041 00042 pti = PtiCurrentShared(); 00043 00044 #ifdef LATER 00045 // 00046 // note - anything that accesses the pq structure is a bad idea since it 00047 // can be changed between any two instructions. 00048 // 00049 #endif 00050 00051 wKeyState = 0; 00052 00053 /* 00054 * Set the toggle bit. 00055 */ 00056 if (TestKeyStateToggle(pti->pq, vk)) 00057 wKeyState = 0x0001; 00058 00059 /* 00060 * Set the keyup/down bit. 00061 */ 00062 if (TestKeyStateDown(pti->pq, vk)) { 00063 /* 00064 * Used to be wKeyState|= 0x8000.Fix for bug 28820; Ctrl-Enter 00065 * accelerator doesn't work on Nestscape Navigator Mail 2.0 00066 */ 00067 wKeyState |= 0xff80; // This is what 3.1 returned!!!! 00068 } 00069 00070 return (SHORT)wKeyState; 00071 } 00072 00073 /***************************************************************************\ 00074 * _GetAsyncKeyState (API) 00075 * 00076 * This function is similar to GetKeyState except it returns what could be 00077 * considered the 'hardware' keystate or what state the key is in at the 00078 * moment the function is called, rather than based on what key events the 00079 * application has processed. Also, rather than returning the toggle bit, 00080 * it has a bit telling whether the key was pressed since the last call to 00081 * GetAsyncKeyState(). 00082 * 00083 * History: 00084 * 11-11-90 DavidPe Created. 00085 \***************************************************************************/ 00086 00087 SHORT _GetAsyncKeyState( 00088 int vk) 00089 { 00090 SHORT sKeyState; 00091 00092 if ((UINT)vk >= CVKKEYSTATE) { 00093 RIPERR1(ERROR_INVALID_PARAMETER, 00094 RIP_WARNING, 00095 "Invalid parameter \"vk\" (%ld) to _GetAsyncKeyState", 00096 vk); 00097 00098 return 0; 00099 } 00100 00101 /* 00102 * See if this key went down since the last time state for it was 00103 * read. Clear the flag if so. 00104 */ 00105 sKeyState = 0; 00106 if (TestAsyncKeyStateRecentDown(vk)) { 00107 ClearAsyncKeyStateRecentDown(vk); 00108 sKeyState = 1; 00109 } 00110 00111 /* 00112 * Set the keyup/down bit. 00113 */ 00114 if (TestAsyncKeyStateDown(vk)) 00115 sKeyState |= 0x8000; 00116 00117 /* 00118 * Don't return the toggle bit since it's a new bit and might 00119 * cause compatibility problems. 00120 */ 00121 return sKeyState; 00122 } 00123 00124 /***************************************************************************\ 00125 * _SetKeyboardState (API) 00126 * 00127 * This function allows the app to set the current keystate. This is mainly 00128 * useful for setting the toggle bit, particularly for the keys associated 00129 * with the LEDs on the physical keyboard. 00130 * 00131 * History: 00132 * 11-11-90 DavidPe Created. 00133 * 16-May-1991 mikeke Changed to return BOOL 00134 \***************************************************************************/ 00135 00136 BOOL _SetKeyboardState( 00137 CONST BYTE *pb) 00138 { 00139 int i; 00140 PQ pq; 00141 PTHREADINFO ptiCurrent = PtiCurrent(); 00142 00143 pq = ptiCurrent->pq; 00144 00145 /* 00146 * Copy in the new state table. 00147 */ 00148 for (i = 0; i < 256; i++, pb++) { 00149 if (*pb & 0x80) { 00150 SetKeyStateDown(pq, i); 00151 } else { 00152 ClearKeyStateDown(pq, i); 00153 } 00154 00155 if (*pb & 0x01) { 00156 SetKeyStateToggle(pq, i); 00157 } else { 00158 ClearKeyStateToggle(pq, i); 00159 } 00160 } 00161 00162 /* 00163 * Update the key cache index. 00164 */ 00165 gpsi->dwKeyCache++; 00166 00167 #ifdef LATER 00168 // scottlu 6-9-91 00169 // I don't think we ought to do this unless someone really complains. This 00170 // could have bad side affects, especially considering that terminal 00171 // apps will want to do this, and terminal apps could easily not respond 00172 // to input for awhile, causing this state to change unexpectedly while 00173 // a user is using some other application. - scottlu. 00174 00175 /* DavidPe 02/05/92 00176 * How about if we only do it when the calling app is foreground? 00177 */ 00178 00179 /* 00180 * Propagate the toggle bits for the keylight keys to the 00181 * async keystate table and update the keylights. 00182 * 00183 * THIS could be evil in a de-synced environment, but to do this 00184 * in a totally "synchronous" way is hard. 00185 */ 00186 if (pb[VK_CAPITAL] & 0x01) { 00187 SetAsyncKeyStateToggle(VK_CAPITAL); 00188 } else { 00189 ClearAsyncKeyStateToggle(VK_CAPITAL); 00190 } 00191 00192 if (pb[VK_NUMLOCK] & 0x01) { 00193 SetAsyncKeyStateToggle(VK_NUMLOCK); 00194 } else { 00195 ClearAsyncKeyStateToggle(VK_NUMLOCK); 00196 } 00197 00198 if (pb[VK_SCROLL] & 0x01) { 00199 SetAsyncKeyStateToggle(VK_SCROLL); 00200 } else { 00201 ClearAsyncKeyStateToggle(VK_SCROLL); 00202 } 00203 00204 UpdateKeyLights(TRUE); 00205 #endif 00206 00207 return TRUE; 00208 } 00209 00210 /***************************************************************************\ 00211 * RegisterPerUserKeyboardIndicators 00212 * 00213 * Saves the current keyboard indicators in the user's profile. 00214 * 00215 * ASSUMPTIONS: 00216 * 00217 * 10-14-92 IanJa Created. 00218 \***************************************************************************/ 00219 00220 static CONST WCHAR wszInitialKeyboardIndicators[] = L"InitialKeyboardIndicators"; 00221 00222 VOID 00223 RegisterPerUserKeyboardIndicators(PUNICODE_STRING pProfileUserName) 00224 { 00225 WCHAR wszInitKbdInd[2] = L"0"; 00226 00227 /* 00228 * Initial Keyboard state (Num-Lock only) 00229 */ 00230 00231 /* 00232 * For HYDRA we do not want to save this as set, since it confuses 00233 * dial in laptop computers. So we force it off in the profile on 00234 * logoff. 00235 */ 00236 if (!ISTS()) { 00237 wszInitKbdInd[0] += TestAsyncKeyStateToggle(VK_NUMLOCK) ? 2 : 0; 00238 } 00239 00240 FastWriteProfileStringW(pProfileUserName, 00241 PMAP_KEYBOARD, 00242 wszInitialKeyboardIndicators, 00243 wszInitKbdInd); 00244 } 00245 00246 /***************************************************************************\ 00247 * UpdatePerUserKeyboardIndicators 00248 * 00249 * Sets the initial keyboard indicators according to the user's profile. 00250 * 00251 * ASSUMPTIONS: 00252 * 00253 * 10-14-92 IanJa Created. 00254 \***************************************************************************/ 00255 VOID 00256 UpdatePerUserKeyboardIndicators(PUNICODE_STRING pProfileUserName) 00257 { 00258 DWORD dw; 00259 PQ pq; 00260 PTHREADINFO ptiCurrent = PtiCurrent(); 00261 pq = ptiCurrent->pq; 00262 00263 /* 00264 * For terminal server, the client is responsible for synchronizing the 00265 * keyboard state. 00266 */ 00267 if (gbRemoteSession) { 00268 return; 00269 } 00270 00271 /* 00272 * Initial Keyboard state (Num-Lock only) 00273 */ 00274 dw = FastGetProfileIntW(pProfileUserName, 00275 PMAP_KEYBOARD, 00276 wszInitialKeyboardIndicators, 00277 2); 00278 00279 dw &= 0x80000002; 00280 00281 00282 /* 00283 * The special value 0x80000000 in the registry indicates that the BIOS 00284 * settings are to be used as the initial LED state. (This is undocumented) 00285 */ 00286 if (dw == 0x80000000) { 00287 dw = gklpBootTime.LedFlags; 00288 } 00289 if (dw & 0x02) { 00290 SetKeyStateToggle(pq, VK_NUMLOCK); 00291 SetAsyncKeyStateToggle(VK_NUMLOCK); 00292 SetRawKeyToggle(VK_NUMLOCK); 00293 } else { 00294 ClearKeyStateToggle(pq, VK_NUMLOCK); 00295 ClearAsyncKeyStateToggle(VK_NUMLOCK); 00296 ClearRawKeyToggle(VK_NUMLOCK); 00297 } 00298 00299 /* 00300 * Initialize KANA Toggle status 00301 */ 00302 gfKanaToggle = FALSE; 00303 ClearKeyStateToggle(pq, VK_KANA); 00304 ClearAsyncKeyStateToggle(VK_KANA); 00305 ClearRawKeyToggle(VK_KANA); 00306 00307 UpdateKeyLights(FALSE); 00308 } 00309 00310 00311 /***************************************************************************\ 00312 * UpdateAsyncKeyState 00313 * 00314 * Based on a VK and a make/break flag, this function will update the async 00315 * keystate table. 00316 * 00317 * History: 00318 * 06-09-91 ScottLu Added keystate synchronization across threads. 00319 * 11-12-90 DavidPe Created. 00320 \***************************************************************************/ 00321 00322 void UpdateAsyncKeyState( 00323 PQ pqOwner, 00324 UINT wVK, 00325 BOOL fBreak) 00326 { 00327 PQ pqT; 00328 PLIST_ENTRY pHead, pEntry; 00329 PTHREADINFO pti; 00330 00331 CheckCritIn(); 00332 00333 /* 00334 * First check to see if the queue this key is going to has a pending 00335 * key state event. If it does, post it because we need to copy the 00336 * async key state into this event as it is before we modify 00337 * this key's state, or else we'll generate a key state event with 00338 * the wrong key state in it. 00339 */ 00340 if (pqOwner != NULL && pqOwner->QF_flags & QF_UPDATEKEYSTATE) { 00341 PostUpdateKeyStateEvent(pqOwner); 00342 } 00343 00344 if (!fBreak) { 00345 /* 00346 * This key has gone down - update the "recent down" bit in the 00347 * async key state table. 00348 */ 00349 SetAsyncKeyStateRecentDown(wVK); 00350 00351 /* 00352 * This is a key make. If the key was not already down, update the 00353 * toggle bit. 00354 */ 00355 if (!TestAsyncKeyStateDown(wVK)) { 00356 if (TestAsyncKeyStateToggle(wVK)) { 00357 ClearAsyncKeyStateToggle(wVK); 00358 } else { 00359 SetAsyncKeyStateToggle(wVK); 00360 } 00361 } 00362 00363 /* 00364 * This is a make, so turn on the key down bit. 00365 */ 00366 SetAsyncKeyStateDown(wVK); 00367 00368 } else { 00369 /* 00370 * This is a break, so turn off the key down bit. 00371 */ 00372 ClearAsyncKeyStateDown(wVK); 00373 } 00374 00375 /* 00376 * If this is one of the keys we cache, update the async key cache index. 00377 */ 00378 if (wVK < CVKASYNCKEYCACHE) { 00379 gpsi->dwAsyncKeyCache++; 00380 } 00381 00382 /* 00383 * A key has changed state. Update all queues not receiving this input so 00384 * they know that this key has changed state. This lets us know which keys to 00385 * update in the thread specific key state table to keep it in sync 00386 * with the user. Walking down the thread list may mean that an 00387 * individual queue may by updated more than once, but it is cheaper 00388 * than maintaining a list of queues on the desktop. 00389 */ 00390 UserAssert(grpdeskRitInput != NULL); 00391 00392 pHead = &grpdeskRitInput->PtiList; 00393 for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink) { 00394 pti = CONTAINING_RECORD(pEntry, THREADINFO, PtiLink); 00395 00396 /* 00397 * Don't update the queue this message is going to - it'll be 00398 * in sync because it is receiving this message. 00399 */ 00400 pqT = pti->pq; 00401 if (pqT == pqOwner) 00402 continue; 00403 00404 /* 00405 * Set the "recent down" bit. In this case this doesn't really mean 00406 * "recent down", it means "recent change" (since the last time 00407 * we synced this queue), either up or down. This tells us which 00408 * keys went down since the last time this thread synced with key 00409 * state. Set the "update key state" flag so we know that later 00410 * we need to sync with these keys. 00411 */ 00412 SetKeyRecentDownBit(pqT->afKeyRecentDown, wVK); 00413 pqT->QF_flags |= QF_UPDATEKEYSTATE; 00414 } 00415 00416 /* 00417 * Update the key cache index. 00418 */ 00419 gpsi->dwKeyCache++; 00420 }

Generated on Sat May 15 19:40:35 2004 for test by doxygen 1.3.7