libsdl-org / SDL

Simple Directmedia Layer
https://libsdl.org
zlib License
9.85k stars 1.83k forks source link

SDL3: SDL_MouseMotionEvent and SDL_MouseButtonEvent not reporting a valid SDL_MouseId. #11259

Open Oliver-makes-code opened 1 week ago

Oliver-makes-code commented 1 week ago

I'm setting up an input handler for my game engine, and I'm setting it up to support different devices (for local multiplayer), and the events SDL_MouseButtonEvent and SDL_MouseMotionEvent are returning 0 for .which. SDL_MouseWheelEvent is unaffected.

Here's the debug log output from my engine:

main: [DEBUG] SDL event: 1024
main: [WARN] Failed to find Rendering::Input::Mouse device with index 0
main: [DEBUG] SDL event: 1025
main: [WARN] Failed to find Rendering::Input::Mouse device with index 0
main: [DEBUG] SDL event: 1026
main: [WARN] Failed to find Rendering::Input::Mouse device with index 0

I made sure I was on the latest commit from the main branch before reporting.

AntTheAlchemist commented 1 week ago

I'm getting the same. It's been this way for as long as I remember. I just assumed the ID wasn't available. I'd be interested in this working.

AntTheAlchemist commented 1 week ago

Oddly, I get a correct ID when in relative mode.

slouken commented 1 week ago

I'm not sure where best to document it, but the mouse ID is only available in relative mode on desktop platforms.

Oliver-makes-code commented 1 week ago

I'm not sure where best to document it, but the mouse ID is only available in relative mode on desktop platforms.

Could there be a hint to treat it as an arbitrary ID? SDL_SetHint(SDL_HINT_GLOBAL_MOUSE_ID, "1");

slouken commented 1 week ago

Or you can just treat mouse ID 0 as your default mouse?

Sackzement commented 1 day ago

I'm not sure where best to document it, but the mouse ID is only available in relative mode on desktop platforms.

I would put it right beside the other comment. Something short like "relative-mode only". https://github.com/libsdl-org/SDL/blob/2a05b63580b3962fd19a9fcac77c5ba9c6fa0276/include/SDL3/SDL_events.h#L425

And that for every struct member with a mouse ID that only works in relative mode.

This is the most likely place where users look for what the members do.

Sackzement commented 1 day ago

Or you can just treat mouse ID 0 as your default mouse?

For a wheel event I always get a mouse ID of 7, for every other event I get 0.

Susko3 commented 14 hours ago

Or you can just treat mouse ID 0 as your default mouse?

The documentation makes it very clear that 0 is an invalid SDL_MouseID, so using it is incorrect.

https://github.com/libsdl-org/SDL/blob/bdf16628fb664b32e24859ed4c5cec0df6204642/include/SDL3/SDL_mouse.h#L48

For fixing this bug, maybe SDL can reserve an ID for "unknown mouse" and use that instead of 0.

Sackzement commented 13 hours ago

Another reason why 0 shouldn't be the default mouse ID is that SDL_GetMice() claims to return a 0 terminated list of mouse IDs. https://github.com/libsdl-org/SDL/blob/6c10446a6cda1820fd19fa081ddb937aefd11060/include/SDL3/SDL_mouse.h#L158

Also: Other ID types use 0 as an invalid ID. Using it as a valid ID for mice, would be a minor but significant style break.

icculus commented 11 hours ago

Zero in the mouse event field seems like a reasonable way to say "this is mouse input but the system doesn't report different mice so we have no more information."

Susko3 commented 11 hours ago

Yeah but why overload SDL_MouseID 0 when you can easily add #define SDL_MOUSEID_UNKNOWN -3. (Well, it's not so easy when you give it a proper ID as you need to consider the mouse added events and whatnot.)

Having 0 be a valid mouse ID complicates applications since they cannot use 0 as "no mouse". See the your first-party woodeneye-008 example that bugs out when the mouse id is 0, as it assumes 0 is "no mouse" in application logic.

expikr commented 4 hours ago

Actually, WoodenEye 008 treats mousse id 0 as the "global fallback default mouse" (and keyboard id 0 as the global fallback keyboard) which means that you can always play in singleplayer mode as player 1 on emulated mouse/keyboard inputs (i.e. SendInput), until a concrete device id is detected and bound to player 1.

I think this is fundamentally a documentation issue. From what I understand, there doesn't really exist any notion of a "reserved ID indicating an invalid device" in SDL. The catch-all virtual mouse id 0 is perfectly valid, it just means that it's an emulated input, which is what you will always receive on platforms like emcripten.

since they cannot use 0 as "no mouse".

What do you mean? It seems perfectly reasonable to me that when there are no mice attached, you can only ever receive mice input from emulated injection. Conversely, even when you have mice attached, you can always still receive mice inputs from emulated source. Unless I'm missing something, the two concepts are wholly orthogonal to each other, I don't see any contradiction here?