Conversation
There was a problem hiding this comment.
Hey - 我在这里给出了一些整体性的反馈:
- 可以考虑修改
send_activate(),让它返回解析后的目标HWND(或者通过其他方式共享它),这样在同一次操作中后续的调用(例如touch_*、input_text、key_*、scroll)就能使用同一个窗口,而不是每次都重新调用get_active_hwnd()。否则如果在操作过程中焦点发生变化,可能会导致一个手势/序列的不同部分发送到不同的窗口。 - 在
get_active_hwnd()中,可以考虑更明确地处理/记录GetAncestor(hwnd_, GA_ROOTOWNER)返回nullptr的情况,而不是直接回退到使用hwnd_。这样在存储的hwnd_失效时,会更容易诊断问题。
给 AI Agent 的提示
Please address the comments from this code review:
## Overall Comments
- Consider changing `send_activate()` to return the resolved target `HWND` (or otherwise share it) so that subsequent calls in the same operation (e.g., `touch_*`, `input_text`, `key_*`, `scroll`) use a consistent window rather than re-resolving `get_active_hwnd()` and potentially sending parts of a gesture/sequence to different windows if focus changes mid-flow.
- In `get_active_hwnd()`, it may be worth handling/logging the case where `GetAncestor(hwnd_, GA_ROOTOWNER)` returns `nullptr` more explicitly instead of falling back to `hwnd_`, to make it easier to diagnose issues when the stored `hwnd_` becomes invalid.帮我变得更有用!请对每条评论点 👍 或 👎,我会根据你的反馈改进后续的 Review。
Original comment in English
Hey - I've left some high level feedback:
- Consider changing
send_activate()to return the resolved targetHWND(or otherwise share it) so that subsequent calls in the same operation (e.g.,touch_*,input_text,key_*,scroll) use a consistent window rather than re-resolvingget_active_hwnd()and potentially sending parts of a gesture/sequence to different windows if focus changes mid-flow. - In
get_active_hwnd(), it may be worth handling/logging the case whereGetAncestor(hwnd_, GA_ROOTOWNER)returnsnullptrmore explicitly instead of falling back tohwnd_, to make it easier to diagnose issues when the storedhwnd_becomes invalid.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider changing `send_activate()` to return the resolved target `HWND` (or otherwise share it) so that subsequent calls in the same operation (e.g., `touch_*`, `input_text`, `key_*`, `scroll`) use a consistent window rather than re-resolving `get_active_hwnd()` and potentially sending parts of a gesture/sequence to different windows if focus changes mid-flow.
- In `get_active_hwnd()`, it may be worth handling/logging the case where `GetAncestor(hwnd_, GA_ROOTOWNER)` returns `nullptr` more explicitly instead of falling back to `hwnd_`, to make it easier to diagnose issues when the stored `hwnd_` becomes invalid.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Pull request overview
This PR updates the Win32 MessageInput path to target the active popup window (when present) instead of always sending input messages to the originally configured hwnd_, enabling correct clicking/typing behavior on modal/pop-up UI.
Changes:
- Route activation and input messages to
GetLastActivePopup(GetAncestor(hwnd_, GA_ROOTOWNER))when it’s visible. - Add coordinate remapping helper (
make_mouse_lparam) to translate(x,y)fromhwnd_client coordinates into the popup’s client coordinates. - Update
send_or_post_wto accept an explicit targetHWNDand update call sites accordingly.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| source/MaaWin32ControlUnit/Input/MessageInput.h | Updates helper declarations to support targeting active popup and mouse lParam remapping. |
| source/MaaWin32ControlUnit/Input/MessageInput.cpp | Implements active-popup targeting + coordinate translation and applies it across mouse/keyboard/scroll input flows. |
|
@sourcery-ai review |
There was a problem hiding this comment.
Hey - 我发现了 1 个问题,并给出了一些整体性的反馈:
- 在
touch_up中,send_activate()已经会调用send_activate_message,所以紧接着再显式调用一次send_activate_message(target, use_post)是多余的,应当移除以避免发送重复的激活消息。 - 当
touch_move中的send_or_post_w调用失败时,gesture_target_保持不变;建议在失败时清空或以其他方式处理gesture_target_,以避免后续手势继续使用已经失效的 HWND。
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `touch_up`, `send_activate()` already calls `send_activate_message`, so the additional explicit `send_activate_message(target, use_post)` right after is redundant and should be removed to avoid double activation messages.
- When `send_or_post_w` fails in `touch_move`, `gesture_target_` is left unchanged; consider clearing or otherwise handling `gesture_target_` on failure to avoid subsequent gestures using a stale HWND.
## Individual Comments
### Comment 1
<location path="source/MaaWin32ControlUnit/Input/MessageInput.cpp" line_range="132-141" />
<code_context>
+ return hwnd_;
+}
+
+LPARAM MessageInput::make_mouse_lparam(HWND target, int x, int y)
+{
+ if (target == hwnd_) {
+ return MAKELPARAM(x, y);
+ }
+ POINT pt = { x, y };
+ if (!ClientToScreen(hwnd_, &pt)) {
+ LogError << "ClientToScreen failed in make_mouse_lparam" << VAR(hwnd_) << VAR(GetLastError());
+ return MAKELPARAM(x, y);
+ }
+ if (!ScreenToClient(target, &pt)) {
+ LogError << "ScreenToClient failed in make_mouse_lparam" << VAR(target) << VAR(GetLastError());
+ return MAKELPARAM(x, y);
+ }
+ return MAKELPARAM(pt.x, pt.y);
+}
+
</code_context>
<issue_to_address>
**issue (bug_risk):** Failure paths in make_mouse_lparam may produce coordinates in the wrong space for the target window.
If either `ClientToScreen(hwnd_, &pt)` or `ScreenToClient(target, &pt)` fails, we log but still return `MAKELPARAM(x, y)`, which is in `hwnd_`’s client space while the message is sent to `target`. That means we may send mouse events with coordinates in the wrong space, potentially targeting the wrong location. Consider instead either:
- Returning coordinates in a known, consistent space (e.g., last successfully derived screen coords), or
- Explicitly signaling failure so the caller can avoid sending a message with invalid coordinates.
</issue_to_address>帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续的评审。
Original comment in English
Hey - I've found 1 issue, and left some high level feedback:
- In
touch_up,send_activate()already callssend_activate_message, so the additional explicitsend_activate_message(target, use_post)right after is redundant and should be removed to avoid double activation messages. - When
send_or_post_wfails intouch_move,gesture_target_is left unchanged; consider clearing or otherwise handlinggesture_target_on failure to avoid subsequent gestures using a stale HWND.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `touch_up`, `send_activate()` already calls `send_activate_message`, so the additional explicit `send_activate_message(target, use_post)` right after is redundant and should be removed to avoid double activation messages.
- When `send_or_post_w` fails in `touch_move`, `gesture_target_` is left unchanged; consider clearing or otherwise handling `gesture_target_` on failure to avoid subsequent gestures using a stale HWND.
## Individual Comments
### Comment 1
<location path="source/MaaWin32ControlUnit/Input/MessageInput.cpp" line_range="132-141" />
<code_context>
+ return hwnd_;
+}
+
+LPARAM MessageInput::make_mouse_lparam(HWND target, int x, int y)
+{
+ if (target == hwnd_) {
+ return MAKELPARAM(x, y);
+ }
+ POINT pt = { x, y };
+ if (!ClientToScreen(hwnd_, &pt)) {
+ LogError << "ClientToScreen failed in make_mouse_lparam" << VAR(hwnd_) << VAR(GetLastError());
+ return MAKELPARAM(x, y);
+ }
+ if (!ScreenToClient(target, &pt)) {
+ LogError << "ScreenToClient failed in make_mouse_lparam" << VAR(target) << VAR(GetLastError());
+ return MAKELPARAM(x, y);
+ }
+ return MAKELPARAM(pt.x, pt.y);
+}
+
</code_context>
<issue_to_address>
**issue (bug_risk):** Failure paths in make_mouse_lparam may produce coordinates in the wrong space for the target window.
If either `ClientToScreen(hwnd_, &pt)` or `ScreenToClient(target, &pt)` fails, we log but still return `MAKELPARAM(x, y)`, which is in `hwnd_`’s client space while the message is sent to `target`. That means we may send mouse events with coordinates in the wrong space, potentially targeting the wrong location. Consider instead either:
- Returning coordinates in a known, consistent space (e.g., last successfully derived screen coords), or
- Explicitly signaling failure so the caller can avoid sending a message with invalid coordinates.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| LPARAM MessageInput::make_mouse_lparam(HWND target, int x, int y) | ||
| { | ||
| if (target == hwnd_) { | ||
| return MAKELPARAM(x, y); | ||
| } | ||
| POINT pt = { x, y }; | ||
| if (!ClientToScreen(hwnd_, &pt)) { | ||
| LogError << "ClientToScreen failed in make_mouse_lparam" << VAR(hwnd_) << VAR(GetLastError()); | ||
| return MAKELPARAM(x, y); | ||
| } |
There was a problem hiding this comment.
issue (bug_risk): make_mouse_lparam 中的失败路径可能会为目标窗口生成处于错误坐标空间的坐标。
如果 ClientToScreen(hwnd_, &pt) 或 ScreenToClient(target, &pt) 任一调用失败,我们虽然会记录日志,但仍然返回 MAKELPARAM(x, y)。这对调用者来说是 hwnd_ 的客户区坐标,而消息却是发往 target 的。也就是说,我们可能会发送坐标空间错误的鼠标事件,从而点击到错误的位置。建议改为:
- 返回处于某个已知且一致坐标空间中的坐标(例如上一次成功计算出的屏幕坐标),或者
- 明确向调用方返回失败信号,以便调用方避免在坐标无效时继续发送消息。
Original comment in English
issue (bug_risk): Failure paths in make_mouse_lparam may produce coordinates in the wrong space for the target window.
If either ClientToScreen(hwnd_, &pt) or ScreenToClient(target, &pt) fails, we log but still return MAKELPARAM(x, y), which is in hwnd_’s client space while the message is sent to target. That means we may send mouse events with coordinates in the wrong space, potentially targeting the wrong location. Consider instead either:
- Returning coordinates in a known, consistent space (e.g., last successfully derived screen coords), or
- Explicitly signaling failure so the caller can avoid sending a message with invalid coordinates.
|
@sourcery-ai review |
There was a problem hiding this comment.
Hey - 我发现了 1 个问题
给 AI 代理的提示
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="source/MaaWin32ControlUnit/Input/MessageInput.cpp" line_range="132-141" />
<code_context>
+ return hwnd_;
+}
+
+LPARAM MessageInput::make_mouse_lparam(HWND target, int x, int y)
+{
+ if (target == hwnd_) {
+ return MAKELPARAM(x, y);
+ }
+ POINT pt = { x, y };
+ if (!ClientToScreen(hwnd_, &pt)) {
+ LogError << "ClientToScreen failed in make_mouse_lparam" << VAR(hwnd_) << VAR(GetLastError());
+ return MAKELPARAM(x, y);
+ }
+ if (!ScreenToClient(target, &pt)) {
+ LogError << "ScreenToClient failed in make_mouse_lparam" << VAR(target) << VAR(GetLastError());
+ return MAKELPARAM(x, y);
+ }
+ return MAKELPARAM(pt.x, pt.y);
+}
+
</code_context>
<issue_to_address>
**suggestion (bug_risk):** 在坐标转换失败时回退使用原坐标,可能会产生错误的鼠标位置。
如果 `ClientToScreen(hwnd_, &pt)` 或 `ScreenToClient(target, &pt)` 调用失败,我们会记录日志并回退到 `MAKELPARAM(x, y)`。但此时 `x`/`y` 仍然是 `hwnd_` 的客户区坐标,而不是 `target` 的坐标,因此生成的 lParam 对目标窗口来说是不正确的。可以考虑改为返回一个哨兵值(例如 `0`),让调用方中止操作,或者返回处于一个明确约定的、当前最可靠的坐标空间中的坐标(例如屏幕坐标),而不是具有误导性的、被当成 `target` 客户区坐标来使用的值。
建议的实现:
```cpp
LPARAM MessageInput::make_mouse_lparam(HWND target, int x, int y)
{
if (target == hwnd_) {
return MAKELPARAM(x, y);
}
POINT pt = { x, y };
if (!ClientToScreen(hwnd_, &pt)) {
LogError << "ClientToScreen failed in make_mouse_lparam" << VAR(hwnd_) << VAR(GetLastError());
// Return sentinel to signal failure so callers can abort sending an incorrect lParam.
return 0;
}
if (!ScreenToClient(target, &pt)) {
LogError << "ScreenToClient failed in make_mouse_lparam" << VAR(target) << VAR(GetLastError());
// Return sentinel to signal failure so callers can abort sending an incorrect lParam.
return 0;
}
return MAKELPARAM(pt.x, pt.y);
}
```
`MessageInput::make_mouse_lparam` 的调用方应作如下更新:
1. 检查返回的 `LPARAM` 值;
2. 如果值为 `0`,则将其视为坐标转换失败,并且**不要**发送鼠标消息(或采取在你们代码库中适合的回退/中止行为)。
</issue_to_address>帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续评审。
Original comment in English
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="source/MaaWin32ControlUnit/Input/MessageInput.cpp" line_range="132-141" />
<code_context>
+ return hwnd_;
+}
+
+LPARAM MessageInput::make_mouse_lparam(HWND target, int x, int y)
+{
+ if (target == hwnd_) {
+ return MAKELPARAM(x, y);
+ }
+ POINT pt = { x, y };
+ if (!ClientToScreen(hwnd_, &pt)) {
+ LogError << "ClientToScreen failed in make_mouse_lparam" << VAR(hwnd_) << VAR(GetLastError());
+ return MAKELPARAM(x, y);
+ }
+ if (!ScreenToClient(target, &pt)) {
+ LogError << "ScreenToClient failed in make_mouse_lparam" << VAR(target) << VAR(GetLastError());
+ return MAKELPARAM(x, y);
+ }
+ return MAKELPARAM(pt.x, pt.y);
+}
+
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Coordinate fallback on conversion failure may produce incorrect mouse positions.
If `ClientToScreen(hwnd_, &pt)` or `ScreenToClient(target, &pt)` fails, we log and fall back to `MAKELPARAM(x, y)`. But at that point `x`/`y` are still client coords for `hwnd_`, not for `target`, so the resulting lParam is incorrect for the target window. Consider instead either returning a sentinel (e.g. `0`) so callers can abort, or returning coordinates in a clearly-defined, best-known space (e.g. screen) rather than misleading client coords for `target`.
Suggested implementation:
```cpp
LPARAM MessageInput::make_mouse_lparam(HWND target, int x, int y)
{
if (target == hwnd_) {
return MAKELPARAM(x, y);
}
POINT pt = { x, y };
if (!ClientToScreen(hwnd_, &pt)) {
LogError << "ClientToScreen failed in make_mouse_lparam" << VAR(hwnd_) << VAR(GetLastError());
// Return sentinel to signal failure so callers can abort sending an incorrect lParam.
return 0;
}
if (!ScreenToClient(target, &pt)) {
LogError << "ScreenToClient failed in make_mouse_lparam" << VAR(target) << VAR(GetLastError());
// Return sentinel to signal failure so callers can abort sending an incorrect lParam.
return 0;
}
return MAKELPARAM(pt.x, pt.y);
}
```
Callers of `MessageInput::make_mouse_lparam` should be updated to:
1. Check the returned `LPARAM` value.
2. If it is `0`, treat that as a failure to convert coordinates and **do not** send the mouse message (or take whatever fallback/abort behavior is appropriate for your codebase).
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Summary by Sourcery
将 Win32 输入消息路由到当前活动的弹出窗口,而不是始终发送到根窗口,并在手势整个持续期间,将触摸手势始终绑定到同一个弹出窗口上。
Enhancements:
LPARAM。MessageInput中增加最小状态,用于在触摸交互期间记录手势的目标窗口。Original summary in English
Summary by Sourcery
Route Win32 input messages to the currently active popup window instead of always targeting the root window, and keep touch gestures consistently bound to a single popup for their duration.
Enhancements:
增强内容:
Original summary in English
Summary by Sourcery
将 Win32 输入消息路由到当前活动的弹出窗口,而不是始终发送到根窗口,并在手势整个持续期间,将触摸手势始终绑定到同一个弹出窗口上。
Enhancements:
LPARAM。MessageInput中增加最小状态,用于在触摸交互期间记录手势的目标窗口。Original summary in English
Summary by Sourcery
Route Win32 input messages to the currently active popup window instead of always targeting the root window, and keep touch gestures consistently bound to a single popup for their duration.
Enhancements:
增强内容:
LPARAM的辅助函数,并重构输入路径,使其在消息分发时接受显式的HWND目标。Original summary in English
Summary by Sourcery
将 Win32 输入消息路由到当前活动的弹出窗口,而不是始终发送到根窗口,并在手势整个持续期间,将触摸手势始终绑定到同一个弹出窗口上。
Enhancements:
LPARAM。MessageInput中增加最小状态,用于在触摸交互期间记录手势的目标窗口。Original summary in English
Summary by Sourcery
Route Win32 input messages to the currently active popup window instead of always targeting the root window, and keep touch gestures consistently bound to a single popup for their duration.
Enhancements:
增强内容:
Original summary in English
Summary by Sourcery
将 Win32 输入消息路由到当前活动的弹出窗口,而不是始终发送到根窗口,并在手势整个持续期间,将触摸手势始终绑定到同一个弹出窗口上。
Enhancements:
LPARAM。MessageInput中增加最小状态,用于在触摸交互期间记录手势的目标窗口。Original summary in English
Summary by Sourcery
Route Win32 input messages to the currently active popup window instead of always targeting the root window, and keep touch gestures consistently bound to a single popup for their duration.
Enhancements: