llkeyboard.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 #include "indra_constants.h"
00034 #include "llkeyboard.h"
00035 
00036 #include "llwindow.h"
00037 
00038 
00039 //
00040 // Globals
00041 //
00042 
00043 LLKeyboard *gKeyboard = NULL;
00044 
00045 //static
00046 std::map<KEY,LLString> LLKeyboard::sKeysToNames;
00047 std::map<LLString,KEY> LLKeyboard::sNamesToKeys;
00048 
00049 //
00050 // Class Implementation
00051 //
00052 
00053 LLKeyboard::LLKeyboard() : mCallbacks(NULL), mNumpadDistinct(ND_NUMLOCK_OFF)
00054 {
00055         S32 i;
00056 
00057         // Constructor for LLTimer inits each timer. We want them to
00058         // be constructed without being initialized, so we shut them down here.
00059         for (i = 0; i < KEY_COUNT; i++)
00060         {
00061                 mKeyLevelFrameCount[i] = 0;
00062                 mKeyLevel[i] = FALSE;
00063                 mKeyUp[i]    = FALSE;
00064                 mKeyDown[i]  = FALSE;
00065                 mKeyRepeated[i] = FALSE;
00066         }
00067 
00068         mInsertMode = LL_KIM_INSERT;
00069         mCurTranslatedKey = KEY_NONE;
00070 
00071         addKeyName(' ', "Space" );
00072         addKeyName(KEY_RETURN, "Enter" );
00073         addKeyName(KEY_LEFT, "Left" );
00074         addKeyName(KEY_RIGHT, "Right" );
00075         addKeyName(KEY_UP, "Up" );
00076         addKeyName(KEY_DOWN, "Down" );
00077         addKeyName(KEY_ESCAPE, "Esc" );
00078         addKeyName(KEY_HOME, "Home" );
00079         addKeyName(KEY_END, "End" );
00080         addKeyName(KEY_PAGE_UP, "PgUp" );
00081         addKeyName(KEY_PAGE_DOWN, "PgDn" );
00082         addKeyName(KEY_F1, "F1" );
00083         addKeyName(KEY_F2, "F2" );
00084         addKeyName(KEY_F3, "F3" );
00085         addKeyName(KEY_F4, "F4" );
00086         addKeyName(KEY_F5, "F5" );
00087         addKeyName(KEY_F6, "F6" );
00088         addKeyName(KEY_F7, "F7" );
00089         addKeyName(KEY_F8, "F8" );
00090         addKeyName(KEY_F9, "F9" );
00091         addKeyName(KEY_F10, "F10" );
00092         addKeyName(KEY_F11, "F11" );
00093         addKeyName(KEY_F12, "F12" );
00094         addKeyName(KEY_TAB, "Tab" );
00095         addKeyName(KEY_ADD, "Add" );
00096         addKeyName(KEY_SUBTRACT, "Subtract" );
00097         addKeyName(KEY_MULTIPLY, "Multiply" );
00098         addKeyName(KEY_DIVIDE, "Divide" );
00099         addKeyName(KEY_PAD_LEFT, "PAD_LEFT" );
00100         addKeyName(KEY_PAD_RIGHT, "PAD_RIGHT" );
00101         addKeyName(KEY_PAD_DOWN, "PAD_DOWN" );
00102         addKeyName(KEY_PAD_UP, "PAD_UP" );
00103         addKeyName(KEY_PAD_HOME, "PAD_HOME" );
00104         addKeyName(KEY_PAD_END, "PAD_END" );
00105         addKeyName(KEY_PAD_PGUP, "PAD_PGUP" );
00106         addKeyName(KEY_PAD_PGDN, "PAD_PGDN" );
00107         addKeyName(KEY_PAD_CENTER, "PAD_CENTER" );
00108         addKeyName(KEY_PAD_INS, "PAD_INS" );
00109         addKeyName(KEY_PAD_DEL, "PAD_DEL" );
00110         addKeyName(KEY_PAD_RETURN, "PAD_Enter" );
00111         addKeyName(KEY_BUTTON0, "PAD_BUTTON0" );
00112         addKeyName(KEY_BUTTON1, "PAD_BUTTON1" );
00113         addKeyName(KEY_BUTTON2, "PAD_BUTTON2" );
00114         addKeyName(KEY_BUTTON3, "PAD_BUTTON3" );
00115         addKeyName(KEY_BUTTON4, "PAD_BUTTON4" );
00116         addKeyName(KEY_BUTTON5, "PAD_BUTTON5" );
00117         addKeyName(KEY_BUTTON6, "PAD_BUTTON6" );
00118         addKeyName(KEY_BUTTON7, "PAD_BUTTON7" );
00119         addKeyName(KEY_BUTTON8, "PAD_BUTTON8" );
00120         addKeyName(KEY_BUTTON9, "PAD_BUTTON9" );
00121         addKeyName(KEY_BUTTON10, "PAD_BUTTON10" );
00122         addKeyName(KEY_BUTTON11, "PAD_BUTTON11" );
00123         addKeyName(KEY_BUTTON12, "PAD_BUTTON12" );
00124         addKeyName(KEY_BUTTON13, "PAD_BUTTON13" );
00125         addKeyName(KEY_BUTTON14, "PAD_BUTTON14" );
00126         addKeyName(KEY_BUTTON15, "PAD_BUTTON15" );
00127         
00128         addKeyName(KEY_BACKSPACE, "Backsp" );
00129         addKeyName(KEY_DELETE, "Del" );
00130         addKeyName(KEY_SHIFT, "Shift" );
00131         addKeyName(KEY_CONTROL, "Ctrl" );
00132         addKeyName(KEY_ALT, "Alt" );
00133         addKeyName(KEY_HYPHEN, "-" );
00134         addKeyName(KEY_EQUALS, "=" );
00135         addKeyName(KEY_INSERT, "Ins" );
00136         addKeyName(KEY_CAPSLOCK, "CapsLock" );
00137 }
00138 
00139 
00140 LLKeyboard::~LLKeyboard()
00141 {
00142         // nothing
00143 }
00144 
00145 void LLKeyboard::addKeyName(KEY key, const LLString& name)
00146 {
00147         sKeysToNames[key] = name;
00148         LLString nameuc = name;
00149         LLString::toUpper(nameuc);
00150         sNamesToKeys[nameuc] = key;
00151 }
00152 
00153 // BUG this has to be called when an OS dialog is shown, otherwise modifier key state
00154 // is wrong because the keyup event is never received by the main window. JC
00155 void LLKeyboard::resetKeys()
00156 {
00157         S32 i;
00158 
00159         for (i = 0; i < KEY_COUNT; i++)
00160         {
00161                 if( mKeyLevel[i] )
00162                 {
00163                         mKeyLevel[i] = FALSE;
00164                 }
00165         }
00166 
00167         for (i = 0; i < KEY_COUNT; i++)
00168         {
00169                 mKeyUp[i] = FALSE;
00170         }
00171 
00172         for (i = 0; i < KEY_COUNT; i++)
00173         {
00174                 mKeyDown[i] = FALSE;
00175         }
00176 
00177         for (i = 0; i < KEY_COUNT; i++)
00178         {
00179                 mKeyRepeated[i] = FALSE;
00180         }
00181 }
00182 
00183 
00184 BOOL LLKeyboard::translateKey(const U16 os_key, KEY *out_key)
00185 {
00186         std::map<U16, KEY>::iterator iter;
00187 
00188         // Only translate keys in the map, ignore all other keys for now
00189         iter = mTranslateKeyMap.find(os_key);
00190         if (iter == mTranslateKeyMap.end())
00191         {
00192                 //llwarns << "Unknown virtual key " << os_key << llendl;
00193                 *out_key = 0;
00194                 return FALSE;
00195         }
00196         else
00197         {
00198                 *out_key = iter->second;
00199                 return TRUE;
00200         }
00201 }
00202 
00203 
00204 U16 LLKeyboard::inverseTranslateKey(const KEY translated_key)
00205 {
00206         std::map<KEY, U16>::iterator iter;
00207         iter = mInvTranslateKeyMap.find(translated_key);
00208         if (iter == mInvTranslateKeyMap.end())
00209         {
00210                 return 0;
00211         }
00212         else
00213         {
00214                 return iter->second;
00215         }
00216 }
00217 
00218 
00219 BOOL LLKeyboard::handleTranslatedKeyDown(KEY translated_key, U32 translated_mask)
00220 {
00221         BOOL handled = FALSE;
00222         BOOL repeated = FALSE;
00223 
00224         // is this the first time the key went down?
00225         // if so, generate "character" message
00226         if( !mKeyLevel[translated_key] )
00227         {
00228                 mKeyLevel[translated_key] = TRUE;
00229                 mKeyLevelTimer[translated_key].reset();
00230                 mKeyLevelFrameCount[translated_key] = 0;
00231                 mKeyRepeated[translated_key] = FALSE;
00232         }
00233         else
00234         {
00235                 // Level is already down, assume it's repeated.
00236                 repeated = TRUE;
00237                 mKeyRepeated[translated_key] = TRUE;
00238         }
00239         
00240         mKeyDown[translated_key] = TRUE;
00241         mCurTranslatedKey = (KEY)translated_key;
00242         handled = mCallbacks->handleTranslatedKeyDown(translated_key, translated_mask, repeated);
00243         return handled;
00244 }
00245 
00246 
00247 BOOL LLKeyboard::handleTranslatedKeyUp(KEY translated_key, U32 translated_mask)
00248 {       
00249         BOOL handled = FALSE;
00250         if( mKeyLevel[translated_key] )
00251         {
00252                 mKeyLevel[translated_key] = FALSE;
00253                 
00254                 // Only generate key up events if the key is thought to
00255                 // be down.  This allows you to call resetKeys() in the
00256                 // middle of a frame and ignore subsequent KEY_UP
00257                 // messages in the same frame.  This was causing the
00258                 // sequence W<return> in chat to move agents forward. JC
00259                 mKeyUp[translated_key] = TRUE;
00260                 handled = mCallbacks->handleTranslatedKeyUp(translated_key, translated_mask);
00261         }
00262         
00263         lldebugst(LLERR_USER_INPUT) << "keyup -" << translated_key << "-" << llendl;
00264 
00265         return handled;
00266 }
00267 
00268 
00269 void LLKeyboard::toggleInsertMode()
00270 {
00271         if (LL_KIM_INSERT == mInsertMode)
00272         {
00273                 mInsertMode = LL_KIM_OVERWRITE;
00274         }
00275         else
00276         {
00277                 mInsertMode = LL_KIM_INSERT;
00278         }
00279 }
00280 
00281 
00282 // Returns time in seconds since key was pressed.
00283 F32 LLKeyboard::getKeyElapsedTime(KEY key)
00284 {
00285         return mKeyLevelTimer[key].getElapsedTimeF32();
00286 }
00287 
00288 // Returns time in frames since key was pressed.
00289 S32 LLKeyboard::getKeyElapsedFrameCount(KEY key)
00290 {
00291         return mKeyLevelFrameCount[key];
00292 }
00293 
00294 // static
00295 BOOL LLKeyboard::keyFromString(const LLString& str, KEY *key)
00296 {
00297         LLString instring(str);
00298         size_t length = instring.size();
00299 
00300         if (length < 1)
00301         {
00302                 return FALSE;
00303         }
00304         if (length == 1)
00305         {
00306                 char ch = toupper(instring[0]);
00307                 if (('0' <= ch && ch <= '9') ||
00308                         ('A' <= ch && ch <= 'Z') ||
00309                         ('!' <= ch && ch <= '/') || // !"#$%&'()*+,-./
00310                         (':' <= ch && ch <= '@') || // :;<=>?@
00311                         ('[' <= ch && ch <= '`') || // [\]^_`
00312                         ('{' <= ch && ch <= '~'))   // {|}~
00313                 {
00314                         *key = ch;
00315                         return TRUE;
00316                 }
00317         }
00318 
00319         LLString::toUpper(instring);
00320         KEY res = get_if_there(sNamesToKeys, instring, (KEY)0);
00321         if (res != 0)
00322         {
00323                 *key = res;
00324                 return TRUE;
00325         }
00326         llwarns << "keyFromString failed: " << str << llendl;
00327         return FALSE;
00328 }
00329 
00330 
00331 // static
00332 LLString LLKeyboard::stringFromKey(KEY key)
00333 {
00334         LLString res = get_if_there(sKeysToNames, key, LLString::null);
00335         if (res.empty())
00336         {
00337                 char buffer[2];         /* Flawfinder: ignore */
00338                 buffer[0] = key;
00339                 buffer[1] = '\0';
00340                 res = LLString(buffer);
00341         }
00342         return res;
00343 }
00344 
00345 
00346 
00347 //static
00348 BOOL LLKeyboard::maskFromString(const LLString& str, MASK *mask)
00349 {
00350         LLString instring(str);
00351         if (instring == "NONE")
00352         {
00353                 *mask = MASK_NONE;
00354                 return TRUE;
00355         }
00356         else if (instring == "SHIFT")
00357         {
00358                 *mask = MASK_SHIFT;
00359                 return TRUE;
00360         }
00361         else if (instring == "CTL")
00362         {
00363                 *mask = MASK_CONTROL;
00364                 return TRUE;
00365         }
00366         else if (instring == "ALT")
00367         {
00368                 *mask = MASK_ALT;
00369                 return TRUE;
00370         }
00371         else if (instring == "CTL_SHIFT")
00372         {
00373                 *mask = MASK_CONTROL | MASK_SHIFT;
00374                 return TRUE;
00375         }
00376         else if (instring == "ALT_SHIFT")
00377         {
00378                 *mask = MASK_ALT | MASK_SHIFT;
00379                 return TRUE;
00380         }
00381         else if (instring == "CTL_ALT")
00382         {
00383                 *mask = MASK_CONTROL | MASK_ALT;
00384                 return TRUE;
00385         }
00386         else if (instring == "CTL_ALT_SHIFT")
00387         {
00388                 *mask = MASK_CONTROL | MASK_ALT | MASK_SHIFT;
00389                 return TRUE;
00390         }
00391         else 
00392         {
00393                 return FALSE;
00394         }
00395 }

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