349 lines
9.8 KiB
C++
349 lines
9.8 KiB
C++
/**
|
|
* @file llkeyboardsdl.cpp
|
|
* @brief Handler for assignable key bindings
|
|
*
|
|
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
|
*
|
|
* Copyright (c) 2001-2009, Linden Research, Inc.
|
|
*
|
|
* Second Life Viewer Source Code
|
|
* The source code in this file ("Source Code") is provided by Linden Lab
|
|
* to you under the terms of the GNU General Public License, version 2.0
|
|
* ("GPL"), unless you have obtained a separate licensing agreement
|
|
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
|
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
|
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
|
*
|
|
* There are special exceptions to the terms and conditions of the GPL as
|
|
* it is applied to this Source Code. View the full text of the exception
|
|
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
|
* online at
|
|
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
|
*
|
|
* By copying, modifying or distributing this software, you acknowledge
|
|
* that you have read and understood your obligations described above,
|
|
* and agree to abide by those obligations.
|
|
*
|
|
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
|
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
|
* COMPLETENESS OR PERFORMANCE.
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#if LL_SDL
|
|
|
|
#include "linden_common.h"
|
|
#include "llkeyboardsdl.h"
|
|
#include "llwindowcallbacks.h"
|
|
#include "SDL/SDL.h"
|
|
|
|
LLKeyboardSDL::LLKeyboardSDL()
|
|
{
|
|
// Set up key mapping for SDL - eventually can read this from a file?
|
|
// Anything not in the key map gets dropped
|
|
// Add default A-Z
|
|
|
|
// Virtual key mappings from SDL_keysym.h ...
|
|
|
|
// SDL maps the letter keys to the ASCII you'd expect, but it's lowercase...
|
|
U16 cur_char;
|
|
for (cur_char = 'A'; cur_char <= 'Z'; cur_char++)
|
|
{
|
|
mTranslateKeyMap[cur_char] = cur_char;
|
|
}
|
|
for (cur_char = 'a'; cur_char <= 'z'; cur_char++)
|
|
{
|
|
mTranslateKeyMap[cur_char] = (cur_char - 'a') + 'A';
|
|
}
|
|
|
|
for (cur_char = '0'; cur_char <= '9'; cur_char++)
|
|
{
|
|
mTranslateKeyMap[cur_char] = cur_char;
|
|
}
|
|
|
|
// These ones are translated manually upon keydown/keyup because
|
|
// SDL doesn't handle their numlock transition.
|
|
//mTranslateKeyMap[SDLK_KP4] = KEY_PAD_LEFT;
|
|
//mTranslateKeyMap[SDLK_KP6] = KEY_PAD_RIGHT;
|
|
//mTranslateKeyMap[SDLK_KP8] = KEY_PAD_UP;
|
|
//mTranslateKeyMap[SDLK_KP2] = KEY_PAD_DOWN;
|
|
//mTranslateKeyMap[SDLK_KP_PERIOD] = KEY_DELETE;
|
|
//mTranslateKeyMap[SDLK_KP7] = KEY_HOME;
|
|
//mTranslateKeyMap[SDLK_KP1] = KEY_END;
|
|
//mTranslateKeyMap[SDLK_KP9] = KEY_PAGE_UP;
|
|
//mTranslateKeyMap[SDLK_KP3] = KEY_PAGE_DOWN;
|
|
//mTranslateKeyMap[SDLK_KP0] = KEY_INSERT;
|
|
|
|
mTranslateKeyMap[SDLK_SPACE] = ' ';
|
|
mTranslateKeyMap[SDLK_RETURN] = KEY_RETURN;
|
|
mTranslateKeyMap[SDLK_LEFT] = KEY_LEFT;
|
|
mTranslateKeyMap[SDLK_RIGHT] = KEY_RIGHT;
|
|
mTranslateKeyMap[SDLK_UP] = KEY_UP;
|
|
mTranslateKeyMap[SDLK_DOWN] = KEY_DOWN;
|
|
mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE;
|
|
mTranslateKeyMap[SDLK_KP_ENTER] = KEY_RETURN;
|
|
mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE;
|
|
mTranslateKeyMap[SDLK_BACKSPACE] = KEY_BACKSPACE;
|
|
mTranslateKeyMap[SDLK_DELETE] = KEY_DELETE;
|
|
mTranslateKeyMap[SDLK_LSHIFT] = KEY_SHIFT;
|
|
mTranslateKeyMap[SDLK_RSHIFT] = KEY_SHIFT;
|
|
mTranslateKeyMap[SDLK_LCTRL] = KEY_CONTROL;
|
|
mTranslateKeyMap[SDLK_RCTRL] = KEY_CONTROL;
|
|
mTranslateKeyMap[SDLK_LALT] = KEY_ALT;
|
|
mTranslateKeyMap[SDLK_RALT] = KEY_ALT;
|
|
mTranslateKeyMap[SDLK_HOME] = KEY_HOME;
|
|
mTranslateKeyMap[SDLK_END] = KEY_END;
|
|
mTranslateKeyMap[SDLK_PAGEUP] = KEY_PAGE_UP;
|
|
mTranslateKeyMap[SDLK_PAGEDOWN] = KEY_PAGE_DOWN;
|
|
mTranslateKeyMap[SDLK_MINUS] = KEY_HYPHEN;
|
|
mTranslateKeyMap[SDLK_EQUALS] = KEY_EQUALS;
|
|
mTranslateKeyMap[SDLK_KP_EQUALS] = KEY_EQUALS;
|
|
mTranslateKeyMap[SDLK_INSERT] = KEY_INSERT;
|
|
mTranslateKeyMap[SDLK_CAPSLOCK] = KEY_CAPSLOCK;
|
|
mTranslateKeyMap[SDLK_TAB] = KEY_TAB;
|
|
mTranslateKeyMap[SDLK_KP_PLUS] = KEY_ADD;
|
|
mTranslateKeyMap[SDLK_KP_MINUS] = KEY_SUBTRACT;
|
|
mTranslateKeyMap[SDLK_KP_MULTIPLY] = KEY_MULTIPLY;
|
|
mTranslateKeyMap[SDLK_KP_DIVIDE] = KEY_PAD_DIVIDE;
|
|
mTranslateKeyMap[SDLK_F1] = KEY_F1;
|
|
mTranslateKeyMap[SDLK_F2] = KEY_F2;
|
|
mTranslateKeyMap[SDLK_F3] = KEY_F3;
|
|
mTranslateKeyMap[SDLK_F4] = KEY_F4;
|
|
mTranslateKeyMap[SDLK_F5] = KEY_F5;
|
|
mTranslateKeyMap[SDLK_F6] = KEY_F6;
|
|
mTranslateKeyMap[SDLK_F7] = KEY_F7;
|
|
mTranslateKeyMap[SDLK_F8] = KEY_F8;
|
|
mTranslateKeyMap[SDLK_F9] = KEY_F9;
|
|
mTranslateKeyMap[SDLK_F10] = KEY_F10;
|
|
mTranslateKeyMap[SDLK_F11] = KEY_F11;
|
|
mTranslateKeyMap[SDLK_F12] = KEY_F12;
|
|
mTranslateKeyMap[SDLK_PLUS] = '=';
|
|
mTranslateKeyMap[SDLK_COMMA] = ',';
|
|
mTranslateKeyMap[SDLK_MINUS] = '-';
|
|
mTranslateKeyMap[SDLK_PERIOD] = '.';
|
|
mTranslateKeyMap[SDLK_BACKQUOTE] = '`';
|
|
mTranslateKeyMap[SDLK_SLASH] = KEY_DIVIDE;
|
|
mTranslateKeyMap[SDLK_SEMICOLON] = ';';
|
|
mTranslateKeyMap[SDLK_LEFTBRACKET] = '[';
|
|
mTranslateKeyMap[SDLK_BACKSLASH] = '\\';
|
|
mTranslateKeyMap[SDLK_RIGHTBRACKET] = ']';
|
|
mTranslateKeyMap[SDLK_QUOTE] = '\'';
|
|
|
|
// Build inverse map
|
|
std::map<U16, KEY>::iterator iter;
|
|
for (iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++)
|
|
{
|
|
mInvTranslateKeyMap[iter->second] = iter->first;
|
|
}
|
|
|
|
// numpad map
|
|
mTranslateNumpadMap[SDLK_KP0] = KEY_PAD_INS;
|
|
mTranslateNumpadMap[SDLK_KP1] = KEY_PAD_END;
|
|
mTranslateNumpadMap[SDLK_KP2] = KEY_PAD_DOWN;
|
|
mTranslateNumpadMap[SDLK_KP3] = KEY_PAD_PGDN;
|
|
mTranslateNumpadMap[SDLK_KP4] = KEY_PAD_LEFT;
|
|
mTranslateNumpadMap[SDLK_KP5] = KEY_PAD_CENTER;
|
|
mTranslateNumpadMap[SDLK_KP6] = KEY_PAD_RIGHT;
|
|
mTranslateNumpadMap[SDLK_KP7] = KEY_PAD_HOME;
|
|
mTranslateNumpadMap[SDLK_KP8] = KEY_PAD_UP;
|
|
mTranslateNumpadMap[SDLK_KP9] = KEY_PAD_PGUP;
|
|
mTranslateNumpadMap[SDLK_KP_PERIOD] = KEY_PAD_DEL;
|
|
|
|
// build inverse numpad map
|
|
for (iter = mTranslateNumpadMap.begin();
|
|
iter != mTranslateNumpadMap.end();
|
|
iter++)
|
|
{
|
|
mInvTranslateNumpadMap[iter->second] = iter->first;
|
|
}
|
|
}
|
|
|
|
void LLKeyboardSDL::resetMaskKeys()
|
|
{
|
|
SDLMod mask = SDL_GetModState();
|
|
|
|
// MBW -- XXX -- This mirrors the operation of the Windows version of resetMaskKeys().
|
|
// It looks a bit suspicious, as it won't correct for keys that have been released.
|
|
// Is this the way it's supposed to work?
|
|
|
|
if(mask & KMOD_SHIFT)
|
|
{
|
|
mKeyLevel[KEY_SHIFT] = TRUE;
|
|
}
|
|
|
|
if(mask & KMOD_CTRL)
|
|
{
|
|
mKeyLevel[KEY_CONTROL] = TRUE;
|
|
}
|
|
|
|
if(mask & KMOD_ALT)
|
|
{
|
|
mKeyLevel[KEY_ALT] = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
MASK LLKeyboardSDL::updateModifiers(const U32 mask)
|
|
{
|
|
// translate the mask
|
|
MASK out_mask = MASK_NONE;
|
|
|
|
if(mask & KMOD_SHIFT)
|
|
{
|
|
out_mask |= MASK_SHIFT;
|
|
}
|
|
|
|
if(mask & KMOD_CTRL)
|
|
{
|
|
out_mask |= MASK_CONTROL;
|
|
}
|
|
|
|
if(mask & KMOD_ALT)
|
|
{
|
|
out_mask |= MASK_ALT;
|
|
}
|
|
|
|
return out_mask;
|
|
}
|
|
|
|
|
|
static U16 adjustNativekeyFromUnhandledMask(const U16 key, const U32 mask)
|
|
{
|
|
// SDL doesn't automatically adjust the keysym according to
|
|
// whether NUMLOCK is engaged, so we massage the keysym manually.
|
|
U16 rtn = key;
|
|
if (!(mask & KMOD_NUM))
|
|
{
|
|
switch (key)
|
|
{
|
|
case SDLK_KP_PERIOD: rtn = SDLK_DELETE; break;
|
|
case SDLK_KP0: rtn = SDLK_INSERT; break;
|
|
case SDLK_KP1: rtn = SDLK_END; break;
|
|
case SDLK_KP2: rtn = SDLK_DOWN; break;
|
|
case SDLK_KP3: rtn = SDLK_PAGEDOWN; break;
|
|
case SDLK_KP4: rtn = SDLK_LEFT; break;
|
|
case SDLK_KP6: rtn = SDLK_RIGHT; break;
|
|
case SDLK_KP7: rtn = SDLK_HOME; break;
|
|
case SDLK_KP8: rtn = SDLK_UP; break;
|
|
case SDLK_KP9: rtn = SDLK_PAGEUP; break;
|
|
}
|
|
}
|
|
return rtn;
|
|
}
|
|
|
|
|
|
BOOL LLKeyboardSDL::handleKeyDown(const U16 key, const U32 mask)
|
|
{
|
|
U16 adjusted_nativekey;
|
|
KEY translated_key = 0;
|
|
U32 translated_mask = MASK_NONE;
|
|
BOOL handled = FALSE;
|
|
|
|
adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
|
|
|
|
translated_mask = updateModifiers(mask);
|
|
|
|
if(translateNumpadKey(adjusted_nativekey, &translated_key))
|
|
{
|
|
handled = handleTranslatedKeyDown(translated_key, translated_mask);
|
|
}
|
|
|
|
return handled;
|
|
}
|
|
|
|
|
|
BOOL LLKeyboardSDL::handleKeyUp(const U16 key, const U32 mask)
|
|
{
|
|
U16 adjusted_nativekey;
|
|
KEY translated_key = 0;
|
|
U32 translated_mask = MASK_NONE;
|
|
BOOL handled = FALSE;
|
|
|
|
adjusted_nativekey = adjustNativekeyFromUnhandledMask(key, mask);
|
|
|
|
translated_mask = updateModifiers(mask);
|
|
|
|
if(translateNumpadKey(adjusted_nativekey, &translated_key))
|
|
{
|
|
handled = handleTranslatedKeyUp(translated_key, translated_mask);
|
|
}
|
|
|
|
return handled;
|
|
}
|
|
|
|
MASK LLKeyboardSDL::currentMask(BOOL for_mouse_event)
|
|
{
|
|
MASK result = MASK_NONE;
|
|
SDLMod mask = SDL_GetModState();
|
|
|
|
if (mask & KMOD_SHIFT) result |= MASK_SHIFT;
|
|
if (mask & KMOD_CTRL) result |= MASK_CONTROL;
|
|
if (mask & KMOD_ALT) result |= MASK_ALT;
|
|
|
|
// For keyboard events, consider Meta keys equivalent to Control
|
|
if (!for_mouse_event)
|
|
{
|
|
if (mask & KMOD_META) result |= MASK_CONTROL;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void LLKeyboardSDL::scanKeyboard()
|
|
{
|
|
for (S32 key = 0; key < KEY_COUNT; key++)
|
|
{
|
|
// Generate callback if any event has occurred on this key this frame.
|
|
// Can't just test mKeyLevel, because this could be a slow frame and
|
|
// key might have gone down then up. JC
|
|
if (mKeyLevel[key] || mKeyDown[key] || mKeyUp[key])
|
|
{
|
|
mCurScanKey = key;
|
|
mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]);
|
|
}
|
|
}
|
|
|
|
// Reset edges for next frame
|
|
for (S32 key = 0; key < KEY_COUNT; key++)
|
|
{
|
|
mKeyUp[key] = FALSE;
|
|
mKeyDown[key] = FALSE;
|
|
if (mKeyLevel[key])
|
|
{
|
|
mKeyLevelFrameCount[key]++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
BOOL LLKeyboardSDL::translateNumpadKey( const U16 os_key, KEY *translated_key)
|
|
{
|
|
if(mNumpadDistinct == ND_NUMLOCK_ON)
|
|
{
|
|
std::map<U16, KEY>::iterator iter= mTranslateNumpadMap.find(os_key);
|
|
if(iter != mTranslateNumpadMap.end())
|
|
{
|
|
*translated_key = iter->second;
|
|
return TRUE;
|
|
}
|
|
}
|
|
BOOL success = translateKey(os_key, translated_key);
|
|
return success;
|
|
}
|
|
|
|
U16 LLKeyboardSDL::inverseTranslateNumpadKey(const KEY translated_key)
|
|
{
|
|
if(mNumpadDistinct == ND_NUMLOCK_ON)
|
|
{
|
|
std::map<KEY, U16>::iterator iter= mInvTranslateNumpadMap.find(translated_key);
|
|
if(iter != mInvTranslateNumpadMap.end())
|
|
{
|
|
return iter->second;
|
|
}
|
|
}
|
|
return inverseTranslateKey(translated_key);
|
|
}
|
|
|
|
#endif
|
|
|