I was looking into how to receive/interpret multiple key presses on the keyboard, inspired by this question, and noticed that when I make multiple key presses, the queue only holds six(6), the first six, inputs. I wrote a small script to check and I’m not sure what is happening.
[Description of the script: It logs your key presses and how long you have been holding them; for example holding down the key ‘a’ will log as 97 being held. Every second it will output to the terminal how long a specific key has been held, if it being held at the moment of logging.]
I used the script below and held 6 keys and it logs them all as being held down, but when I hold down a seventh key (not that any practical game/application will have any human holding down seven keys simultaneously, hopefully) it doesn’t appear in the queue. Is this expected behavior?
edit: Subsequent key press events after the sixth one appear to be blocked.
For example, if I press/hold ‘A’, ‘S’, ‘D’, ‘F’, ‘J’, and ‘K’, pressing/holding ‘L’ will not be registered until I lift my finger off of ‘a’.
Another oddity is that, if I press/hold ‘A’, ‘S’, ‘D’, ‘F’, ‘J’, and ‘K’, followed by pressing/holding ‘L’ and ‘;’ , the ‘L’ and ‘;’ will not be registered into the event queue until I release both ‘A’ and ‘S’. Releasing only ‘A’ leaves ‘L’ outside of the event queue and the ‘A’ SDL_KEYUP appears to be outside of the event queue…
#include <iostream>
#include <unordered_map>
#include <SDL.h>
#define SCREEN_WIDTH (300)
#define SCREEN_HEIGHT (300)
int main(int argc, char** argv) {
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
return EXIT_FAILURE;
}
SDL_Window *window;
SDL_Renderer *renderer;
SDL_CreateWindowAndRenderer(SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN, &window, &renderer);
if (window == NULL || renderer == NULL) {
std::cout << "Error: failed to make window/renderer: " << SDL_GetError() << std::endl;
return EXIT_FAILURE;
}
SDL_Event e;
bool isRunning = true;
std::unordered_map<uint32_t, int32_t> key_state; //mapping from key_value to tick time
int last_output = SDL_GetTicks();
// Run loop
while (isRunning) {
// Event loop
SDL_PumpEvents();
while(SDL_PollEvent(&e)) {
if(e.type == SDL_QUIT) {
std::cout << "Quitting..." << std::endl;
isRunning = false;
}
else {
if (e.type == SDL_KEYDOWN) {
if (e.key.repeat == 0)
{
std::cout << "keydown: " << e.key.keysym.sym << std::endl;
key_state[e.key.keysym.sym] = SDL_GetTicks();
}
}
else if (e.type == SDL_KEYUP){
std::cout << "keyup : " << e.key.keysym.sym;
key_state[e.key.keysym.sym] = -1;
std::cout << ", set key_state[" << e.key.keysym.sym << "] to " << key_state[e.key.keysym.sym] << std::endl;
}
}
}
// loop over key_state and find positives.
int current_time = SDL_GetTicks();
if (current_time - last_output >= 999) { //if our last output was 1 second or more ago
std::string output = "Current buttons pressed: \n";
bool trigger = false;
for (auto &it : key_state) {
if (it.second > 0) {
trigger = true;
output += "\t" + std::to_string(it.first) + " " + std::to_string((current_time - it.second)/1000) + "\n";
}
}
last_output = current_time;
if (trigger) {
std::cout << output << std::flush;
trigger = false;
}
}
}
SDL_DestroyWindow(window); window=nullptr;
SDL_DestroyRenderer(renderer); renderer=nullptr;
SDL_Quit();
return EXIT_SUCCESS;
}