Mercurial > sdl-ios-xcode
diff src/video/x11/SDL_x11keyboard.c @ 2295:dbc6d1893869
Checking in Christian Walther's patch for x11 keyboard input. Minor code tweaks by Bob.
author | Bob Pendleton <bob@pendleton.com> |
---|---|
date | Tue, 08 Jan 2008 00:10:46 +0000 |
parents | a344e42bce3b |
children | 0869721b488f |
line wrap: on
line diff
--- a/src/video/x11/SDL_x11keyboard.c Thu Jan 03 06:07:30 2008 +0000 +++ b/src/video/x11/SDL_x11keyboard.c Tue Jan 08 00:10:46 2008 +0000 @@ -25,14 +25,993 @@ #include "../../events/SDL_keyboard_c.h" -void +#include <X11/keysym.h> + +#include "imKStoUCS.h" + +/* Used for two purposes: - by X11_GetLayoutKey(), with physical = + false, to convert a KeySym to the corresponding layout key code + (SDLK_ ones and some character ones - most character KeySyms are + handled by X11_KeySymToUcs4() after this function returns + SDLK_UNKNOWN for them). - by X11_InitKeyboard(), with physical = + true, 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. +*/ + +/* 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[] = { + xorgLinuxKeyCodeToSDLK, + macKeyCodeToSDLK, + 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[] = { + /* 0 */ SDLK_UNKNOWN, + /* 1 */ SDLK_UNKNOWN, + /* 2 */ SDLK_UNKNOWN, + /* 3 */ SDLK_UNKNOWN, + /* 4 */ SDLK_UNKNOWN, + /* 5 */ SDLK_UNKNOWN, + /* 6 */ SDLK_UNKNOWN, + /* 7 */ SDLK_UNKNOWN, + /* 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[] = { + /* 0 */ SDLK_UNKNOWN, + /* 1 */ SDLK_UNKNOWN, + /* 2 */ SDLK_UNKNOWN, + /* 3 */ SDLK_UNKNOWN, + /* 4 */ SDLK_UNKNOWN, + /* 5 */ SDLK_UNKNOWN, + /* 6 */ SDLK_UNKNOWN, + /* 7 */ SDLK_UNKNOWN, + /* 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 (needed in X11_GetLayoutKey()) and a fallback KeySym-to-physical-key + mapping under the assumption of a US keyboard layout (needed in + X11_InitKeyboard()). If for a given KeySym... + - the layout and physical codes are the same (must be an SDLK_ constant): + there is one entry, + - the layout and physical codes differ: there are two entries, with the + layout one first, + - there is only a physical code in the table (must be an SDLK_ constant): + it's marked by X11_KEY_PHYSICAL_ONLY_BIT (this is the case when the layout + key code is handled by KeySymToUcs4()), + - there is only a layout code in the table (can't be an SDLK_ constant): + recognizable by the absence of SDL_KEY_CAN_BE_PHYSICAL_BIT. + This list is sorted by KeySym to allow a binary search. +*/ +#define X11_KEY_PHYSICAL_ONLY_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_PHYSICAL_ONLY_BIT}, { + XK_comma, SDLK_COMMA | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_minus, SDLK_HYPHENMINUS | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_period, SDLK_PERIOD | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_slash, SDLK_SLASH | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_0, SDLK_0 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_1, SDLK_1 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_2, SDLK_2 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_3, SDLK_3 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_4, SDLK_4 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_5, SDLK_5 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_6, SDLK_6 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_7, SDLK_7 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_8, SDLK_8 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_9, SDLK_9 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_semicolon, SDLK_SEMICOLON | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_less, SDLK_NONUSBACKSLASH | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_equal, SDLK_EQUALS | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_bracketleft, SDLK_LEFTBRACKET | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_backslash, SDLK_BACKSLASH | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_bracketright, SDLK_RIGHTBRACKET | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_grave, SDLK_GRAVE | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_a, SDLK_A | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_b, SDLK_B | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_c, SDLK_C | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_d, SDLK_D | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_e, SDLK_E | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_f, SDLK_F | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_g, SDLK_G | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_h, SDLK_H | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_i, SDLK_I | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_j, SDLK_J | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_k, SDLK_K | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_l, SDLK_L | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_m, SDLK_M | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_n, SDLK_N | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_o, SDLK_O | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_p, SDLK_P | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_q, SDLK_Q | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_r, SDLK_R | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_s, SDLK_S | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_t, SDLK_T | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_u, SDLK_U | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_v, SDLK_V | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_w, SDLK_W | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_x, SDLK_X | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_y, SDLK_Y | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_z, SDLK_Z | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_section, SDLK_NONUSBACKSLASH | X11_KEY_PHYSICAL_ONLY_BIT}, + /* 0xFExx */ + { + XK_ISO_Level3_Shift, SDLK_RALT}, { + XK_dead_grave, '`'}, { + XK_dead_acute, 0xB4}, { + XK_dead_circumflex, '^'}, { + XK_dead_tilde, '~'}, { + XK_dead_macron, 0xAF}, { + XK_dead_breve, 0x2D8}, { + XK_dead_abovedot, 0x2D9}, { + XK_dead_diaeresis, 0xA8}, { + XK_dead_abovering, 0x2DA}, { + XK_dead_doubleacute, 0x2DD}, { + XK_dead_caron, 0x2C7}, { + XK_dead_cedilla, 0xB8}, { + XK_dead_ogonek, 0x2DB}, { + XK_dead_iota, 0x3B9}, { + XK_dead_voiced_sound, 0x309B}, { + XK_dead_semivoiced_sound, 0x309C}, { + XK_dead_belowdot, 0xB7}, /* that's actually MIDDLE DOT, but I haven't found a non-combining DOT BELOW */ + /* XK_dead_hook, XK_dead_horn: I haven't found non-combining HOOK and HORN characters */ + /* 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 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_KP_Left, SDLK_KP_4 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_KP_Up, SDLK_KP_8 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_KP_Right, SDLK_KP_6 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_KP_Down, SDLK_KP_2 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_KP_Page_Up, SDLK_KP_9 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_KP_Page_Down, SDLK_KP_3 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_KP_End, SDLK_KP_1 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_KP_Begin, SDLK_KP_5 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_KP_Insert, SDLK_KP_0 | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_KP_Delete, SDLK_KP_PERIOD | X11_KEY_PHYSICAL_ONLY_BIT}, { + XK_KP_Multiply, '*'}, { + XK_KP_Multiply, SDLK_KP_MULTIPLY}, { + XK_KP_Add, '+'}, { + XK_KP_Add, SDLK_KP_PLUS}, { + XK_KP_Separator, '.'}, { + XK_KP_Separator, SDLK_KP_PERIOD}, { + XK_KP_Subtract, '-'}, { + XK_KP_Subtract, SDLK_KP_MINUS}, { + XK_KP_Decimal, '.'}, { + XK_KP_Decimal, SDLK_KP_PERIOD}, { + XK_KP_Divide, '/'}, { + XK_KP_Divide, SDLK_KP_DIVIDE}, { + XK_KP_0, '0'}, { + XK_KP_0, SDLK_KP_0}, { + XK_KP_1, '1'}, { + XK_KP_1, SDLK_KP_1}, { + XK_KP_2, '2'}, { + XK_KP_2, SDLK_KP_2}, { + XK_KP_3, '3'}, { + XK_KP_3, SDLK_KP_3}, { + XK_KP_4, '4'}, { + XK_KP_4, SDLK_KP_4}, { + XK_KP_5, '5'}, { + XK_KP_5, SDLK_KP_5}, { + XK_KP_6, '6'}, { + XK_KP_6, SDLK_KP_6}, { + XK_KP_7, '7'}, { + XK_KP_7, SDLK_KP_7}, { + XK_KP_8, '8'}, { + XK_KP_8, SDLK_KP_8}, { + XK_KP_9, '9'}, { + XK_KP_9, SDLK_KP_9}, { + XK_KP_Equal, '='}, { + XK_KP_Equal, SDLK_KP_EQUALS}, { + 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 */ +}; + +static SDLKey +X11_KeySymToSDLKey(KeySym sym, SDL_bool physical) +{ + /* Do a binary search for sym in the keySymToSDLKey table */ + SDLKey key = SDLK_UNKNOWN; + 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) { + /* found an entry, if it's the second of two back up to the first */ + if (keySymToSDLKey[i - 1].sym == sym) + i--; + /* if there are two, the physical one is the second */ + if (physical && keySymToSDLKey[i + 1].sym == sym) + i++; + key = keySymToSDLKey[i].key; + break; + } else if (keySymToSDLKey[i].sym < sym) + start = i; + else + end = i; + } + + /* if we're being asked for a layout key code, but the table only + has a physical one, or vice versa, return SDLK_UNKNOWN) */ + + if (!physical && ((key & X11_KEY_PHYSICAL_ONLY_BIT) != 0) + || physical && ((key & SDL_KEY_CAN_BE_PHYSICAL_BIT) == 0)) + key = SDLK_UNKNOWN; + key &= ~X11_KEY_PHYSICAL_ONLY_BIT; + return key; +} + +int X11_InitKeyboard(_THIS) { SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; SDL_Keyboard keyboard; + SDLKey **table; + SDLKey *foundTable; + int i; + int 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 */ + + foundTable = NULL; + table = keyCodeToSDLKeyTables; + while ((NULL == foundTable) && (NULL != (*table))) { + foundTable = *table; + for (i = 0; i < SDL_arraysize(fingerprint); i++) { + code = XKeysymToKeycode(data->display, fingerprint[i].sym); + if ((code != 0) && ((*table)[code] != fingerprint[i].key)) { + foundTable = NULL; + break; + } + } + table++; + } + + if (NULL != foundTable) { + /* Found a suitable one among the predefined tables */ + data->keyCodeToSDLKTable = foundTable; + } 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 <sdl@libsdl.org> or to Christian Walther <cwalther@gmx.ch>.\n"); +#endif + data->keyCodeToSDLKTable = + SDL_malloc(SDL_arraysize(xorgLinuxKeyCodeToSDLK)); + if (data->keyCodeToSDLKTable == NULL) { + SDL_OutOfMemory(); + return -1; + } + for (code = SDL_arraysize(xorgLinuxKeyCodeToSDLK); code >= 0; code--) { + data->keyCodeToSDLKTable[code] = + X11_KeySymToSDLKey(XKeycodeToKeysym(data->display, code, 0), + SDL_TRUE); + } + } + + /* Set some non-default key names */ + + for (code = 0; code < SDL_arraysize(xorgLinuxKeyCodeToSDLK); 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, 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; + int code = 0; + KeySym sym; + SDLKey layoutKey; + + switch (physicalKey) { + case SDLK_UNKNOWN: + return physicalKey; + + /* 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. */ + 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 < SDL_arraysize(xorgLinuxKeyCodeToSDLK) && physicalKey) + != data->keyCodeToSDLKTable[code]) { + code++; + } + + if (code == SDL_arraysize(xorgLinuxKeyCodeToSDLK)) { + return physicalKey; + } + /* Get the corresponding KeySym - this is where the keyboard + layout comes into play */ + sym = XKeycodeToKeysym(data->display, code, 0); + + /* Try our own KeySym-to-layout-key-code table: it handles all + keys whose layout code is an SDLK_ one, including a few where + X11_KeySymToUcs4() would yield a character, but not a suitable + one as a key name (e.g. space), and some that are character + keys for our purposes, but aren't handled by X11_KeySymToUcs4() + (dead keys, keypad operations). */ + + layoutKey = X11_KeySymToSDLKey(sym, SDL_FALSE); + + /* If it wasn't handled by X11_KeySymToSDLKey(), it's most + probably a plain character KeySym that X11_KeySymToUcs4() + (ripped from X.org) knows. */ + + if (layoutKey == SDLK_UNKNOWN) { + unsigned int ucs = X11_KeySymToUcs4(sym); + if (ucs != 0) + layoutKey = (SDLKey) ucs; + } + + /* Still no success? Give up. */ + if (layoutKey == SDLK_UNKNOWN) { + return physicalKey; + } + + return layoutKey; } void @@ -40,6 +1019,18 @@ { 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); }