Skip to content

feat: ensure_window_on_screen#1170

Merged
MistEO merged 2 commits intomainfrom
feat/ensure_window_on_screen
Mar 3, 2026
Merged

feat: ensure_window_on_screen#1170
MistEO merged 2 commits intomainfrom
feat/ensure_window_on_screen

Conversation

@MistEO
Copy link
Member

@MistEO MistEO commented Mar 3, 2026

fix MaaEnd/MaaEnd#922

Summary by Sourcery

在执行屏幕捕获操作之前,确保被捕获窗口在屏幕上完全可见,以避免客户端区域位于屏幕外。

Bug Fixes:

  • 当目标窗口部分或完全位于屏幕外时,通过在捕获前将其重新定位并在显示器范围内调整大小,防止窗口捕获问题。

Enhancements:

  • 新增一个实用工具,用于验证并调整窗口的客户端区域,使其完全适配到最近的显示器内,并在发生调整时记录相关日志。
Original summary in English

Summary by Sourcery

Ensure captured windows are fully visible on screen before performing screencap operations to avoid off-screen client areas.

Bug Fixes:

  • Prevent window capture issues when the target window is partially or fully off-screen by repositioning and resizing it within monitor bounds before capture.

Enhancements:

  • Add a utility to validate and adjust a window's client area to fit entirely within the nearest monitor, logging adjustments when applied.

Copilot AI review requested due to automatic review settings March 3, 2026 03:19
Copy link
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 - 我发现了两个问题,并给出了一些整体性的反馈:

  • 建议使用 mi.rcWork 而不是 mi.rcMonitor,这样 ensure_window_on_screen 就能保证客户端区域保持在可用桌面区域内,避免把内容移动到任务栏或其他保留区域下面。
  • 由于 ensure_window_on_screen 会在每次截图时调用,可以考虑在更昂贵的 client/frame 计算之前做短路判断(例如先检查当前窗口/客户端矩形是否已经位于显示器边界内),以减少在常见场景下多余的 WinAPI 调用。
给 AI Agent 的提示词
Please address the comments from this code review:

## Overall Comments
- Consider using `mi.rcWork` instead of `mi.rcMonitor` so that `ensure_window_on_screen` keeps the client area within the usable desktop region and avoids moving content under the taskbar or other reserved areas.
- Since `ensure_window_on_screen` is called on every screencap, you could short‑circuit before the more expensive client/frame calculations (e.g., first check if the current window/client rect already lies within the monitor bounds) to reduce redundant WinAPI calls in the common case.

## Individual Comments

### Comment 1
<location path="source/MaaWin32ControlUnit/Screencap/HwndUtils.hpp" line_range="82-84" />
<code_context>
+        return false;
+    }
+
+    RECT monitor_rect = mi.rcMonitor;
+    int monitor_w = monitor_rect.right - monitor_rect.left;
+    int monitor_h = monitor_rect.bottom - monitor_rect.top;
</code_context>
<issue_to_address>
**suggestion (bug_risk):** 使用 rcMonitor 而不是 rcWork 可能会把客户端区域放到任务栏或其他保留区域下面。

如果目标是让客户端区域对用户保持可见,这里更合理的做法是使用 `mi.rcWork`,从而遵守任务栏和其他保留区域。如果你确实希望允许内容位于任务栏下方,请在文档中明确说明这一点,并确认下游使用方可以接受可能被遮挡的区域。

```suggestion
    // Use the monitor work area so the client remains visible and is not placed
    // under the taskbar or other reserved areas.
    RECT monitor_rect = mi.rcWork;
    int monitor_w = monitor_rect.right - monitor_rect.left;
    int monitor_h = monitor_rect.bottom - monitor_rect.top;
```
</issue_to_address>

### Comment 2
<location path="source/MaaWin32ControlUnit/Screencap/HwndUtils.hpp" line_range="159-160" />
<code_context>
+    int new_window_w = new_client_w + frame_left + frame_right;
+    int new_window_h = new_client_h + frame_top + frame_bottom;
+
+    LogInfo << "Moving/resizing window to keep client area on screen" << VAR(new_window_x) << VAR(new_window_y)
+            << VAR(new_window_w) << VAR(new_window_h);
+
</code_context>
<issue_to_address>
**suggestion:** 在 info 级别记录每一次移动/缩放,对于频繁的截图调用来说可能会导致日志噪声过大。

由于这段代码会在每次截图前运行,在高捕获频率或窗口经常移动的情况下,这条日志可能会产生大量噪声。建议将日志级别降低(例如 debug/trace),或者只在计算出的矩形相较上一次有明显变化时再进行记录,以保持日志的实用性。

```suggestion
    LogDebug << "Moving/resizing window to keep client area on screen" << VAR(new_window_x) << VAR(new_window_y)
             << VAR(new_window_w) << VAR(new_window_h);
```
</issue_to_address>

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

Hey - I've found 2 issues, and left some high level feedback:

  • Consider using mi.rcWork instead of mi.rcMonitor so that ensure_window_on_screen keeps the client area within the usable desktop region and avoids moving content under the taskbar or other reserved areas.
  • Since ensure_window_on_screen is called on every screencap, you could short‑circuit before the more expensive client/frame calculations (e.g., first check if the current window/client rect already lies within the monitor bounds) to reduce redundant WinAPI calls in the common case.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider using `mi.rcWork` instead of `mi.rcMonitor` so that `ensure_window_on_screen` keeps the client area within the usable desktop region and avoids moving content under the taskbar or other reserved areas.
- Since `ensure_window_on_screen` is called on every screencap, you could short‑circuit before the more expensive client/frame calculations (e.g., first check if the current window/client rect already lies within the monitor bounds) to reduce redundant WinAPI calls in the common case.

## Individual Comments

### Comment 1
<location path="source/MaaWin32ControlUnit/Screencap/HwndUtils.hpp" line_range="82-84" />
<code_context>
+        return false;
+    }
+
+    RECT monitor_rect = mi.rcMonitor;
+    int monitor_w = monitor_rect.right - monitor_rect.left;
+    int monitor_h = monitor_rect.bottom - monitor_rect.top;
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Using rcMonitor instead of rcWork may place the client under taskbars or reserved areas.

If the goal is to keep the client visible to the user, this should likely use `mi.rcWork` so it respects the taskbar and other reserved areas. If you do intend to allow content under the taskbar, please document that explicitly and verify that downstream consumers are OK with potentially obscured regions.

```suggestion
    // Use the monitor work area so the client remains visible and is not placed
    // under the taskbar or other reserved areas.
    RECT monitor_rect = mi.rcWork;
    int monitor_w = monitor_rect.right - monitor_rect.left;
    int monitor_h = monitor_rect.bottom - monitor_rect.top;
```
</issue_to_address>

### Comment 2
<location path="source/MaaWin32ControlUnit/Screencap/HwndUtils.hpp" line_range="159-160" />
<code_context>
+    int new_window_w = new_client_w + frame_left + frame_right;
+    int new_window_h = new_client_h + frame_top + frame_bottom;
+
+    LogInfo << "Moving/resizing window to keep client area on screen" << VAR(new_window_x) << VAR(new_window_y)
+            << VAR(new_window_w) << VAR(new_window_h);
+
</code_context>
<issue_to_address>
**suggestion:** Logging every move/resize at info level may be noisy for frequent screencap calls.

Because this runs before every screencap, this log may generate excessive noise, especially at high capture rates or when the window frequently moves. Consider lowering the level (e.g., debug/trace) or only logging when the computed rect meaningfully changes from the last value to keep logs useful.

```suggestion
    LogDebug << "Moving/resizing window to keep client area on screen" << VAR(new_window_x) << VAR(new_window_y)
             << VAR(new_window_w) << VAR(new_window_h);
```
</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.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses MaaEnd#922 by proactively repositioning/resizing a target window so its client area remains within the current monitor bounds before performing certain Win32 screencap operations.

Changes:

  • Added ensure_window_on_screen(HWND) utility to keep a window’s client area fully within the active monitor.
  • Invoked this utility before capturing in ScreenDCScreencap and DesktopDupWindowScreencap.
  • Added logging around adjustment attempts/failures.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
source/MaaWin32ControlUnit/Screencap/ScreenDCScreencap.cpp Calls ensure_window_on_screen() before screen-DC based capture.
source/MaaWin32ControlUnit/Screencap/HwndUtils.hpp Introduces ensure_window_on_screen() helper (move/resize + logging).
source/MaaWin32ControlUnit/Screencap/DesktopDupWindowScreencap.cpp Calls ensure_window_on_screen() before desktop-dup + window crop capture.

@MistEO
Copy link
Member Author

MistEO commented Mar 3, 2026

简单测了下没啥问题

@MistEO MistEO merged commit a0f559f into main Mar 3, 2026
19 checks passed
@MistEO MistEO deleted the feat/ensure_window_on_screen branch March 3, 2026 05:26
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.

游戏窗口化时无法使用前台模式

2 participants