llkeyboardwin32.cpp

Go to the documentation of this file.
00001 
00032 #if LL_WINDOWS
00033 
00034 #include "linden_common.h"
00035 
00036 #include "llkeyboardwin32.h"
00037 
00038 #include "llwindow.h"
00039 
00040 #define WIN32_LEAN_AND_MEAN
00041 #include <winsock2.h>
00042 #include <windows.h>
00043 
00044 LLKeyboardWin32::LLKeyboardWin32()
00045 {
00046         // Set up key mapping for windows - eventually can read this from a file?
00047         // Anything not in the key map gets dropped
00048         // Add default A-Z
00049 
00050         // Virtual key mappings from WinUser.h
00051 
00052         KEY cur_char;
00053         for (cur_char = 'A'; cur_char <= 'Z'; cur_char++)
00054         {
00055                 mTranslateKeyMap[cur_char] = (KEY)cur_char;
00056         }
00057 
00058         for (cur_char = '0'; cur_char <= '9'; cur_char++)
00059         {
00060                 mTranslateKeyMap[cur_char] = (KEY)cur_char;
00061         }
00062         // numpad number keys
00063         for (cur_char = 0x60; cur_char <= 0x69; cur_char++)
00064         {
00065                 mTranslateKeyMap[cur_char] = (KEY)('0' + (0x60 - cur_char));
00066         }
00067 
00068 
00069         mTranslateKeyMap[VK_SPACE] = ' ';
00070         mTranslateKeyMap[VK_OEM_1] = ';';
00071         // When the user hits, for example, Ctrl-= as a keyboard shortcut,
00072         // Windows generates VK_OEM_PLUS.  This is true on both QWERTY and DVORAK
00073         // keyboards in the US.  Numeric keypad '+' generates VK_ADD below.
00074         // Thus we translate it as '='.
00075         // Potential bug: This may not be true on international keyboards. JC
00076         mTranslateKeyMap[VK_OEM_PLUS]   = '=';
00077         mTranslateKeyMap[VK_OEM_COMMA]  = ',';
00078         mTranslateKeyMap[VK_OEM_MINUS]  = '-';
00079         mTranslateKeyMap[VK_OEM_PERIOD] = '.';
00080         mTranslateKeyMap[VK_OEM_2] = '/';
00081         mTranslateKeyMap[VK_OEM_3] = '`';
00082         mTranslateKeyMap[VK_OEM_4] = '[';
00083         mTranslateKeyMap[VK_OEM_5] = '\\';
00084         mTranslateKeyMap[VK_OEM_6] = ']';
00085         mTranslateKeyMap[VK_OEM_7] = '\'';
00086         mTranslateKeyMap[VK_ESCAPE] = KEY_ESCAPE;
00087         mTranslateKeyMap[VK_RETURN] = KEY_RETURN;
00088         mTranslateKeyMap[VK_LEFT] = KEY_LEFT;
00089         mTranslateKeyMap[VK_RIGHT] = KEY_RIGHT;
00090         mTranslateKeyMap[VK_UP] = KEY_UP;
00091         mTranslateKeyMap[VK_DOWN] = KEY_DOWN;
00092         mTranslateKeyMap[VK_BACK] = KEY_BACKSPACE;
00093         mTranslateKeyMap[VK_INSERT] = KEY_INSERT;
00094         mTranslateKeyMap[VK_DELETE] = KEY_DELETE;
00095         mTranslateKeyMap[VK_SHIFT] = KEY_SHIFT;
00096         mTranslateKeyMap[VK_CONTROL] = KEY_CONTROL;
00097         mTranslateKeyMap[VK_MENU] = KEY_ALT;
00098         mTranslateKeyMap[VK_CAPITAL] = KEY_CAPSLOCK;
00099         mTranslateKeyMap[VK_HOME] = KEY_HOME;
00100         mTranslateKeyMap[VK_END] = KEY_END;
00101         mTranslateKeyMap[VK_PRIOR] = KEY_PAGE_UP;
00102         mTranslateKeyMap[VK_NEXT] = KEY_PAGE_DOWN;
00103         mTranslateKeyMap[VK_TAB] = KEY_TAB;
00104         mTranslateKeyMap[VK_ADD] = KEY_ADD;
00105         mTranslateKeyMap[VK_SUBTRACT] = KEY_SUBTRACT;
00106         mTranslateKeyMap[VK_MULTIPLY] = KEY_MULTIPLY;
00107         mTranslateKeyMap[VK_DIVIDE] = KEY_DIVIDE;
00108         mTranslateKeyMap[VK_F1] = KEY_F1;
00109         mTranslateKeyMap[VK_F2] = KEY_F2;
00110         mTranslateKeyMap[VK_F3] = KEY_F3;
00111         mTranslateKeyMap[VK_F4] = KEY_F4;
00112         mTranslateKeyMap[VK_F5] = KEY_F5;
00113         mTranslateKeyMap[VK_F6] = KEY_F6;
00114         mTranslateKeyMap[VK_F7] = KEY_F7;
00115         mTranslateKeyMap[VK_F8] = KEY_F8;
00116         mTranslateKeyMap[VK_F9] = KEY_F9;
00117         mTranslateKeyMap[VK_F10] = KEY_F10;
00118         mTranslateKeyMap[VK_F11] = KEY_F11;
00119         mTranslateKeyMap[VK_F12] = KEY_F12;
00120         mTranslateKeyMap[VK_CLEAR] = KEY_PAD_CENTER;
00121 
00122         // Build inverse map
00123         std::map<U16, KEY>::iterator iter;
00124         for (iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++)
00125         {
00126                 mInvTranslateKeyMap[iter->second] = iter->first;
00127         }
00128 
00129         // numpad map
00130         mTranslateNumpadMap[0x60] = KEY_PAD_INS;        // keypad 0
00131         mTranslateNumpadMap[0x61] = KEY_PAD_END;        // keypad 1
00132         mTranslateNumpadMap[0x62] = KEY_PAD_DOWN;       // keypad 2
00133         mTranslateNumpadMap[0x63] = KEY_PAD_PGDN;       // keypad 3
00134         mTranslateNumpadMap[0x64] = KEY_PAD_LEFT;       // keypad 4
00135         mTranslateNumpadMap[0x65] = KEY_PAD_CENTER;     // keypad 5
00136         mTranslateNumpadMap[0x66] = KEY_PAD_RIGHT;      // keypad 6
00137         mTranslateNumpadMap[0x67] = KEY_PAD_HOME;       // keypad 7
00138         mTranslateNumpadMap[0x68] = KEY_PAD_UP;         // keypad 8
00139         mTranslateNumpadMap[0x69] = KEY_PAD_PGUP;       // keypad 9
00140         mTranslateNumpadMap[0x6E] = KEY_PAD_DEL;        // keypad .
00141 
00142         for (iter = mTranslateNumpadMap.begin(); iter != mTranslateNumpadMap.end(); iter++)
00143         {
00144                 mInvTranslateNumpadMap[iter->second] = iter->first;
00145         }
00146 }
00147 
00148 // Asynchronously poll the control, alt and shift keys and set the
00149 // appropriate states.
00150 // Note: this does not generate edges.
00151 void LLKeyboardWin32::resetMaskKeys()
00152 {
00153         // GetAsyncKeyState returns a short and uses the most significant
00154         // bit to indicate that the key is down.
00155         if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
00156         {
00157                 mKeyLevel[KEY_SHIFT] = TRUE;
00158         }
00159 
00160         if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
00161         {
00162                 mKeyLevel[KEY_CONTROL] = TRUE;
00163         }
00164 
00165         if (GetAsyncKeyState(VK_MENU) & 0x8000)
00166         {
00167                 mKeyLevel[KEY_ALT] = TRUE;
00168         }
00169 }
00170 
00171 
00172 //void LLKeyboardWin32::setModifierKeyLevel( KEY key, BOOL new_state )
00173 //{
00174 //      if( mKeyLevel[key] != new_state )
00175 //      {
00176 //              mKeyLevelFrameCount[key] = 0;
00177 //
00178 //              if( new_state )
00179 //              {
00180 //                      mKeyLevelTimer[key].reset();
00181 //              }
00182 //              mKeyLevel[key] = new_state;
00183 //      }
00184 //}
00185 
00186 
00187 MASK LLKeyboardWin32::updateModifiers()
00188 {
00189         //RN: this seems redundant, as we should have already received the appropriate
00190         // messages for the modifier keys
00191 
00192         // Scan the modifier keys as of the last Windows key message
00193         // (keydown encoded in high order bit of short)
00194         mKeyLevel[KEY_CAPSLOCK] = (GetKeyState(VK_CAPITAL) & 0x0001) != 0; // Low order bit carries the toggle state.
00195         // Get mask for keyboard events
00196         MASK mask = currentMask(FALSE);
00197         return mask;
00198 }
00199 
00200 
00201 // mask is ignored, except for extended flag -- we poll the modifier keys for the other flags
00202 BOOL LLKeyboardWin32::handleKeyDown(const U16 key, MASK mask)
00203 {
00204         KEY             translated_key;
00205         U32             translated_mask;
00206         BOOL    handled = FALSE;
00207 
00208         translated_mask = updateModifiers();
00209 
00210         if (translateExtendedKey(key, mask, &translated_key))
00211         {
00212                 handled = handleTranslatedKeyDown(translated_key, translated_mask);
00213         }
00214 
00215         return handled;
00216 }
00217 
00218 // mask is ignored, except for extended flag -- we poll the modifier keys for the other flags
00219 BOOL LLKeyboardWin32::handleKeyUp(const U16 key, MASK mask)
00220 {
00221         KEY             translated_key;
00222         U32             translated_mask;
00223         BOOL    handled = FALSE;
00224 
00225         translated_mask = updateModifiers();
00226 
00227         if (translateExtendedKey(key, mask, &translated_key))
00228         {
00229                 handled = handleTranslatedKeyUp(translated_key, translated_mask);
00230         }
00231 
00232         return handled;
00233 }
00234 
00235 
00236 MASK LLKeyboardWin32::currentMask(BOOL)
00237 {
00238         MASK mask = MASK_NONE;
00239 
00240         if (mKeyLevel[KEY_SHIFT])               mask |= MASK_SHIFT;
00241         if (mKeyLevel[KEY_CONTROL])             mask |= MASK_CONTROL;
00242         if (mKeyLevel[KEY_ALT])                 mask |= MASK_ALT;
00243 
00244         return mask;
00245 }
00246 
00247 
00248 void LLKeyboardWin32::scanKeyboard()
00249 {
00250         S32 key;
00251         MSG     msg;
00252         BOOL pending_key_events = PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE | PM_NOYIELD);
00253         for (key = 0; key < KEY_COUNT; key++)
00254         {
00255                 // On Windows, verify key down state. JC
00256                 // RN: only do this if we don't have further key events in the queue
00257                 // as otherwise there might be key repeat events still waiting for this key we are now dumping
00258                 if (!pending_key_events && mKeyLevel[key])
00259                 {
00260                         // *TODO: I KNOW there must be a better way of
00261                         // interrogating the key state than this, using async key
00262                         // state can cause ALL kinds of bugs - Doug
00263                         if (key < KEY_BUTTON0)
00264                         {
00265                                 // ...under windows make sure the key actually still is down.
00266                                 // ...translate back to windows key
00267                                 U16 virtual_key = inverseTranslateExtendedKey(key);
00268                                 // keydown in highest bit
00269                                 if (!pending_key_events && !(GetAsyncKeyState(virtual_key) & 0x8000))
00270                                 {
00271                                         //llinfos << "Key up event missed, resetting" << llendl;
00272                                         mKeyLevel[key] = FALSE;
00273                                 }
00274                         }
00275                 }
00276 
00277                 // Generate callback if any event has occurred on this key this frame.
00278                 // Can't just test mKeyLevel, because this could be a slow frame and
00279                 // key might have gone down then up. JC
00280                 if (mKeyLevel[key] || mKeyDown[key] || mKeyUp[key])
00281                 {
00282                         mCurScanKey = key;
00283                         mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]);
00284                 }
00285         }
00286 
00287         // Reset edges for next frame
00288         for (key = 0; key < KEY_COUNT; key++)
00289         {
00290                 mKeyUp[key] = FALSE;
00291                 mKeyDown[key] = FALSE;
00292                 if (mKeyLevel[key])
00293                 {
00294                         mKeyLevelFrameCount[key]++;
00295                 }
00296         }
00297 }
00298 
00299 BOOL LLKeyboardWin32::translateExtendedKey(const U16 os_key, const MASK mask, KEY *translated_key)
00300 {
00301         if(mNumpadDistinct == ND_NUMLOCK_ON)
00302         {
00303                 std::map<U16, KEY>::iterator iter = mTranslateNumpadMap.find(os_key);
00304                 if (iter != mTranslateNumpadMap.end())
00305                 {
00306                         *translated_key = iter->second;
00307                         return TRUE;
00308                 }
00309         }
00310 
00311         BOOL success = translateKey(os_key, translated_key);
00312         if(mNumpadDistinct != ND_NEVER) {
00313                 if(!success) return success;
00314                 if(mask & MASK_EXTENDED) 
00315                 {
00316                         // this is where we'd create new keycodes for extended keys
00317                         // the set of extended keys includes the 'normal' arrow keys and 
00318                         // the pgup/dn/insert/home/end/delete cluster above the arrow keys
00319                         // see http://windowssdk.msdn.microsoft.com/en-us/library/ms646280.aspx
00320 
00321                         // only process the return key if numlock is off
00322                         if(((mNumpadDistinct == ND_NUMLOCK_OFF && 
00323                                  !(GetKeyState(VK_NUMLOCK) & 1)) 
00324                                  || mNumpadDistinct == ND_NUMLOCK_ON) &&
00325                                         *translated_key == KEY_RETURN) {
00326                                         *translated_key = KEY_PAD_RETURN;
00327                         }
00328                 }
00329                 else 
00330                 {
00331                         // the non-extended keys, those are in the numpad
00332                         switch (*translated_key) 
00333                         {
00334                                 case KEY_LEFT:
00335                                         *translated_key = KEY_PAD_LEFT; break;
00336                                 case KEY_RIGHT: 
00337                                         *translated_key = KEY_PAD_RIGHT; break;
00338                                 case KEY_UP: 
00339                                         *translated_key = KEY_PAD_UP; break;
00340                                 case KEY_DOWN:
00341                                         *translated_key = KEY_PAD_DOWN; break;
00342                                 case KEY_HOME:
00343                                         *translated_key = KEY_PAD_HOME; break;
00344                                 case KEY_END:
00345                                         *translated_key = KEY_PAD_END; break;
00346                                 case KEY_PAGE_UP:
00347                                         *translated_key = KEY_PAD_PGUP; break;
00348                                 case KEY_PAGE_DOWN:
00349                                         *translated_key = KEY_PAD_PGDN; break;
00350                                 case KEY_INSERT:
00351                                         *translated_key = KEY_PAD_INS; break;
00352                                 case KEY_DELETE:
00353                                         *translated_key = KEY_PAD_DEL; break;
00354                         }
00355                 }
00356         }
00357         return success;
00358 }
00359 
00360 U16  LLKeyboardWin32::inverseTranslateExtendedKey(const KEY translated_key)
00361 {
00362         // if numlock is on, then we need to translate KEY_PAD_FOO to the corresponding number pad number
00363         if((mNumpadDistinct == ND_NUMLOCK_ON) && (GetKeyState(VK_NUMLOCK) & 1))
00364         {
00365                 std::map<KEY, U16>::iterator iter = mInvTranslateNumpadMap.find(translated_key);
00366                 if (iter != mInvTranslateNumpadMap.end())
00367                 {
00368                         return iter->second;
00369                 }
00370         }
00371 
00372         // if numlock is off or we're not converting numbers to arrows, we map our keypad arrows
00373         // to regular arrows since Windows doesn't distinguish between them
00374         KEY converted_key = translated_key;
00375         switch (converted_key) 
00376         {
00377                 case KEY_PAD_LEFT:
00378                         converted_key = KEY_LEFT; break;
00379                 case KEY_PAD_RIGHT: 
00380                         converted_key = KEY_RIGHT; break;
00381                 case KEY_PAD_UP: 
00382                         converted_key = KEY_UP; break;
00383                 case KEY_PAD_DOWN:
00384                         converted_key = KEY_DOWN; break;
00385                 case KEY_PAD_HOME:
00386                         converted_key = KEY_HOME; break;
00387                 case KEY_PAD_END:
00388                         converted_key = KEY_END; break;
00389                 case KEY_PAD_PGUP:
00390                         converted_key = KEY_PAGE_UP; break;
00391                 case KEY_PAD_PGDN:
00392                         converted_key = KEY_PAGE_DOWN; break;
00393                 case KEY_PAD_INS:
00394                         converted_key = KEY_INSERT; break;
00395                 case KEY_PAD_DEL:
00396                         converted_key = KEY_DELETE; break;
00397                 case KEY_PAD_RETURN:
00398                         converted_key = KEY_RETURN; break;
00399         }
00400         // convert our virtual keys to OS keys
00401         return inverseTranslateKey(converted_key);
00402 }
00403 
00404 #endif

Generated on Thu Jul 1 06:08:47 2010 for Second Life Viewer by  doxygen 1.4.7