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:
@@ -86,17 +86,16 @@ int run()
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Steam Input is the plan's primary guest-input path (it falls back to XInput
|
||||
// per slot, and to pure XInput if Steam isn't available). When the host is built
|
||||
// without the Steamworks SDK, use XInput directly.
|
||||
// XInput is the default guest-input path: Remote Play Together delivers guest
|
||||
// pads as XInput, and it Just Works. Steam Input is opt-in (Controllers panel) --
|
||||
// merely initializing it activates Steam's in-process XInput interception, which
|
||||
// hides controllers from XInput unless they're bound to our action set for this
|
||||
// app, so making it the default can silently break input. We switch the active
|
||||
// backend at runtime to match the toggle.
|
||||
coop::XInputSource xinput;
|
||||
coop::InputSource* input = &xinput;
|
||||
#ifdef COOP_WITH_STEAM
|
||||
std::unique_ptr<coop::InputSource> input = [] {
|
||||
auto steam = std::make_unique<coop::SteamInputSource>();
|
||||
steam->init(steam_manifest_path());
|
||||
return steam;
|
||||
}();
|
||||
#else
|
||||
std::unique_ptr<coop::InputSource> input = std::make_unique<coop::XInputSource>();
|
||||
std::unique_ptr<coop::SteamInputSource> steam;
|
||||
#endif
|
||||
coop::ControllersPanel controllers;
|
||||
coop::InjectionPanel injection;
|
||||
@@ -119,6 +118,31 @@ int run()
|
||||
|
||||
while (window.pump_messages())
|
||||
{
|
||||
#ifdef COOP_WITH_STEAM
|
||||
// Switch the active input backend to match the Controllers-panel toggle.
|
||||
const bool want_steam = controllers.steam_input_requested();
|
||||
if (want_steam && steam == nullptr)
|
||||
{
|
||||
steam = std::make_unique<coop::SteamInputSource>();
|
||||
if (steam->init(steam_manifest_path()))
|
||||
{
|
||||
input = steam.get();
|
||||
controllers.set_steam_active(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
steam.reset();
|
||||
controllers.on_steam_init_failed();
|
||||
}
|
||||
}
|
||||
else if (!want_steam && steam != nullptr)
|
||||
{
|
||||
steam->shutdown();
|
||||
steam.reset();
|
||||
input = &xinput;
|
||||
controllers.set_steam_active(false);
|
||||
}
|
||||
#endif
|
||||
input->poll();
|
||||
injection.publish(input->pads());
|
||||
const HWND game = injection.game_hwnd();
|
||||
|
||||
Reference in New Issue
Block a user