llkeyboardsdl.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. /**
  2. * @file llkeyboardsdl.cpp
  3. * @brief Handler for assignable key bindings
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #if LL_LINUX
  33. #include "linden_common.h"
  34. #include "SDL2/SDL.h"
  35. #include "SDL2/SDL_keycode.h"
  36. #include "llkeyboardsdl.h"
  37. #include "llwindow.h"
  38. LLKeyboardSDL::LLKeyboardSDL()
  39. {
  40. // Set up key mapping for SDL - eventually can read this from a file ?
  41. // Anything not in the key map gets dropped
  42. // Add default A-Z
  43. // Virtual key mappings from SDL_keysym.h ...
  44. // SDL maps the letter keys to the ASCII you'd expect, but it's lowercase...
  45. U32 cur_char;
  46. for (cur_char = 'A'; cur_char <= 'Z'; cur_char++)
  47. {
  48. mTranslateKeyMap[cur_char] = cur_char;
  49. }
  50. for (cur_char = 'a'; cur_char <= 'z'; cur_char++)
  51. {
  52. mTranslateKeyMap[cur_char] = (cur_char - 'a') + 'A';
  53. }
  54. for (cur_char = '0'; cur_char <= '9'; cur_char++)
  55. {
  56. mTranslateKeyMap[cur_char] = cur_char;
  57. }
  58. mTranslateKeyMap[SDLK_RETURN] = KEY_RETURN;
  59. mTranslateKeyMap[SDLK_LEFT] = KEY_LEFT;
  60. mTranslateKeyMap[SDLK_RIGHT] = KEY_RIGHT;
  61. mTranslateKeyMap[SDLK_UP] = KEY_UP;
  62. mTranslateKeyMap[SDLK_DOWN] = KEY_DOWN;
  63. mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE;
  64. mTranslateKeyMap[SDLK_KP_ENTER] = KEY_RETURN;
  65. mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE;
  66. mTranslateKeyMap[SDLK_BACKSPACE] = KEY_BACKSPACE;
  67. mTranslateKeyMap[SDLK_DELETE] = KEY_DELETE;
  68. mTranslateKeyMap[SDLK_LSHIFT] = KEY_SHIFT;
  69. mTranslateKeyMap[SDLK_RSHIFT] = KEY_SHIFT;
  70. mTranslateKeyMap[SDLK_LCTRL] = KEY_CONTROL;
  71. mTranslateKeyMap[SDLK_RCTRL] = KEY_CONTROL;
  72. mTranslateKeyMap[SDLK_LALT] = KEY_ALT;
  73. mTranslateKeyMap[SDLK_RALT] = KEY_ALT;
  74. mTranslateKeyMap[SDLK_HOME] = KEY_HOME;
  75. mTranslateKeyMap[SDLK_END] = KEY_END;
  76. mTranslateKeyMap[SDLK_PAGEUP] = KEY_PAGE_UP;
  77. mTranslateKeyMap[SDLK_PAGEDOWN] = KEY_PAGE_DOWN;
  78. mTranslateKeyMap[SDLK_EQUALS] = KEY_EQUALS;
  79. mTranslateKeyMap[SDLK_KP_EQUALS] = KEY_EQUALS;
  80. mTranslateKeyMap[SDLK_INSERT] = KEY_INSERT;
  81. mTranslateKeyMap[SDLK_CAPSLOCK] = KEY_CAPSLOCK;
  82. mTranslateKeyMap[SDLK_TAB] = KEY_TAB;
  83. mTranslateKeyMap[SDLK_KP_PLUS] = KEY_ADD;
  84. mTranslateKeyMap[SDLK_KP_MINUS] = KEY_SUBTRACT;
  85. mTranslateKeyMap[SDLK_KP_MULTIPLY] = KEY_MULTIPLY;
  86. mTranslateKeyMap[SDLK_KP_DIVIDE] = KEY_PAD_DIVIDE;
  87. mTranslateKeyMap[SDLK_F1] = KEY_F1;
  88. mTranslateKeyMap[SDLK_F2] = KEY_F2;
  89. mTranslateKeyMap[SDLK_F3] = KEY_F3;
  90. mTranslateKeyMap[SDLK_F4] = KEY_F4;
  91. mTranslateKeyMap[SDLK_F5] = KEY_F5;
  92. mTranslateKeyMap[SDLK_F6] = KEY_F6;
  93. mTranslateKeyMap[SDLK_F7] = KEY_F7;
  94. mTranslateKeyMap[SDLK_F8] = KEY_F8;
  95. mTranslateKeyMap[SDLK_F9] = KEY_F9;
  96. mTranslateKeyMap[SDLK_F10] = KEY_F10;
  97. mTranslateKeyMap[SDLK_F11] = KEY_F11;
  98. mTranslateKeyMap[SDLK_F12] = KEY_F12;
  99. // Build inverse map
  100. std::map<U32, KEY>::iterator iter;
  101. for (iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++)
  102. {
  103. mInvTranslateKeyMap[iter->second] = iter->first;
  104. }
  105. // Numpad map
  106. mTranslateNumpadMap[SDLK_KP_0] = KEY_PAD_INS;
  107. mTranslateNumpadMap[SDLK_KP_1] = KEY_PAD_END;
  108. mTranslateNumpadMap[SDLK_KP_2] = KEY_PAD_DOWN;
  109. mTranslateNumpadMap[SDLK_KP_3] = KEY_PAD_PGDN;
  110. mTranslateNumpadMap[SDLK_KP_4] = KEY_PAD_LEFT;
  111. mTranslateNumpadMap[SDLK_KP_5] = KEY_PAD_CENTER;
  112. mTranslateNumpadMap[SDLK_KP_6] = KEY_PAD_RIGHT;
  113. mTranslateNumpadMap[SDLK_KP_7] = KEY_PAD_HOME;
  114. mTranslateNumpadMap[SDLK_KP_8] = KEY_PAD_UP;
  115. mTranslateNumpadMap[SDLK_KP_9] = KEY_PAD_PGUP;
  116. mTranslateNumpadMap[SDLK_KP_PERIOD] = KEY_PAD_DEL;
  117. // Build inverse numpad map
  118. for (iter = mTranslateNumpadMap.begin();
  119. iter != mTranslateNumpadMap.end();
  120. iter++)
  121. {
  122. mInvTranslateNumpadMap[iter->second] = iter->first;
  123. }
  124. }
  125. // This mirrors the operation of the Windows version of resetMaskKeys(). It
  126. // looks a quite bit suspicious, as it would not correct for keys that have
  127. // been released. Is this the way it is supposed to work ?
  128. //virtual
  129. void LLKeyboardSDL::resetMaskKeys()
  130. {
  131. SDL_Keymod mask = SDL_GetModState();
  132. if (mask & KMOD_SHIFT)
  133. {
  134. mKeyLevel[KEY_SHIFT] = true;
  135. }
  136. else
  137. {
  138. mKeyLevel[KEY_SHIFT] = false;
  139. }
  140. if (mask & KMOD_CTRL)
  141. {
  142. mKeyLevel[KEY_CONTROL] = true;
  143. }
  144. if (mask & KMOD_ALT)
  145. {
  146. mKeyLevel[KEY_ALT] = true;
  147. }
  148. }
  149. MASK LLKeyboardSDL::updateModifiers(U32 mask)
  150. {
  151. // translate the mask
  152. MASK out_mask = MASK_NONE;
  153. if (mask & KMOD_SHIFT)
  154. {
  155. out_mask |= MASK_SHIFT;
  156. }
  157. if (mask & KMOD_CTRL)
  158. {
  159. out_mask |= MASK_CONTROL;
  160. }
  161. if (mask & KMOD_ALT)
  162. {
  163. out_mask |= MASK_ALT;
  164. }
  165. // Used at the login screen, for warning about caps lock on in password
  166. // field. HB
  167. if (mask & KMOD_CAPS)
  168. {
  169. mKeyLevel[KEY_CAPSLOCK] = true;
  170. }
  171. else
  172. {
  173. mKeyLevel[KEY_CAPSLOCK] = false;
  174. }
  175. return out_mask;
  176. }
  177. static U32 adjustNativekeyFromUnhandledMask(U32 key, U32 mask)
  178. {
  179. // SDL does not automatically adjust the keysym according to whether
  180. // NUMLOCK is engaged, so we manage the keysym manually.
  181. // Also translate numeric and operator pad keys into normal numeric and
  182. // character keys (especially useful in menu accelerators for AZERTY
  183. // keyboards where numeric keys are SHIFTed keys)
  184. U32 rtn = key;
  185. if (mask & KMOD_NUM)
  186. {
  187. switch (key)
  188. {
  189. case SDLK_KP_DIVIDE: rtn = SDLK_SLASH; break;
  190. case SDLK_KP_MULTIPLY: rtn = SDLK_ASTERISK; break;
  191. case SDLK_KP_MINUS: rtn = SDLK_MINUS; break;
  192. case SDLK_KP_PLUS: rtn = SDLK_PLUS; break;
  193. case SDLK_KP_EQUALS: rtn = SDLK_EQUALS; break;
  194. case SDLK_KP_0: rtn = SDLK_0; break;
  195. case SDLK_KP_1: rtn = SDLK_1; break;
  196. case SDLK_KP_2: rtn = SDLK_2; break;
  197. case SDLK_KP_3: rtn = SDLK_3; break;
  198. case SDLK_KP_4: rtn = SDLK_4; break;
  199. case SDLK_KP_5: rtn = SDLK_5; break;
  200. case SDLK_KP_6: rtn = SDLK_6; break;
  201. case SDLK_KP_7: rtn = SDLK_7; break;
  202. case SDLK_KP_8: rtn = SDLK_8; break;
  203. case SDLK_KP_9: rtn = SDLK_9;
  204. }
  205. }
  206. else
  207. {
  208. switch (key)
  209. {
  210. case SDLK_KP_DIVIDE: rtn = SDLK_SLASH; break;
  211. case SDLK_KP_MULTIPLY: rtn = SDLK_ASTERISK; break;
  212. case SDLK_KP_MINUS: rtn = SDLK_MINUS; break;
  213. case SDLK_KP_PLUS: rtn = SDLK_PLUS; break;
  214. case SDLK_KP_EQUALS: rtn = SDLK_EQUALS; break;
  215. case SDLK_KP_PERIOD: rtn = SDLK_DELETE; break;
  216. case SDLK_KP_0: rtn = SDLK_INSERT; break;
  217. case SDLK_KP_1: rtn = SDLK_END; break;
  218. case SDLK_KP_2: rtn = SDLK_DOWN; break;
  219. case SDLK_KP_3: rtn = SDLK_PAGEDOWN; break;
  220. case SDLK_KP_4: rtn = SDLK_LEFT; break;
  221. case SDLK_KP_6: rtn = SDLK_RIGHT; break;
  222. case SDLK_KP_7: rtn = SDLK_HOME; break;
  223. case SDLK_KP_8: rtn = SDLK_UP; break;
  224. case SDLK_KP_9: rtn = SDLK_PAGEUP;
  225. }
  226. }
  227. return rtn;
  228. }
  229. //virtual
  230. bool LLKeyboardSDL::handleKeyDown(U32 key, U32 mask)
  231. {
  232. U32 translated_code = adjustNativekeyFromUnhandledMask(key, mask);
  233. U32 translated_mask = updateModifiers(mask);
  234. LL_DEBUGS("KeyCodes") << "Key code: " << std::hex << key
  235. << " - Mask: "<< mask
  236. << " Translated code: " << translated_code
  237. << " Translated mask: " << translated_mask
  238. << std::dec << LL_ENDL;
  239. KEY translated_key = 0;
  240. if (translateNumpadKey(translated_code, &translated_key, translated_mask))
  241. {
  242. return handleTranslatedKeyDown(translated_key, translated_mask);
  243. }
  244. return false;
  245. }
  246. //virtual
  247. bool LLKeyboardSDL::handleKeyUp(U32 key, U32 mask)
  248. {
  249. U32 translated_code = adjustNativekeyFromUnhandledMask(key, mask);
  250. U32 translated_mask = updateModifiers(mask);
  251. KEY translated_key = 0;
  252. if (translateNumpadKey(translated_code, &translated_key, translated_mask))
  253. {
  254. return handleTranslatedKeyUp(translated_key, translated_mask);
  255. }
  256. return false;
  257. }
  258. //virtual
  259. MASK LLKeyboardSDL::currentMask(bool for_mouse_event)
  260. {
  261. MASK result = MASK_NONE;
  262. SDL_Keymod mask = SDL_GetModState();
  263. if (mask & KMOD_SHIFT)
  264. {
  265. result |= MASK_SHIFT;
  266. }
  267. if (mask & KMOD_CTRL)
  268. {
  269. result |= MASK_CONTROL;
  270. }
  271. if (mask & KMOD_ALT)
  272. {
  273. result |= MASK_ALT;
  274. }
  275. // For keyboard events, consider Meta keys equivalent to Control
  276. if (!for_mouse_event && (mask & KMOD_GUI))
  277. {
  278. result |= MASK_CONTROL;
  279. }
  280. return result;
  281. }
  282. //virtual
  283. void LLKeyboardSDL::scanKeyboard()
  284. {
  285. for (S32 key = 0; key < KEY_COUNT; ++key)
  286. {
  287. // Generate callback if any event has occurred on this key this frame.
  288. // Can't just test mKeyLevel, because this could be a slow frame and
  289. // key might have gone down then up. JC
  290. if (mKeyLevel[key] || mKeyDown[key] || mKeyUp[key])
  291. {
  292. mCurScanKey = key;
  293. mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key],
  294. mKeyLevel[key]);
  295. }
  296. }
  297. // Reset edges for next frame
  298. for (S32 key = 0; key < KEY_COUNT; ++key)
  299. {
  300. mKeyUp[key] = false;
  301. mKeyDown[key] = false;
  302. if (mKeyLevel[key])
  303. {
  304. ++mKeyLevelFrameCount[key];
  305. }
  306. }
  307. }
  308. bool LLKeyboardSDL::translateNumpadKey(U32 os_key, KEY* translated_key,
  309. MASK mask)
  310. {
  311. if (mNumpadDistinct == ND_NUMLOCK_ON)
  312. {
  313. std::map<U32, KEY>::iterator iter= mTranslateNumpadMap.find(os_key);
  314. if (iter != mTranslateNumpadMap.end())
  315. {
  316. *translated_key = iter->second;
  317. return true;
  318. }
  319. }
  320. return translateKey(os_key, translated_key, mask);
  321. }
  322. U32 LLKeyboardSDL::inverseTranslateNumpadKey(KEY translated_key)
  323. {
  324. if (mNumpadDistinct == ND_NUMLOCK_ON)
  325. {
  326. std::map<KEY, U32>::iterator iter= mInvTranslateNumpadMap.find(translated_key);
  327. if (iter != mInvTranslateNumpadMap.end())
  328. {
  329. return iter->second;
  330. }
  331. }
  332. return inverseTranslateKey(translated_key);
  333. }
  334. #endif // LL_LINUX