X11: cache raw mouse valuators by source device to fix "mouse stuck in middle" - #16259
X11: cache raw mouse valuators by source device to fix "mouse stuck in middle"#16259edmundselliot wants to merge 1 commit into
Conversation
|
Hi - this issue was affecting cs2 mouse tracking, where in game the mouse could effectively get stuck in the middle of the screen (seems like a common issue others are hitting according to ValveSoftware/csgo-osx-linux#4354), fixed by restarting the game and "getting lucky". I debugged it using an AI tool, but I reviewed the debug/code change, and the fix makes sense. Because the bad classification is cached during startup, the initial input sequence can vary, so this only reproduced about ~25% of the time for me. With the fix I started my game O(20) times and it worked every time! |
|
Seems pretty much the same issue as #12968 |
|
@Kontrabant @icculus @slouken please let me know there's anything else I should do for this fix, haven't contributed here before so not sure of the process 😄 |
|
This fix is strange. It's applying the relative pointer slave device valuator mappings to events from the master device. If this fixes things, then there is a mismatch and the master pointer is incorrectly reporting relative axes as absolute. Why is this happening though? |
|
Yeah, this is the part that confused me too. In the failing case, XI_RawMotion is delivered as deviceid=2, sourceid=7. Device 2 reports its X/Y valuators as absolute, while source 7 (xwayland-relative-pointer) reports them as relative. But the raw values in those events behave as relative deltas, not absolute coordinates. I verified this by tracing the XI2 values before SDL processes them. When SDL uses device 2’s absolute classification, parse_relative_valuators() subtracts consecutive raw values and the resulting SDL motion is exactly delta-of-delta. Using source 7’s relative classification passes those same values through unchanged and fixes the motion. So I agree there seems to be a mismatch between the master device’s advertised valuator classes and the semantics of these raw events. I’m not yet sure whether that’s expected XI2/XWayland behavior? |
|
I dug into the XWayland/XI2 side, and I think this explains why the master can report absolute axes here. XWayland creates two slave devices attached to the same master: xwayland-pointer with absolute X/Y valuators, and xwayland-relative-pointer with relative X/Y valuators. Relative-pointer motion is queued on the latter using POINTER_RAWONLY. The master’s device classes can change when the active slave changes. The server copies the active slave’s classes to the master and sends an XI_DeviceChanged event with SlaveSwitch. So the master can have absolute classes after the absolute XWayland slave was active, while a later XI_RawMotion event contains raw values from the relative slave. SDL currently caches the device info by deviceid, so those master classes can stick around after the source changes. That can make SDL interpret the raw values incorrectly. I think the issue is that the master’s classes are being treated as stable, even though they can change depending on which slave was active. |
Description
Use the raw event's
sourceidwhen querying and caching its XInput2 valuator metadata. An XWayland master pointer can deliver events from both an absolute pointer source and a relative pointer source. Caching metadata by the shared masterdeviceidlets the relative source inherit an absolute-axis classification. SDL then subtracts consecutive values that are already relative movements, reversing mouse-look movement as the user slows the mouse.The source-specific lookup gives each source its own axis classification and previous-coordinate state. This remains a candidate correction pending maintainer review and multi-day gameplay testing.
Validation
Observed in a running native CS2 session on GNOME Wayland using the SDL X11 backend:
deviceid=2,sourceid=7; source 7 advertised relative X/Y axes.relative[0]=0andrelative[1]=0.An isolated helper loaded the game's original SDL library with the dummy video backend, reconstructed the observed master-absolute/source-relative cache state, and fed synthetic raw events through its compiled X11 handler. A source-equivalent, one-byte local binary correction was assembled and tested against the exact same library:
Existing Issue(s)
Related to #16163. The live branch trace confirms the absolute-conversion path requested in that issue; the exact first-event ordering on this machine was not captured.