# Taglauncher WindowServer 预防收窄 日期:2026-07-02 项目:Taglauncher 会话:Coder3 主题:WindowServer 预防收窄 ## 用户目标 用户确认按会诊建议继续做两项预防性收窄,顺序为: 1. 先做 Usage Tips local monitor 事件来源收窄。 2. 再做 App note 泡泡输入框 IME 风险收窄,并跑中文输入法真实输入相关的代码门禁。 本轮目标是最小范围提前降低 WindowServer / TextInput 风险,不重做已验收 UI,不生成新的视觉方案。 ## 已完成事项 - Usage Tips local mouse monitor 只处理同一 AppGrid 窗口的鼠标事件。 - Usage Tips 坐标换算去掉跨窗口时基于 `NSEvent.mouseLocation` 的兜底,非本窗口事件直接返回 `.zero`。 - App note 泡泡编辑框从 SwiftUI `TextField` 改为 AppKit `NSTextField` 桥接。 - App note 泡泡在 IME marked text 期间不覆盖、不截断、不提交文本,回车提交和 Esc 取消只在 marked text 结束后处理。 - 新增 App note 泡泡输入静态 QA,并把 Usage Tips 同窗口收窄写进原有 QA。 - 完整构建通过,生成 `/Users/ar/Projects/Taglauncher/src/build/TagLauncher.app`,构建号输出为 `8.3.1 (20260702.0128)`。 ## 关键决策 - 不改 `OverlayWindowController` 的 `.nonactivatingPanel` 行为,避免扩大行为变化。 - App note 泡泡只替换输入控件内部实现,保留原泡泡布局、外观、备注长度上限和 Esc 取消语义。 - Usage Tips 只收窄事件来源,不改变显示、关闭提醒、按钮和翻页行为。 ## 核心事实 / 变更快照 - 变更对象:Usage Tips local monitor 鼠标事件路由。 - 变更前:local monitor 会在 `self.window != nil` 时继续处理事件,跨窗口坐标可用 `NSEvent.mouseLocation` 兜底换算。 - 变更后:local monitor 必须满足 `event.window === self.window`;跨窗口事件不再用全局鼠标位置换算,直接返回 `.zero`。 - 范围边界:只影响 Usage Tips 鼠标事件吞噬范围,不影响 AppGrid 普通点击和 Usage Tips 同窗口点击。 - 证据:`bash Scripts/usage_tips_qa.sh` PASS。 - 变更对象:App note 泡泡编辑输入框。 - 变更前:SwiftUI `TextField(tr("appNote.placeholder"), text: limitedDraft)` 通过 Binding setter 即时 `prefix(maxAppNoteLength)` 截断。 - 变更后:`AppBubbleNoteTextField` 使用 AppKit `NSTextField` 桥接;marked text 期间不写回 SwiftUI binding,不截断,不执行回车提交 / Esc 取消。 - 范围边界:最终提交仍由 `TagDatabase.maxAppNoteLength` 限制;未改变备注额度、备注保存路径和泡泡外观容器。 - 证据:`bash Scripts/app_note_bubble_input_qa.sh` PASS;`bash Scripts/macos14_availability_typecheck_qa.sh` PASS;`bash build.sh` PASS。 ## 文件变更 - `/Users/ar/Projects/Taglauncher/src/Apptag/AppGridCollectionView.swift` - 收窄 Usage Tips local monitor 到本窗口事件。 - Usage Tips host / view 坐标换算移除跨窗口全局鼠标位置兜底。 - `/Users/ar/Projects/Taglauncher/src/Apptag/AppGridSupport.swift` - 新增 `AppBubbleNoteTextField` / `AppBubbleNativeTextField`。 - App note 泡泡编辑框改用原生 `NSTextField` 桥接。 - marked text 期间保护 IME 组合输入,最终同步时再限制备注长度。 - `/Users/ar/Projects/Taglauncher/src/Scripts/usage_tips_qa.sh` - 新增 Usage Tips local monitor 只消费本窗口事件的静态断言。 - 新增 Usage Tips 坐标换算不得使用跨窗口 `NSEvent.mouseLocation` 兜底的静态断言。 - `/Users/ar/Projects/Taglauncher/src/Scripts/app_note_bubble_input_qa.sh` - 新增 App note 泡泡输入 IME 安全静态 QA。 - `/Users/ar/Projects/Taglauncher/CODEGRAPH.md` - 追加 `windowserver_event_safety_qa.sh` 和 `app_note_bubble_input_qa.sh` QA 索引说明。 ## QA 结果 ```bash cd /Users/ar/Projects/Taglauncher/src bash Scripts/app_note_bubble_input_qa.sh ``` 结果:PASS app note bubble input QA。 ```bash cd /Users/ar/Projects/Taglauncher/src bash Scripts/usage_tips_qa.sh ``` 结果:PASS usage tips QA。 ```bash cd /Users/ar/Projects/Taglauncher/src bash Scripts/windowserver_event_safety_qa.sh ``` 结果:PASS windowserver event safety QA。 ```bash cd /Users/ar/Projects/Taglauncher/src bash Scripts/tag_editor_mouse_event_qa.sh ``` 结果:PASS Tag editor mouse event QA。 ```bash cd /Users/ar/Projects/Taglauncher/src bash Scripts/quick_search_launch_contract_qa.sh ``` 结果:PASS quick search launch contract。 ```bash cd /Users/ar/Projects/Taglauncher/src bash Scripts/macos14_availability_typecheck_qa.sh ``` 结果:PASS macOS 14.0 availability typecheck: arm64。 ```bash cd /Users/ar/Projects/Taglauncher/src git diff --check ``` 结果:PASS,无输出。 ```bash cd /Users/ar/Projects/Taglauncher/src bash build.sh ``` 结果:PASS,生成 `/Users/ar/Projects/Taglauncher/src/build/TagLauncher.app`,构建输出 `TagLauncher 8.3.1 (20260702.0128)`。 ```bash cd /Users/ar/Projects/Taglauncher/src bash Scripts/macos14_build_metadata_qa.sh ``` 结果:PASS build metadata: `LSMinimumSystemVersion=14.0 minos=14.0 arches=arm64`。 ## 可复用命令 / Runbook 用途:复查本轮 WindowServer / TextInput 预防性收窄是否仍成立。 前置条件: - 项目源码目录为 `/Users/ar/Projects/Taglauncher/src`。 - 当前代码包含 Usage Tips 本窗口事件收窄与 App note 泡泡原生输入框桥接。 - 不需要真实购买状态。 设置命令: ```bash cd /Users/ar/Projects/Taglauncher/src bash Scripts/usage_tips_qa.sh bash Scripts/app_note_bubble_input_qa.sh bash Scripts/windowserver_event_safety_qa.sh bash Scripts/tag_editor_mouse_event_qa.sh bash Scripts/quick_search_launch_contract_qa.sh bash Scripts/macos14_availability_typecheck_qa.sh git diff --check bash build.sh bash Scripts/macos14_build_metadata_qa.sh ``` 验证步骤: - 所有 QA 输出 PASS。 - `bash build.sh` 输出 App 构建成功,并生成 `/Users/ar/Projects/Taglauncher/src/build/TagLauncher.app`。 清理 / 恢复命令: - 本 Runbook 不修改系统环境变量,不需要清理。 - 若运行构建后只想删除本地构建产物,可手动删除 `/Users/ar/Projects/Taglauncher/src/build/`,但发布或验收前不建议删除。 搜索关键词:`usage_tips_qa.sh`、`app_note_bubble_input_qa.sh`、`WindowServer`、`App note bubble`、`NSTextField`、`hasMarkedText`、`NSEvent.mouseLocation`、`event.window === self.window`。 ## 未决问题 - 本轮没有做真实 GUI 中文输入法人工录屏验证;仅完成代码层防线、静态 QA、typecheck 和完整构建。 - 工作区仍保留此前已有的 Release 文档脏改动,本轮未触碰。 ## 后续建议 - 用户空闲时可人工打开备注泡泡,用中文输入法输入候选词、回车确认、Esc 取消,观察是否仍出现卡死或输入中断。 - 若后续还有 WindowServer 日志,可优先对照本记录中的两个风险点确认是否复发。