src/events/SDL_keyboard.c
changeset 2268 4baee598306d
parent 2229 22342048bcb8
child 2295 dbc6d1893869
     1.1 --- a/src/events/SDL_keyboard.c	Sat Aug 18 05:39:09 2007 +0000
     1.2 +++ b/src/events/SDL_keyboard.c	Sun Aug 19 14:52:52 2007 +0000
     1.3 @@ -27,6 +27,7 @@
     1.4  #include "SDL_events.h"
     1.5  #include "SDL_events_c.h"
     1.6  #include "SDL_sysevents.h"
     1.7 +#include "SDL_keynames.h"
     1.8  
     1.9  
    1.10  /* Global keyboard information */
    1.11 @@ -35,246 +36,13 @@
    1.12  static int SDL_current_keyboard;
    1.13  static SDL_Keyboard **SDL_keyboards;
    1.14  
    1.15 -static const char *SDL_keynames[SDLK_LAST];     /* Array of keycode names */
    1.16 -
    1.17  /* Public functions */
    1.18  int
    1.19  SDL_KeyboardInit(void)
    1.20  {
    1.21 -    int i;
    1.22 -
    1.23      /* Set default mode of UNICODE translation */
    1.24      SDL_EnableUNICODE(DEFAULT_UNICODE_TRANSLATION);
    1.25  
    1.26 -    /* Initialize the tables */
    1.27 -    for (i = 0; i < SDL_arraysize(SDL_keynames); ++i) {
    1.28 -        switch (i) {
    1.29 -        case SDLK_BACKSPACE:
    1.30 -            SDL_keynames[i] = "backspace";
    1.31 -            break;
    1.32 -        case SDLK_TAB:
    1.33 -            SDL_keynames[i] = "tab";
    1.34 -            break;
    1.35 -        case SDLK_CLEAR:
    1.36 -            SDL_keynames[i] = "clear";
    1.37 -            break;
    1.38 -        case SDLK_RETURN:
    1.39 -            SDL_keynames[i] = "return";
    1.40 -            break;
    1.41 -        case SDLK_PAUSE:
    1.42 -            SDL_keynames[i] = "pause";
    1.43 -            break;
    1.44 -        case SDLK_ESCAPE:
    1.45 -            SDL_keynames[i] = "escape";
    1.46 -            break;
    1.47 -        case SDLK_SPACE:
    1.48 -            SDL_keynames[i] = "space";
    1.49 -            break;
    1.50 -
    1.51 -        case SDLK_KP0:
    1.52 -            SDL_keynames[i] = "[0]";
    1.53 -            break;
    1.54 -        case SDLK_KP1:
    1.55 -            SDL_keynames[i] = "[1]";
    1.56 -            break;
    1.57 -        case SDLK_KP2:
    1.58 -            SDL_keynames[i] = "[2]";
    1.59 -            break;
    1.60 -        case SDLK_KP3:
    1.61 -            SDL_keynames[i] = "[3]";
    1.62 -            break;
    1.63 -        case SDLK_KP4:
    1.64 -            SDL_keynames[i] = "[4]";
    1.65 -            break;
    1.66 -        case SDLK_KP5:
    1.67 -            SDL_keynames[i] = "[5]";
    1.68 -            break;
    1.69 -        case SDLK_KP6:
    1.70 -            SDL_keynames[i] = "[6]";
    1.71 -            break;
    1.72 -        case SDLK_KP7:
    1.73 -            SDL_keynames[i] = "[7]";
    1.74 -            break;
    1.75 -        case SDLK_KP8:
    1.76 -            SDL_keynames[i] = "[8]";
    1.77 -            break;
    1.78 -        case SDLK_KP9:
    1.79 -            SDL_keynames[i] = "[9]";
    1.80 -            break;
    1.81 -        case SDLK_KP_PERIOD:
    1.82 -            SDL_keynames[i] = "[.]";
    1.83 -            break;
    1.84 -        case SDLK_KP_DIVIDE:
    1.85 -            SDL_keynames[i] = "[/]";
    1.86 -            break;
    1.87 -        case SDLK_KP_MULTIPLY:
    1.88 -            SDL_keynames[i] = "[*]";
    1.89 -            break;
    1.90 -        case SDLK_KP_MINUS:
    1.91 -            SDL_keynames[i] = "[-]";
    1.92 -            break;
    1.93 -        case SDLK_KP_PLUS:
    1.94 -            SDL_keynames[i] = "[+]";
    1.95 -            break;
    1.96 -        case SDLK_KP_ENTER:
    1.97 -            SDL_keynames[i] = "enter";
    1.98 -            break;
    1.99 -        case SDLK_KP_EQUALS:
   1.100 -            SDL_keynames[i] = "equals";
   1.101 -            break;
   1.102 -
   1.103 -        case SDLK_UP:
   1.104 -            SDL_keynames[i] = "up";
   1.105 -            break;
   1.106 -        case SDLK_DOWN:
   1.107 -            SDL_keynames[i] = "down";
   1.108 -            break;
   1.109 -        case SDLK_RIGHT:
   1.110 -            SDL_keynames[i] = "right";
   1.111 -            break;
   1.112 -        case SDLK_LEFT:
   1.113 -            SDL_keynames[i] = "left";
   1.114 -            break;
   1.115 -        case SDLK_INSERT:
   1.116 -            SDL_keynames[i] = "insert";
   1.117 -            break;
   1.118 -        case SDLK_HOME:
   1.119 -            SDL_keynames[i] = "home";
   1.120 -            break;
   1.121 -        case SDLK_END:
   1.122 -            SDL_keynames[i] = "end";
   1.123 -            break;
   1.124 -        case SDLK_PAGEUP:
   1.125 -            SDL_keynames[i] = "page up";
   1.126 -            break;
   1.127 -        case SDLK_PAGEDOWN:
   1.128 -            SDL_keynames[i] = "page down";
   1.129 -            break;
   1.130 -
   1.131 -        case SDLK_F1:
   1.132 -            SDL_keynames[i] = "f1";
   1.133 -            break;
   1.134 -        case SDLK_F2:
   1.135 -            SDL_keynames[i] = "f2";
   1.136 -            break;
   1.137 -        case SDLK_F3:
   1.138 -            SDL_keynames[i] = "f3";
   1.139 -            break;
   1.140 -        case SDLK_F4:
   1.141 -            SDL_keynames[i] = "f4";
   1.142 -            break;
   1.143 -        case SDLK_F5:
   1.144 -            SDL_keynames[i] = "f5";
   1.145 -            break;
   1.146 -        case SDLK_F6:
   1.147 -            SDL_keynames[i] = "f6";
   1.148 -            break;
   1.149 -        case SDLK_F7:
   1.150 -            SDL_keynames[i] = "f7";
   1.151 -            break;
   1.152 -        case SDLK_F8:
   1.153 -            SDL_keynames[i] = "f8";
   1.154 -            break;
   1.155 -        case SDLK_F9:
   1.156 -            SDL_keynames[i] = "f9";
   1.157 -            break;
   1.158 -        case SDLK_F10:
   1.159 -            SDL_keynames[i] = "f10";
   1.160 -            break;
   1.161 -        case SDLK_F11:
   1.162 -            SDL_keynames[i] = "f11";
   1.163 -            break;
   1.164 -        case SDLK_F12:
   1.165 -            SDL_keynames[i] = "f12";
   1.166 -            break;
   1.167 -        case SDLK_F13:
   1.168 -            SDL_keynames[i] = "f13";
   1.169 -            break;
   1.170 -        case SDLK_F14:
   1.171 -            SDL_keynames[i] = "f14";
   1.172 -            break;
   1.173 -        case SDLK_F15:
   1.174 -            SDL_keynames[i] = "f15";
   1.175 -            break;
   1.176 -
   1.177 -        case SDLK_NUMLOCK:
   1.178 -            SDL_keynames[i] = "numlock";
   1.179 -            break;
   1.180 -        case SDLK_CAPSLOCK:
   1.181 -            SDL_keynames[i] = "caps lock";
   1.182 -            break;
   1.183 -        case SDLK_SCROLLOCK:
   1.184 -            SDL_keynames[i] = "scroll lock";
   1.185 -            break;
   1.186 -        case SDLK_RSHIFT:
   1.187 -            SDL_keynames[i] = "right shift";
   1.188 -            break;
   1.189 -        case SDLK_LSHIFT:
   1.190 -            SDL_keynames[i] = "left shift";
   1.191 -            break;
   1.192 -        case SDLK_RCTRL:
   1.193 -            SDL_keynames[i] = "right ctrl";
   1.194 -            break;
   1.195 -        case SDLK_LCTRL:
   1.196 -            SDL_keynames[i] = "left ctrl";
   1.197 -            break;
   1.198 -        case SDLK_RALT:
   1.199 -            SDL_keynames[i] = "right alt";
   1.200 -            break;
   1.201 -        case SDLK_LALT:
   1.202 -            SDL_keynames[i] = "left alt";
   1.203 -            break;
   1.204 -        case SDLK_RMETA:
   1.205 -            SDL_keynames[i] = "right meta";
   1.206 -            break;
   1.207 -        case SDLK_LMETA:
   1.208 -            SDL_keynames[i] = "left meta";
   1.209 -            break;
   1.210 -        case SDLK_LSUPER:
   1.211 -            SDL_keynames[i] = "left super";     /* "Windows" keys */
   1.212 -            break;
   1.213 -        case SDLK_RSUPER:
   1.214 -            SDL_keynames[i] = "right super";
   1.215 -            break;
   1.216 -        case SDLK_MODE:
   1.217 -            SDL_keynames[i] = "alt gr";
   1.218 -            break;
   1.219 -        case SDLK_COMPOSE:
   1.220 -            SDL_keynames[i] = "compose";
   1.221 -            break;
   1.222 -
   1.223 -        case SDLK_HELP:
   1.224 -            SDL_keynames[i] = "help";
   1.225 -            break;
   1.226 -        case SDLK_PRINT:
   1.227 -            SDL_keynames[i] = "print screen";
   1.228 -            break;
   1.229 -        case SDLK_SYSREQ:
   1.230 -            SDL_keynames[i] = "sys req";
   1.231 -            break;
   1.232 -        case SDLK_BREAK:
   1.233 -            SDL_keynames[i] = "break";
   1.234 -            break;
   1.235 -        case SDLK_MENU:
   1.236 -            SDL_keynames[i] = "menu";
   1.237 -            break;
   1.238 -        case SDLK_POWER:
   1.239 -            SDL_keynames[i] = "power";
   1.240 -            break;
   1.241 -        case SDLK_EURO:
   1.242 -            SDL_keynames[i] = "euro";
   1.243 -            break;
   1.244 -        case SDLK_UNDO:
   1.245 -            SDL_keynames[i] = "undo";
   1.246 -            break;
   1.247 -
   1.248 -        default:
   1.249 -            SDL_keynames[i] = NULL;
   1.250 -            break;
   1.251 -        }
   1.252 -    }
   1.253 -
   1.254 -    /* Done.  Whew. */
   1.255      return (0);
   1.256  }
   1.257  
   1.258 @@ -338,7 +106,7 @@
   1.259  SDL_ResetKeyboard(int index)
   1.260  {
   1.261      SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   1.262 -    SDLKey key;
   1.263 +    int key;
   1.264  
   1.265      if (!keyboard) {
   1.266          return;
   1.267 @@ -346,7 +114,8 @@
   1.268  
   1.269      for (key = SDLK_FIRST; key < SDLK_LAST; ++key) {
   1.270          if (keyboard->keystate[key] == SDL_PRESSED) {
   1.271 -            SDL_SendKeyboardKey(index, SDL_RELEASED, 0, key);
   1.272 +            SDL_SendKeyboardKey(index, SDL_RELEASED, 0,
   1.273 +                                key | SDL_KEY_CAN_BE_PHYSICAL_BIT);
   1.274          }
   1.275      }
   1.276  }
   1.277 @@ -432,36 +201,81 @@
   1.278      keyboard->modstate = modstate;
   1.279  }
   1.280  
   1.281 +SDLKey
   1.282 +SDL_GetLayoutKey(SDLKey physicalKey)
   1.283 +{
   1.284 +    SDL_VideoDevice *_this = SDL_GetVideoDevice();
   1.285 +    if (_this && _this->GetLayoutKey) {
   1.286 +        return _this->GetLayoutKey(_this, physicalKey)
   1.287 +            | (physicalKey & SDL_KEY_KEYPAD_BIT);
   1.288 +    } else {
   1.289 +        return physicalKey;
   1.290 +    }
   1.291 +}
   1.292 +
   1.293  const char *
   1.294 -SDL_GetKeyName(SDLKey key)
   1.295 +SDL_GetKeyName(SDLKey layoutKey)
   1.296  {
   1.297 -    const char *keyname;
   1.298 +    const char *keyname = NULL;
   1.299  
   1.300 -    if (key < SDL_arraysize(SDL_keynames)) {
   1.301 -        keyname = SDL_keynames[key];
   1.302 +    if ((layoutKey & SDL_KEY_LAYOUT_SPECIAL_BIT) != 0) {
   1.303 +        SDL_VideoDevice *_this = SDL_GetVideoDevice();
   1.304 +        if (_this && _this->GetSpecialKeyName) {
   1.305 +            keyname = _this->GetSpecialKeyName(_this, layoutKey);
   1.306 +        }
   1.307 +    } else if ((layoutKey & SDL_KEY_CAN_BE_PHYSICAL_BIT) == 0) {
   1.308 +        /* SDLK_INDEX(layoutKey) is the unicode code point of the character generated by the key */
   1.309 +        static char buffer[9];  /* 6 (maximal UTF-8 char length) + 2 ([] for keypad) + 1 (null teminator) */
   1.310 +        char *bufferPtr = &buffer[1];
   1.311 +        SDL_iconv_t cd;
   1.312 +        size_t inbytesleft = 4, outbytesleft = 8;
   1.313 +        Uint32 codepoint = SDLK_INDEX(layoutKey);
   1.314 +        const char *codepointPtr = (const char *) &codepoint;
   1.315 +
   1.316 +        /* 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). */
   1.317 +        if (codepoint >= 'a' && codepoint <= 'z') {
   1.318 +            codepoint -= 32;
   1.319 +        }
   1.320 +
   1.321 +        cd = SDL_iconv_open("UTF-8", "UCS-4");
   1.322 +        if (cd == (SDL_iconv_t) (-1))
   1.323 +            return "";
   1.324 +        SDL_iconv(cd, &codepointPtr, &inbytesleft, &bufferPtr, &outbytesleft);
   1.325 +        SDL_iconv_close(cd);
   1.326 +        *bufferPtr = '\0';
   1.327 +
   1.328 +        if ((layoutKey & SDL_KEY_KEYPAD_BIT) != 0) {
   1.329 +            buffer[0] = '[';
   1.330 +            *bufferPtr++ = ']';
   1.331 +            *bufferPtr = '\0';
   1.332 +            keyname = buffer;
   1.333 +        } else {
   1.334 +            keyname = &buffer[1];
   1.335 +        }
   1.336      } else {
   1.337 -        keyname = NULL;
   1.338 -    }
   1.339 -    if (keyname == NULL) {
   1.340 -        if (key < 256) {
   1.341 -            static char temp[4];
   1.342 -            char *cvt;
   1.343 -            temp[0] = (char) key;
   1.344 -            temp[1] = '\0';
   1.345 -            cvt = SDL_iconv_string("UTF-8", "ISO-8859-1", temp, 1);
   1.346 -            if (cvt) {
   1.347 -                SDL_strlcpy(temp, cvt, SDL_arraysize(temp));
   1.348 -                SDL_free(cvt);
   1.349 -            }
   1.350 -            keyname = temp;
   1.351 -        } else {
   1.352 -            keyname = "unknown key";
   1.353 +        /* SDLK_INDEX(layoutKey) is a physical key number */
   1.354 +        if (SDLK_INDEX(layoutKey) < SDL_arraysize(SDL_keynames)) {
   1.355 +            keyname = SDL_keynames[SDLK_INDEX(layoutKey)];
   1.356          }
   1.357      }
   1.358 +
   1.359 +    if (keyname == NULL) {
   1.360 +        keyname = SDL_keynames[SDLK_INDEX(SDLK_UNKNOWN)];
   1.361 +    }
   1.362 +
   1.363      return keyname;
   1.364  }
   1.365  
   1.366  void
   1.367 +SDL_SetKeyName(SDLKey physicalKey, const char *name)
   1.368 +{
   1.369 +    physicalKey = SDLK_INDEX(physicalKey);
   1.370 +    if (physicalKey < SDL_arraysize(SDL_keynames)) {
   1.371 +        SDL_keynames[physicalKey] = name;
   1.372 +    }
   1.373 +}
   1.374 +
   1.375 +void
   1.376  SDL_SetKeyboardFocus(int index, SDL_WindowID windowID)
   1.377  {
   1.378      SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   1.379 @@ -513,26 +327,27 @@
   1.380  }
   1.381  
   1.382  int
   1.383 -SDL_SendKeyboardKey(int index, Uint8 state, Uint8 scancode, SDLKey key)
   1.384 +SDL_SendKeyboardKey(int index, Uint8 state, Uint8 scancode,
   1.385 +                    SDLKey physicalKey)
   1.386  {
   1.387      SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   1.388      int posted;
   1.389      Uint16 modstate;
   1.390      Uint8 type;
   1.391  
   1.392 -    if (!keyboard) {
   1.393 +    if (!keyboard || physicalKey == SDLK_NONE) {
   1.394          return 0;
   1.395      }
   1.396  #if 0
   1.397 -    printf("The '%s' key has been %s\n", SDL_GetKeyName(key),
   1.398 +    printf("The '%s' key has been %s\n", SDL_GetKeyName(physicalKey),
   1.399             state == SDL_PRESSED ? "pressed" : "released");
   1.400  #endif
   1.401      if (state == SDL_PRESSED) {
   1.402          modstate = keyboard->modstate;
   1.403 -        switch (key) {
   1.404 +        switch (physicalKey) {
   1.405          case SDLK_UNKNOWN:
   1.406              break;
   1.407 -        case SDLK_NUMLOCK:
   1.408 +        case SDLK_KP_NUMLOCKCLEAR:
   1.409              keyboard->modstate ^= KMOD_NUM;
   1.410              break;
   1.411          case SDLK_CAPSLOCK:
   1.412 @@ -569,10 +384,10 @@
   1.413              break;
   1.414          }
   1.415      } else {
   1.416 -        switch (key) {
   1.417 +        switch (physicalKey) {
   1.418          case SDLK_UNKNOWN:
   1.419              break;
   1.420 -        case SDLK_NUMLOCK:
   1.421 +        case SDLK_KP_NUMLOCKCLEAR:
   1.422          case SDLK_CAPSLOCK:
   1.423              break;
   1.424          case SDLK_LCTRL:
   1.425 @@ -621,9 +436,9 @@
   1.426          return 0;
   1.427      }
   1.428  
   1.429 -    if (key != SDLK_UNKNOWN) {
   1.430 +    if (physicalKey != SDLK_UNKNOWN) {
   1.431          /* Drop events that don't change state */
   1.432 -        if (keyboard->keystate[key] == state) {
   1.433 +        if (keyboard->keystate[SDLK_INDEX(physicalKey)] == state) {
   1.434  #if 0
   1.435              printf("Keyboard event didn't change state - dropped!\n");
   1.436  #endif
   1.437 @@ -631,7 +446,7 @@
   1.438          }
   1.439  
   1.440          /* Update internal keyboard state */
   1.441 -        keyboard->keystate[key] = state;
   1.442 +        keyboard->keystate[SDLK_INDEX(physicalKey)] = state;
   1.443      }
   1.444  
   1.445      /* Post the event, if desired */
   1.446 @@ -642,7 +457,7 @@
   1.447          event.key.which = (Uint8) index;
   1.448          event.key.state = state;
   1.449          event.key.keysym.scancode = scancode;
   1.450 -        event.key.keysym.sym = (Uint16) key;
   1.451 +        event.key.keysym.sym = physicalKey;
   1.452          event.key.keysym.mod = modstate;
   1.453          event.key.keysym.unicode = 0;
   1.454          event.key.windowID = keyboard->focus;