Skip to content

Commit 722e33a

Browse files
ZeroAd-06Z_06claudesisyphus-dev-ai
authored
feat(win32): 添加鼠标锁定跟随模式,支持后台 TPS/FPS 视角控制 (#1232)
Co-authored-by: Z_06 <z060606060606@gmail.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
1 parent 8e669eb commit 722e33a

16 files changed

Lines changed: 719 additions & 25 deletions

File tree

docs/en_us/2.4-ControlMethods.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ Different programs on Win32 handle input differently, so there is no universal m
9898
> - Admin privileges mainly depend on the target program's permission level. If the target program runs as administrator, running with admin privileges is required for compatibility.
9999
> - The `WithCursorPos` methods briefly move the cursor to the target position, then restore it after sending the message, hence "Brief" cursor seizure, but it does not block user operations.
100100
> - The `WithWindowPos` methods briefly move the window so the target position aligns with the current cursor position, then restore the window position after sending the message. The cursor is not moved, so there is no mouse seizure, but the window may briefly flicker.
101+
> - Win32 also provides a **Mouse Lock Follow** mode: enable with `MaaControllerSetOption(ctrl, MaaCtrlOption_MouseLockFollow, &enabled, sizeof(bool))` (set `enabled` to `true` to enable, `false` to disable). Designed for TPS/FPS games that lock the mouse to the window in the background. When enabled, the window continuously follows the mouse cursor, and RawInput counter-moves prevent the game from sensing hardware mouse movement. Use `MaaControllerPostRelativeMove` to inject intentional camera rotation while this mode is active. **Note:** On Win32, `MaaControllerPostRelativeMove` requires mouse-lock-follow mode to be active; calling it without this mode will fail. Only supported with MessageInput-based input methods (SendMessage / PostMessage variants).
101102
102103
### Win32 Screencap
103104

docs/zh_cn/2.4-控制方式说明.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ Win32 下不同程序处理输入的方法不同,不存在一个通用方式
9898
> - 管理员权限主要取决于目标程序的权限级别,若目标程序为管理员权限,则需以管理员权限运行以保证兼容性。
9999
> - `WithCursorPos` 系列方式会短暂移动光标到目标位置,发送完消息后会将光标移回原位置,因此会“短暂”抢占鼠标,但不会阻止用户操作。
100100
> - `WithWindowPos` 系列方式会短暂移动窗口,使目标位置与当前光标位置重合,发送完消息后会将窗口移回原位置。不会移动光标,因此不抢占鼠标,但窗口会短暂闪烁。
101+
> - Win32 还提供了**鼠标锁定跟随模式**(Mouse Lock Follow):通过 `MaaControllerSetOption(ctrl, MaaCtrlOption_MouseLockFollow, &enabled, sizeof(bool))` 开启(`enabled``true` 开启,`false` 关闭),适用于 TPS/FPS 等在后台将鼠标锁定到窗口内的游戏。开启后窗口会始终跟随鼠标移动,同时通过 RawInput 对冲阻止游戏感知硬件鼠标位移。配合 `MaaControllerPostRelativeMove` 可在此模式下注入视角旋转。**注意:** Win32 平台的 `MaaControllerPostRelativeMove` 需要先开启鼠标锁定跟随模式,否则调用将失败。仅支持 MessageInput 系列输入方式(SendMessage / PostMessage 及其变体)。
101102
102103
### Win32 Screencap
103104

include/MaaControlUnit/ControlUnitAPI.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ class Win32ControlUnitAPI
9999
{
100100
public:
101101
virtual ~Win32ControlUnitAPI() = default;
102+
103+
virtual bool set_mouse_lock_follow(bool /*enabled*/) { return false; }
102104
};
103105

104106
class MacOSControlUnitAPI

include/MaaFramework/MaaDef.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,13 @@ enum MaaCtrlOptionEnum
210210
/// value: bool, eg: true; val_size: sizeof(bool)
211211
MaaCtrlOption_ScreenshotUseRawSize = 3,
212212

213+
/// Enable or disable mouse-lock-follow mode for Win32 controllers.
214+
/// This is designed for TPS/FPS games that lock the mouse to their window in the background.
215+
/// Only valid for Win32 controllers using message-based input methods.
216+
///
217+
/// value: bool, eg: true; val_size: sizeof(bool)
218+
MaaCtrlOption_MouseLockFollow = 4,
219+
213220
// Deprecated
214221
// Dump all screenshots and actions
215222
//

source/MaaFramework/Controller/ControllerAgent.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ bool ControllerAgent::set_option(MaaCtrlOption key, MaaOptionValue value, MaaOpt
4141
return set_image_target_short_side(value, val_size);
4242
case MaaCtrlOption_ScreenshotUseRawSize:
4343
return set_image_use_raw_size(value, val_size);
44+
case MaaCtrlOption_MouseLockFollow:
45+
return set_mouse_lock_follow_option(value, val_size);
4446

4547
default:
4648
LogError << "Unknown key" << VAR(key) << VAR(value);
@@ -1201,4 +1203,28 @@ bool ControllerAgent::set_image_use_raw_size(MaaOptionValue value, MaaOptionValu
12011203
return true;
12021204
}
12031205

1206+
bool ControllerAgent::set_mouse_lock_follow_option(MaaOptionValue value, MaaOptionValueSize val_size)
1207+
{
1208+
LogDebug;
1209+
1210+
if (val_size != sizeof(bool)) {
1211+
LogError << "invalid value size: " << val_size;
1212+
return false;
1213+
}
1214+
1215+
if (!control_unit_) {
1216+
LogError << "control_unit_ is nullptr";
1217+
return false;
1218+
}
1219+
1220+
auto win32_unit = std::dynamic_pointer_cast<MAA_CTRL_UNIT_NS::Win32ControlUnitAPI>(control_unit_);
1221+
if (!win32_unit) {
1222+
LogError << "Mouse lock follow is only supported for Win32 controllers.";
1223+
return false;
1224+
}
1225+
1226+
bool enabled = *reinterpret_cast<bool*>(value);
1227+
return win32_unit->set_mouse_lock_follow(enabled);
1228+
}
1229+
12041230
MAA_CTRL_NS_END

source/MaaFramework/Controller/ControllerAgent.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ class ControllerAgent : public MaaController
288288
bool set_image_target_long_side(MaaOptionValue value, MaaOptionValueSize val_size);
289289
bool set_image_target_short_side(MaaOptionValue value, MaaOptionValueSize val_size);
290290
bool set_image_use_raw_size(MaaOptionValue value, MaaOptionValueSize val_size);
291+
bool set_mouse_lock_follow_option(MaaOptionValue value, MaaOptionValueSize val_size);
291292

292293
private:
293294
bool need_to_stop_ = false;

0 commit comments

Comments
 (0)