SDL
SDL copied to clipboard
separate `SDL_RawMotionEvent` to receive raw mouse delta
Motivation
Currently, SDL_MouseMotionEvent
has to couple multiple streams of unrelated platform features to the SDL-specific state machine:
- synchronization of raw events to emulate SDL's internal cursor position
- synchronization of cursor events to emulate SDL's relative cursor motion
- synchronization of platform cursor visibility to SDL's RelativeMode state machine
- synchronization of platform cursor confinement to SDL's RelativeMode state machine
this design decision is motivated by the need to present an always-available jack-of-all-trades interface: if you make it favor one specific use case then you compromise its usability for others.
We can sidestep the issue via a separation of design concerns approach: keep the simple-to-use interface as the always-available fallback, and additionally provide a cross-platform optional interface that can reasonably be expected to be not always available.
Proposal
First, the default (fallback) behavior on platforms which do not have raw mouse inputs should simply be that no such events are generated. This is reasonable because this is a specialized interface that does not hamper basic functionality when absent.
Second, the interface should be completely stateless -- that it, it only forwards state-changes from the platform, there should be no notion of modifying SDL's internal states, nor should said states affect them.
Third, the new raw event should be emitted in parallel to the current general-purpose mouse events, meaning that this is simply a independent optional channel that the developer can choose to ignore.
Finally, there must be a hint that enables the underlying platform subscription separately from the current general-purpose mouse events. Enabling or disabling the functionality should not influence the RelativeMode state machine, nor should the RelativeMode state machine affect the availability.
Original Proposal
Use Case
I do not want to use a laggy software-cursor, but I still need to be able to receive raw unscaled mouse deltas.
Currently SDL just sends the manually calculated cursor delta in non-relative mode instead of the true device delta, which is a big problem because it means that I do not receive deltas when the cursor reaches the edge of the game window.
Proposal
An idea is to leave SDL_MouseMotionEvent as-is and add two new events: SDL_RawMotionEvent and SDL_CursorMotionEvent, both of which are always sent regardless of relative mode status
The x and y positions of both should use the result of GetMessagePos function rather than manually calculating it, to remove the whole class of "first move discrepancy" bugs.
The dx and dy of CursorMotion should be calculated by the difference between the posted xy position and the GetMessagePos xy position, rather than using some janky internal cache of the last known position. For RawMotion it should just report the deltas directly.
@slouken I've refactored this issue to be a more actionable cross-platform proposal, in light of other issues expressing similar use cases and sentiments regarding the lack of an escape hatch.
This seems like a reasonable proposal to me, want to put together a PR for it?