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

X11 mouse position has subtle issues #11646

Open
niconii opened this issue Dec 14, 2024 · 5 comments
Open

X11 mouse position has subtle issues #11646

niconii opened this issue Dec 14, 2024 · 5 comments
Milestone

Comments

@niconii
Copy link

niconii commented Dec 14, 2024

Here's a YouTube video showcasing the below code. driver is the current video driver, mouse is the position from the latest mouse motion event, and gmouse is the position from SDL_GetGlobalMouseState.

It's hard to pin down exactly what's wrong, but you can see instances where mouse seems to lag behind gmouse, instances where the mouse cursor visibly moves a pixel but this isn't reflected in SDL, and so on.

As best as I can tell, SDL_VIDEO_DRIVER=wayland doesn't have these issues.

#include <SDL3/SDL.h>

#define SDL_MAIN_USE_CALLBACKS
#include <SDL3/SDL_main.h>

SDL_Window *window;
SDL_Renderer *renderer;

float mouse_x = 0;
float mouse_y = 0;
float gmouse_x = 0;
float gmouse_y = 0;

SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) {
  SDL_Init(SDL_INIT_VIDEO);
  SDL_CreateWindowAndRenderer("Test Window", 320, 240, 0, &window, &renderer);
  
  return SDL_APP_CONTINUE;
}

SDL_AppResult SDL_AppIterate(void *appstate) {
  char *text = NULL;
  
  SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
  SDL_RenderClear(renderer);

  SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);

  SDL_asprintf(&text, "driver %s", SDL_GetCurrentVideoDriver());
  SDL_RenderDebugText(renderer, 0, 0*8, text);
  SDL_free(text);

  SDL_asprintf(&text, " mouse x=%11.6f y=%11.6f", mouse_x, mouse_y);
  SDL_RenderDebugText(renderer, 0, 1*8, text);
  SDL_free(text);

  SDL_GetGlobalMouseState(&gmouse_x, &gmouse_y);
  SDL_asprintf(&text, "gmouse x=%11.6f y=%11.6f", gmouse_x, gmouse_y);
  SDL_RenderDebugText(renderer, 0, 2*8, text);
  SDL_free(text);

  SDL_RenderPresent(renderer);

  return SDL_APP_CONTINUE;
}

SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
  switch (event->type) {
    case SDL_EVENT_QUIT: {
      return SDL_APP_SUCCESS;
    }

    case SDL_EVENT_MOUSE_MOTION: {
      mouse_x = event->motion.x;
      mouse_y = event->motion.y;
      break;
    }
  }

  return SDL_APP_CONTINUE;
}

void SDL_AppQuit(void *appstate, SDL_AppResult result) {
  SDL_DestroyRenderer(renderer);
  SDL_DestroyWindow(window);
}
@slouken slouken added this to the 3.2.0 milestone Dec 14, 2024
@Kontrabant
Copy link
Contributor

For clarification, are you seeing this behavior on a real X11 session, when running via XWayland, or both?

@niconii
Copy link
Author

niconii commented Dec 15, 2024

I've tested this in GNOME on Arch Linux, in both Wayland and X11. It happens on both a real X11 session and Xwayland, but doesn't happen running natively on Wayland. @12Me21 and @y-ack were both able to reproduce this on their computers. @y-ack has also confirmed this doesn't happen on Windows.

I'd like to provide more videos, but while recording I discovered a bug in OBS preventing me from accurately recording the mouse position, so now I'm investigating that too. In the meantime, adding this code to SDL_AppIterate before SDL_RenderPresent makes the problem a bit easier to see:

  SDL_SetRenderDrawColor(renderer, 0, 255, 0, 128);
  SDL_RenderLine(renderer, SDL_floorf(mouse_x), 0, SDL_floorf(mouse_x), 240);
  SDL_RenderLine(renderer, 0, SDL_floorf(mouse_y), 320, SDL_floorf(mouse_y));

@Kontrabant
Copy link
Contributor

This seems like a mismatch between the coordinates provided by XInput and XQueryPointer. XInput does provide the root coordinates in motion events, so that should be used if a window has focus to avoid possible relative/global mismatches.

Can you test this branch and see if it fixes your issue: https://github.com/Kontrabant/SDL/tree/x11_coordinate_mismatch

@niconii
Copy link
Author

niconii commented Dec 17, 2024

Before this branch, mouse seemed to lag behind by one motion, but gmouse was correct.

With this branch, mouse and gmouse both lag behind by one motion.

So, this doesn't fix the issue. However, this suggests to me that the problem lies with the Xinput code specifically, and indeed, when I build without Xinput support, the bug does not occur.

@niconii
Copy link
Author

niconii commented Dec 18, 2024

if (xev->deviceid != xev->sourceid) {
// Discard events from "Master" devices to avoid duplicates.
break;
}

Commenting out these lines fixes the bug, though I don't know why.

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

3 participants