llkeyboardwin32.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:12k
源码类别:

游戏引擎

开发平台:

C++ Builder

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