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_DIVIDE, "PAD_DIVIDE" );
00100         addKeyName(KEY_PAD_LEFT, "PAD_LEFT" );
00101         addKeyName(KEY_PAD_RIGHT, "PAD_RIGHT" );
00102         addKeyName(KEY_PAD_DOWN, "PAD_DOWN" );
00103         addKeyName(KEY_PAD_UP, "PAD_UP" );
00104         addKeyName(KEY_PAD_HOME, "PAD_HOME" );
00105         addKeyName(KEY_PAD_END, "PAD_END" );
00106         addKeyName(KEY_PAD_PGUP, "PAD_PGUP" );
00107         addKeyName(KEY_PAD_PGDN, "PAD_PGDN" );
00108         addKeyName(KEY_PAD_CENTER, "PAD_CENTER" );
00109         addKeyName(KEY_PAD_INS, "PAD_INS" );
00110         addKeyName(KEY_PAD_DEL, "PAD_DEL" );
00111         addKeyName(KEY_PAD_RETURN, "PAD_Enter" );
00112         addKeyName(KEY_BUTTON0, "PAD_BUTTON0" );
00113         addKeyName(KEY_BUTTON1, "PAD_BUTTON1" );
00114         addKeyName(KEY_BUTTON2, "PAD_BUTTON2" );
00115         addKeyName(KEY_BUTTON3, "PAD_BUTTON3" );
00116         addKeyName(KEY_BUTTON4, "PAD_BUTTON4" );
00117         addKeyName(KEY_BUTTON5, "PAD_BUTTON5" );
00118         addKeyName(KEY_BUTTON6, "PAD_BUTTON6" );
00119         addKeyName(KEY_BUTTON7, "PAD_BUTTON7" );
00120         addKeyName(KEY_BUTTON8, "PAD_BUTTON8" );
00121         addKeyName(KEY_BUTTON9, "PAD_BUTTON9" );
00122         addKeyName(KEY_BUTTON10, "PAD_BUTTON10" );
00123         addKeyName(KEY_BUTTON11, "PAD_BUTTON11" );
00124         addKeyName(KEY_BUTTON12, "PAD_BUTTON12" );
00125         addKeyName(KEY_BUTTON13, "PAD_BUTTON13" );
00126         addKeyName(KEY_BUTTON14, "PAD_BUTTON14" );
00127         addKeyName(KEY_BUTTON15, "PAD_BUTTON15" );
00128         
00129         addKeyName(KEY_BACKSPACE, "Backsp" );
00130         addKeyName(KEY_DELETE, "Del" );
00131         addKeyName(KEY_SHIFT, "Shift" );
00132         addKeyName(KEY_CONTROL, "Ctrl" );
00133         addKeyName(KEY_ALT, "Alt" );
00134         addKeyName(KEY_HYPHEN, "-" );
00135         addKeyName(KEY_EQUALS, "=" );
00136         addKeyName(KEY_INSERT, "Ins" );
00137         addKeyName(KEY_CAPSLOCK, "CapsLock" );
00138 }
00139 
00140 
00141 LLKeyboard::~LLKeyboard()
00142 {
00143         // nothing
00144 }
00145 
00146 void LLKeyboard::addKeyName(KEY key, const LLString& name)
00147 {
00148         sKeysToNames[key] = name;
00149         LLString nameuc = name;
00150         LLString::toUpper(nameuc);
00151         sNamesToKeys[nameuc] = key;
00152 }
00153 
00154 // BUG this has to be called when an OS dialog is shown, otherwise modifier key state
00155 // is wrong because the keyup event is never received by the main window. JC
00156 void LLKeyboard::resetKeys()
00157 {
00158         S32 i;
00159 
00160         for (i = 0; i < KEY_COUNT; i++)
00161         {
00162                 if( mKeyLevel[i] )
00163                 {
00164                         mKeyLevel[i] = FALSE;
00165                 }
00166         }
00167 
00168         for (i = 0; i < KEY_COUNT; i++)
00169         {
00170                 mKeyUp[i] = FALSE;
00171         }
00172 
00173         for (i = 0; i < KEY_COUNT; i++)
00174         {
00175                 mKeyDown[i] = FALSE;
00176         }
00177 
00178         for (i = 0; i < KEY_COUNT; i++)
00179         {
00180                 mKeyRepeated[i] = FALSE;
00181         }
00182 }
00183 
00184 
00185 BOOL LLKeyboard::translateKey(const U16 os_key, KEY *out_key)
00186 {
00187         std::map<U16, KEY>::iterator iter;
00188 
00189         // Only translate keys in the map, ignore all other keys for now
00190         iter = mTranslateKeyMap.find(os_key);
00191         if (iter == mTranslateKeyMap.end())
00192         {
00193                 //llwarns << "Unknown virtual key " << os_key << llendl;
00194                 *out_key = 0;
00195                 return FALSE;
00196         }
00197         else
00198         {
00199                 *out_key = iter->second;
00200                 return TRUE;
00201         }
00202 }
00203 
00204 
00205 U16 LLKeyboard::inverseTranslateKey(const KEY translated_key)
00206 {
00207         std::map<KEY, U16>::iterator iter;
00208         iter = mInvTranslateKeyMap.find(translated_key);
00209         if (iter == mInvTranslateKeyMap.end())
00210         {
00211                 return 0;
00212         }
00213         else
00214         {
00215                 return iter->second;
00216         }
00217 }
00218 
00219 
00220 BOOL LLKeyboard::handleTranslatedKeyDown(KEY translated_key, U32 translated_mask)
00221 {
00222         BOOL handled = FALSE;
00223         BOOL repeated = FALSE;
00224 
00225         // is this the first time the key went down?
00226         // if so, generate "character" message
00227         if( !mKeyLevel[translated_key] )
00228         {
00229                 mKeyLevel[translated_key] = TRUE;
00230                 mKeyLevelTimer[translated_key].reset();
00231                 mKeyLevelFrameCount[translated_key] = 0;
00232                 mKeyRepeated[translated_key] = FALSE;
00233         }
00234         else
00235         {
00236                 // Level is already down, assume it's repeated.
00237                 repeated = TRUE;
00238                 mKeyRepeated[translated_key] = TRUE;
00239         }
00240         
00241         mKeyDown[translated_key] = TRUE;
00242         mCurTranslatedKey = (KEY)translated_key;
00243         handled = mCallbacks->handleTranslatedKeyDown(translated_key, translated_mask, repeated);
00244         return handled;
00245 }
00246 
00247 
00248 BOOL LLKeyboard::handleTranslatedKeyUp(KEY translated_key, U32 translated_mask)
00249 {       
00250         BOOL handled = FALSE;
00251         if( mKeyLevel[translated_key] )
00252         {
00253                 mKeyLevel[translated_key] = FALSE;
00254                 
00255                 // Only generate key up events if the key is thought to
00256                 // be down.  This allows you to call resetKeys() in the
00257                 // middle of a frame and ignore subsequent KEY_UP
00258                 // messages in the same frame.  This was causing the
00259                 // sequence W<return> in chat to move agents forward. JC
00260                 mKeyUp[translated_key] = TRUE;
00261                 handled = mCallbacks->handleTranslatedKeyUp(translated_key, translated_mask);
00262         }
00263         
00264         lldebugst(LLERR_USER_INPUT) << "keyup -" << translated_key << "-" << llendl;
00265 
00266         return handled;
00267 }
00268 
00269 
00270 void LLKeyboard::toggleInsertMode()
00271 {
00272         if (LL_KIM_INSERT == mInsertMode)
00273         {
00274                 mInsertMode = LL_KIM_OVERWRITE;
00275         }
00276         else
00277         {
00278                 mInsertMode = LL_KIM_INSERT;
00279         }
00280 }
00281 
00282 
00283 // Returns time in seconds since key was pressed.
00284 F32 LLKeyboard::getKeyElapsedTime(KEY key)
00285 {
00286         return mKeyLevelTimer[key].getElapsedTimeF32();
00287 }
00288 
00289 // Returns time in frames since key was pressed.
00290 S32 LLKeyboard::getKeyElapsedFrameCount(KEY key)
00291 {
00292         return mKeyLevelFrameCount[key];
00293 }
00294 
00295 // static
00296 BOOL LLKeyboard::keyFromString(const LLString& str, KEY *key)
00297 {
00298         LLString instring(str);
00299         size_t length = instring.size();
00300 
00301         if (length < 1)
00302         {
00303                 return FALSE;
00304         }
00305         if (length == 1)
00306         {
00307                 char ch = toupper(instring[0]);
00308                 if (('0' <= ch && ch <= '9') ||
00309                         ('A' <= ch && ch <= 'Z') ||
00310                         ('!' <= ch && ch <= '/') || // !"#$%&'()*+,-./
00311                         (':' <= ch && ch <= '@') || // :;<=>?@
00312                         ('[' <= ch && ch <= '`') || // [\]^_`
00313                         ('{' <= ch && ch <= '~'))   // {|}~
00314                 {
00315                         *key = ch;
00316                         return TRUE;
00317                 }
00318         }
00319 
00320         LLString::toUpper(instring);
00321         KEY res = get_if_there(sNamesToKeys, instring, (KEY)0);
00322         if (res != 0)
00323         {
00324                 *key = res;
00325                 return TRUE;
00326         }
00327         llwarns << "keyFromString failed: " << str << llendl;
00328         return FALSE;
00329 }
00330 
00331 
00332 // static
00333 LLString LLKeyboard::stringFromKey(KEY key)
00334 {
00335         LLString res = get_if_there(sKeysToNames, key, LLString::null);
00336         if (res.empty())
00337         {
00338                 char buffer[2];         /* Flawfinder: ignore */
00339                 buffer[0] = key;
00340                 buffer[1] = '\0';
00341                 res = LLString(buffer);
00342         }
00343         return res;
00344 }
00345 
00346 
00347 
00348 //static
00349 BOOL LLKeyboard::maskFromString(const LLString& str, MASK *mask)
00350 {
00351         LLString instring(str);
00352         if (instring == "NONE")
00353         {
00354                 *mask = MASK_NONE;
00355                 return TRUE;
00356         }
00357         else if (instring == "SHIFT")
00358         {
00359                 *mask = MASK_SHIFT;
00360                 return TRUE;
00361         }
00362         else if (instring == "CTL")
00363         {
00364                 *mask = MASK_CONTROL;
00365                 return TRUE;
00366         }
00367         else if (instring == "ALT")
00368         {
00369                 *mask = MASK_ALT;
00370                 return TRUE;
00371         }
00372         else if (instring == "CTL_SHIFT")
00373         {
00374                 *mask = MASK_CONTROL | MASK_SHIFT;
00375                 return TRUE;
00376         }
00377         else if (instring == "ALT_SHIFT")
00378         {
00379                 *mask = MASK_ALT | MASK_SHIFT;
00380                 return TRUE;
00381         }
00382         else if (instring == "CTL_ALT")
00383         {
00384                 *mask = MASK_CONTROL | MASK_ALT;
00385                 return TRUE;
00386         }
00387         else if (instring == "CTL_ALT_SHIFT")
00388         {
00389                 *mask = MASK_CONTROL | MASK_ALT | MASK_SHIFT;
00390                 return TRUE;
00391         }
00392         else 
00393         {
00394                 return FALSE;
00395         }
00396 }

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