Repository navigation
feat(macos): 终端标签任意拖拽分屏并保留 PTY - #1638
Conversation
- 终端标签改用 AppKit 拖拽会话与私有 pasteboard,避免 Monaco 接收文本拖放 - 工具窗终端可拖入编辑器边缘或空编辑器,编辑器终端可拖回工具窗 - 抽出 EditorGroupLayout.splitting 复用分屏几何,补充模型、拖拽与 PTY 测试 Refs 1lck#1622
xiaoyumuxi
left a comment
There was a problem hiding this comment.
Review
审查范围:preview ← feat/macos-terminal-tab-splits,head dc29d667d35244a17103449502373999a2b4ab00,共 12 个变更文件。
发现 2 项 P2 问题,具体见行内评论,均为本次引入,建议修改;未发现需要阻塞合并的问题。
- 工具窗整窗 drop overlay 抢占标签栏落点,拖回终端时无法按目标标签前后插入,只能追加到末尾。
- 编辑器 drop overlay 在目标没有变化时仍反复发布
@Published target,引起整个编辑分组布局的不必要刷新。
补充建议:补齐平台功能矩阵
本 PR 自身没有更新终端拖拽/分屏对应的能力记录。以 merge-base e2e7f5cad92e69d0b635642570697d1da56f5b35 到本次 head 运行矩阵变更门禁,会报告缺少实质能力更新。现有矩阵 CI 绿灯包含目标分支推进造成的其他能力记录差异,不能证明本功能已登记。建议更新终端会话或编辑分组对应的能力记录,补充边缘分屏、中心加入及工具窗往返保留 PTY 的验证动作;没有完成的平台验收继续保持 pending。
验证范围
- 已静态追踪分组布局、标签选择、工具窗/编辑器 placement、原生拖放和终端 surface 生命周期;未发现移动时重建会话或进程的路径。
- 已查阅 macOS CI:3,589 项 Swift 测试通过,新增测试通过,但未覆盖上述原生 overlay 路由和相同落点通知次数。
- 本地对 PR head 的临时源码快照运行
scripts/macos/verify/verify-runtime-bundle-immutability.sh,通过;PR diff 的git diff --check通过。 - 未启动产品、未执行本地完整测试,以上交互问题基于静态调用链审查,尚未做本机真实拖放复现。未修改源码。
|
|
||
| required init?(coder: NSCoder) { nil } | ||
|
|
||
| override func hitTest(_ point: NSPoint) -> NSView? { |
There was a problem hiding this comment.
[P2] 工具窗覆盖层应保留标签落点顺序
这个 overlay 覆盖整个 TerminalView,且编辑器终端拖拽期间没有避让标签栏,因此会先于原有 TerminalTabDropDelegate 接收落点。performDragOperation 随后统一调用 moveTerminalToTool(sessionID),只会把会话追加到工具窗列表末尾,丢失原有按目标标签左/右半区插入的行为。
可构造的复现路径:工具窗已有 A、B,从编辑器将 C 拖到 A 的左半边,最终得到 A、B、C,而不是 C、A、B。
建议像编辑区 overlay 一样排除标签栏命中,交还已有前后插入 delegate;或者在原生目标中解析目标标签和插入侧,再调用带 before/after 的移动入口。补一项跨容器拖到已有标签前后的聚焦回归即可。来源:本次引入。
| currentTarget = nil | ||
| return [] | ||
| } | ||
| drag.target = target |
There was a problem hiding this comment.
[P2] 发布预览目标前应比较是否变化
draggingUpdated 每次都会走到这里,并无条件给 @Published target 赋值;即使指针仍在同一个边缘区域,生成的 Target 完全相同,也会发送通知,使观察它的 EditorGroupContainer 重新计算编辑分组布局。无效落点分支反复赋 nil 也有同样问题。普通标签拖动的 updateTabDrag 已经用新旧目标比较避免这项开销。
建议仅在 drag.target != target 时发布,清空目标时也去重;用重复输入同一落点并检查通知次数的聚焦回归保护该边界,不需要跑整机性能测试。来源:本次引入。
- Limit the native tool-window drop overlay to the canvas so tab-strip before/after insertion remains available for terminals dragged from editors. - Publish editor-group preview targets only when they change, including repeated clearing and drag lifecycle cleanup. - Add focused native overlay geometry and preview publication regressions. - Update the docking Agent Note and terminal capability matrix evidence and verification steps without claiming unperformed runtime verification. Validation: six focused Swift tests passed on Swift 6.3.3 with macOS 26.5 SDK; runtime bundle, architecture, i18n, Agent Notes and matrix static gates passed. The exact PR-based push tree also passed the static gates. Refs 1lck#1638
终端标签任意拖拽分屏并保留 PTY
背景
Issue #1622:终端标签只能在自身标签栏内重排,不能像编辑器页签一样拖到分组边缘分屏;工具窗里的终端也无法拖进编辑器。
根因:
.onDrag,Monaco 所在的WKWebView会消费拖放目标,祖先视图的.onDrop收不到终端 payload。text/plain兜底,拖到编辑器时会把 “Terminal” 当文本插入。EditorTabOrderFeatureModel.drop只接受已在编辑器中的页签,缺少从外部插入的入口。本次只处理终端标签拖拽/分屏;关闭确认、分栏比例持久化和
TerminalPlacementFeatureModel双列表结构不变。实现
group(containing:)、insert(_:into:side:)和AppModel.moveTerminalToEditor(_:into:side:),支持外部标签加入分组或在边缘分屏。EditorGroupLayout.splitting(_:by:newGroup:),drop与insert共用,删除重复的内联 split。TerminalTabInteraction改用 AppKitNSDraggingSession,pasteboard 只写私有com.lithe.terminal-tab,不再提供文本表示。EditorGroupDragState的分栏预览,标签栏仍交给 SwiftUI。影响
TerminalPlacementFeatureModel双列表重构。验证
iShot_2026-11-01_18.12.31.mp4