Merge Events of Same Type?

I’m porting a fairly simple mesh processing app written with Qt5 to GLFW, and I’m running into a few performance issues with user input. The original app redrew the main user view directly in response to mouse activity. That is, every mouse move event triggered a redraw, and there were no timers. This led me to use glfwWaitEvents with the response to mouse events explicitly kicking off draw calls instead of glfwPollEvents followed by a render (no need to sit in the background constantly redrawing if nothing has changed). This leads to noticeable lag, however, as quite a few mouse events can queue up while a draw call is running, and each of these mouse events in turn fires off its own render.

Looking into the Qt5 solution, it appears that Qt5 merges events of similar types that are next to one another in the event queue (consecutive draw events get merged, consecutive mouse events of the same type get merged, etc). Is there a way of doing something similar in GLFW? I primarily want multiple, consecutive mouse cursor position events to get merged. Is this possible out of the box, or will I have to roll my own fix?

Thanks!

Merging events is not always preferable. For example, for drawing program it is very useful to receive each mouse move event for it to be able to draw smooth lines. Even if it means processing more than one mouse move event per frame.

Afaik on Windows it typically does repaint after all other messages are processed. Basically in each message (mouse move or keyboard key press or whatever) if you want to repaint window you do InvalidateRect(…) call that generates WM_PAINT message. But WM_PAINT message is special - it is basically boolean flag. It is actually generated only after window processes all other messages: https://support.microsoft.com/en-us/kb/96006

You can do the same - create global boolean that would mean “need_to_redraw” and structure main loop to to wait for messages until this boolean is true. And in each event (mouse move / key press / refresh / etc) you want to redraw window simply set boolean to true. Something like this:

bool globalNeedToRedraw = false; ... while (true) { while (!globalNeedToRedraw) { glfwWaitEvents(); } globalNeedToRedraw = false; DoTheRendering(); glfwSwapBuffers(window); }

This will always process all events before rendering, so there won’t any lag for rendering. And it won’t do any rendering if no event has happened.

Actually it would be nice if glfw would allow to call InvalidateRect on window. Then you totally could skip rendering in main loop, call only glfwWaitMessages() tehre. And do the rendering only in refresh callback - that is the one that responds to WM_PAINT message.

As per @mmozeiko’s reply there is no event merging in GLFW, and it wouldn’t be suitable for most applications.

Some more information may be required to help you find a solution, such as whether you’re using cursor position callbacks and how you’re handling the drawing (asynchronously with the input thread or not).

My temptation in this case would be simply to avoid using mouse position callbacks and instead sample the mouse position with glfwGetCursorPos whilst using glfwWaitEvents to block. Then check if your position has changed and if so draw - though you may not need to check as most events you’ll get will be mouse position changes.

You can do the same - create global boolean that would mean “need_to_redraw” and structure main loop to to wait for messages until this boolean is true. And in each event (mouse move / key press / refresh / etc) you want to redraw window simply set boolean to true.

I like this solution a lot, thank you for the suggestion. As long as I make the book keeping for accumulating events fast enough I think this should perform well.

Some more information may be required to help you find a solution, such as whether you’re using cursor position callbacks and how you’re handling the drawing (asynchronously with the input thread or not).

I am using the cursor position callbacks (via glfwSetCursorPosCallback) and rendering is synchronous with the main thread.

My temptation in this case would be simply to avoid using mouse position callbacks and instead sample the mouse position with glfwGetCursorPos whilst using glfwWaitEvents to block. Then check if your position has changed and if so draw - though you may not need to check as most events you’ll get will be mouse position changes.

Something like that could work, I hadn’t considered bypassing the cursor callbacks entirely. Thanks!

I use glfwWaitEvents with glfwGetCursorPos in my Power Save mode in the editor. It works well for me.