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
+32
View File
@@ -36,10 +36,17 @@
class Window;
namespace StellarX
{
class FocusManager;
}
class Control
{
friend class Window;
friend class Canvas;
friend class Table;
friend class TabControl;
protected:
inline static std::atomic<std::uint64_t> nextHandleValue{ 1 };
// 句柄随控件构造生成,容器只通过句柄排队删除,避免遍历期间直接持有失效指针。
@@ -52,6 +59,9 @@ protected:
bool dirty = true; // 是否重绘
bool show = true; // 是否显示
bool eventVisualChanged = false; // 最近一次 handleEvent 是否真的引发了视觉变化(用于上层判断是否需要登记重绘)
StellarX::FocusPolicy focusPolicy = StellarX::FocusPolicy::None; // 逻辑焦点入口能力
std::int32_t tabIndex = 0; // 同一作用域内的显式 Tab 顺序;相同时保持树顺序
bool logicalFocused = false; // 仅由 FocusManager 提交,控件不得自行切换
/* == 布局模式 == */
StellarX::LayoutMode layoutMode = StellarX::LayoutMode::Fixed; // 布局模式
@@ -228,6 +238,15 @@ public:
std::string getId() const { return id; }
// 返回稳定句柄而非对象地址;调用方不得据此推断控件当前仍在容器中。
StellarX::ControlHandle getHandle() const noexcept { return handle; }
// 申请逻辑焦点。回调重入时请求会进入 FocusManager 当前回合的单槽 pending。
StellarX::FocusChangeResult requestFocus(
StellarX::FocusReason reason = StellarX::FocusReason::Programmatic);
// 设置焦点入口策略;修改后若当前焦点不再有效,会立即进入焦点回退。
void setFocusPolicy(StellarX::FocusPolicy policy);
StellarX::FocusPolicy getFocusPolicy() const noexcept { return focusPolicy; }
void setTabIndex(std::int32_t value);
std::int32_t getTabIndex() const noexcept { return tabIndex; }
bool hasLogicalFocus() const noexcept { return logicalFocused; }
// 检查控件当前是否处于待重绘状态。
bool isDirty() { return dirty; }
//获取控件最近一次事件处理是否引发了视觉变化
@@ -280,6 +299,19 @@ public:
// - 仅用于少数需要把当前结果固化为新设计基线的场景
void commitCurrentGeometryAsDesignRect();
protected:
// 焦点参与协议:默认节点只解析 {本控件句柄, 0};复合控件递归转发给真实子 Control。
virtual bool queryFocusTargetSnapshot(const StellarX::FocusTargetId& target,
StellarX::FocusTargetSnapshot& snapshot) const;
virtual void collectFocusTargetSnapshots(
std::vector<StellarX::FocusTargetSnapshot>& snapshots) const;
virtual bool applyFocusState(const StellarX::FocusTargetId& target, bool focused,
StellarX::FocusReason reason);
// 各控件动态提供 enabled 语义;Button 会根据 DISABLED 模式覆盖。
virtual bool isFocusEnabled() const { return true; }
// 派生控件可响应焦点变化;回调允许安全地请求焦点或排队修改控件树。
virtual void onLogicalFocusChanged(bool, StellarX::FocusReason) {}
bool isEffectivelyVisible() const;
void notifyFocusSubtreeStateChanged();
// 容器和窗口在事件、绘制、tick 期间进入事务;具体容器在最外层结束时提交队列。
MutationScope enterMutationScope() { return MutationScope(this); }
// 进入子树结构变更事务。默认向父容器或宿主 Window 传播,使整棵树共享同一提交边界。