SDL: SDL_GetGlobalMouseState returns wrong mouse position when using x11vnc
Hi,
When using x11vnc to stream the content of the screen on Ubuntu 22.04, SDL_GetGlobalMouseState will not return the actual current mouse position, but the position where the last mouse click occurred.
I have reported this bug first on ImGui, which has an SDL2 backend: https://github.com/ocornut/imgui/issues/7217
I confirmed that the current code of X11_GetGlobalMouseState is almost the same as SDL 2.0.20 (the version shipped by Ubuntu 22.04; it only has an ifdef check for XInput2 instead of a runtime check): https://github.com/libsdl-org/SDL/blob/5b3ee51c6ca94f803a4ca77ce0dce08ee0426f80/src/video/x11/SDL_x11mouse.c#L419
I can’t say for certain if XInput2 is enabled in the version of SDL2 shipped with Ubuntu, but if it is, then I believe this behavior could be explained this way:
- The position is only updated if global_mouse_changed is true.
- It is set to true in SDL_x11xinput2.c if, e.g., XI_RawMotion or XI_RawButtonRelease events are encountered by XInput2.
- The XI_RawMotion event is not triggered by x11vnc, but XI_Motion. global_mouse_changed is not set to true by this event.
This is also supported by this source: https://stackoverflow.com/questions/62448181/how-do-i-monitor-mouse-movement-events-in-all-windows-not-just-one-on-x11
Set mask to receive XI_RawMotion events. Because it’s raw, XWarpPointer() events are not included, you can use XI_Motion instead.
If x11vnc uses XWarpPointer (which is highly likely, as the mouse position is transferred via the network), XI_RawMotion will never trigger, and as SDL doesn’t set the variable to true for XI_Motion events, it will think the mouse position never changed. Only when a XI_RawButton* event arrives, it will finally update the mouse position.
The solution should be for SDL to also set global_mouse_changed to true when encountering XI_Motion events. This should be a bug in SDL2 and not in x11vnc, as it should be perfectly legal for x11vnc to call XWarpPointer, which triggers a XI_Motion event, which in turn is not handled correctly by SDL.
About this issue
- Original URL
- State: closed
- Created 6 months ago
- Reactions: 1
- Comments: 18
Commits related to this issue
- x11: XI_Motion should mark the global mouse position as changed. Otherwise we'll miss it when XWarpPointer() is used. x11vnc may do this to manage mouse input in some circumstances, so it can be poss... — committed to libsdl-org/SDL by icculus 5 months ago
- x11: XI_Motion should mark the global mouse position as changed. Otherwise we'll miss it when XWarpPointer() is used. x11vnc may do this to manage mouse input in some circumstances, so it can be poss... — committed to madebr/SDL by icculus 5 months ago
Okay, the fix is in revision control, for both SDL2 and SDL3!
I’m impressed with all the research you did not just to solve this, but figure out why it was happening with x11vnc. Nice work. 😃