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 4560 95352c671a6e
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
--- a/include/SDL_events.h	Tue Jul 20 00:57:01 2010 -0700
+++ b/include/SDL_events.h	Tue Jul 20 23:25:24 2010 -0700
@@ -132,7 +132,7 @@
     Uint32 type;        /**< ::SDL_KEYDOWN or ::SDL_KEYUP */
     Uint32 windowID;    /**< The window with keyboard focus, if any */
     Uint8 state;        /**< ::SDL_PRESSED or ::SDL_RELEASED */
-    Uint8 padding1;
+    Uint8 repeat;       /**< Non-zero if this is a key repeat */
     Uint8 padding2;
     Uint8 padding3;
     SDL_keysym keysym;  /**< The key that was pressed or released */
--- a/src/events/SDL_keyboard.c	Tue Jul 20 00:57:01 2010 -0700
+++ b/src/events/SDL_keyboard.c	Tue Jul 20 23:25:24 2010 -0700
@@ -566,7 +566,7 @@
 
     for (scancode = 0; scancode < SDL_NUM_SCANCODES; ++scancode) {
         if (keyboard->keystate[scancode] == SDL_PRESSED) {
-            SDL_SendKeyboardKey(SDL_RELEASED, scancode);
+            SDL_SendKeyboardKey(SDL_RELEASED, scancode, SDL_FALSE);
         }
     }
 }
@@ -627,7 +627,7 @@
 }
 
 int
-SDL_SendKeyboardKey(Uint8 state, SDL_scancode scancode)
+SDL_SendKeyboardKey(Uint8 state, SDL_scancode scancode, SDL_bool repeat)
 {
     SDL_Keyboard *keyboard = &SDL_keyboard;
     int posted;
@@ -732,7 +732,7 @@
     }
 
     /* Drop events that don't change state */
-    if (keyboard->keystate[scancode] == state) {
+    if (keyboard->keystate[scancode] == state && !repeat) {
 #if 0
         printf("Keyboard event didn't change state - dropped!\n");
 #endif
@@ -748,6 +748,7 @@
         SDL_Event event;
         event.key.type = type;
         event.key.state = state;
+        event.key.repeat = repeat ? 1 : 0;
         event.key.keysym.scancode = scancode;
         event.key.keysym.sym = keyboard->keymap[scancode];
         event.key.keysym.mod = modstate;
--- a/src/events/SDL_keyboard_c.h	Tue Jul 20 00:57:01 2010 -0700
+++ b/src/events/SDL_keyboard_c.h	Tue Jul 20 23:25:24 2010 -0700
@@ -49,7 +49,7 @@
 extern void SDL_SetKeyboardFocus(SDL_Window * window);
 
 /* Send a keyboard key event */
-extern int SDL_SendKeyboardKey(Uint8 state, SDL_scancode scancode);
+extern int SDL_SendKeyboardKey(Uint8 state, SDL_scancode scancode, SDL_bool repeat);
 
 /* Send keyboard text input */
 extern int SDL_SendKeyboardText(const char *text);
--- a/src/video/cocoa/SDL_cocoakeyboard.m	Tue Jul 20 00:57:01 2010 -0700
+++ b/src/video/cocoa/SDL_cocoakeyboard.m	Tue Jul 20 23:25:24 2010 -0700
@@ -219,14 +219,14 @@
         if (oldMask && oldMask != newMask) {        /* modifier up event */
             /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
             if (bit == NSAlphaShiftKeyMask) {
-                SDL_SendKeyboardKey(SDL_PRESSED, mapping[i]);
+                SDL_SendKeyboardKey(SDL_PRESSED, mapping[i], SDL_FALSE);
             }
-            SDL_SendKeyboardKey(SDL_RELEASED, mapping[i]);
+            SDL_SendKeyboardKey(SDL_RELEASED, mapping[i], SDL_FALSE);
         } else if (newMask && oldMask != newMask) { /* modifier down event */
-            SDL_SendKeyboardKey(SDL_PRESSED, mapping[i]);
+            SDL_SendKeyboardKey(SDL_PRESSED, mapping[i], SDL_FALSE);
             /* If this was Caps Lock, we need some additional voodoo to make SDL happy */
             if (bit == NSAlphaShiftKeyMask) {
-                SDL_SendKeyboardKey(SDL_RELEASED, mapping[i]);
+                SDL_SendKeyboardKey(SDL_RELEASED, mapping[i], SDL_FALSE);
             }
         }
     }
@@ -251,9 +251,9 @@
     newMask = newMods & device_independent_mask;
     
     if (oldMask && oldMask != newMask) {
-        SDL_SendKeyboardKey(SDL_RELEASED, scancode);
+        SDL_SendKeyboardKey(SDL_RELEASED, scancode, SDL_FALSE);
     } else if (newMask && oldMask != newMask) {
-        SDL_SendKeyboardKey(SDL_PRESSED, scancode);
+        SDL_SendKeyboardKey(SDL_PRESSED, scancode, SDL_FALSE);
     }
 }
 
@@ -278,9 +278,9 @@
      * find out which it is.
      */
     if (new_dep_mask && old_dep_mask != new_dep_mask) {
-        SDL_SendKeyboardKey(SDL_PRESSED, scancode);
+        SDL_SendKeyboardKey(SDL_PRESSED, scancode, SDL_FALSE);
     } else {
-        SDL_SendKeyboardKey(SDL_RELEASED, scancode);
+        SDL_SendKeyboardKey(SDL_RELEASED, scancode, SDL_FALSE);
     }
 }
 
@@ -351,7 +351,7 @@
         /* In this case, we can't detect the keyboard, so use the left side 
          * to represent both, and release it. 
          */
-        SDL_SendKeyboardKey(SDL_RELEASED, left_scancode);
+        SDL_SendKeyboardKey(SDL_RELEASED, left_scancode, SDL_FALSE);
         return;
     }
 
@@ -362,10 +362,10 @@
      * so I hope this doesn't cause other problems.
      */
     if ( left_device_dependent_mask & oldMods ) {
-        SDL_SendKeyboardKey(SDL_RELEASED, left_scancode);
+        SDL_SendKeyboardKey(SDL_RELEASED, left_scancode, SDL_FALSE);
     }
     if ( right_device_dependent_mask & oldMods ) {
-        SDL_SendKeyboardKey(SDL_RELEASED, right_scancode);
+        SDL_SendKeyboardKey(SDL_RELEASED, right_scancode, SDL_FALSE);
     }
 }
 
@@ -382,16 +382,16 @@
     newMask = newMods & NSAlphaShiftKeyMask;
 
     if (oldMask != newMask) {
-        SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_CAPSLOCK);
-        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_CAPSLOCK);
+        SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_CAPSLOCK, SDL_FALSE);
+        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_CAPSLOCK, SDL_FALSE);
     }
 
     oldMask = oldMods & NSNumericPadKeyMask;
     newMask = newMods & NSNumericPadKeyMask;
 
     if (oldMask != newMask) {
-        SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_NUMLOCKCLEAR);
-        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_NUMLOCKCLEAR);
+        SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_NUMLOCKCLEAR, SDL_FALSE);
+        SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_NUMLOCKCLEAR, SDL_FALSE);
     }
 }
 
@@ -670,6 +670,7 @@
     SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
     unsigned short scancode = [event keyCode];
     SDL_scancode code;
+    SDL_bool repeat;
 #if 0
     const char *text;
 #endif
@@ -688,17 +689,18 @@
 
     switch ([event type]) {
     case NSKeyDown:
-        if (![event isARepeat]) {
+        repeat = [event isARepeat] ? SDL_TRUE : SDL_FALSE;
+        if (!repeat) {
             /* See if we need to rebuild the keyboard layout */
             UpdateKeymap(data);
+        }
 
-            SDL_SendKeyboardKey(SDL_PRESSED, code);
+        SDL_SendKeyboardKey(SDL_PRESSED, code, repeat);
 #if 1
-            if (code == SDL_SCANCODE_UNKNOWN) {
-                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);
-            }
+        if (code == SDL_SCANCODE_UNKNOWN) {
+            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);
+        }
 #endif
-        }
         if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
             /* 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. */
             [data->fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]];
@@ -712,7 +714,7 @@
         }
         break;
     case NSKeyUp:
-        SDL_SendKeyboardKey(SDL_RELEASED, code);
+        SDL_SendKeyboardKey(SDL_RELEASED, code, SDL_FALSE);
         break;
     case NSFlagsChanged:
         /* FIXME CW 2007-08-14: check if this whole mess that takes up half of this file is really necessary */
--- a/src/video/uikit/SDL_uikitview.m	Tue Jul 20 00:57:01 2010 -0700
+++ b/src/video/uikit/SDL_uikitview.m	Tue Jul 20 23:25:24 2010 -0700
@@ -245,8 +245,8 @@
 	
 	if ([string length] == 0) {
 		/* it wants to replace text with nothing, ie a delete */
-		SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_DELETE);
-		SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_DELETE);
+		SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_DELETE, SDL_FALSE);
+		SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_DELETE, SDL_FALSE);
 	}
 	else {
 		/* go through all the characters in the string we've been sent
@@ -272,14 +272,14 @@
 			
 			if (mod & KMOD_SHIFT) {
 				/* If character uses shift, press shift down */
-				SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_LSHIFT);
+				SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_LSHIFT, SDL_FALSE);
 			}
 			/* send a keydown and keyup even for the character */
-			SDL_SendKeyboardKey(SDL_PRESSED, code);
-			SDL_SendKeyboardKey(SDL_RELEASED, code);
+			SDL_SendKeyboardKey(SDL_PRESSED, code, SDL_FALSE);
+			SDL_SendKeyboardKey(SDL_RELEASED, code, SDL_FALSE);
 			if (mod & KMOD_SHIFT) {
 				/* If character uses shift, press shift back up */
-				SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT);
+				SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT, SDL_FALSE);
 			}			
 		}
 	}
--- a/src/video/win32/SDL_win32events.c	Tue Jul 20 00:57:01 2010 -0700
+++ b/src/video/win32/SDL_win32events.c	Tue Jul 20 23:25:24 2010 -0700
@@ -201,10 +201,12 @@
     case WM_SYSKEYDOWN:
     case WM_KEYDOWN:
         {
-            /* Ignore repeated keys */
+            SDL_bool repeat;
+
             if (lParam & REPEATED_KEYMASK) {
-                returnCode = 0;
-                break;
+                repeat = SDL_TRUE;
+            } else {
+                repeat = SDL_FALSE;
             }
 
             wParam = RemapVKEY(wParam, lParam);
@@ -244,7 +246,8 @@
             }
             if (wParam < 256) {
                 SDL_SendKeyboardKey(SDL_PRESSED,
-                                    data->videodata->key_layout[wParam]);
+                                    data->videodata->key_layout[wParam],
+                                    repeat);
             }
         }
         returnCode = 0;
@@ -294,11 +297,13 @@
                 && SDL_GetKeyboardState(NULL)[SDL_SCANCODE_PRINTSCREEN] ==
                 SDL_RELEASED) {
                 SDL_SendKeyboardKey(SDL_PRESSED,
-                                    data->videodata->key_layout[wParam]);
+                                    data->videodata->key_layout[wParam],
+                                    SDL_FALSE);
             }
             if (wParam < 256) {
                 SDL_SendKeyboardKey(SDL_RELEASED,
-                                    data->videodata->key_layout[wParam]);
+                                    data->videodata->key_layout[wParam],
+                                    SDL_FALSE);
             }
         }
         returnCode = 0;
--- a/src/video/x11/SDL_x11events.c	Tue Jul 20 00:57:01 2010 -0700
+++ b/src/video/x11/SDL_x11events.c	Tue Jul 20 23:25:24 2010 -0700
@@ -182,7 +182,8 @@
 #ifdef DEBUG_XEVENTS
             printf("KeyPress (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
 #endif
-            SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
+            /* FIXME: How do we tell if this was a key repeat? */
+            SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode], SDL_FALSE);
 #if 1
             if (videodata->key_layout[keycode] == SDLK_UNKNOWN) {
                 int min_keycode, max_keycode;
@@ -217,7 +218,7 @@
 #ifdef DEBUG_XEVENTS
             printf("KeyRelease (X11 keycode = 0x%X)\n", xevent.xkey.keycode);
 #endif
-            SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
+            SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode], SDL_FALSE);
         }
         break;
 
--- a/test/checkkeys.c	Tue Jul 20 00:57:01 2010 -0700
+++ b/test/checkkeys.c	Tue Jul 20 23:25:24 2010 -0700
@@ -53,7 +53,7 @@
 }
 
 static void
-PrintKey(SDL_keysym * sym, int pressed)
+PrintKey(SDL_keysym * sym, SDL_bool pressed, SDL_bool repeat)
 {
     /* Print the keycode, name and state */
     if (sym->sym) {
@@ -87,6 +87,9 @@
         }
     }
     print_modifiers();
+    if (repeat) {
+        printf(" (repeat)");
+    }
     printf("\n");
 }
 
@@ -134,10 +137,8 @@
         SDL_WaitEvent(&event);
         switch (event.type) {
         case SDL_KEYDOWN:
-            PrintKey(&event.key.keysym, 1);
-            break;
         case SDL_KEYUP:
-            PrintKey(&event.key.keysym, 0);
+            PrintKey(&event.key.keysym, event.key.state, event.key.repeat);
             break;
         case SDL_TEXTINPUT:
             PrintText(event.text.text);