llkeyboardwin32.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. /**
  2. * @file llkeyboardwin32.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_WINDOWS
  33. #include "linden_common.h"
  34. #include "llkeyboardwin32.h"
  35. #include "llwindow.h"
  36. LLKeyboardWin32::LLKeyboardWin32()
  37. {
  38. // Set up key mapping for windows - eventually can read this from a file ?
  39. // Anything not in the key map gets dropped. Add default A-Z.
  40. // Virtual key mappings from WinUser.h
  41. KEY cur_char;
  42. for (cur_char = 'A'; cur_char <= 'Z'; ++cur_char)
  43. {
  44. mTranslateKeyMap[cur_char] = (KEY)cur_char;
  45. }
  46. for (cur_char = '0'; cur_char <= '9'; ++cur_char)
  47. {
  48. mTranslateKeyMap[cur_char] = (KEY)cur_char;
  49. }
  50. // numpad number keys
  51. for (cur_char = 0x60; cur_char <= 0x69; ++cur_char)
  52. {
  53. mTranslateKeyMap[cur_char] = (KEY)('0' + (0x60 - cur_char));
  54. }
  55. mTranslateKeyMap[VK_SPACE] = ' ';
  56. mTranslateKeyMap[VK_OEM_1] = ';';
  57. // When the user hits, for example, Ctrl-= as a keyboard shortcut, Windows
  58. // generates VK_OEM_PLUS. This is true on both QWERTY and DVORAK keyboards
  59. // in the US. Numeric keypad '+' generates VK_ADD below. Thus we translate
  60. // it as '='. Potential bug: This may not be true on international
  61. // keyboards. JC
  62. mTranslateKeyMap[VK_OEM_PLUS] = '=';
  63. mTranslateKeyMap[VK_OEM_COMMA] = ',';
  64. mTranslateKeyMap[VK_OEM_MINUS] = '-';
  65. mTranslateKeyMap[VK_OEM_PERIOD] = '.';
  66. mTranslateKeyMap[VK_OEM_2] = KEY_PAD_DIVIDE;
  67. mTranslateKeyMap[VK_OEM_3] = '`';
  68. mTranslateKeyMap[VK_OEM_4] = '[';
  69. mTranslateKeyMap[VK_OEM_5] = '\\';
  70. mTranslateKeyMap[VK_OEM_6] = ']';
  71. mTranslateKeyMap[VK_OEM_7] = '\'';
  72. mTranslateKeyMap[VK_ESCAPE] = KEY_ESCAPE;
  73. mTranslateKeyMap[VK_RETURN] = KEY_RETURN;
  74. mTranslateKeyMap[VK_LEFT] = KEY_LEFT;
  75. mTranslateKeyMap[VK_RIGHT] = KEY_RIGHT;
  76. mTranslateKeyMap[VK_UP] = KEY_UP;
  77. mTranslateKeyMap[VK_DOWN] = KEY_DOWN;
  78. mTranslateKeyMap[VK_BACK] = KEY_BACKSPACE;
  79. mTranslateKeyMap[VK_INSERT] = KEY_INSERT;
  80. mTranslateKeyMap[VK_DELETE] = KEY_DELETE;
  81. mTranslateKeyMap[VK_SHIFT] = KEY_SHIFT;
  82. mTranslateKeyMap[VK_CONTROL] = KEY_CONTROL;
  83. mTranslateKeyMap[VK_MENU] = KEY_ALT;
  84. mTranslateKeyMap[VK_CAPITAL] = KEY_CAPSLOCK;
  85. mTranslateKeyMap[VK_HOME] = KEY_HOME;
  86. mTranslateKeyMap[VK_END] = KEY_END;
  87. mTranslateKeyMap[VK_PRIOR] = KEY_PAGE_UP;
  88. mTranslateKeyMap[VK_NEXT] = KEY_PAGE_DOWN;
  89. mTranslateKeyMap[VK_TAB] = KEY_TAB;
  90. mTranslateKeyMap[VK_ADD] = KEY_ADD;
  91. mTranslateKeyMap[VK_SUBTRACT] = KEY_SUBTRACT;
  92. mTranslateKeyMap[VK_MULTIPLY] = KEY_MULTIPLY;
  93. mTranslateKeyMap[VK_DIVIDE] = KEY_DIVIDE;
  94. mTranslateKeyMap[VK_F1] = KEY_F1;
  95. mTranslateKeyMap[VK_F2] = KEY_F2;
  96. mTranslateKeyMap[VK_F3] = KEY_F3;
  97. mTranslateKeyMap[VK_F4] = KEY_F4;
  98. mTranslateKeyMap[VK_F5] = KEY_F5;
  99. mTranslateKeyMap[VK_F6] = KEY_F6;
  100. mTranslateKeyMap[VK_F7] = KEY_F7;
  101. mTranslateKeyMap[VK_F8] = KEY_F8;
  102. mTranslateKeyMap[VK_F9] = KEY_F9;
  103. mTranslateKeyMap[VK_F10] = KEY_F10;
  104. mTranslateKeyMap[VK_F11] = KEY_F11;
  105. mTranslateKeyMap[VK_F12] = KEY_F12;
  106. mTranslateKeyMap[VK_CLEAR] = KEY_PAD_CENTER;
  107. // Also translate numeric and operator pad keys into normal numeric and
  108. // character keys (especially useful in menu accelerators for AZERTY
  109. // keyboards where numeric keys are SHIFTed keys)
  110. mTranslateKeyMap[VK_NUMPAD0] = '0';
  111. mTranslateKeyMap[VK_NUMPAD1] = '1';
  112. mTranslateKeyMap[VK_NUMPAD2] = '2';
  113. mTranslateKeyMap[VK_NUMPAD3] = '3';
  114. mTranslateKeyMap[VK_NUMPAD4] = '4';
  115. mTranslateKeyMap[VK_NUMPAD5] = '5';
  116. mTranslateKeyMap[VK_NUMPAD6] = '6';
  117. mTranslateKeyMap[VK_NUMPAD7] = '7';
  118. mTranslateKeyMap[VK_NUMPAD8] = '8';
  119. mTranslateKeyMap[VK_NUMPAD9] = '9';
  120. mTranslateKeyMap[VK_MULTIPLY] = '*';
  121. mTranslateKeyMap[VK_ADD] = '+';
  122. mTranslateKeyMap[VK_SUBTRACT] = '-';
  123. mTranslateKeyMap[VK_DECIMAL] = '.';
  124. mTranslateKeyMap[VK_DIVIDE] = '/';
  125. // Build inverse map
  126. std::map<U32, KEY>::iterator iter;
  127. for (iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end();
  128. ++iter)
  129. {
  130. mInvTranslateKeyMap[iter->second] = iter->first;
  131. }
  132. // Numpad map
  133. mTranslateNumpadMap[VK_NUMPAD0] = KEY_PAD_INS;
  134. mTranslateNumpadMap[VK_NUMPAD1] = KEY_PAD_END;
  135. mTranslateNumpadMap[VK_NUMPAD2] = KEY_PAD_DOWN;
  136. mTranslateNumpadMap[VK_NUMPAD3] = KEY_PAD_PGDN;
  137. mTranslateNumpadMap[VK_NUMPAD4] = KEY_PAD_LEFT;
  138. mTranslateNumpadMap[VK_NUMPAD5] = KEY_PAD_CENTER;
  139. mTranslateNumpadMap[VK_NUMPAD6] = KEY_PAD_RIGHT;
  140. mTranslateNumpadMap[VK_NUMPAD7] = KEY_PAD_HOME;
  141. mTranslateNumpadMap[VK_NUMPAD8] = KEY_PAD_UP;
  142. mTranslateNumpadMap[VK_NUMPAD9] = KEY_PAD_PGUP;
  143. mTranslateNumpadMap[VK_MULTIPLY] = KEY_PAD_MULTIPLY;
  144. mTranslateNumpadMap[VK_ADD] = KEY_PAD_ADD;
  145. mTranslateNumpadMap[VK_SUBTRACT] = KEY_PAD_SUBTRACT;
  146. mTranslateNumpadMap[VK_DECIMAL] = KEY_PAD_DEL;
  147. mTranslateNumpadMap[VK_DIVIDE] = KEY_PAD_DIVIDE;
  148. for (iter = mTranslateNumpadMap.begin(); iter != mTranslateNumpadMap.end();
  149. ++iter)
  150. {
  151. mInvTranslateNumpadMap[iter->second] = iter->first;
  152. }
  153. }
  154. // Asynchronously poll the control, alt and shift keys and set the appropriate
  155. // states. Note: this does not generate edges.
  156. //virtual
  157. void LLKeyboardWin32::resetMaskKeys()
  158. {
  159. // GetAsyncKeyState returns a short and uses the most significant bit to
  160. // indicate that the key is down.
  161. if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
  162. {
  163. mKeyLevel[KEY_SHIFT] = true;
  164. }
  165. if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
  166. {
  167. mKeyLevel[KEY_CONTROL] = true;
  168. }
  169. if (GetAsyncKeyState(VK_MENU) & 0x8000)
  170. {
  171. mKeyLevel[KEY_ALT] = true;
  172. }
  173. }
  174. #if 0
  175. void LLKeyboardWin32::setModifierKeyLevel(KEY key, bool new_state)
  176. {
  177. if (mKeyLevel[key] != new_state)
  178. {
  179. mKeyLevelFrameCount[key] = 0;
  180. if (new_state)
  181. {
  182. mKeyLevelTimer[key].reset();
  183. }
  184. mKeyLevel[key] = new_state;
  185. }
  186. }
  187. #endif
  188. MASK LLKeyboardWin32::updateModifiers()
  189. {
  190. // Used at the login screen, for warning about caps lock on in password
  191. // field. HB
  192. // Low order bit carries the toggle state.
  193. mKeyLevel[KEY_CAPSLOCK] = (GetKeyState(VK_CAPITAL) & 0x0001) != 0;
  194. // Get mask for keyboard events
  195. return currentMask(false);
  196. }
  197. // mask is ignored, except for extended flag: we poll the modifier keys for the
  198. // other flags
  199. //virtual
  200. bool LLKeyboardWin32::handleKeyDown(U32 key, MASK mask)
  201. {
  202. U32 translated_mask = updateModifiers();
  203. KEY translated_key;
  204. if (translateExtendedKey(key, mask, &translated_key, translated_mask))
  205. {
  206. return handleTranslatedKeyDown(translated_key, translated_mask);
  207. }
  208. return false;
  209. }
  210. // mask is ignored, except for extended flag: we poll the modifier keys for the
  211. // other flags
  212. //virtual
  213. bool LLKeyboardWin32::handleKeyUp(U32 key, MASK mask)
  214. {
  215. U32 translated_mask = updateModifiers();
  216. KEY translated_key;
  217. if (translateExtendedKey(key, mask, &translated_key, translated_mask))
  218. {
  219. U32 translated_mask = updateModifiers();
  220. return handleTranslatedKeyUp(translated_key, translated_mask);
  221. }
  222. return false;
  223. }
  224. //virtual
  225. MASK LLKeyboardWin32::currentMask(bool)
  226. {
  227. MASK mask = MASK_NONE;
  228. if (mKeyLevel[KEY_SHIFT])
  229. {
  230. mask |= MASK_SHIFT;
  231. }
  232. if (mKeyLevel[KEY_CONTROL])
  233. {
  234. mask |= MASK_CONTROL;
  235. }
  236. if (mKeyLevel[KEY_ALT])
  237. {
  238. mask |= MASK_ALT;
  239. }
  240. return mask;
  241. }
  242. //virtual
  243. void LLKeyboardWin32::scanKeyboard()
  244. {
  245. MSG msg;
  246. bool pending_key_events = (bool)PeekMessage(&msg, NULL,
  247. WM_KEYFIRST, WM_KEYLAST,
  248. PM_NOREMOVE | PM_NOYIELD);
  249. for (S32 key = 0; key < KEY_COUNT; ++key)
  250. {
  251. // On Windows, verify key down state. JC
  252. // RN: only do this if we do not have further key events in the queue
  253. // as otherwise there might be key repeat events still waiting for this
  254. // key we are now dumping
  255. if (!pending_key_events && mKeyLevel[key])
  256. {
  257. // *TODO: I KNOW there must be a better way of interrogating the
  258. // key state than this, using async key state can cause ALL kinds
  259. // of bugs - Doug
  260. if (key < KEY_BUTTON0 && (key < '0' || key > '9'))
  261. {
  262. // ...under windows make sure the key actually still is down.
  263. // ...translate back to windows key
  264. U32 virtual_key = inverseTranslateExtendedKey(key);
  265. // keydown in highest bit
  266. if (!pending_key_events &&
  267. !(GetAsyncKeyState(virtual_key) & 0x8000))
  268. {
  269. mKeyLevel[key] = false;
  270. }
  271. }
  272. }
  273. // Generate callback if any event has occurred on this key this frame.
  274. // Cannot just test mKeyLevel, because this could be a slow frame and
  275. // key might have gone down then up. JC
  276. if (mKeyLevel[key] || mKeyDown[key] || mKeyUp[key])
  277. {
  278. mCurScanKey = key;
  279. mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key],
  280. mKeyLevel[key]);
  281. }
  282. }
  283. // Reset edges for next frame
  284. for (S32 key = 0; key < KEY_COUNT; ++key)
  285. {
  286. mKeyUp[key] = false;
  287. mKeyDown[key] = false;
  288. if (mKeyLevel[key])
  289. {
  290. ++mKeyLevelFrameCount[key];
  291. }
  292. }
  293. }
  294. bool LLKeyboardWin32::translateExtendedKey(U32 os_key, MASK mask,
  295. KEY* translated_key,
  296. MASK translated_mask)
  297. {
  298. if (mNumpadDistinct == ND_NUMLOCK_ON)
  299. {
  300. std::map<U32, KEY>::iterator iter = mTranslateNumpadMap.find(os_key);
  301. if (iter != mTranslateNumpadMap.end())
  302. {
  303. *translated_key = iter->second;
  304. return true;
  305. }
  306. }
  307. if (!translateKey(os_key, translated_key, translated_mask))
  308. {
  309. return false;
  310. }
  311. if (mNumpadDistinct != ND_NEVER)
  312. {
  313. if (mask & MASK_EXTENDED)
  314. {
  315. // This is where we would create new keycodes for extended keys
  316. // the set of extended keys includes the 'normal' arrow keys and
  317. // the pgup/Down/insert/home/end/delete cluster above the arrow
  318. // keys see:
  319. // http://windowssdk.msdn.microsoft.com/en-us/library/ms646280.aspx
  320. // Only process the return key if numlock is off
  321. if (((mNumpadDistinct == ND_NUMLOCK_OFF &&
  322. !(GetKeyState(VK_NUMLOCK) & 1)) ||
  323. mNumpadDistinct == ND_NUMLOCK_ON) &&
  324. *translated_key == KEY_RETURN)
  325. {
  326. *translated_key = KEY_PAD_RETURN;
  327. }
  328. }
  329. else
  330. {
  331. // The non-extended keys, those are in the numpad
  332. switch (*translated_key)
  333. {
  334. case KEY_LEFT:
  335. *translated_key = KEY_PAD_LEFT;
  336. break;
  337. case KEY_RIGHT:
  338. *translated_key = KEY_PAD_RIGHT;
  339. break;
  340. case KEY_UP:
  341. *translated_key = KEY_PAD_UP;
  342. break;
  343. case KEY_DOWN:
  344. *translated_key = KEY_PAD_DOWN;
  345. break;
  346. case KEY_HOME:
  347. *translated_key = KEY_PAD_HOME;
  348. break;
  349. case KEY_END:
  350. *translated_key = KEY_PAD_END;
  351. break;
  352. case KEY_PAGE_UP:
  353. *translated_key = KEY_PAD_PGUP;
  354. break;
  355. case KEY_PAGE_DOWN:
  356. *translated_key = KEY_PAD_PGDN;
  357. break;
  358. case KEY_INSERT:
  359. *translated_key = KEY_PAD_INS;
  360. break;
  361. case KEY_DELETE:
  362. *translated_key = KEY_PAD_DEL;
  363. }
  364. }
  365. }
  366. return true;
  367. }
  368. U32 LLKeyboardWin32::inverseTranslateExtendedKey(KEY translated_key)
  369. {
  370. // If numlock is on, then we need to translate KEY_PAD_FOO to the
  371. // corresponding number pad number
  372. if (mNumpadDistinct == ND_NUMLOCK_ON && (GetKeyState(VK_NUMLOCK) & 1))
  373. {
  374. std::map<KEY, U32>::iterator iter;
  375. iter = mInvTranslateNumpadMap.find(translated_key);
  376. if (iter != mInvTranslateNumpadMap.end())
  377. {
  378. return iter->second;
  379. }
  380. }
  381. // If numlock is off or we are not converting numbers to arrows, we map our
  382. // keypad arrows to regular arrows since Windows does not distinguish
  383. // between them
  384. KEY converted_key = translated_key;
  385. switch (converted_key)
  386. {
  387. case KEY_PAD_LEFT:
  388. converted_key = KEY_LEFT; break;
  389. case KEY_PAD_RIGHT:
  390. converted_key = KEY_RIGHT; break;
  391. case KEY_PAD_UP:
  392. converted_key = KEY_UP; break;
  393. case KEY_PAD_DOWN:
  394. converted_key = KEY_DOWN; break;
  395. case KEY_PAD_HOME:
  396. converted_key = KEY_HOME; break;
  397. case KEY_PAD_END:
  398. converted_key = KEY_END; break;
  399. case KEY_PAD_PGUP:
  400. converted_key = KEY_PAGE_UP; break;
  401. case KEY_PAD_PGDN:
  402. converted_key = KEY_PAGE_DOWN; break;
  403. case KEY_PAD_INS:
  404. converted_key = KEY_INSERT; break;
  405. case KEY_PAD_DEL:
  406. converted_key = KEY_DELETE;
  407. break;
  408. case KEY_PAD_RETURN:
  409. converted_key = KEY_RETURN;
  410. }
  411. // Convert our virtual keys to OS keys
  412. return inverseTranslateKey(converted_key);
  413. }
  414. #endif