Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delay in Combo Popup Opening with glfwWaitEventsTimeout #7544

Open
xevgeny opened this issue Apr 30, 2024 · 5 comments
Open

Delay in Combo Popup Opening with glfwWaitEventsTimeout #7544

xevgeny opened this issue Apr 30, 2024 · 5 comments

Comments

@xevgeny
Copy link

xevgeny commented Apr 30, 2024

Version/Branch of Dear ImGui:

master

Back-ends:

imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp

Compiler, OS:

Any

Full config/build information:

No response

Details:

I'm building a simple monitoring app using ImGUI and experimenting with resource-friendly rendering strategies. I use glfwWaitEventsTimeout with N-second granularity, which significantly reduces GPU load when there are no user inputs or events.

While I recognize that this may not be the intended use case for ImGUI, all widgets function well in this mode (Menu, TreeNode, CollapsingHeader), except the ComboBox - the popup opens with a delay when clicked.

In the attached video, the click occurs at frame 75, but the popup only appears at frame 79. Extra frames in between are rendered due to mouse input (GLFW_PRESS, GLFW_RELEASE). The thread sleeps between frames 78 and 79 due to glfwWaitEventsTimeout, which causes a noticeable delay. In the video, the timeout is set to 3 seconds.

I could not reproduce the issue with the keyboard input by selecting the ComboBox and pressing Enter.

Screenshots/Video:

Video: https://github.com/ocornut/imgui/assets/1928818/02641263-fb67-469e-9e53-75ccc0104766

Screenshot 2024-04-30 at 17 15 04

Minimal, Complete and Verifiable Example code:

To reproduce the issue replace glfwPollEvents with glfwWaitEventsTimeout in exapmle_glfw_opengl3/main.cpp file.

while (!glfwWindowShouldClose(window))
{
  // wait for an incoming event for 3 seconds
  glfwWaitEventsTimeout(3.0);
  // rendering loop continues
}
@xevgeny
Copy link
Author

xevgeny commented Apr 30, 2024

Changing the behavior of the ComboBox's button fixes the issue. Is there a reason why "pressed on click" is not the default option?

bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_PressedOnClick);

@ocornut
Copy link
Owner

ocornut commented Apr 30, 2024

You are not well explaining how your sleeping logic works but any mouse press OR release should enforce the next 3 frames to be updated, then you won’t have issues.

@xevgeny
Copy link
Author

xevgeny commented May 5, 2024

The problem might be that ImGUI needs 4 frames to draw an open combo box, not 3.

The sleeping logic is very simple. Instead of using glfwPollEvents();, I use glfwWaitEventsTimeout(3.0). The rest is pretty much the same as in example_glfw_opengl3/main.cpp. Code to reproduce the issue is here https://gist.github.com/xevgeny/9bc7bc2d4e185cde2b71c52a0270fbb6

From the example above:

Frame 75: click happens
Frame 76: (MOUSE_PRESS)
Frame 77: (MOUSE_RELEASE)
Frame 78: (set popup open = true)
Frame 79: popup opens

Frames 76, 77, and 78 are rendered immediately after the initial mouse click. But nothing triggers frame 79, so the rendering loop waits for 3 seconds as configured.

@ocornut
Copy link
Owner

ocornut commented May 5, 2024

Then maybe 4 frames is a better wait time for now.

Down the line we should replace the “wait 3-4 frames” by a signal emitted by the lib. I believe our idling system could be made better by noting when a popup is opened or a window is just appearing.

@ocornut
Copy link
Owner

ocornut commented May 13, 2024

While I am open to discuss the possibility of making combo box start opening on mouse-down, I believe this is not your actual problem here.

Between #7569 and some comments above there is something is miunderstood:
(1) If I change combo-box to starts its opening process on mouse-down rather than mouse-up, in theory it should not change anything with your idling system, because mouse-up is an equally important event than mouse-down.

(2) I ran your repro and things works for me, I do get the combo appearing without delay as soon as I release the mouse button. I wonder if it could be caused by a swap-chain setup requiring an extra glfwSwapBuffers() to make visible the previous one?

(3) The general logic should look like:

static int run_frames = 2;
if (run_frames > 0)
{
    glfwPollEvents();
    run_frames--;
}
else
{
    glfwWaitEventsTimeout(3.0);
    run_frames = 2; // FIXME: No need to increase run_frames if timeout elapsed, how to detect?
}

Tho it is not ideal to set run_frames = 2 when wait events had a timeout.

I believe since the GLFW API doesn't allow it, the easier way to detect this currently is to read GImGui->InputEventsNextEventId before and after the call, to see if it changed. If it did it means our callbacks have generated events. it's not perfect because e.g. MonitorCallback doesn't immediately registers an event.
(Once we formalize idling we can probably expose a simple IO value to help detect this.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants