feat: 在交互窗口后重新激活先前的窗口#924
Conversation
close #923
for more information, see https://pre-commit.ci
对于 1 ? 对于 2 确实 windows only |
1.需要可被打断 |
你的意思是在调用 restore 的时候可能被其他程序打断也就是 e.g. 在同时手动把焦点转移到另一个程序上而 restore 又使其切回了原来的程序对吧 还有 windows only 心哪大了 |
for more information, see https://pre-commit.ci
那你if去哪了。 |
ChimeYao-bot
left a comment
There was a problem hiding this comment.
PR Review
该 PR 的目标是:在与交互窗口(小组件/浮窗)交互后,恢复前一个活动窗口至前台。整体思路合理,但有几个问题需要优化和修复(按严重性排序):
1. 致命问题:focus_manager 为 None 导致崩溃
-
问题:
main.py中多处使用QTimer.singleShot调用时,focus_manager可能尚未初始化,导致AttributeError。 -
建议:
- 在
lambda内加focus_manager存在性检查:if focus_manager: focus_manager.ignore.emit(...)。 - 或者提前初始化
focus_manager。
- 在
2. 资源泄漏:忽略集合无限增长
-
问题:
PreviousWindowFocusManager.ignore_hwnds使用set存储窗口句柄,但没有移除,导致句柄堆积。 -
建议:
- 在窗口销毁时移除句柄,或使用定时器延时移除:
QTimer.singleShot(2000, lambda h=hwnd: focus_manager.ignore_hwnds.discard(h))。
- 在窗口销毁时移除句柄,或使用定时器延时移除:
3. 跨平台兼容性问题
-
问题:
PreviousWindowFocusManager在非 Windows 系统上也被定义,可能导致维护问题。 -
建议:
- 将
PreviousWindowFocusManager的定义放入Windows平台判断内,或在初始化时抛出PlatformNotSupported错误。
- 将
4. 恢复焦点不稳定(Windows 限制)
-
问题:
win32gui.SetForegroundWindow在现代 Windows 系统中常受“前台窗口限制”影响,可能无法成功恢复焦点。 -
建议:
- 使用附加手段如
AttachThreadInput、ShowWindow/SetWindowPos,或模拟Alt+Tab来提高成功率。
- 使用附加手段如
5. 逻辑及可读性问题
- 问题:
_do_restore中的判断current_hwnd not in self.ignore_hwnds: return可能导致误解。 - 建议:添加注释,解释其意图:仅在当前前台窗口是需要忽略的窗口时,才尝试恢复焦点。
6. 性能问题:高频轮询
-
问题:
PreviousWindowFocusManager每 100ms 调用一次win32gui.GetForegroundWindow,对性能有影响。 -
建议:
- 使用 Windows 事件回调(如
SetWinEventHook)代替高频轮询,或仅在需要时启用定时器。
- 使用 Windows 事件回调(如
7. 信号一致性问题
- 问题:在某些地方使用
if focus_manager:检查,部分地方没有。 - 建议:统一在所有
ignore.emit和restoreRequested.emit前做存在性检查。
8. 代码风格及日志
- 问题:
_do_restore中的print应改为logger.error,便于排查。 - 建议:添加更多
logger.debug,记录ignore_hwnd的变化以及恢复焦点的成功与失败。
9. 其他
- 程序退出时,调用
focus_manager.stop()停止定时器,避免线程泄漏。
总结建议
- 修复:修正
singleShot中的lambda,提前检查focus_manager是否存在,或调整创建顺序。 - 优化:移除忽略集合中的无用句柄,并避免高频轮询,改用事件驱动。
- 兼容性:限制
PreviousWindowFocusManager仅在 Windows 平台使用,增加错误处理。
ChimeYao-bot
left a comment
There was a problem hiding this comment.
当前代码兼容性良好,非 Windows 平台不会报错。
推荐的兼容性做法
- 如需更保险,可在非 Windows 下赋值一个 Dummy 类(空类),即使误用也不会报错。
baiyao105
left a comment
There was a problem hiding this comment.
如果可以其实可以加到update_timer(存疑?
if system == 'Windows':
focus_manager = utils.PreviousWindowFocusManager()
update_timer.add_callback(focus_manager.store)
close #923