llkeyboardsdl.cpp

Go to the documentation of this file.
00001 
00032 #if LL_SDL
00033 
00034 #include "linden_common.h"
00035 #include "llkeyboardsdl.h"
00036 #include "llwindow.h"
00037 #include "SDL/SDL.h"
00038 
00039 LLKeyboardSDL::LLKeyboardSDL()
00040 {
00041         // Set up key mapping for SDL - eventually can read this from a file?
00042         // Anything not in the key map gets dropped
00043         // Add default A-Z
00044 
00045         // Virtual key mappings from SDL_keysym.h ...
00046 
00047         // SDL maps the letter keys to the ASCII you'd expect, but it's lowercase...
00048         U16 cur_char;
00049         for (cur_char = 'A'; cur_char <= 'Z'; cur_char++)
00050         {
00051                 mTranslateKeyMap[cur_char] = cur_char;
00052         }
00053         for (cur_char = 'a'; cur_char <= 'z'; cur_char++)
00054         {
00055                 mTranslateKeyMap[cur_char] = (cur_char - 'a') + 'A';
00056         }
00057 
00058         for (cur_char = '0'; cur_char <= '9'; cur_char++)
00059         {
00060                 mTranslateKeyMap[cur_char] = cur_char;
00061         }
00062 
00063         // These ones are translated manually upon keydown/keyup because
00064         // SDL doesn't handle their numlock transition.
00065         //mTranslateKeyMap[SDLK_KP4] = KEY_PAD_LEFT;
00066         //mTranslateKeyMap[SDLK_KP6] = KEY_PAD_RIGHT;
00067         //mTranslateKeyMap[SDLK_KP8] = KEY_PAD_UP;
00068         //mTranslateKeyMap[SDLK_KP2] = KEY_PAD_DOWN;
00069         //mTranslateKeyMap[SDLK_KP_PERIOD] = KEY_DELETE;
00070         //mTranslateKeyMap[SDLK_KP7] = KEY_HOME;
00071         //mTranslateKeyMap[SDLK_KP1] = KEY_END;
00072         //mTranslateKeyMap[SDLK_KP9] = KEY_PAGE_UP;
00073         //mTranslateKeyMap[SDLK_KP3] = KEY_PAGE_DOWN;
00074         //mTranslateKeyMap[SDLK_KP0] = KEY_INSERT;
00075 
00076         mTranslateKeyMap[SDLK_SPACE] = ' ';
00077         mTranslateKeyMap[SDLK_RETURN] = KEY_RETURN;
00078         mTranslateKeyMap[SDLK_LEFT] = KEY_LEFT;
00079         mTranslateKeyMap[SDLK_RIGHT] = KEY_RIGHT;
00080         mTranslateKeyMap[SDLK_UP] = KEY_UP;
00081         mTranslateKeyMap[SDLK_DOWN] = KEY_DOWN;
00082         mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE;
00083         mTranslateKeyMap[SDLK_KP_ENTER] = KEY_RETURN;
00084         mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE;
00085         mTranslateKeyMap[SDLK_BACKSPACE] = KEY_BACKSPACE;
00086         mTranslateKeyMap[SDLK_DELETE] = KEY_DELETE;
00087         mTranslateKeyMap[SDLK_LSHIFT] = KEY_SHIFT;
00088         mTranslateKeyMap[SDLK_RSHIFT] = KEY_SHIFT;
00089         mTranslateKeyMap[SDLK_LCTRL] = KEY_CONTROL;
00090         mTranslateKeyMap[SDLK_RCTRL] = KEY_CONTROL;
00091         mTranslateKeyMap[SDLK_LALT] = KEY_ALT;
00092         mTranslateKeyMap[SDLK_RALT] = KEY_ALT;
00093         mTranslateKeyMap[SDLK_HOME] = KEY_HOME;
00094         mTranslateKeyMap[SDLK_END] = KEY_END;
00095         mTranslateKeyMap[SDLK_PAGEUP] = KEY_PAGE_UP;
00096         mTranslateKeyMap[SDLK_PAGEDOWN] = KEY_PAGE_DOWN;
00097         mTranslateKeyMap[SDLK_MINUS] = KEY_HYPHEN;
00098         mTranslateKeyMap[SDLK_EQUALS] = KEY_EQUALS;
00099         mTranslateKeyMap[SDLK_KP_EQUALS] = KEY_EQUALS;
00100         mTranslateKeyMap[SDLK_INSERT] = KEY_INSERT;
00101         mTranslateKeyMap[SDLK_CAPSLOCK] = KEY_CAPSLOCK;
00102         mTranslateKeyMap[SDLK_TAB] = KEY_TAB;
00103         mTranslateKeyMap[SDLK_KP_PLUS] = KEY_ADD;
00104         mTranslateKeyMap[SDLK_KP_MINUS] = KEY_SUBTRACT;
00105         mTranslateKeyMap[SDLK_KP_MULTIPLY] = KEY_MULTIPLY;
00106         mTranslateKeyMap[SDLK_KP_DIVIDE] = KEY_PAD_DIVIDE;
00107         mTranslateKeyMap[SDLK_F1] = KEY_F1;
00108         mTranslateKeyMap[SDLK_F2] = KEY_F2;
00109         mTranslateKeyMap[SDLK_F3] = KEY_F3;
00110         mTranslateKeyMap[SDLK_F4] = KEY_F4;
00111         mTranslateKeyMap[SDLK_F5] = KEY_F5;
00112         mTranslateKeyMap[SDLK_F6] = KEY_F6;
00113         mTranslateKeyMap[SDLK_F7] = KEY_F7;
00114         mTranslateKeyMap[SDLK_F8] = KEY_F8;
00115         mTranslateKeyMap[SDLK_F9] = KEY_F9;
00116         mTranslateKeyMap[SDLK_F10] = KEY_F10;
00117         mTranslateKeyMap[SDLK_F11] = KEY_F11;
00118         mTranslateKeyMap[SDLK_F12] = KEY_F12;
00119         mTranslateKeyMap[SDLK_PLUS]   = '=';
00120         mTranslateKeyMap[SDLK_COMMA]  = ',';
00121         mTranslateKeyMap[SDLK_MINUS]  = '-';
00122         mTranslateKeyMap[SDLK_PERIOD] = '.';
00123         mTranslateKeyMap[SDLK_BACKQUOTE] = '`';
00124         mTranslateKeyMap[SDLK_SLASH] = KEY_DIVIDE;
00125         mTranslateKeyMap[SDLK_SEMICOLON] = ';';
00126         mTranslateKeyMap[SDLK_LEFTBRACKET] = '[';
00127         mTranslateKeyMap[SDLK_BACKSLASH] = '\\';
00128         mTranslateKeyMap[SDLK_RIGHTBRACKET] = ']';
00129         mTranslateKeyMap[SDLK_QUOTE] = '\'';
00130 
00131         // Build inverse map
00132         std::map<U16, KEY>::iterator iter;
00133         for (iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++)
00134         {
00135                 mInvTranslateKeyMap[iter->second] = iter->first;
00136         }
00137 
00138         // numpad map
00139         mTranslateNumpadMap[SDLK_KP0] = KEY_PAD_INS;
00140         mTranslateNumpadMap[SDLK_KP1] = KEY_PAD_END;
00141         mTranslateNumpadMap[SDLK_KP2] = KEY_PAD_DOWN;
00142         mTranslateNumpadMap[SDLK_KP3] = KEY_PAD_PGDN;
00143         mTranslateNumpadMap[SDLK_KP4] = KEY_PAD_LEFT;
00144         mTranslateNumpadMap[SDLK_KP5] = KEY_PAD_CENTER;
00145         mTranslateNumpadMap[SDLK_KP6] = KEY_PAD_RIGHT;
00146         mTranslateNumpadMap[SDLK_KP7] = KEY_PAD_HOME;
00147         mTranslateNumpadMap[SDLK_KP8] = KEY_PAD_UP;
00148         mTranslateNumpadMap[SDLK_KP9] = KEY_PAD_PGUP;
00149         mTranslateNumpadMap[SDLK_KP_PERIOD] = KEY_PAD_DEL;
00150 
00151         // build inverse numpad map
00152         for (iter = mTranslateNumpadMap.begin();
00153              iter != mTranslateNumpadMap.end();
00154              iter++)
00155         {
00156                 mInvTranslateNumpadMap[iter->second] = iter->first;
00157         }
00158 }
00159 
00160 void LLKeyboardSDL::resetMaskKeys()
00161 {
00162         SDLMod mask = SDL_GetModState();
00163 
00164         // MBW -- XXX -- This mirrors the operation of the Windows version of resetMaskKeys().
00165         //    It looks a bit suspicious, as it won't correct for keys that have been released.
00166         //    Is this the way it's supposed to work?
00167 
00168         if(mask & KMOD_SHIFT)
00169         {
00170                 mKeyLevel[KEY_SHIFT] = TRUE;
00171         }
00172 
00173         if(mask & KMOD_CTRL)
00174         {
00175                 mKeyLevel[KEY_CONTROL] = TRUE;
00176         }
00177 
00178         if(mask & KMOD_ALT)
00179         {
00180                 mKeyLevel[KEY_ALT] = TRUE;
00181         }
00182 }
00183 
00184 
00185 MASK LLKeyboardSDL::updateModifiers(const U32 mask)
00186 {
00187         // translate the mask
00188         MASK out_mask = MASK_NONE;
00189 
00190         if(mask & KMOD_SHIFT)
00191         {
00192                 out_mask |= MASK_SHIFT;
00193         }
00194 
00195         if(mask & KMOD_CTRL)
00196         {
00197                 out_mask |= MASK_CONTROL;
00198         }
00199 
00200         if(mask & KMOD_ALT)
00201         {
00202                 out_mask |= MASK_ALT;
00203         }
00204 
00205         return out_mask;
00206 }
00207 
00208 
00209 static U16 adjustNativekeyFromUnhandledMask(const U16 key, const U32 mask)
00210 {
00211         // SDL doesn't automatically adjust the keysym according to
00212         // whether NUMLOCK is engaged, so we massage the keysym manually.
00213         U16 rtn = key;
00214         if (!(mask & KMOD_NUM))
00215         {
00216                 switch (key)
00217                 {
00218                 case SDLK_KP_PERIOD: rtn = SDLK_DELETE; break;
00219                 case SDLK_KP0: rtn = SDLK_INSERT; break;
00220                 case SDLK_KP1: rtn = SDLK_END; break;
00221                 case SDLK_KP2: rtn = SDLK_DOWN; break;
00222                 case SDLK_KP3: rtn = SDLK_PAGEDOWN; break;
00223                 case SDLK_KP4: rtn = SDLK_LEFT; break;
00224                 case SDLK_KP6: rtn = SDLK_RIGHT; break;
00225                 case SDLK_KP7: rtn = SDLK_HOME; break;
00226                 case SDLK_KP8: rtn = SDLK_UP; break;
00227                 case SDLK_KP9: rtn = SDLK_PAGEUP; break;
00228                 }
00229         }
00230         return rtn;
00231 }
00232 
00233 
00234 BOOL LLKeyboardSDL::handleKeyDown(const U16 key, const U32 mask)
00235 {
00236         U16     adjusted_nativekey;
00237         KEY     translated_key = 0;
00238         U32     translated_mask = MASK_NONE;
00239         BOOL    handled = FALSE;
00240 
00241         adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
00242 
00243         translated_mask = updateModifiers(mask);
00244         
00245         if(translateNumpadKey(adjusted_nativekey, &translated_key))
00246         {
00247                 handled = handleTranslatedKeyDown(translated_key, translated_mask);
00248         }
00249 
00250         return handled;
00251 }
00252 
00253 
00254 BOOL LLKeyboardSDL::handleKeyUp(const U16 key, const U32 mask)
00255 {
00256         U16     adjusted_nativekey;
00257         KEY     translated_key = 0;
00258         U32     translated_mask = MASK_NONE;
00259         BOOL    handled = FALSE;
00260 
00261         adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
00262 
00263         translated_mask = updateModifiers(mask);
00264 
00265         if(translateNumpadKey(adjusted_nativekey, &translated_key))
00266         {
00267                 handled = handleTranslatedKeyUp(translated_key, translated_mask);
00268         }
00269 
00270         return handled;
00271 }
00272 
00273 MASK LLKeyboardSDL::currentMask(BOOL for_mouse_event)
00274 {
00275         MASK result = MASK_NONE;
00276         SDLMod mask = SDL_GetModState();
00277 
00278         if (mask & KMOD_SHIFT)                  result |= MASK_SHIFT;
00279         if (mask & KMOD_CTRL)                   result |= MASK_CONTROL;
00280         if (mask & KMOD_ALT)                    result |= MASK_ALT;
00281 
00282         // For keyboard events, consider Meta keys equivalent to Control
00283         if (!for_mouse_event)
00284         {
00285                 if (mask & KMOD_META) result |= MASK_CONTROL;
00286         }
00287 
00288         return result;
00289 }
00290 
00291 void LLKeyboardSDL::scanKeyboard()
00292 {
00293         for (S32 key = 0; key < KEY_COUNT; key++)
00294         {
00295                 // Generate callback if any event has occurred on this key this frame.
00296                 // Can't just test mKeyLevel, because this could be a slow frame and
00297                 // key might have gone down then up. JC
00298                 if (mKeyLevel[key] || mKeyDown[key] || mKeyUp[key])
00299                 {
00300                         mCurScanKey = key;
00301                         mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]);
00302                 }
00303         }
00304 
00305         // Reset edges for next frame
00306         for (S32 key = 0; key < KEY_COUNT; key++)
00307         {
00308                 mKeyUp[key] = FALSE;
00309                 mKeyDown[key] = FALSE;
00310                 if (mKeyLevel[key])
00311                 {
00312                         mKeyLevelFrameCount[key]++;
00313                 }
00314         }
00315 }
00316 
00317  
00318 BOOL LLKeyboardSDL::translateNumpadKey( const U16 os_key, KEY *translated_key)
00319 {
00320         if(mNumpadDistinct == ND_NUMLOCK_ON)
00321         {
00322                 std::map<U16, KEY>::iterator iter= mTranslateNumpadMap.find(os_key);
00323                 if(iter != mTranslateNumpadMap.end())
00324                 {
00325                         *translated_key = iter->second;
00326                         return TRUE;
00327                 }
00328         }
00329         BOOL success = translateKey(os_key, translated_key);
00330         return success; 
00331 }
00332 
00333 U16 LLKeyboardSDL::inverseTranslateNumpadKey(const KEY translated_key)
00334 {
00335         if(mNumpadDistinct == ND_NUMLOCK_ON)
00336         {
00337                 std::map<KEY, U16>::iterator iter= mInvTranslateNumpadMap.find(translated_key);
00338                 if(iter != mInvTranslateNumpadMap.end())
00339                 {
00340                         return iter->second;
00341                 }
00342         }
00343         return inverseTranslateKey(translated_key);
00344 }
00345 
00346 #endif
00347 

Generated on Fri May 16 08:33:02 2008 for SecondLife by  doxygen 1.5.5