Question on sdl event queue and its length

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;
}

The event queue can definitely hold (much) more than six events.

However, the USB HID Boot Keyboard Protocol only supports 6 keys being pressed at the same time plus modifier keys - you should be able to verify that by pressing Ctrl/Alt/Shift/Windows Keys in addition to 6 normal keys (some technical details of the protocol).
Some (more expensive) keyboards support more than six keys with custom HID protocols, that feature is usually called n-key rollover (NKRO).

(Cheaper keyboards don’t even properly support 6 keys at the same time, depending on the position of the keys, due to how their internal electronics work - if 6 keys can be registered properly that’s often called 6KRO)

I think 6KRO is usually sufficient, I don’t see many situations where you legitimately need to press more than six keys (+modifiers) at the same time (two-player coop at the same keyboard might be such a situation).

2 Likes

Ah, I see; it was a limitation of my keyboard.
Thanks!