Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDL_WarpMouseInWindow doesn't affect future mouse coordinates #5741

Closed
Flamefire opened this issue Jun 1, 2022 · 11 comments
Closed

SDL_WarpMouseInWindow doesn't affect future mouse coordinates #5741

Flamefire opened this issue Jun 1, 2022 · 11 comments
Assignees
Milestone

Comments

@Flamefire
Copy link
Contributor

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?

@slouken
Copy link
Collaborator

slouken commented Jun 1, 2022

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 slouken added this to the 2.24.0 milestone Jun 1, 2022
@Flamefire
Copy link
Contributor Author

How can I check and change that?

@sulix
Copy link
Contributor

sulix commented Jun 2, 2022

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.

@Flamefire
Copy link
Contributor Author

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

@slouken
Copy link
Collaborator

slouken commented Aug 5, 2022

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
Copy link
Collaborator

slouken commented Aug 5, 2022

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

@slouken slouken added the waiting Waiting on user response label Aug 5, 2022
@icculus
Copy link
Collaborator

icculus commented Aug 6, 2022

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
Copy link
Collaborator

icculus commented Aug 9, 2022

Let's boot this from the 2.24 milestone.

@slouken slouken modified the milestones: 2.24.0, 2.26.0 Aug 9, 2022
@slouken slouken assigned slouken and unassigned icculus Aug 11, 2022
@slouken slouken removed the waiting Waiting on user response label Aug 11, 2022
@slouken slouken modified the milestones: 2.26.0, 2.24.0 Aug 11, 2022
@slouken
Copy link
Collaborator

slouken commented Aug 11, 2022

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.

@Flamefire
Copy link
Contributor Author

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?

@slouken
Copy link
Collaborator

slouken commented Aug 12, 2022

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

PJB3005 pushed a commit to PJB3005/SDL that referenced this issue Oct 5, 2022
This hint controls whether mouse warping generates motion events in relative mode, and defaults off.

Fixes libsdl-org#6034
Fixes libsdl-org#5741
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants