Skip to content

fix(Win32-Input): 支持系统鼠标左右键互换设置#1330

Open
laoyijiehe wants to merge 3 commits into
MaaXYZ:mainfrom
laoyijiehe:fix/win32-swap-mouse-buttons
Open

fix(Win32-Input): 支持系统鼠标左右键互换设置#1330
laoyijiehe wants to merge 3 commits into
MaaXYZ:mainfrom
laoyijiehe:fix/win32-swap-mouse-buttons

Conversation

@laoyijiehe
Copy link
Copy Markdown

@laoyijiehe laoyijiehe commented May 12, 2026

问题描述

MaaFramework v5.10.4 Win32 输入层将 contact=0/1 直接硬编码为左/右键消息或 SendInput 标志,未读取系统 SM_SWAPBUTTON 设置。

Windows 开启「左右键互换」后:

  • Win32-Front(SeizeInput)点击失效
  • Win32-Window-Background(MessageInput with_window_pos)点击失效

修复方案

InputUtils.h 中统一做逻辑主键/副键 remap:

  • 添加 IsMouseButtonSwapped() 读取 GetSystemMetrics(SM_SWAPBUTTON)
  • 添加 GetMappedContact() 使用异或 ^1 实现 0↔1 互换
  • 修改所有 contact_to_xxx 函数,使用映射后的按键
  • MessageInput 和 SeizeInput 自动获得左右键互换支持

修改的文件

  • source/MaaWin32ControlUnit/Input/InputUtils.h

关联 Issue

Fixes #1323

说明

此 PR 替代已关闭的旧 PR(#1329)。

Summary by Sourcery

在 Win32 输入工具中添加对 Windows 系统“鼠标主次按钮交换”设置的支持,使逻辑接触点能够遵从用户的左右键配置。

Bug Fixes:

  • 确保在 Windows 配置为交换鼠标左键和右键时,SeizeInputMessageInput 能够正确处理点击事件。

Enhancements:

  • 通过一个辅助工具集中管理“鼠标接触点到按键”的映射,并根据系统的交换设置对逻辑接触点进行重新映射。
Original summary in English

Summary by Sourcery

Add support for Windows system mouse button swap settings in the Win32 input utilities so logical contacts respect the user’s left/right button configuration.

Bug Fixes:

  • Ensure SeizeInput and MessageInput correctly handle clicks when Windows is configured to swap left and right mouse buttons.

Enhancements:

  • Centralize mouse contact-to-button mapping through a helper that remaps logical contacts based on the system swap setting.

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - 我发现了 1 个问题,并给出了一些整体层面的反馈:

  • IsMouseButtonSwapped() 中缓存 GetSystemMetrics(SM_SWAPBUTTON) 的结果,会导致运行时更改系统鼠标按键设置时无法被检测到;建议要么每次都查询,要么在接收到 WM_SETTINGCHANGE 时增加一个刷新该值的机制。
  • GetMappedContact 对任意 original_contact 都直接应用 ^ 1,这会改变超出 0/1 范围的值;如果这里只允许 0/1,有必要通过断言或限制范围来明确这一点,或者在文档中显式说明这个假设。
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Caching the result of `GetSystemMetrics(SM_SWAPBUTTON)` in `IsMouseButtonSwapped()` means changes to the system mouse button setting at runtime won’t be picked up; consider either querying each time or adding a mechanism to refresh this value on `WM_SETTINGCHANGE`.
- `GetMappedContact` blindly applies `^ 1` to any `original_contact`, which will change values beyond 0/1; if only 0/1 are valid here, it would be clearer to assert or clamp the range, or document this assumption explicitly.

## Individual Comments

### Comment 1
<location path="source/MaaWin32ControlUnit/Input/InputUtils.h" line_range="66-68" />
<code_context>
+}
+
+// 获取兼容鼠标左右按键交换后的鼠标按键映射
+inline int GetMappedContact(int original_contact)
+{
+    if (IsMouseButtonSwapped()) {
+        // 左右键交换后,左键为1,右键为0,异或取反输出即可
+        return original_contact ^ 1;
</code_context>
<issue_to_address>
**issue (bug_risk):** 基于异或的映射会错误地重新映射非左右键的按键(例如中键/X 键)。

`original_contact ^ 1` 只有在 `original_contact` 被保证仅为 0 或 1 时才是正确的。按当前对 0–4 这些 contact 的处理方式,它还会把 2↔3、4↔5 等也翻转,从而在交换左右键时改变中键和 X 键的行为。相反,应当只交换 0 和 1,并保持其它所有 contact 不变,例如:

```cpp
inline int GetMappedContact(int original_contact)
{
    if (!IsMouseButtonSwapped()) {
        return original_contact;
    }
    if (original_contact == 0) return 1;
    if (original_contact == 1) return 0;
    return original_contact;
}
```
</issue_to_address>

Sourcery 对开源项目是免费的——如果你觉得我们的 Review 有帮助,欢迎分享 ✨
帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续的 Review。
Original comment in English

Hey - I've found 1 issue, and left some high level feedback:

  • Caching the result of GetSystemMetrics(SM_SWAPBUTTON) in IsMouseButtonSwapped() means changes to the system mouse button setting at runtime won’t be picked up; consider either querying each time or adding a mechanism to refresh this value on WM_SETTINGCHANGE.
  • GetMappedContact blindly applies ^ 1 to any original_contact, which will change values beyond 0/1; if only 0/1 are valid here, it would be clearer to assert or clamp the range, or document this assumption explicitly.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Caching the result of `GetSystemMetrics(SM_SWAPBUTTON)` in `IsMouseButtonSwapped()` means changes to the system mouse button setting at runtime won’t be picked up; consider either querying each time or adding a mechanism to refresh this value on `WM_SETTINGCHANGE`.
- `GetMappedContact` blindly applies `^ 1` to any `original_contact`, which will change values beyond 0/1; if only 0/1 are valid here, it would be clearer to assert or clamp the range, or document this assumption explicitly.

## Individual Comments

### Comment 1
<location path="source/MaaWin32ControlUnit/Input/InputUtils.h" line_range="66-68" />
<code_context>
+}
+
+// 获取兼容鼠标左右按键交换后的鼠标按键映射
+inline int GetMappedContact(int original_contact)
+{
+    if (IsMouseButtonSwapped()) {
+        // 左右键交换后,左键为1,右键为0,异或取反输出即可
+        return original_contact ^ 1;
</code_context>
<issue_to_address>
**issue (bug_risk):** XOR-based mapping will incorrectly remap non-left/right contacts (e.g., middle/X buttons).

`original_contact ^ 1` only works if `original_contact` is guaranteed to be 0 or 1. With the current handling of contacts 0–4, it will also remap 2↔3, 4↔5, etc., changing the behavior of middle/X buttons when swapping. Instead, only swap 0 and 1 and leave all other contacts unchanged, for example:

```cpp
inline int GetMappedContact(int original_contact)
{
    if (!IsMouseButtonSwapped()) {
        return original_contact;
    }
    if (original_contact == 0) return 1;
    if (original_contact == 1) return 0;
    return original_contact;
}
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread source/MaaWin32ControlUnit/Input/InputUtils.h Outdated
Copy link
Copy Markdown
Member

@MistEO MistEO left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 感谢修 #1323!不过 GetMappedContactoriginal_contact ^ 1 会把中键(2)/侧键(3/4) 也一起翻转。建议仅在 swapped 时 if (c==0) return 1; if (c==1) return 0; 其余原样返回。另外 IsMouseButtonSwapped 不要 static 缓存到死,至少每次调 GetSystemMetrics。修完这俩我再看一眼

@laoyijiehe laoyijiehe force-pushed the fix/win32-swap-mouse-buttons branch from 5c24347 to 2ead700 Compare May 18, 2026 06:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Win32 input 未适配 Windows 左右键互换(SM_SWAPBUTTON)

2 participants