/indra/llwindow/llkeyboardsdl.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 342 lines · 239 code · 47 blank · 56 comment · 36 complexity · 57bc4d92fe8ce5b00909445305a3c3f8 MD5 · raw file

  1. /**
  2. * @file llkeyboardsdl.cpp
  3. * @brief Handler for assignable key bindings
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #if LL_SDL
  27. #include "linden_common.h"
  28. #include "llkeyboardsdl.h"
  29. #include "llwindowcallbacks.h"
  30. #include "SDL/SDL.h"
  31. LLKeyboardSDL::LLKeyboardSDL()
  32. {
  33. // Set up key mapping for SDL - eventually can read this from a file?
  34. // Anything not in the key map gets dropped
  35. // Add default A-Z
  36. // Virtual key mappings from SDL_keysym.h ...
  37. // SDL maps the letter keys to the ASCII you'd expect, but it's lowercase...
  38. U16 cur_char;
  39. for (cur_char = 'A'; cur_char <= 'Z'; cur_char++)
  40. {
  41. mTranslateKeyMap[cur_char] = cur_char;
  42. }
  43. for (cur_char = 'a'; cur_char <= 'z'; cur_char++)
  44. {
  45. mTranslateKeyMap[cur_char] = (cur_char - 'a') + 'A';
  46. }
  47. for (cur_char = '0'; cur_char <= '9'; cur_char++)
  48. {
  49. mTranslateKeyMap[cur_char] = cur_char;
  50. }
  51. // These ones are translated manually upon keydown/keyup because
  52. // SDL doesn't handle their numlock transition.
  53. //mTranslateKeyMap[SDLK_KP4] = KEY_PAD_LEFT;
  54. //mTranslateKeyMap[SDLK_KP6] = KEY_PAD_RIGHT;
  55. //mTranslateKeyMap[SDLK_KP8] = KEY_PAD_UP;
  56. //mTranslateKeyMap[SDLK_KP2] = KEY_PAD_DOWN;
  57. //mTranslateKeyMap[SDLK_KP_PERIOD] = KEY_DELETE;
  58. //mTranslateKeyMap[SDLK_KP7] = KEY_HOME;
  59. //mTranslateKeyMap[SDLK_KP1] = KEY_END;
  60. //mTranslateKeyMap[SDLK_KP9] = KEY_PAGE_UP;
  61. //mTranslateKeyMap[SDLK_KP3] = KEY_PAGE_DOWN;
  62. //mTranslateKeyMap[SDLK_KP0] = KEY_INSERT;
  63. mTranslateKeyMap[SDLK_SPACE] = ' ';
  64. mTranslateKeyMap[SDLK_RETURN] = KEY_RETURN;
  65. mTranslateKeyMap[SDLK_LEFT] = KEY_LEFT;
  66. mTranslateKeyMap[SDLK_RIGHT] = KEY_RIGHT;
  67. mTranslateKeyMap[SDLK_UP] = KEY_UP;
  68. mTranslateKeyMap[SDLK_DOWN] = KEY_DOWN;
  69. mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE;
  70. mTranslateKeyMap[SDLK_KP_ENTER] = KEY_RETURN;
  71. mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE;
  72. mTranslateKeyMap[SDLK_BACKSPACE] = KEY_BACKSPACE;
  73. mTranslateKeyMap[SDLK_DELETE] = KEY_DELETE;
  74. mTranslateKeyMap[SDLK_LSHIFT] = KEY_SHIFT;
  75. mTranslateKeyMap[SDLK_RSHIFT] = KEY_SHIFT;
  76. mTranslateKeyMap[SDLK_LCTRL] = KEY_CONTROL;
  77. mTranslateKeyMap[SDLK_RCTRL] = KEY_CONTROL;
  78. mTranslateKeyMap[SDLK_LALT] = KEY_ALT;
  79. mTranslateKeyMap[SDLK_RALT] = KEY_ALT;
  80. mTranslateKeyMap[SDLK_HOME] = KEY_HOME;
  81. mTranslateKeyMap[SDLK_END] = KEY_END;
  82. mTranslateKeyMap[SDLK_PAGEUP] = KEY_PAGE_UP;
  83. mTranslateKeyMap[SDLK_PAGEDOWN] = KEY_PAGE_DOWN;
  84. mTranslateKeyMap[SDLK_MINUS] = KEY_HYPHEN;
  85. mTranslateKeyMap[SDLK_EQUALS] = KEY_EQUALS;
  86. mTranslateKeyMap[SDLK_KP_EQUALS] = KEY_EQUALS;
  87. mTranslateKeyMap[SDLK_INSERT] = KEY_INSERT;
  88. mTranslateKeyMap[SDLK_CAPSLOCK] = KEY_CAPSLOCK;
  89. mTranslateKeyMap[SDLK_TAB] = KEY_TAB;
  90. mTranslateKeyMap[SDLK_KP_PLUS] = KEY_ADD;
  91. mTranslateKeyMap[SDLK_KP_MINUS] = KEY_SUBTRACT;
  92. mTranslateKeyMap[SDLK_KP_MULTIPLY] = KEY_MULTIPLY;
  93. mTranslateKeyMap[SDLK_KP_DIVIDE] = KEY_PAD_DIVIDE;
  94. mTranslateKeyMap[SDLK_F1] = KEY_F1;
  95. mTranslateKeyMap[SDLK_F2] = KEY_F2;
  96. mTranslateKeyMap[SDLK_F3] = KEY_F3;
  97. mTranslateKeyMap[SDLK_F4] = KEY_F4;
  98. mTranslateKeyMap[SDLK_F5] = KEY_F5;
  99. mTranslateKeyMap[SDLK_F6] = KEY_F6;
  100. mTranslateKeyMap[SDLK_F7] = KEY_F7;
  101. mTranslateKeyMap[SDLK_F8] = KEY_F8;
  102. mTranslateKeyMap[SDLK_F9] = KEY_F9;
  103. mTranslateKeyMap[SDLK_F10] = KEY_F10;
  104. mTranslateKeyMap[SDLK_F11] = KEY_F11;
  105. mTranslateKeyMap[SDLK_F12] = KEY_F12;
  106. mTranslateKeyMap[SDLK_PLUS] = '=';
  107. mTranslateKeyMap[SDLK_COMMA] = ',';
  108. mTranslateKeyMap[SDLK_MINUS] = '-';
  109. mTranslateKeyMap[SDLK_PERIOD] = '.';
  110. mTranslateKeyMap[SDLK_BACKQUOTE] = '`';
  111. mTranslateKeyMap[SDLK_SLASH] = KEY_DIVIDE;
  112. mTranslateKeyMap[SDLK_SEMICOLON] = ';';
  113. mTranslateKeyMap[SDLK_LEFTBRACKET] = '[';
  114. mTranslateKeyMap[SDLK_BACKSLASH] = '\\';
  115. mTranslateKeyMap[SDLK_RIGHTBRACKET] = ']';
  116. mTranslateKeyMap[SDLK_QUOTE] = '\'';
  117. // Build inverse map
  118. std::map<U16, KEY>::iterator iter;
  119. for (iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++)
  120. {
  121. mInvTranslateKeyMap[iter->second] = iter->first;
  122. }
  123. // numpad map
  124. mTranslateNumpadMap[SDLK_KP0] = KEY_PAD_INS;
  125. mTranslateNumpadMap[SDLK_KP1] = KEY_PAD_END;
  126. mTranslateNumpadMap[SDLK_KP2] = KEY_PAD_DOWN;
  127. mTranslateNumpadMap[SDLK_KP3] = KEY_PAD_PGDN;
  128. mTranslateNumpadMap[SDLK_KP4] = KEY_PAD_LEFT;
  129. mTranslateNumpadMap[SDLK_KP5] = KEY_PAD_CENTER;
  130. mTranslateNumpadMap[SDLK_KP6] = KEY_PAD_RIGHT;
  131. mTranslateNumpadMap[SDLK_KP7] = KEY_PAD_HOME;
  132. mTranslateNumpadMap[SDLK_KP8] = KEY_PAD_UP;
  133. mTranslateNumpadMap[SDLK_KP9] = KEY_PAD_PGUP;
  134. mTranslateNumpadMap[SDLK_KP_PERIOD] = KEY_PAD_DEL;
  135. // build inverse numpad map
  136. for (iter = mTranslateNumpadMap.begin();
  137. iter != mTranslateNumpadMap.end();
  138. iter++)
  139. {
  140. mInvTranslateNumpadMap[iter->second] = iter->first;
  141. }
  142. }
  143. void LLKeyboardSDL::resetMaskKeys()
  144. {
  145. SDLMod mask = SDL_GetModState();
  146. // MBW -- XXX -- This mirrors the operation of the Windows version of resetMaskKeys().
  147. // It looks a bit suspicious, as it won't correct for keys that have been released.
  148. // Is this the way it's supposed to work?
  149. if(mask & KMOD_SHIFT)
  150. {
  151. mKeyLevel[KEY_SHIFT] = TRUE;
  152. }
  153. if(mask & KMOD_CTRL)
  154. {
  155. mKeyLevel[KEY_CONTROL] = TRUE;
  156. }
  157. if(mask & KMOD_ALT)
  158. {
  159. mKeyLevel[KEY_ALT] = TRUE;
  160. }
  161. }
  162. MASK LLKeyboardSDL::updateModifiers(const U32 mask)
  163. {
  164. // translate the mask
  165. MASK out_mask = MASK_NONE;
  166. if(mask & KMOD_SHIFT)
  167. {
  168. out_mask |= MASK_SHIFT;
  169. }
  170. if(mask & KMOD_CTRL)
  171. {
  172. out_mask |= MASK_CONTROL;
  173. }
  174. if(mask & KMOD_ALT)
  175. {
  176. out_mask |= MASK_ALT;
  177. }
  178. return out_mask;
  179. }
  180. static U16 adjustNativekeyFromUnhandledMask(const U16 key, const U32 mask)
  181. {
  182. // SDL doesn't automatically adjust the keysym according to
  183. // whether NUMLOCK is engaged, so we massage the keysym manually.
  184. U16 rtn = key;
  185. if (!(mask & KMOD_NUM))
  186. {
  187. switch (key)
  188. {
  189. case SDLK_KP_PERIOD: rtn = SDLK_DELETE; break;
  190. case SDLK_KP0: rtn = SDLK_INSERT; break;
  191. case SDLK_KP1: rtn = SDLK_END; break;
  192. case SDLK_KP2: rtn = SDLK_DOWN; break;
  193. case SDLK_KP3: rtn = SDLK_PAGEDOWN; break;
  194. case SDLK_KP4: rtn = SDLK_LEFT; break;
  195. case SDLK_KP6: rtn = SDLK_RIGHT; break;
  196. case SDLK_KP7: rtn = SDLK_HOME; break;
  197. case SDLK_KP8: rtn = SDLK_UP; break;
  198. case SDLK_KP9: rtn = SDLK_PAGEUP; break;
  199. }
  200. }
  201. return rtn;
  202. }
  203. BOOL LLKeyboardSDL::handleKeyDown(const U16 key, const U32 mask)
  204. {
  205. U16 adjusted_nativekey;
  206. KEY translated_key = 0;
  207. U32 translated_mask = MASK_NONE;
  208. BOOL handled = FALSE;
  209. adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
  210. translated_mask = updateModifiers(mask);
  211. if(translateNumpadKey(adjusted_nativekey, &translated_key))
  212. {
  213. handled = handleTranslatedKeyDown(translated_key, translated_mask);
  214. }
  215. return handled;
  216. }
  217. BOOL LLKeyboardSDL::handleKeyUp(const U16 key, const U32 mask)
  218. {
  219. U16 adjusted_nativekey;
  220. KEY translated_key = 0;
  221. U32 translated_mask = MASK_NONE;
  222. BOOL handled = FALSE;
  223. adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
  224. translated_mask = updateModifiers(mask);
  225. if(translateNumpadKey(adjusted_nativekey, &translated_key))
  226. {
  227. handled = handleTranslatedKeyUp(translated_key, translated_mask);
  228. }
  229. return handled;
  230. }
  231. MASK LLKeyboardSDL::currentMask(BOOL for_mouse_event)
  232. {
  233. MASK result = MASK_NONE;
  234. SDLMod mask = SDL_GetModState();
  235. if (mask & KMOD_SHIFT) result |= MASK_SHIFT;
  236. if (mask & KMOD_CTRL) result |= MASK_CONTROL;
  237. if (mask & KMOD_ALT) result |= MASK_ALT;
  238. // For keyboard events, consider Meta keys equivalent to Control
  239. if (!for_mouse_event)
  240. {
  241. if (mask & KMOD_META) result |= MASK_CONTROL;
  242. }
  243. return result;
  244. }
  245. void LLKeyboardSDL::scanKeyboard()
  246. {
  247. for (S32 key = 0; key < KEY_COUNT; key++)
  248. {
  249. // Generate callback if any event has occurred on this key this frame.
  250. // Can't just test mKeyLevel, because this could be a slow frame and
  251. // key might have gone down then up. JC
  252. if (mKeyLevel[key] || mKeyDown[key] || mKeyUp[key])
  253. {
  254. mCurScanKey = key;
  255. mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]);
  256. }
  257. }
  258. // Reset edges for next frame
  259. for (S32 key = 0; key < KEY_COUNT; key++)
  260. {
  261. mKeyUp[key] = FALSE;
  262. mKeyDown[key] = FALSE;
  263. if (mKeyLevel[key])
  264. {
  265. mKeyLevelFrameCount[key]++;
  266. }
  267. }
  268. }
  269. BOOL LLKeyboardSDL::translateNumpadKey( const U16 os_key, KEY *translated_key)
  270. {
  271. if(mNumpadDistinct == ND_NUMLOCK_ON)
  272. {
  273. std::map<U16, KEY>::iterator iter= mTranslateNumpadMap.find(os_key);
  274. if(iter != mTranslateNumpadMap.end())
  275. {
  276. *translated_key = iter->second;
  277. return TRUE;
  278. }
  279. }
  280. BOOL success = translateKey(os_key, translated_key);
  281. return success;
  282. }
  283. U16 LLKeyboardSDL::inverseTranslateNumpadKey(const KEY translated_key)
  284. {
  285. if(mNumpadDistinct == ND_NUMLOCK_ON)
  286. {
  287. std::map<KEY, U16>::iterator iter= mInvTranslateNumpadMap.find(translated_key);
  288. if(iter != mInvTranslateNumpadMap.end())
  289. {
  290. return iter->second;
  291. }
  292. }
  293. return inverseTranslateKey(translated_key);
  294. }
  295. #endif