| 1 | /* |
| 2 | SDL - Simple DirectMedia Layer |
| 3 | Copyright (C) 1997-2009 Sam Lantinga |
| 4 | |
| 5 | This library is free software; you can redistribute it and/or |
| 6 | modify it under the terms of the GNU Lesser General Public |
| 7 | License as published by the Free Software Foundation; either |
| 8 | version 2.1 of the License, or (at your option) any later version. |
| 9 | |
| 10 | This library is distributed in the hope that it will be useful, |
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 13 | Lesser General Public License for more details. |
| 14 | |
| 15 | You should have received a copy of the GNU Lesser General Public |
| 16 | License along with this library; if not, write to the Free Software |
| 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 18 | |
| 19 | Sam Lantinga |
| 20 | slouken@libsdl.org |
| 21 | */ |
| 22 | #include "SDL_config.h" |
| 23 | |
| 24 | /* Handle the event stream, converting X11 events into SDL events */ |
| 25 | |
| 26 | #include <vga.h> |
| 27 | #include <vgamouse.h> |
| 28 | #include <vgakeyboard.h> |
| 29 | #if defined(__LINUX__) |
| 30 | #include <linux/kd.h> |
| 31 | #include <linux/keyboard.h> |
| 32 | #elif defined(__FREEBSD__) |
| 33 | #include <sys/kbio.h> |
| 34 | #else |
| 35 | #error You must choose your operating system here |
| 36 | #endif |
| 37 | |
| 38 | #include "../../events/SDL_sysevents.h" |
| 39 | #include "../../events/SDL_events_c.h" |
| 40 | #include "SDL_svgavideo.h" |
| 41 | #include "SDL_svgaevents_c.h" |
| 42 | |
| 43 | /* The translation tables from a console scancode to a SDL keysym */ |
| 44 | #if defined(linux) |
| 45 | #define NUM_VGAKEYMAPS (1<<KG_CAPSSHIFT) |
| 46 | static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS]; |
| 47 | #elif defined(__FREEBSD__) |
| 48 | /* FIXME: Free the keymap when we shut down the video mode */ |
| 49 | static keymap_t *vga_keymap = NULL; |
| 50 | #else |
| 51 | #error You must choose your operating system here |
| 52 | #endif |
| 53 | static SDLKey keymap[128]; |
| 54 | static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym); |
| 55 | |
| 56 | /* Ugh, we have to duplicate the kernel's keysym mapping code... |
| 57 | Oh, it's not so bad. :-) |
| 58 | |
| 59 | FIXME: Add keyboard LED handling code |
| 60 | */ |
| 61 | #if defined(linux) |
| 62 | int SVGA_initkeymaps(int fd) |
| 63 | { |
| 64 | struct kbentry entry; |
| 65 | int map, i; |
| 66 | |
| 67 | /* Load all the keysym mappings */ |
| 68 | for ( map=0; map<NUM_VGAKEYMAPS; ++map ) { |
| 69 | SDL_memset(vga_keymap[map], 0, NR_KEYS*sizeof(Uint16)); |
| 70 | for ( i=0; i<NR_KEYS; ++i ) { |
| 71 | entry.kb_table = map; |
| 72 | entry.kb_index = i; |
| 73 | if ( ioctl(fd, KDGKBENT, &entry) == 0 ) { |
| 74 | /* The "Enter" key is a special case */ |
| 75 | if ( entry.kb_value == K_ENTER ) { |
| 76 | entry.kb_value = K(KT_ASCII,13); |
| 77 | } |
| 78 | /* Handle numpad specially as well */ |
| 79 | if ( KTYP(entry.kb_value) == KT_PAD ) { |
| 80 | switch ( entry.kb_value ) { |
| 81 | case K_P0: |
| 82 | case K_P1: |
| 83 | case K_P2: |
| 84 | case K_P3: |
| 85 | case K_P4: |
| 86 | case K_P5: |
| 87 | case K_P6: |
| 88 | case K_P7: |
| 89 | case K_P8: |
| 90 | case K_P9: |
| 91 | vga_keymap[map][i]=entry.kb_value; |
| 92 | vga_keymap[map][i]+= '0'; |
| 93 | break; |
| 94 | case K_PPLUS: |
| 95 | vga_keymap[map][i]=K(KT_ASCII,'+'); |
| 96 | break; |
| 97 | case K_PMINUS: |
| 98 | vga_keymap[map][i]=K(KT_ASCII,'-'); |
| 99 | break; |
| 100 | case K_PSTAR: |
| 101 | vga_keymap[map][i]=K(KT_ASCII,'*'); |
| 102 | break; |
| 103 | case K_PSLASH: |
| 104 | vga_keymap[map][i]=K(KT_ASCII,'/'); |
| 105 | break; |
| 106 | case K_PENTER: |
| 107 | vga_keymap[map][i]=K(KT_ASCII,'\r'); |
| 108 | break; |
| 109 | case K_PCOMMA: |
| 110 | vga_keymap[map][i]=K(KT_ASCII,','); |
| 111 | break; |
| 112 | case K_PDOT: |
| 113 | vga_keymap[map][i]=K(KT_ASCII,'.'); |
| 114 | break; |
| 115 | default: |
| 116 | break; |
| 117 | } |
| 118 | } |
| 119 | /* Do the normal key translation */ |
| 120 | if ( (KTYP(entry.kb_value) == KT_LATIN) || |
| 121 | (KTYP(entry.kb_value) == KT_ASCII) || |
| 122 | (KTYP(entry.kb_value) == KT_LETTER) ) { |
| 123 | vga_keymap[map][i] = entry.kb_value; |
| 124 | } |
| 125 | } |
| 126 | } |
| 127 | } |
| 128 | return(0); |
| 129 | } |
| 130 | #elif defined(__FREEBSD__) |
| 131 | int SVGA_initkeymaps(int fd) |
| 132 | { |
| 133 | vga_keymap = SDL_malloc(sizeof(keymap_t)); |
| 134 | if ( ! vga_keymap ) { |
| 135 | SDL_OutOfMemory(); |
| 136 | return(-1); |
| 137 | } |
| 138 | if (ioctl(fd, GIO_KEYMAP, vga_keymap) == -1) { |
| 139 | SDL_free(vga_keymap); |
| 140 | vga_keymap = NULL; |
| 141 | SDL_SetError("Unable to get keyboard map"); |
| 142 | return(-1); |
| 143 | } |
| 144 | return(0); |
| 145 | } |
| 146 | #else |
| 147 | #error You must choose your operating system here |
| 148 | #endif |
| 149 | |
| 150 | int posted = 0; |
| 151 | |
| 152 | void SVGA_mousecallback(int button, int dx, int dy, |
| 153 | int u1,int u2,int u3, int u4) |
| 154 | { |
| 155 | if ( dx || dy ) { |
| 156 | posted += SDL_PrivateMouseMotion(0, 1, dx, dy); |
| 157 | } |
| 158 | if ( button & MOUSE_LEFTBUTTON ) { |
| 159 | if ( !(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(1)) ) { |
| 160 | posted += SDL_PrivateMouseButton(SDL_PRESSED, 1, 0, 0); |
| 161 | } |
| 162 | } else { |
| 163 | if ( (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(1)) ) { |
| 164 | posted += SDL_PrivateMouseButton(SDL_RELEASED, 1, 0, 0); |
| 165 | } |
| 166 | } |
| 167 | if ( button & MOUSE_MIDDLEBUTTON ) { |
| 168 | if ( !(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(2)) ) { |
| 169 | posted += SDL_PrivateMouseButton(SDL_PRESSED, 2, 0, 0); |
| 170 | } |
| 171 | } else { |
| 172 | if ( (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(2)) ) { |
| 173 | posted += SDL_PrivateMouseButton(SDL_RELEASED, 2, 0, 0); |
| 174 | } |
| 175 | } |
| 176 | if ( button & MOUSE_RIGHTBUTTON ) { |
| 177 | if ( !(SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(3)) ) { |
| 178 | posted += SDL_PrivateMouseButton(SDL_PRESSED, 3, 0, 0); |
| 179 | } |
| 180 | } else { |
| 181 | if ( (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(3)) ) { |
| 182 | posted += SDL_PrivateMouseButton(SDL_RELEASED, 3, 0, 0); |
| 183 | } |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | void SVGA_keyboardcallback(int scancode, int pressed) |
| 188 | { |
| 189 | SDL_keysym keysym; |
| 190 | |
| 191 | if ( pressed ) { |
| 192 | posted += SDL_PrivateKeyboard(SDL_PRESSED, |
| 193 | TranslateKey(scancode, &keysym)); |
| 194 | } else { |
| 195 | posted += SDL_PrivateKeyboard(SDL_RELEASED, |
| 196 | TranslateKey(scancode, &keysym)); |
| 197 | } |
| 198 | } |
| 199 | |
| 200 | void SVGA_PumpEvents(_THIS) |
| 201 | { |
| 202 | do { |
| 203 | posted = 0; |
| 204 | mouse_update(); |
| 205 | keyboard_update(); |
| 206 | } while ( posted ); |
| 207 | } |
| 208 | |
| 209 | void SVGA_InitOSKeymap(_THIS) |
| 210 | { |
| 211 | int i; |
| 212 | |
| 213 | /* Initialize the BeOS key translation table */ |
| 214 | for ( i=0; i<SDL_arraysize(keymap); ++i ) |
| 215 | keymap[i] = SDLK_UNKNOWN; |
| 216 | |
| 217 | keymap[SCANCODE_ESCAPE] = SDLK_ESCAPE; |
| 218 | keymap[SCANCODE_1] = SDLK_1; |
| 219 | keymap[SCANCODE_2] = SDLK_2; |
| 220 | keymap[SCANCODE_3] = SDLK_3; |
| 221 | keymap[SCANCODE_4] = SDLK_4; |
| 222 | keymap[SCANCODE_5] = SDLK_5; |
| 223 | keymap[SCANCODE_6] = SDLK_6; |
| 224 | keymap[SCANCODE_7] = SDLK_7; |
| 225 | keymap[SCANCODE_8] = SDLK_8; |
| 226 | keymap[SCANCODE_9] = SDLK_9; |
| 227 | keymap[SCANCODE_0] = SDLK_0; |
| 228 | keymap[SCANCODE_MINUS] = SDLK_MINUS; |
| 229 | keymap[SCANCODE_EQUAL] = SDLK_EQUALS; |
| 230 | keymap[SCANCODE_BACKSPACE] = SDLK_BACKSPACE; |
| 231 | keymap[SCANCODE_TAB] = SDLK_TAB; |
| 232 | keymap[SCANCODE_Q] = SDLK_q; |
| 233 | keymap[SCANCODE_W] = SDLK_w; |
| 234 | keymap[SCANCODE_E] = SDLK_e; |
| 235 | keymap[SCANCODE_R] = SDLK_r; |
| 236 | keymap[SCANCODE_T] = SDLK_t; |
| 237 | keymap[SCANCODE_Y] = SDLK_y; |
| 238 | keymap[SCANCODE_U] = SDLK_u; |
| 239 | keymap[SCANCODE_I] = SDLK_i; |
| 240 | keymap[SCANCODE_O] = SDLK_o; |
| 241 | keymap[SCANCODE_P] = SDLK_p; |
| 242 | keymap[SCANCODE_BRACKET_LEFT] = SDLK_LEFTBRACKET; |
| 243 | keymap[SCANCODE_BRACKET_RIGHT] = SDLK_RIGHTBRACKET; |
| 244 | keymap[SCANCODE_ENTER] = SDLK_RETURN; |
| 245 | keymap[SCANCODE_LEFTCONTROL] = SDLK_LCTRL; |
| 246 | keymap[SCANCODE_A] = SDLK_a; |
| 247 | keymap[SCANCODE_S] = SDLK_s; |
| 248 | keymap[SCANCODE_D] = SDLK_d; |
| 249 | keymap[SCANCODE_F] = SDLK_f; |
| 250 | keymap[SCANCODE_G] = SDLK_g; |
| 251 | keymap[SCANCODE_H] = SDLK_h; |
| 252 | keymap[SCANCODE_J] = SDLK_j; |
| 253 | keymap[SCANCODE_K] = SDLK_k; |
| 254 | keymap[SCANCODE_L] = SDLK_l; |
| 255 | keymap[SCANCODE_SEMICOLON] = SDLK_SEMICOLON; |
| 256 | keymap[SCANCODE_APOSTROPHE] = SDLK_QUOTE; |
| 257 | keymap[SCANCODE_GRAVE] = SDLK_BACKQUOTE; |
| 258 | keymap[SCANCODE_LEFTSHIFT] = SDLK_LSHIFT; |
| 259 | keymap[SCANCODE_BACKSLASH] = SDLK_BACKSLASH; |
| 260 | keymap[SCANCODE_Z] = SDLK_z; |
| 261 | keymap[SCANCODE_X] = SDLK_x; |
| 262 | keymap[SCANCODE_C] = SDLK_c; |
| 263 | keymap[SCANCODE_V] = SDLK_v; |
| 264 | keymap[SCANCODE_B] = SDLK_b; |
| 265 | keymap[SCANCODE_N] = SDLK_n; |
| 266 | keymap[SCANCODE_M] = SDLK_m; |
| 267 | keymap[SCANCODE_COMMA] = SDLK_COMMA; |
| 268 | keymap[SCANCODE_PERIOD] = SDLK_PERIOD; |
| 269 | keymap[SCANCODE_SLASH] = SDLK_SLASH; |
| 270 | keymap[SCANCODE_RIGHTSHIFT] = SDLK_RSHIFT; |
| 271 | keymap[SCANCODE_KEYPADMULTIPLY] = SDLK_KP_MULTIPLY; |
| 272 | keymap[SCANCODE_LEFTALT] = SDLK_LALT; |
| 273 | keymap[SCANCODE_SPACE] = SDLK_SPACE; |
| 274 | keymap[SCANCODE_CAPSLOCK] = SDLK_CAPSLOCK; |
| 275 | keymap[SCANCODE_F1] = SDLK_F1; |
| 276 | keymap[SCANCODE_F2] = SDLK_F2; |
| 277 | keymap[SCANCODE_F3] = SDLK_F3; |
| 278 | keymap[SCANCODE_F4] = SDLK_F4; |
| 279 | keymap[SCANCODE_F5] = SDLK_F5; |
| 280 | keymap[SCANCODE_F6] = SDLK_F6; |
| 281 | keymap[SCANCODE_F7] = SDLK_F7; |
| 282 | keymap[SCANCODE_F8] = SDLK_F8; |
| 283 | keymap[SCANCODE_F9] = SDLK_F9; |
| 284 | keymap[SCANCODE_F10] = SDLK_F10; |
| 285 | keymap[SCANCODE_NUMLOCK] = SDLK_NUMLOCK; |
| 286 | keymap[SCANCODE_SCROLLLOCK] = SDLK_SCROLLOCK; |
| 287 | keymap[SCANCODE_KEYPAD7] = SDLK_KP7; |
| 288 | keymap[SCANCODE_CURSORUPLEFT] = SDLK_KP7; |
| 289 | keymap[SCANCODE_KEYPAD8] = SDLK_KP8; |
| 290 | keymap[SCANCODE_CURSORUP] = SDLK_KP8; |
| 291 | keymap[SCANCODE_KEYPAD9] = SDLK_KP9; |
| 292 | keymap[SCANCODE_CURSORUPRIGHT] = SDLK_KP9; |
| 293 | keymap[SCANCODE_KEYPADMINUS] = SDLK_KP_MINUS; |
| 294 | keymap[SCANCODE_KEYPAD4] = SDLK_KP4; |
| 295 | keymap[SCANCODE_CURSORLEFT] = SDLK_KP4; |
| 296 | keymap[SCANCODE_KEYPAD5] = SDLK_KP5; |
| 297 | keymap[SCANCODE_KEYPAD6] = SDLK_KP6; |
| 298 | keymap[SCANCODE_CURSORRIGHT] = SDLK_KP6; |
| 299 | keymap[SCANCODE_KEYPADPLUS] = SDLK_KP_PLUS; |
| 300 | keymap[SCANCODE_KEYPAD1] = SDLK_KP1; |
| 301 | keymap[SCANCODE_CURSORDOWNLEFT] = SDLK_KP1; |
| 302 | keymap[SCANCODE_KEYPAD2] = SDLK_KP2; |
| 303 | keymap[SCANCODE_CURSORDOWN] = SDLK_KP2; |
| 304 | keymap[SCANCODE_KEYPAD3] = SDLK_KP3; |
| 305 | keymap[SCANCODE_CURSORDOWNRIGHT] = SDLK_KP3; |
| 306 | keymap[SCANCODE_KEYPAD0] = SDLK_KP0; |
| 307 | keymap[SCANCODE_KEYPADPERIOD] = SDLK_KP_PERIOD; |
| 308 | keymap[SCANCODE_LESS] = SDLK_LESS; |
| 309 | keymap[SCANCODE_F11] = SDLK_F11; |
| 310 | keymap[SCANCODE_F12] = SDLK_F12; |
| 311 | keymap[SCANCODE_KEYPADENTER] = SDLK_KP_ENTER; |
| 312 | keymap[SCANCODE_RIGHTCONTROL] = SDLK_RCTRL; |
| 313 | keymap[SCANCODE_CONTROL] = SDLK_RCTRL; |
| 314 | keymap[SCANCODE_KEYPADDIVIDE] = SDLK_KP_DIVIDE; |
| 315 | keymap[SCANCODE_PRINTSCREEN] = SDLK_PRINT; |
| 316 | keymap[SCANCODE_RIGHTALT] = SDLK_RALT; |
| 317 | keymap[SCANCODE_BREAK] = SDLK_BREAK; |
| 318 | keymap[SCANCODE_BREAK_ALTERNATIVE] = SDLK_UNKNOWN; |
| 319 | keymap[SCANCODE_HOME] = SDLK_HOME; |
| 320 | keymap[SCANCODE_CURSORBLOCKUP] = SDLK_UP; |
| 321 | keymap[SCANCODE_PAGEUP] = SDLK_PAGEUP; |
| 322 | keymap[SCANCODE_CURSORBLOCKLEFT] = SDLK_LEFT; |
| 323 | keymap[SCANCODE_CURSORBLOCKRIGHT] = SDLK_RIGHT; |
| 324 | keymap[SCANCODE_END] = SDLK_END; |
| 325 | keymap[SCANCODE_CURSORBLOCKDOWN] = SDLK_DOWN; |
| 326 | keymap[SCANCODE_PAGEDOWN] = SDLK_PAGEDOWN; |
| 327 | keymap[SCANCODE_INSERT] = SDLK_INSERT; |
| 328 | keymap[SCANCODE_REMOVE] = SDLK_DELETE; |
| 329 | keymap[119] = SDLK_PAUSE; |
| 330 | keymap[SCANCODE_RIGHTWIN] = SDLK_RSUPER; |
| 331 | keymap[SCANCODE_LEFTWIN] = SDLK_LSUPER; |
| 332 | keymap[127] = SDLK_MENU; |
| 333 | } |
| 334 | |
| 335 | #if defined(linux) |
| 336 | static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) |
| 337 | { |
| 338 | /* Set the keysym information */ |
| 339 | keysym->scancode = scancode; |
| 340 | keysym->sym = keymap[scancode]; |
| 341 | keysym->mod = KMOD_NONE; |
| 342 | |
| 343 | /* If UNICODE is on, get the UNICODE value for the key */ |
| 344 | keysym->unicode = 0; |
| 345 | if ( SDL_TranslateUNICODE ) { |
| 346 | int map; |
| 347 | SDLMod modstate; |
| 348 | |
| 349 | modstate = SDL_GetModState(); |
| 350 | map = 0; |
| 351 | if ( modstate & KMOD_SHIFT ) { |
| 352 | map |= (1<<KG_SHIFT); |
| 353 | } |
| 354 | if ( modstate & KMOD_CTRL ) { |
| 355 | map |= (1<<KG_CTRL); |
| 356 | } |
| 357 | if ( modstate & KMOD_ALT ) { |
| 358 | map |= (1<<KG_ALT); |
| 359 | } |
| 360 | if ( modstate & KMOD_MODE ) { |
| 361 | map |= (1<<KG_ALTGR); |
| 362 | } |
| 363 | if ( KTYP(vga_keymap[map][scancode]) == KT_LETTER ) { |
| 364 | if ( modstate & KMOD_CAPS ) { |
| 365 | map ^= (1<<KG_SHIFT); |
| 366 | } |
| 367 | } |
| 368 | if ( KTYP(vga_keymap[map][scancode]) == KT_PAD ) { |
| 369 | if ( modstate & KMOD_NUM ) { |
| 370 | keysym->unicode=KVAL(vga_keymap[map][scancode]); |
| 371 | } |
| 372 | } else { |
| 373 | keysym->unicode = KVAL(vga_keymap[map][scancode]); |
| 374 | } |
| 375 | } |
| 376 | return(keysym); |
| 377 | } |
| 378 | #elif defined(__FREEBSD__) |
| 379 | static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym) |
| 380 | { |
| 381 | /* Set the keysym information */ |
| 382 | keysym->scancode = scancode; |
| 383 | keysym->sym = keymap[scancode]; |
| 384 | keysym->mod = KMOD_NONE; |
| 385 | |
| 386 | /* If UNICODE is on, get the UNICODE value for the key */ |
| 387 | keysym->unicode = 0; |
| 388 | if ( SDL_TranslateUNICODE && vga_keymap ) { |
| 389 | int map; |
| 390 | SDLMod modstate; |
| 391 | |
| 392 | modstate = SDL_GetModState(); |
| 393 | map = 0; |
| 394 | if ( modstate & KMOD_SHIFT ) { |
| 395 | map += 1; |
| 396 | } |
| 397 | if ( modstate & KMOD_CTRL ) { |
| 398 | map += 2; |
| 399 | } |
| 400 | if ( modstate & KMOD_ALT ) { |
| 401 | map += 4; |
| 402 | } |
| 403 | if ( !(vga_keymap->key[scancode].spcl & (0x80 >> map)) ) { |
| 404 | keysym->unicode = vga_keymap->key[scancode].map[map]; |
| 405 | } |
| 406 | |
| 407 | } |
| 408 | return(keysym); |
| 409 | } |
| 410 | #else |
| 411 | #error You must choose your operating system here |
| 412 | #endif |