diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llwindow/llkeyboardwin32.cpp | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/llwindow/llkeyboardwin32.cpp')
-rw-r--r-- | linden/indra/llwindow/llkeyboardwin32.cpp | 401 |
1 files changed, 401 insertions, 0 deletions
diff --git a/linden/indra/llwindow/llkeyboardwin32.cpp b/linden/indra/llwindow/llkeyboardwin32.cpp new file mode 100644 index 0000000..531ad87 --- /dev/null +++ b/linden/indra/llwindow/llkeyboardwin32.cpp | |||
@@ -0,0 +1,401 @@ | |||
1 | /** | ||
2 | * @file llkeyboardwin32.cpp | ||
3 | * @brief Handler for assignable key bindings | ||
4 | * | ||
5 | * Copyright (c) 2001-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #if LL_WINDOWS | ||
29 | |||
30 | #include "linden_common.h" | ||
31 | |||
32 | #include "llkeyboardwin32.h" | ||
33 | |||
34 | #include "llwindow.h" | ||
35 | |||
36 | #define WIN32_LEAN_AND_MEAN | ||
37 | #include <winsock2.h> | ||
38 | #include <windows.h> | ||
39 | |||
40 | LLKeyboardWin32::LLKeyboardWin32() | ||
41 | { | ||
42 | // Set up key mapping for windows - eventually can read this from a file? | ||
43 | // Anything not in the key map gets dropped | ||
44 | // Add default A-Z | ||
45 | |||
46 | // Virtual key mappings from WinUser.h | ||
47 | |||
48 | KEY cur_char; | ||
49 | for (cur_char = 'A'; cur_char <= 'Z'; cur_char++) | ||
50 | { | ||
51 | mTranslateKeyMap[cur_char] = (KEY)cur_char; | ||
52 | } | ||
53 | |||
54 | for (cur_char = '0'; cur_char <= '9'; cur_char++) | ||
55 | { | ||
56 | mTranslateKeyMap[cur_char] = (KEY)cur_char; | ||
57 | } | ||
58 | // numpad number keys | ||
59 | for (cur_char = 0x60; cur_char <= 0x69; cur_char++) | ||
60 | { | ||
61 | mTranslateKeyMap[cur_char] = (KEY)('0' + (0x60 - cur_char)); | ||
62 | } | ||
63 | |||
64 | |||
65 | mTranslateKeyMap[VK_SPACE] = ' '; | ||
66 | mTranslateKeyMap[VK_OEM_1] = ';'; | ||
67 | // When the user hits, for example, Ctrl-= as a keyboard shortcut, | ||
68 | // Windows generates VK_OEM_PLUS. This is true on both QWERTY and DVORAK | ||
69 | // keyboards in the US. Numeric keypad '+' generates VK_ADD below. | ||
70 | // Thus we translate it as '='. | ||
71 | // Potential bug: This may not be true on international keyboards. JC | ||
72 | mTranslateKeyMap[VK_OEM_PLUS] = '='; | ||
73 | mTranslateKeyMap[VK_OEM_COMMA] = ','; | ||
74 | mTranslateKeyMap[VK_OEM_MINUS] = '-'; | ||
75 | mTranslateKeyMap[VK_OEM_PERIOD] = '.'; | ||
76 | mTranslateKeyMap[VK_OEM_2] = '/'; | ||
77 | mTranslateKeyMap[VK_OEM_3] = '`'; | ||
78 | mTranslateKeyMap[VK_OEM_4] = '['; | ||
79 | mTranslateKeyMap[VK_OEM_5] = '\\'; | ||
80 | mTranslateKeyMap[VK_OEM_6] = ']'; | ||
81 | mTranslateKeyMap[VK_OEM_7] = '\''; | ||
82 | mTranslateKeyMap[VK_ESCAPE] = KEY_ESCAPE; | ||
83 | mTranslateKeyMap[VK_RETURN] = KEY_RETURN; | ||
84 | mTranslateKeyMap[VK_LEFT] = KEY_LEFT; | ||
85 | mTranslateKeyMap[VK_RIGHT] = KEY_RIGHT; | ||
86 | mTranslateKeyMap[VK_UP] = KEY_UP; | ||
87 | mTranslateKeyMap[VK_DOWN] = KEY_DOWN; | ||
88 | mTranslateKeyMap[VK_BACK] = KEY_BACKSPACE; | ||
89 | mTranslateKeyMap[VK_INSERT] = KEY_INSERT; | ||
90 | mTranslateKeyMap[VK_DELETE] = KEY_DELETE; | ||
91 | mTranslateKeyMap[VK_SHIFT] = KEY_SHIFT; | ||
92 | mTranslateKeyMap[VK_CONTROL] = KEY_CONTROL; | ||
93 | mTranslateKeyMap[VK_MENU] = KEY_ALT; | ||
94 | mTranslateKeyMap[VK_CAPITAL] = KEY_CAPSLOCK; | ||
95 | mTranslateKeyMap[VK_HOME] = KEY_HOME; | ||
96 | mTranslateKeyMap[VK_END] = KEY_END; | ||
97 | mTranslateKeyMap[VK_PRIOR] = KEY_PAGE_UP; | ||
98 | mTranslateKeyMap[VK_NEXT] = KEY_PAGE_DOWN; | ||
99 | mTranslateKeyMap[VK_TAB] = KEY_TAB; | ||
100 | mTranslateKeyMap[VK_ADD] = KEY_ADD; | ||
101 | mTranslateKeyMap[VK_SUBTRACT] = KEY_SUBTRACT; | ||
102 | mTranslateKeyMap[VK_MULTIPLY] = KEY_MULTIPLY; | ||
103 | mTranslateKeyMap[VK_DIVIDE] = KEY_DIVIDE; | ||
104 | mTranslateKeyMap[VK_F1] = KEY_F1; | ||
105 | mTranslateKeyMap[VK_F2] = KEY_F2; | ||
106 | mTranslateKeyMap[VK_F3] = KEY_F3; | ||
107 | mTranslateKeyMap[VK_F4] = KEY_F4; | ||
108 | mTranslateKeyMap[VK_F5] = KEY_F5; | ||
109 | mTranslateKeyMap[VK_F6] = KEY_F6; | ||
110 | mTranslateKeyMap[VK_F7] = KEY_F7; | ||
111 | mTranslateKeyMap[VK_F8] = KEY_F8; | ||
112 | mTranslateKeyMap[VK_F9] = KEY_F9; | ||
113 | mTranslateKeyMap[VK_F10] = KEY_F10; | ||
114 | mTranslateKeyMap[VK_F11] = KEY_F11; | ||
115 | mTranslateKeyMap[VK_F12] = KEY_F12; | ||
116 | mTranslateKeyMap[VK_CLEAR] = KEY_PAD_CENTER; | ||
117 | |||
118 | // Build inverse map | ||
119 | std::map<U16, KEY>::iterator iter; | ||
120 | for (iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++) | ||
121 | { | ||
122 | mInvTranslateKeyMap[iter->second] = iter->first; | ||
123 | } | ||
124 | |||
125 | // numpad map | ||
126 | mTranslateNumpadMap[0x60] = KEY_PAD_INS; // keypad 0 | ||
127 | mTranslateNumpadMap[0x61] = KEY_PAD_END; // keypad 1 | ||
128 | mTranslateNumpadMap[0x62] = KEY_PAD_DOWN; // keypad 2 | ||
129 | mTranslateNumpadMap[0x63] = KEY_PAD_PGDN; // keypad 3 | ||
130 | mTranslateNumpadMap[0x64] = KEY_PAD_LEFT; // keypad 4 | ||
131 | mTranslateNumpadMap[0x65] = KEY_PAD_CENTER; // keypad 5 | ||
132 | mTranslateNumpadMap[0x66] = KEY_PAD_RIGHT; // keypad 6 | ||
133 | mTranslateNumpadMap[0x67] = KEY_PAD_HOME; // keypad 7 | ||
134 | mTranslateNumpadMap[0x68] = KEY_PAD_UP; // keypad 8 | ||
135 | mTranslateNumpadMap[0x69] = KEY_PAD_PGUP; // keypad 9 | ||
136 | mTranslateNumpadMap[0x6E] = KEY_PAD_DEL; // keypad . | ||
137 | |||
138 | for (iter = mTranslateNumpadMap.begin(); iter != mTranslateNumpadMap.end(); iter++) | ||
139 | { | ||
140 | mInvTranslateNumpadMap[iter->second] = iter->first; | ||
141 | } | ||
142 | } | ||
143 | |||
144 | // Asynchronously poll the control, alt and shift keys and set the | ||
145 | // appropriate states. | ||
146 | // Note: this does not generate edges. | ||
147 | void LLKeyboardWin32::resetMaskKeys() | ||
148 | { | ||
149 | // GetAsyncKeyState returns a short and uses the most significant | ||
150 | // bit to indicate that the key is down. | ||
151 | if (GetAsyncKeyState(VK_SHIFT) & 0x8000) | ||
152 | { | ||
153 | mKeyLevel[KEY_SHIFT] = TRUE; | ||
154 | } | ||
155 | |||
156 | if (GetAsyncKeyState(VK_CONTROL) & 0x8000) | ||
157 | { | ||
158 | mKeyLevel[KEY_CONTROL] = TRUE; | ||
159 | } | ||
160 | |||
161 | if (GetAsyncKeyState(VK_MENU) & 0x8000) | ||
162 | { | ||
163 | mKeyLevel[KEY_ALT] = TRUE; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | |||
168 | //void LLKeyboardWin32::setModifierKeyLevel( KEY key, BOOL new_state ) | ||
169 | //{ | ||
170 | // if( mKeyLevel[key] != new_state ) | ||
171 | // { | ||
172 | // mKeyLevelFrameCount[key] = 0; | ||
173 | // | ||
174 | // if( new_state ) | ||
175 | // { | ||
176 | // mKeyLevelTimer[key].reset(); | ||
177 | // } | ||
178 | // mKeyLevel[key] = new_state; | ||
179 | // } | ||
180 | //} | ||
181 | |||
182 | |||
183 | MASK LLKeyboardWin32::updateModifiers() | ||
184 | { | ||
185 | //RN: this seems redundant, as we should have already received the appropriate | ||
186 | // messages for the modifier keys | ||
187 | |||
188 | // Scan the modifier keys as of the last Windows key message | ||
189 | // (keydown encoded in high order bit of short) | ||
190 | //setModifierKeyLevel( KEY_SHIFT, GetKeyState(VK_SHIFT) & 0x8000 ); | ||
191 | //setModifierKeyLevel( KEY_CONTROL, GetKeyState(VK_CONTROL) & 0x8000 ); | ||
192 | //setModifierKeyLevel( KEY_ALT, GetKeyState(VK_MENU) & 0x8000 ); | ||
193 | //setModifierKeyLevel( KEY_CAPSLOCK, GetKeyState(VK_CAPITAL) & 0x0001); // Low order bit carries the toggle state. | ||
194 | // Get mask for keyboard events | ||
195 | MASK mask = currentMask(FALSE); | ||
196 | return mask; | ||
197 | } | ||
198 | |||
199 | |||
200 | // mask is ignored, except for extended flag -- we poll the modifier keys for the other flags | ||
201 | BOOL LLKeyboardWin32::handleKeyDown(const U16 key, MASK mask) | ||
202 | { | ||
203 | KEY translated_key; | ||
204 | U32 translated_mask; | ||
205 | BOOL handled = FALSE; | ||
206 | |||
207 | translated_mask = updateModifiers(); | ||
208 | |||
209 | if (translateExtendedKey(key, mask, &translated_key)) | ||
210 | { | ||
211 | handled = handleTranslatedKeyDown(translated_key, translated_mask); | ||
212 | } | ||
213 | |||
214 | return handled; | ||
215 | } | ||
216 | |||
217 | |||
218 | // mask is ignored, except for extended flag -- we poll the modifier keys for the other flags | ||
219 | BOOL LLKeyboardWin32::handleKeyUp(const U16 key, MASK mask) | ||
220 | { | ||
221 | KEY translated_key; | ||
222 | U32 translated_mask; | ||
223 | BOOL handled = FALSE; | ||
224 | |||
225 | translated_mask = updateModifiers(); | ||
226 | |||
227 | if (translateExtendedKey(key, mask, &translated_key)) | ||
228 | { | ||
229 | handled = handleTranslatedKeyUp(translated_key, translated_mask); | ||
230 | } | ||
231 | |||
232 | return handled; | ||
233 | } | ||
234 | |||
235 | |||
236 | MASK LLKeyboardWin32::currentMask(BOOL) | ||
237 | { | ||
238 | MASK mask = MASK_NONE; | ||
239 | |||
240 | if (mKeyLevel[KEY_SHIFT]) mask |= MASK_SHIFT; | ||
241 | if (mKeyLevel[KEY_CONTROL]) mask |= MASK_CONTROL; | ||
242 | if (mKeyLevel[KEY_ALT]) mask |= MASK_ALT; | ||
243 | |||
244 | return mask; | ||
245 | } | ||
246 | |||
247 | |||
248 | void LLKeyboardWin32::scanKeyboard() | ||
249 | { | ||
250 | S32 key; | ||
251 | for (key = 0; key < KEY_COUNT; key++) | ||
252 | { | ||
253 | // On Windows, verify key down state. JC | ||
254 | if (mKeyLevel[key]) | ||
255 | { | ||
256 | // *TODO: I KNOW there must be a better way of | ||
257 | // interrogating the key state than this, using async key | ||
258 | // state can cause ALL kinds of bugs - Doug | ||
259 | if (key < KEY_BUTTON0) | ||
260 | { | ||
261 | // ...under windows make sure the key actually still is down. | ||
262 | // ...translate back to windows key | ||
263 | U16 virtual_key = inverseTranslateExtendedKey(key); | ||
264 | // keydown in highest bit | ||
265 | if (!(GetAsyncKeyState(virtual_key) & 0x8000)) | ||
266 | { | ||
267 | //llinfos << "Key up event missed, resetting" << llendl; | ||
268 | mKeyLevel[key] = FALSE; | ||
269 | mKeyLevelFrameCount[key] = 0; | ||
270 | } | ||
271 | } | ||
272 | } | ||
273 | |||
274 | // Generate callback if any event has occurred on this key this frame. | ||
275 | // Can't just test mKeyLevel, because this could be a slow frame and | ||
276 | // key might have gone down then up. JC | ||
277 | if (mKeyLevel[key] || mKeyDown[key] || mKeyUp[key]) | ||
278 | { | ||
279 | mCurScanKey = key; | ||
280 | mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | // Reset edges for next frame | ||
285 | for (key = 0; key < KEY_COUNT; key++) | ||
286 | { | ||
287 | mKeyUp[key] = FALSE; | ||
288 | mKeyDown[key] = FALSE; | ||
289 | if (mKeyLevel[key]) | ||
290 | { | ||
291 | mKeyLevelFrameCount[key]++; | ||
292 | } | ||
293 | } | ||
294 | } | ||
295 | |||
296 | BOOL LLKeyboardWin32::translateExtendedKey(const U16 os_key, const MASK mask, KEY *translated_key) | ||
297 | { | ||
298 | if(mNumpadDistinct == ND_NUMLOCK_ON) | ||
299 | { | ||
300 | std::map<U16, KEY>::iterator iter = mTranslateNumpadMap.find(os_key); | ||
301 | if (iter != mTranslateNumpadMap.end()) | ||
302 | { | ||
303 | *translated_key = iter->second; | ||
304 | return TRUE; | ||
305 | } | ||
306 | } | ||
307 | |||
308 | BOOL success = translateKey(os_key, translated_key); | ||
309 | if(mNumpadDistinct != ND_NEVER) { | ||
310 | if(!success) return success; | ||
311 | if(mask & MASK_EXTENDED) | ||
312 | { | ||
313 | // this is where we'd create new keycodes for extended keys | ||
314 | // the set of extended keys includes the 'normal' arrow keys and | ||
315 | // the pgup/dn/insert/home/end/delete cluster above the arrow keys | ||
316 | // see http://windowssdk.msdn.microsoft.com/en-us/library/ms646280.aspx | ||
317 | |||
318 | // only process the return key if numlock is off | ||
319 | if(((mNumpadDistinct == ND_NUMLOCK_OFF && | ||
320 | !(GetKeyState(VK_NUMLOCK) & 1)) | ||
321 | || mNumpadDistinct == ND_NUMLOCK_ON) && | ||
322 | *translated_key == KEY_RETURN) { | ||
323 | *translated_key = KEY_PAD_RETURN; | ||
324 | } | ||
325 | } | ||
326 | else | ||
327 | { | ||
328 | // the non-extended keys, those are in the numpad | ||
329 | switch (*translated_key) | ||
330 | { | ||
331 | case KEY_LEFT: | ||
332 | *translated_key = KEY_PAD_LEFT; break; | ||
333 | case KEY_RIGHT: | ||
334 | *translated_key = KEY_PAD_RIGHT; break; | ||
335 | case KEY_UP: | ||
336 | *translated_key = KEY_PAD_UP; break; | ||
337 | case KEY_DOWN: | ||
338 | *translated_key = KEY_PAD_DOWN; break; | ||
339 | case KEY_HOME: | ||
340 | *translated_key = KEY_PAD_HOME; break; | ||
341 | case KEY_END: | ||
342 | *translated_key = KEY_PAD_END; break; | ||
343 | case KEY_PAGE_UP: | ||
344 | *translated_key = KEY_PAD_PGUP; break; | ||
345 | case KEY_PAGE_DOWN: | ||
346 | *translated_key = KEY_PAD_PGDN; break; | ||
347 | case KEY_INSERT: | ||
348 | *translated_key = KEY_PAD_INS; break; | ||
349 | case KEY_DELETE: | ||
350 | *translated_key = KEY_PAD_DEL; break; | ||
351 | } | ||
352 | } | ||
353 | } | ||
354 | return success; | ||
355 | } | ||
356 | |||
357 | U16 LLKeyboardWin32::inverseTranslateExtendedKey(const KEY translated_key) | ||
358 | { | ||
359 | // if numlock is on, then we need to translate KEY_PAD_FOO to the corresponding number pad number | ||
360 | if((mNumpadDistinct == ND_NUMLOCK_ON) && (GetKeyState(VK_NUMLOCK) & 1)) | ||
361 | { | ||
362 | std::map<KEY, U16>::iterator iter = mInvTranslateNumpadMap.find(translated_key); | ||
363 | if (iter != mInvTranslateNumpadMap.end()) | ||
364 | { | ||
365 | return iter->second; | ||
366 | } | ||
367 | } | ||
368 | |||
369 | // if numlock is off or we're not converting numbers to arrows, we map our keypad arrows | ||
370 | // to regular arrows since Windows doesn't distinguish between them | ||
371 | KEY converted_key = translated_key; | ||
372 | switch (converted_key) | ||
373 | { | ||
374 | case KEY_PAD_LEFT: | ||
375 | converted_key = KEY_LEFT; break; | ||
376 | case KEY_PAD_RIGHT: | ||
377 | converted_key = KEY_RIGHT; break; | ||
378 | case KEY_PAD_UP: | ||
379 | converted_key = KEY_UP; break; | ||
380 | case KEY_PAD_DOWN: | ||
381 | converted_key = KEY_DOWN; break; | ||
382 | case KEY_PAD_HOME: | ||
383 | converted_key = KEY_HOME; break; | ||
384 | case KEY_PAD_END: | ||
385 | converted_key = KEY_END; break; | ||
386 | case KEY_PAD_PGUP: | ||
387 | converted_key = KEY_PAGE_UP; break; | ||
388 | case KEY_PAD_PGDN: | ||
389 | converted_key = KEY_PAGE_DOWN; break; | ||
390 | case KEY_PAD_INS: | ||
391 | converted_key = KEY_INSERT; break; | ||
392 | case KEY_PAD_DEL: | ||
393 | converted_key = KEY_DELETE; break; | ||
394 | case KEY_PAD_RETURN: | ||
395 | converted_key = KEY_RETURN; break; | ||
396 | } | ||
397 | // convert our virtual keys to OS keys | ||
398 | return inverseTranslateKey(converted_key); | ||
399 | } | ||
400 | |||
401 | #endif | ||