Add window-based target picker as the default; process list goes advanced
New host/src/inject/window_list.{hpp,cpp} enumerates visible, titled, non-tool
top-level (alt-tab-style) windows via EnumWindows -- root-owner only, our own
process excluded -- and maps each to its owning pid + image name. The Injection
panel now defaults to this window list (each row "title [process.exe pid]", with a
filter over title or process), since there are far fewer windows than processes and
a window maps straight to the HWND the capturer wants. The full process list stays
as the advanced picker under Debug details.
Verified live: launched the host and captured its window -- the picker lists real
windows (Discord/Firefox/Explorer/...) in "title [exe pid]" form, filter present,
and the host's own window correctly excluded. x64 build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -84,7 +84,13 @@ std::wstring hook_dll_path()
|
||||
|
||||
InjectionPanel::InjectionPanel()
|
||||
{
|
||||
refresh_processes();
|
||||
refresh_targets();
|
||||
}
|
||||
|
||||
void InjectionPanel::refresh_targets()
|
||||
{
|
||||
windows_ = list_windows();
|
||||
processes_ = list_processes();
|
||||
}
|
||||
|
||||
InjectionPanel::~InjectionPanel()
|
||||
@@ -507,35 +513,64 @@ void InjectionPanel::draw(bool debug_details)
|
||||
ImGui::Separator();
|
||||
}
|
||||
|
||||
ImGui::TextUnformatted("Target process");
|
||||
ImGui::TextUnformatted("Target window");
|
||||
if (ImGui::Button("Refresh"))
|
||||
{
|
||||
refresh_processes();
|
||||
refresh_targets();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(-1.0f);
|
||||
ImGui::InputTextWithHint("##filter", "filter by name...", filter_, sizeof(filter_));
|
||||
ImGui::InputTextWithHint("##wfilter", "filter by title or process...", window_filter_, sizeof(window_filter_));
|
||||
|
||||
if (ImGui::BeginListBox("##processes", ImVec2(-1.0f, 200.0f)))
|
||||
if (ImGui::BeginListBox("##windows", ImVec2(-1.0f, 180.0f)))
|
||||
{
|
||||
for (const ProcessEntry& entry : processes_)
|
||||
for (const WindowEntry& w : windows_)
|
||||
{
|
||||
if (!contains_ci(entry.exe_name, filter_))
|
||||
if (!contains_ci(w.title, window_filter_) && !contains_ci(w.exe_name, window_filter_))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const bool selected = entry.pid == selected_pid_;
|
||||
char label[300];
|
||||
snprintf(label, sizeof(label), "%-40s %lu", narrow(entry.exe_name).c_str(), entry.pid);
|
||||
const bool selected = w.pid == selected_pid_;
|
||||
char label[400];
|
||||
snprintf(label, sizeof(label), "%-32s [%s %lu]", narrow(w.title).c_str(),
|
||||
narrow(w.exe_name).c_str(), w.pid);
|
||||
if (ImGui::Selectable(label, selected))
|
||||
{
|
||||
selected_pid_ = entry.pid;
|
||||
selected_name_ = entry.exe_name;
|
||||
selected_pid_ = w.pid;
|
||||
selected_name_ = w.exe_name;
|
||||
}
|
||||
}
|
||||
ImGui::EndListBox();
|
||||
}
|
||||
|
||||
// The full process list is the advanced fallback (e.g. a windowless game host),
|
||||
// kept out of the way unless the operator wants it.
|
||||
if (debug_details)
|
||||
{
|
||||
ImGui::SeparatorText("All processes (advanced)");
|
||||
ImGui::SetNextItemWidth(-1.0f);
|
||||
ImGui::InputTextWithHint("##filter", "filter by name...", filter_, sizeof(filter_));
|
||||
if (ImGui::BeginListBox("##processes", ImVec2(-1.0f, 160.0f)))
|
||||
{
|
||||
for (const ProcessEntry& entry : processes_)
|
||||
{
|
||||
if (!contains_ci(entry.exe_name, filter_))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const bool selected = entry.pid == selected_pid_;
|
||||
char label[300];
|
||||
snprintf(label, sizeof(label), "%-40s %lu", narrow(entry.exe_name).c_str(), entry.pid);
|
||||
if (ImGui::Selectable(label, selected))
|
||||
{
|
||||
selected_pid_ = entry.pid;
|
||||
selected_name_ = entry.exe_name;
|
||||
}
|
||||
}
|
||||
ImGui::EndListBox();
|
||||
}
|
||||
}
|
||||
|
||||
const bool can_inject = selected_pid_ != 0;
|
||||
ImGui::BeginDisabled(!can_inject);
|
||||
if (ImGui::Button("Inject & Connect", ImVec2(-1.0f, 0.0f)))
|
||||
|
||||
Reference in New Issue
Block a user