feat(focus): 完成阶段 2 通用焦点系统

This commit is contained in:
Codex
2026-10-08 18:37:34 +08:00
parent 81341fab2c
commit 255aba688f
25 changed files with 1533 additions and 5 deletions
+17
View File
@@ -2,6 +2,23 @@
本次变更包含不兼容的所有权与文本样式 API 调整。GUI 仍限定在主线程,字符集仍为 MBCS。
## 阶段 2 焦点协议与二进制重编译
阶段 2 新增 `FocusManager`、`FocusTargetId`、`FocusScopeId`、`FocusPolicy`、`FocusReason`、`FocusError` 和 `FocusTargetSnapshot`。每个 `Window` 现在拥有一个逻辑焦点管理器:
```cpp
button->setTabIndex(10);
const auto result = button->requestFocus(StellarX::FocusReason::Programmatic);
const auto focused = window.getFocusManager().focusedTarget();
```
`Control` 新增焦点参与虚接口,用于递归快照解析、收集和焦点状态提交。该变化会改变 `Control` 及派生类的 vtable,因此:
- 已编译的第三方派生控件二进制必须使用新头文件重新编译,不能直接与新 Core 静态库混用。
- 源码派生控件无需立刻覆盖新虚接口;默认实现把自身作为焦点节点,默认 `FocusPolicy::None`,正常全量重编译即可。
- 需要参与焦点的自定义控件可调用 `setFocusPolicy()`;复合控件应覆盖焦点递归协议,但不得长期保存解析得到的裸指针。
- 本阶段没有移除 `Control::handleEvent()`,也没有停止旧 `EX_KEY` 业务交付;键盘迁移仍在阶段 3。
## Window 与 Canvas 所有权
不再公开可变的 `std::vector<std::unique_ptr<Control>>`。调用方必须保存稳定句柄,而不是保存容器迭代器或假设控件地址永久有效。