Skip to content

[Bug] 子任务执行期间窗口频繁抢占焦点与闪烁 #17

Open

Description

@Zh1uyan

问题描述

在 oc-manager-v2 运行期间,当模型自动执行子任务时,界面会频繁抢占前台焦点,当前活动窗口被切走又切回,出现快速闪烁现象,干扰正常使用。

排查过程与实测数据

  1. 排除外部命令行终端窗口:
    • 实测排查表明,opencode serve --service 自身并无顶层可见/隐藏控制台窗口,亦无 cmd.exe / conhost.exe 等子进程。
    • launchTerminal 仅在用户手动点击“在终端中打开”时触发,与自动子任务无关。
  2. 确认焦点抢占源为 oc-manager 自身:
    • 通过前台窗口采样监控(50ms 采样周期),捕获到大量抢占前台焦点的事件,归属进程均为 oc-manager.exe(WebView2 顶层宿主窗口)。
  3. 根本原因定位:
    • 子任务执行期间,服务端通过 SSE 持续高频推送事件流。
    • frontend/dist/chat/sidepanel.js 中的 renderSubtaskPanel() 在原实现中每次被触发都会无条件执行 box.innerHTML = html 全量销毁并重建子任务列表 DOM。
    • 高频 DOM 全量重建导致界面剧烈重排与布局抖动,从而引致宿主窗口被系统反复激活置前。

修复方案建议

  1. 按稳定内容指纹跳过无效重建:
    • 在 renderSubtaskPanel() 中引入结构与状态指纹(对比 childSessionId / title / agent / model / status)。
    • 刻意排除每秒递增变化的 durationMs(避免缓存判定落空)。当列表结构与状态未发生实质变化时,跳过 DOM 重建。
  2. 运行时长解耦为独立秒表:
    • 运行中的子任务卡片添加 data-started-at 时间戳标记。
    • 通过 1 秒全局轻量定时器直接更新 textContent,无需重排 DOM 即可实时走秒。
  3. 状态清理同步重置:
    • 在 clearClientUI() 清空子任务面板 DOM 时,同步重置内容指纹缓存,避免状态失配。

Activity

  1. Mrsandman327 commented on Nov 5, 2026

    @Mrsandman327
    Owner

    当模型自动执行子任务时,界面会频繁抢占前台焦点 这个问题没有复现,你用的是哪个版本
    我基于最新opencode v2版本代码
    1、子任务面板确实存在全量重建,但没有那么高频,最多约 1.1 次/秒,不是每个 SSE 事件都重建。
    2、DOM 重排不会调用 SetForegroundWindow,元素更新去不会激活宿主窗口。

    工具全局快捷键 Shift+X 进行 window.Show() + window.Focus(),这个会激活窗口,是否与你的哪个工具冲突了

  2. Zh1uyan commented on Nov 5, 2026

    @Zh1uyan
    Author

    追更(2026-11-05):撤回我此前的根因结论,补实测证据与真根因

    一、接受你的两点纠正

    • 子任务面板重建约 1.1 次/秒(节流 900ms),措辞已修正;
    • DOM 重排不激活宿主窗口,原根因链撤回;前端「跳过重建」改动仅作性能优化保留(已含于你的 54f4810)。

    二、Shift+X 是独立真 bug(本地已修)

    • Wails v3 在 Windows 用 Win32 RegisterHotKey 实现 GlobalShortcut(系统级);Shift+X 等价「大写 X」,任意应用输入大写 X 都会触发主窗口隐藏/弹出并抢焦点;
    • 本地已改为 Ctrl+Shift+X;建议上游评估换默认组合或 opt-in。

    三、闪窗/抢焦点真根因:opencode v2 在 Windows 拉子进程未加隐藏窗口标志

    实测(WMI 进程创建事件 + 60ms 全量新可见顶层窗口枚举,交叉归因):

    • 子任务运行期间,可见 ConsoleWindowClass 窗口约每 5 秒成对闪灭,标题为 C:\Python314\python.exe、C:\Programs\Git\cmd\git.exe;
    • 其父进程 = tools\opencode.exe serve --service(opencode v2.2.5);
    • 对应命令:shell 工具的 python .trellis/scripts/get_context.py、git status --porcelain、pwsh -Command "python ./.trellis/scripts/task.py list",以及 snapshot 的 git.EXE --git-dir ...;
    • 机制:服务以 detached 无控制台运行,控制台子系统子进程(git/python/pwsh)未带 CREATE_NO_WINDOW/HideWindow,各自新建可见控制台 → 闪灭;实测这些新控制台会抢前台(子进程存活期间前台采样命中子 PID);
    • oc-manager 自身所有 spawn 均设 HideWindow(internal/executil),实测不闪,故与 manager 代码无关。

    建议上游修复(二选一):

    1. opencode 在 Windows 的所有子进程 spawn 点(shell 工具、snapshot git)统一加 HideWindow / CREATE_NO_WINDOW;
    2. 或给 daemon/serve 一个隐藏控制台,让子进程继承、不再新建窗口。

    四、临时缓解尝试(均失败,记录免得走弯路)

    • 默认终端改 Windows Terminal + launchMode:minimized —— 本机 WT 为非打包版(D:\Programz\terminal),DefTerm CLSID 未注册,委派不生效;
    • 控制台默认窗口位置移出屏幕(HKCU\Console WindowPosition)—— 视觉闪灭消失但抢前台依旧,且影响正常控制台启动,已回滚。
      → 本地无有效缓解,等上游修复。

    五、版本

    • oc-manager:上游 54f4810(2026-11-05)+ 本地 Ctrl+Shift+X;opencode v2.2.5;Wails v3.0.0-beta.28;Windows 11。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions