Getting rid of key repeat input

I am having a bit of trouble with the arrow keys repeating when I don’t want them to. I have a keyboard function that is called during the game loop. It works as expected with the wasd keys which control directions. The problem is that when I use the arrow keys, which are expected to work the same, they repeat very quickly even though my condition is “if (e.type == SDL_KEYDOWN && e.key.repeat==0)”.
Somehow the arrow keys are still repeating even though the letter keys do not. I’m running on Ubuntu Linux but I don’t think that would make much of a difference. Is there something I missed?

void keyboard()
{
 int key;
 SDL_PollEvent( &e );
  if( e.type == SDL_QUIT ){loop=0; printf("X clicked! This program will close!\n");}
  if (e.type == SDL_KEYDOWN && e.key.repeat==0)
  {


   key=e.key.keysym.sym;

   switch(key)
   {
    case SDLK_ESCAPE:
    loop=0;
    break;

    case SDLK_z:
     block_rotate_left_basic();
    break;
    case SDLK_x:
     block_rotate_right_basic();
    break;
    case SDLK_c:
     block_hold();
    break;


    /*the main 4 directions*/
    case SDLK_KP_8:
    case SDLK_UP:
    case SDLK_w:
     tetris_move_up();
    break;
    case SDLK_KP_2:
    case SDLK_DOWN:
    case SDLK_s:
     tetris_move_down();
    break;
    case SDLK_KP_4:
    case SDLK_LEFT:
    case SDLK_a:
    tetris_move_left();
    break;
    case SDLK_KP_6:
    case SDLK_RIGHT:
    case SDLK_d:
     tetris_move_right();
    break;


    case SDLK_COMMA:
     tetris_load_state();
    break;
    case SDLK_PERIOD:
     tetris_save_state();
    break;

   }

  }

}

You should put your SDL_PollEvent() call in a while loop.
If not, only the latest event that was put in the event queue will be processed, which might cause issues with taking input from the keyboard and other event-based issues.

while(SDL_PollEvent(&e))
{
	// Handle events
}
1 Like

I fixed this issue awhile back. Turns out that by reinstalling to the latest version of Ubuntu fixed it. The same code ran fine on Windows but not the old Ubuntu. I also finished the Tetris game I was working on and published it as Chaste Tris. I made the same game in both SDL and Raylib. I find that SDL gives me greater input control than Raylib.

Daniel, was right. You really should check the return value of SDL_PollEvent before using the event. Otherwise you don’t know if there was an event or if you’re just reading “garbage”. This is the “correct” fix.

You’re right. Oddly enough, I haven’t been running into any problems, but I should check the return value and act accordingly the next time I update the source.

The problem with “repeated input” (the reason you created this thread) was likely caused by this.

There was a person with a similar problem a while ago, except that that person wanted the “repeated events” and complained when it stopped working.

Also note that you probably want to check the events using a while loop rather than an if statement otherwise you might run into other problems.

I meant I haven’t been running into any problems since reinstalling the operating system. Why that fixed the issue with no code changes is beyond explanation. But just today I did put the event polling inside a while loop as you all suggested. Hopefully this will prevent issues from happening on whatever operating system people are using who try to compile and run my code.

You’re acting on the same event over and over, which is why it doesn’t show as a repeat. Basically, when SDL_PollEvent() actually has an event, it fills in the provided SDL_Event struct. But when it doesn’t have an event to report, older versions of SDL left the SDL_Event struct as-is. And since each time your SDL_Event struct is getting put in the same place in the stack relative to the other local variables, you’re acting on the same “first time keypress” event over and over.

In newer versions of SDL, SDL_PollEvent() zeroes out the provided event struct if there are no events. Which is why your code works on Windows (you’re providing SDL yourself, I’m assuming the latest version), didn’t work on Ubuntu before (they were providing an older SDL version) but works now that you’ve upgraded (they updated to a newer version of SDL that zeroes out the event struct).

This is also why you should provide your own SDL build (or use Valve’s if your distributing via Steam) if you’re shipping game binaries on Linux

Thanks for explaining that! That does make sense why it was working on Windows but not the older version of Ubuntu. Seems they did make that small change to SDL_PollEvent. As long as I do check the return value by placing it in a loop, it should still work regardless of version. The fact that it worked at all was just me getting lucky.

Now I have it correct in my current program but will probably have to update my other SDL projects as well.

 /*test for events and only process if they exist*/
 while(SDL_PollEvent(&e))
 {
  keyboard();
 }

I also considered that this means a huge speed benefit because it won’t even try to call the keyboard function which processes different keypresses unless there was actually an event. I’ve been wasting CPU cycles for the longest time without realizing it for months and now I have some work to fix in 3 different games I wrote in SDL.

Thanks for the help everyone. This is exactly the benefit of forums like this where people can ask questions about SDL.