Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Sync problem with SetCursorPosition() and GetMouse*()  (Read 4738 times)

0 Members and 1 Guest are viewing this topic.

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Sync problem with SetCursorPosition() and GetMouse*()
« on: May 25, 2011, 09:02:13 pm »
Hey,

when setting the mouse cursor position manually by calling sf::Window::SetCursorPosition(), the next call to GetMouseX/Y() returns exactly that position, even if the mouse has moved during that time (needed by mouse look/mouse grabbing, for example).

I haven't checked how it's implemented, yet, therefore I'm asking if the delay is too short so that sf::Window (or even the OS/window manager) isn't able to fetch the mouse move event in-time.

Here's a minimal example to reproduce the problem. It prints out the relative position from the window's center when the mouse has moved + one iteration after that.

Code: [Select]
#include <SFML/Graphics.hpp>
#include <iostream>

int main() {
sf::RenderWindow window( sf::VideoMode( 800, 600, 16 ), "Minimal" );
sf::Event event;
const sf::Input& input( window.GetInput() );
unsigned char print_count( 0 );

window.EnableVerticalSync( true );

while( window.IsOpened() ) {
while( window.PollEvent( event ) ) {
if( event.Type == sf::Event::Closed ) {
window.Close();
}
}

// Get mouse movement delta values.
sf::Vector2i mouse_delta(
input.GetMouseX() - (800 / 2),
input.GetMouseY() - (600 / 2)
);

if( mouse_delta.x || mouse_delta.y ) {
print_count = 2;

// Reset mouse cursor to window center (fake grabbing).
window.SetCursorPosition( 800 / 2, 600 / 2 );
}

// Print 'em.
if( print_count ) {
std::cout << mouse_delta.x << ", " << mouse_delta.y << std::endl;
--print_count;
}

window.Clear();
window.Display();
}
}


The example shows that the mouse deltas are always (0, 0) after each mouse move which results in stuttering mouse looks. Any ideas?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Sync problem with SetCursorPosition() and GetMouse*()
« Reply #1 on: May 25, 2011, 10:11:02 pm »
Which version of SFML?
Laurent Gomila - SFML developer

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Sync problem with SetCursorPosition() and GetMouse*()
« Reply #2 on: May 26, 2011, 12:16:52 am »
SFML 2, latest commit.

Edit: And just to clarify: Not ALL following deltas show (0, 0), only one after the other. For example if you move the mouse continously to the left in the above source code, you'll get something like this:

Code: [Select]
-5, 0
0, 0
-10, 0
0, 0
-8, 0
0, 0
-x, 0
0, 0
...

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Sync problem with SetCursorPosition() and GetMouse*()
« Reply #3 on: May 26, 2011, 07:55:32 am »
Which operating system?
Laurent Gomila - SFML developer

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Sync problem with SetCursorPosition() and GetMouse*()
« Reply #4 on: May 26, 2011, 02:52:09 pm »
Debian GNU/Linux, therefore X Window system.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Sync problem with SetCursorPosition() and GetMouse*()
« Reply #5 on: May 26, 2011, 03:28:55 pm »
Thanks.

Looking at the implementation doesn't give a clear explanation to this problem, so I'll need to do some tests.
Laurent Gomila - SFML developer

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Sync problem with SetCursorPosition() and GetMouse*()
« Reply #6 on: May 28, 2011, 02:36:37 pm »
I did some tests and was able to reproduce the problem on Linux. However it works fine on Windows.

This is strange because the code that removes mouse events triggered by calling SetCursorPosition is applied on top of the OS-specific implementation, so the results should be the same for every platform. And both OS-specific functions (the ones that implement SetCursorPosition) behave the same way.

So I'm sorry but I couldn't find out what's wrong :?
Laurent Gomila - SFML developer

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Sync problem with SetCursorPosition() and GetMouse*()
« Reply #7 on: May 28, 2011, 02:45:38 pm »
Maybe it's X faulting here. :)

Thanks for your tests. I'll also try to find something. If nothing shows up, I'll talk to some X guys or file a bug report.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Sync problem with SetCursorPosition() and GetMouse*()
« Reply #8 on: May 28, 2011, 03:21:20 pm »
I still don't know what happens but I have the feeling that I'm doing something wrong with mouse move events.

Since SFML 1.3, the mouse move events triggered by SetCursorPosition are filtered out by sf::Window. This was necessary according to this old topic.

So, your event loop doesn't receive these events, but sf::Input does and updates its MouseX and MouseY members accordingly. So I think your code would work if you catch mouse move events rather than using sf::Input.
Laurent Gomila - SFML developer

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Sync problem with SetCursorPosition() and GetMouse*()
« Reply #9 on: May 28, 2011, 11:42:49 pm »
Ah, I understand the problem now. So that means when I set the cursor position manually, the program runs probably too fast to get a new movement into the chain (for sf::Input), therefore sf::Input still returns the "old new position".

Okay, I will check for MouseMoved events to see if there's new data of interest. Thanks!

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Sync problem with SetCursorPosition() and GetMouse*()
« Reply #10 on: May 30, 2011, 12:18:59 pm »
The described problem can't be solved on the user-side. The problem is that FilterEvent() returns false when it detects mySetCursorPos* for the current MouseMoved event. By returning false, the whole event loop (calling PollEvent) is canceled, because false is returned (you usually have something like "while( window.PollEvent( ... ) ) { ... }", and that one is cancelled due to FilterEvent()).

The result is that not all pending events get processed and a mouse look will stutter because every 2nd frame the event loop is cancelled.

Two options:
- Even if FilterEvent() returns false, continue on pending events in the queue.
- Remove the check.

Personally I'd go with the second option. I can't think of any situations where SetCursorPosition() raising an event would be problematic. You set the mouse position, you get an event, quite logical IMHO.

If on the user-side you want to drop that position, cache it and drop it next cycle (like you're doing it with SFML currently). The advantage is that the event processing isn't cancelled.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Sync problem with SetCursorPosition() and GetMouse*()
« Reply #11 on: May 30, 2011, 12:41:29 pm »
Quote
Personally I'd go with the second option. I can't think of any situations where SetCursorPosition() raising an event would be problematic. You set the mouse position, you get an event, quite logical IMHO.

I tend to agree with that, but I'm sure that a lot of users will be unhappy if I do so.
But anyway, it makes more sense and it works like that in other libraries (especially SDL), so I think it's no crazy to let SetCursorPosition trigger mouse move events :)

Thank you a lot for your help. I'll apply the fix as soon as possible.
Laurent Gomila - SFML developer

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Sync problem with SetCursorPosition() and GetMouse*()
« Reply #12 on: May 30, 2011, 12:59:36 pm »
I guess it won't break any existing code.

Thanks, looking forward to smooth mouse look, again. ;)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Sync problem with SetCursorPosition() and GetMouse*()
« Reply #13 on: May 30, 2011, 06:57:31 pm »
Quote
I guess it won't break any existing code.

I think it will, but anyway... it's done now.
Laurent Gomila - SFML developer

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Sync problem with SetCursorPosition() and GetMouse*()
« Reply #14 on: May 30, 2011, 10:02:01 pm »
Thank you very much.

 

anything