aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llwindow/llkeyboardwin32.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llwindow/llkeyboardwin32.cpp
parentREADME.txt (diff)
downloadmeta-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.cpp401
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
40LLKeyboardWin32::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.
147void 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
183MASK 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
201BOOL 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
219BOOL 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
236MASK 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
248void 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
296BOOL 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
357U16 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