Injection panel UX: reachable auto re-attach + explain disabled controls

- The "Auto re-attach this game on relaunch" checkbox (and the Vulkan-layer
  checkbox) lived inside the connected-only block, so after a disconnect the
  control vanished while auto_reattach_ could stay enabled -- an active,
  invisible flag. Move both to render whenever a target is selected, connected or
  not, so they can be set up pre-launch and toggled off after disconnect.
- Explain why controls are greyed out: an inline hint under the subsystem toggles
  when no live game is connected, and a hover tooltip (AllowWhenDisabled) on the
  disabled "Inject & Connect" button telling the operator to pick a target.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-24 02:23:11 +02:00
parent e5668d9c48
commit 47be3fa53f
2 changed files with 39 additions and 33 deletions

View File

@@ -561,6 +561,10 @@ void InjectionPanel::draw_hook_status(bool debug_details)
ImGui::BeginDisabled(target_state_ != TargetState::Alive);
draw_subsystem_controls(status);
ImGui::EndDisabled();
if (target_state_ != TargetState::Alive)
{
ImGui::TextDisabled("(connect to a live game to change these)"); // why the toggles are locked
}
ImGui::TextDisabled("Controller poll rates are in the Controllers panel.");
draw_hook_list(status);
@@ -636,40 +640,41 @@ void InjectionPanel::draw(bool debug_details)
ImGui::SameLine();
ImGui::TextDisabled("(relaunched %s)", narrow(selected_name_).c_str());
}
// Session-only auto re-attach: tick it (while attached or terminated), then kill +
// relaunch the game and it re-injects itself early -- the kill+relaunch fix for a
// wrong audio format, without picking a target again.
if (!selected_name_.empty())
ImGui::Separator();
}
// Session options for the selected game, shown whether or not we're connected -- so they can be set
// up before launching the game, and an enabled auto re-attach is never hidden after a disconnect.
if (!selected_name_.empty())
{
// Session-only auto re-attach: tick it, then kill + relaunch the game and it re-injects itself
// early -- the kill+relaunch fix for a wrong audio format, without picking a target again.
ImGui::Checkbox("Auto re-attach this game on relaunch", &auto_reattach_);
if (auto_reattach_ && target_state_ == TargetState::Terminated)
{
ImGui::Checkbox("Auto re-attach this game on relaunch", &auto_reattach_);
if (auto_reattach_ && target_state_ == TargetState::Terminated)
ImGui::SameLine();
ImGui::TextColored(kGrey, "(watching for %s...)", narrow(selected_name_).c_str());
}
// Opt-in Vulkan capture layer: for Vulkan games that initialize Vulkan immediately (where even
// auto-attach injects too late -- see the red banner), register a per-user implicit layer scoped
// to this game so the next launch is captured from the first frame. Removed when unticked / exit.
if (ImGui::Checkbox("Set up Vulkan layer (for immediate-init Vulkan games)", &vk_layer_enabled_))
{
if (vk_layer_enabled_)
{
ImGui::SameLine();
ImGui::TextColored(kGrey, "(watching for %s...)", narrow(selected_name_).c_str());
vk_layer_enabled_ = register_vk_layer(selected_name_);
}
// Opt-in Vulkan capture layer: for Vulkan games that initialize Vulkan immediately
// (where even auto-attach injects too late -- see the red banner), register a per-user
// implicit layer scoped to this game so the next launch is captured from the first frame.
// Removed when unticked or the host exits.
if (ImGui::Checkbox("Set up Vulkan layer (for immediate-init Vulkan games)", &vk_layer_enabled_))
else
{
if (vk_layer_enabled_)
{
vk_layer_enabled_ = register_vk_layer(selected_name_);
}
else
{
unregister_vk_layer();
}
}
if (ImGui::IsItemHovered())
{
ImGui::SetTooltip("Registers a per-user (HKCU, no admin) implicit Vulkan layer scoped to\n"
"this game, so a relaunch is captured before Vulkan init. Pair with\n"
"Auto re-attach. Removed when you untick it or close the tool.");
unregister_vk_layer();
}
}
ImGui::Separator();
if (ImGui::IsItemHovered())
{
ImGui::SetTooltip("Registers a per-user (HKCU, no admin) implicit Vulkan layer scoped to\n"
"this game, so a relaunch is captured before Vulkan init. Pair with\n"
"Auto re-attach. Removed when you untick it or close the tool.");
}
}
ImGui::TextUnformatted("Target window");
@@ -737,6 +742,12 @@ void InjectionPanel::draw(bool debug_details)
inject_selected();
}
ImGui::EndDisabled();
// Explain the disabled state on hover (AllowWhenDisabled, since the button is greyed out).
if (!can_inject && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled))
{
ImGui::SetTooltip("Pick a target window or process above first.\n"
"If the game already has the DLL (e.g. after a reconnect), this reuses it.");
}
if (!status_.empty())
{