Why does glfwGetMouseButton() miss button presses

I poll events with GLFW 60 times per second. Which as I understand means that glfwGetMouseButton() should detect any mouse button press with the duration over ca 0.016 seconds. If I press and release a button quicker than that it will get the GLFW_RELEASE state. I don’t think it is physically possible to press and release a mouse button quicker than that. So how come most of my mouse clicks are missed when I use this function?

Of course using callback for this purpose works. But could someone explain to me why it works if I do this:

bool clickedLeft, clickedRight;
void MyClickCallback(GLFWwindow* window, int button, int action, int mods) {
    if (button == GLFW_MOUSE_BUTTON_LEFT && action == 1) {
        clickedLeft = (clickedLeft) ? false : true;
    }

    else if (button == GLFW_MOUSE_BUTTON_RIGHT && action == 1) {
        clickedRight = (clickedRight) ? false : true;
    }
}

void UpdateFrame() {
    if (clickedLeft)
        cout << "Clicked Left" << endl;
    if (clickedRight)
        cout << "Clicked Right" << endl;
}

In this example the boolean clickedLeft may be updated multiple times per frame if I click and release a button faster than the duration of a frame. But on frame update we get the final state of the clickedLeft. So how come glfw detects the button press correctly with this approach when it does not with glfwGetMouseButton()?

As you note glfwGetMouseButton() can miss events whereas a callback won’t.

Your code looks like it will toggle the state of your bool variables every time a button is pressed. I would instead use something like:

bool clickedLeft = false;
bool clickedRight = false;
void MyClickCallback(GLFWwindow* window, int button, int action, int mods) {
    if (button == GLFW_MOUSE_BUTTON_LEFT && action == 1) {
        clickedLeft = true;
    }

    else if (button == GLFW_MOUSE_BUTTON_RIGHT && action == 1) {
        clickedRight = true;
    }
}

void UpdateFrame() {
    if (clickedLeft)
        cout << "Clicked Left" << endl;
    if (clickedRight)
        cout << "Clicked Right" << endl;

    // reset every frame
    clickedLeft  = false;
    clickedRight = false;
}
1 Like