glfwSetMousePos() weirdness?

sporkstorms wrote on Monday, January 15, 2007:

Let’s consider the following simplifed pseudo-code. The purpose is to detect relative movements of the mouse - ie, I’m interested in knowing delta movements.

void called_with_each_draw() {
mid_x = screen_width / 2;
mid_y = screen_height / 2;
glfwGetMousePos(&x, &y);
// Don’t do anything if mouse hasn’t moved
if (x == mid_x && y == mid_y) { return; }

delta\_x = mid\_x + x;
delta\_y = mid\_y - y;

move\_camera\_or\_do\_whatever\(delta\_x, delta\_y\);

// Now move the mouse back to the middle, because
// we don't care where it really is, just how much 
// it moves.
glfwSetMousePos\(mid\_x, mid\_y\);


Now I expect this to give me a small value for delta_x if i move the mouse slowly and slightly to the side, and a large value if I jerk the mouse quickly.

It does not work like this, hower. You can move it and initially get something like my expectations, and then (also as I’d expect) while keeping the mouse still you get 0s for the deltas.
The weirdness comes in when you move the mouse again. At this point is seems to remember what the last position was. Rather than moving from the mid_x and mid_y with which we called glfwSetMousePos(), it moves from the value that gave us those first deltas.

Whenever the mouse isn’t moving you get, as expected, zeros for the deltas (ie, getMousePos is giving the thing you last set with setMousePos). But as soon as you move the mouse, its position is suddenly tracking from its old location before you called setMousePos.

Why does this happen? Is it intentional, and if so, how can I get the behavior I’m looking for?

If it isn’t intentional, here is some further info in case it’s helpful: This behavior appears to happen in fullscreen mode whether you disabled GLFW_MOUSE_CURSOR or not. In windowed mode it happens if you disable the cursor. In windowed mode with the cursor enabled, I’m not entirely sure how it behaves (i still have to work out how to test it because the mouse coordinates appear to be different and the setMousePos is throwing my cursor out of the window before i can figure out what’s going on).

sporkstorms wrote on Monday, January 15, 2007:

This is on OS X, in case that’s relevant (since I’d guess carbon is used for mouse stuff)

elmindreda wrote on Thursday, March 22, 2007:

Bug confirmed and being worked on.

elmindreda wrote on Friday, March 23, 2007:

This bug is now fixed. Thank you.

nobody wrote on Wednesday, April 25, 2007:

Which version was this fixed in?

elmindreda wrote on Wednesday, April 25, 2007:

It is fixed in CVS but not in any release (yet).

ttk-bandit wrote on Friday, March 21, 2008:

I get similar problems on windows.
using mouseposcallback, but it gives me very strange values.
for example:
After I drag the mouse to the left a few times, my cam angle spins up very fast to the left even though I only move the mouse slowly.
And when I then try to move right, it keeps turning left, getting slower over time until then finally turning right and speeding up again.

ttk-bandit wrote on Friday, March 21, 2008:

got it fixed, here is what I changed (based on version 2.6):

starting changes in the middle of _glfwWindowCallback:

// Did the mouse move?
if ( _glfwWin.Active ) // add this… (so there wont be any mouse events on an inactive window when the mouse hovers over your opengl window)

#if 0 // change this
_glfwInput.MousePosX = NewMouseX;
_glfwInput.MousePosY = NewMouseY;
_glfwInput.OldMouseX = NewMouseX;
_glfwInput.OldMouseY = NewMouseY;
#else // to this:
_glfwInput.OldMouseX = _glfwInput.MousePosX = NewMouseX;
_glfwInput.OldMouseY = _glfwInput.MousePosY = NewMouseY;

… // at the end of _glfwCreateWindow, add this:

\_glfwInput.MouseMoved = GL\_FALSE;

… // at the beginning of _glfwPlatformPollEvents, remove these 3 lines:

// Flag: mouse was not moved \(will be changed by \_glfwGetNextEvent if
// there was a mouse move event\)
\_glfwInput.MouseMoved = GL\_FALSE;

… // and later in this function:

// Did we have mouse movement in locked cursor mode?
if\( \_glfwInput.MouseMoved && \_glfwWin.MouseLock \)
    \_glfwPlatformSetMouseCursorPos\( \_glfwWin.Width / 2,
                                    \_glfwWin.Height / 2 \);
    \_glfwInput.MouseMoved = GL\_FALSE; // Add this\!

elmindreda wrote on Friday, March 21, 2008:

Please submit a patch for this to the patch tracker and I’ll review it.