Fix input forwarding: default to XInput, make Steam Input opt-in

Making Steam Input the default backend silently broke input forwarding. Merely
initializing Steam Input activates Steam's in-process XInput interception, which
hides controllers from XInputGetState unless they're bound to our action set for
the running appid. With no such binding (the normal case for a donor appid) Steam
Input reports zero controllers AND XInput now sees nothing -> no input at all.

Reproduced with coop_steam_input_probe: without Steam, XInput slot 0 is seen;
with Steam Input initialized, 0 Steam controllers and the XInput fallback goes
empty.

Default to XInput (RPT delivers guest pads there and it works) and make Steam
Input an opt-in Controllers-panel toggle that switches the backend at runtime;
turning it off restores XInput. All 6 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-20 14:25:43 +02:00
parent 24d66020f6
commit 914dba4d25
4 changed files with 90 additions and 21 deletions

View File

@@ -75,6 +75,21 @@ void ControllersPanel::draw(const InputSource& input, const HookStatusView& stat
ImGui::TextDisabled("This window is what Remote Play Together captures.");
ImGui::TextDisabled("F1: hide overlay (clean mirror) Esc: quit");
#ifdef COOP_WITH_STEAM
ImGui::Checkbox("Use Steam Input (experimental)", &steam_requested_);
if (steam_requested_)
{
ImGui::SameLine();
ImGui::TextColored(steam_active_ ? kGreen : kGrey, steam_active_ ? "(active)" : "(starting...)");
ImGui::TextDisabled("Needs a controller bound to Steam Input for this app; otherwise");
ImGui::TextDisabled("XInput is hidden and no input arrives. Leave off for plain XInput.");
}
if (steam_note_[0] != '\0')
{
ImGui::TextColored(kGrey, "%s", steam_note_);
}
#endif
// --- Guest pads the host receives from RPT -----------------------------
ImGui::SeparatorText("Incoming (host receives)");
const auto& pads = input.pads();