Search code examples
c++ioglfw

Is there a way to process only one input event after a key is pressed using GLFW?


Currently, when holding down the desired key, the input registers multiple times. Is there a way to process only the first event after the key is pressed and ignore the following events until the key is released?

I'm using a processInput function, with the following condition:

if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) {
        currentXPos--;
        if (currentXPos < 0)
            currentXPos = 0;
}

currentXPos is just an integer that's affected by the left/right arrow keys. I have an equivalent currentYPos integer also that's affected by the up/down arrow keys. I need to increment/decrement currentXPos once per key-press. I've tried adding a global bool initially set to true and on execution setting it to false, like this:

if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) {
        if (canMove) {
            canMove = false;
            currentXPos--;
            if (currentXPos < 0)
                currentXPos = 0;
        }
}

if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_RELEASE) {
        canMove = true;
}

This does work with the single key, but if I implement this functionality with the right arrow key as well, (for incrementing the same value), the below function constantly returns GLFW_RELEASE after the first release, setting the canMove bool to true and ultimately making it redundant;

if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_RELEASE) {
            canMove = true;
}

I've tried using glfwWaitEvents() but that still processes multiple inputs when help for longer than 0.5 seconds or so (the same effect as holding down any character on the keyboard in a search bar/text editor).


Solution

  • When you want to handle every key just once, the best solution is to listen to the key callback event instead of querying the key state in every frame. The key callback is a function that can be hooked into glfw and is called once for every key event.

    The callback should look somehow like this:

    void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
    {
        if (key == GLFW_KEY_RIGHT && action == GLFW_PRESS)
        {
            currentXPos--;
            if (currentXPos < 0)
                currentXPos = 0;
        }
    }
    

    This callback can then be registered somewhere after the point where the window has been created:

    glfwSetKeyCallback(window, key_callback);
    

    More details can be found in the GLFW Input Guide.