Index: src/events/SDL_keyboard.c =================================================================== --- src/events/SDL_keyboard.c (revision 2741) +++ src/events/SDL_keyboard.c (working copy) @@ -27,6 +27,7 @@ #include "SDL_events.h" #include "SDL_events_c.h" #include "SDL_sysevents.h" +#include "SDL_pkeynames.h" /* Global keystate information */ @@ -369,6 +370,25 @@ return (char *)(keyname); } +const char *SDL_PKeyName(SDLPKey pkey) +{ + const char *name = NULL; + + if ( pkey == SDL_PK_NONE ) return ""; + if ( pkey == SDL_PK_UNKNOWN ) return pKeyNames[SDL_PK_UNKNOWN]; + + if ( current_video->PKeyName ) { + name = current_video->PKeyName(current_video, pkey); + } + if ( name == NULL && pkey < SDL_PK_LAST ) { + name = pKeyNames[pkey]; + } + if ( name == NULL ) { + name = pKeyNames[SDL_PK_UNKNOWN]; + } + return name; +} + /* These are global for SDL_eventloop.c */ int SDL_PrivateKeyboard(Uint8 state, SDL_keysym *keysym) { Index: src/events/SDL_pkeynames.h =================================================================== --- src/events/SDL_pkeynames.h (revision 0) +++ src/events/SDL_pkeynames.h (revision 0) @@ -0,0 +1,263 @@ +/* Hardcoded generic names for the SDLPKey constants, used by SDL_PKeyName() when the platform-specific backend doesn't provide a better name. The letter keys in particular are only correct on a US key mapping. */ + +static const char *pKeyNames[SDL_PK_LAST] = { + /* 0 */ "", /* SDL_PK_NONE */ + /* 1 */ "unknown key", + /* 2 */ NULL, /* unused */ + /* 3 */ NULL, /* unused */ + /* 4 */ "A", + /* 5 */ "B", + /* 6 */ "C", + /* 7 */ "D", + /* 8 */ "E", + /* 9 */ "F", + /* 10 */ "G", + /* 11 */ "H", + /* 12 */ "I", + /* 13 */ "J", + /* 14 */ "K", + /* 15 */ "L", + /* 16 */ "M", + /* 17 */ "N", + /* 18 */ "O", + /* 19 */ "P", + /* 20 */ "Q", + /* 21 */ "R", + /* 22 */ "S", + /* 23 */ "T", + /* 24 */ "U", + /* 25 */ "V", + /* 26 */ "W", + /* 27 */ "X", + /* 28 */ "Y", + /* 29 */ "Z", + /* 30 */ "1", + /* 31 */ "2", + /* 32 */ "3", + /* 33 */ "4", + /* 34 */ "5", + /* 35 */ "6", + /* 36 */ "7", + /* 37 */ "8", + /* 38 */ "9", + /* 39 */ "0", + /* 40 */ "return", + /* 41 */ "escape", + /* 42 */ "backspace", + /* 43 */ "tab", + /* 44 */ "space", + /* 45 */ "-", + /* 46 */ "=", + /* 47 */ "[", + /* 48 */ "]", + /* 49 */ "\\", + /* 50 */ "\\", + /* 51 */ ";", + /* 52 */ "'", + /* 53 */ "`", + /* 54 */ ",", + /* 55 */ ".", + /* 56 */ "/", + /* 57 */ "caps lock", + /* 58 */ "F1", + /* 59 */ "F2", + /* 60 */ "F3", + /* 61 */ "F4", + /* 62 */ "F5", + /* 63 */ "F6", + /* 64 */ "F7", + /* 65 */ "F8", + /* 66 */ "F9", + /* 67 */ "F10", + /* 68 */ "F11", + /* 69 */ "F12", + /* 70 */ "print screen", + /* 71 */ "scroll lock", + /* 72 */ "pause", + /* 73 */ "insert", + /* 74 */ "home", + /* 75 */ "page up", + /* 76 */ "delete", + /* 77 */ "end", + /* 78 */ "page down", + /* 79 */ "right", + /* 80 */ "left", + /* 81 */ "down", + /* 82 */ "up", + /* 83 */ "num lock", + /* 84 */ "[/]", + /* 85 */ "[*]", + /* 86 */ "[-]", + /* 87 */ "[+]", + /* 88 */ "enter", + /* 89 */ "[1]", + /* 90 */ "[2]", + /* 91 */ "[3]", + /* 92 */ "[4]", + /* 93 */ "[5]", + /* 94 */ "[6]", + /* 95 */ "[7]", + /* 96 */ "[8]", + /* 97 */ "[9]", + /* 98 */ "[0]", + /* 99 */ "[.]", + /* 100 */ "<", + /* 101 */ "application", + /* 102 */ "power", + /* 103 */ "[=]", + /* 104 */ "F13", + /* 105 */ "F14", + /* 106 */ "F15", + /* 107 */ "F16", + /* 108 */ "F17", + /* 109 */ "F18", + /* 110 */ "F19", + /* 111 */ "F20", + /* 112 */ "F21", + /* 113 */ "F22", + /* 114 */ "F23", + /* 115 */ "F24", + /* 116 */ "execute", + /* 117 */ "help", + /* 118 */ "menu", + /* 119 */ "select", + /* 120 */ "stop", + /* 121 */ "again", + /* 122 */ "undo", + /* 123 */ "cut", + /* 124 */ "copy", + /* 125 */ "paste", + /* 126 */ "find", + /* 127 */ "mute", + /* 128 */ "volume up", + /* 129 */ "volume down", + /* 130 */ "caps lock", /* unused */ + /* 131 */ "num lock", /* unused */ + /* 132 */ "scroll lock", /* unused */ + /* 133 */ "[,]", + /* 134 */ "[=]", + /* 135 */ "international 1", + /* 136 */ "international 2", + /* 137 */ "international 3", + /* 138 */ "international 4", + /* 139 */ "international 5", + /* 140 */ "international 6", + /* 141 */ "international 7", + /* 142 */ "international 8", + /* 143 */ "international 9", + /* 144 */ "lang 1", + /* 145 */ "lang 2", + /* 146 */ "lang 3", + /* 147 */ "lang 4", + /* 148 */ "lang 5", + /* 149 */ "lang 6", + /* 150 */ "lang 7", + /* 151 */ "lang 8", + /* 152 */ "lang 9", + /* 153 */ "alt erase", + /* 154 */ "sys req", + /* 155 */ "cancel", + /* 156 */ "clear", + /* 157 */ "prior", + /* 158 */ "return", + /* 159 */ "separator", + /* 160 */ "out", + /* 161 */ "oper", + /* 162 */ "clear/again", + /* 163 */ "crsel/props", + /* 164 */ "exsel", + /* 165 */ NULL, /* unused */ + /* 166 */ NULL, /* unused */ + /* 167 */ NULL, /* unused */ + /* 168 */ NULL, /* unused */ + /* 169 */ NULL, /* unused */ + /* 170 */ NULL, /* unused */ + /* 171 */ NULL, /* unused */ + /* 172 */ NULL, /* unused */ + /* 173 */ NULL, /* unused */ + /* 174 */ NULL, /* unused */ + /* 175 */ NULL, /* unused */ + /* 176 */ "[00]", + /* 177 */ "[000]", + /* 178 */ "thousands separator", + /* 179 */ "decimal separator", + /* 180 */ "currency unit", + /* 181 */ "currency sub-unit", + /* 182 */ "[(]", + /* 183 */ "[)]", + /* 184 */ "[{]", + /* 185 */ "[}]", + /* 186 */ "[tab]", + /* 187 */ "[backspace]", + /* 188 */ "[A]", + /* 189 */ "[B]", + /* 190 */ "[C]", + /* 191 */ "[D]", + /* 192 */ "[E]", + /* 193 */ "[F]", + /* 194 */ "[XOR]", + /* 195 */ "[^]", + /* 196 */ "[%]", + /* 197 */ "[<]", + /* 198 */ "[>]", + /* 199 */ "[&]", + /* 200 */ "[&&]", + /* 201 */ "[|]", + /* 202 */ "[||]", + /* 203 */ "[:]", + /* 204 */ "[#]", + /* 205 */ "[space]", + /* 206 */ "[@]", + /* 207 */ "[!]", + /* 208 */ "[mem store]", + /* 209 */ "[mem recall]", + /* 210 */ "[mem clear]", + /* 211 */ "[mem +]", + /* 212 */ "[mem -]", + /* 213 */ "[mem *]", + /* 214 */ "[mem /]", + /* 215 */ "[+/-]", + /* 216 */ "[clear]", + /* 217 */ "[clear entry]", + /* 218 */ "[binary]", + /* 219 */ "[octal]", + /* 220 */ "[decimal]", + /* 221 */ "[hexadecimal]", + /* 222 */ NULL, /* unused */ + /* 223 */ NULL, /* unused */ + /* 224 */ "left ctrl", + /* 225 */ "left shift", + /* 226 */ "left alt", + /* 227 */ "left GUI", + /* 228 */ "right ctrl", + /* 229 */ "right shift", + /* 230 */ "right alt", + /* 231 */ "right GUI", + /* 232 */ NULL, /* unused */ + /* 233 */ NULL, /* unused */ + /* 234 */ NULL, /* unused */ + /* 235 */ NULL, /* unused */ + /* 236 */ "brightness down", + /* 237 */ "brightness up", + /* 238 */ "display switch", + /* 239 */ "kbd illum toggle", + /* 240 */ "kbd illum down", + /* 241 */ "kbd illum up", + /* 242 */ "eject", + /* 243 */ "sleep", + /* 244 */ "play", + /* 245 */ "stop", + /* 246 */ "previous", + /* 247 */ "next", + /* 248 */ "calc", + /* 249 */ "www", + /* 250 */ "e-mail", + /* 251 */ "media", + /* 252 */ "computer", + /* 253 */ "search", + /* 254 */ "bookmarks", + /* 255 */ "back", + /* 256 */ "forward", + /* 257 */ "reload", + /* 258 */ "stop" +}; Property changes on: src/events/SDL_pkeynames.h ___________________________________________________________________ Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: src/video/quartz/SDL_QuartzVideo.h =================================================================== --- src/video/quartz/SDL_QuartzVideo.h (revision 2741) +++ src/video/quartz/SDL_QuartzVideo.h (working copy) @@ -202,6 +202,7 @@ /* Event functions */ void QZ_InitOSKeymap (_THIS); +const char * QZ_PKeyName (_THIS, SDLPKey pkey); void QZ_PumpEvents (_THIS); /* Window Manager functions */ Index: src/video/quartz/SDL_QuartzEvents.m =================================================================== --- src/video/quartz/SDL_QuartzEvents.m (revision 2741) +++ src/video/quartz/SDL_QuartzEvents.m (working copy) @@ -180,10 +180,10 @@ keymap[QZ_KP0] = SDLK_KP0; keymap[QZ_KP_PERIOD] = SDLK_KP_PERIOD; keymap[QZ_IBOOK_ENTER] = SDLK_KP_ENTER; - keymap[QZ_IBOOK_RIGHT] = SDLK_RIGHT; - keymap[QZ_IBOOK_DOWN] = SDLK_DOWN; - keymap[QZ_IBOOK_UP] = SDLK_UP; - keymap[QZ_IBOOK_LEFT] = SDLK_LEFT; + //keymap[QZ_IBOOK_RIGHT] = SDLK_RIGHT; + //keymap[QZ_IBOOK_DOWN] = SDLK_DOWN; + //keymap[QZ_IBOOK_UP] = SDLK_UP; + //keymap[QZ_IBOOK_LEFT] = SDLK_LEFT; /* Up there we setup a static scancode->keysym map. However, it will not @@ -246,6 +246,156 @@ keymap[QZ_KP_ENTER] = SDLK_KP_ENTER; } +const char *QZ_PKeyName(_THIS, SDLPKey pkey) { + switch (pkey) { + /* for some keys, we have platform-dependent but layout-independent names */ + case SDL_PK_KP_NUMLOCKCLEAR: return "clear"; + case SDL_PK_LALT: return "left option"; + case SDL_PK_LGUI: return "left command"; + case SDL_PK_RALT: return "right option"; + case SDL_PK_RGUI: return "right command"; + + /* for others, the generic platform-agnostic names provided by SDL_PKeyName() are better than what we would obtain from a translation by keyboard layout */ + case SDL_PK_RETURN: + case SDL_PK_ESCAPE: + case SDL_PK_BACKSPACE: + case SDL_PK_TAB: + case SDL_PK_SPACE: + case SDL_PK_CAPSLOCK: + case SDL_PK_F1: + case SDL_PK_F2: + case SDL_PK_F3: + case SDL_PK_F4: + case SDL_PK_F5: + case SDL_PK_F6: + case SDL_PK_F7: + case SDL_PK_F8: + case SDL_PK_F9: + case SDL_PK_F10: + case SDL_PK_F11: + case SDL_PK_F12: + case SDL_PK_PRINTSCREEN: + case SDL_PK_SCROLLLOCK: + case SDL_PK_PAUSE: + case SDL_PK_INSERT: + case SDL_PK_HOME: + case SDL_PK_PAGEUP: + case SDL_PK_DELETE: + case SDL_PK_END: + case SDL_PK_PAGEDOWN: + case SDL_PK_RIGHT: + case SDL_PK_LEFT: + case SDL_PK_DOWN: + case SDL_PK_UP: + case SDL_PK_KP_ENTER: + case SDL_PK_APPLICATION: + case SDL_PK_POWER: + case SDL_PK_F13: + case SDL_PK_F14: + case SDL_PK_F15: + case SDL_PK_F16: + case SDL_PK_LCTRL: + case SDL_PK_LSHIFT: + case SDL_PK_RCTRL: + case SDL_PK_RSHIFT: + return NULL; + + /* for the rest, we try the translation first */ + default: { + static char outputBuffer[25]; /* 4 * 6 (maximal UTF-8 char length) + 1 (null teminator) */ + CFStringRef conversionString; + Boolean ok; + UInt16 vkey = 0; + KeyboardLayoutRef layout; + KeyboardLayoutKind kind; + UInt32 keyboardType = LMGetKbdType(); + + /* look up pkey to get a Mac virtual key code - linear search isn't terribly efficient, but should be OK here */ + while (vkey < 128 && pkey != macToSDLPK[vkey]) vkey++; + if (vkey == 128) return NULL; + if ((vkey == 10 || vkey == 50) && KBGetLayoutType(keyboardType) == kKeyboardISO) vkey = 60 - vkey; /* see comments in SDL_QuartzKeys.h */ + + if (KLGetCurrentKeyboardLayout(&layout) != noErr) return NULL; + if (KLGetKeyboardLayoutProperty(layout, kKLKind, (const void **)&kind) != noErr) return NULL; + if (kind == kKLKCHRuchrKind || kind == kKLuchrKind) { + UniChar utf16String[4]; + UInt32 deadKeyState = 0; + UniCharCount actualStringLength; + const UCKeyboardLayout *uchrData; + + if (KLGetKeyboardLayoutProperty(layout, kKLuchrData, (const void **)&uchrData) != noErr) return NULL; + if (UCKeyTranslate(uchrData, vkey, kUCKeyActionDisplay, 0, keyboardType, 0, &deadKeyState, 4, &actualStringLength, utf16String) != noErr) return NULL; + /* kUCKeyActionDisplay (instead of kUCKeyActionDown) seems to take care of dead keys, so no need to check for that case and simulate a second key press */ + + if (actualStringLength == 0) return NULL; + + /* letter keys on latin keyboards are normally labeled in upper case (and probably on others too, so if you happen to know for sure, please adapt this) */ + if (actualStringLength == 1 && utf16String[0] >= 0x61 && utf16String[0] <= 0x7A) { + utf16String[0] -= 32; + } + + conversionString = CFStringCreateWithCharacters(kCFAllocatorDefault, utf16String, actualStringLength); + } + else { /* kind == kKLKCHRKind */ + const void *kchrData; + UInt32 state = 0; + UInt8 charCode; + SInt32 scriptCode; + TextEncoding keyboardEncoding; + + if (KLGetKeyboardLayoutProperty(layout, kKLKCHRData, &kchrData) != noErr) return NULL; + charCode = KeyTranslate(kchrData, vkey, &state) & 0xFF; /* actually returns a UInt32 containing two character codes, but we're only interested in the second (or only) one */ + if (charCode == 0) { + /* it's a dead key, so simulate a second key press */ + charCode = KeyTranslate(kchrData, vkey, &state) & 0xFF; + /* Still zero? Give up. */ + if (charCode == 0) return NULL; + } + if (KLGetKeyboardLayoutProperty(layout, kKLGroupIdentifier, (const void **)&scriptCode) != noErr) return NULL; /* that the group identifier is actually a script code is not documented, but confirmed here: */ + if (UpgradeScriptInfoToTextEncoding(scriptCode, kTextLanguageDontCare, kTextRegionDontCare, NULL, &keyboardEncoding) != noErr) return NULL; + + /* letter keys on latin keyboards are normally labeled in upper case (and probably on others too, so if you happen to know for sure, please adapt this) */ + if (GetTextEncodingBase(keyboardEncoding) == kTextEncodingMacRoman && charCode >= 0x61 && charCode <= 0x7A) { + charCode -= 32; + } + + conversionString = CFStringCreateWithBytes(kCFAllocatorDefault, &charCode, 1, keyboardEncoding, FALSE); + } + + /* if it's a keypad key, add [] around the name */ + switch (pkey) { + case SDL_PK_KP_DIVIDE: + case SDL_PK_KP_MULTIPLY: + case SDL_PK_KP_MINUS: + case SDL_PK_KP_PLUS: + case SDL_PK_KP_1: + case SDL_PK_KP_2: + case SDL_PK_KP_3: + case SDL_PK_KP_4: + case SDL_PK_KP_5: + case SDL_PK_KP_6: + case SDL_PK_KP_7: + case SDL_PK_KP_8: + case SDL_PK_KP_9: + case SDL_PK_KP_0: + case SDL_PK_KP_PERIOD: + case SDL_PK_KP_EQUALS: + outputBuffer[0] = '['; + ok = CFStringGetCString(conversionString, outputBuffer+1, sizeof(outputBuffer)-2, kCFStringEncodingUTF8); + SDL_strlcat(outputBuffer, "]", sizeof(outputBuffer)); + break; + default: + ok = CFStringGetCString(conversionString, outputBuffer, sizeof(outputBuffer), kCFStringEncodingUTF8); + break; + } + + CFRelease(conversionString); + if (ok) return outputBuffer; + else return NULL; + } + } +} + static void QZ_DoKey (_THIS, int state, NSEvent *event) { NSString *chars; @@ -260,13 +410,33 @@ contains multiple characters, we'll use 0 as the scancode/keysym. */ - if (SDL_TranslateUNICODE) { + if ([event type] != NSFlagsChanged && SDL_TranslateUNICODE) { chars = [ event characters ]; numChars = [ chars length ]; } else { numChars = 0; } + unsigned short vkey = [event keyCode]; + if (vkey < 128) { + key.pkey = macToSDLPK[vkey]; + } + else { /* I don't think this ever happens with normal keyboards, but you never know... */ + key.pkey = SDL_PK_UNKNOWN; + } + if (KBGetLayoutType(LMGetKbdType()) == kKeyboardISO) { + /* see comments in SDL_QuartzKeys.h */ + switch (vkey) { + case 10: key.pkey = SDL_PK_GRAVE; break; + case 50: key.pkey = SDL_PK_NONUSBACKSLASH; break; + } + } +#if 1 + if (key.pkey == SDL_PK_UNKNOWN && state == SDL_PRESSED) { + fprintf(stderr, "The key you just pressed is not recognized by SDL. To help get this fixed, report this to the SDL mailing list or to Christian Walther . Mac virtual key code is %d.\n", vkey); + } +#endif + if (numChars == 0) { key.scancode = [ event keyCode ]; @@ -274,7 +444,12 @@ key.unicode = 0; key.mod = KMOD_NONE; - SDL_PrivateKeyboard (state, &key); + if (key.pkey == SDL_PK_CAPSLOCK) { + /* SDL handles the locking of the caps lock key itself, so we need to send it two events */ + SDL_PrivateKeyboard (SDL_PRESSED, &key); + SDL_PrivateKeyboard (SDL_RELEASED, &key); + } + else SDL_PrivateKeyboard (state, &key); } else if (numChars == 1) { @@ -779,7 +954,7 @@ type = [ event type ]; isInGameWin = QZ_IsMouseInWindow (this); - QZ_DoModifiers(this, [ event modifierFlags ] ); + //QZ_DoModifiers(this, [ event modifierFlags ] ); switch (type) { case NSLeftMouseDown: @@ -952,6 +1127,14 @@ QZ_DoKey (this, SDL_PRESSED, event); break; case NSFlagsChanged: + if ([event keyCode] != 127) { + /* On my PowerBook, the 'num lock' key sends NSFlagsChanged events with a key code of 127, which otherwise belongs to the power key. Since the PowerBook 'num lock' (not to be confused with the 'num lock' key on PC keyboards or the 'clear' key that sits at its place on Mac keyboards) already acts as a hardware-level modifier, we can ignore these events. */ + unsigned int newMods = [event modifierFlags]; + if (newMods != current_mods) { + QZ_DoKey(this, ((newMods & ~current_mods) != 0) ? SDL_PRESSED : SDL_RELEASED, event); + current_mods = newMods; + } + } break; /* case NSAppKitDefined: break; */ /* case NSApplicationDefined: break; */ Index: src/video/quartz/SDL_QuartzKeys.h =================================================================== --- src/video/quartz/SDL_QuartzKeys.h (revision 2741) +++ src/video/quartz/SDL_QuartzKeys.h (working copy) @@ -139,3 +139,141 @@ #define QZ_IBOOK_RIGHT 0x3C #define QZ_IBOOK_DOWN 0x3D #define QZ_IBOOK_UP 0x3E + + +/* Mac virtual key code to SDLPKey mapping table + Sources: + - Inside Macintosh: Text + - Apple USB keyboard driver source + - experimentation on various ADB and USB ISO keyboards and one ADB ANSI keyboard +*/ +static SDLPKey macToSDLPK[128] = { + /* 0 */ SDL_PK_A, + /* 1 */ SDL_PK_S, + /* 2 */ SDL_PK_D, + /* 3 */ SDL_PK_F, + /* 4 */ SDL_PK_H, + /* 5 */ SDL_PK_G, + /* 6 */ SDL_PK_Z, + /* 7 */ SDL_PK_X, + /* 8 */ SDL_PK_C, + /* 9 */ SDL_PK_V, + /* 10 */ SDL_PK_NONUSBACKSLASH, /* SDL_PK_NONUSBACKSLASH on ANSI and JIS keyboards (if this key would exist there), SDL_PK_GRAVE on ISO. (The USB keyboard driver actually translates these usage codes to different virtual key codes depending on whether the keyboard is ISO/ANSI/JIS. That's why you have to help it identify the keyboard layout when you plug in a PC USB keyboard. It's a historical thing - ADB keyboards are wired this way.) */ + /* 11 */ SDL_PK_B, + /* 12 */ SDL_PK_Q, + /* 13 */ SDL_PK_W, + /* 14 */ SDL_PK_E, + /* 15 */ SDL_PK_R, + /* 16 */ SDL_PK_Y, + /* 17 */ SDL_PK_T, + /* 18 */ SDL_PK_1, + /* 19 */ SDL_PK_2, + /* 20 */ SDL_PK_3, + /* 21 */ SDL_PK_4, + /* 22 */ SDL_PK_6, + /* 23 */ SDL_PK_5, + /* 24 */ SDL_PK_EQUALS, + /* 25 */ SDL_PK_9, + /* 26 */ SDL_PK_7, + /* 27 */ SDL_PK_HYPHENMINUS, + /* 28 */ SDL_PK_8, + /* 29 */ SDL_PK_0, + /* 30 */ SDL_PK_RIGHTBRACKET, + /* 31 */ SDL_PK_O, + /* 32 */ SDL_PK_U, + /* 33 */ SDL_PK_LEFTBRACKET, + /* 34 */ SDL_PK_I, + /* 35 */ SDL_PK_P, + /* 36 */ SDL_PK_RETURN, + /* 37 */ SDL_PK_L, + /* 38 */ SDL_PK_J, + /* 39 */ SDL_PK_APOSTROPHE, + /* 40 */ SDL_PK_K, + /* 41 */ SDL_PK_SEMICOLON, + /* 42 */ SDL_PK_BACKSLASH, + /* 43 */ SDL_PK_COMMA, + /* 44 */ SDL_PK_SLASH, + /* 45 */ SDL_PK_N, + /* 46 */ SDL_PK_M, + /* 47 */ SDL_PK_PERIOD, + /* 48 */ SDL_PK_TAB, + /* 49 */ SDL_PK_SPACE, + /* 50 */ SDL_PK_GRAVE, /* SDL_PK_GRAVE on ANSI and JIS keyboards, SDL_PK_NONUSBACKSLASH on ISO (see comment about virtual key code 10 above) */ + /* 51 */ SDL_PK_BACKSPACE, + /* 52 */ SDL_PK_KP_ENTER, /* keyboard enter on portables */ + /* 53 */ SDL_PK_ESCAPE, + /* 54 */ SDL_PK_RGUI, + /* 55 */ SDL_PK_LGUI, + /* 56 */ SDL_PK_LSHIFT, + /* 57 */ SDL_PK_CAPSLOCK, + /* 58 */ SDL_PK_LALT, + /* 59 */ SDL_PK_LCTRL, + /* 60 */ SDL_PK_RSHIFT, + /* 61 */ SDL_PK_RALT, + /* 62 */ SDL_PK_RCTRL, + /* 63 */ SDL_PK_NONE, /* fn on portables, acts a a hardware-level modifier already, so we don't generate events for it */ + /* 64 */ SDL_PK_UNKNOWN, /* unknown (unused?) */ + /* 65 */ SDL_PK_KP_PERIOD, + /* 66 */ SDL_PK_UNKNOWN, /* unknown (unused?) */ + /* 67 */ SDL_PK_KP_MULTIPLY, + /* 68 */ SDL_PK_UNKNOWN, /* unknown (unused?) */ + /* 69 */ SDL_PK_KP_PLUS, + /* 70 */ SDL_PK_UNKNOWN, /* unknown (unused?) */ + /* 71 */ SDL_PK_KP_NUMLOCKCLEAR, + /* 72 */ SDL_PK_VOLUMEUP, + /* 73 */ SDL_PK_VOLUMEDOWN, + /* 74 */ SDL_PK_MUTE, + /* 75 */ SDL_PK_KP_DIVIDE, + /* 76 */ SDL_PK_KP_ENTER, /* keypad enter on external keyboards, fn-return on portables */ + /* 77 */ SDL_PK_UNKNOWN, /* unknown (unused?) */ + /* 78 */ SDL_PK_KP_MINUS, + /* 79 */ SDL_PK_UNKNOWN, /* unknown (unused?) */ + /* 80 */ SDL_PK_UNKNOWN, /* unknown (unused?) */ + /* 81 */ SDL_PK_KP_EQUALS, + /* 82 */ SDL_PK_KP_0, + /* 83 */ SDL_PK_KP_1, + /* 84 */ SDL_PK_KP_2, + /* 85 */ SDL_PK_KP_3, + /* 86 */ SDL_PK_KP_4, + /* 87 */ SDL_PK_KP_5, + /* 88 */ SDL_PK_KP_6, + /* 89 */ SDL_PK_KP_7, + /* 90 */ SDL_PK_UNKNOWN, /* unknown (unused?) */ + /* 91 */ SDL_PK_KP_8, + /* 92 */ SDL_PK_KP_9, + /* 93 */ SDL_PK_INTERNATIONAL3, /* Cosmo_USB2ADB.c says "Yen (JIS)" */ + /* 94 */ SDL_PK_INTERNATIONAL1, /* Cosmo_USB2ADB.c says "Ro (JIS)" */ + /* 95 */ SDL_PK_KP_COMMA, /* Cosmo_USB2ADB.c says ", JIS only" */ + /* 96 */ SDL_PK_F5, + /* 97 */ SDL_PK_F6, + /* 98 */ SDL_PK_F7, + /* 99 */ SDL_PK_F3, + /* 100 */ SDL_PK_F8, + /* 101 */ SDL_PK_F9, + /* 102 */ SDL_PK_LANG2, /* Cosmo_USB2ADB.c says "Eisu" */ + /* 103 */ SDL_PK_F11, + /* 104 */ SDL_PK_LANG1, /* Cosmo_USB2ADB.c says "Kana" */ + /* 105 */ SDL_PK_PRINTSCREEN, /* On ADB keyboards, this key is labeled "F13/print screen". Problem: USB has different usage codes for these two functions. On Apple USB keyboards, the key is labeled "F13" and sends the F13 usage code (SDL_PK_F13). I decided to use SDL_PK_PRINTSCREEN here nevertheless since SDL applications are more likely to assume the presence of a print screen key than an F13 key.*/ + /* 106 */ SDL_PK_F16, + /* 107 */ SDL_PK_SCROLLLOCK, /* F14/scroll lock, see comment about F13/print screen above */ + /* 108 */ SDL_PK_UNKNOWN, /* unknown (unused?) */ + /* 109 */ SDL_PK_F10, + /* 110 */ SDL_PK_APPLICATION, /* windows contextual menu key, fn-enter on portables */ + /* 111 */ SDL_PK_F12, + /* 112 */ SDL_PK_UNKNOWN, /* unknown (unused?) */ + /* 113 */ SDL_PK_PAUSE, /* F15/pause, see comment about F13/print screen above */ + /* 114 */ SDL_PK_INSERT, /* the key is actually labeled "help" on Apple keyboards, and works as such in Mac OS, but it sends the "insert" usage code even on Apple USB keyboards */ + /* 115 */ SDL_PK_HOME, + /* 116 */ SDL_PK_PAGEUP, + /* 117 */ SDL_PK_DELETE, + /* 118 */ SDL_PK_F4, + /* 119 */ SDL_PK_END, + /* 120 */ SDL_PK_F2, + /* 121 */ SDL_PK_PAGEDOWN, + /* 122 */ SDL_PK_F1, + /* 123 */ SDL_PK_LEFT, + /* 124 */ SDL_PK_RIGHT, + /* 125 */ SDL_PK_DOWN, + /* 126 */ SDL_PK_UP, + /* 127 */ SDL_PK_POWER +}; Index: src/video/quartz/SDL_QuartzVideo.m =================================================================== --- src/video/quartz/SDL_QuartzVideo.m (revision 2741) +++ src/video/quartz/SDL_QuartzVideo.m (working copy) @@ -161,6 +161,7 @@ device->MoveWMCursor = QZ_MoveWMCursor; device->CheckMouseMode = QZ_CheckMouseMode; device->InitOSKeymap = QZ_InitOSKeymap; + device->PKeyName = QZ_PKeyName; device->PumpEvents = QZ_PumpEvents; device->SetCaption = QZ_SetCaption; Index: src/video/SDL_sysvideo.h =================================================================== --- src/video/SDL_sysvideo.h (revision 2741) +++ src/video/SDL_sysvideo.h (working copy) @@ -28,6 +28,7 @@ #define SDL_PROTOTYPES_ONLY #include "SDL_syswm.h" #undef SDL_PROTOTYPES_ONLY +#include "SDL_keysym.h" /* This file prototypes the video driver implementation. This is designed to be easily converted to C++ in the future. @@ -254,6 +255,19 @@ /* Initialize keyboard mapping for this driver */ void (*InitOSKeymap)(_THIS); + + /*! \brief Get a human-readable name for an SDL physical key code, + taking into account the OS' current keyboard mapping. + + This function may return NULL if it is unable to get a key name or if + it is satisfied with the generic name from SDL_pkeynames.h. + + The returned string must be encoded in UTF-8. + + The returned pointer must stay valid at least until the next call to + this function (i.e. it may point to a static internal buffer). + */ + const char *(*PKeyName)(_THIS, SDLPKey pkey); /* Handle any queued OS events */ void (*PumpEvents)(_THIS); Index: src/video/x11/SDL_x11events.c =================================================================== --- src/video/x11/SDL_x11events.c (revision 2741) +++ src/video/x11/SDL_x11events.c (working copy) @@ -47,6 +47,7 @@ #include "SDL_x11wm_c.h" #include "SDL_x11mouse_c.h" #include "SDL_x11events_c.h" +#include "SDL_x11pkeytables.h" /* Define this if you want to debug X11 events */ @@ -57,7 +58,10 @@ static SDLKey MISC_keymap[256]; SDLKey X11_TranslateKeycode(Display *display, KeyCode kc); +static SDLPKey fallbackKeyCodeToSDLPK[248]; +static SDLPKey X11_TranslatePKeycode(_THIS, KeyCode kc); + #ifdef X_HAVE_UTF8_STRING Uint32 Utf8ToUcs4(const Uint8 *utf8) { @@ -420,11 +424,17 @@ if ( keycode ) { keysym.scancode = keycode; keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); + keysym.pkey = X11_TranslatePKeycode(this, keycode); keysym.mod = KMOD_NONE; keysym.unicode = 0; } else { keysym = saved_keysym; } +#if 1 + if (keysym.pkey == SDL_PK_UNKNOWN) { + fprintf(stderr, "The key you just pressed is not recognized by SDL. To help get this fixed, report this to the SDL mailing list or to Christian Walther . X11 KeyCode is %d, X11 KeySym 0x%X.\n", (int)keycode, (unsigned int)XKeycodeToKeysym(SDL_Display, keycode, 0)); + } +#endif /* If we're not doing translation, we're done! */ if ( !SDL_TranslateUNICODE ) { @@ -493,6 +503,7 @@ /* Get the translated SDL virtual keysym */ keysym.scancode = keycode; keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); + keysym.pkey = X11_TranslatePKeycode(this, keycode); keysym.mod = KMOD_NONE; keysym.unicode = 0; @@ -688,6 +699,198 @@ } } +const char *X11_PKeyName(_THIS, SDLPKey pkey) +{ + KeyCode code = 0; + KeySym sym; + SDL_bool ok = SDL_FALSE; + SDL_bool doStringLookup = SDL_TRUE; + static char buffer[27]; + char *bufferPointer = buffer + 1; + XKeyPressedEvent fakeEvent; + + /* for the keypad keys, we use the generic platform-agnostic names provided by SDL_PKeyName() because on my PC their primary KeySyms are not the numbers that I want but XK_KP_Home, XK_KP_Up etc. */ + switch (pkey) { + case SDL_PK_KP_1: + case SDL_PK_KP_2: + case SDL_PK_KP_3: + case SDL_PK_KP_4: + case SDL_PK_KP_5: + case SDL_PK_KP_6: + case SDL_PK_KP_7: + case SDL_PK_KP_8: + case SDL_PK_KP_9: + case SDL_PK_KP_0: + case SDL_PK_KP_PERIOD: + return NULL; + break; + default: + break; /* just to avoid a compiler warning */ + } + + /* look up pkey to get an X11 KeyCode - linear search isn't terribly efficient, but should be OK here */ + while (code < 248 && pkey != this->hidden->currentKeyCodeToSDLPKTable[code]) code++; + if (code == 248) return NULL; + code += 8; + /* get the corresponding KeySym */ + sym = XKeycodeToKeysym(SDL_Display, code, 0); + + /* now try various methods of converting the KeyCode or KeySym to a name until one succeeds */ + + switch (sym) { + /* for some keys, the KeySym name is better than what we would obtain from a string lookup */ + case XK_space: + case XK_BackSpace: + case XK_Tab: + case XK_Return: + case XK_Pause: + case XK_Scroll_Lock: + case XK_Escape: + case XK_Home: + case XK_Left: + case XK_Up: + case XK_Right: + case XK_Down: + case XK_Page_Up: + case XK_Page_Down: + case XK_End: + case XK_Print: + case XK_Insert: + case XK_Menu: + case XK_Help: + case XK_Break: + case XK_Num_Lock: + case XK_Caps_Lock: + case XK_Shift_Lock: + case XK_Delete: + doStringLookup = SDL_FALSE; + break; + /* for some KeySyms, we have our own names (consistent with the generic platform-agnostic names provided by SDL_PKeyName()) */ + case XK_KP_Enter: + case 0x1000003: /* keyboard enter on Mac OS X */ + return "enter"; + case XK_Shift_L: return "left shift"; + case XK_Shift_R: return "right shift"; + case XK_Control_L: return "left ctrl"; + case XK_Control_R: return "right ctrl"; + case XK_Meta_L: return "left meta"; + case XK_Meta_R: return "right meta"; + case XK_Alt_L: return "left alt"; + case XK_Alt_R: return "right alt"; + case XK_Super_L: return "left super"; + case XK_Super_R: return "right super"; + case XK_Hyper_L: return "left hyper"; + case XK_Hyper_R: return "right hyper"; + case XK_ISO_Level3_Shift: + case XK_Mode_switch: + return "alt gr"; /* not sure if this is correct everywhere, it seems so here */ + } + + if (doStringLookup) { + + /* set up a fake event for the two string lookup methods */ + SDL_memset(&fakeEvent, 0, sizeof(fakeEvent)); + fakeEvent.type = KeyPress; + fakeEvent.display = SDL_Display; + fakeEvent.state = 0; + fakeEvent.keycode = code; + + /* try UTF-8 string lookup */ + #ifdef X_HAVE_UTF8_STRING + if (SDL_IC != NULL) { + Status status; + int length; + /* I'm not sure if it's a good idea to use SDL_IC here - could this mess it up somehow (dead key state or so)? X11 experts, please review... */ + length = Xutf8LookupString(SDL_IC, &fakeEvent, bufferPointer, sizeof(buffer)-2, NULL, &status); + if ((status == XLookupChars || status == XLookupBoth) && (unsigned char)bufferPointer[0] >= 0x20) { + /* Xutf8LookupString doesn't seem to zero-terminate its output if it's two bytes */ + bufferPointer[length] = '\0'; + ok = SDL_TRUE; + } + } + #endif + + /* try Latin-1 string lookup */ + if (!ok) { + char latin1Buffer[5]; + int length; + length = XLookupString(&fakeEvent, latin1Buffer, sizeof(latin1Buffer), NULL, NULL); + if (length > 0 && (unsigned char)latin1Buffer[0] >= 0x20) { + /* convert Latin-1 to UTF-8 - luckily Unicode code points 128-255 are identical to Latin-1 */ + unsigned char *src = (unsigned char *)latin1Buffer; + unsigned char *dest = (unsigned char *)bufferPointer; + for (; length > 0; length--) { + if (*src < 128) { + *dest++ = *src; + } + else { + *dest++ = (0xC0 | (*src >> 6)); + *dest++ = (0x80 | (*src & 0x3F)); + } + src++; + } + *dest = '\0'; + ok = SDL_TRUE; + } + } + + } + + /* try KeySym name lookup */ + if (!ok) { + if (sym != NoSymbol) { + const char *string = XKeysymToString(sym); + if (string != NULL) { + /* string is in "Host Portable Character Encoding", so it is valid UTF-8 if the original encoding is ASCII-compatible (which is hopefully the case everywhere today) */ + SDL_strlcpy(bufferPointer, string, sizeof(buffer)-2); + /* for consistency with the generic platform-agnostic names provided by SDL_PKeyName(), convert the name to lower case and replace underscore by space, unless it's a function key */ + if (sym < XK_F1 || sym > XK_F35) { + char *p; + SDL_strlwr(bufferPointer); + while ((p = SDL_strchr(bufferPointer, '_')) != NULL) *p = ' '; + } + ok = SDL_TRUE; + } + } + } + + /* if still no success, give up */ + if (!ok) return NULL; + + /* letter keys on latin keyboards are normally labeled in upper case (and probably on others too, so if you happen to know for sure, please adapt this) */ + if (bufferPointer[1] == '\0' && bufferPointer[0] >= 0x61 && bufferPointer[0] <= 0x7A) { + bufferPointer[0] -= 32; + } + + /* if it's a keypad key, add [] around the name */ + switch (pkey) { + case SDL_PK_KP_DIVIDE: + case SDL_PK_KP_MULTIPLY: + case SDL_PK_KP_MINUS: + case SDL_PK_KP_PLUS: + case SDL_PK_KP_1: + case SDL_PK_KP_2: + case SDL_PK_KP_3: + case SDL_PK_KP_4: + case SDL_PK_KP_5: + case SDL_PK_KP_6: + case SDL_PK_KP_7: + case SDL_PK_KP_8: + case SDL_PK_KP_9: + case SDL_PK_KP_0: + case SDL_PK_KP_PERIOD: + case SDL_PK_KP_EQUALS: + SDL_strlcat(bufferPointer, "]", sizeof(buffer)-1); + bufferPointer--; + bufferPointer[0] = '['; + break; + default: /* just to avoid a compiler warning */ + break; + } + + return bufferPointer; +} + void X11_InitKeymap(void) { int i; @@ -820,6 +1023,70 @@ MISC_keymap[XK_Hyper_R&0xFF] = SDLK_MENU; /* Windows "Menu" key */ } +/* determine which X11 KeyCode to SDL physical key code table to use */ +static void X11_InitPKeymap(_THIS) +{ + SDLPKey **table; + + /* A random collection of KeySym/SDLPKey pairs that should be valid in any keyboard mapping (if this isn't the case on yours, please adjust). Using XKeysymToKeycode on these KeySyms creates a "fingerprint" of the X server's key-to-KeyCode mapping which is then matched against all our predefined KeyCodeToSDLPK tables to find the right one (if any). */ + struct { KeySym sym; SDLPKey pkey; } fingerprint[] = { + {XK_Tab, SDL_PK_TAB}, + {XK_Return, SDL_PK_RETURN}, + {XK_Escape, SDL_PK_ESCAPE}, + {XK_space, SDL_PK_SPACE} + }; + + SDL_bool ok; + int i; + KeyCode code; + + for (table = keyCodeToSDLPKTables; *table != NULL; table++) { + ok = SDL_TRUE; + for (i = 0; i < SDL_arraysize(fingerprint); i++) { + code = XKeysymToKeycode(SDL_Display, fingerprint[i].sym); + if (code != 0 && (*table)[code - 8] != fingerprint[i].pkey) { + ok = SDL_FALSE; + break; + } + } + if (ok) break; + } + if (*table != NULL) { + /* found a suitable one among the predefined tables */ + this->hidden->currentKeyCodeToSDLPKTable = *table; + } + else { + /* no suitable table found - build a makeshift table based on the KeySyms, assuming a US keyboard mapping */ + KeySym sym; + SDLPKey pkey; + int start, end; + +#if 1 + fprintf(stderr, "The key codes of your X server are unknown to SDL. Keys may not be recognized properly. To help get this fixed, report this to the SDL mailing list or to Christian Walther .\n"); +#endif + for (code = 255; code >= 8; code--) { + sym = XKeycodeToKeysym(SDL_Display, code, 0); + pkey = SDL_PK_UNKNOWN; + /* do a binary search for sym in fallbackKeySymToSDLPK */ + start = -1; + end = SDL_arraysize(fallbackKeySymToSDLPK); + /* invariant: fallbackKeySymToSDLPK[start].sym < sym < fallbackKeySymToSDLPK[end].sym + (imagine ...[-1] = -inf and ...[arraysize] = inf, these entries needn't be there in reality because they're never accessed) */ + while (end > start + 1) { + i = (start + end)/2; + if (fallbackKeySymToSDLPK[i].sym == sym) { + pkey = fallbackKeySymToSDLPK[i].pkey; + break; + } + else if (fallbackKeySymToSDLPK[i].sym < sym) start = i; + else end = i; + } + fallbackKeyCodeToSDLPK[code - 8] = pkey; + } + this->hidden->currentKeyCodeToSDLPKTable = fallbackKeyCodeToSDLPK; + } +} + /* Get the translated SDL virtual keysym */ SDLKey X11_TranslateKeycode(Display *display, KeyCode kc) { @@ -899,6 +1166,12 @@ return key; } +/* Get the translated SDL physical key code */ +static SDLPKey X11_TranslatePKeycode(_THIS, KeyCode kc) +{ + return this->hidden->currentKeyCodeToSDLPKTable[kc - 8]; +} + /* X11 modifier masks for various keys */ static unsigned meta_l_mask, meta_r_mask, alt_l_mask, alt_r_mask; static unsigned num_mask, mode_switch_mask; @@ -1115,6 +1388,7 @@ void X11_InitOSKeymap(_THIS) { X11_InitKeymap(); + X11_InitPKeymap(this); } void X11_SaveScreenSaver(Display *display, int *saved_timeout, BOOL *dpms) Index: src/video/x11/SDL_x11video.c =================================================================== --- src/video/x11/SDL_x11video.c (revision 2741) +++ src/video/x11/SDL_x11video.c (working copy) @@ -163,6 +163,7 @@ device->WarpWMCursor = X11_WarpWMCursor; device->CheckMouseMode = X11_CheckMouseMode; device->InitOSKeymap = X11_InitOSKeymap; + device->PKeyName = X11_PKeyName; device->PumpEvents = X11_PumpEvents; device->free = X11_DeleteDevice; Index: src/video/x11/SDL_x11pkeytables.h =================================================================== --- src/video/x11/SDL_x11pkeytables.h (revision 0) +++ src/video/x11/SDL_x11pkeytables.h (revision 0) @@ -0,0 +1,672 @@ +/* Used to build a makeshift translation table based on the KeySyms when none + of the predefined KeyCode-to-SDLPK tables (below) fits. This is *not* + correct anywhere but on a US mapping, but it's better than nothing. + + This list is sorted by KeySym to allow a binary search. +*/ +static struct {KeySym sym; SDLPKey pkey; } fallbackKeySymToSDLPK[] = { + /* 0x00xx */ + { XK_space, SDL_PK_SPACE }, + { XK_apostrophe, SDL_PK_APOSTROPHE }, + { XK_comma, SDL_PK_COMMA }, + { XK_minus, SDL_PK_HYPHENMINUS }, + { XK_period, SDL_PK_PERIOD }, + { XK_slash, SDL_PK_SLASH }, + { XK_0, SDL_PK_0 }, + { XK_1, SDL_PK_1 }, + { XK_2, SDL_PK_2 }, + { XK_3, SDL_PK_3 }, + { XK_4, SDL_PK_4 }, + { XK_5, SDL_PK_5 }, + { XK_6, SDL_PK_6 }, + { XK_7, SDL_PK_7 }, + { XK_8, SDL_PK_8 }, + { XK_9, SDL_PK_9 }, + { XK_semicolon, SDL_PK_SEMICOLON }, + { XK_less, SDL_PK_NONUSBACKSLASH }, + { XK_equal, SDL_PK_EQUALS }, + { XK_bracketleft, SDL_PK_LEFTBRACKET }, + { XK_backslash, SDL_PK_BACKSLASH }, + { XK_bracketright, SDL_PK_RIGHTBRACKET }, + { XK_grave, SDL_PK_GRAVE }, + { XK_a, SDL_PK_A }, + { XK_b, SDL_PK_B }, + { XK_c, SDL_PK_C }, + { XK_d, SDL_PK_D }, + { XK_e, SDL_PK_E }, + { XK_f, SDL_PK_F }, + { XK_g, SDL_PK_G }, + { XK_h, SDL_PK_H }, + { XK_i, SDL_PK_I }, + { XK_j, SDL_PK_J }, + { XK_k, SDL_PK_K }, + { XK_l, SDL_PK_L }, + { XK_m, SDL_PK_M }, + { XK_n, SDL_PK_N }, + { XK_o, SDL_PK_O }, + { XK_p, SDL_PK_P }, + { XK_q, SDL_PK_Q }, + { XK_r, SDL_PK_R }, + { XK_s, SDL_PK_S }, + { XK_t, SDL_PK_T }, + { XK_u, SDL_PK_U }, + { XK_v, SDL_PK_V }, + { XK_w, SDL_PK_W }, + { XK_x, SDL_PK_X }, + { XK_y, SDL_PK_Y }, + { XK_z, SDL_PK_Z }, + { XK_section, SDL_PK_NONUSBACKSLASH }, + + /* 0xFExx */ + { XK_ISO_Level3_Shift, SDL_PK_RALT }, + + /* 0xFFxx */ + { XK_BackSpace, SDL_PK_BACKSPACE }, + { XK_Tab, SDL_PK_TAB }, + { XK_Return, SDL_PK_RETURN }, + { XK_Pause, SDL_PK_PAUSE }, + { XK_Scroll_Lock, SDL_PK_SCROLLLOCK }, + { XK_Escape, SDL_PK_ESCAPE }, + { XK_Home, SDL_PK_HOME }, + { XK_Left, SDL_PK_LEFT }, + { XK_Up, SDL_PK_UP }, + { XK_Right, SDL_PK_RIGHT }, + { XK_Down, SDL_PK_DOWN }, + { XK_Page_Up, SDL_PK_PAGEUP }, + { XK_Page_Down, SDL_PK_PAGEDOWN }, + { XK_End, SDL_PK_END }, + { XK_Print, SDL_PK_PRINTSCREEN }, + { XK_Insert, SDL_PK_INSERT }, + { XK_Menu, SDL_PK_APPLICATION }, + { XK_Break, SDL_PK_PAUSE }, + { XK_Mode_switch, SDL_PK_RALT }, + { XK_Num_Lock, SDL_PK_KP_NUMLOCKCLEAR }, + { XK_KP_Enter, SDL_PK_KP_ENTER }, + { XK_KP_Home, SDL_PK_KP_7 }, + { XK_KP_Left, SDL_PK_KP_4 }, + { XK_KP_Up, SDL_PK_KP_8 }, + { XK_KP_Right, SDL_PK_KP_6 }, + { XK_KP_Down, SDL_PK_KP_2 }, + { XK_KP_Page_Up, SDL_PK_KP_9 }, + { XK_KP_Page_Down, SDL_PK_KP_3 }, + { XK_KP_End, SDL_PK_KP_1 }, + { XK_KP_Begin, SDL_PK_KP_5 }, + { XK_KP_Insert, SDL_PK_KP_0 }, + { XK_KP_Delete, SDL_PK_KP_PERIOD }, + { XK_KP_Multiply, SDL_PK_KP_MULTIPLY }, + { XK_KP_Add, SDL_PK_KP_PLUS }, + { XK_KP_Separator, SDL_PK_KP_PERIOD }, + { XK_KP_Subtract, SDL_PK_KP_MINUS }, + { XK_KP_Decimal, SDL_PK_KP_PERIOD }, + { XK_KP_Divide, SDL_PK_KP_DIVIDE }, + { XK_KP_0, SDL_PK_KP_0 }, + { XK_KP_1, SDL_PK_KP_1 }, + { XK_KP_2, SDL_PK_KP_2 }, + { XK_KP_3, SDL_PK_KP_3 }, + { XK_KP_4, SDL_PK_KP_4 }, + { XK_KP_5, SDL_PK_KP_5 }, + { XK_KP_6, SDL_PK_KP_6 }, + { XK_KP_7, SDL_PK_KP_7 }, + { XK_KP_8, SDL_PK_KP_8 }, + { XK_KP_9, SDL_PK_KP_9 }, + { XK_KP_Equal, SDL_PK_KP_EQUALS }, + { XK_F1, SDL_PK_F1 }, + { XK_F2, SDL_PK_F2 }, + { XK_F3, SDL_PK_F3 }, + { XK_F4, SDL_PK_F4 }, + { XK_F5, SDL_PK_F5 }, + { XK_F6, SDL_PK_F6 }, + { XK_F7, SDL_PK_F7 }, + { XK_F8, SDL_PK_F8 }, + { XK_F9, SDL_PK_F9 }, + { XK_F10, SDL_PK_F10 }, + { XK_F11, SDL_PK_F11 }, + { XK_F12, SDL_PK_F12 }, + { XK_F13, SDL_PK_F13 }, + { XK_F14, SDL_PK_F14 }, + { XK_F15, SDL_PK_F15 }, + { XK_F16, SDL_PK_F16 }, + { XK_F17, SDL_PK_F17 }, + { XK_F18, SDL_PK_F18 }, + { XK_F19, SDL_PK_F19 }, + { XK_F20, SDL_PK_F20 }, + { XK_F21, SDL_PK_F21 }, + { XK_F22, SDL_PK_F22 }, + { XK_F23, SDL_PK_F23 }, + { XK_F24, SDL_PK_F24 }, + { XK_Shift_L, SDL_PK_LSHIFT }, + { XK_Shift_R, SDL_PK_RSHIFT }, + { XK_Control_L, SDL_PK_LCTRL }, + { XK_Control_R, SDL_PK_RCTRL }, + { XK_Caps_Lock, SDL_PK_CAPSLOCK }, + { XK_Shift_Lock, SDL_PK_CAPSLOCK }, + { XK_Meta_L, SDL_PK_LGUI }, + { XK_Meta_R, SDL_PK_RGUI }, + { XK_Alt_L, SDL_PK_LALT }, + { XK_Alt_R, SDL_PK_RALT }, + { XK_Super_L, SDL_PK_LGUI }, + { XK_Super_R, SDL_PK_RGUI }, + { XK_Delete, SDL_PK_DELETE } +}; + +/*---------------------------------------------------------------------------*/ + +/* KeyCode-to-SDLPK translation tables for various X servers. Which one to use + is decided in X11_InitPKeymap(). +*/ + +/* These are just Mac virtual key codes + 8 (see SDL/src/video/quartz/ + SDL_QuartzKeys.h for more info). Observed to work with Apple X11 on Mac OS + X 10.4. May also work on older Linux distributions on Mac hardware. +*/ +static SDLPKey macKeyCodeToSDLPK[248] = { + /* 8 */ SDL_PK_A, + /* 9 */ SDL_PK_S, + /* 10 */ SDL_PK_D, + /* 11 */ SDL_PK_F, + /* 12 */ SDL_PK_H, + /* 13 */ SDL_PK_G, + /* 14 */ SDL_PK_Z, + /* 15 */ SDL_PK_X, + /* 16 */ SDL_PK_C, + /* 17 */ SDL_PK_V, + /* 18 */ SDL_PK_GRAVE, + /* 19 */ SDL_PK_B, + /* 20 */ SDL_PK_Q, + /* 21 */ SDL_PK_W, + /* 22 */ SDL_PK_E, + /* 23 */ SDL_PK_R, + /* 24 */ SDL_PK_Y, + /* 25 */ SDL_PK_T, + /* 26 */ SDL_PK_1, + /* 27 */ SDL_PK_2, + /* 28 */ SDL_PK_3, + /* 29 */ SDL_PK_4, + /* 30 */ SDL_PK_6, + /* 31 */ SDL_PK_5, + /* 32 */ SDL_PK_EQUALS, + /* 33 */ SDL_PK_9, + /* 34 */ SDL_PK_7, + /* 35 */ SDL_PK_HYPHENMINUS, + /* 36 */ SDL_PK_8, + /* 37 */ SDL_PK_0, + /* 38 */ SDL_PK_RIGHTBRACKET, + /* 39 */ SDL_PK_O, + /* 40 */ SDL_PK_U, + /* 41 */ SDL_PK_LEFTBRACKET, + /* 42 */ SDL_PK_I, + /* 43 */ SDL_PK_P, + /* 44 */ SDL_PK_RETURN, + /* 45 */ SDL_PK_L, + /* 46 */ SDL_PK_J, + /* 47 */ SDL_PK_APOSTROPHE, + /* 48 */ SDL_PK_K, + /* 49 */ SDL_PK_SEMICOLON, + /* 50 */ SDL_PK_BACKSLASH, + /* 51 */ SDL_PK_COMMA, + /* 52 */ SDL_PK_SLASH, + /* 53 */ SDL_PK_N, + /* 54 */ SDL_PK_M, + /* 55 */ SDL_PK_PERIOD, + /* 56 */ SDL_PK_TAB, + /* 57 */ SDL_PK_SPACE, + /* 58 */ SDL_PK_NONUSBACKSLASH, + /* 59 */ SDL_PK_BACKSPACE, + /* 60 */ SDL_PK_KP_ENTER, + /* 61 */ SDL_PK_ESCAPE, + /* 62 */ SDL_PK_RGUI, + /* 63 */ SDL_PK_LGUI, + /* 64 */ SDL_PK_LSHIFT, + /* 65 */ SDL_PK_CAPSLOCK, + /* 66 */ SDL_PK_LALT, + /* 67 */ SDL_PK_LCTRL, + /* 68 */ SDL_PK_RSHIFT, + /* 69 */ SDL_PK_RALT, + /* 70 */ SDL_PK_RCTRL, + /* 71 */ SDL_PK_NONE, + /* 72 */ SDL_PK_UNKNOWN, + /* 73 */ SDL_PK_KP_PERIOD, + /* 74 */ SDL_PK_UNKNOWN, + /* 75 */ SDL_PK_KP_MULTIPLY, + /* 76 */ SDL_PK_UNKNOWN, + /* 77 */ SDL_PK_KP_PLUS, + /* 78 */ SDL_PK_UNKNOWN, + /* 79 */ SDL_PK_KP_NUMLOCKCLEAR, + /* 80 */ SDL_PK_VOLUMEUP, + /* 81 */ SDL_PK_VOLUMEDOWN, + /* 82 */ SDL_PK_MUTE, + /* 83 */ SDL_PK_KP_DIVIDE, + /* 84 */ SDL_PK_KP_ENTER, + /* 85 */ SDL_PK_UNKNOWN, + /* 86 */ SDL_PK_KP_MINUS, + /* 87 */ SDL_PK_UNKNOWN, + /* 88 */ SDL_PK_UNKNOWN, + /* 89 */ SDL_PK_KP_EQUALS, + /* 90 */ SDL_PK_KP_0, + /* 91 */ SDL_PK_KP_1, + /* 92 */ SDL_PK_KP_2, + /* 93 */ SDL_PK_KP_3, + /* 94 */ SDL_PK_KP_4, + /* 95 */ SDL_PK_KP_5, + /* 96 */ SDL_PK_KP_6, + /* 97 */ SDL_PK_KP_7, + /* 98 */ SDL_PK_UNKNOWN, + /* 99 */ SDL_PK_KP_8, + /* 100 */ SDL_PK_KP_9, + /* 101 */ SDL_PK_INTERNATIONAL3, + /* 102 */ SDL_PK_INTERNATIONAL1, + /* 103 */ SDL_PK_KP_COMMA, + /* 104 */ SDL_PK_F5, + /* 105 */ SDL_PK_F6, + /* 106 */ SDL_PK_F7, + /* 107 */ SDL_PK_F3, + /* 108 */ SDL_PK_F8, + /* 109 */ SDL_PK_F9, + /* 110 */ SDL_PK_LANG2, + /* 111 */ SDL_PK_F11, + /* 112 */ SDL_PK_LANG1, + /* 113 */ SDL_PK_PRINTSCREEN, + /* 114 */ SDL_PK_F16, + /* 115 */ SDL_PK_SCROLLLOCK, + /* 116 */ SDL_PK_UNKNOWN, + /* 117 */ SDL_PK_F10, + /* 118 */ SDL_PK_APPLICATION, + /* 119 */ SDL_PK_F12, + /* 120 */ SDL_PK_UNKNOWN, + /* 121 */ SDL_PK_PAUSE, + /* 122 */ SDL_PK_INSERT, + /* 123 */ SDL_PK_HOME, + /* 124 */ SDL_PK_PAGEUP, + /* 125 */ SDL_PK_DELETE, + /* 126 */ SDL_PK_F4, + /* 127 */ SDL_PK_END, + /* 128 */ SDL_PK_F2, + /* 129 */ SDL_PK_PAGEDOWN, + /* 130 */ SDL_PK_F1, + /* 131 */ SDL_PK_LEFT, + /* 132 */ SDL_PK_RIGHT, + /* 133 */ SDL_PK_DOWN, + /* 134 */ SDL_PK_UP, + /* 135 */ SDL_PK_POWER, + /* 136 */ SDL_PK_UNKNOWN, /* codes higher than 135 shouldn't occur as Mac virtual keycodes only go to 127 */ + /* 137 */ SDL_PK_UNKNOWN, + /* 138 */ SDL_PK_UNKNOWN, + /* 139 */ SDL_PK_UNKNOWN, + /* 140 */ SDL_PK_UNKNOWN, + /* 141 */ SDL_PK_UNKNOWN, + /* 142 */ SDL_PK_UNKNOWN, + /* 143 */ SDL_PK_UNKNOWN, + /* 144 */ SDL_PK_UNKNOWN, + /* 145 */ SDL_PK_UNKNOWN, + /* 146 */ SDL_PK_UNKNOWN, + /* 147 */ SDL_PK_UNKNOWN, + /* 148 */ SDL_PK_UNKNOWN, + /* 149 */ SDL_PK_UNKNOWN, + /* 150 */ SDL_PK_UNKNOWN, + /* 151 */ SDL_PK_UNKNOWN, + /* 152 */ SDL_PK_UNKNOWN, + /* 153 */ SDL_PK_UNKNOWN, + /* 154 */ SDL_PK_UNKNOWN, + /* 155 */ SDL_PK_UNKNOWN, + /* 156 */ SDL_PK_UNKNOWN, + /* 157 */ SDL_PK_UNKNOWN, + /* 158 */ SDL_PK_UNKNOWN, + /* 159 */ SDL_PK_UNKNOWN, + /* 160 */ SDL_PK_UNKNOWN, + /* 161 */ SDL_PK_UNKNOWN, + /* 162 */ SDL_PK_UNKNOWN, + /* 163 */ SDL_PK_UNKNOWN, + /* 164 */ SDL_PK_UNKNOWN, + /* 165 */ SDL_PK_UNKNOWN, + /* 166 */ SDL_PK_UNKNOWN, + /* 167 */ SDL_PK_UNKNOWN, + /* 168 */ SDL_PK_UNKNOWN, + /* 169 */ SDL_PK_UNKNOWN, + /* 170 */ SDL_PK_UNKNOWN, + /* 171 */ SDL_PK_UNKNOWN, + /* 172 */ SDL_PK_UNKNOWN, + /* 173 */ SDL_PK_UNKNOWN, + /* 174 */ SDL_PK_UNKNOWN, + /* 175 */ SDL_PK_UNKNOWN, + /* 176 */ SDL_PK_UNKNOWN, + /* 177 */ SDL_PK_UNKNOWN, + /* 178 */ SDL_PK_UNKNOWN, + /* 179 */ SDL_PK_UNKNOWN, + /* 180 */ SDL_PK_UNKNOWN, + /* 181 */ SDL_PK_UNKNOWN, + /* 182 */ SDL_PK_UNKNOWN, + /* 183 */ SDL_PK_UNKNOWN, + /* 184 */ SDL_PK_UNKNOWN, + /* 185 */ SDL_PK_UNKNOWN, + /* 186 */ SDL_PK_UNKNOWN, + /* 187 */ SDL_PK_UNKNOWN, + /* 188 */ SDL_PK_UNKNOWN, + /* 189 */ SDL_PK_UNKNOWN, + /* 190 */ SDL_PK_UNKNOWN, + /* 191 */ SDL_PK_UNKNOWN, + /* 192 */ SDL_PK_UNKNOWN, + /* 193 */ SDL_PK_UNKNOWN, + /* 194 */ SDL_PK_UNKNOWN, + /* 195 */ SDL_PK_UNKNOWN, + /* 196 */ SDL_PK_UNKNOWN, + /* 197 */ SDL_PK_UNKNOWN, + /* 198 */ SDL_PK_UNKNOWN, + /* 199 */ SDL_PK_UNKNOWN, + /* 200 */ SDL_PK_UNKNOWN, + /* 201 */ SDL_PK_UNKNOWN, + /* 202 */ SDL_PK_UNKNOWN, + /* 203 */ SDL_PK_UNKNOWN, + /* 204 */ SDL_PK_UNKNOWN, + /* 205 */ SDL_PK_UNKNOWN, + /* 206 */ SDL_PK_UNKNOWN, + /* 207 */ SDL_PK_UNKNOWN, + /* 208 */ SDL_PK_UNKNOWN, + /* 209 */ SDL_PK_UNKNOWN, + /* 210 */ SDL_PK_UNKNOWN, + /* 211 */ SDL_PK_UNKNOWN, + /* 212 */ SDL_PK_UNKNOWN, + /* 213 */ SDL_PK_UNKNOWN, + /* 214 */ SDL_PK_UNKNOWN, + /* 215 */ SDL_PK_UNKNOWN, + /* 216 */ SDL_PK_UNKNOWN, + /* 217 */ SDL_PK_UNKNOWN, + /* 218 */ SDL_PK_UNKNOWN, + /* 219 */ SDL_PK_UNKNOWN, + /* 220 */ SDL_PK_UNKNOWN, + /* 221 */ SDL_PK_UNKNOWN, + /* 222 */ SDL_PK_UNKNOWN, + /* 223 */ SDL_PK_UNKNOWN, + /* 224 */ SDL_PK_UNKNOWN, + /* 225 */ SDL_PK_UNKNOWN, + /* 226 */ SDL_PK_UNKNOWN, + /* 227 */ SDL_PK_UNKNOWN, + /* 228 */ SDL_PK_UNKNOWN, + /* 229 */ SDL_PK_UNKNOWN, + /* 230 */ SDL_PK_UNKNOWN, + /* 231 */ SDL_PK_UNKNOWN, + /* 232 */ SDL_PK_UNKNOWN, + /* 233 */ SDL_PK_UNKNOWN, + /* 234 */ SDL_PK_UNKNOWN, + /* 235 */ SDL_PK_UNKNOWN, + /* 236 */ SDL_PK_UNKNOWN, + /* 237 */ SDL_PK_UNKNOWN, + /* 238 */ SDL_PK_UNKNOWN, + /* 239 */ SDL_PK_UNKNOWN, + /* 240 */ SDL_PK_UNKNOWN, + /* 241 */ SDL_PK_UNKNOWN, + /* 242 */ SDL_PK_UNKNOWN, + /* 243 */ SDL_PK_UNKNOWN, + /* 244 */ SDL_PK_UNKNOWN, + /* 245 */ SDL_PK_UNKNOWN, + /* 246 */ SDL_PK_UNKNOWN, + /* 247 */ SDL_PK_UNKNOWN, + /* 248 */ SDL_PK_UNKNOWN, + /* 249 */ SDL_PK_UNKNOWN, + /* 250 */ SDL_PK_UNKNOWN, + /* 251 */ SDL_PK_UNKNOWN, + /* 252 */ SDL_PK_UNKNOWN, + /* 253 */ SDL_PK_UNKNOWN, + /* 254 */ SDL_PK_UNKNOWN, + /* 255 */ SDL_PK_UNKNOWN +}; + +/* Found mostly by experimentation with X.org on Linux (Fedora Core 3 and + Ubuntu Dapper) on PC and PPC Mac hardware, some parts (especially about + the "multimedia"/"internet" keys) from various sources on the web. +*/ +static SDLPKey xorgLinuxKeyCodeToSDLPK[248] = { + /* 8 */ SDL_PK_UNKNOWN, + /* 9 */ SDL_PK_ESCAPE, + /* 10 */ SDL_PK_1, + /* 11 */ SDL_PK_2, + /* 12 */ SDL_PK_3, + /* 13 */ SDL_PK_4, + /* 14 */ SDL_PK_5, + /* 15 */ SDL_PK_6, + /* 16 */ SDL_PK_7, + /* 17 */ SDL_PK_8, + /* 18 */ SDL_PK_9, + /* 19 */ SDL_PK_0, + /* 20 */ SDL_PK_HYPHENMINUS, + /* 21 */ SDL_PK_EQUALS, + /* 22 */ SDL_PK_BACKSPACE, + /* 23 */ SDL_PK_TAB, + /* 24 */ SDL_PK_Q, + /* 25 */ SDL_PK_W, + /* 26 */ SDL_PK_E, + /* 27 */ SDL_PK_R, + /* 28 */ SDL_PK_T, + /* 29 */ SDL_PK_Y, + /* 30 */ SDL_PK_U, + /* 31 */ SDL_PK_I, + /* 32 */ SDL_PK_O, + /* 33 */ SDL_PK_P, + /* 34 */ SDL_PK_LEFTBRACKET, + /* 35 */ SDL_PK_RIGHTBRACKET, + /* 36 */ SDL_PK_RETURN, + /* 37 */ SDL_PK_LCTRL, + /* 38 */ SDL_PK_A, + /* 39 */ SDL_PK_S, + /* 40 */ SDL_PK_D, + /* 41 */ SDL_PK_F, + /* 42 */ SDL_PK_G, + /* 43 */ SDL_PK_H, + /* 44 */ SDL_PK_J, + /* 45 */ SDL_PK_K, + /* 46 */ SDL_PK_L, + /* 47 */ SDL_PK_SEMICOLON, + /* 48 */ SDL_PK_APOSTROPHE, + /* 49 */ SDL_PK_GRAVE, + /* 50 */ SDL_PK_LSHIFT, + /* 51 */ SDL_PK_BACKSLASH, + /* 52 */ SDL_PK_Z, + /* 53 */ SDL_PK_X, + /* 54 */ SDL_PK_C, + /* 55 */ SDL_PK_V, + /* 56 */ SDL_PK_B, + /* 57 */ SDL_PK_N, + /* 58 */ SDL_PK_M, + /* 59 */ SDL_PK_COMMA, + /* 60 */ SDL_PK_PERIOD, + /* 61 */ SDL_PK_SLASH, + /* 62 */ SDL_PK_RSHIFT, + /* 63 */ SDL_PK_KP_MULTIPLY, + /* 64 */ SDL_PK_LALT, + /* 65 */ SDL_PK_SPACE, + /* 66 */ SDL_PK_CAPSLOCK, + /* 67 */ SDL_PK_F1, + /* 68 */ SDL_PK_F2, + /* 69 */ SDL_PK_F3, + /* 70 */ SDL_PK_F4, + /* 71 */ SDL_PK_F5, + /* 72 */ SDL_PK_F6, + /* 73 */ SDL_PK_F7, + /* 74 */ SDL_PK_F8, + /* 75 */ SDL_PK_F9, + /* 76 */ SDL_PK_F10, + /* 77 */ SDL_PK_KP_NUMLOCKCLEAR, + /* 78 */ SDL_PK_SCROLLLOCK, + /* 79 */ SDL_PK_KP_7, + /* 80 */ SDL_PK_KP_8, + /* 81 */ SDL_PK_KP_9, + /* 82 */ SDL_PK_KP_MINUS, + /* 83 */ SDL_PK_KP_4, + /* 84 */ SDL_PK_KP_5, + /* 85 */ SDL_PK_KP_6, + /* 86 */ SDL_PK_KP_PLUS, + /* 87 */ SDL_PK_KP_1, + /* 88 */ SDL_PK_KP_2, + /* 89 */ SDL_PK_KP_3, + /* 90 */ SDL_PK_KP_0, + /* 91 */ SDL_PK_KP_PERIOD, + /* 92 */ SDL_PK_SYSREQ, + /* 93 */ SDL_PK_UNKNOWN, /* is translated to XK_Mode_switch by my X server, but I have no keyboard that generates this code, so I don't know what the correct SDL_PK_* for it is */ + /* 94 */ SDL_PK_NONUSBACKSLASH, + /* 95 */ SDL_PK_F11, + /* 96 */ SDL_PK_F12, + /* 97 */ SDL_PK_HOME, + /* 98 */ SDL_PK_UP, + /* 99 */ SDL_PK_PAGEUP, + /* 100 */ SDL_PK_LEFT, + /* 101 */ SDL_PK_BRIGHTNESSDOWN, /* on PowerBook G4 */ + /* 102 */ SDL_PK_RIGHT, + /* 103 */ SDL_PK_END, + /* 104 */ SDL_PK_DOWN, + /* 105 */ SDL_PK_PAGEDOWN, + /* 106 */ SDL_PK_INSERT, + /* 107 */ SDL_PK_DELETE, + /* 108 */ SDL_PK_KP_ENTER, + /* 109 */ SDL_PK_RCTRL, + /* 110 */ SDL_PK_PAUSE, + /* 111 */ SDL_PK_PRINTSCREEN, + /* 112 */ SDL_PK_KP_DIVIDE, + /* 113 */ SDL_PK_RALT, + /* 114 */ SDL_PK_UNKNOWN, + /* 115 */ SDL_PK_LGUI, + /* 116 */ SDL_PK_RGUI, + /* 117 */ SDL_PK_APPLICATION, + /* 118 */ SDL_PK_F13, + /* 119 */ SDL_PK_F14, + /* 120 */ SDL_PK_F15, + /* 121 */ SDL_PK_F16, + /* 122 */ SDL_PK_F17, + /* 123 */ SDL_PK_UNKNOWN, + /* 124 */ SDL_PK_UNKNOWN, /* is translated to XK_ISO_Level3_Shift by my X server, but I have no keyboard that generates this code, so I don't know what the correct SDL_PK_* for it is */ + /* 125 */ SDL_PK_UNKNOWN, + /* 126 */ SDL_PK_KP_EQUALS, + /* 127 */ SDL_PK_UNKNOWN, + /* 128 */ SDL_PK_UNKNOWN, + /* 129 */ SDL_PK_UNKNOWN, + /* 130 */ SDL_PK_UNKNOWN, + /* 131 */ SDL_PK_UNKNOWN, + /* 132 */ SDL_PK_UNKNOWN, + /* 133 */ SDL_PK_INTERNATIONAL3, /* Yen */ + /* 134 */ SDL_PK_UNKNOWN, + /* 135 */ SDL_PK_AGAIN, + /* 136 */ SDL_PK_UNDO, + /* 137 */ SDL_PK_UNKNOWN, + /* 138 */ SDL_PK_UNKNOWN, + /* 139 */ SDL_PK_UNKNOWN, + /* 140 */ SDL_PK_UNKNOWN, + /* 141 */ SDL_PK_UNKNOWN, + /* 142 */ SDL_PK_UNKNOWN, + /* 143 */ SDL_PK_UNKNOWN, + /* 144 */ SDL_PK_AUDIOPREV, + /* 145 */ SDL_PK_UNKNOWN, + /* 146 */ SDL_PK_UNKNOWN, + /* 147 */ SDL_PK_UNKNOWN, + /* 148 */ SDL_PK_UNKNOWN, + /* 149 */ SDL_PK_UNKNOWN, + /* 150 */ SDL_PK_UNKNOWN, + /* 151 */ SDL_PK_UNKNOWN, + /* 152 */ SDL_PK_UNKNOWN, + /* 153 */ SDL_PK_AUDIONEXT, + /* 154 */ SDL_PK_UNKNOWN, + /* 155 */ SDL_PK_UNKNOWN, + /* 156 */ SDL_PK_UNKNOWN, + /* 157 */ SDL_PK_KP_EQUALS, /* on PowerBook G4 */ + /* 158 */ SDL_PK_UNKNOWN, + /* 159 */ SDL_PK_UNKNOWN, + /* 160 */ SDL_PK_MUTE, + /* 161 */ SDL_PK_CALC, + /* 162 */ SDL_PK_AUDIOPLAY, + /* 163 */ SDL_PK_UNKNOWN, + /* 164 */ SDL_PK_AUDIOSTOP, + /* 165 */ SDL_PK_UNKNOWN, + /* 166 */ SDL_PK_UNKNOWN, + /* 167 */ SDL_PK_UNKNOWN, + /* 168 */ SDL_PK_UNKNOWN, + /* 169 */ SDL_PK_UNKNOWN, + /* 170 */ SDL_PK_UNKNOWN, + /* 171 */ SDL_PK_UNKNOWN, + /* 172 */ SDL_PK_UNKNOWN, + /* 173 */ SDL_PK_UNKNOWN, + /* 174 */ SDL_PK_VOLUMEDOWN, + /* 175 */ SDL_PK_UNKNOWN, + /* 176 */ SDL_PK_VOLUMEUP, + /* 177 */ SDL_PK_UNKNOWN, + /* 178 */ SDL_PK_WWW, + /* 179 */ SDL_PK_UNKNOWN, + /* 180 */ SDL_PK_UNKNOWN, + /* 181 */ SDL_PK_UNKNOWN, + /* 182 */ SDL_PK_UNKNOWN, + /* 183 */ SDL_PK_UNKNOWN, + /* 184 */ SDL_PK_UNKNOWN, + /* 185 */ SDL_PK_UNKNOWN, + /* 186 */ SDL_PK_UNKNOWN, + /* 187 */ SDL_PK_HELP, + /* 188 */ SDL_PK_UNKNOWN, + /* 189 */ SDL_PK_UNKNOWN, + /* 190 */ SDL_PK_UNKNOWN, + /* 191 */ SDL_PK_UNKNOWN, + /* 192 */ SDL_PK_UNKNOWN, + /* 193 */ SDL_PK_UNKNOWN, + /* 194 */ SDL_PK_UNKNOWN, + /* 195 */ SDL_PK_UNKNOWN, + /* 196 */ SDL_PK_UNKNOWN, + /* 197 */ SDL_PK_UNKNOWN, + /* 198 */ SDL_PK_UNKNOWN, + /* 199 */ SDL_PK_UNKNOWN, + /* 200 */ SDL_PK_UNKNOWN, + /* 201 */ SDL_PK_UNKNOWN, + /* 202 */ SDL_PK_UNKNOWN, + /* 203 */ SDL_PK_UNKNOWN, + /* 204 */ SDL_PK_EJECT, /* on PowerBook G4 */ + /* 205 */ SDL_PK_UNKNOWN, + /* 206 */ SDL_PK_UNKNOWN, + /* 207 */ SDL_PK_UNKNOWN, + /* 208 */ SDL_PK_UNKNOWN, + /* 209 */ SDL_PK_UNKNOWN, + /* 210 */ SDL_PK_UNKNOWN, + /* 211 */ SDL_PK_UNKNOWN, + /* 212 */ SDL_PK_BRIGHTNESSUP, /* on PowerBook G4 */ + /* 213 */ SDL_PK_UNKNOWN, + /* 214 */ SDL_PK_DISPLAYSWITCH, /* on PowerBook G4 */ + /* 215 */ SDL_PK_KBDILLUMTOGGLE, + /* 216 */ SDL_PK_KBDILLUMDOWN, + /* 217 */ SDL_PK_KBDILLUMUP, + /* 218 */ SDL_PK_UNKNOWN, + /* 219 */ SDL_PK_UNKNOWN, + /* 220 */ SDL_PK_UNKNOWN, + /* 221 */ SDL_PK_UNKNOWN, + /* 222 */ SDL_PK_POWER, + /* 223 */ SDL_PK_SLEEP, + /* 224 */ SDL_PK_UNKNOWN, + /* 225 */ SDL_PK_UNKNOWN, + /* 226 */ SDL_PK_UNKNOWN, + /* 227 */ SDL_PK_UNKNOWN, + /* 228 */ SDL_PK_UNKNOWN, + /* 229 */ SDL_PK_SEARCH, + /* 230 */ SDL_PK_BOOKMARKS, + /* 231 */ SDL_PK_BROWSERRELOAD, + /* 232 */ SDL_PK_BROWSERSTOP, + /* 233 */ SDL_PK_BROWSERFORWARD, + /* 234 */ SDL_PK_BROWSERBACK, + /* 235 */ SDL_PK_COMPUTER, + /* 236 */ SDL_PK_EMAIL, + /* 237 */ SDL_PK_MEDIA, + /* 238 */ SDL_PK_UNKNOWN, + /* 239 */ SDL_PK_UNKNOWN, + /* 240 */ SDL_PK_UNKNOWN, + /* 241 */ SDL_PK_UNKNOWN, + /* 242 */ SDL_PK_UNKNOWN, + /* 243 */ SDL_PK_UNKNOWN, + /* 244 */ SDL_PK_UNKNOWN, + /* 245 */ SDL_PK_UNKNOWN, + /* 246 */ SDL_PK_UNKNOWN, + /* 247 */ SDL_PK_UNKNOWN, + /* 248 */ SDL_PK_UNKNOWN, + /* 249 */ SDL_PK_UNKNOWN, + /* 250 */ SDL_PK_UNKNOWN, + /* 251 */ SDL_PK_UNKNOWN, + /* 252 */ SDL_PK_UNKNOWN, + /* 253 */ SDL_PK_UNKNOWN, + /* 254 */ SDL_PK_UNKNOWN, + /* 255 */ SDL_PK_UNKNOWN +}; + +static SDLPKey *keyCodeToSDLPKTables[] = { + macKeyCodeToSDLPK, + xorgLinuxKeyCodeToSDLPK, + NULL +}; Property changes on: src/video/x11/SDL_x11pkeytables.h ___________________________________________________________________ Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native Index: src/video/x11/SDL_x11video.h =================================================================== --- src/video/x11/SDL_x11video.h (revision 2741) +++ src/video/x11/SDL_x11video.h (working copy) @@ -158,6 +158,9 @@ /* Screensaver settings */ int screensaver_timeout; BOOL dpms_enabled; + + /* translation table from X11 KeyCode to SDL physical key code */ + SDLPKey *currentKeyCodeToSDLPKTable; }; /* Old variable names */ Index: src/video/x11/SDL_x11events_c.h =================================================================== --- src/video/x11/SDL_x11events_c.h (revision 2741) +++ src/video/x11/SDL_x11events_c.h (working copy) @@ -25,6 +25,7 @@ /* Functions to be exported */ extern void X11_InitOSKeymap(_THIS); +extern const char *X11_PKeyName(_THIS, SDLPKey pkey); extern void X11_PumpEvents(_THIS); extern void X11_SetKeyboardState(Display *display, const char *key_vec); Index: src/video/x11/SDL_x11sym.h =================================================================== --- src/video/x11/SDL_x11sym.h (revision 2741) +++ src/video/x11/SDL_x11sym.h (working copy) @@ -65,6 +65,7 @@ SDL_X11_SYM(Status,XIconifyWindow,(Display* a,Window b,int c),(a,b,c),return) SDL_X11_SYM(int,XInstallColormap,(Display* a,Colormap b),(a,b),return) SDL_X11_SYM(KeyCode,XKeysymToKeycode,(Display* a,KeySym b),(a,b),return) +SDL_X11_SYM(char*,XKeysymToString,(KeySym a),(a),return) SDL_X11_SYM(Atom,XInternAtom,(Display* a,_Xconst char* b,Bool c),(a,b,c),return) SDL_X11_SYM(XPixmapFormatValues*,XListPixmapFormats,(Display* a,int* b),(a,b),return) SDL_X11_SYM(int,XLookupString,(XKeyEvent* a,char* b,int c,KeySym* d,XComposeStatus* e),(a,b,c,d,e),return) Index: test/checkkeys.c =================================================================== --- test/checkkeys.c (revision 2741) +++ test/checkkeys.c (working copy) @@ -54,12 +54,14 @@ { /* Print the keycode, name and state */ if ( sym->sym ) { - printf("Key %s: %d-%s ", pressed ? "pressed" : "released", + printf("Key %s: %d-%s ", pressed ? "pressed " : "released", sym->sym, SDL_GetKeyName(sym->sym)); } else { printf("Unknown Key (scancode = %d) %s ", sym->scancode, pressed ? "pressed" : "released"); } + + printf(" (physical: code: %d, name: %s) ", sym->pkey, SDL_PKeyName(sym->pkey)); /* Print the translated character, if one exists */ if ( sym->unicode ) { Index: include/SDL_keyboard.h =================================================================== --- include/SDL_keyboard.h (revision 2741) +++ include/SDL_keyboard.h (working copy) @@ -54,6 +54,7 @@ typedef struct SDL_keysym { Uint8 scancode; /* hardware specific scancode */ SDLKey sym; /* SDL virtual keysym */ + SDLPKey pkey; /*!< physical key code */ SDLMod mod; /* current key modifiers */ Uint16 unicode; /* translated character */ } SDL_keysym; @@ -111,7 +112,19 @@ */ extern DECLSPEC char * SDLCALL SDL_GetKeyName(SDLKey key); +/*! + * \brief Get a human-readable name for a key given its SDL physical key code, + * taking into account the OS' current keyboard mapping. + * + * The returned pointer points to a UTF-8 string that stays valid at least + * until the next call to this function. If you need it around any longer, you + * must copy it. + * + * Always returns non-NULL. + */ +extern DECLSPEC const char * SDLCALL SDL_PKeyName(SDLPKey pkey); + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } Index: include/SDL_keysym.h =================================================================== --- include/SDL_keysym.h (revision 2741) +++ include/SDL_keysym.h (working copy) @@ -308,4 +308,280 @@ #define KMOD_ALT (KMOD_LALT|KMOD_RALT) #define KMOD_META (KMOD_LMETA|KMOD_RMETA) +/*! \brief Physical key codes + + These are the values of the pkey field of the SDL_keysym structure. + + This list is based on the USB HID usage tables, version 1.12 + , + section "10 Keyboard/Keypad Page (0x07)". + + Reminder: SDL_PK_A means "the key that would be labeled 'A' on a + US keyboard" or "the key that would type 'a' if we were using a US + key mapping", not "the key that's labeled 'A'" or "the key that + types the character 'a'"! +*/ +typedef enum { + SDL_PK_NONE = 0, + SDL_PK_UNKNOWN = 1, /* not from the USB spec, but this is a convenient place for it */ + + SDL_PK_A = 4, + SDL_PK_B = 5, + SDL_PK_C = 6, + SDL_PK_D = 7, + SDL_PK_E = 8, + SDL_PK_F = 9, + SDL_PK_G = 10, + SDL_PK_H = 11, + SDL_PK_I = 12, + SDL_PK_J = 13, + SDL_PK_K = 14, + SDL_PK_L = 15, + SDL_PK_M = 16, + SDL_PK_N = 17, + SDL_PK_O = 18, + SDL_PK_P = 19, + SDL_PK_Q = 20, + SDL_PK_R = 21, + SDL_PK_S = 22, + SDL_PK_T = 23, + SDL_PK_U = 24, + SDL_PK_V = 25, + SDL_PK_W = 26, + SDL_PK_X = 27, + SDL_PK_Y = 28, + SDL_PK_Z = 29, + + SDL_PK_1 = 30, + SDL_PK_2 = 31, + SDL_PK_3 = 32, + SDL_PK_4 = 33, + SDL_PK_5 = 34, + SDL_PK_6 = 35, + SDL_PK_7 = 36, + SDL_PK_8 = 37, + SDL_PK_9 = 38, + SDL_PK_0 = 39, + + SDL_PK_RETURN = 40, + SDL_PK_ESCAPE = 41, + SDL_PK_BACKSPACE = 42, + SDL_PK_TAB = 43, + SDL_PK_SPACE = 44, + + SDL_PK_HYPHENMINUS = 45, + SDL_PK_EQUALS = 46, + SDL_PK_LEFTBRACKET = 47, + SDL_PK_RIGHTBRACKET = 48, + SDL_PK_BACKSLASH = 49, /*!< Located at the lower left of the return key on ISO keyboards and at the right end of the QWERTY row on ANSI keyboards. Produces REVERSE SOLIDUS (backslash) and VERTICAL LINE in a US mapping, REVERSE SOLIDUS and VERTICAL LINE in a UK Mac mapping, NUMBER SIGN and TILDE in a UK Windows mapping, DOLLAR SIGN and POUND SIGN in a Swiss German mapping, NUMBER SIGN and APOSTROPHE in a German mapping, GRAVE ACCENT and POUND SIGN in a French Mac mapping, and ASTERISK and MICRO SIGN in a French Windows mapping. */ + SDL_PK_NONUSHASH = 50, /*!< ISO USB keyboards actually use this code instead of 49 for the same key, but all OSes I've seen treat the two codes identically. So, as an implementor, unless your keyboard generates both of those codes and your OS treats them differently, you should generate SDL_PK_BACKSLASH instead of this code. As a user, you should not rely on this code because SDL will never generate it with most (all?) keyboards. */ + SDL_PK_SEMICOLON = 51, + SDL_PK_APOSTROPHE = 52, + SDL_PK_GRAVE = 53, /*!< Located in the top left corner (on both ANSI and ISO keyboards). Produces GRAVE ACCENT and TILDE in a US Windows mapping, GRAVE ACCENT and NOT SIGN in a UK Windows mapping, SECTION SIGN and PLUS-MINUS SIGN in US and UK Mac mappings, SECTION SIGN and DEGREE SIGN in a Swiss German mapping, CIRCUMFLEX ACCENT and DEGREE SIGN in a German mapping, SUPERSCRIPT TWO and TILDE in a French Windows mapping, and COMMERCIAL AT and NUMBER SIGN in a French Mac mapping. */ + SDL_PK_COMMA = 54, + SDL_PK_PERIOD = 55, + SDL_PK_SLASH = 56, + + SDL_PK_CAPSLOCK = 57, + + SDL_PK_F1 = 58, + SDL_PK_F2 = 59, + SDL_PK_F3 = 60, + SDL_PK_F4 = 61, + SDL_PK_F5 = 62, + SDL_PK_F6 = 63, + SDL_PK_F7 = 64, + SDL_PK_F8 = 65, + SDL_PK_F9 = 66, + SDL_PK_F10 = 67, + SDL_PK_F11 = 68, + SDL_PK_F12 = 69, + + SDL_PK_PRINTSCREEN = 70, + SDL_PK_SCROLLLOCK = 71, + SDL_PK_PAUSE = 72, + SDL_PK_INSERT = 73, + SDL_PK_HOME = 74, + SDL_PK_PAGEUP = 75, + SDL_PK_DELETE = 76, + SDL_PK_END = 77, + SDL_PK_PAGEDOWN = 78, + SDL_PK_RIGHT = 79, + SDL_PK_LEFT = 80, + SDL_PK_DOWN = 81, + SDL_PK_UP = 82, + + SDL_PK_KP_NUMLOCKCLEAR = 83, /*!< num lock on PC, clear on Mac keyboards */ + SDL_PK_KP_DIVIDE = 84, + SDL_PK_KP_MULTIPLY = 85, + SDL_PK_KP_MINUS = 86, + SDL_PK_KP_PLUS = 87, + SDL_PK_KP_ENTER = 88, + SDL_PK_KP_1 = 89, + SDL_PK_KP_2 = 90, + SDL_PK_KP_3 = 91, + SDL_PK_KP_4 = 92, + SDL_PK_KP_5 = 93, + SDL_PK_KP_6 = 94, + SDL_PK_KP_7 = 95, + SDL_PK_KP_8 = 96, + SDL_PK_KP_9 = 97, + SDL_PK_KP_0 = 98, + SDL_PK_KP_PERIOD = 99, + + SDL_PK_NONUSBACKSLASH = 100, /*!< This is the additional key that ISO keyboards have over ANSI ones, located between left shift and Y. Produces GRAVE ACCENT and TILDE in a US or UK Mac mapping, REVERSE SOLIDUS (backslash) and VERTICAL LINE in a US or UK Windows mapping, and LESS-THAN SIGN and GREATER-THAN SIGN in a Swiss German, German, or French mapping */ + SDL_PK_APPLICATION = 101, /*!< windows contextual menu, compose */ + SDL_PK_POWER = 102, /*!< The USB document says this is a status flag, not a physical key - but some Mac keyboards do have a power key. */ + SDL_PK_KP_EQUALS = 103, + SDL_PK_F13 = 104, + SDL_PK_F14 = 105, + SDL_PK_F15 = 106, + SDL_PK_F16 = 107, + SDL_PK_F17 = 108, + SDL_PK_F18 = 109, + SDL_PK_F19 = 110, + SDL_PK_F20 = 111, + SDL_PK_F21 = 112, + SDL_PK_F22 = 113, + SDL_PK_F23 = 114, + SDL_PK_F24 = 115, + SDL_PK_EXECUTE = 116, + SDL_PK_HELP = 117, + SDL_PK_MENU = 118, + SDL_PK_SELECT = 119, + SDL_PK_STOP = 120, + SDL_PK_AGAIN = 121, /*!< redo */ + SDL_PK_UNDO = 122, + SDL_PK_CUT = 123, + SDL_PK_COPY = 124, + SDL_PK_PASTE = 125, + SDL_PK_FIND = 126, + SDL_PK_MUTE = 127, + SDL_PK_VOLUMEUP = 128, + SDL_PK_VOLUMEDOWN = 129, + /*SDL_PK_LOCKINGCAPSLOCK = 130, not sure whether we should enable these + SDL_PK_LOCKINGNUMLOCK = 131, + SDL_PK_LOCKINGSCROLLLOCK = 132,*/ + SDL_PK_KP_COMMA = 133, + SDL_PK_KP_EQUALSAS400 = 134, + + SDL_PK_INTERNATIONAL1 = 135, /*!< used on Asian keyboards, see footnotes in USB doc */ + SDL_PK_INTERNATIONAL2 = 136, + SDL_PK_INTERNATIONAL3 = 137, /*!< Yen */ + SDL_PK_INTERNATIONAL4 = 138, + SDL_PK_INTERNATIONAL5 = 139, + SDL_PK_INTERNATIONAL6 = 140, + SDL_PK_INTERNATIONAL7 = 141, + SDL_PK_INTERNATIONAL8 = 142, + SDL_PK_INTERNATIONAL9 = 143, + SDL_PK_LANG1 = 144, /*!< Hangul/English toggle */ + SDL_PK_LANG2 = 145, /*!< Hanja conversion */ + SDL_PK_LANG3 = 146, /*!< Katakana */ + SDL_PK_LANG4 = 147, /*!< Hiragana */ + SDL_PK_LANG5 = 148, /*!< Zenkaku/Hankaku */ + SDL_PK_LANG6 = 149, /*!< reserved */ + SDL_PK_LANG7 = 150, /*!< reserved */ + SDL_PK_LANG8 = 151, /*!< reserved */ + SDL_PK_LANG9 = 152, /*!< reserved */ + + SDL_PK_ALTERASE = 153, /*!< Erase-Eaze */ + SDL_PK_SYSREQ = 154, + SDL_PK_CANCEL = 155, + SDL_PK_CLEAR = 156, + SDL_PK_PRIOR = 157, + SDL_PK_RETURN2 = 158, + SDL_PK_SEPARATOR = 159, + SDL_PK_OUT = 160, + SDL_PK_OPER = 161, + SDL_PK_CLEARAGAIN = 162, + SDL_PK_CRSELPROPS = 163, + SDL_PK_EXSEL = 164, + + SDL_PK_KP_00 = 176, + SDL_PK_KP_000 = 177, + SDL_PK_THOUSANDSSEPARATOR = 178, + SDL_PK_DECIMALSEPARATOR = 179, + SDL_PK_CURRENCYUNIT = 180, + SDL_PK_CURRENCYSUBUNIT = 181, + SDL_PK_KP_LEFTPAREN = 182, + SDL_PK_KP_RIGHTPAREN = 183, + SDL_PK_KP_LEFTBRACE = 184, + SDL_PK_KP_RIGHTBRACE = 185, + SDL_PK_KP_TAB = 186, + SDL_PK_KP_BACKSPACE = 187, + SDL_PK_KP_A = 188, + SDL_PK_KP_B = 189, + SDL_PK_KP_C = 190, + SDL_PK_KP_D = 191, + SDL_PK_KP_E = 192, + SDL_PK_KP_F = 193, + SDL_PK_KP_XOR = 194, + SDL_PK_KP_POWER = 195, + SDL_PK_KP_PERCENT = 196, + SDL_PK_KP_LESS = 197, + SDL_PK_KP_GREATER = 198, + SDL_PK_KP_AMPERSAND = 199, + SDL_PK_KP_DBLAMPERSAND = 200, + SDL_PK_KP_VERTICALBAR = 201, + SDL_PK_KP_DBLVERTICALBAR = 202, + SDL_PK_KP_COLON = 203, + SDL_PK_KP_HASH = 204, + SDL_PK_KP_SPACE = 205, + SDL_PK_KP_AT = 206, + SDL_PK_KP_EXCLAM = 207, + SDL_PK_KP_MEMSTORE = 208, + SDL_PK_KP_MEMRECALL = 209, + SDL_PK_KP_MEMCLEAR = 210, + SDL_PK_KP_MEMADD = 211, + SDL_PK_KP_MEMSUBTRACT = 212, + SDL_PK_KP_MEMMULTIPLY = 213, + SDL_PK_KP_MEMDIVIDE = 214, + SDL_PK_KP_PLUSMINUS = 215, + SDL_PK_KP_CLEAR = 216, + SDL_PK_KP_CLEARENTRY = 217, + SDL_PK_KP_BINARY = 218, + SDL_PK_KP_OCTAL = 219, + SDL_PK_KP_DECIMAL = 220, + SDL_PK_KP_HEXADECIMAL = 221, + + SDL_PK_LCTRL = 224, + SDL_PK_LSHIFT = 225, + SDL_PK_LALT = 226, /*!< alt, option */ + SDL_PK_LGUI = 227, /*!< windows, command (apple), meta */ + SDL_PK_RCTRL = 228, + SDL_PK_RSHIFT = 229, + SDL_PK_RALT = 230, /*!< alt gr, option */ + SDL_PK_RGUI = 231, /*!< windows, command (apple), meta */ + + /* everything below here is not from the USB spec */ + + SDL_PK_BRIGHTNESSDOWN = 236, + SDL_PK_BRIGHTNESSUP = 237, + SDL_PK_DISPLAYSWITCH = 238, /*!< display mirroring/dual display switch, video mode switch */ + SDL_PK_KBDILLUMTOGGLE = 239, + SDL_PK_KBDILLUMDOWN = 240, + SDL_PK_KBDILLUMUP =241, + SDL_PK_EJECT = 242, + SDL_PK_SLEEP = 243, + + /* some of the more common and more standardized "multimedia"/"internet" keyboard keys */ + SDL_PK_AUDIOPLAY = 244, + SDL_PK_AUDIOSTOP = 245, + SDL_PK_AUDIOPREV = 246, + SDL_PK_AUDIONEXT = 247, + SDL_PK_CALC = 248, + SDL_PK_WWW = 249, + SDL_PK_EMAIL = 250, + SDL_PK_MEDIA = 251, + SDL_PK_COMPUTER = 252, + SDL_PK_SEARCH = 253, + SDL_PK_BOOKMARKS = 254, + SDL_PK_BROWSERBACK = 255, + SDL_PK_BROWSERFORWARD = 256, + SDL_PK_BROWSERRELOAD = 257, + SDL_PK_BROWSERSTOP = 258, + + SDL_PK_LAST /*!< (not a key, just marks the highest used value in this enum) */ +} SDLPKey; + #endif /* _SDL_keysym_h */