SDL icon indicating copy to clipboard operation
SDL copied to clipboard

SDL_WarpMouseInWindow doesn't affect future mouse coordinates

Open Flamefire opened this issue 2 years ago • 8 comments

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?

Flamefire avatar Jun 01 '22 08:06 Flamefire

I'm guessing maybe you're getting Wayland instead of X11 as the active backend? Wayland doesn't support any mouse warping at all.

slouken avatar Jun 01 '22 14:06 slouken

How can I check and change that?

Flamefire avatar Jun 01 '22 20:06 Flamefire

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.

sulix avatar Jun 02 '22 15:06 sulix

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...

Flamefire avatar Jun 02 '22 15:06 Flamefire

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

slouken avatar Aug 05 '22 20:08 slouken

Can you provide more information on your distribution and desktop environment?

slouken avatar Aug 05 '22 20:08 slouken

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.

icculus avatar Aug 06 '22 00:08 icculus

Let's boot this from the 2.24 milestone.

icculus avatar Aug 09 '22 13:08 icculus

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.

slouken avatar Aug 11 '22 21:08 slouken

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?

Flamefire avatar Aug 12 '22 11:08 Flamefire

It should, there was another change in there that corrects mouse positioning after any warp. Did you try it?

slouken avatar Aug 12 '22 14:08 slouken