Questions about frequency of cursorPos events when using vsync


#1

I’m working on a little cellular automata project to familiarize myself with GLFW, (for those unfamiliar, its essentially just a grid that can be drawn into by the user, which updates each cell over time according to some function)

Currently, I process events by registering callbacks and calling glfwPollEvents() every frame before updating. As I understand it, this will de-queue every item currently in the event queue and dispatch to their respective callbacks. The input guide says “glfwPollEvents, processes only those events that have already been received and then returns immediately.” but the name implies it may also poll the current device states? …I’m just a little iffy on the exact behavior…

On to the main point of confusion: I wanted the user’s drawing to be as accurate as possible, so I decided I would examine every mouse position in the queue instead of just the most recent one. However, there are way, way fewer cursorPos events coming in than I would expect. Normally with the swap interval set to 1, (updating at 60 hz) I’m getting 1 or 2 cursorPos events coming in, maybe 3. I was a little surprised that there were so few so I experimented a little, changing the swap interval so it only updated once per second, and still got 1 - 4 events per update.

:neutral_face: Hmm…ok maybe glfwSwapBuffers is preventing some events from being recorded while it waits for the swap interval to pass…? how bout if I just put an empty loop right before the call to glfwPollEvents and spin until at least a second has elapsed then continue? Same deal, at most 4 cursorPos events in the queue.

How do glfwPollEvents and the event queue work exactly?

At first I thought maybe it was polling and only giving me the current mouse position right when I called glfwPollEvents, but then why am I getting up to 4 per update (all roughly evenly spaced apart)?

Then I thought maybe GLFW was polling events for the queue way less frequently that I first assumed, but then why when processing the queue 60x less frequently, am I only seeing ~2x more cursorPos events? Is the event frequency dependent on something else I’m forgetting?

Is this just a completely unreliable way to track mouse input? Is there no guarantee that there will be regular cursorPos events in the queue (assuming the cursor is actually moving)?

Hopefully someone here can tell my that I’m stupid and thinking about this completely wrong . Maybe there’s a simple explanation that I’m just failing to see. :slight_smile:

EDIT: It might also relevant to mention that I’m running on Windows 10.


#2

Mouse move events on Windows are processed as WM_MOUSEMOVE message. This message is special “low priority” message. These messages are not generated all the time, because processing them would cost a lot of CPU - most applications are not interested in every single small mouse movement.

What actually happens is when you poll messages from OS, the OS checks is there any other message currently in queue. If there are, then it deques them and passes to processing. But if there are none, then it generates these “low priority” messages. Like WM_MOUSEMOVE, which will contain change from last time it was generated. Other examples are WM_PAINT and WM_TIMER (if I’m not mistaken).

This is very simplified explanation what happens. In reality OS still can generate WM_MOUSEMOVE even if there are other messages in queue, I guess there is some time-out - if low-priority message was not generated in last N milliseconds then generate it even if there are other messages in queue.

If you want more accurate mouse input, you’ll need to look into using Raw Input API. Afaik GLFW doesn’t use Raw Input.


#3

Ah thanks! That actually explains a lot. It didn’t occur to me it’d be something to do with Windows itself. Good to know I was just trying to go down the wrong road.

I’m still not sure why waiting for a much longer time didn’t seem to have much effect on the number of messages coming in, but I guess that’s likely just another Windows related thing. :slight_smile:


#4

If you’re not hiding the cursor with GLFW_CURSOR_DISABLED, and you call glfwGetCursorPos the code will call GetCursorPos and return the value, which may give you improved update rates.

For raw input, see issue Raw mouse input #125. There used to be a fork with Windows raw mouse but I can’t find it any more. I might be able to find time to do this (unless @elmindreda already has a fix), but I have a lot of other work on atm.


#5

Raw motion input for disabled cursor mode on Windows is available in the raw-mouse-motion branch, waiting for me to finish the X11 implementation.

The way it’s currently implemented won’t give more frequent cursor position updates, just more accurate ones. Should I retrieve and pass along the full motion? That will be a lot of cursor position events.