imgui: Mouse spamming wheel events causing input queue to never catch up (was: Can I make imgui consume all the input events when ImGuiIO::ConfigInputTrickleEventQueue is on?)

Version/Branch of Dear ImGui:

Version: 1.88 Branch: master

My Question:

Context: I have a mouse that can generate ~100 WM_MOUSEWHEEL events every second for 15secs when flicked hard. I use ImGuiIO::AddMousePosEvent(); ImGuiIO::AddMouseWheelEvent(); to pass all these events and imgui becomes very unresponsive until the events calm down. I tracked the problem down to ImGuiIO::ConfigInputTrickleEventQueue being true by default. If I turn it off there is no unresponsiveness. Similarly turning off vsync (so ImGui::NewFrame()/ImGui::Render() loop runs as fast as possible) also helps.

My question: Is there a way to make imgui consume all the input in the same frame (and update all the control datastructures multiple times until all the events are consumed) when ImGuiIO::ConfigInputTrickleEventQueue is on? I like the idea of ImGuiIO::ConfigInputTrickleEventQueue flag so I don’t want to turn it off, but I also like to flick my mouse wheel.

Thanks

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Comments: 19 (8 by maintainers)

Most upvoted comments

Currently traveling so will look in detais later, but you haven’t answered the core of my question quoted above. What happens with the wheeling inputs, what do they perform in term of acting with while simultaneously moving around ?

Moving around the mouse/window while wheeling was an example to illustrate the problem of event flooding. A more realistic example would be scrolling to the end of a long list of input fields from top of the window and hit submit button that is at the very bottom. That doesn’t require moving the mouse that much while scrolling. What happens today (if I use the fast mouse wheel) is that button is hit a couple of seconds after I click the mouse button. Everything eventually works but experience isn’t great when mouse wheel events are firing that often. Turning io.ConfigInputTrickleEventQueue off improves the experience greatly but as I mentioned in the very first post, I’d like to keep it on in order to not stomp on events I care about (e.g. repeated presses during low fps situations).

What would happens on an application where eg wheeling can be used to edit a spinner widget that is being hovered ?

What is a spinner widget? I searched for spin in imgui_demo.cpp but I don’t have any hits.

This is making assumptions about what each application does with the inputs, I don’t know how far those assumptions can hold.

That’s fair. If you think rest of the idea is valuable, priority can be a user input instead of a library default.

If anybody can legally buy that mouse you have, my intuition is not to provide you with an opt-in workaround but make sure it is works for everyone.

It isn’t necessarily an obscure mouse https://www.amazon.com/Logitech-M500-Corded-Mouse-Hyper-Fast/dp/B002B3YCQM

Hi, I’m very sorry for the late reply.

Which might work but honestly I can sense this may be causing obscure problem with backends… Not mentioning it would be abnormally heavy, even more bizarrely slow considering the overall situation being “wheeling with a certain type of mouse reduce framerate by 30% and surfaces obscure app bugs”. I think it is reasonable to rule out that solution completely.

You are opening quite a complicated problem here. We can’t design a fix or workaround just for you, it needs to work for all apps by default since people shipping apps would expect things to work with that sorts of mouse (designed by devils I must say).

My intention for creating this issue was to look for something I can personally do myself, not change something for everyone, unless the change is trivial. I understand what I described could be heavy for general use.

I guess for a start we need to consider: what do you generally expect to happen when doing such a “long” wheeling while simultaneously moving the mouse?

I expect UI to stay interactive just like the file explorer or chrome browser do when “long” wheeling happens (e.g. when I click on a button during wheeling, button still works just like it normally does).

What happens in your typical game or application? Are things mostly relying on the fact that most (but maybe not all) modern software are “locking” on the wheeling target when starting to wheel?

I use DearImGui for simple debugging ui, so I don’t want imgui to lose io events (by keeping io.ConfigInputTrickleEventQueue on) and I want it to perform reasonably when flooded with wheel events (admittedly, flooding due to wheel events is something I can prevent through my behavior).

I suspect we may need to involve two approaches:

  • Input queue need to know how to react when its over-filling. It may be senseful to merge events and catch up in some cases. Maybe simply we stop trickling interleaved mouse pos/wheel events if that “fast rate of events” is a thing only specific to mouse wheel. Or we stop trickling only in some situation (based on event counts or frame/time of each event…).
  • Input queue could be aware that something has been “locked” for mouse wheeling meaning mouse position won’t interfere with use of wheel values. In that situation it becomes safe to merge interleaved pos/wheel events. When wheeling to scroll a window we set a latch (g.WheelingWindow in StartLockWheelingWindow()) we would need to generalize that to having a “wheel owner” and that wheel owner can state that it doesn’t care anymore about mouse position and then merging can be done.
  • Also means if no one is using the mouse wheel we can safely merge but right now we have no mechanism to tell that mouse wheel is being used or even polled. This is very tricky.

Approach 1 sounds reasonable to me. I imagine categorizing events into high (mouse/keyboard button press) and low priority (mouse pos/wheel) events and making sure high priority events are handled by merging/skipping over low priority events during event queue flooding could work in this case.

Could you run the same code, copy the full log to Clipboard then into a file and attach to a file here?

Please find the logs at https://gist.github.com/esert/5ec32d1dbf3be812795f15aa2216f58c

Thanks

PS: In the very last commit under Tools>DebugLog I have added a [X] IO checkbox allowing to visualize input events and how they are trickled. This is equivalent to what I asked you to enable, but it is now always on. image