Games that ClipCursor / re-center via SetCursorPos while focused trap the operator's mouse (the focus spoof makes them think they're always focused), so the operator can't reach the overlay. The Focus subsystem now inline-hooks ClipCursor and SetCursorPos (stdcall trampolines): while "release" is requested it forces ClipCursor(NULL) and swallows the re-centering SetCursorPos; otherwise it passes them through. It frees any existing clip at install and re-frees each worker tick (covers one-time clippers and a runtime clip->release toggle). Host: protocol v10->v11 adds HookControl::allow_cursor_clip (0 = release, the default). The Injection panel gets a "Release operator cursor" checkbox and an F2 hotkey (InjectionPanel::toggle_cursor_release); default released, since the guest plays via the pad so the game's clip is operator-only. Verified: full build x64 + x86 clean; ctest x64 9/9, x86 3/3. The cursor behavior against a real clipping game (Trails through Daybreak) needs a live injected session to confirm; logic reviewed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
32 lines
1.3 KiB
C++
32 lines
1.3 KiB
C++
// Makes the injected game believe it always has foreground focus, so it keeps
|
|
// running and polling input while the tool's window holds the real OS focus
|
|
// (required for Steam RPT to capture the tool). Without this, games that pause
|
|
// or stop polling on focus loss are unusable in the final design.
|
|
#pragma once
|
|
|
|
#include "ipc_client.hpp"
|
|
|
|
namespace coop::hook
|
|
{
|
|
|
|
// Finds the game's main window, subclasses it to suppress deactivation messages,
|
|
// and hooks the focus-query APIs to always report the game as active. Returns
|
|
// true once spoofing is active; safe to retry until the window exists. Reports
|
|
// status through `ipc`.
|
|
bool install_focus_spoof(IpcClient& ipc);
|
|
|
|
// Reports how the game currently reads input (Raw Input gamepad usage + sink
|
|
// flag, DirectInput presence) so the host can identify a focus-gated path. Cheap
|
|
// to call each tick.
|
|
void update_input_diagnostics(IpcClient& ipc);
|
|
|
|
// While the focus subsystem is installed, free the operator's mouse each tick if the
|
|
// host requested cursor release (covers games that ClipCursor once rather than every
|
|
// frame, and a runtime toggle from clip -> release). No-op when clipping is allowed.
|
|
void release_cursor_tick();
|
|
|
|
// Restores the original window procedure and removes the focus API hooks.
|
|
void remove_focus_spoof();
|
|
|
|
} // namespace coop::hook
|