Hello!
Since switching to UE 5.1 and CommonUI we’ve been seeing an issue where some players would frequently get stuck on random screens while playing on Windows with a gamepad while others players have no issues at all. When the problem occurs gamepad input would still be active and the correct button widget would appear hovered/focused, but pressing the accept button on gamepad would just do nothing. Some combination of alt+tabbing, spamming directional input on gamepad, or just using mouse would then be needed to get unstuck.
I’ve been poking at this for years and think I finally have an idea of what’s going on - if Windows sends a bunch of WM_MOUSEMOVE events without the platform cursor having actually moved, Slate will switch back to using the platform cursor (see FSlateApplication::OnMouseMove) while CommonUI will continue using the faux internal cursor (see FCommonInputPreprocessor::HandleMouseMoveEvent). Pressing accept on gamepad will then cause a fake mouse click to be generated at the platform cursor’s position instead of the faux internal cursor’s position (see FAnalogCursor::HandleKeyDownEvent via FCommonAnalogCursor), which means we’re basically clicking on a random location on the screen until you actually do something to cause CommonUI to cycle the active input type from & back into Gamepad.
The reason this is happening for some players and not others is because external programs can cause spurious WM_MOUSEMOVE events to be generated even when the mouse hasn’t actually moved! Here’s some relevant linkage on that:
- Raymond Chen - Why do I get spurious WM_MOUSEMOVE messages?
- Raymond Chen - Sure, I can get spurious WM_MOUSEMOVE messages, but why do they keep streaming in?
- Raymond Chen - Why do I get a spurious WM_MOUSEMOVE message whenever Resource Manager is running?
This was briefly touched upon in [another [Content removed] but the suggested workaround of always forcing the faux cursor back on when gamepad input is received doesn’t fix our issue as it won’t move the faux cursor where it needs to be before the fake click event is sent. Instead I think we want to update FSlateApplication::OnMouseMove so it doesn’t ever use the faux cursor and specifically checks if the platform cursor moved before attempting to switch Slate back to using it (see attached diff).
Does this all make sense and seem like a reasonable fix? It seems to be working locally for me, but this is pretty low level so I wanted to confirm and see if you guys agree before moving forward with it.
Thanks!