banner
NEWS LETTER

Clawd on Desk 透明窗口渲染失败:从 D3D11 到 D3D9 的修复之旅

Scroll down

一个好的 AI 搭档,能帮你在黑暗里一块一块地拼出真相。

Clawd 桌面宠物

问题:宠物去哪了?

前段时间我装了两个桌面宠物 —— Clawd on Desk 和 EVE。EVE 一切正常,但 Clawd 启动后完全不显示。不是贴图错误,不是闪烁,是桌面上什么都没有,仿佛它从未存在过。

奇怪的是,它的进程跑得好好的(7 个进程,约 900MB 内存),Hook 事件也能正常上报,日志里没有任何报错。宠物会响应 Claude Code 的状态变化,但你就是看不到它。

第一轮:方向错了

我的第一个怀疑是 DeepSeek V4 模型。因为 Clawd 通过 Claude Code 的 Hook 系统工作,会不会是非 Anthropic 模型导致 Hook 数据异常,宠物状态机卡住了?

我把这个猜测告诉了 Claude Code,它直接指出:Hook 是 Claude Code 的基础设施层,跟模型提供商没有关系。 换个模型不会影响桌面应用的渲染。后来换 Theme 也无效,印证了这个判断。

接着我让 Claude Code 分析 Clawd 的 SVG 渲染通道。它翻出源码,发现 Clawd 支持两种 SVG 渲染:<img> 标签(默认)和 <object> 标签。它建议把 theme.json 里的 rendering.svgChannel 强制设为 "object" 试试。我还换了基于 APNG 的 calico 主题 —— 都没用

到这里我意识到:这不是应用层的问题,得往更深的地方挖。

第二轮:让 Claude Code 操刀 CDP 调试

Claude Code 提议启用 Chrome DevTools Protocol(CDP)远程调试,连上 Clawd 的 Electron 渲染进程。这一步是转折点。

它当场写了几段 Node.js 脚本,通过 WebSocket 连上 localhost:9222,直接操控渲染进程。

CDP 页面截图

Claude Code 调了 Page.captureScreenshot,拿到 Electron 页面内部的截图,然后写脚本逐像素分析:

  • 3587 个彩色像素,宠物形象完整渲染
  • DOM 树正常,SVG 图片加载成功,无任何 console 报错
  • window.innerWidthinnerHeight 都正确

页面内部一切正常。宠物确实在画,只是站在桌面上看不到它。

桌面级截图对比

Claude Code 接着截取桌面相同区域做像素级对比,分析结果:

  • 桌面截图中,对应区域只有背景壁纸的像素
  • 宠物窗口理应在的位置,DWM(桌面窗口管理器)没有合成任何内容

它就差直接把结论写我脸上了:Electron 渲染引擎画出了内容,但 Windows 的 DWM 拒绝把它合成到桌面上。

突破:D3D9 意外立功

走投无路之际,我抱着试试看的心态,让 Claude Code 搜一下有没有人遇到过类似的问题。它翻了不少资料后,建议尝试 --use-angle=d3d9 这个 Chromium 启动参数。

测试时出过一个小插曲:Claude Code 分析 D3D9 模式的桌面截图,发现只有 209 个彩色像素(占比 0.5%),它判断这是壁纸噪点,说”还是不行”。但我肉眼一看 —— 宠物明明就显示出来了! 它误判了,那 209 个像素正是小螃蟹的像素身形。

我告诉它”D3D9 其实可以正常显示”,它立刻反应过来,承认之前的像素分析阈值设错了。然后它顺着 D3D9 这条路往下挖,把根因完整拼了出来。

根因:D3D11 ANGLE 与透明窗口的死结

ANGLE 是什么?

Chromium 用 ANGLE(Almost Native Graphics Layer Engine)把 WebGL / Canvas 调用翻译成平台的 3D API。在 Windows 上,默认后端是 D3D11

我的系统环境

组件 详情
操作系统 Windows 11 Build 26200
主显卡 NVIDIA RTX 4060
核显 Intel UHD Graphics
虚拟适配器 GameViewer、Honor(各装了一个虚拟显示驱动)

为什么 D3D11 会失败?

Electron 的透明窗口依赖 DirectComposition —— Windows 的硬件合成引擎。正常情况下:

1
Electron 渲染 → ANGLE(D3D11) → D3D11 纹理 → DirectComposition → DWM 合成 → 桌面

但在多显卡 + 虚拟显示适配器的环境下,D3D11 与 DirectComposition 的纹理共享机制会出现静默失败。纹理数据存在,但 DWM 拿不到 —— 于是透明窗口变成了”完全透明”。

Claude Code 还注意到一个关键对比:EVE 宠物也是 Electron 写的,它正常。这说明问题不是”所有 Electron 透明窗口都会挂”,而是 Clawd 特定的渲染管线在这个环境下踩到了 D3D11 的坑

D3D9 为什么能行?

切换到 D3D9 后端后:

1
Electron 渲染 → ANGLE(D3D9) → D3D9 纹理 → DirectComposition → DWM 合成 → 桌面 ✅

D3D9 的纹理共享路径更老也更稳定,在复杂 GPU 拓扑下反而更兼容。

修复:一行参数的事

根因找到,Claude Code 帮我设计了永久方案。

临时验证

1
& "D:\Program Files (x86)\Clawd on Desk\Clawd on Desk.exe" --use-angle=d3d9

启动后,宠物立刻出现,所有状态切换正常。

永久方案

Claude Code 提出两步走:

1. 注册表自启动

1
2
HKCU\Software\Microsoft\Windows\CurrentVersion\Run
ClawdOnDesk = "D:\Program Files (x86)\Clawd on Desk\Clawd on Desk.exe" --use-angle=d3d9

2. 禁用内置自启

%APPDATA%\clawd-on-desk\clawd-prefs.json 中:

1
"openAtLogin": false

防止 Clawd 以无参数方式二次启动,导致又用回 D3D11。

Claude Code 还顺手清理了调试过程中产生的临时文件,把 theme.json 的无用改动也还原了,最后把排查经验写入项目的 CLAUDE.md 长期记忆中,防止以后再踩同一个坑。

复盘:三个收获

1. AI 搭档改变了排 Bug 的节奏。 以前遇到这种问题,我可能要搜半天资料、配半天环境。这次 Claude Code 直接写 CDP 调试脚本、分析像素数据、搜 Chromium issue —— 它干脏活,我做决策。D3D9 那次它误判了,但我说”这个能用”,它立刻调整方向继续推进。这种交互节奏很舒服。

2. CDP 是 Electron 调试的神器。 开启 --remote-debugging-port=9222 后,你就可以用 WebSocket 直接操控渲染进程。Claude Code 很擅长写这种胶水脚本,几行代码就能拿到关键证据。

3. 多显卡 + 虚拟适配器 = 隐形的坑。 GameViewer 和 Honor 的虚拟显示驱动在设备管理器里安安静静,但它们会干扰 ANGLE 的 GPU 选择逻辑。如果你也在用类似工具,遇到 Electron 渲染问题可以优先尝试 --use-angle=d3d9


最终,这只小螃蟹在桌面上活蹦乱跳了。而它的”隐形”能力,不过是 D3D11 在复杂 GPU 拓扑下一次静默的罢工 —— 以及一个 AI 搭档陪着我在黑暗中拼出来的真相。

其他文章