src/events/SDL_keyboard.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 30 Jun 2006 08:18:44 +0000
branchSDL-1.3
changeset 1722 5daa04d862f1
parent 1720 a1ebb17f9c52
child 1724 6c63fc2bd986
permissions -rw-r--r--
Added a userdata parameter for event filters.
Added a function to filter the existing queued events.
Added explicit support for relative mouse mode to the API.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 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 /* General keyboard handling code for SDL */
    25 
    26 #include "SDL_timer.h"
    27 #include "SDL_events.h"
    28 #include "SDL_events_c.h"
    29 #include "SDL_sysevents.h"
    30 
    31 
    32 /* Global keyboard information */
    33 int SDL_TranslateUNICODE = 0;
    34 static int SDL_num_keyboards;
    35 static int SDL_current_keyboard;
    36 static SDL_Keyboard **SDL_keyboards;
    37 
    38 static const char *SDL_keynames[SDLK_LAST];     /* Array of keycode names */
    39 
    40 /* Public functions */
    41 int
    42 SDL_KeyboardInit(void)
    43 {
    44     int i;
    45 
    46     /* Set default mode of UNICODE translation */
    47     SDL_EnableUNICODE(DEFAULT_UNICODE_TRANSLATION);
    48 
    49     /* Initialize the tables */
    50     for (i = 0; i < SDL_arraysize(SDL_keynames); ++i) {
    51         switch (i) {
    52         case SDLK_BACKSPACE:
    53             SDL_keynames[i] = "backspace";
    54             break;
    55         case SDLK_TAB:
    56             SDL_keynames[i] = "tab";
    57             break;
    58         case SDLK_CLEAR:
    59             SDL_keynames[i] = "clear";
    60             break;
    61         case SDLK_RETURN:
    62             SDL_keynames[i] = "return";
    63             break;
    64         case SDLK_PAUSE:
    65             SDL_keynames[i] = "pause";
    66             break;
    67         case SDLK_ESCAPE:
    68             SDL_keynames[i] = "escape";
    69             break;
    70         case SDLK_SPACE:
    71             SDL_keynames[i] = "space";
    72             break;
    73 
    74         case SDLK_KP0:
    75             SDL_keynames[i] = "[0]";
    76             break;
    77         case SDLK_KP1:
    78             SDL_keynames[i] = "[1]";
    79             break;
    80         case SDLK_KP2:
    81             SDL_keynames[i] = "[2]";
    82             break;
    83         case SDLK_KP3:
    84             SDL_keynames[i] = "[3]";
    85             break;
    86         case SDLK_KP4:
    87             SDL_keynames[i] = "[4]";
    88             break;
    89         case SDLK_KP5:
    90             SDL_keynames[i] = "[5]";
    91             break;
    92         case SDLK_KP6:
    93             SDL_keynames[i] = "[6]";
    94             break;
    95         case SDLK_KP7:
    96             SDL_keynames[i] = "[7]";
    97             break;
    98         case SDLK_KP8:
    99             SDL_keynames[i] = "[8]";
   100             break;
   101         case SDLK_KP9:
   102             SDL_keynames[i] = "[9]";
   103             break;
   104         case SDLK_KP_PERIOD:
   105             SDL_keynames[i] = "[.]";
   106             break;
   107         case SDLK_KP_DIVIDE:
   108             SDL_keynames[i] = "[/]";
   109             break;
   110         case SDLK_KP_MULTIPLY:
   111             SDL_keynames[i] = "[*]";
   112             break;
   113         case SDLK_KP_MINUS:
   114             SDL_keynames[i] = "[-]";
   115             break;
   116         case SDLK_KP_PLUS:
   117             SDL_keynames[i] = "[+]";
   118             break;
   119         case SDLK_KP_ENTER:
   120             SDL_keynames[i] = "enter";
   121             break;
   122         case SDLK_KP_EQUALS:
   123             SDL_keynames[i] = "equals";
   124             break;
   125 
   126         case SDLK_UP:
   127             SDL_keynames[i] = "up";
   128             break;
   129         case SDLK_DOWN:
   130             SDL_keynames[i] = "down";
   131             break;
   132         case SDLK_RIGHT:
   133             SDL_keynames[i] = "right";
   134             break;
   135         case SDLK_LEFT:
   136             SDL_keynames[i] = "left";
   137             break;
   138         case SDLK_INSERT:
   139             SDL_keynames[i] = "insert";
   140             break;
   141         case SDLK_HOME:
   142             SDL_keynames[i] = "home";
   143             break;
   144         case SDLK_END:
   145             SDL_keynames[i] = "end";
   146             break;
   147         case SDLK_PAGEUP:
   148             SDL_keynames[i] = "page up";
   149             break;
   150         case SDLK_PAGEDOWN:
   151             SDL_keynames[i] = "page down";
   152             break;
   153 
   154         case SDLK_F1:
   155             SDL_keynames[i] = "f1";
   156             break;
   157         case SDLK_F2:
   158             SDL_keynames[i] = "f2";
   159             break;
   160         case SDLK_F3:
   161             SDL_keynames[i] = "f3";
   162             break;
   163         case SDLK_F4:
   164             SDL_keynames[i] = "f4";
   165             break;
   166         case SDLK_F5:
   167             SDL_keynames[i] = "f5";
   168             break;
   169         case SDLK_F6:
   170             SDL_keynames[i] = "f6";
   171             break;
   172         case SDLK_F7:
   173             SDL_keynames[i] = "f7";
   174             break;
   175         case SDLK_F8:
   176             SDL_keynames[i] = "f8";
   177             break;
   178         case SDLK_F9:
   179             SDL_keynames[i] = "f9";
   180             break;
   181         case SDLK_F10:
   182             SDL_keynames[i] = "f10";
   183             break;
   184         case SDLK_F11:
   185             SDL_keynames[i] = "f11";
   186             break;
   187         case SDLK_F12:
   188             SDL_keynames[i] = "f12";
   189             break;
   190         case SDLK_F13:
   191             SDL_keynames[i] = "f13";
   192             break;
   193         case SDLK_F14:
   194             SDL_keynames[i] = "f14";
   195             break;
   196         case SDLK_F15:
   197             SDL_keynames[i] = "f15";
   198             break;
   199 
   200         case SDLK_NUMLOCK:
   201             SDL_keynames[i] = "numlock";
   202             break;
   203         case SDLK_CAPSLOCK:
   204             SDL_keynames[i] = "caps lock";
   205             break;
   206         case SDLK_SCROLLOCK:
   207             SDL_keynames[i] = "scroll lock";
   208             break;
   209         case SDLK_RSHIFT:
   210             SDL_keynames[i] = "right shift";
   211             break;
   212         case SDLK_LSHIFT:
   213             SDL_keynames[i] = "left shift";
   214             break;
   215         case SDLK_RCTRL:
   216             SDL_keynames[i] = "right ctrl";
   217             break;
   218         case SDLK_LCTRL:
   219             SDL_keynames[i] = "left ctrl";
   220             break;
   221         case SDLK_RALT:
   222             SDL_keynames[i] = "right alt";
   223             break;
   224         case SDLK_LALT:
   225             SDL_keynames[i] = "left alt";
   226             break;
   227         case SDLK_RMETA:
   228             SDL_keynames[i] = "right meta";
   229             break;
   230         case SDLK_LMETA:
   231             SDL_keynames[i] = "left meta";
   232             break;
   233         case SDLK_LSUPER:
   234             SDL_keynames[i] = "left super";     /* "Windows" keys */
   235             break;
   236         case SDLK_RSUPER:
   237             SDL_keynames[i] = "right super";
   238             break;
   239         case SDLK_MODE:
   240             SDL_keynames[i] = "alt gr";
   241             break;
   242         case SDLK_COMPOSE:
   243             SDL_keynames[i] = "compose";
   244             break;
   245 
   246         case SDLK_HELP:
   247             SDL_keynames[i] = "help";
   248             break;
   249         case SDLK_PRINT:
   250             SDL_keynames[i] = "print screen";
   251             break;
   252         case SDLK_SYSREQ:
   253             SDL_keynames[i] = "sys req";
   254             break;
   255         case SDLK_BREAK:
   256             SDL_keynames[i] = "break";
   257             break;
   258         case SDLK_MENU:
   259             SDL_keynames[i] = "menu";
   260             break;
   261         case SDLK_POWER:
   262             SDL_keynames[i] = "power";
   263             break;
   264         case SDLK_EURO:
   265             SDL_keynames[i] = "euro";
   266             break;
   267         case SDLK_UNDO:
   268             SDL_keynames[i] = "undo";
   269             break;
   270 
   271         default:
   272             SDL_keynames[i] = NULL;
   273             break;
   274         }
   275     }
   276 
   277     /* Done.  Whew. */
   278     return (0);
   279 }
   280 
   281 SDL_Keyboard *
   282 SDL_GetKeyboard(int index)
   283 {
   284     if (index < 0 || index >= SDL_num_keyboards) {
   285         return NULL;
   286     }
   287     return SDL_keyboards[index];
   288 }
   289 
   290 int
   291 SDL_AddKeyboard(const SDL_Keyboard * keyboard, int index)
   292 {
   293     SDL_Keyboard **keyboards;
   294 
   295     /* Add the keyboard to the list of keyboards */
   296     if (index < 0 || index >= SDL_num_keyboards || SDL_keyboards[index]) {
   297         keyboards =
   298             (SDL_Keyboard **) SDL_realloc(SDL_keyboards,
   299                                           (SDL_num_keyboards +
   300                                            1) * sizeof(*keyboards));
   301         if (!keyboards) {
   302             SDL_OutOfMemory();
   303             return -1;
   304         }
   305 
   306         SDL_keyboards = keyboards;
   307         index = SDL_num_keyboards++;
   308     }
   309     SDL_keyboards[index] =
   310         (SDL_Keyboard *) SDL_malloc(sizeof(*SDL_keyboards[index]));
   311     if (!SDL_keyboards[index]) {
   312         SDL_OutOfMemory();
   313         return -1;
   314     }
   315     *SDL_keyboards[index] = *keyboard;
   316 
   317     return index;
   318 }
   319 
   320 void
   321 SDL_DelKeyboard(int index)
   322 {
   323     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   324 
   325     if (!keyboard) {
   326         return;
   327     }
   328 
   329     if (keyboard->FreeKeyboard) {
   330         keyboard->FreeKeyboard(keyboard);
   331     }
   332     SDL_free(keyboard);
   333 
   334     SDL_keyboards[index] = NULL;
   335 }
   336 
   337 void
   338 SDL_ResetKeyboard(int index)
   339 {
   340     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   341     SDL_keysym keysym;
   342     Uint16 key;
   343 
   344     if (!keyboard) {
   345         return;
   346     }
   347 
   348     SDL_memset(&keysym, 0, (sizeof keysym));
   349     for (key = SDLK_FIRST; key < SDLK_LAST; ++key) {
   350         if (keyboard->keystate[key] == SDL_PRESSED) {
   351             keysym.sym = key;
   352             SDL_SendKeyboardKey(index, 0, SDL_RELEASED, &keysym);
   353         }
   354     }
   355     keyboard->repeat.timestamp = 0;
   356 }
   357 
   358 void
   359 SDL_KeyboardQuit(void)
   360 {
   361     int i;
   362 
   363     for (i = 0; i < SDL_num_keyboards; ++i) {
   364         SDL_DelKeyboard(i);
   365     }
   366     SDL_num_keyboards = 0;
   367     SDL_current_keyboard = 0;
   368 
   369     if (SDL_keyboards) {
   370         SDL_free(SDL_keyboards);
   371         SDL_keyboards = NULL;
   372     }
   373 }
   374 
   375 int
   376 SDL_GetNumKeyboards(void)
   377 {
   378     return SDL_num_keyboards;
   379 }
   380 
   381 int
   382 SDL_SelectKeyboard(int index)
   383 {
   384     if (index >= 0 && index < SDL_num_keyboards) {
   385         SDL_current_keyboard = index;
   386     }
   387     return SDL_current_keyboard;
   388 }
   389 
   390 int
   391 SDL_EnableUNICODE(int enable)
   392 {
   393     int old_mode;
   394 
   395     old_mode = SDL_TranslateUNICODE;
   396     if (enable >= 0) {
   397         SDL_TranslateUNICODE = enable;
   398     }
   399     return (old_mode);
   400 }
   401 
   402 Uint8 *
   403 SDL_GetKeyState(int *numkeys)
   404 {
   405     SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
   406 
   407     if (numkeys != (int *) 0) {
   408         *numkeys = SDLK_LAST;
   409     }
   410 
   411     if (!keyboard) {
   412         return NULL;
   413     }
   414     return keyboard->keystate;
   415 }
   416 
   417 SDLMod
   418 SDL_GetModState(void)
   419 {
   420     SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
   421 
   422     if (!keyboard) {
   423         return KMOD_NONE;
   424     }
   425     return keyboard->modstate;
   426 }
   427 
   428 void
   429 SDL_SetModState(SDLMod modstate)
   430 {
   431     SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
   432 
   433     if (!keyboard) {
   434         return;
   435     }
   436     keyboard->modstate = modstate;
   437 }
   438 
   439 const char *
   440 SDL_GetKeyName(SDLKey key)
   441 {
   442     const char *keyname;
   443 
   444     if (key < SDL_arraysize(SDL_keynames)) {
   445         keyname = SDL_keynames[key];
   446     } else {
   447         keyname = NULL;
   448     }
   449     if (keyname == NULL) {
   450         if (key < 256) {
   451             static char temp[4];
   452             char *cvt;
   453             temp[0] = (char) key;
   454             temp[1] = '\0';
   455             cvt = SDL_iconv_string("UTF-8", "LATIN1", temp, 1);
   456             SDL_strlcpy(temp, cvt, SDL_arraysize(temp));
   457             SDL_free(cvt);
   458             keyname = temp;
   459         } else {
   460             keyname = "unknown key";
   461         }
   462     }
   463     return keyname;
   464 }
   465 
   466 int
   467 SDL_SendKeyboardKey(int index, SDL_WindowID windowID, Uint8 state,
   468                     SDL_keysym * keysym)
   469 {
   470     SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
   471     int posted, repeatable;
   472     Uint16 modstate;
   473     Uint8 type;
   474 
   475     if (!keyboard) {
   476         return 0;
   477     }
   478 
   479     if (windowID) {
   480         keyboard->focus = windowID;
   481     }
   482 #if 0
   483     printf("The '%s' key has been %s\n", SDL_GetKeyName(keysym->sym),
   484            state == SDL_PRESSED ? "pressed" : "released");
   485 #endif
   486     /* Set up the keysym */
   487     modstate = keyboard->modstate;
   488 
   489     repeatable = 0;
   490 
   491     if (state == SDL_PRESSED) {
   492         keysym->mod = modstate;
   493         switch (keysym->sym) {
   494         case SDLK_UNKNOWN:
   495             break;
   496         case SDLK_NUMLOCK:
   497             modstate ^= KMOD_NUM;
   498             if (!(modstate & KMOD_NUM))
   499                 state = SDL_RELEASED;
   500             keysym->mod = modstate;
   501             break;
   502         case SDLK_CAPSLOCK:
   503             modstate ^= KMOD_CAPS;
   504             if (!(modstate & KMOD_CAPS))
   505                 state = SDL_RELEASED;
   506             keysym->mod = modstate;
   507             break;
   508         case SDLK_LCTRL:
   509             modstate |= KMOD_LCTRL;
   510             break;
   511         case SDLK_RCTRL:
   512             modstate |= KMOD_RCTRL;
   513             break;
   514         case SDLK_LSHIFT:
   515             modstate |= KMOD_LSHIFT;
   516             break;
   517         case SDLK_RSHIFT:
   518             modstate |= KMOD_RSHIFT;
   519             break;
   520         case SDLK_LALT:
   521             modstate |= KMOD_LALT;
   522             break;
   523         case SDLK_RALT:
   524             modstate |= KMOD_RALT;
   525             break;
   526         case SDLK_LMETA:
   527             modstate |= KMOD_LMETA;
   528             break;
   529         case SDLK_RMETA:
   530             modstate |= KMOD_RMETA;
   531             break;
   532         case SDLK_MODE:
   533             modstate |= KMOD_MODE;
   534             break;
   535         default:
   536             repeatable = 1;
   537             break;
   538         }
   539     } else {
   540         switch (keysym->sym) {
   541         case SDLK_UNKNOWN:
   542             break;
   543         case SDLK_NUMLOCK:
   544         case SDLK_CAPSLOCK:
   545             /* Only send keydown events */
   546             return (0);
   547         case SDLK_LCTRL:
   548             modstate &= ~KMOD_LCTRL;
   549             break;
   550         case SDLK_RCTRL:
   551             modstate &= ~KMOD_RCTRL;
   552             break;
   553         case SDLK_LSHIFT:
   554             modstate &= ~KMOD_LSHIFT;
   555             break;
   556         case SDLK_RSHIFT:
   557             modstate &= ~KMOD_RSHIFT;
   558             break;
   559         case SDLK_LALT:
   560             modstate &= ~KMOD_LALT;
   561             break;
   562         case SDLK_RALT:
   563             modstate &= ~KMOD_RALT;
   564             break;
   565         case SDLK_LMETA:
   566             modstate &= ~KMOD_LMETA;
   567             break;
   568         case SDLK_RMETA:
   569             modstate &= ~KMOD_RMETA;
   570             break;
   571         case SDLK_MODE:
   572             modstate &= ~KMOD_MODE;
   573             break;
   574         default:
   575             break;
   576         }
   577         keysym->mod = modstate;
   578     }
   579 
   580     /* Figure out what type of event this is */
   581     switch (state) {
   582     case SDL_PRESSED:
   583         type = SDL_KEYDOWN;
   584         break;
   585     case SDL_RELEASED:
   586         type = SDL_KEYUP;
   587         /*
   588          * jk 991215 - Added
   589          */
   590         if (keyboard->repeat.timestamp &&
   591             keyboard->repeat.evt.key.keysym.sym == keysym->sym) {
   592             keyboard->repeat.timestamp = 0;
   593         }
   594         break;
   595     default:
   596         /* Invalid state -- bail */
   597         return 0;
   598     }
   599 
   600     if (keysym->sym != SDLK_UNKNOWN) {
   601         /* Drop events that don't change state */
   602         if (keyboard->keystate[keysym->sym] == state) {
   603 #if 0
   604             printf("Keyboard event didn't change state - dropped!\n");
   605 #endif
   606             return 0;
   607         }
   608 
   609         /* Update internal keyboard state */
   610         keyboard->modstate = modstate;
   611         keyboard->keystate[keysym->sym] = state;
   612     }
   613 
   614     /* Post the event, if desired */
   615     posted = 0;
   616     if (SDL_ProcessEvents[type] == SDL_ENABLE) {
   617         SDL_Event event;
   618         event.key.type = type;
   619         event.key.which = (Uint8) index;
   620         event.key.state = state;
   621         event.key.keysym = *keysym;
   622         event.key.windowID = keyboard->focus;
   623         /*
   624          * jk 991215 - Added
   625          */
   626         if (repeatable && (keyboard->repeat.delay != 0)) {
   627             Uint32 timestamp = SDL_GetTicks();
   628             if (!timestamp) {
   629                 timestamp = 1;
   630             }
   631             keyboard->repeat.evt = event;
   632             keyboard->repeat.firsttime = 1;
   633             keyboard->repeat.timestamp = 1;
   634         }
   635         if ((SDL_EventOK == NULL) || SDL_EventOK(SDL_EventOKParam, &event)) {
   636             posted = 1;
   637             SDL_PushEvent(&event);
   638         }
   639     }
   640     return (posted);
   641 }
   642 
   643 /*
   644  * jk 991215 - Added
   645  */
   646 void
   647 SDL_CheckKeyRepeat(void)
   648 {
   649     int i;
   650 
   651     for (i = 0; i < SDL_num_keyboards; ++i) {
   652         SDL_Keyboard *keyboard = SDL_keyboards[i];
   653 
   654         if (!keyboard) {
   655             continue;
   656         }
   657 
   658         if (keyboard->repeat.timestamp) {
   659             Uint32 now, interval;
   660 
   661             now = SDL_GetTicks();
   662             interval = (now - keyboard->repeat.timestamp);
   663             if (keyboard->repeat.firsttime) {
   664                 if (interval > (Uint32) keyboard->repeat.delay) {
   665                     keyboard->repeat.timestamp = now;
   666                     keyboard->repeat.firsttime = 0;
   667                 }
   668             } else {
   669                 if (interval > (Uint32) keyboard->repeat.interval) {
   670                     keyboard->repeat.timestamp = now;
   671                     if ((SDL_EventOK == NULL)
   672                         || SDL_EventOK(SDL_EventOKParam,
   673                                        &keyboard->repeat.evt)) {
   674                         SDL_PushEvent(&keyboard->repeat.evt);
   675                     }
   676                 }
   677             }
   678         }
   679     }
   680 }
   681 
   682 int
   683 SDL_EnableKeyRepeat(int delay, int interval)
   684 {
   685     SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
   686 
   687     if (!keyboard) {
   688         SDL_SetError("No keyboard is currently selected");
   689         return -1;
   690     }
   691 
   692     if ((delay < 0) || (interval < 0)) {
   693         SDL_SetError("keyboard repeat value less than zero");
   694         return -1;
   695     }
   696 
   697     keyboard->repeat.firsttime = 0;
   698     keyboard->repeat.delay = delay;
   699     keyboard->repeat.interval = interval;
   700     keyboard->repeat.timestamp = 0;
   701 
   702     return 0;
   703 }
   704 
   705 void
   706 SDL_GetKeyRepeat(int *delay, int *interval)
   707 {
   708     SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
   709 
   710     if (!keyboard) {
   711         if (delay) {
   712             *delay = 0;
   713         }
   714         if (interval) {
   715             *interval = 0;
   716         }
   717         return;
   718     }
   719     if (delay) {
   720         *delay = keyboard->repeat.delay;
   721     }
   722     if (interval) {
   723         *interval = keyboard->repeat.interval;
   724     }
   725 }
   726 
   727 /* vi: set ts=4 sw=4 expandtab: */