PageRenderTime 102ms CodeModel.GetById 80ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llwindow/llkeyboardsdl.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 342 lines | 239 code | 47 blank | 56 comment | 36 complexity | 57bc4d92fe8ce5b00909445305a3c3f8 MD5 | raw file
  1/** 
  2 * @file llkeyboardsdl.cpp
  3 * @brief Handler for assignable key bindings
  4 *
  5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#if LL_SDL
 28
 29#include "linden_common.h"
 30#include "llkeyboardsdl.h"
 31#include "llwindowcallbacks.h"
 32#include "SDL/SDL.h"
 33
 34LLKeyboardSDL::LLKeyboardSDL()
 35{
 36	// Set up key mapping for SDL - eventually can read this from a file?
 37	// Anything not in the key map gets dropped
 38	// Add default A-Z
 39
 40	// Virtual key mappings from SDL_keysym.h ...
 41
 42	// SDL maps the letter keys to the ASCII you'd expect, but it's lowercase...
 43	U16 cur_char;
 44	for (cur_char = 'A'; cur_char <= 'Z'; cur_char++)
 45	{
 46		mTranslateKeyMap[cur_char] = cur_char;
 47	}
 48	for (cur_char = 'a'; cur_char <= 'z'; cur_char++)
 49	{
 50		mTranslateKeyMap[cur_char] = (cur_char - 'a') + 'A';
 51	}
 52
 53	for (cur_char = '0'; cur_char <= '9'; cur_char++)
 54	{
 55		mTranslateKeyMap[cur_char] = cur_char;
 56	}
 57
 58	// These ones are translated manually upon keydown/keyup because
 59	// SDL doesn't handle their numlock transition.
 60	//mTranslateKeyMap[SDLK_KP4] = KEY_PAD_LEFT;
 61	//mTranslateKeyMap[SDLK_KP6] = KEY_PAD_RIGHT;
 62	//mTranslateKeyMap[SDLK_KP8] = KEY_PAD_UP;
 63	//mTranslateKeyMap[SDLK_KP2] = KEY_PAD_DOWN;
 64	//mTranslateKeyMap[SDLK_KP_PERIOD] = KEY_DELETE;
 65	//mTranslateKeyMap[SDLK_KP7] = KEY_HOME;
 66	//mTranslateKeyMap[SDLK_KP1] = KEY_END;
 67	//mTranslateKeyMap[SDLK_KP9] = KEY_PAGE_UP;
 68	//mTranslateKeyMap[SDLK_KP3] = KEY_PAGE_DOWN;
 69	//mTranslateKeyMap[SDLK_KP0] = KEY_INSERT;
 70
 71	mTranslateKeyMap[SDLK_SPACE] = ' ';
 72	mTranslateKeyMap[SDLK_RETURN] = KEY_RETURN;
 73	mTranslateKeyMap[SDLK_LEFT] = KEY_LEFT;
 74	mTranslateKeyMap[SDLK_RIGHT] = KEY_RIGHT;
 75	mTranslateKeyMap[SDLK_UP] = KEY_UP;
 76	mTranslateKeyMap[SDLK_DOWN] = KEY_DOWN;
 77	mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE;
 78	mTranslateKeyMap[SDLK_KP_ENTER] = KEY_RETURN;
 79	mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE;
 80	mTranslateKeyMap[SDLK_BACKSPACE] = KEY_BACKSPACE;
 81	mTranslateKeyMap[SDLK_DELETE] = KEY_DELETE;
 82	mTranslateKeyMap[SDLK_LSHIFT] = KEY_SHIFT;
 83	mTranslateKeyMap[SDLK_RSHIFT] = KEY_SHIFT;
 84	mTranslateKeyMap[SDLK_LCTRL] = KEY_CONTROL;
 85	mTranslateKeyMap[SDLK_RCTRL] = KEY_CONTROL;
 86	mTranslateKeyMap[SDLK_LALT] = KEY_ALT;
 87	mTranslateKeyMap[SDLK_RALT] = KEY_ALT;
 88	mTranslateKeyMap[SDLK_HOME] = KEY_HOME;
 89	mTranslateKeyMap[SDLK_END] = KEY_END;
 90	mTranslateKeyMap[SDLK_PAGEUP] = KEY_PAGE_UP;
 91	mTranslateKeyMap[SDLK_PAGEDOWN] = KEY_PAGE_DOWN;
 92	mTranslateKeyMap[SDLK_MINUS] = KEY_HYPHEN;
 93	mTranslateKeyMap[SDLK_EQUALS] = KEY_EQUALS;
 94	mTranslateKeyMap[SDLK_KP_EQUALS] = KEY_EQUALS;
 95	mTranslateKeyMap[SDLK_INSERT] = KEY_INSERT;
 96	mTranslateKeyMap[SDLK_CAPSLOCK] = KEY_CAPSLOCK;
 97	mTranslateKeyMap[SDLK_TAB] = KEY_TAB;
 98	mTranslateKeyMap[SDLK_KP_PLUS] = KEY_ADD;
 99	mTranslateKeyMap[SDLK_KP_MINUS] = KEY_SUBTRACT;
100	mTranslateKeyMap[SDLK_KP_MULTIPLY] = KEY_MULTIPLY;
101	mTranslateKeyMap[SDLK_KP_DIVIDE] = KEY_PAD_DIVIDE;
102	mTranslateKeyMap[SDLK_F1] = KEY_F1;
103	mTranslateKeyMap[SDLK_F2] = KEY_F2;
104	mTranslateKeyMap[SDLK_F3] = KEY_F3;
105	mTranslateKeyMap[SDLK_F4] = KEY_F4;
106	mTranslateKeyMap[SDLK_F5] = KEY_F5;
107	mTranslateKeyMap[SDLK_F6] = KEY_F6;
108	mTranslateKeyMap[SDLK_F7] = KEY_F7;
109	mTranslateKeyMap[SDLK_F8] = KEY_F8;
110	mTranslateKeyMap[SDLK_F9] = KEY_F9;
111	mTranslateKeyMap[SDLK_F10] = KEY_F10;
112	mTranslateKeyMap[SDLK_F11] = KEY_F11;
113	mTranslateKeyMap[SDLK_F12] = KEY_F12;
114	mTranslateKeyMap[SDLK_PLUS]   = '=';
115	mTranslateKeyMap[SDLK_COMMA]  = ',';
116	mTranslateKeyMap[SDLK_MINUS]  = '-';
117	mTranslateKeyMap[SDLK_PERIOD] = '.';
118	mTranslateKeyMap[SDLK_BACKQUOTE] = '`';
119	mTranslateKeyMap[SDLK_SLASH] = KEY_DIVIDE;
120	mTranslateKeyMap[SDLK_SEMICOLON] = ';';
121	mTranslateKeyMap[SDLK_LEFTBRACKET] = '[';
122	mTranslateKeyMap[SDLK_BACKSLASH] = '\\';
123	mTranslateKeyMap[SDLK_RIGHTBRACKET] = ']';
124	mTranslateKeyMap[SDLK_QUOTE] = '\'';
125
126	// Build inverse map
127	std::map<U16, KEY>::iterator iter;
128	for (iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++)
129	{
130		mInvTranslateKeyMap[iter->second] = iter->first;
131	}
132
133	// numpad map
134	mTranslateNumpadMap[SDLK_KP0] = KEY_PAD_INS;
135	mTranslateNumpadMap[SDLK_KP1] = KEY_PAD_END;
136	mTranslateNumpadMap[SDLK_KP2] = KEY_PAD_DOWN;
137	mTranslateNumpadMap[SDLK_KP3] = KEY_PAD_PGDN;
138	mTranslateNumpadMap[SDLK_KP4] = KEY_PAD_LEFT;
139	mTranslateNumpadMap[SDLK_KP5] = KEY_PAD_CENTER;
140	mTranslateNumpadMap[SDLK_KP6] = KEY_PAD_RIGHT;
141	mTranslateNumpadMap[SDLK_KP7] = KEY_PAD_HOME;
142	mTranslateNumpadMap[SDLK_KP8] = KEY_PAD_UP;
143	mTranslateNumpadMap[SDLK_KP9] = KEY_PAD_PGUP;
144	mTranslateNumpadMap[SDLK_KP_PERIOD] = KEY_PAD_DEL;
145
146	// build inverse numpad map
147	for (iter = mTranslateNumpadMap.begin();
148	     iter != mTranslateNumpadMap.end();
149	     iter++)
150	{
151		mInvTranslateNumpadMap[iter->second] = iter->first;
152	}
153}
154
155void LLKeyboardSDL::resetMaskKeys()
156{
157	SDLMod mask = SDL_GetModState();
158
159	// MBW -- XXX -- This mirrors the operation of the Windows version of resetMaskKeys().
160	//    It looks a bit suspicious, as it won't correct for keys that have been released.
161	//    Is this the way it's supposed to work?
162
163	if(mask & KMOD_SHIFT)
164	{
165		mKeyLevel[KEY_SHIFT] = TRUE;
166	}
167
168	if(mask & KMOD_CTRL)
169	{
170		mKeyLevel[KEY_CONTROL] = TRUE;
171	}
172
173	if(mask & KMOD_ALT)
174	{
175		mKeyLevel[KEY_ALT] = TRUE;
176	}
177}
178
179
180MASK LLKeyboardSDL::updateModifiers(const U32 mask)
181{
182	// translate the mask
183	MASK out_mask = MASK_NONE;
184
185	if(mask & KMOD_SHIFT)
186	{
187		out_mask |= MASK_SHIFT;
188	}
189
190	if(mask & KMOD_CTRL)
191	{
192		out_mask |= MASK_CONTROL;
193	}
194
195	if(mask & KMOD_ALT)
196	{
197		out_mask |= MASK_ALT;
198	}
199
200	return out_mask;
201}
202
203
204static U16 adjustNativekeyFromUnhandledMask(const U16 key, const U32 mask)
205{
206	// SDL doesn't automatically adjust the keysym according to
207	// whether NUMLOCK is engaged, so we massage the keysym manually.
208	U16 rtn = key;
209	if (!(mask & KMOD_NUM))
210	{
211		switch (key)
212		{
213		case SDLK_KP_PERIOD: rtn = SDLK_DELETE; break;
214		case SDLK_KP0: rtn = SDLK_INSERT; break;
215		case SDLK_KP1: rtn = SDLK_END; break;
216		case SDLK_KP2: rtn = SDLK_DOWN; break;
217		case SDLK_KP3: rtn = SDLK_PAGEDOWN; break;
218		case SDLK_KP4: rtn = SDLK_LEFT; break;
219		case SDLK_KP6: rtn = SDLK_RIGHT; break;
220		case SDLK_KP7: rtn = SDLK_HOME; break;
221		case SDLK_KP8: rtn = SDLK_UP; break;
222		case SDLK_KP9: rtn = SDLK_PAGEUP; break;
223		}
224	}
225	return rtn;
226}
227
228
229BOOL LLKeyboardSDL::handleKeyDown(const U16 key, const U32 mask)
230{
231	U16     adjusted_nativekey;
232	KEY	translated_key = 0;
233	U32	translated_mask = MASK_NONE;
234	BOOL	handled = FALSE;
235
236	adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
237
238	translated_mask = updateModifiers(mask);
239	
240	if(translateNumpadKey(adjusted_nativekey, &translated_key))
241	{
242		handled = handleTranslatedKeyDown(translated_key, translated_mask);
243	}
244
245	return handled;
246}
247
248
249BOOL LLKeyboardSDL::handleKeyUp(const U16 key, const U32 mask)
250{
251	U16     adjusted_nativekey;
252	KEY	translated_key = 0;
253	U32	translated_mask = MASK_NONE;
254	BOOL	handled = FALSE;
255
256	adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
257
258	translated_mask = updateModifiers(mask);
259
260	if(translateNumpadKey(adjusted_nativekey, &translated_key))
261	{
262		handled = handleTranslatedKeyUp(translated_key, translated_mask);
263	}
264
265	return handled;
266}
267
268MASK LLKeyboardSDL::currentMask(BOOL for_mouse_event)
269{
270	MASK result = MASK_NONE;
271	SDLMod mask = SDL_GetModState();
272
273	if (mask & KMOD_SHIFT)			result |= MASK_SHIFT;
274	if (mask & KMOD_CTRL)			result |= MASK_CONTROL;
275	if (mask & KMOD_ALT)			result |= MASK_ALT;
276
277	// For keyboard events, consider Meta keys equivalent to Control
278	if (!for_mouse_event)
279	{
280		if (mask & KMOD_META) result |= MASK_CONTROL;
281	}
282
283	return result;
284}
285
286void LLKeyboardSDL::scanKeyboard()
287{
288	for (S32 key = 0; key < KEY_COUNT; key++)
289	{
290		// Generate callback if any event has occurred on this key this frame.
291		// Can't just test mKeyLevel, because this could be a slow frame and
292		// key might have gone down then up. JC
293		if (mKeyLevel[key] || mKeyDown[key] || mKeyUp[key])
294		{
295			mCurScanKey = key;
296			mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]);
297		}
298	}
299
300	// Reset edges for next frame
301	for (S32 key = 0; key < KEY_COUNT; key++)
302	{
303		mKeyUp[key] = FALSE;
304		mKeyDown[key] = FALSE;
305		if (mKeyLevel[key])
306		{
307			mKeyLevelFrameCount[key]++;
308		}
309	}
310}
311
312 
313BOOL LLKeyboardSDL::translateNumpadKey( const U16 os_key, KEY *translated_key)
314{
315	if(mNumpadDistinct == ND_NUMLOCK_ON)
316	{
317		std::map<U16, KEY>::iterator iter= mTranslateNumpadMap.find(os_key);
318		if(iter != mTranslateNumpadMap.end())
319		{
320			*translated_key = iter->second;
321			return TRUE;
322		}
323	}
324	BOOL success = translateKey(os_key, translated_key);
325	return success;	
326}
327
328U16 LLKeyboardSDL::inverseTranslateNumpadKey(const KEY translated_key)
329{
330	if(mNumpadDistinct == ND_NUMLOCK_ON)
331	{
332		std::map<KEY, U16>::iterator iter= mInvTranslateNumpadMap.find(translated_key);
333		if(iter != mInvTranslateNumpadMap.end())
334		{
335			return iter->second;
336		}
337	}
338	return inverseTranslateKey(translated_key);
339}
340
341#endif
342