Files
navop/docs
胡飞 5c19d51a2b fix(one-core): 弹窗关闭一律只隐藏、不销毁,红点这条路也不再交给 AppKit
真机反馈:0.19.2-touchbar-kvo-noop 上「确定」不再闪退,但点原生红点仍然闪退。
也就是说变量不是「有没有守卫」,而是**谁发起的销毁** —— 我们自己那条
(`remove_window()` + GPUI 延迟回收)已经安全,AppKit 在自己的关闭流程里那条还是会崩。

既然差别就在「谁销毁」,那就把「销毁弹窗」这件事整个拿掉:

- `popup_window.rs`:新增 `PARKED_POPUPS`(窗口 id → 内容实体),没有复用键的一次性弹窗
  也登记;`reusable_popup_content` 收敛为 `popup_content`(复用登记 + 停放两处查询),
  `is_reusable_popup` → `is_popup_window`,`end_reusable_popup_session` → `end_popup_session`,
  `forget_reusable_popup_by_window` → `forget_popup_by_window`(两类登记都按 window_id 清理)。
- `window_close.rs`:`close_window_for_reuse` 对弹窗只隐藏(`orderOut`)+ 结束业务会话,
  不再 `remove_window()`;销毁只剩「不是弹窗」(主窗口、远程编辑器窗口等不经过弹窗登记表的
  窗口)与两个隐藏失败分支。
- 红点路线保持上一版的接法:先返回 `false` 取消 AppKit 的关闭,再走同一个漏斗。

代价(写在明处):一次性弹窗没有复用键,隐藏后不会被重新显示,下一次打开是新建窗口 ⇒
停放窗口数随打开次数增长,直到退出应用。每个停放窗口只是空壳(业务 view 在关闭时已卸载)。
收敛方向是把热点弹窗改成 `open_reusable_popup_window`(数量收敛到弹窗种类数,且不需要任何
销毁),而不是加回销毁;在还有窗口必须销毁之前,不考虑「停放上限 + 延迟销毁」。

验证:

- `cargo test -p one-core --lib` → **693 passed / 0 failed**
- `cargo check -p one-core -p main --all-targets` → `Finished`(exit 0)
- `rustfmt --edition 2024` 只跑改动的两个文件
- 契约测试:`popup_windows_are_hidden_and_never_destroyed`(弹窗判断在隐藏之前;成功隐藏的
  分支里绝不允许出现 `remove_window()`)、`one_shot_popups_are_registered_as_parked`
  (两种登记都在,且一次性登记必须在 `reuse_key` 的 `else` 分支)、
  `every_popup_intercepts_the_native_close_route` 继续守住关闭路线。
- 文档:`docs/macos-memory-investigation.md` §10.7(并在 §10.6 标注它只对了一半)+
  `popup_lifecycle.rs` 计数口径 + `AGENTS.md` 弹窗条目。

真机判据(同一台 Intel + Touch Bar 机器):点红点关弹窗既不闪退也不卡死,且窗口确实消失。

Refs: navop#308 navop#314, zed#64819
2026-09-27 23:33:17 +08:00
..