Added support for keyboard repeat (only tested on Windows so far)
authorSam Lantinga <slouken@libsdl.org>
Tue, 20 Jul 2010 23:25:24 -0700
changeset 456095352c671a6e
parent 4559 f8c3870af5a2
child 4561 e4b2b7207f79
Added support for keyboard repeat (only tested on Windows so far)
include/SDL_events.h
src/events/SDL_keyboard.c
src/events/SDL_keyboard_c.h
src/video/cocoa/SDL_cocoakeyboard.m
src/video/uikit/SDL_uikitview.m
src/video/win32/SDL_win32events.c
src/video/x11/SDL_x11events.c
test/checkkeys.c
     1.1 --- a/include/SDL_events.h	Tue Jul 20 00:57:01 2010 -0700
     1.2 +++ b/include/SDL_events.h	Tue Jul 20 23:25:24 2010 -0700
     1.3 @@ -132,7 +132,7 @@
     1.4      Uint32 type;        /**< ::SDL_KEYDOWN or ::SDL_KEYUP */
     1.5      Uint32 windowID;    /**< The window with keyboard focus, if any */
     1.6      Uint8 state;        /**< ::SDL_PRESSED or ::SDL_RELEASED */
     1.7 -    Uint8 padding1;
     1.8 +    Uint8 repeat;       /**< Non-zero if this is a key repeat */
     1.9      Uint8 padding2;
    1.10      Uint8 padding3;
    1.11      SDL_keysym keysym;  /**< The key that was pressed or released */
     2.1 --- a/src/events/SDL_keyboard.c	Tue Jul 20 00:57:01 2010 -0700
     2.2 +++ b/src/events/SDL_keyboard.c	Tue Jul 20 23:25:24 2010 -0700
     2.3 @@ -566,7 +566,7 @@
     2.4  
     2.5      for (scancode = 0; scancode < SDL_NUM_SCANCODES; ++scancode) {
     2.6          if (keyboard->keystate[scancode] == SDL_PRESSED) {
     2.7 -            SDL_SendKeyboardKey(SDL_RELEASED, scancode);
     2.8 +            SDL_SendKeyboardKey(SDL_RELEASED, scancode, SDL_FALSE);
     2.9          }
    2.10      }
    2.11  }
    2.12 @@ -627,7 +627,7 @@
    2.13  }
    2.14  
    2.15  int
    2.16 -SDL_SendKeyboardKey(Uint8 state, SDL_scancode scancode)
    2.17 +SDL_SendKeyboardKey(Uint8 state, SDL_scancode scancode, SDL_bool repeat)
    2.18  {
    2.19      SDL_Keyboard *keyboard = &SDL_keyboard;
    2.20      int posted;
    2.21 @@ -732,7 +732,7 @@
    2.22      }
    2.23  
    2.24      /* Drop events that don't change state */
    2.25 -    if (keyboard->keystate[scancode] == state) {
    2.26 +    if (keyboard->keystate[scancode] == state && !repeat) {
    2.27  #if 0
    2.28          printf("Keyboard event didn't change state - dropped!\n");
    2.29  #endif
    2.30 @@ -748,6 +748,7 @@
    2.31          SDL_Event event;
    2.32          event.key.type = type;
    2.33          event.key.state = state;
    2.34 +        event.key.repeat = repeat ? 1 : 0;
    2.35          event.key.keysym.scancode = scancode;
    2.36          event.key.keysym.sym = keyboard->keymap[scancode];
    2.37          event.key.keysym.mod = modstate;
     3.1 --- a/src/events/SDL_keyboard_c.h	Tue Jul 20 00:57:01 2010 -0700
     3.2 +++ b/src/events/SDL_keyboard_c.h	Tue Jul 20 23:25:24 2010 -0700
     3.3 @@ -49,7 +49,7 @@
     3.4  extern void SDL_SetKeyboardFocus(SDL_Window * window);
     3.5  
     3.6  /* Send a keyboard key event */
     3.7 -extern int SDL_SendKeyboardKey(Uint8 state, SDL_scancode scancode);
     3.8 +extern int SDL_SendKeyboardKey(Uint8 state, SDL_scancode scancode, SDL_bool repeat);
     3.9  
    3.10  /* Send keyboard text input */
    3.11  extern int SDL_SendKeyboardText(const char *text);
     4.1 --- a/src/video/cocoa/SDL_cocoakeyboard.m	Tue Jul 20 00:57:01 2010 -0700
     4.2 +++ b/src/video/cocoa/SDL_cocoakeyboard.m	Tue Jul 20 23:25:24 2010 -0700
     4.3 @@ -219,14 +219,14 @@
     4.4          if (oldMask && oldMask != newMask) {        /* modifier up event */
     4.5              /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
     4.6              if (bit == NSAlphaShiftKeyMask) {
     4.7 -                SDL_SendKeyboardKey(SDL_PRESSED, mapping[i]);
     4.8 +                SDL_SendKeyboardKey(SDL_PRESSED, mapping[i], SDL_FALSE);
     4.9              }
    4.10 -            SDL_SendKeyboardKey(SDL_RELEASED, mapping[i]);
    4.11 +            SDL_SendKeyboardKey(SDL_RELEASED, mapping[i], SDL_FALSE);
    4.12          } else if (newMask && oldMask != newMask) { /* modifier down event */
    4.13 -            SDL_SendKeyboardKey(SDL_PRESSED, mapping[i]);
    4.14 +            SDL_SendKeyboardKey(SDL_PRESSED, mapping[i], SDL_FALSE);
    4.15              /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
    4.16              if (bit == NSAlphaShiftKeyMask) {
    4.17 -                SDL_SendKeyboardKey(SDL_RELEASED, mapping[i]);
    4.18 +                SDL_SendKeyboardKey(SDL_RELEASED, mapping[i], SDL_FALSE);
    4.19              }
    4.20          }
    4.21      }
    4.22 @@ -251,9 +251,9 @@
    4.23      newMask = newMods & device_independent_mask;
    4.24      
    4.25      if (oldMask && oldMask != newMask) {
    4.26 -        SDL_SendKeyboardKey(SDL_RELEASED, scancode);
    4.27 +        SDL_SendKeyboardKey(SDL_RELEASED, scancode, SDL_FALSE);
    4.28      } else if (newMask && oldMask != newMask) {
    4.29 -        SDL_SendKeyboardKey(SDL_PRESSED, scancode);
    4.30 +        SDL_SendKeyboardKey(SDL_PRESSED, scancode, SDL_FALSE);
    4.31      }
    4.32  }
    4.33  
    4.34 @@ -278,9 +278,9 @@
    4.35       * find out which it is.
    4.36       */
    4.37      if (new_dep_mask && old_dep_mask != new_dep_mask) {
    4.38 -        SDL_SendKeyboardKey(SDL_PRESSED, scancode);
    4.39 +        SDL_SendKeyboardKey(SDL_PRESSED, scancode, SDL_FALSE);
    4.40      } else {
    4.41 -        SDL_SendKeyboardKey(SDL_RELEASED, scancode);
    4.42 +        SDL_SendKeyboardKey(SDL_RELEASED, scancode, SDL_FALSE);
    4.43      }
    4.44  }
    4.45  
    4.46 @@ -351,7 +351,7 @@
    4.47          /* In this case, we can't detect the keyboard, so use the left side 
    4.48           * to represent both, and release it. 
    4.49           */
    4.50 -        SDL_SendKeyboardKey(SDL_RELEASED, left_scancode);
    4.51 +        SDL_SendKeyboardKey(SDL_RELEASED, left_scancode, SDL_FALSE);
    4.52          return;
    4.53      }
    4.54  
    4.55 @@ -362,10 +362,10 @@
    4.56       * so I hope this doesn't cause other problems.
    4.57       */
    4.58      if ( left_device_dependent_mask & oldMods ) {
    4.59 -        SDL_SendKeyboardKey(SDL_RELEASED, left_scancode);
    4.60 +        SDL_SendKeyboardKey(SDL_RELEASED, left_scancode, SDL_FALSE);
    4.61      }
    4.62      if ( right_device_dependent_mask & oldMods ) {
    4.63 -        SDL_SendKeyboardKey(SDL_RELEASED, right_scancode);
    4.64 +        SDL_SendKeyboardKey(SDL_RELEASED, right_scancode, SDL_FALSE);
    4.65      }
    4.66  }
    4.67  
    4.68 @@ -382,16 +382,16 @@
    4.69      newMask = newMods & NSAlphaShiftKeyMask;
    4.70  
    4.71      if (oldMask != newMask) {
    4.72 -        SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_CAPSLOCK);
    4.73 -        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_CAPSLOCK);
    4.74 +        SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_CAPSLOCK, SDL_FALSE);
    4.75 +        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_CAPSLOCK, SDL_FALSE);
    4.76      }
    4.77  
    4.78      oldMask = oldMods & NSNumericPadKeyMask;
    4.79      newMask = newMods & NSNumericPadKeyMask;
    4.80  
    4.81      if (oldMask != newMask) {
    4.82 -        SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_NUMLOCKCLEAR);
    4.83 -        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_NUMLOCKCLEAR);
    4.84 +        SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_NUMLOCKCLEAR, SDL_FALSE);
    4.85 +        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_NUMLOCKCLEAR, SDL_FALSE);
    4.86      }
    4.87  }
    4.88  
    4.89 @@ -670,6 +670,7 @@
    4.90      SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
    4.91      unsigned short scancode = [event keyCode];
    4.92      SDL_scancode code;
    4.93 +    SDL_bool repeat;
    4.94  #if 0
    4.95      const char *text;
    4.96  #endif
    4.97 @@ -688,17 +689,18 @@
    4.98  
    4.99      switch ([event type]) {
   4.100      case NSKeyDown:
   4.101 -        if (![event isARepeat]) {
   4.102 +        repeat = [event isARepeat] ? SDL_TRUE : SDL_FALSE;
   4.103 +        if (!repeat) {
   4.104              /* See if we need to rebuild the keyboard layout */
   4.105              UpdateKeymap(data);
   4.106 +        }
   4.107  
   4.108 -            SDL_SendKeyboardKey(SDL_PRESSED, code);
   4.109 +        SDL_SendKeyboardKey(SDL_PRESSED, code, repeat);
   4.110  #if 1
   4.111 -            if (code == SDL_SCANCODE_UNKNOWN) {
   4.112 -                fprintf(stderr, "The key you just pressed is not recognized by SDL. To help get this fixed, report this to the SDL mailing list <sdl@libsdl.org> or to Christian Walther <cwalther@gmx.ch>. Mac virtual key code is %d.\n", scancode);
   4.113 -            }
   4.114 +        if (code == SDL_SCANCODE_UNKNOWN) {
   4.115 +            fprintf(stderr, "The key you just pressed is not recognized by SDL. To help get this fixed, report this to the SDL mailing list <sdl@libsdl.org> or to Christian Walther <cwalther@gmx.ch>. Mac virtual key code is %d.\n", scancode);
   4.116 +        }
   4.117  #endif
   4.118 -        }
   4.119          if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
   4.120              /* FIXME CW 2007-08-16: only send those events to the field editor for which we actually want text events, not e.g. esc or function keys. Arrow keys in particular seem to produce crashes sometimes. */
   4.121              [data->fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]];
   4.122 @@ -712,7 +714,7 @@
   4.123          }
   4.124          break;
   4.125      case NSKeyUp:
   4.126 -        SDL_SendKeyboardKey(SDL_RELEASED, code);
   4.127 +        SDL_SendKeyboardKey(SDL_RELEASED, code, SDL_FALSE);
   4.128          break;
   4.129      case NSFlagsChanged:
   4.130          /* FIXME CW 2007-08-14: check if this whole mess that takes up half of this file is really necessary */
     5.1 --- a/src/video/uikit/SDL_uikitview.m	Tue Jul 20 00:57:01 2010 -0700
     5.2 +++ b/src/video/uikit/SDL_uikitview.m	Tue Jul 20 23:25:24 2010 -0700
     5.3 @@ -245,8 +245,8 @@
     5.4  	
     5.5  	if ([string length] == 0) {
     5.6  		/* it wants to replace text with nothing, ie a delete */
     5.7 -		SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_DELETE);
     5.8 -		SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_DELETE);
     5.9 +		SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_DELETE, SDL_FALSE);
    5.10 +		SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_DELETE, SDL_FALSE);
    5.11  	}
    5.12  	else {
    5.13  		/* go through all the characters in the string we've been sent
    5.14 @@ -272,14 +272,14 @@
    5.15  			
    5.16  			if (mod & KMOD_SHIFT) {
    5.17  				/* If character uses shift, press shift down */
    5.18 -				SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_LSHIFT);
    5.19 +				SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_LSHIFT, SDL_FALSE);
    5.20  			}
    5.21  			/* send a keydown and keyup even for the character */
    5.22 -			SDL_SendKeyboardKey(SDL_PRESSED, code);
    5.23 -			SDL_SendKeyboardKey(SDL_RELEASED, code);
    5.24 +			SDL_SendKeyboardKey(SDL_PRESSED, code, SDL_FALSE);
    5.25 +			SDL_SendKeyboardKey(SDL_RELEASED, code, SDL_FALSE);
    5.26  			if (mod & KMOD_SHIFT) {
    5.27  				/* If character uses shift, press shift back up */
    5.28 -				SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT);
    5.29 +				SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT, SDL_FALSE);
    5.30  			}			
    5.31  		}
    5.32  	}
     6.1 --- a/src/video/win32/SDL_win32events.c	Tue Jul 20 00:57:01 2010 -0700
     6.2 +++ b/src/video/win32/SDL_win32events.c	Tue Jul 20 23:25:24 2010 -0700
     6.3 @@ -201,10 +201,12 @@
     6.4      case WM_SYSKEYDOWN:
     6.5      case WM_KEYDOWN:
     6.6          {
     6.7 -            /* Ignore repeated keys */
     6.8 +            SDL_bool repeat;
     6.9 +
    6.10              if (lParam & REPEATED_KEYMASK) {
    6.11 -                returnCode = 0;
    6.12 -                break;
    6.13 +                repeat = SDL_TRUE;
    6.14 +            } else {
    6.15 +                repeat = SDL_FALSE;
    6.16              }
    6.17  
    6.18              wParam = RemapVKEY(wParam, lParam);
    6.19 @@ -244,7 +246,8 @@
    6.20              }
    6.21              if (wParam < 256) {
    6.22                  SDL_SendKeyboardKey(SDL_PRESSED,
    6.23 -                                    data->videodata->key_layout[wParam]);
    6.24 +                                    data->videodata->key_layout[wParam],
    6.25 +                                    repeat);
    6.26              }
    6.27          }
    6.28          returnCode = 0;
    6.29 @@ -294,11 +297,13 @@
    6.30                  && SDL_GetKeyboardState(NULL)[SDL_SCANCODE_PRINTSCREEN] ==
    6.31                  SDL_RELEASED) {
    6.32                  SDL_SendKeyboardKey(SDL_PRESSED,
    6.33 -                                    data->videodata->key_layout[wParam]);
    6.34 +                                    data->videodata->key_layout[wParam],
    6.35 +                                    SDL_FALSE);
    6.36              }
    6.37              if (wParam < 256) {
    6.38                  SDL_SendKeyboardKey(SDL_RELEASED,
    6.39 -                                    data->videodata->key_layout[wParam]);
    6.40 +                                    data->videodata->key_layout[wParam],
    6.41 +                                    SDL_FALSE);
    6.42              }
    6.43          }
    6.44          returnCode = 0;
     7.1 --- a/src/video/x11/SDL_x11events.c	Tue Jul 20 00:57:01 2010 -0700
     7.2 +++ b/src/video/x11/SDL_x11events.c	Tue Jul 20 23:25:24 2010 -0700
     7.3 @@ -182,7 +182,8 @@
     7.4  #ifdef DEBUG_XEVENTS
     7.5              printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
     7.6  #endif
     7.7 -            SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
     7.8 +            /* FIXME: How do we tell if this was a key repeat? */
     7.9 +            SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode], SDL_FALSE);
    7.10  #if 1
    7.11              if (videodata->key_layout[keycode] == SDLK_UNKNOWN) {
    7.12                  int min_keycode, max_keycode;
    7.13 @@ -217,7 +218,7 @@
    7.14  #ifdef DEBUG_XEVENTS
    7.15              printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
    7.16  #endif
    7.17 -            SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
    7.18 +            SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode], SDL_FALSE);
    7.19          }
    7.20          break;
    7.21  
     8.1 --- a/test/checkkeys.c	Tue Jul 20 00:57:01 2010 -0700
     8.2 +++ b/test/checkkeys.c	Tue Jul 20 23:25:24 2010 -0700
     8.3 @@ -53,7 +53,7 @@
     8.4  }
     8.5  
     8.6  static void
     8.7 -PrintKey(SDL_keysym * sym, int pressed)
     8.8 +PrintKey(SDL_keysym * sym, SDL_bool pressed, SDL_bool repeat)
     8.9  {
    8.10      /* Print the keycode, name and state */
    8.11      if (sym->sym) {
    8.12 @@ -87,6 +87,9 @@
    8.13          }
    8.14      }
    8.15      print_modifiers();
    8.16 +    if (repeat) {
    8.17 +        printf(" (repeat)");
    8.18 +    }
    8.19      printf("\n");
    8.20  }
    8.21  
    8.22 @@ -134,10 +137,8 @@
    8.23          SDL_WaitEvent(&event);
    8.24          switch (event.type) {
    8.25          case SDL_KEYDOWN:
    8.26 -            PrintKey(&event.key.keysym, 1);
    8.27 -            break;
    8.28          case SDL_KEYUP:
    8.29 -            PrintKey(&event.key.keysym, 0);
    8.30 +            PrintKey(&event.key.keysym, event.key.state, event.key.repeat);
    8.31              break;
    8.32          case SDL_TEXTINPUT:
    8.33              PrintText(event.text.text);