Index: src/events/SDL_keyboard.c =================================================================== --- src/events/SDL_keyboard.c (revision 3452) +++ src/events/SDL_keyboard.c (working copy) @@ -36,6 +36,47 @@ static int SDL_current_keyboard; static SDL_Keyboard **SDL_keyboards; +/* Taken from SDL_iconv() */ +static char *encodeUtf8(Uint32 ch, char *dst) +{ + Uint8 *p = (Uint8 *) dst; + if (ch <= 0x7F) { + *p = (Uint8) ch; + ++dst; + } else if (ch <= 0x7FF) { + p[0] = 0xC0 | (Uint8) ((ch >> 6) & 0x1F); + p[1] = 0x80 | (Uint8) (ch & 0x3F); + dst += 2; + } else if (ch <= 0xFFFF) { + p[0] = 0xE0 | (Uint8) ((ch >> 12) & 0x0F); + p[1] = 0x80 | (Uint8) ((ch >> 6) & 0x3F); + p[2] = 0x80 | (Uint8) (ch & 0x3F); + dst += 3; + } else if (ch <= 0x1FFFFF) { + p[0] = 0xF0 | (Uint8) ((ch >> 18) & 0x07); + p[1] = 0x80 | (Uint8) ((ch >> 12) & 0x3F); + p[2] = 0x80 | (Uint8) ((ch >> 6) & 0x3F); + p[3] = 0x80 | (Uint8) (ch & 0x3F); + dst += 4; + } else if (ch <= 0x3FFFFFF) { + p[0] = 0xF8 | (Uint8) ((ch >> 24) & 0x03); + p[1] = 0x80 | (Uint8) ((ch >> 18) & 0x3F); + p[2] = 0x80 | (Uint8) ((ch >> 12) & 0x3F); + p[3] = 0x80 | (Uint8) ((ch >> 6) & 0x3F); + p[4] = 0x80 | (Uint8) (ch & 0x3F); + dst += 5; + } else { + p[0] = 0xFC | (Uint8) ((ch >> 30) & 0x01); + p[1] = 0x80 | (Uint8) ((ch >> 24) & 0x3F); + p[2] = 0x80 | (Uint8) ((ch >> 18) & 0x3F); + p[3] = 0x80 | (Uint8) ((ch >> 12) & 0x3F); + p[4] = 0x80 | (Uint8) ((ch >> 6) & 0x3F); + p[5] = 0x80 | (Uint8) (ch & 0x3F); + dst += 6; + } + return dst; +} + /* Public functions */ int SDL_KeyboardInit(void) @@ -227,21 +268,14 @@ /* SDLK_INDEX(layoutKey) is the unicode code point of the character generated by the key */ static char buffer[9]; /* 6 (maximal UTF-8 char length) + 2 ([] for keypad) + 1 (null teminator) */ char *bufferPtr = &buffer[1]; - SDL_iconv_t cd; - size_t inbytesleft = 4, outbytesleft = 8; Uint32 codepoint = SDLK_INDEX(layoutKey); - const char *codepointPtr = (const char *) &codepoint; /* Unaccented letter keys on latin keyboards are normally labeled in upper case (and probably on others like Greek or Cyrillic too, so if you happen to know for sure, please adapt this). */ if (codepoint >= 'a' && codepoint <= 'z') { codepoint -= 32; } - cd = SDL_iconv_open("UTF-8", "UCS-4"); - if (cd == (SDL_iconv_t) (-1)) - return ""; - SDL_iconv(cd, &codepointPtr, &inbytesleft, &bufferPtr, &outbytesleft); - SDL_iconv_close(cd); + bufferPtr = encodeUtf8(codepoint, bufferPtr); *bufferPtr = '\0'; if ((layoutKey & SDL_KEY_KEYPAD_BIT) != 0) { Index: src/video/x11/SDL_x11events.c =================================================================== --- src/video/x11/SDL_x11events.c (revision 3452) +++ src/video/x11/SDL_x11events.c (working copy) @@ -30,6 +30,27 @@ #include "../../events/SDL_events_c.h" +/* Check to see if this is a repeated key. + (idea shamelessly lifted from GII -- thanks guys! :) + */ +static int X11_KeyRepeat(Display *display, XEvent *event) +{ + XEvent peekevent; + int repeated; + + repeated = 0; + if ( XPending(display) ) { + XPeekEvent(display, &peekevent); + if ( (peekevent.type == KeyPress) && + (peekevent.xkey.keycode == event->xkey.keycode) && + ((peekevent.xkey.time-event->xkey.time) < 2) ) { + repeated = 1; + XNextEvent(display, &peekevent); + } + } + return(repeated); +} + static void X11_DispatchEvent(_THIS) { @@ -167,6 +188,16 @@ /* Key press? */ case KeyPress:{ + KeyCode keycode = xevent.xkey.keycode; + if (!X11_KeyRepeat(videodata->display, &xevent)) { + SDLKey physicalKey = videodata->keyCodeToSDLKTable[keycode - 8]; + SDL_SendKeyboardKey(videodata->keyboard, SDL_PRESSED, (Uint8)keycode, physicalKey); +#if 1 + if (physicalKey == SDLK_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(videodata->display, keycode, 0)); + } +#endif + } #if 0 /* FIXME */ static SDL_keysym saved_keysym; SDL_keysym keysym; @@ -236,26 +267,17 @@ /* Key release? */ case KeyRelease:{ -#if 0 /* FIXME */ - SDL_keysym keysym; KeyCode keycode = xevent.xkey.keycode; #ifdef DEBUG_XEVENTS printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode); #endif /* Check to see if this is a repeated key */ - if (X11_KeyRepeat(SDL_Display, &xevent)) { + if (X11_KeyRepeat(videodata->display, &xevent)) { break; } - /* Get the translated SDL virtual keysym */ - keysym.scancode = keycode; - keysym.sym = X11_TranslateKeycode(SDL_Display, keycode); - keysym.mod = KMOD_NONE; - keysym.unicode = 0; - - posted = SDL_PrivateKeyboard(SDL_RELEASED, &keysym); -#endif // 0 + SDL_SendKeyboardKey(videodata->keyboard, SDL_RELEASED, (Uint8)keycode, videodata->keyCodeToSDLKTable[keycode - 8]); } break; Index: src/video/x11/SDL_x11keyboard.h =================================================================== --- src/video/x11/SDL_x11keyboard.h (revision 3452) +++ src/video/x11/SDL_x11keyboard.h (working copy) @@ -24,7 +24,8 @@ #ifndef _SDL_x11keyboard_h #define _SDL_x11keyboard_h -extern void X11_InitKeyboard(_THIS); +extern int X11_InitKeyboard(_THIS); +extern SDLKey X11_GetLayoutKey(_THIS, SDLKey physicalKey); extern void X11_QuitKeyboard(_THIS); #endif /* _SDL_x11keyboard_h */ Index: src/video/x11/SDL_x11video.c =================================================================== --- src/video/x11/SDL_x11video.c (revision 3452) +++ src/video/x11/SDL_x11video.c (working copy) @@ -171,6 +171,7 @@ device->SetDisplayGammaRamp = X11_SetDisplayGammaRamp; device->GetDisplayGammaRamp = X11_GetDisplayGammaRamp; device->PumpEvents = X11_PumpEvents; + device->GetLayoutKey = X11_GetLayoutKey; device->CreateWindow = X11_CreateWindow; device->CreateWindowFrom = X11_CreateWindowFrom; @@ -242,7 +243,7 @@ // GDI_AddRenderDriver(_this); //#endif - X11_InitKeyboard(_this); + if (X11_InitKeyboard(_this) != 0) return -1; X11_InitMouse(_this); return 0; Index: src/video/x11/SDL_x11video.h =================================================================== --- src/video/x11/SDL_x11video.h (revision 3452) +++ src/video/x11/SDL_x11video.h (working copy) @@ -70,6 +70,7 @@ int mouse; int keyboard; Atom WM_DELETE_WINDOW; + SDLKey *keyCodeToSDLKTable; } SDL_VideoData; #endif /* _SDL_x11video_h */ Index: src/video/x11/SDL_x11keytables.h =================================================================== --- src/video/x11/SDL_x11keytables.h (revision 0) +++ src/video/x11/SDL_x11keytables.h (revision 0) @@ -0,0 +1,685 @@ +/* KeyCode-to-SDLKey translation tables for various X servers. Which one to use + is decided in X11_InitKeyboard(). +*/ + +static SDLKey macKeyCodeToSDLK[]; +static SDLKey xorgLinuxKeyCodeToSDLK[]; + +static SDLKey *keyCodeToSDLKeyTables[] = { + macKeyCodeToSDLK, + xorgLinuxKeyCodeToSDLK, + NULL +}; + +/* *INDENT-OFF* */ + +/* These are just Mac virtual key codes + 8 (see SDL/src/video/cocoa/ + SDL_cocoakeys.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 SDLKey macKeyCodeToSDLK[248] = { + /* 8 */ SDLK_A, + /* 9 */ SDLK_S, + /* 10 */ SDLK_D, + /* 11 */ SDLK_F, + /* 12 */ SDLK_H, + /* 13 */ SDLK_G, + /* 14 */ SDLK_Z, + /* 15 */ SDLK_X, + /* 16 */ SDLK_C, + /* 17 */ SDLK_V, + /* 18 */ SDLK_GRAVE, + /* 19 */ SDLK_B, + /* 20 */ SDLK_Q, + /* 21 */ SDLK_W, + /* 22 */ SDLK_E, + /* 23 */ SDLK_R, + /* 24 */ SDLK_Y, + /* 25 */ SDLK_T, + /* 26 */ SDLK_1, + /* 27 */ SDLK_2, + /* 28 */ SDLK_3, + /* 29 */ SDLK_4, + /* 30 */ SDLK_6, + /* 31 */ SDLK_5, + /* 32 */ SDLK_EQUALS, + /* 33 */ SDLK_9, + /* 34 */ SDLK_7, + /* 35 */ SDLK_HYPHENMINUS, + /* 36 */ SDLK_8, + /* 37 */ SDLK_0, + /* 38 */ SDLK_RIGHTBRACKET, + /* 39 */ SDLK_O, + /* 40 */ SDLK_U, + /* 41 */ SDLK_LEFTBRACKET, + /* 42 */ SDLK_I, + /* 43 */ SDLK_P, + /* 44 */ SDLK_RETURN, + /* 45 */ SDLK_L, + /* 46 */ SDLK_J, + /* 47 */ SDLK_APOSTROPHE, + /* 48 */ SDLK_K, + /* 49 */ SDLK_SEMICOLON, + /* 50 */ SDLK_BACKSLASH, + /* 51 */ SDLK_COMMA, + /* 52 */ SDLK_SLASH, + /* 53 */ SDLK_N, + /* 54 */ SDLK_M, + /* 55 */ SDLK_PERIOD, + /* 56 */ SDLK_TAB, + /* 57 */ SDLK_SPACE, + /* 58 */ SDLK_NONUSBACKSLASH, + /* 59 */ SDLK_BACKSPACE, + /* 60 */ SDLK_KP_ENTER, + /* 61 */ SDLK_ESCAPE, + /* 62 */ SDLK_RMETA, + /* 63 */ SDLK_LMETA, + /* 64 */ SDLK_LSHIFT, + /* 65 */ SDLK_CAPSLOCK, + /* 66 */ SDLK_LALT, + /* 67 */ SDLK_LCTRL, + /* 68 */ SDLK_RSHIFT, + /* 69 */ SDLK_RALT, + /* 70 */ SDLK_RCTRL, + /* 71 */ SDLK_NONE, + /* 72 */ SDLK_UNKNOWN, + /* 73 */ SDLK_KP_PERIOD, + /* 74 */ SDLK_UNKNOWN, + /* 75 */ SDLK_KP_MULTIPLY, + /* 76 */ SDLK_UNKNOWN, + /* 77 */ SDLK_KP_PLUS, + /* 78 */ SDLK_UNKNOWN, + /* 79 */ SDLK_KP_NUMLOCKCLEAR, + /* 80 */ SDLK_VOLUMEUP, + /* 81 */ SDLK_VOLUMEDOWN, + /* 82 */ SDLK_MUTE, + /* 83 */ SDLK_KP_DIVIDE, + /* 84 */ SDLK_KP_ENTER, + /* 85 */ SDLK_UNKNOWN, + /* 86 */ SDLK_KP_MINUS, + /* 87 */ SDLK_UNKNOWN, + /* 88 */ SDLK_UNKNOWN, + /* 89 */ SDLK_KP_EQUALS, + /* 90 */ SDLK_KP_0, + /* 91 */ SDLK_KP_1, + /* 92 */ SDLK_KP_2, + /* 93 */ SDLK_KP_3, + /* 94 */ SDLK_KP_4, + /* 95 */ SDLK_KP_5, + /* 96 */ SDLK_KP_6, + /* 97 */ SDLK_KP_7, + /* 98 */ SDLK_UNKNOWN, + /* 99 */ SDLK_KP_8, + /* 100 */ SDLK_KP_9, + /* 101 */ SDLK_INTERNATIONAL3, + /* 102 */ SDLK_INTERNATIONAL1, + /* 103 */ SDLK_KP_COMMA, + /* 104 */ SDLK_F5, + /* 105 */ SDLK_F6, + /* 106 */ SDLK_F7, + /* 107 */ SDLK_F3, + /* 108 */ SDLK_F8, + /* 109 */ SDLK_F9, + /* 110 */ SDLK_LANG2, + /* 111 */ SDLK_F11, + /* 112 */ SDLK_LANG1, + /* 113 */ SDLK_PRINTSCREEN, + /* 114 */ SDLK_F16, + /* 115 */ SDLK_SCROLLLOCK, + /* 116 */ SDLK_UNKNOWN, + /* 117 */ SDLK_F10, + /* 118 */ SDLK_APPLICATION, + /* 119 */ SDLK_F12, + /* 120 */ SDLK_UNKNOWN, + /* 121 */ SDLK_PAUSE, + /* 122 */ SDLK_INSERT, + /* 123 */ SDLK_HOME, + /* 124 */ SDLK_PAGEUP, + /* 125 */ SDLK_DELETE, + /* 126 */ SDLK_F4, + /* 127 */ SDLK_END, + /* 128 */ SDLK_F2, + /* 129 */ SDLK_PAGEDOWN, + /* 130 */ SDLK_F1, + /* 131 */ SDLK_LEFT, + /* 132 */ SDLK_RIGHT, + /* 133 */ SDLK_DOWN, + /* 134 */ SDLK_UP, + /* 135 */ SDLK_POWER, + /* 136 */ SDLK_UNKNOWN, /* codes higher than 135 shouldn't occur as Mac virtual keycodes only go to 127 */ + /* 137 */ SDLK_UNKNOWN, + /* 138 */ SDLK_UNKNOWN, + /* 139 */ SDLK_UNKNOWN, + /* 140 */ SDLK_UNKNOWN, + /* 141 */ SDLK_UNKNOWN, + /* 142 */ SDLK_UNKNOWN, + /* 143 */ SDLK_UNKNOWN, + /* 144 */ SDLK_UNKNOWN, + /* 145 */ SDLK_UNKNOWN, + /* 146 */ SDLK_UNKNOWN, + /* 147 */ SDLK_UNKNOWN, + /* 148 */ SDLK_UNKNOWN, + /* 149 */ SDLK_UNKNOWN, + /* 150 */ SDLK_UNKNOWN, + /* 151 */ SDLK_UNKNOWN, + /* 152 */ SDLK_UNKNOWN, + /* 153 */ SDLK_UNKNOWN, + /* 154 */ SDLK_UNKNOWN, + /* 155 */ SDLK_UNKNOWN, + /* 156 */ SDLK_UNKNOWN, + /* 157 */ SDLK_UNKNOWN, + /* 158 */ SDLK_UNKNOWN, + /* 159 */ SDLK_UNKNOWN, + /* 160 */ SDLK_UNKNOWN, + /* 161 */ SDLK_UNKNOWN, + /* 162 */ SDLK_UNKNOWN, + /* 163 */ SDLK_UNKNOWN, + /* 164 */ SDLK_UNKNOWN, + /* 165 */ SDLK_UNKNOWN, + /* 166 */ SDLK_UNKNOWN, + /* 167 */ SDLK_UNKNOWN, + /* 168 */ SDLK_UNKNOWN, + /* 169 */ SDLK_UNKNOWN, + /* 170 */ SDLK_UNKNOWN, + /* 171 */ SDLK_UNKNOWN, + /* 172 */ SDLK_UNKNOWN, + /* 173 */ SDLK_UNKNOWN, + /* 174 */ SDLK_UNKNOWN, + /* 175 */ SDLK_UNKNOWN, + /* 176 */ SDLK_UNKNOWN, + /* 177 */ SDLK_UNKNOWN, + /* 178 */ SDLK_UNKNOWN, + /* 179 */ SDLK_UNKNOWN, + /* 180 */ SDLK_UNKNOWN, + /* 181 */ SDLK_UNKNOWN, + /* 182 */ SDLK_UNKNOWN, + /* 183 */ SDLK_UNKNOWN, + /* 184 */ SDLK_UNKNOWN, + /* 185 */ SDLK_UNKNOWN, + /* 186 */ SDLK_UNKNOWN, + /* 187 */ SDLK_UNKNOWN, + /* 188 */ SDLK_UNKNOWN, + /* 189 */ SDLK_UNKNOWN, + /* 190 */ SDLK_UNKNOWN, + /* 191 */ SDLK_UNKNOWN, + /* 192 */ SDLK_UNKNOWN, + /* 193 */ SDLK_UNKNOWN, + /* 194 */ SDLK_UNKNOWN, + /* 195 */ SDLK_UNKNOWN, + /* 196 */ SDLK_UNKNOWN, + /* 197 */ SDLK_UNKNOWN, + /* 198 */ SDLK_UNKNOWN, + /* 199 */ SDLK_UNKNOWN, + /* 200 */ SDLK_UNKNOWN, + /* 201 */ SDLK_UNKNOWN, + /* 202 */ SDLK_UNKNOWN, + /* 203 */ SDLK_UNKNOWN, + /* 204 */ SDLK_UNKNOWN, + /* 205 */ SDLK_UNKNOWN, + /* 206 */ SDLK_UNKNOWN, + /* 207 */ SDLK_UNKNOWN, + /* 208 */ SDLK_UNKNOWN, + /* 209 */ SDLK_UNKNOWN, + /* 210 */ SDLK_UNKNOWN, + /* 211 */ SDLK_UNKNOWN, + /* 212 */ SDLK_UNKNOWN, + /* 213 */ SDLK_UNKNOWN, + /* 214 */ SDLK_UNKNOWN, + /* 215 */ SDLK_UNKNOWN, + /* 216 */ SDLK_UNKNOWN, + /* 217 */ SDLK_UNKNOWN, + /* 218 */ SDLK_UNKNOWN, + /* 219 */ SDLK_UNKNOWN, + /* 220 */ SDLK_UNKNOWN, + /* 221 */ SDLK_UNKNOWN, + /* 222 */ SDLK_UNKNOWN, + /* 223 */ SDLK_UNKNOWN, + /* 224 */ SDLK_UNKNOWN, + /* 225 */ SDLK_UNKNOWN, + /* 226 */ SDLK_UNKNOWN, + /* 227 */ SDLK_UNKNOWN, + /* 228 */ SDLK_UNKNOWN, + /* 229 */ SDLK_UNKNOWN, + /* 230 */ SDLK_UNKNOWN, + /* 231 */ SDLK_UNKNOWN, + /* 232 */ SDLK_UNKNOWN, + /* 233 */ SDLK_UNKNOWN, + /* 234 */ SDLK_UNKNOWN, + /* 235 */ SDLK_UNKNOWN, + /* 236 */ SDLK_UNKNOWN, + /* 237 */ SDLK_UNKNOWN, + /* 238 */ SDLK_UNKNOWN, + /* 239 */ SDLK_UNKNOWN, + /* 240 */ SDLK_UNKNOWN, + /* 241 */ SDLK_UNKNOWN, + /* 242 */ SDLK_UNKNOWN, + /* 243 */ SDLK_UNKNOWN, + /* 244 */ SDLK_UNKNOWN, + /* 245 */ SDLK_UNKNOWN, + /* 246 */ SDLK_UNKNOWN, + /* 247 */ SDLK_UNKNOWN, + /* 248 */ SDLK_UNKNOWN, + /* 249 */ SDLK_UNKNOWN, + /* 250 */ SDLK_UNKNOWN, + /* 251 */ SDLK_UNKNOWN, + /* 252 */ SDLK_UNKNOWN, + /* 253 */ SDLK_UNKNOWN, + /* 254 */ SDLK_UNKNOWN, + /* 255 */ SDLK_UNKNOWN +}; + +/* Found mostly by experimentation with X.org on Linux (Fedora Core 4 and + Ubuntu Dapper) on PC and PPC Mac hardware, some parts (especially about + the "multimedia"/"internet" keys) from various sources on the web. +*/ +static SDLKey xorgLinuxKeyCodeToSDLK[248] = { + /* 8 */ SDLK_UNKNOWN, + /* 9 */ SDLK_ESCAPE, + /* 10 */ SDLK_1, + /* 11 */ SDLK_2, + /* 12 */ SDLK_3, + /* 13 */ SDLK_4, + /* 14 */ SDLK_5, + /* 15 */ SDLK_6, + /* 16 */ SDLK_7, + /* 17 */ SDLK_8, + /* 18 */ SDLK_9, + /* 19 */ SDLK_0, + /* 20 */ SDLK_HYPHENMINUS, + /* 21 */ SDLK_EQUALS, + /* 22 */ SDLK_BACKSPACE, + /* 23 */ SDLK_TAB, + /* 24 */ SDLK_Q, + /* 25 */ SDLK_W, + /* 26 */ SDLK_E, + /* 27 */ SDLK_R, + /* 28 */ SDLK_T, + /* 29 */ SDLK_Y, + /* 30 */ SDLK_U, + /* 31 */ SDLK_I, + /* 32 */ SDLK_O, + /* 33 */ SDLK_P, + /* 34 */ SDLK_LEFTBRACKET, + /* 35 */ SDLK_RIGHTBRACKET, + /* 36 */ SDLK_RETURN, + /* 37 */ SDLK_LCTRL, + /* 38 */ SDLK_A, + /* 39 */ SDLK_S, + /* 40 */ SDLK_D, + /* 41 */ SDLK_F, + /* 42 */ SDLK_G, + /* 43 */ SDLK_H, + /* 44 */ SDLK_J, + /* 45 */ SDLK_K, + /* 46 */ SDLK_L, + /* 47 */ SDLK_SEMICOLON, + /* 48 */ SDLK_APOSTROPHE, + /* 49 */ SDLK_GRAVE, + /* 50 */ SDLK_LSHIFT, + /* 51 */ SDLK_BACKSLASH, + /* 52 */ SDLK_Z, + /* 53 */ SDLK_X, + /* 54 */ SDLK_C, + /* 55 */ SDLK_V, + /* 56 */ SDLK_B, + /* 57 */ SDLK_N, + /* 58 */ SDLK_M, + /* 59 */ SDLK_COMMA, + /* 60 */ SDLK_PERIOD, + /* 61 */ SDLK_SLASH, + /* 62 */ SDLK_RSHIFT, + /* 63 */ SDLK_KP_MULTIPLY, + /* 64 */ SDLK_LALT, + /* 65 */ SDLK_SPACE, + /* 66 */ SDLK_CAPSLOCK, + /* 67 */ SDLK_F1, + /* 68 */ SDLK_F2, + /* 69 */ SDLK_F3, + /* 70 */ SDLK_F4, + /* 71 */ SDLK_F5, + /* 72 */ SDLK_F6, + /* 73 */ SDLK_F7, + /* 74 */ SDLK_F8, + /* 75 */ SDLK_F9, + /* 76 */ SDLK_F10, + /* 77 */ SDLK_KP_NUMLOCKCLEAR, + /* 78 */ SDLK_SCROLLLOCK, + /* 79 */ SDLK_KP_7, + /* 80 */ SDLK_KP_8, + /* 81 */ SDLK_KP_9, + /* 82 */ SDLK_KP_MINUS, + /* 83 */ SDLK_KP_4, + /* 84 */ SDLK_KP_5, + /* 85 */ SDLK_KP_6, + /* 86 */ SDLK_KP_PLUS, + /* 87 */ SDLK_KP_1, + /* 88 */ SDLK_KP_2, + /* 89 */ SDLK_KP_3, + /* 90 */ SDLK_KP_0, + /* 91 */ SDLK_KP_PERIOD, + /* 92 */ SDLK_SYSREQ, + /* 93 */ SDLK_MODE, /* is translated to XK_Mode_switch by my X server, but I have no keyboard that generates this code, so I'm not sure if this is correct */ + /* 94 */ SDLK_NONUSBACKSLASH, + /* 95 */ SDLK_F11, + /* 96 */ SDLK_F12, + /* 97 */ SDLK_HOME, + /* 98 */ SDLK_UP, + /* 99 */ SDLK_PAGEUP, + /* 100 */ SDLK_LEFT, + /* 101 */ SDLK_BRIGHTNESSDOWN, /* on PowerBook G4 */ + /* 102 */ SDLK_RIGHT, + /* 103 */ SDLK_END, + /* 104 */ SDLK_DOWN, + /* 105 */ SDLK_PAGEDOWN, + /* 106 */ SDLK_INSERT, + /* 107 */ SDLK_DELETE, + /* 108 */ SDLK_KP_ENTER, + /* 109 */ SDLK_RCTRL, + /* 110 */ SDLK_PAUSE, + /* 111 */ SDLK_PRINTSCREEN, + /* 112 */ SDLK_KP_DIVIDE, + /* 113 */ SDLK_RALT, + /* 114 */ SDLK_UNKNOWN, + /* 115 */ SDLK_LMETA, + /* 116 */ SDLK_RMETA, + /* 117 */ SDLK_APPLICATION, + /* 118 */ SDLK_F13, + /* 119 */ SDLK_F14, + /* 120 */ SDLK_F15, + /* 121 */ SDLK_F16, + /* 122 */ SDLK_F17, + /* 123 */ SDLK_UNKNOWN, + /* 124 */ SDLK_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 SDLK_* for it is */ + /* 125 */ SDLK_UNKNOWN, + /* 126 */ SDLK_KP_EQUALS, + /* 127 */ SDLK_UNKNOWN, + /* 128 */ SDLK_UNKNOWN, + /* 129 */ SDLK_UNKNOWN, + /* 130 */ SDLK_UNKNOWN, + /* 131 */ SDLK_UNKNOWN, + /* 132 */ SDLK_UNKNOWN, + /* 133 */ SDLK_INTERNATIONAL3, /* Yen */ + /* 134 */ SDLK_UNKNOWN, + /* 135 */ SDLK_AGAIN, + /* 136 */ SDLK_UNDO, + /* 137 */ SDLK_UNKNOWN, + /* 138 */ SDLK_UNKNOWN, + /* 139 */ SDLK_UNKNOWN, + /* 140 */ SDLK_UNKNOWN, + /* 141 */ SDLK_UNKNOWN, + /* 142 */ SDLK_UNKNOWN, + /* 143 */ SDLK_UNKNOWN, + /* 144 */ SDLK_AUDIOPREV, + /* 145 */ SDLK_UNKNOWN, + /* 146 */ SDLK_UNKNOWN, + /* 147 */ SDLK_UNKNOWN, + /* 148 */ SDLK_UNKNOWN, + /* 149 */ SDLK_UNKNOWN, + /* 150 */ SDLK_UNKNOWN, + /* 151 */ SDLK_UNKNOWN, + /* 152 */ SDLK_UNKNOWN, + /* 153 */ SDLK_AUDIONEXT, + /* 154 */ SDLK_UNKNOWN, + /* 155 */ SDLK_UNKNOWN, + /* 156 */ SDLK_UNKNOWN, + /* 157 */ SDLK_KP_EQUALS, /* on PowerBook G4 */ + /* 158 */ SDLK_UNKNOWN, + /* 159 */ SDLK_UNKNOWN, + /* 160 */ SDLK_MUTE, + /* 161 */ SDLK_CALC, + /* 162 */ SDLK_AUDIOPLAY, + /* 163 */ SDLK_UNKNOWN, + /* 164 */ SDLK_AUDIOSTOP, + /* 165 */ SDLK_UNKNOWN, + /* 166 */ SDLK_UNKNOWN, + /* 167 */ SDLK_UNKNOWN, + /* 168 */ SDLK_UNKNOWN, + /* 169 */ SDLK_UNKNOWN, + /* 170 */ SDLK_UNKNOWN, + /* 171 */ SDLK_UNKNOWN, + /* 172 */ SDLK_UNKNOWN, + /* 173 */ SDLK_UNKNOWN, + /* 174 */ SDLK_VOLUMEDOWN, + /* 175 */ SDLK_UNKNOWN, + /* 176 */ SDLK_VOLUMEUP, + /* 177 */ SDLK_UNKNOWN, + /* 178 */ SDLK_WWW, + /* 179 */ SDLK_UNKNOWN, + /* 180 */ SDLK_UNKNOWN, + /* 181 */ SDLK_UNKNOWN, + /* 182 */ SDLK_UNKNOWN, + /* 183 */ SDLK_UNKNOWN, + /* 184 */ SDLK_UNKNOWN, + /* 185 */ SDLK_UNKNOWN, + /* 186 */ SDLK_UNKNOWN, + /* 187 */ SDLK_HELP, + /* 188 */ SDLK_UNKNOWN, + /* 189 */ SDLK_UNKNOWN, + /* 190 */ SDLK_UNKNOWN, + /* 191 */ SDLK_UNKNOWN, + /* 192 */ SDLK_UNKNOWN, + /* 193 */ SDLK_UNKNOWN, + /* 194 */ SDLK_UNKNOWN, + /* 195 */ SDLK_UNKNOWN, + /* 196 */ SDLK_UNKNOWN, + /* 197 */ SDLK_UNKNOWN, + /* 198 */ SDLK_UNKNOWN, + /* 199 */ SDLK_UNKNOWN, + /* 200 */ SDLK_UNKNOWN, + /* 201 */ SDLK_UNKNOWN, + /* 202 */ SDLK_UNKNOWN, + /* 203 */ SDLK_UNKNOWN, + /* 204 */ SDLK_EJECT, /* on PowerBook G4 */ + /* 205 */ SDLK_UNKNOWN, + /* 206 */ SDLK_UNKNOWN, + /* 207 */ SDLK_UNKNOWN, + /* 208 */ SDLK_UNKNOWN, + /* 209 */ SDLK_UNKNOWN, + /* 210 */ SDLK_UNKNOWN, + /* 211 */ SDLK_UNKNOWN, + /* 212 */ SDLK_BRIGHTNESSUP, /* on PowerBook G4 */ + /* 213 */ SDLK_UNKNOWN, + /* 214 */ SDLK_DISPLAYSWITCH, /* on PowerBook G4 */ + /* 215 */ SDLK_KBDILLUMTOGGLE, + /* 216 */ SDLK_KBDILLUMDOWN, + /* 217 */ SDLK_KBDILLUMUP, + /* 218 */ SDLK_UNKNOWN, + /* 219 */ SDLK_UNKNOWN, + /* 220 */ SDLK_UNKNOWN, + /* 221 */ SDLK_UNKNOWN, + /* 222 */ SDLK_POWER, + /* 223 */ SDLK_SLEEP, + /* 224 */ SDLK_UNKNOWN, + /* 225 */ SDLK_UNKNOWN, + /* 226 */ SDLK_UNKNOWN, + /* 227 */ SDLK_UNKNOWN, + /* 228 */ SDLK_UNKNOWN, + /* 229 */ SDLK_SEARCH, + /* 230 */ SDLK_BOOKMARKS, + /* 231 */ SDLK_BROWSERRELOAD, + /* 232 */ SDLK_BROWSERSTOP, + /* 233 */ SDLK_BROWSERFORWARD, + /* 234 */ SDLK_BROWSERBACK, + /* 235 */ SDLK_COMPUTER, + /* 236 */ SDLK_EMAIL, + /* 237 */ SDLK_MEDIA, + /* 238 */ SDLK_UNKNOWN, + /* 239 */ SDLK_UNKNOWN, + /* 240 */ SDLK_UNKNOWN, + /* 241 */ SDLK_UNKNOWN, + /* 242 */ SDLK_UNKNOWN, + /* 243 */ SDLK_UNKNOWN, + /* 244 */ SDLK_UNKNOWN, + /* 245 */ SDLK_UNKNOWN, + /* 246 */ SDLK_UNKNOWN, + /* 247 */ SDLK_UNKNOWN, + /* 248 */ SDLK_UNKNOWN, + /* 249 */ SDLK_UNKNOWN, + /* 250 */ SDLK_UNKNOWN, + /* 251 */ SDLK_UNKNOWN, + /* 252 */ SDLK_UNKNOWN, + /* 253 */ SDLK_UNKNOWN, + /* 254 */ SDLK_UNKNOWN, + /* 255 */ SDLK_UNKNOWN +}; + +/* *INDENT-ON* */ +/*---------------------------------------------------------------------------*/ + +/* Used by X11_KeySymToSDLKey(). This is a hybrid of a KeySym-to-layout-key + mapping for non-character keys (needed in X11_GetLayoutKey()) and a + fallback KeySym-to-physical-key mapping under the assumption of a US + keyboard layout (needed in X11_InitKeyboard()). The X11_KEY_CHARACTER_BIT + tells to which of these two kinds each entry belongs. + This list is sorted by KeySym to allow a binary search. +*/ +#define X11_KEY_CHARACTER_BIT SDL_KEY_LAYOUT_SPECIAL_BIT +/* SDL_KEY_LAYOUT_SPECIAL_BIT cannot possibly occur in an SDLK_ constant, so we may repurpose that bit for our own use. */ +static struct { KeySym sym; SDLKey key; } keySymToSDLKey[] = { + /* 0x00xx */ + { XK_space, SDLK_SPACE }, + { XK_apostrophe, SDLK_APOSTROPHE | X11_KEY_CHARACTER_BIT }, + { XK_comma, SDLK_COMMA | X11_KEY_CHARACTER_BIT }, + { XK_minus, SDLK_HYPHENMINUS | X11_KEY_CHARACTER_BIT }, + { XK_period, SDLK_PERIOD | X11_KEY_CHARACTER_BIT }, + { XK_slash, SDLK_SLASH | X11_KEY_CHARACTER_BIT }, + { XK_0, SDLK_0 | X11_KEY_CHARACTER_BIT }, + { XK_1, SDLK_1 | X11_KEY_CHARACTER_BIT }, + { XK_2, SDLK_2 | X11_KEY_CHARACTER_BIT }, + { XK_3, SDLK_3 | X11_KEY_CHARACTER_BIT }, + { XK_4, SDLK_4 | X11_KEY_CHARACTER_BIT }, + { XK_5, SDLK_5 | X11_KEY_CHARACTER_BIT }, + { XK_6, SDLK_6 | X11_KEY_CHARACTER_BIT }, + { XK_7, SDLK_7 | X11_KEY_CHARACTER_BIT }, + { XK_8, SDLK_8 | X11_KEY_CHARACTER_BIT }, + { XK_9, SDLK_9 | X11_KEY_CHARACTER_BIT }, + { XK_semicolon, SDLK_SEMICOLON | X11_KEY_CHARACTER_BIT }, + { XK_less, SDLK_NONUSBACKSLASH | X11_KEY_CHARACTER_BIT }, + { XK_equal, SDLK_EQUALS | X11_KEY_CHARACTER_BIT }, + { XK_bracketleft, SDLK_LEFTBRACKET | X11_KEY_CHARACTER_BIT }, + { XK_backslash, SDLK_BACKSLASH | X11_KEY_CHARACTER_BIT }, + { XK_bracketright, SDLK_RIGHTBRACKET | X11_KEY_CHARACTER_BIT }, + { XK_grave, SDLK_GRAVE | X11_KEY_CHARACTER_BIT }, + { XK_a, SDLK_A | X11_KEY_CHARACTER_BIT }, + { XK_b, SDLK_B | X11_KEY_CHARACTER_BIT }, + { XK_c, SDLK_C | X11_KEY_CHARACTER_BIT }, + { XK_d, SDLK_D | X11_KEY_CHARACTER_BIT }, + { XK_e, SDLK_E | X11_KEY_CHARACTER_BIT }, + { XK_f, SDLK_F | X11_KEY_CHARACTER_BIT }, + { XK_g, SDLK_G | X11_KEY_CHARACTER_BIT }, + { XK_h, SDLK_H | X11_KEY_CHARACTER_BIT }, + { XK_i, SDLK_I | X11_KEY_CHARACTER_BIT }, + { XK_j, SDLK_J | X11_KEY_CHARACTER_BIT }, + { XK_k, SDLK_K | X11_KEY_CHARACTER_BIT }, + { XK_l, SDLK_L | X11_KEY_CHARACTER_BIT }, + { XK_m, SDLK_M | X11_KEY_CHARACTER_BIT }, + { XK_n, SDLK_N | X11_KEY_CHARACTER_BIT }, + { XK_o, SDLK_O | X11_KEY_CHARACTER_BIT }, + { XK_p, SDLK_P | X11_KEY_CHARACTER_BIT }, + { XK_q, SDLK_Q | X11_KEY_CHARACTER_BIT }, + { XK_r, SDLK_R | X11_KEY_CHARACTER_BIT }, + { XK_s, SDLK_S | X11_KEY_CHARACTER_BIT }, + { XK_t, SDLK_T | X11_KEY_CHARACTER_BIT }, + { XK_u, SDLK_U | X11_KEY_CHARACTER_BIT }, + { XK_v, SDLK_V | X11_KEY_CHARACTER_BIT }, + { XK_w, SDLK_W | X11_KEY_CHARACTER_BIT }, + { XK_x, SDLK_X | X11_KEY_CHARACTER_BIT }, + { XK_y, SDLK_Y | X11_KEY_CHARACTER_BIT }, + { XK_z, SDLK_Z | X11_KEY_CHARACTER_BIT }, + { XK_section, SDLK_NONUSBACKSLASH | X11_KEY_CHARACTER_BIT }, + + /* 0xFExx */ + { XK_ISO_Level3_Shift, SDLK_RALT }, + + /* 0xFFxx */ + { XK_BackSpace, SDLK_BACKSPACE }, + { XK_Tab, SDLK_TAB }, + { XK_Return, SDLK_RETURN }, + { XK_Pause, SDLK_PAUSE }, + { XK_Scroll_Lock, SDLK_SCROLLLOCK }, + { XK_Escape, SDLK_ESCAPE }, + { XK_Home, SDLK_HOME }, + { XK_Left, SDLK_LEFT }, + { XK_Up, SDLK_UP }, + { XK_Right, SDLK_RIGHT }, + { XK_Down, SDLK_DOWN }, + { XK_Page_Up, SDLK_PAGEUP }, + { XK_Page_Down, SDLK_PAGEDOWN }, + { XK_End, SDLK_END }, + { XK_Print, SDLK_PRINTSCREEN }, + { XK_Insert, SDLK_INSERT }, + { XK_Menu, SDLK_APPLICATION }, + { XK_Break, SDLK_PAUSE }, + { XK_Mode_switch, SDLK_MODE }, + { XK_Num_Lock, SDLK_KP_NUMLOCKCLEAR }, + { XK_KP_Enter, SDLK_KP_ENTER }, + { XK_KP_Home, SDLK_KP_7 }, + { XK_KP_Left, SDLK_KP_4 }, + { XK_KP_Up, SDLK_KP_8 }, + { XK_KP_Right, SDLK_KP_6 }, + { XK_KP_Down, SDLK_KP_2 }, + { XK_KP_Page_Up, SDLK_KP_9 }, + { XK_KP_Page_Down, SDLK_KP_3 }, + { XK_KP_End, SDLK_KP_1 }, + { XK_KP_Begin, SDLK_KP_5 }, + { XK_KP_Insert, SDLK_KP_0 }, + { XK_KP_Delete, SDLK_KP_PERIOD }, + { XK_KP_Multiply, SDLK_KP_MULTIPLY | X11_KEY_CHARACTER_BIT }, + { XK_KP_Add, SDLK_KP_PLUS | X11_KEY_CHARACTER_BIT }, + { XK_KP_Separator, SDLK_KP_PERIOD | X11_KEY_CHARACTER_BIT }, + { XK_KP_Subtract, SDLK_KP_MINUS | X11_KEY_CHARACTER_BIT }, + { XK_KP_Decimal, SDLK_KP_PERIOD | X11_KEY_CHARACTER_BIT }, + { XK_KP_Divide, SDLK_KP_DIVIDE | X11_KEY_CHARACTER_BIT }, + { XK_KP_0, SDLK_KP_0 | X11_KEY_CHARACTER_BIT }, + { XK_KP_1, SDLK_KP_1 | X11_KEY_CHARACTER_BIT }, + { XK_KP_2, SDLK_KP_2 | X11_KEY_CHARACTER_BIT }, + { XK_KP_3, SDLK_KP_3 | X11_KEY_CHARACTER_BIT }, + { XK_KP_4, SDLK_KP_4 | X11_KEY_CHARACTER_BIT }, + { XK_KP_5, SDLK_KP_5 | X11_KEY_CHARACTER_BIT }, + { XK_KP_6, SDLK_KP_6 | X11_KEY_CHARACTER_BIT }, + { XK_KP_7, SDLK_KP_7 | X11_KEY_CHARACTER_BIT }, + { XK_KP_8, SDLK_KP_8 | X11_KEY_CHARACTER_BIT }, + { XK_KP_9, SDLK_KP_9 | X11_KEY_CHARACTER_BIT }, + { XK_KP_Equal, SDLK_KP_EQUALS | X11_KEY_CHARACTER_BIT }, + { XK_F1, SDLK_F1 }, + { XK_F2, SDLK_F2 }, + { XK_F3, SDLK_F3 }, + { XK_F4, SDLK_F4 }, + { XK_F5, SDLK_F5 }, + { XK_F6, SDLK_F6 }, + { XK_F7, SDLK_F7 }, + { XK_F8, SDLK_F8 }, + { XK_F9, SDLK_F9 }, + { XK_F10, SDLK_F10 }, + { XK_F11, SDLK_F11 }, + { XK_F12, SDLK_F12 }, + { XK_F13, SDLK_F13 }, + { XK_F14, SDLK_F14 }, + { XK_F15, SDLK_F15 }, + { XK_F16, SDLK_F16 }, + { XK_F17, SDLK_F17 }, + { XK_F18, SDLK_F18 }, + { XK_F19, SDLK_F19 }, + { XK_F20, SDLK_F20 }, + { XK_F21, SDLK_F21 }, + { XK_F22, SDLK_F22 }, + { XK_F23, SDLK_F23 }, + { XK_F24, SDLK_F24 }, + { XK_Shift_L, SDLK_LSHIFT }, + { XK_Shift_R, SDLK_RSHIFT }, + { XK_Control_L, SDLK_LCTRL }, + { XK_Control_R, SDLK_RCTRL }, + { XK_Caps_Lock, SDLK_CAPSLOCK }, + { XK_Shift_Lock, SDLK_CAPSLOCK }, + { XK_Meta_L, SDLK_LMETA }, + { XK_Meta_R, SDLK_RMETA }, + { XK_Alt_L, SDLK_LALT }, + { XK_Alt_R, SDLK_RALT }, + { XK_Super_L, SDLK_LMETA }, + { XK_Super_R, SDLK_RMETA }, + { XK_Hyper_L, SDLK_LMETA }, + { XK_Hyper_R, SDLK_RMETA }, + { XK_Delete, SDLK_DELETE }, + + { 0x1000003, SDLK_KP_ENTER } /* keyboard enter on Mac OS X */ +}; Property changes on: src/video/x11/SDL_x11keytables.h ___________________________________________________________________ Name: svn:keywords + Id Index: src/video/x11/SDL_x11keyboard.c =================================================================== --- src/video/x11/SDL_x11keyboard.c (revision 3452) +++ src/video/x11/SDL_x11keyboard.c (working copy) @@ -25,20 +25,321 @@ #include "../../events/SDL_keyboard_c.h" -void +#include +#include "SDL_x11keytables.h" + +/* Taken from SDL_iconv() */ +#define UNKNOWN_UNICODE 0xFFFD +static Uint32 decodeUtf8(const Uint8 *p) +{ + Uint32 ch = 0; + size_t left = 0; + SDL_bool overlong = SDL_FALSE; + if (p[0] >= 0xFC) { + if ((p[0] & 0xFE) != 0xFC) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + } else { + if (p[0] == 0xFC) { + overlong = SDL_TRUE; + } + ch = (Uint32) (p[0] & 0x01); + left = 5; + } + } else if (p[0] >= 0xF8) { + if ((p[0] & 0xFC) != 0xF8) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + } else { + if (p[0] == 0xF8) { + overlong = SDL_TRUE; + } + ch = (Uint32) (p[0] & 0x03); + left = 4; + } + } else if (p[0] >= 0xF0) { + if ((p[0] & 0xF8) != 0xF0) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + } else { + if (p[0] == 0xF0) { + overlong = SDL_TRUE; + } + ch = (Uint32) (p[0] & 0x07); + left = 3; + } + } else if (p[0] >= 0xE0) { + if ((p[0] & 0xF0) != 0xE0) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + } else { + if (p[0] == 0xE0) { + overlong = SDL_TRUE; + } + ch = (Uint32) (p[0] & 0x0F); + left = 2; + } + } else if (p[0] >= 0xC0) { + if ((p[0] & 0xE0) != 0xC0) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + } else { + if ((p[0] & 0xCE) == 0xC0) { + overlong = SDL_TRUE; + } + ch = (Uint32) (p[0] & 0x1F); + left = 1; + } + } else { + if ((p[0] & 0x80) != 0x00) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + } else { + ch = (Uint32) p[0]; + } + } + while (left--) { + ++p; + if ((p[0] & 0xC0) != 0x80) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + break; + } + ch <<= 6; + ch |= (p[0] & 0x3F); + } + if (overlong) { + /* Potential security risk + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + } + if ((ch >= 0xD800 && ch <= 0xDFFF) || + (ch == 0xFFFE || ch == 0xFFFF) || ch > 0x10FFFF) { + /* Skip illegal sequences + return SDL_ICONV_EILSEQ; + */ + ch = UNKNOWN_UNICODE; + } + return ch; +} + +/* Used for two purposes: + - by X11_GetLayoutKey() to determine whether to return a character code or + an SDLK_ code, and to allow layout-dependence of non-character keys + - by X11_InitKeyboard() to build a makeshift translation table based on the + KeySyms when none of the predefined KeyCode-to-SDLKey tables fits. This is + *not* correct anywhere but on a US layout, since the translation table deals + with physical key codes, while the X11 KeySym corresponds to our concept of + a layout key code, but it's better than nothing. +*/ +static SDLKey +X11_KeySymToSDLKey(KeySym sym, SDL_bool *isCharacterKey) { + /* Do a binary search for sym in the keySymToSDLKey table */ + SDLKey key = SDLK_UNKNOWN | X11_KEY_CHARACTER_BIT; + int start = -1; + int end = SDL_arraysize(keySymToSDLKey); + int i; + /* Invariant: keySymToSDLKey[start].sym < sym < keySymToSDLKey[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 (keySymToSDLKey[i].sym == sym) { + key = keySymToSDLKey[i].key; + break; + } + else if (keySymToSDLKey[i].sym < sym) start = i; + else end = i; + } + if (isCharacterKey != NULL) { + *isCharacterKey = ((key & X11_KEY_CHARACTER_BIT) != 0); + } + key &= ~X11_KEY_CHARACTER_BIT; + return key; +} + +int X11_InitKeyboard(_THIS) { SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; SDL_Keyboard keyboard; + SDLKey **table; + SDL_bool ok; + int i; + KeyCode code; + SDLKey sdlkey; + + /* A random collection of KeySym/SDLKey pairs that should be valid in any + keyboard layout (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 KeyCodeToSDLK tables to find the right one (if any). + */ + struct { KeySym sym; SDLKey key; } fingerprint[] = { + {XK_Tab, SDLK_TAB}, + {XK_Return, SDLK_RETURN}, + {XK_Escape, SDLK_ESCAPE}, + {XK_space, SDLK_SPACE} + }; SDL_zero(keyboard); data->keyboard = SDL_AddKeyboard(&keyboard, -1); + + /* Determine which X11 KeyCode to SDL physical key code table to use */ + + for (table = keyCodeToSDLKeyTables; *table != NULL; table++) { + ok = SDL_TRUE; + for (i = 0; i < SDL_arraysize(fingerprint); i++) { + code = XKeysymToKeycode(data->display, fingerprint[i].sym); + if (code != 0 && (*table)[code - 8] != fingerprint[i].key) { + ok = SDL_FALSE; + break; + } + } + if (ok) break; + } + if (*table != NULL) { + /* Found a suitable one among the predefined tables */ + data->keyCodeToSDLKTable = *table; + } + else { + /* No suitable table found - build a makeshift table based on the KeySyms, assuming a US keyboard layout */ + +#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 + data->keyCodeToSDLKTable = SDL_malloc(248*sizeof(SDLKey)); + if (data->keyCodeToSDLKTable == NULL) { + SDL_OutOfMemory(); + return -1; + } + for (code = 255; code >= 8; code--) { + data->keyCodeToSDLKTable[code - 8] = X11_KeySymToSDLKey(XKeycodeToKeysym(data->display, code, 0), NULL); + } + } + + /* Set some non-default key names */ + + for (code = 0; code < 248; code++) { + sdlkey = data->keyCodeToSDLKTable[code]; + switch (sdlkey) { + /* The SDLK_*META keys are used as XK_Meta_* by some X servers, as XK_Super_* by others */ + case SDLK_LMETA: + case SDLK_RMETA: + switch (XKeycodeToKeysym(data->display, code+8, 0)) { + /* nothing to do for XK_Meta_* because that's already the default name */ + case XK_Super_L: SDL_SetKeyName(sdlkey, "left super"); break; + case XK_Super_R: SDL_SetKeyName(sdlkey, "right super"); break; + } + break; + } + } + SDL_SetKeyName(SDLK_APPLICATION, "menu"); + + return 0; } +SDLKey +X11_GetLayoutKey(_THIS, SDLKey physicalKey) +{ + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + KeyCode code = 0; + KeySym sym; + SDLKey layoutKey; + SDL_bool doStringLookup; + + /* Shortcut handling of keypad numbers because on my PC their primary KeySyms are not the numbers that I want but XK_KP_Home, XK_KP_Up etc. The downside is that this gets us latin numerals even on e.g. an Arabic layout. */ + switch (physicalKey) { + case SDLK_KP_1: return '1'; + case SDLK_KP_2: return '2'; + case SDLK_KP_3: return '3'; + case SDLK_KP_4: return '4'; + case SDLK_KP_5: return '5'; + case SDLK_KP_6: return '6'; + case SDLK_KP_7: return '7'; + case SDLK_KP_8: return '8'; + case SDLK_KP_9: return '9'; + case SDLK_KP_0: return '0'; + case SDLK_KP_PERIOD: return '.'; + default: break; /* just to avoid a compiler warning */ + } + + /* Look up physicalKey to get an X11 KeyCode - linear search isn't terribly efficient, this might have to be optimized. */ + while (code < 248 && physicalKey != data->keyCodeToSDLKTable[code]) code++; + if (code == 248) return physicalKey; + code += 8; + /* Get the corresponding KeySym - this is where the keyboard layout comes into play */ + sym = XKeycodeToKeysym(data->display, code, 0); + + /* See whether to do a string lookup, and if not get the layout SDLK_ code corresponding to the KeySym (for some keys (e.g. tab) the string lookup would yield a character, but not a suitable one as a key name) */ + layoutKey = X11_KeySymToSDLKey(sym, &doStringLookup); + + /* FIXME: A string lookup is not the right thing to do here, since it takes input methods and dead keys into account. What we really want is a static mapping for character keys from KeySyms to single-character key names. However, I currently see no way of achieving that short of using an enormous look-up table. Maybe someone more proficient with X11 than me has a better idea... */ + + if (doStringLookup) { + XKeyPressedEvent fakeEvent; + char buffer[25]; + size_t length; + + /* Set up a fake event for the two string lookup methods */ + SDL_memset(&fakeEvent, 0, sizeof(fakeEvent)); + fakeEvent.type = KeyPress; + fakeEvent.display = data->display; + fakeEvent.state = 0; + fakeEvent.keycode = code; + + /* Try UTF-8 string lookup */ + #ifdef X_HAVE_UTF8_STRING + /* FIXME: I have no clear idea of what an XIC is, but I suspect it's not appropriate to just use the one of the first window... It probably contains dead-key and input method state that we're messing up here. */ + if (data->windowlist[0] != NULL && data->windowlist[0]->ic != NULL) { + Status status; + length = Xutf8LookupString(data->windowlist[0]->ic, &fakeEvent, buffer, sizeof(buffer), NULL, &status); + if ((status == XLookupChars || status == XLookupBoth) && (unsigned char)buffer[0] >= 0x20) { + /* Decode the first character from UTF-8. I'm not sure if this is appropriate in cases where there is more than 1 character, or if we would have to use SDL_KEY_LAYOUT_SPECIAL_BIT in that case. */ + return decodeUtf8((const Uint8*)buffer); + } + } + #endif + + /* Try Latin-1 string lookup */ + length = XLookupString(&fakeEvent, buffer, sizeof(buffer), NULL, NULL); + if (length > 0 && (unsigned char)buffer[0] >= 0x20) { + /* Luckily Unicode code points 128-255 are identical to Latin-1 */ + return (SDLKey)(unsigned char)buffer[0]; + } + + /* Still here? Give up. */ + return physicalKey; + } + return layoutKey; +} + void X11_QuitKeyboard(_THIS) { SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + + if (data->keyCodeToSDLKTable != NULL) { + /* If it's not one of the predefined tables, it was malloced and must be freed */ + SDLKey **table = keyCodeToSDLKeyTables; + while (*table != NULL && *table != data->keyCodeToSDLKTable) table++; + if (*table == NULL) SDL_free(data->keyCodeToSDLKTable); + data->keyCodeToSDLKTable = NULL; + } SDL_DelKeyboard(data->keyboard); } Index: include/SDL_compat.h =================================================================== --- include/SDL_compat.h (revision 3452) +++ include/SDL_compat.h (working copy) @@ -185,7 +185,7 @@ #define SDLK_SCROLLOCK SDLK_SCROLLLOCK #define SDLK_PRINT SDLK_PRINTSCREEN -/* These key constants are obsoleted the new keyboard handling, their definitions here correspond to how they appear on a US keyboard. */ +/* These key constants are obsoleted by the new keyboard handling, their definitions here correspond to how they appear on a US keyboard. */ #define SDLK_EXCLAIM SDLK_1 #define SDLK_QUOTEDBL SDLK_APOSTROPHE #define SDLK_HASH SDLK_3