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_GetMouseState() seems to give raw mouse position when using SDL_RenderSetLogicalSize() #1397

Closed
SDLBugzilla opened this issue Feb 10, 2021 · 6 comments
Assignees
Milestone

Comments

@SDLBugzilla
Copy link
Collaborator

SDLBugzilla commented Feb 10, 2021

This bug report was migrated from our old Bugzilla tracker.

These attachments are available in the static archive:

Reported in version: HG 2.1
Reported for operating system, platform: Linux, x86_64

Comments on the original bug report:

On 2014-03-11 01:41:25 +0000, wrote:

As summary. MOUSEBUTTONDOWN events report the position as expected (in logical screen coordinates). The window is resizable. Probably also happens with fixed-size windows and a logical size that is a different aspect ratio than the window itself.

On 2014-03-11 01:54:46 +0000, wrote:

Created attachment 1589
shows bug

Here is an example program that shows the bug. On my machine, clicking in the corners of the white rectangle:

$ ./mousestate 
MOUSEBUTTONDOWN (1, 2)
GetMouseState (102, 3)

MOUSEBUTTONDOWN (398, 398)
GetMouseState (697, 598)

On 2014-05-10 15:13:51 +0000, Leonardo wrote:

This is true. The problem is that GetMouseState() consults the x/y directly whereas when reported via events, the renderer changes all the mouse events first with an event watcher before they go to the queue.

I don't see this being fixed easily as it would require the GetMouseState function to consult the renderer.

Actually this can come in handy if you ever need the real mouse position as there is no other way of knowing it. If you require your mouse coordinates to be adjusted to the logical size, you can create a event watcher like this:

int MouseWatcher(void* userdata, SDL_Event* event) {
  MouseState * m = (MouseState*) userdata;
  switch(event->type) {
    case SDL_MOUSEBUTTONDOWN:
    case SDL_MOUSEBUTTONUP:
      m->x = event->button.x;
      m->y = event->button.y;
      break;
    case SDL_MOUSEMOTION: 
      m->x = event->motion.x;
      m->y = event->motion.y;
      break;
   default:
      break;
  }
  return 0;
}

And then add it:

{
  SDL_AddEventWatch(MouseWatcher, mouseState);
}

Note that you'll need at least 2.0.3 because of bug # 2414

On 2014-07-09 07:09:03 +0000, Sylvain wrote:

Hey, I am not the original poster but I faced the same issue.
Just some thought:

CreateRenderer assume a Window.
But could we created several Renderer for the Same Window?

If so, converting an "event" (mouse position) from Window Frame to Renderer Frame is king of buggy, we could only convert to 1 specific Renderer Frame (or to the only renderer if only 1 one exists).

If no, maybe we could add a function to get the renderer of a Window :

SDL_renderer * SDL_GetRendererOfWindow(SDL_window*)

Also. Maybe the code of "SDL_RendererEventWatch" could be factorized to have a function like :

"convert_event_in_window_coordinates_to_renderer_coordinates"

We would be used in SDL_RendererEventWatch, and also exported so that users who call SDL_GetMouseState can convert their event to LogicalRendererSize.

Cheers,

Sylvain

On 2015-01-09 20:55:05 +0000, wrote:

It seems to me the resolution of this is just to add Leonardo's comments to the docs/wiki. Right now it doesn't say that SDL_GetMouseState() is the only way to get the real mouse position. In light of that, it makes sense to just get the computed position from the motion or button events.

On 2016-06-09 03:02:31 +0000, Arne Döring wrote:

I would like to ask, if there is anything done on this bug? I found out about this bug, too, and because the logical size didn't even do a recalculation of the mouse coordinates, I decided, to not use the logical size anymore. I really feels like a not well thought through feature, that I wouldn't recommend to anyone who uses SDL.

But the not make this post sound too negative. Thanks for the great work to have SDL2 actually done. I enjoy working with it.

On 2019-10-17 11:45:16 +0000, Sylvain wrote:

It's reasonable to say that querying the state returns raw values,!
We can revisit this for SDL 2.1
(see also bug 4028)

@ColinPitrat
Copy link

One option could be to have a HINT that modifies what SDL_GetMouseState returns.
Or an additional parameter to the function.

It seems having a way to get unmodified mouse coordinates can be useful but in most cases, users will want the logical coordinates, something consistent with what event contain.

@ColinPitrat
Copy link

This issue and the discussion from http://forums.libsdl.org/viewtopic.php?p=40516 make me think that SDL_RenderSetLogicalSize() is indeed not really thought through and should be avoided.

@icculus
Copy link
Collaborator

icculus commented Aug 11, 2021

SDL_RenderSetLogicalSize() is indeed not really thought through and should be avoided.

🙄

Let's look at this for 2.0.18, it seems like we can probably make this work in some way, even if it's just a hint.

@icculus icculus added this to the 2.0.18 milestone Aug 11, 2021
@icculus icculus self-assigned this Aug 11, 2021
@johnblat
Copy link
Contributor

johnblat commented Aug 11, 2021

Not sure if this is perfect, but this is what I use for getting a "logical" mouse position after setting a logical render size

void
windowMousePositionToLogicalMousePosition(SDL_Renderer *renderer, SDL_Window *window, int realMouseX, int realMouseY, int *logicalMouseX, int *logicalMouseY) {
    int wWidth, wHeight;
    int rLogicalWidth, rLogicalHeight;
    int rRealWidth, rRealHeight;
    float rScaleX, rScaleY;
    int rMidpointY, wMidpointY;
    int rMidpointX, wMidpointX;
    int rY, rX;

    SDL_GetWindowSize(window, &wWidth, &wHeight);
    wMidpointY = wHeight/2;
    wMidpointX = wWidth/2;

    SDL_RenderGetLogicalSize(renderer, &rLogicalWidth, &rLogicalHeight);
    SDL_RenderGetScale(renderer, &rScaleX, &rScaleY);
    rRealWidth = (float)rLogicalWidth*(float)rScaleX;
    rRealHeight = (float)rLogicalHeight*(float)rScaleY;
    rMidpointY = rRealHeight/2;
    rMidpointX = rRealWidth/2;
    rY = wMidpointY - rMidpointY;
    rX = wMidpointX - rMidpointX;

    int adjustedMouseY = realMouseY - rY; // takes into account any border when keeping aspect ratio
    int adjustedMouseX = realMouseX - rX;
    *logicalMouseX = (float)adjustedMouseX / (float)rRealWidth * (float)rLogicalWidth;
    *logicalMouseY = (float) adjustedMouseY / (float)rRealHeight * (float)rLogicalHeight;

}

@slouken slouken modified the milestones: 2.0.18, 2.0.20 Nov 8, 2021
@slouken
Copy link
Collaborator

slouken commented Nov 8, 2021

Let's add a function in the render API that takes real coordinates and scales them into the logical coordinates, and then document that SDL_GetMouseState() gets real coordinates.

@slouken
Copy link
Collaborator

slouken commented Dec 18, 2021

This function has been added, and should be used to transform mouse coordinates as needed.

@slouken slouken closed this as completed Dec 18, 2021
@icculus icculus modified the milestones: 2.0.22, 2.0.20 Dec 18, 2021
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

Successfully merging a pull request may close this issue.

5 participants