SDL
SDL copied to clipboard
SDL_WarpMouseInWindow doesn't affect future mouse coordinates
Context: I'm using an abstraction layer over SDL2 where the application gets (only) mouse-motion events with the coordinates (x,y from the SDL motion event), not the relative coordinates. Also the SDL_WarpMouseInWindow
is exposed in the abstraction layer. I haven't tested SDL_SetRelativeMouseMode
as it would require changing a lot in that layer and down.
Now I implement map scrolling/panning on rightclick by:
- store x,y on rightclick
- on mouse-move calculate the delta to stored x,y
- move map by this delta
- warp the mouse back to stored x,y
This works well on most platforms but somewhere in the near past it broke on linux, likely after updating some system packages. There I observe the following behavior (stream of events) during e.g. a horizontal movement:
- rightclick @ 1,1
- move to 2,1 -> Warp 1,1
- move to 1,1
- move to 3,1 -> Warp 1,1
- move to 1,1
- move to 4,1 -> Warp 1,1
- move to 1,1
- move to 5,1 -> Warp 1,1
- etc.
I.e. what seemingly happens is that I get the expected motion event for the warp, but the next real motion event reports coordinates completely unaffected by the warp, even in case of VERY slow mouse movement.
Ingame-effect: The map starts moving faster and faster as the mouse moves (in the last above example) 4 pixels instead of 1.
I'm lost in how to handle this especially as it seemingly is caused by a change on the OS side not on the SDL side which AFAIK wasn't changed when that started to happen.
Any ideas on why the actual cursor state is seemingly unaffected by the warp?
I'm guessing maybe you're getting Wayland instead of X11 as the active backend? Wayland doesn't support any mouse warping at all.
How can I check and change that?
You can force the x11 backend with the SDL_VIDEODRIVER=x11
environment variable.
Otherwise, you might get some use out of Pull Request #5546 — which attempts to emulate mouse warp using relative mouse mode. It's designed for the 'controlling a 3d camera' case, so might not work with your use-case though.
In general, though, mouse warping isn't supported on Wayland systems, and the Wayland developers have no plans to ever support it. Rewriting to use SDL_SetRelativeMouseMode
is going to be the future-proof solution to this.
I tried with SDL_VIDEODRIVER=x11 ./my_game
and got the same behavior. Seems I have to try and use the relative mouse mode. Ugh...
I modified testsprite2 to help reproduce this behavior, and what I'm seeing is that the X server is applying the warp and then applying the motion afterward.
diff --git a/test/testsprite2.c b/test/testsprite2.c
index a91ddd86e..39fc752e9 100644
--- a/test/testsprite2.c
+++ b/test/testsprite2.c
@@ -404,6 +404,12 @@ loop()
/* Check for events */
while (SDL_PollEvent(&event)) {
+ if (event.type == SDL_MOUSEMOTION) {
+ printf("Motion: %d,%d\n", event.motion.x, event.motion.y);
+ if (event.motion.x != 1 || event.motion.y != 1) {
+ SDL_WarpMouseInWindow(state->windows[0], 1, 1);
+ }
+ }
SDLTest_CommonEvent(state, &event, &done);
}
for (i = 0; i < state->num_windows; ++i) {
I think these are legitimate deltas:
Motion: 1,1
Motion: 9,0
Motion: 1,1
Motion: 3,0
Motion: 1,1
Motion: 6,0
Motion: 1,1
Motion: 8,0
Motion: 1,1
Motion: 8,0
Motion: 1,1
Motion: 5,0
Motion: 1,1
Motion: 6,0
Motion: 1,1
Motion: 6,0
Motion: 1,1
Motion: 4,0
Motion: 1,1
Can you provide more information on your distribution and desktop environment?
Just remembering that Wayland doesn't get used by default (we changed it to favor x11 at the last moment and haven't tried again), so forcing X11 didn't change anything because X11 was probably what was used in the first place.
Let's boot this from the 2.24 milestone.
I think I found the problem and fixed this. Please reopen this bug if it doesn't resolve your issue, and we can look at it again.
The referenced commit seems to fix behavior in relative mode. But I'm not using relative mode (yet) due to another abstraction layer on top of SDL. So I don't think this will fix my issue, will it?
It should, there was another change in there that corrects mouse positioning after any warp. Did you try it?