Browse Source

Added love.keyboard.getKeyFromScancode and love.keyboard.getScancodeFromKey. Resolves issue #982.

Scancodes represent a physical key independent of the keyboard's current layout. For example, pressing the key located where 'q' is on a U.S. keyboard will produce the key 'q' and the scancode 'q' when using a U.S. keyboard layout, but when using a French keyboard layout it will produce the key 'a' and the scancode 'q'.

Scancodes are useful for creating default controls that have the same physical locations on on all keyboards.
Alex Szpakowski 10 years ago
parent
commit
a314b18515

+ 277 - 2
src/modules/keyboard/Keyboard.cpp

@@ -27,18 +27,30 @@ namespace love
 namespace keyboard
 {
 
-bool Keyboard::getConstant(const char *in, Keyboard::Key &out)
+bool Keyboard::getConstant(const char *in, Key &out)
 {
 	return keys.find(in, out);
 }
 
-bool Keyboard::getConstant(Keyboard::Key in, const char  *&out)
+bool Keyboard::getConstant(Key in, const char *&out)
 {
 	return keys.find(in, out);
 }
 
+bool Keyboard::getConstant(const char *in, Scancode &out)
+{
+	return scancodes.find(in, out);
+}
+
+bool Keyboard::getConstant(Scancode in, const char *&out)
+{
+	return scancodes.find(in, out);
+}
+
 StringMap<Keyboard::Key, Keyboard::KEY_MAX_ENUM>::Entry Keyboard::keyEntries[] =
 {
+	{"unknown", Keyboard::KEY_UNKNOWN},
+
 	{"return", Keyboard::KEY_RETURN},
 	{"escape", Keyboard::KEY_ESCAPE},
 	{"backspace", Keyboard::KEY_BACKSPACE},
@@ -244,6 +256,269 @@ StringMap<Keyboard::Key, Keyboard::KEY_MAX_ENUM>::Entry Keyboard::keyEntries[] =
 
 StringMap<Keyboard::Key, Keyboard::KEY_MAX_ENUM> Keyboard::keys(Keyboard::keyEntries, sizeof(Keyboard::keyEntries));
 
+StringMap<Keyboard::Scancode, Keyboard::SCANCODE_MAX_ENUM>::Entry Keyboard::scancodeEntries[] =
+{
+	{"unknown", SCANCODE_UNKNOWN},
+
+	{"a", SCANCODE_A},
+	{"b", SCANCODE_B},
+	{"c", SCANCODE_C},
+	{"d", SCANCODE_D},
+	{"e", SCANCODE_E},
+	{"f", SCANCODE_F},
+	{"g", SCANCODE_G},
+	{"h", SCANCODE_H},
+	{"i", SCANCODE_I},
+	{"j", SCANCODE_J},
+	{"k", SCANCODE_K},
+	{"l", SCANCODE_L},
+	{"m", SCANCODE_M},
+	{"n", SCANCODE_N},
+	{"o", SCANCODE_O},
+	{"p", SCANCODE_P},
+	{"q", SCANCODE_Q},
+	{"r", SCANCODE_R},
+	{"s", SCANCODE_S},
+	{"t", SCANCODE_T},
+	{"u", SCANCODE_U},
+	{"v", SCANCODE_V},
+	{"w", SCANCODE_W},
+	{"x", SCANCODE_X},
+	{"y", SCANCODE_Y},
+	{"z", SCANCODE_Z},
+
+	{"1", SCANCODE_1},
+	{"2", SCANCODE_2},
+	{"3", SCANCODE_3},
+	{"4", SCANCODE_4},
+	{"5", SCANCODE_5},
+	{"6", SCANCODE_6},
+	{"7", SCANCODE_7},
+	{"8", SCANCODE_8},
+	{"9", SCANCODE_9},
+	{"0", SCANCODE_0},
+
+	{"return", SCANCODE_RETURN},
+	{"escape", SCANCODE_ESCAPE},
+	{"backspace", SCANCODE_BACKSPACE},
+	{"tab", SCANCODE_TAB},
+	{" ", SCANCODE_SPACE},
+
+	{"-", SCANCODE_MINUS},
+	{"=", SCANCODE_EQUALS},
+	{"[", SCANCODE_LEFTBRACKET},
+	{"]", SCANCODE_RIGHTBRACKET},
+	{"\\", SCANCODE_BACKSLASH},
+	{"nonus#", SCANCODE_NONUSHASH},
+	{";", SCANCODE_SEMICOLON},
+	{"'", SCANCODE_APOSTROPHE},
+	{"`", SCANCODE_GRAVE},
+	{",", SCANCODE_COMMA},
+	{".", SCANCODE_PERIOD},
+	{"/", SCANCODE_SLASH},
+
+	{"capslock", SCANCODE_CAPSLOCK},
+
+	{"f1", SCANCODE_F1},
+	{"f2", SCANCODE_F2},
+	{"f3", SCANCODE_F3},
+	{"f4", SCANCODE_F4},
+	{"f5", SCANCODE_F5},
+	{"f6", SCANCODE_F6},
+	{"f7", SCANCODE_F7},
+	{"f8", SCANCODE_F8},
+	{"f9", SCANCODE_F9},
+	{"f10", SCANCODE_F10},
+	{"f11", SCANCODE_F11},
+	{"f12", SCANCODE_F12},
+
+	{"printscreen", SCANCODE_PRINTSCREEN},
+	{"scrolllock", SCANCODE_SCROLLLOCK},
+	{"pause", SCANCODE_PAUSE},
+	{"insert", SCANCODE_INSERT},
+	{"home", SCANCODE_HOME},
+	{"pageup", SCANCODE_PAGEUP},
+	{"delete", SCANCODE_DELETE},
+	{"end", SCANCODE_END},
+	{"pagedown", SCANCODE_PAGEDOWN},
+	{"right", SCANCODE_RIGHT},
+	{"left", SCANCODE_LEFT},
+	{"down", SCANCODE_DOWN},
+	{"up", SCANCODE_UP},
+
+	{"numlock", SCANCODE_NUMLOCKCLEAR},
+	{"kp/", SCANCODE_KP_DIVIDE},
+	{"kp*", SCANCODE_KP_MULTIPLY},
+	{"kp-", SCANCODE_KP_MINUS},
+	{"kp+", SCANCODE_KP_PLUS},
+	{"kpenter", SCANCODE_KP_ENTER},
+	{"kp1", SCANCODE_KP_1},
+	{"kp2", SCANCODE_KP_2},
+	{"kp3", SCANCODE_KP_3},
+	{"kp4", SCANCODE_KP_4},
+	{"kp5", SCANCODE_KP_5},
+	{"kp6", SCANCODE_KP_6},
+	{"kp7", SCANCODE_KP_7},
+	{"kp8", SCANCODE_KP_8},
+	{"kp9", SCANCODE_KP_9},
+	{"kp0", SCANCODE_KP_0},
+	{"kp.", SCANCODE_KP_PERIOD},
+
+	{"nonusbackslash", SCANCODE_NONUSBACKSLASH},
+	{"application", SCANCODE_APPLICATION},
+	{"power", SCANCODE_POWER},
+	{"=", SCANCODE_KP_EQUALS},
+	{"f13", SCANCODE_F13},
+	{"f14", SCANCODE_F14},
+	{"f15", SCANCODE_F15},
+	{"f16", SCANCODE_F16},
+	{"f17", SCANCODE_F17},
+	{"f18", SCANCODE_F18},
+	{"f19", SCANCODE_F19},
+	{"f20", SCANCODE_F20},
+	{"f21", SCANCODE_F21},
+	{"f22", SCANCODE_F22},
+	{"f23", SCANCODE_F23},
+	{"f24", SCANCODE_F24},
+	{"execute", SCANCODE_EXECUTE},
+	{"help", SCANCODE_HELP},
+	{"menu", SCANCODE_MENU},
+	{"select", SCANCODE_SELECT},
+	{"stop", SCANCODE_STOP},
+	{"again", SCANCODE_AGAIN},
+	{"undo", SCANCODE_UNDO},
+	{"cut", SCANCODE_CUT},
+	{"copy", SCANCODE_COPY},
+	{"paste", SCANCODE_PASTE},
+	{"find", SCANCODE_FIND},
+	{"mute", SCANCODE_MUTE},
+	{"volumeup", SCANCODE_VOLUMEUP},
+	{"volumedown", SCANCODE_VOLUMEDOWN},
+	{"kp,", SCANCODE_KP_COMMA},
+	{"kp=400", SCANCODE_KP_EQUALSAS400},
+
+	{"international1", SCANCODE_INTERNATIONAL1},
+	{"international2", SCANCODE_INTERNATIONAL2},
+	{"international3", SCANCODE_INTERNATIONAL3},
+	{"international4", SCANCODE_INTERNATIONAL4},
+	{"international5", SCANCODE_INTERNATIONAL5},
+	{"international6", SCANCODE_INTERNATIONAL6},
+	{"international7", SCANCODE_INTERNATIONAL7},
+	{"international8", SCANCODE_INTERNATIONAL8},
+	{"international9", SCANCODE_INTERNATIONAL9},
+	{"lang1", SCANCODE_LANG1},
+	{"lang2", SCANCODE_LANG2},
+	{"lang3", SCANCODE_LANG3},
+	{"lang4", SCANCODE_LANG4},
+	{"lang5", SCANCODE_LANG5},
+	{"lang6", SCANCODE_LANG6},
+	{"lang7", SCANCODE_LANG7},
+	{"lang8", SCANCODE_LANG8},
+	{"lang9", SCANCODE_LANG9},
+
+	{"alterase", SCANCODE_ALTERASE},
+	{"sysreq", SCANCODE_SYSREQ},
+	{"cancel", SCANCODE_CANCEL},
+	{"clear", SCANCODE_CLEAR},
+	{"prior", SCANCODE_PRIOR},
+	{"return2", SCANCODE_RETURN2},
+	{"separator", SCANCODE_SEPARATOR},
+	{"out", SCANCODE_OUT},
+	{"oper", SCANCODE_OPER},
+	{"clearagain", SCANCODE_CLEARAGAIN},
+	{"crsel", SCANCODE_CRSEL},
+	{"exsel", SCANCODE_EXSEL},
+
+	{"kp00", SCANCODE_KP_00},
+	{"kp000", SCANCODE_KP_000},
+	{"thsousandsseparator", SCANCODE_THOUSANDSSEPARATOR},
+	{"decimalseparator", SCANCODE_DECIMALSEPARATOR},
+	{"currencyunit", SCANCODE_CURRENCYUNIT},
+	{"currencysubunit", SCANCODE_CURRENCYSUBUNIT},
+	{"kp(", SCANCODE_KP_LEFTPAREN},
+	{"kp)", SCANCODE_KP_RIGHTPAREN},
+	{"kp{", SCANCODE_KP_LEFTBRACE},
+	{"kp}", SCANCODE_KP_RIGHTBRACE},
+	{"kptab", SCANCODE_KP_TAB},
+	{"kpbackspace", SCANCODE_KP_BACKSPACE},
+	{"kpa", SCANCODE_KP_A},
+	{"kpb", SCANCODE_KP_B},
+	{"kpc", SCANCODE_KP_C},
+	{"kpd", SCANCODE_KP_D},
+	{"kpe", SCANCODE_KP_E},
+	{"kpf", SCANCODE_KP_F},
+	{"kpxor", SCANCODE_KP_XOR},
+	{"kpower", SCANCODE_KP_POWER},
+	{"kp%", SCANCODE_KP_PERCENT},
+	{"kp<", SCANCODE_KP_LESS},
+	{"kp>", SCANCODE_KP_GREATER},
+	{"kp&", SCANCODE_KP_AMPERSAND},
+	{"kp&&", SCANCODE_KP_DBLAMPERSAND},
+	{"kp|", SCANCODE_KP_VERTICALBAR},
+	{"kp||", SCANCODE_KP_DBLVERTICALBAR},
+	{"kp:", SCANCODE_KP_COLON},
+	{"kp#", SCANCODE_KP_HASH},
+	{"kp ", SCANCODE_KP_SPACE},
+	{"kp@", SCANCODE_KP_AT},
+	{"kp!", SCANCODE_KP_EXCLAM},
+	{"kpmemstore", SCANCODE_KP_MEMSTORE},
+	{"kpmemrecall", SCANCODE_KP_MEMRECALL},
+	{"kpmemclear", SCANCODE_KP_MEMCLEAR},
+	{"kpmem+", SCANCODE_KP_MEMADD},
+	{"kpmem-", SCANCODE_KP_MEMSUBTRACT},
+	{"kpmem*", SCANCODE_KP_MEMMULTIPLY},
+	{"kpmem/", SCANCODE_KP_MEMDIVIDE},
+	{"kp+-", SCANCODE_KP_PLUSMINUS},
+	{"kpclear", SCANCODE_KP_CLEAR},
+	{"kpclearentry", SCANCODE_KP_CLEARENTRY},
+	{"kpbinary", SCANCODE_KP_BINARY},
+	{"kpoctal", SCANCODE_KP_OCTAL},
+	{"kpdecimal", SCANCODE_KP_DECIMAL},
+	{"kphex", SCANCODE_KP_HEXADECIMAL},
+
+	{"lctrl", SCANCODE_LCTRL},
+	{"lshift", SCANCODE_LSHIFT},
+	{"lalt", SCANCODE_LALT},
+	{"lgui", SCANCODE_LGUI},
+	{"rctrl", SCANCODE_RCTRL},
+	{"rshift", SCANCODE_RSHIFT},
+	{"ralt", SCANCODE_RALT},
+	{"rgui", SCANCODE_RGUI},
+
+	{"mode", SCANCODE_MODE},
+
+	{"audionext", SCANCODE_AUDIONEXT},
+	{"audioprev", SCANCODE_AUDIOPREV},
+	{"audiostop", SCANCODE_AUDIOSTOP},
+	{"audioplay", SCANCODE_AUDIOPLAY},
+	{"audiomute", SCANCODE_AUDIOMUTE},
+	{"mediaselect", SCANCODE_MEDIASELECT},
+	{"www", SCANCODE_WWW},
+	{"mail", SCANCODE_MAIL},
+	{"calculator", SCANCODE_CALCULATOR},
+	{"computer", SCANCODE_COMPUTER},
+	{"acsearch", SCANCODE_AC_SEARCH},
+	{"achome", SCANCODE_AC_HOME},
+	{"acback", SCANCODE_AC_BACK},
+	{"acforward", SCANCODE_AC_FORWARD},
+	{"acstop", SCANCODE_AC_STOP},
+	{"acrefresh", SCANCODE_AC_REFRESH},
+	{"acbookmarks", SCANCODE_AC_BOOKMARKS},
+
+	{"brightnessdown", SCANCODE_BRIGHTNESSDOWN},
+	{"brightnessup", SCANCODE_BRIGHTNESSUP},
+	{"displayswitch", SCANCODE_DISPLAYSWITCH},
+	{"kbdillumtoggle", SCANCODE_KBDILLUMTOGGLE},
+	{"kbdillumdown", SCANCODE_KBDILLUMDOWN},
+	{"kbdillumup", SCANCODE_KBDILLUMUP},
+	{"eject", SCANCODE_EJECT},
+	{"sleep", SCANCODE_SLEEP},
+	
+	{"app1", SCANCODE_APP1},
+	{"app2", SCANCODE_APP2},
+};
+
+StringMap<Keyboard::Scancode, Keyboard::SCANCODE_MAX_ENUM> Keyboard::scancodes(Keyboard::scancodeEntries, sizeof(Keyboard::scancodeEntries));
 
 } // keyboard
 } // love

+ 291 - 1
src/modules/keyboard/Keyboard.h

@@ -34,6 +34,9 @@ class Keyboard : public Module
 {
 public:
 
+	/**
+	 * Keyboard keys. They are dependent on the current layout of the keyboard.
+	 **/
 	enum Key
 	{
 		KEY_UNKNOWN,
@@ -244,6 +247,275 @@ public:
 		KEY_MAX_ENUM
 	};
 
+	/**
+	 * Scancodes represent physical keys independent of the current layout.
+	 * Their names may not match the names of the keys printed on the keyboard.
+	 * Some of them are very esoteric...
+	 **/
+	enum Scancode
+	{
+		SCANCODE_UNKNOWN,
+
+		SCANCODE_A,
+		SCANCODE_B,
+		SCANCODE_C,
+		SCANCODE_D,
+		SCANCODE_E,
+		SCANCODE_F,
+		SCANCODE_G,
+		SCANCODE_H,
+		SCANCODE_I,
+		SCANCODE_J,
+		SCANCODE_K,
+		SCANCODE_L,
+		SCANCODE_M,
+		SCANCODE_N,
+		SCANCODE_O,
+		SCANCODE_P,
+		SCANCODE_Q,
+		SCANCODE_R,
+		SCANCODE_S,
+		SCANCODE_T,
+		SCANCODE_U,
+		SCANCODE_V,
+		SCANCODE_W,
+		SCANCODE_X,
+		SCANCODE_Y,
+		SCANCODE_Z,
+
+		SCANCODE_1,
+		SCANCODE_2,
+		SCANCODE_3,
+		SCANCODE_4,
+		SCANCODE_5,
+		SCANCODE_6,
+		SCANCODE_7,
+		SCANCODE_8,
+		SCANCODE_9,
+		SCANCODE_0,
+
+		SCANCODE_RETURN,
+		SCANCODE_ESCAPE,
+		SCANCODE_BACKSPACE,
+		SCANCODE_TAB,
+		SCANCODE_SPACE,
+
+		SCANCODE_MINUS,
+		SCANCODE_EQUALS,
+		SCANCODE_LEFTBRACKET,
+		SCANCODE_RIGHTBRACKET,
+		SCANCODE_BACKSLASH,
+		SCANCODE_NONUSHASH,
+		SCANCODE_SEMICOLON,
+		SCANCODE_APOSTROPHE,
+		SCANCODE_GRAVE,
+		SCANCODE_COMMA,
+		SCANCODE_PERIOD,
+		SCANCODE_SLASH,
+
+		SCANCODE_CAPSLOCK,
+
+		SCANCODE_F1,
+		SCANCODE_F2,
+		SCANCODE_F3,
+		SCANCODE_F4,
+		SCANCODE_F5,
+		SCANCODE_F6,
+		SCANCODE_F7,
+		SCANCODE_F8,
+		SCANCODE_F9,
+		SCANCODE_F10,
+		SCANCODE_F11,
+		SCANCODE_F12,
+
+		SCANCODE_PRINTSCREEN,
+		SCANCODE_SCROLLLOCK,
+		SCANCODE_PAUSE,
+		SCANCODE_INSERT,
+		SCANCODE_HOME,
+		SCANCODE_PAGEUP,
+		SCANCODE_DELETE,
+		SCANCODE_END,
+		SCANCODE_PAGEDOWN,
+		SCANCODE_RIGHT,
+		SCANCODE_LEFT,
+		SCANCODE_DOWN,
+		SCANCODE_UP,
+
+		SCANCODE_NUMLOCKCLEAR,
+		SCANCODE_KP_DIVIDE,
+		SCANCODE_KP_MULTIPLY,
+		SCANCODE_KP_MINUS,
+		SCANCODE_KP_PLUS,
+		SCANCODE_KP_ENTER,
+		SCANCODE_KP_1,
+		SCANCODE_KP_2,
+		SCANCODE_KP_3,
+		SCANCODE_KP_4,
+		SCANCODE_KP_5,
+		SCANCODE_KP_6,
+		SCANCODE_KP_7,
+		SCANCODE_KP_8,
+		SCANCODE_KP_9,
+		SCANCODE_KP_0,
+		SCANCODE_KP_PERIOD,
+
+		SCANCODE_NONUSBACKSLASH,
+		SCANCODE_APPLICATION,
+		SCANCODE_POWER,
+		SCANCODE_KP_EQUALS,
+		SCANCODE_F13,
+		SCANCODE_F14,
+		SCANCODE_F15,
+		SCANCODE_F16,
+		SCANCODE_F17,
+		SCANCODE_F18,
+		SCANCODE_F19,
+		SCANCODE_F20,
+		SCANCODE_F21,
+		SCANCODE_F22,
+		SCANCODE_F23,
+		SCANCODE_F24,
+		SCANCODE_EXECUTE,
+		SCANCODE_HELP,
+		SCANCODE_MENU,
+		SCANCODE_SELECT,
+		SCANCODE_STOP,
+		SCANCODE_AGAIN,
+		SCANCODE_UNDO,
+		SCANCODE_CUT,
+		SCANCODE_COPY,
+		SCANCODE_PASTE,
+		SCANCODE_FIND,
+		SCANCODE_MUTE,
+		SCANCODE_VOLUMEUP,
+		SCANCODE_VOLUMEDOWN,
+		SCANCODE_KP_COMMA,
+		SCANCODE_KP_EQUALSAS400,
+
+		SCANCODE_INTERNATIONAL1,
+		SCANCODE_INTERNATIONAL2,
+		SCANCODE_INTERNATIONAL3,
+		SCANCODE_INTERNATIONAL4,
+		SCANCODE_INTERNATIONAL5,
+		SCANCODE_INTERNATIONAL6,
+		SCANCODE_INTERNATIONAL7,
+		SCANCODE_INTERNATIONAL8,
+		SCANCODE_INTERNATIONAL9,
+		SCANCODE_LANG1,
+		SCANCODE_LANG2,
+		SCANCODE_LANG3,
+		SCANCODE_LANG4,
+		SCANCODE_LANG5,
+		SCANCODE_LANG6,
+		SCANCODE_LANG7,
+		SCANCODE_LANG8,
+		SCANCODE_LANG9,
+
+		SCANCODE_ALTERASE,
+		SCANCODE_SYSREQ,
+		SCANCODE_CANCEL,
+		SCANCODE_CLEAR,
+		SCANCODE_PRIOR,
+		SCANCODE_RETURN2,
+		SCANCODE_SEPARATOR,
+		SCANCODE_OUT,
+		SCANCODE_OPER,
+		SCANCODE_CLEARAGAIN,
+		SCANCODE_CRSEL,
+		SCANCODE_EXSEL,
+
+		SCANCODE_KP_00,
+		SCANCODE_KP_000,
+		SCANCODE_THOUSANDSSEPARATOR,
+		SCANCODE_DECIMALSEPARATOR,
+		SCANCODE_CURRENCYUNIT,
+		SCANCODE_CURRENCYSUBUNIT,
+		SCANCODE_KP_LEFTPAREN,
+		SCANCODE_KP_RIGHTPAREN,
+		SCANCODE_KP_LEFTBRACE,
+		SCANCODE_KP_RIGHTBRACE,
+		SCANCODE_KP_TAB,
+		SCANCODE_KP_BACKSPACE,
+		SCANCODE_KP_A,
+		SCANCODE_KP_B,
+		SCANCODE_KP_C,
+		SCANCODE_KP_D,
+		SCANCODE_KP_E,
+		SCANCODE_KP_F,
+		SCANCODE_KP_XOR,
+		SCANCODE_KP_POWER,
+		SCANCODE_KP_PERCENT,
+		SCANCODE_KP_LESS,
+		SCANCODE_KP_GREATER,
+		SCANCODE_KP_AMPERSAND,
+		SCANCODE_KP_DBLAMPERSAND,
+		SCANCODE_KP_VERTICALBAR,
+		SCANCODE_KP_DBLVERTICALBAR,
+		SCANCODE_KP_COLON,
+		SCANCODE_KP_HASH,
+		SCANCODE_KP_SPACE,
+		SCANCODE_KP_AT,
+		SCANCODE_KP_EXCLAM,
+		SCANCODE_KP_MEMSTORE,
+		SCANCODE_KP_MEMRECALL,
+		SCANCODE_KP_MEMCLEAR,
+		SCANCODE_KP_MEMADD,
+		SCANCODE_KP_MEMSUBTRACT,
+		SCANCODE_KP_MEMMULTIPLY,
+		SCANCODE_KP_MEMDIVIDE,
+		SCANCODE_KP_PLUSMINUS,
+		SCANCODE_KP_CLEAR,
+		SCANCODE_KP_CLEARENTRY,
+		SCANCODE_KP_BINARY,
+		SCANCODE_KP_OCTAL,
+		SCANCODE_KP_DECIMAL,
+		SCANCODE_KP_HEXADECIMAL,
+
+		SCANCODE_LCTRL,
+		SCANCODE_LSHIFT,
+		SCANCODE_LALT,
+		SCANCODE_LGUI,
+		SCANCODE_RCTRL,
+		SCANCODE_RSHIFT,
+		SCANCODE_RALT,
+		SCANCODE_RGUI,
+
+		SCANCODE_MODE,
+
+		SCANCODE_AUDIONEXT,
+		SCANCODE_AUDIOPREV,
+		SCANCODE_AUDIOSTOP,
+		SCANCODE_AUDIOPLAY,
+		SCANCODE_AUDIOMUTE,
+		SCANCODE_MEDIASELECT,
+		SCANCODE_WWW,
+		SCANCODE_MAIL,
+		SCANCODE_CALCULATOR,
+		SCANCODE_COMPUTER,
+		SCANCODE_AC_SEARCH,
+		SCANCODE_AC_HOME,
+		SCANCODE_AC_BACK,
+		SCANCODE_AC_FORWARD,
+		SCANCODE_AC_STOP,
+		SCANCODE_AC_REFRESH,
+		SCANCODE_AC_BOOKMARKS,
+		
+		SCANCODE_BRIGHTNESSDOWN,
+		SCANCODE_BRIGHTNESSUP,
+		SCANCODE_DISPLAYSWITCH,
+		SCANCODE_KBDILLUMTOGGLE,
+		SCANCODE_KBDILLUMDOWN,
+		SCANCODE_KBDILLUMUP,
+		SCANCODE_EJECT,
+		SCANCODE_SLEEP,
+		
+		SCANCODE_APP1,
+		SCANCODE_APP2,
+
+		SCANCODE_MAX_ENUM
+	};
+
 	virtual ~Keyboard() {}
 
 	// Implements Module.
@@ -268,6 +540,18 @@ public:
 	 **/
 	virtual bool isDown(Key *keylist) const = 0;
 
+	/**
+	 * Gets the key corresponding to the specified scancode according to the
+	 * current keyboard layout.
+	 **/
+	virtual Key getKeyFromScancode(Scancode scancode) const = 0;
+
+	/**
+	 * Gets the scancode corresponding to the specified key according to the
+	 * current keyboard layout.
+	 **/
+	virtual Scancode getScancodeFromKey(Key key) const = 0;
+
 	/**
 	 * Sets whether text input events should be sent
 	 * @param enable Whether to send text input events.
@@ -280,13 +564,19 @@ public:
 	virtual bool hasTextInput() const = 0;
 
 	static bool getConstant(const char *in, Key &out);
-	static bool getConstant(Key in, const char  *&out);
+	static bool getConstant(Key in, const char *&out);
+
+	static bool getConstant(const char *in, Scancode &out);
+	static bool getConstant(Scancode in, const char *&out);
 
 private:
 
 	static StringMap<Key, KEY_MAX_ENUM>::Entry keyEntries[];
 	static StringMap<Key, KEY_MAX_ENUM> keys;
 
+	static StringMap<Scancode, SCANCODE_MAX_ENUM>::Entry scancodeEntries[];
+	static StringMap<Scancode, SCANCODE_MAX_ENUM> scancodes;
+
 }; // Keyboard
 
 } // keyboard

+ 295 - 0
src/modules/keyboard/sdl/Keyboard.cpp

@@ -61,6 +61,37 @@ bool Keyboard::isDown(Key *keylist) const
 	return false;
 }
 
+Keyboard::Key Keyboard::getKeyFromScancode(Scancode scancode) const
+{
+	SDL_Scancode sdlscancode = SDL_SCANCODE_UNKNOWN;
+	scancodes.find(scancode, sdlscancode);
+
+	SDL_Keycode sdlkey = SDL_GetKeyFromScancode(sdlscancode);
+
+	for (int i = 0; i < KEY_MAX_ENUM; i++)
+	{
+		if (keymap[i] == sdlkey)
+			return (Key) i;
+	}
+
+	return KEY_UNKNOWN;
+}
+
+Keyboard::Scancode Keyboard::getScancodeFromKey(Key key) const
+{
+	Scancode scancode = SCANCODE_UNKNOWN;
+
+	if (key != KEY_MAX_ENUM)
+	{
+		SDL_Keycode sdlkey = keymap[key];
+
+		SDL_Scancode sdlscancode = SDL_GetScancodeFromKey(sdlkey);
+		scancodes.find(sdlscancode, scancode);
+	}
+
+	return scancode;
+}
+
 void Keyboard::setTextInput(bool enable)
 {
 	if (enable)
@@ -288,6 +319,270 @@ const SDL_Keycode *Keyboard::createKeyMap()
 
 const SDL_Keycode *Keyboard::keymap = Keyboard::createKeyMap();
 
+EnumMap<Keyboard::Scancode, SDL_Scancode, SDL_NUM_SCANCODES>::Entry Keyboard::scancodeEntries[] =
+{
+	{SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN},
+
+	{SCANCODE_A, SDL_SCANCODE_A},
+	{SCANCODE_B, SDL_SCANCODE_B},
+	{SCANCODE_C, SDL_SCANCODE_C},
+	{SCANCODE_D, SDL_SCANCODE_D},
+	{SCANCODE_E, SDL_SCANCODE_E},
+	{SCANCODE_F, SDL_SCANCODE_F},
+	{SCANCODE_G, SDL_SCANCODE_G},
+	{SCANCODE_H, SDL_SCANCODE_H},
+	{SCANCODE_I, SDL_SCANCODE_I},
+	{SCANCODE_J, SDL_SCANCODE_J},
+	{SCANCODE_K, SDL_SCANCODE_K},
+	{SCANCODE_L, SDL_SCANCODE_L},
+	{SCANCODE_M, SDL_SCANCODE_M},
+	{SCANCODE_N, SDL_SCANCODE_N},
+	{SCANCODE_O, SDL_SCANCODE_O},
+	{SCANCODE_P, SDL_SCANCODE_P},
+	{SCANCODE_Q, SDL_SCANCODE_Q},
+	{SCANCODE_R, SDL_SCANCODE_R},
+	{SCANCODE_S, SDL_SCANCODE_S},
+	{SCANCODE_T, SDL_SCANCODE_T},
+	{SCANCODE_U, SDL_SCANCODE_U},
+	{SCANCODE_V, SDL_SCANCODE_V},
+	{SCANCODE_W, SDL_SCANCODE_W},
+	{SCANCODE_X, SDL_SCANCODE_X},
+	{SCANCODE_Y, SDL_SCANCODE_Y},
+	{SCANCODE_Z, SDL_SCANCODE_Z},
+
+	{SCANCODE_1, SDL_SCANCODE_1},
+	{SCANCODE_2, SDL_SCANCODE_2},
+	{SCANCODE_3, SDL_SCANCODE_3},
+	{SCANCODE_4, SDL_SCANCODE_4},
+	{SCANCODE_5, SDL_SCANCODE_5},
+	{SCANCODE_6, SDL_SCANCODE_6},
+	{SCANCODE_7, SDL_SCANCODE_7},
+	{SCANCODE_8, SDL_SCANCODE_8},
+	{SCANCODE_9, SDL_SCANCODE_9},
+	{SCANCODE_0, SDL_SCANCODE_0},
+
+	{SCANCODE_RETURN, SDL_SCANCODE_RETURN},
+	{SCANCODE_ESCAPE, SDL_SCANCODE_ESCAPE},
+	{SCANCODE_BACKSPACE, SDL_SCANCODE_BACKSPACE},
+	{SCANCODE_TAB, SDL_SCANCODE_TAB},
+	{SCANCODE_SPACE, SDL_SCANCODE_SPACE},
+
+	{SCANCODE_MINUS, SDL_SCANCODE_MINUS},
+	{SCANCODE_EQUALS, SDL_SCANCODE_EQUALS},
+	{SCANCODE_LEFTBRACKET, SDL_SCANCODE_LEFTBRACKET},
+	{SCANCODE_RIGHTBRACKET, SDL_SCANCODE_RIGHTBRACKET},
+	{SCANCODE_BACKSLASH, SDL_SCANCODE_BACKSLASH},
+	{SCANCODE_NONUSHASH, SDL_SCANCODE_NONUSHASH},
+	{SCANCODE_SEMICOLON, SDL_SCANCODE_SEMICOLON},
+	{SCANCODE_APOSTROPHE, SDL_SCANCODE_APOSTROPHE},
+	{SCANCODE_GRAVE, SDL_SCANCODE_GRAVE},
+	{SCANCODE_COMMA, SDL_SCANCODE_COMMA},
+	{SCANCODE_PERIOD, SDL_SCANCODE_PERIOD},
+	{SCANCODE_SLASH, SDL_SCANCODE_SLASH},
+
+	{SCANCODE_CAPSLOCK, SDL_SCANCODE_CAPSLOCK},
+
+	{SCANCODE_F1, SDL_SCANCODE_F1},
+	{SCANCODE_F2, SDL_SCANCODE_F2},
+	{SCANCODE_F3, SDL_SCANCODE_F3},
+	{SCANCODE_F4, SDL_SCANCODE_F4},
+	{SCANCODE_F5, SDL_SCANCODE_F5},
+	{SCANCODE_F6, SDL_SCANCODE_F6},
+	{SCANCODE_F7, SDL_SCANCODE_F7},
+	{SCANCODE_F8, SDL_SCANCODE_F8},
+	{SCANCODE_F9, SDL_SCANCODE_F9},
+	{SCANCODE_F10, SDL_SCANCODE_F10},
+	{SCANCODE_F11, SDL_SCANCODE_F11},
+	{SCANCODE_F12, SDL_SCANCODE_F12},
+
+	{SCANCODE_PRINTSCREEN, SDL_SCANCODE_PRINTSCREEN},
+	{SCANCODE_SCROLLLOCK, SDL_SCANCODE_SCROLLLOCK},
+	{SCANCODE_PAUSE, SDL_SCANCODE_PAUSE},
+	{SCANCODE_INSERT, SDL_SCANCODE_INSERT},
+	{SCANCODE_HOME, SDL_SCANCODE_HOME},
+	{SCANCODE_PAGEUP, SDL_SCANCODE_PAGEUP},
+	{SCANCODE_DELETE, SDL_SCANCODE_DELETE},
+	{SCANCODE_END, SDL_SCANCODE_END},
+	{SCANCODE_PAGEDOWN, SDL_SCANCODE_PAGEDOWN},
+	{SCANCODE_RIGHT, SDL_SCANCODE_RIGHT},
+	{SCANCODE_LEFT, SDL_SCANCODE_LEFT},
+	{SCANCODE_DOWN, SDL_SCANCODE_DOWN},
+	{SCANCODE_UP, SDL_SCANCODE_UP},
+
+	{SCANCODE_NUMLOCKCLEAR, SDL_SCANCODE_NUMLOCKCLEAR},
+	{SCANCODE_KP_DIVIDE, SDL_SCANCODE_KP_DIVIDE},
+	{SCANCODE_KP_MULTIPLY, SDL_SCANCODE_KP_MULTIPLY},
+	{SCANCODE_KP_MINUS, SDL_SCANCODE_KP_MINUS},
+	{SCANCODE_KP_PLUS, SDL_SCANCODE_KP_PLUS},
+	{SCANCODE_KP_ENTER, SDL_SCANCODE_KP_ENTER},
+	{SCANCODE_KP_1, SDL_SCANCODE_KP_1},
+	{SCANCODE_KP_2, SDL_SCANCODE_KP_2},
+	{SCANCODE_KP_3, SDL_SCANCODE_KP_3},
+	{SCANCODE_KP_4, SDL_SCANCODE_KP_4},
+	{SCANCODE_KP_5, SDL_SCANCODE_KP_5},
+	{SCANCODE_KP_6, SDL_SCANCODE_KP_6},
+	{SCANCODE_KP_7, SDL_SCANCODE_KP_7},
+	{SCANCODE_KP_8, SDL_SCANCODE_KP_8},
+	{SCANCODE_KP_9, SDL_SCANCODE_KP_9},
+	{SCANCODE_KP_0, SDL_SCANCODE_KP_0},
+	{SCANCODE_KP_PERIOD, SDL_SCANCODE_KP_PERIOD},
+
+	{SCANCODE_NONUSBACKSLASH, SDL_SCANCODE_NONUSBACKSLASH},
+	{SCANCODE_APPLICATION, SDL_SCANCODE_APPLICATION},
+	{SCANCODE_POWER, SDL_SCANCODE_POWER},
+	{SCANCODE_KP_EQUALS, SDL_SCANCODE_KP_EQUALS},
+	{SCANCODE_F13, SDL_SCANCODE_F13},
+	{SCANCODE_F14, SDL_SCANCODE_F14},
+	{SCANCODE_F15, SDL_SCANCODE_F15},
+	{SCANCODE_F16, SDL_SCANCODE_F16},
+	{SCANCODE_F17, SDL_SCANCODE_F17},
+	{SCANCODE_F18, SDL_SCANCODE_F18},
+	{SCANCODE_F19, SDL_SCANCODE_F19},
+	{SCANCODE_F20, SDL_SCANCODE_F20},
+	{SCANCODE_F21, SDL_SCANCODE_F21},
+	{SCANCODE_F22, SDL_SCANCODE_F22},
+	{SCANCODE_F23, SDL_SCANCODE_F23},
+	{SCANCODE_F24, SDL_SCANCODE_F24},
+	{SCANCODE_EXECUTE, SDL_SCANCODE_EXECUTE},
+	{SCANCODE_HELP, SDL_SCANCODE_HELP},
+	{SCANCODE_MENU, SDL_SCANCODE_MENU},
+	{SCANCODE_SELECT, SDL_SCANCODE_SELECT},
+	{SCANCODE_STOP, SDL_SCANCODE_STOP},
+	{SCANCODE_AGAIN, SDL_SCANCODE_AGAIN},
+	{SCANCODE_UNDO, SDL_SCANCODE_UNDO},
+	{SCANCODE_CUT, SDL_SCANCODE_CUT},
+	{SCANCODE_COPY, SDL_SCANCODE_COPY},
+	{SCANCODE_PASTE, SDL_SCANCODE_PASTE},
+	{SCANCODE_FIND, SDL_SCANCODE_FIND},
+	{SCANCODE_MUTE, SDL_SCANCODE_MUTE},
+	{SCANCODE_VOLUMEUP, SDL_SCANCODE_VOLUMEUP},
+	{SCANCODE_VOLUMEDOWN, SDL_SCANCODE_VOLUMEDOWN},
+	{SCANCODE_KP_COMMA, SDL_SCANCODE_KP_COMMA},
+	{SCANCODE_KP_EQUALSAS400, SDL_SCANCODE_KP_EQUALSAS400},
+
+	{SCANCODE_INTERNATIONAL1, SDL_SCANCODE_INTERNATIONAL1},
+	{SCANCODE_INTERNATIONAL2, SDL_SCANCODE_INTERNATIONAL2},
+	{SCANCODE_INTERNATIONAL3, SDL_SCANCODE_INTERNATIONAL3},
+	{SCANCODE_INTERNATIONAL4, SDL_SCANCODE_INTERNATIONAL4},
+	{SCANCODE_INTERNATIONAL5, SDL_SCANCODE_INTERNATIONAL5},
+	{SCANCODE_INTERNATIONAL6, SDL_SCANCODE_INTERNATIONAL6},
+	{SCANCODE_INTERNATIONAL7, SDL_SCANCODE_INTERNATIONAL7},
+	{SCANCODE_INTERNATIONAL8, SDL_SCANCODE_INTERNATIONAL8},
+	{SCANCODE_INTERNATIONAL9, SDL_SCANCODE_INTERNATIONAL9},
+	{SCANCODE_LANG1, SDL_SCANCODE_LANG1},
+	{SCANCODE_LANG2, SDL_SCANCODE_LANG2},
+	{SCANCODE_LANG3, SDL_SCANCODE_LANG3},
+	{SCANCODE_LANG4, SDL_SCANCODE_LANG4},
+	{SCANCODE_LANG5, SDL_SCANCODE_LANG5},
+	{SCANCODE_LANG6, SDL_SCANCODE_LANG6},
+	{SCANCODE_LANG7, SDL_SCANCODE_LANG7},
+	{SCANCODE_LANG8, SDL_SCANCODE_LANG8},
+	{SCANCODE_LANG9, SDL_SCANCODE_LANG9},
+
+	{SCANCODE_ALTERASE, SDL_SCANCODE_ALTERASE},
+	{SCANCODE_SYSREQ, SDL_SCANCODE_SYSREQ},
+	{SCANCODE_CANCEL, SDL_SCANCODE_CANCEL},
+	{SCANCODE_CLEAR, SDL_SCANCODE_CLEAR},
+	{SCANCODE_PRIOR, SDL_SCANCODE_PRIOR},
+	{SCANCODE_RETURN2, SDL_SCANCODE_RETURN2},
+	{SCANCODE_SEPARATOR, SDL_SCANCODE_SEPARATOR},
+	{SCANCODE_OUT, SDL_SCANCODE_OUT},
+	{SCANCODE_OPER, SDL_SCANCODE_OPER},
+	{SCANCODE_CLEARAGAIN, SDL_SCANCODE_CLEARAGAIN},
+	{SCANCODE_CRSEL, SDL_SCANCODE_CRSEL},
+	{SCANCODE_EXSEL, SDL_SCANCODE_EXSEL},
+
+	{SCANCODE_KP_00, SDL_SCANCODE_KP_00},
+	{SCANCODE_KP_000, SDL_SCANCODE_KP_000},
+	{SCANCODE_THOUSANDSSEPARATOR, SDL_SCANCODE_THOUSANDSSEPARATOR},
+	{SCANCODE_DECIMALSEPARATOR, SDL_SCANCODE_DECIMALSEPARATOR},
+	{SCANCODE_CURRENCYUNIT, SDL_SCANCODE_CURRENCYUNIT},
+	{SCANCODE_CURRENCYSUBUNIT, SDL_SCANCODE_CURRENCYSUBUNIT},
+	{SCANCODE_KP_LEFTPAREN, SDL_SCANCODE_KP_LEFTPAREN},
+	{SCANCODE_KP_RIGHTPAREN, SDL_SCANCODE_KP_RIGHTPAREN},
+	{SCANCODE_KP_LEFTBRACE, SDL_SCANCODE_KP_LEFTBRACE},
+	{SCANCODE_KP_RIGHTBRACE, SDL_SCANCODE_KP_RIGHTBRACE},
+	{SCANCODE_KP_TAB, SDL_SCANCODE_KP_TAB},
+	{SCANCODE_KP_BACKSPACE, SDL_SCANCODE_KP_BACKSPACE},
+	{SCANCODE_KP_A, SDL_SCANCODE_KP_A},
+	{SCANCODE_KP_B, SDL_SCANCODE_KP_B},
+	{SCANCODE_KP_C, SDL_SCANCODE_KP_C},
+	{SCANCODE_KP_D, SDL_SCANCODE_KP_D},
+	{SCANCODE_KP_E, SDL_SCANCODE_KP_E},
+	{SCANCODE_KP_F, SDL_SCANCODE_KP_F},
+	{SCANCODE_KP_XOR, SDL_SCANCODE_KP_XOR},
+	{SCANCODE_KP_POWER, SDL_SCANCODE_KP_POWER},
+	{SCANCODE_KP_PERCENT, SDL_SCANCODE_KP_PERCENT},
+	{SCANCODE_KP_LESS, SDL_SCANCODE_KP_LESS},
+	{SCANCODE_KP_GREATER, SDL_SCANCODE_KP_GREATER},
+	{SCANCODE_KP_AMPERSAND, SDL_SCANCODE_KP_AMPERSAND},
+	{SCANCODE_KP_DBLAMPERSAND, SDL_SCANCODE_KP_DBLAMPERSAND},
+	{SCANCODE_KP_VERTICALBAR, SDL_SCANCODE_KP_VERTICALBAR},
+	{SCANCODE_KP_DBLVERTICALBAR, SDL_SCANCODE_KP_DBLVERTICALBAR},
+	{SCANCODE_KP_COLON, SDL_SCANCODE_KP_COLON},
+	{SCANCODE_KP_HASH, SDL_SCANCODE_KP_HASH},
+	{SCANCODE_KP_SPACE, SDL_SCANCODE_KP_SPACE},
+	{SCANCODE_KP_AT, SDL_SCANCODE_KP_AT},
+	{SCANCODE_KP_EXCLAM, SDL_SCANCODE_KP_EXCLAM},
+	{SCANCODE_KP_MEMSTORE, SDL_SCANCODE_KP_MEMSTORE},
+	{SCANCODE_KP_MEMRECALL, SDL_SCANCODE_KP_MEMRECALL},
+	{SCANCODE_KP_MEMCLEAR, SDL_SCANCODE_KP_MEMCLEAR},
+	{SCANCODE_KP_MEMADD, SDL_SCANCODE_KP_MEMADD},
+	{SCANCODE_KP_MEMSUBTRACT, SDL_SCANCODE_KP_MEMSUBTRACT},
+	{SCANCODE_KP_MEMMULTIPLY, SDL_SCANCODE_KP_MEMMULTIPLY},
+	{SCANCODE_KP_MEMDIVIDE, SDL_SCANCODE_KP_MEMDIVIDE},
+	{SCANCODE_KP_PLUSMINUS, SDL_SCANCODE_KP_PLUSMINUS},
+	{SCANCODE_KP_CLEAR, SDL_SCANCODE_KP_CLEAR},
+	{SCANCODE_KP_CLEARENTRY, SDL_SCANCODE_KP_CLEARENTRY},
+	{SCANCODE_KP_BINARY, SDL_SCANCODE_KP_BINARY},
+	{SCANCODE_KP_OCTAL, SDL_SCANCODE_KP_OCTAL},
+	{SCANCODE_KP_DECIMAL, SDL_SCANCODE_KP_DECIMAL},
+	{SCANCODE_KP_HEXADECIMAL, SDL_SCANCODE_KP_HEXADECIMAL},
+
+	{SCANCODE_LCTRL, SDL_SCANCODE_LCTRL},
+	{SCANCODE_LSHIFT, SDL_SCANCODE_LSHIFT},
+	{SCANCODE_LALT, SDL_SCANCODE_LALT},
+	{SCANCODE_LGUI, SDL_SCANCODE_LGUI},
+	{SCANCODE_RCTRL, SDL_SCANCODE_RCTRL},
+	{SCANCODE_RSHIFT, SDL_SCANCODE_RSHIFT},
+	{SCANCODE_RALT, SDL_SCANCODE_RALT},
+	{SCANCODE_RGUI, SDL_SCANCODE_RGUI},
+
+	{SCANCODE_MODE, SDL_SCANCODE_MODE},
+
+	{SCANCODE_AUDIONEXT, SDL_SCANCODE_AUDIONEXT},
+	{SCANCODE_AUDIOPREV, SDL_SCANCODE_AUDIOPREV},
+	{SCANCODE_AUDIOSTOP, SDL_SCANCODE_AUDIOSTOP},
+	{SCANCODE_AUDIOPLAY, SDL_SCANCODE_AUDIOPLAY},
+	{SCANCODE_AUDIOMUTE, SDL_SCANCODE_AUDIOMUTE},
+	{SCANCODE_MEDIASELECT, SDL_SCANCODE_MEDIASELECT},
+	{SCANCODE_WWW, SDL_SCANCODE_WWW},
+	{SCANCODE_MAIL, SDL_SCANCODE_MAIL},
+	{SCANCODE_CALCULATOR, SDL_SCANCODE_CALCULATOR},
+	{SCANCODE_COMPUTER, SDL_SCANCODE_COMPUTER},
+	{SCANCODE_AC_SEARCH, SDL_SCANCODE_AC_SEARCH},
+	{SCANCODE_AC_HOME, SDL_SCANCODE_AC_HOME},
+	{SCANCODE_AC_BACK, SDL_SCANCODE_AC_BACK},
+	{SCANCODE_AC_FORWARD, SDL_SCANCODE_AC_FORWARD},
+	{SCANCODE_AC_STOP, SDL_SCANCODE_AC_STOP},
+	{SCANCODE_AC_REFRESH, SDL_SCANCODE_AC_REFRESH},
+	{SCANCODE_AC_BOOKMARKS, SDL_SCANCODE_AC_BOOKMARKS},
+
+	{SCANCODE_BRIGHTNESSDOWN, SDL_SCANCODE_BRIGHTNESSDOWN},
+	{SCANCODE_BRIGHTNESSUP, SDL_SCANCODE_BRIGHTNESSUP},
+	{SCANCODE_DISPLAYSWITCH, SDL_SCANCODE_DISPLAYSWITCH},
+	{SCANCODE_KBDILLUMTOGGLE, SDL_SCANCODE_KBDILLUMTOGGLE},
+	{SCANCODE_KBDILLUMDOWN, SDL_SCANCODE_KBDILLUMDOWN},
+	{SCANCODE_KBDILLUMUP, SDL_SCANCODE_KBDILLUMUP},
+	{SCANCODE_EJECT, SDL_SCANCODE_EJECT},
+	{SCANCODE_SLEEP, SDL_SCANCODE_SLEEP},
+	
+	{SCANCODE_APP1, SDL_SCANCODE_APP1},
+	{SCANCODE_APP2, SDL_SCANCODE_APP2},
+};
+
+EnumMap<Keyboard::Scancode, SDL_Scancode, SDL_NUM_SCANCODES> Keyboard::scancodes(Keyboard::scancodeEntries, sizeof(Keyboard::scancodeEntries));
+
 } // sdl
 } // keyboard
 } // love

+ 6 - 0
src/modules/keyboard/sdl/Keyboard.h

@@ -48,6 +48,9 @@ public:
 	bool hasKeyRepeat() const;
 	bool isDown(Key *keylist) const;
 
+	Key getKeyFromScancode(Scancode scancode) const;
+	Scancode getScancodeFromKey(Key key) const;
+
 	void setTextInput(bool enable);
 	bool hasTextInput() const;
 
@@ -60,6 +63,9 @@ private:
 	static const SDL_Keycode *createKeyMap();
 	static const SDL_Keycode *keymap;
 
+	static EnumMap<Scancode, SDL_Scancode, SDL_NUM_SCANCODES>::Entry scancodeEntries[];
+	static EnumMap<Scancode, SDL_Scancode, SDL_NUM_SCANCODES> scancodes;
+
 }; // Keyboard
 
 } // sdl

+ 36 - 0
src/modules/keyboard/wrap_Keyboard.cpp

@@ -62,6 +62,40 @@ int w_isDown(lua_State *L)
 	return 1;
 }
 
+int w_getScancodeFromKey(lua_State *L)
+{
+	const char *keystr = luaL_checkstring(L, 1);
+	Keyboard::Key key;
+	if (!Keyboard::getConstant(keystr, key))
+		return luaL_error(L, "Invalid key constant: %s", keystr);
+
+	Keyboard::Scancode scancode = instance()->getScancodeFromKey(key);
+
+	const char *scancodestr;
+	if (!Keyboard::getConstant(scancode, scancodestr))
+		return luaL_error(L, "Unknown scancode.");
+
+	lua_pushstring(L, scancodestr);
+	return 1;
+}
+
+int w_getKeyFromScancode(lua_State *L)
+{
+	const char *scancodestr = luaL_checkstring(L, 1);
+	Keyboard::Scancode scancode;
+	if (!Keyboard::getConstant(scancodestr, scancode))
+		return luaL_error(L, "Invalid scancode: %s", scancode);
+
+	Keyboard::Key key = instance()->getKeyFromScancode(scancode);
+
+	const char *keystr;
+	if (!Keyboard::getConstant(key, keystr))
+		return luaL_error(L, "Unknown key constant");
+
+	lua_pushstring(L, keystr);
+	return 1;
+}
+
 int w_setTextInput(lua_State *L)
 {
 	instance()->setTextInput(luax_toboolean(L, 1));
@@ -82,6 +116,8 @@ static const luaL_Reg functions[] =
 	{ "setTextInput", w_setTextInput },
 	{ "hasTextInput", w_hasTextInput },
 	{ "isDown", w_isDown },
+	{ "getScancodeFromKey", w_getScancodeFromKey },
+	{ "getKeyFromScancode", w_getKeyFromScancode },
 	{ 0, 0 }
 };
 

+ 2 - 0
src/modules/keyboard/wrap_Keyboard.h

@@ -33,6 +33,8 @@ namespace keyboard
 int w_setKeyRepeat(lua_State *L);
 int w_hasKeyRepeat(lua_State *L);
 int w_isDown(lua_State *L);
+int w_getKeyFromScancode(lua_State *L);
+int w_getScancodeFromkey(lua_State *L);
 int w_setTextInput(lua_State *L);
 int w_hasTextInput(lua_State *L);
 extern "C" LOVE_EXPORT int luaopen_love_keyboard(lua_State *L);