Release the operator cursor for cursor-clipping games
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>
This commit is contained in:
@@ -55,6 +55,13 @@ public:
|
||||
return block_->control.subsystem_disabled[subsystem].load(std::memory_order_acquire) == 0;
|
||||
}
|
||||
|
||||
// Whether the game is allowed to clip/position the cursor (false = release it,
|
||||
// the default). Drives the Focus subsystem's ClipCursor/SetCursorPos hooks.
|
||||
[[nodiscard]] bool cursor_clip_allowed() const
|
||||
{
|
||||
return block_ != nullptr && block_->control.allow_cursor_clip.load(std::memory_order_acquire) != 0;
|
||||
}
|
||||
|
||||
// Copies a torn-free snapshot of all slots. Returns false only if the host
|
||||
// was mid-write for the whole spin window (caller should reuse its cache).
|
||||
bool snapshot(CoopPadState (&out)[kMaxPads], std::uint32_t& count) const
|
||||
|
||||
Reference in New Issue
Block a user