123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- /**
- * @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_LINUX
- #include "linden_common.h"
- #include "SDL2/SDL.h"
- #include "SDL2/SDL_keycode.h"
- #include "llkeyboardsdl.h"
- #include "llwindow.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...
- U32 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;
- }
- 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_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;
- // Build inverse map
- std::map<U32, KEY>::iterator iter;
- for (iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++)
- {
- mInvTranslateKeyMap[iter->second] = iter->first;
- }
- // Numpad map
- mTranslateNumpadMap[SDLK_KP_0] = KEY_PAD_INS;
- mTranslateNumpadMap[SDLK_KP_1] = KEY_PAD_END;
- mTranslateNumpadMap[SDLK_KP_2] = KEY_PAD_DOWN;
- mTranslateNumpadMap[SDLK_KP_3] = KEY_PAD_PGDN;
- mTranslateNumpadMap[SDLK_KP_4] = KEY_PAD_LEFT;
- mTranslateNumpadMap[SDLK_KP_5] = KEY_PAD_CENTER;
- mTranslateNumpadMap[SDLK_KP_6] = KEY_PAD_RIGHT;
- mTranslateNumpadMap[SDLK_KP_7] = KEY_PAD_HOME;
- mTranslateNumpadMap[SDLK_KP_8] = KEY_PAD_UP;
- mTranslateNumpadMap[SDLK_KP_9] = 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;
- }
- }
- // This mirrors the operation of the Windows version of resetMaskKeys(). It
- // looks a quite bit suspicious, as it would not correct for keys that have
- // been released. Is this the way it is supposed to work ?
- //virtual
- void LLKeyboardSDL::resetMaskKeys()
- {
- SDL_Keymod mask = SDL_GetModState();
- if (mask & KMOD_SHIFT)
- {
- mKeyLevel[KEY_SHIFT] = true;
- }
- else
- {
- mKeyLevel[KEY_SHIFT] = false;
- }
- if (mask & KMOD_CTRL)
- {
- mKeyLevel[KEY_CONTROL] = true;
- }
- if (mask & KMOD_ALT)
- {
- mKeyLevel[KEY_ALT] = true;
- }
- }
- MASK LLKeyboardSDL::updateModifiers(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;
- }
- // Used at the login screen, for warning about caps lock on in password
- // field. HB
- if (mask & KMOD_CAPS)
- {
- mKeyLevel[KEY_CAPSLOCK] = true;
- }
- else
- {
- mKeyLevel[KEY_CAPSLOCK] = false;
- }
- return out_mask;
- }
- static U32 adjustNativekeyFromUnhandledMask(U32 key, U32 mask)
- {
- // SDL does not automatically adjust the keysym according to whether
- // NUMLOCK is engaged, so we manage the keysym manually.
- // Also translate numeric and operator pad keys into normal numeric and
- // character keys (especially useful in menu accelerators for AZERTY
- // keyboards where numeric keys are SHIFTed keys)
- U32 rtn = key;
- if (mask & KMOD_NUM)
- {
- switch (key)
- {
- case SDLK_KP_DIVIDE: rtn = SDLK_SLASH; break;
- case SDLK_KP_MULTIPLY: rtn = SDLK_ASTERISK; break;
- case SDLK_KP_MINUS: rtn = SDLK_MINUS; break;
- case SDLK_KP_PLUS: rtn = SDLK_PLUS; break;
- case SDLK_KP_EQUALS: rtn = SDLK_EQUALS; break;
- case SDLK_KP_0: rtn = SDLK_0; break;
- case SDLK_KP_1: rtn = SDLK_1; break;
- case SDLK_KP_2: rtn = SDLK_2; break;
- case SDLK_KP_3: rtn = SDLK_3; break;
- case SDLK_KP_4: rtn = SDLK_4; break;
- case SDLK_KP_5: rtn = SDLK_5; break;
- case SDLK_KP_6: rtn = SDLK_6; break;
- case SDLK_KP_7: rtn = SDLK_7; break;
- case SDLK_KP_8: rtn = SDLK_8; break;
- case SDLK_KP_9: rtn = SDLK_9;
- }
- }
- else
- {
- switch (key)
- {
- case SDLK_KP_DIVIDE: rtn = SDLK_SLASH; break;
- case SDLK_KP_MULTIPLY: rtn = SDLK_ASTERISK; break;
- case SDLK_KP_MINUS: rtn = SDLK_MINUS; break;
- case SDLK_KP_PLUS: rtn = SDLK_PLUS; break;
- case SDLK_KP_EQUALS: rtn = SDLK_EQUALS; break;
- case SDLK_KP_PERIOD: rtn = SDLK_DELETE; break;
- case SDLK_KP_0: rtn = SDLK_INSERT; break;
- case SDLK_KP_1: rtn = SDLK_END; break;
- case SDLK_KP_2: rtn = SDLK_DOWN; break;
- case SDLK_KP_3: rtn = SDLK_PAGEDOWN; break;
- case SDLK_KP_4: rtn = SDLK_LEFT; break;
- case SDLK_KP_6: rtn = SDLK_RIGHT; break;
- case SDLK_KP_7: rtn = SDLK_HOME; break;
- case SDLK_KP_8: rtn = SDLK_UP; break;
- case SDLK_KP_9: rtn = SDLK_PAGEUP;
- }
- }
- return rtn;
- }
- //virtual
- bool LLKeyboardSDL::handleKeyDown(U32 key, U32 mask)
- {
- U32 translated_code = adjustNativekeyFromUnhandledMask(key, mask);
- U32 translated_mask = updateModifiers(mask);
- LL_DEBUGS("KeyCodes") << "Key code: " << std::hex << key
- << " - Mask: "<< mask
- << " Translated code: " << translated_code
- << " Translated mask: " << translated_mask
- << std::dec << LL_ENDL;
- KEY translated_key = 0;
- if (translateNumpadKey(translated_code, &translated_key, translated_mask))
- {
- return handleTranslatedKeyDown(translated_key, translated_mask);
- }
- return false;
- }
- //virtual
- bool LLKeyboardSDL::handleKeyUp(U32 key, U32 mask)
- {
- U32 translated_code = adjustNativekeyFromUnhandledMask(key, mask);
- U32 translated_mask = updateModifiers(mask);
- KEY translated_key = 0;
- if (translateNumpadKey(translated_code, &translated_key, translated_mask))
- {
- return handleTranslatedKeyUp(translated_key, translated_mask);
- }
- return false;
- }
- //virtual
- MASK LLKeyboardSDL::currentMask(bool for_mouse_event)
- {
- MASK result = MASK_NONE;
- SDL_Keymod 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 && (mask & KMOD_GUI))
- {
- result |= MASK_CONTROL;
- }
- return result;
- }
- //virtual
- 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(U32 os_key, KEY* translated_key,
- MASK mask)
- {
- if (mNumpadDistinct == ND_NUMLOCK_ON)
- {
- std::map<U32, KEY>::iterator iter= mTranslateNumpadMap.find(os_key);
- if (iter != mTranslateNumpadMap.end())
- {
- *translated_key = iter->second;
- return true;
- }
- }
- return translateKey(os_key, translated_key, mask);
- }
- U32 LLKeyboardSDL::inverseTranslateNumpadKey(KEY translated_key)
- {
- if (mNumpadDistinct == ND_NUMLOCK_ON)
- {
- std::map<KEY, U32>::iterator iter= mInvTranslateNumpadMap.find(translated_key);
- if (iter != mInvTranslateNumpadMap.end())
- {
- return iter->second;
- }
- }
- return inverseTranslateKey(translated_key);
- }
- #endif // LL_LINUX
|