Skip to content

feat: 添加强制激活游戏窗口设置 - #2502

Open
Usagi-wusaqi wants to merge 6 commits into
OneDragon-Anything:mainfrom
Usagi-wusaqi:feat/window
Open

feat: 添加强制激活游戏窗口设置#2502
Usagi-wusaqi wants to merge 6 commits into
OneDragon-Anything:mainfrom
Usagi-wusaqi:feat/window

Conversation

@Usagi-wusaqi

@Usagi-wusaqi Usagi-wusaqi commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

close #2490

image
项目 借鉴的内容 当前一条龙实现 差异与结论
窗口恢复顺序 WM_SYSCOMMAND + SC_RESTORE 顺序相同 保持一致
前台激活 SetForegroundWindow 相同 保持一致
窗口置顶 BringWindowToTop 相同 保持一致
设置活动窗口 SetActiveWindow 相同 保持一致
失焦重试 任务级每秒持续重试,直到恢复 仅截图失焦保护触发,每秒重试,最多 30 次 一条龙有界退出,避免无限卡住;覆盖范围较窄
多次失败处理 第 10 次后最小化其他窗口 累计失败 10 次后进入最小化兜底,最多重试 30 次 兜底思路一致,但一条龙有重试上限
最小化其他窗口 Shell_TrayWnd + WM_COMMAND 419 相同命令 保持一致
最小化消息发送 同步 SendMessage 异步 PostMessage 一条龙避免跨进程同步阻塞
失焦检测 检查前台窗口所属进程 比较 GetForegroundWindow() 与游戏 HWND 一条龙判断更精确
最小化等待 while IsIconic 忙等 最多等待 10 次,每次 50ms 一条龙避免 CPU 空转
最小化后恢复 依赖恢复流程 额外调用 ShowWindow(SW_RESTORE) 兜底 一条龙恢复路径更完整
成功判定 外层循环再次检查进程 每次尝试后约 50ms 检查真实 HWND 一条龙反馈更直接
激活异常 P/Invoke 返回值基本忽略 捕获异常后继续尝试其他激活步骤 一条龙异常处理更完整
无效句柄 主要依赖调用失败 清理缓存并重新查找窗口 一条龙更适合游戏重启
成功日志 没有明确成功日志 输出“游戏窗口已恢复前台焦点” 一条龙更易排查
检查触发点 多个任务控制和等待入口 截图失焦时调用 ensure_active_window();其它显式 active_window() 只做一次激活 一条龙触发范围更窄,但启动副作用更小
后台模式 不主动抢前台 焦点保护不抢前台 保持一致;显式键鼠模式切换仍可能短暂切前台
系统前台硬锁 无法突破 无法突破 两者相同
取消/超时 激活循环可能无限等待 没有外部取消令牌,但单次最多 30 次后返回失败 一条龙避免无限等待,但单次调用期间不能即时取消
总体评价 任务级监管更广 HWND 判定更精确、消息更不易阻塞、重试有界,触发范围更收敛 两者取舍不同,不宜简单评价为谁全面优于谁

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

新增

  • 新增“强制激活游戏窗口”配置开关。
  • 新增运行时窗口失焦恢复、激活重试和最小化其他窗口的兜底处理。
  • 新增窗口句柄有效性检查和失效句柄重新查找机制。

变更

  • 配置变更后自动重新初始化控制器。
  • 更新前台窗口激活、截图前窗口校验和窗口区域获取流程。
  • 扩展 PcControllerBaseZPcController 接口,传递强制激活配置。
  • 更新后台模式设计文档,补充前台焦点恢复及相关控制器方案。

Walkthrough

新增 force_active_window 配置和设置开关,并将其传递至 PC 控制器。启用后,截图前检查窗口焦点,必要时通过 Win32 API 重试激活游戏窗口。同时更新窗口缓存处理和后台模式设计文档。

Changes

强制激活游戏窗口

Layer / File(s) Summary
配置属性与设置开关
src/one_dragon/envs/env_config.py, src/one_dragon_qt/view/setting/setting_env_interface.py
新增 force_active_window 配置属性及设置开关,并在界面显示时加载配置值。
控制器参数传递
src/zzz_od/context/zzz_context.py, src/zzz_od/controller/zzz_pc_controller.py, src/one_dragon/base/controller/pc_controller_base.py
将环境配置传递至控制器,保存配置,并区分单次激活与持续重试。
截图前窗口激活流程
src/one_dragon/base/controller/pc_controller_base.py, src/one_dragon/base/controller/pc_game_window.py
截图前检查窗口状态,通过 Win32 API 恢复、置前并验证前台状态,处理失效句柄和窗口矩形重试。
后台模式设计文档
docs/develop/one_dragon/background_mode_design.md
更新后台模式、焦点恢复、控制器接口、输入映射和安装说明。

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SettingEnvInterface
  participant EnvConfig
  participant ZContext
  participant ZPcController
  participant PcControllerBase
  participant PcGameWindow
  SettingEnvInterface->>EnvConfig: 保存 force_active_window
  ZContext->>ZPcController: 传递 force_active_window
  ZPcController->>PcControllerBase: 转发配置
  PcControllerBase->>PcGameWindow: 检查并激活游戏窗口
  PcGameWindow-->>PcControllerBase: 返回激活结果
  PcControllerBase->>PcGameWindow: 激活成功后继续截图
Loading

Suggested reviewers: shadowlemoon

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning 核心代码与 issue #2490 相关,但设计文档同时扩展了 gamepad_key、动作数量和安装方式等无关主题。 拆分或移除与窗口强制激活无关的文档修改,仅保留窗口焦点恢复及其配置说明。
Docstring Coverage ⚠️ Warning Docstring coverage is 64.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed 标题明确概括了新增强制激活游戏窗口设置这一主要变更,与代码和关联 issue 一致。
Description check ✅ Passed 描述围绕窗口恢复流程、重试机制、失败兜底和实现差异展开,与 PR 变更直接相关。
Linked Issues check ✅ Passed 代码新增配置、失焦检测、窗口激活重试及失败兜底,满足 issue #2490 关于恢复非前台游戏窗口的主要要求。
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ShadowLemoon ShadowLemoon left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

这个pr不能解决issue的问题,任务栏橙色是激活失败,怎么调用active_window都没用的

@Usagi-wusaqi
Usagi-wusaqi marked this pull request as draft July 17, 2026 04:29

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/one_dragon_qt/view/setting/setting_env_interface.py (1)

77-83: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

为新增成员补充类型注解

src/**/*.py 要求所有类成员变量都显式声明类型;请将该成员改为:

-        self.force_active_window_switch = SwitchSettingCard(
+        self.force_active_window_switch: SwitchSettingCard = SwitchSettingCard(

依据项目规范,类成员变量必须使用类型注解。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/one_dragon_qt/view/setting/setting_env_interface.py` around lines 77 -
83, 为 SettingEnvInterface 中新增的 force_active_window_switch 成员添加显式类型注解,使用其实际创建的
SwitchSettingCard 类型;保持现有初始化、信号连接和 basic_group.addSettingCard 调用不变。

Sources: Coding guidelines, Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/one_dragon/base/controller/pc_game_window.py`:
- Around line 154-192:
将_minimize_other_windows和_focus_window中的win32gui.SendMessage调用替换为win32gui.PostMessage,保持现有消息参数、等待逻辑、窗口状态检查及异常处理不变。

---

Nitpick comments:
In `@src/one_dragon_qt/view/setting/setting_env_interface.py`:
- Around line 77-83: 为 SettingEnvInterface 中新增的 force_active_window_switch
成员添加显式类型注解,使用其实际创建的 SwitchSettingCard 类型;保持现有初始化、信号连接和
basic_group.addSettingCard 调用不变。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e9158549-3cb5-4972-b574-b45c25685eff

📥 Commits

Reviewing files that changed from the base of the PR and between 2ccf052 and 2e239ab.

📒 Files selected for processing (3)
  • src/one_dragon/base/controller/pc_controller_base.py
  • src/one_dragon/base/controller/pc_game_window.py
  • src/one_dragon_qt/view/setting/setting_env_interface.py

Comment thread src/one_dragon/base/controller/pc_game_window.py Outdated
@Usagi-wusaqi
Usagi-wusaqi marked this pull request as ready for review July 17, 2026 06:04

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/one_dragon/base/controller/pc_game_window.py (1)

113-144: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

为强制激活设置最大重试次数或截止时间。

当窗口始终有效但 Windows 持续拒绝前台切换时,当前循环永不返回,导致 Line 158 的失败处理无法执行,并可能再次让日常任务挂起数小时。请在多次重试后返回 False,由调用方安全停止本轮操作。

建议修复
         attempt = 0
-        while self.is_win_valid:
+        max_attempts = 30 if retry_until_active else 1
+        while self.is_win_valid and attempt < max_attempts:
             ...
             attempt += 1
             time.sleep(1)

+        if self.is_win_valid:
+            log.error('多次尝试后仍无法激活游戏窗口')
+            return False
         log.error('游戏窗口已失效,无法恢复前台焦点')
         return False
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/one_dragon/base/controller/pc_game_window.py` around lines 113 - 144, 为
active 方法增加强制激活的最大重试次数或截止时间,确保 retry_until_active 为 true 且 Windows
持续拒绝前台切换时最终退出循环并返回 False。保留成功激活时的立即返回及窗口失效处理,并让现有重试流程在达到限制后执行失败日志和安全返回。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/one_dragon/base/controller/pc_game_window.py`:
- Around line 113-144: 为 active 方法增加强制激活的最大重试次数或截止时间,确保 retry_until_active 为
true 且 Windows 持续拒绝前台切换时最终退出循环并返回
False。保留成功激活时的立即返回及窗口失效处理,并让现有重试流程在达到限制后执行失败日志和安全返回。

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b42ffec7-0ac3-4b35-ac69-5534654e6449

📥 Commits

Reviewing files that changed from the base of the PR and between 2e239ab and ae5ef86.

📒 Files selected for processing (4)
  • deploy/module_manifest.py
  • src/one_dragon/base/controller/pc_controller_base.py
  • src/one_dragon/base/controller/pc_game_window.py
  • src/one_dragon_qt/view/setting/setting_env_interface.py
💤 Files with no reviewable changes (1)
  • deploy/module_manifest.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/one_dragon_qt/view/setting/setting_env_interface.py

@ShadowLemoon

Copy link
Copy Markdown
Collaborator

这种橙色的感觉一般是启动的时候就没到前台过;按我的经验,到过前台的游戏切换到前台不会失败

@Usagi-wusaqi

Copy link
Copy Markdown
Collaborator Author

这种橙色的感觉一般是启动的时候就没到前台过;按我的经验,到过前台的游戏切换到前台不会失败

正常情况下,可以直接激活曾经处于过前台,但是不小心切到后台的窗口

但如果,打开一条龙并配置好游戏路径时,按下F9,趁绝区零游戏窗口还没有打开,立即疯狂点击切换到其他不相关的应用窗口,绝区零的窗口不会在前台出现,
这就能复现绝区零任务栏图标闪橙光的问题,无法激活其窗口,此时如果持续无法激活窗口,那就可以最小化任务栏里的所有窗口,这样就能激活(参考的实现)

@ShadowLemoon

Copy link
Copy Markdown
Collaborator

所以实际上这是两个问题
1.启动的时候多余操作导致游戏变橙
2.运行的时候多余操作切走,恢复窗口前台
所以我认为解决方案不该把两个都收归为“强制激活、如果失败则最小化其他”

@Usagi-wusaqi

Usagi-wusaqi commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator Author

BetterGI 明确区分:
启动时的一次性激活:只为让游戏接收输入,应尽量少打扰;
运行中失焦恢复:避免截图或点击作用到其他窗口;
多次恢复失败后的兜底:最小化其他窗口,副作用较大,只应最后使用。

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/one_dragon_qt/view/setting/setting_env_interface.py`:
- Around line 77-80: 为 SettingEnvInterface 中的实例成员变量
self.force_active_window_switch 添加明确的 SwitchSettingCard 类型注解,并保留现有的初始化逻辑和配置内容不变。

In `@src/one_dragon/base/controller/pc_game_window.py`:
- Line 17: 为类成员变量 MAX_ACTIVE_ATTEMPTS 添加 int 类型注解,保持其现有值 30 和其他行为不变。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b9101565-29a1-45d8-a681-a2ae4a04abb4

📥 Commits

Reviewing files that changed from the base of the PR and between ae52a4d and e279ff2.

📒 Files selected for processing (4)
  • docs/develop/one_dragon/background_mode_design.md
  • src/one_dragon/base/controller/pc_controller_base.py
  • src/one_dragon/base/controller/pc_game_window.py
  • src/one_dragon_qt/view/setting/setting_env_interface.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/one_dragon/base/controller/pc_controller_base.py
  • docs/develop/one_dragon/background_mode_design.md

Comment thread src/one_dragon_qt/view/setting/setting_env_interface.py
Comment thread src/one_dragon/base/controller/pc_game_window.py
@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Reviews resumed.

1 similar comment
@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Reviews resumed.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/one_dragon_qt/view/setting/setting_env_interface.py (1)

95-95: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

为修改的设置卡成员补充类型注解。

self.repository_url_optself.cpython_source_optself.pip_source_opt 是类成员,但当前声明没有类型注解。请分别声明为 ComboBoxSettingCard

建议的修复
-        self.repository_url_opt = ComboBoxSettingCard(
+        self.repository_url_opt: ComboBoxSettingCard = ComboBoxSettingCard(

-        self.cpython_source_opt = ComboBoxSettingCard(
+        self.cpython_source_opt: ComboBoxSettingCard = ComboBoxSettingCard(

-        self.pip_source_opt = ComboBoxSettingCard(
+        self.pip_source_opt: ComboBoxSettingCard = ComboBoxSettingCard(

As per coding guidelines,src/**/*.py 要求“所有函数签名和类成员变量必须有类型注解”。

Also applies to: 121-121, 132-132

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/one_dragon_qt/view/setting/setting_env_interface.py` at line 95,
为设置界面类中的成员变量 self.repository_url_opt、self.cpython_source_opt 和
self.pip_source_opt 补充 ComboBoxSettingCard 类型注解,保持现有初始化逻辑不变。

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/develop/one_dragon/background_mode_design.md`:
- Around line 319-323: Remove the unresolved Git conflict markers around the
control_method entry and keep one description consistent with the actual
GameConfig.get_action_keys(control_method) signature, including whether the
argument is explicitly required. Verify the documentation build succeeds after
resolving the section.

---

Outside diff comments:
In `@src/one_dragon_qt/view/setting/setting_env_interface.py`:
- Line 95: 为设置界面类中的成员变量 self.repository_url_opt、self.cpython_source_opt 和
self.pip_source_opt 补充 ComboBoxSettingCard 类型注解,保持现有初始化逻辑不变。
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5d6e1e99-a325-4559-a2e0-05e97d9ce718

📥 Commits

Reviewing files that changed from the base of the PR and between b3e90c9 and cbe206e.

📒 Files selected for processing (5)
  • deploy/module_manifest.py
  • docs/develop/one_dragon/background_mode_design.md
  • src/one_dragon/base/controller/pc_controller_base.py
  • src/one_dragon/envs/env_config.py
  • src/one_dragon_qt/view/setting/setting_env_interface.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • deploy/module_manifest.py
  • src/one_dragon/base/controller/pc_controller_base.py

Comment thread docs/develop/one_dragon/background_mode_design.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/develop/one_dragon/background_mode_design.md`:
- Around line 204-205: 更新文档中 enable_background_mode() 在架构说明及对应描述处,将仅支持 Xbox
改为支持所选手柄(Xbox/DS4),以与 get_gamepad_action_keys('ds4') 及现有动作映射保持一致;同时检查
btn_controller 列表是否为完整控制器列表,若是则加入 ds4_controller。
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ad33028c-adb4-4fe9-8cf4-933549ba2be6

📥 Commits

Reviewing files that changed from the base of the PR and between cbe206e and 7f9078b.

📒 Files selected for processing (1)
  • docs/develop/one_dragon/background_mode_design.md

Comment thread docs/develop/one_dragon/background_mode_design.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants