docs: 收口阶段 0B 输入消费结论
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
|
||||
- 模块 ID:Module-20261001-0001
|
||||
- 模块名称:通用输入采集、焦点与键盘路由系统
|
||||
- 状态:设计中(v0.9 IME 位置双时机修订;0C 当前可用环境基线通过,下一步进入 0B,阶段 1 尚未开始)
|
||||
- 状态:设计中(v0.13;0C 当前可用环境基线通过,0B 阶段 1 前置基线已关闭;微软拼音 Forward/Consume 有效,搜狗 Consume 请求按 `ime_condition_not_met` fail-open 并形成 `MustForward`;阶段 1 尚未开始)
|
||||
- 类型:新增模块 / 架构演进
|
||||
- 所属系统 / 子系统:StellarX Core / Window / Control / Input / Focus / TextBox
|
||||
- 版本 / 分支:`master`,阶段 0A 实现基线 `c218c25`
|
||||
@@ -126,6 +126,14 @@
|
||||
- 搜狗真实运行证明候选 UI 可能已经出现,但 EasyX HWND 尚未收到探测器原先依赖的 `WM_IME_STARTCOMPOSITION/WM_IME_COMPOSITION`。因此位置设置不能只挂在 IME 生命周期消息上;必须在焦点/caret/anchor 变化时预设,并在生命周期消息到达时再校准。
|
||||
- 修复后的搜狗运行中,F1/F2/F3 的 anchor 预设全部成功,F3 生命周期二次校准成功;F3 提交后回到 F1 的截图与初始 F1 裁剪字节一致。当前 96 DPI 虚拟化视图下,微软拼音与搜狗 0C-3 均通过人工视觉验收。
|
||||
|
||||
2026-10-06 的 0B 首轮 Composition 人工运行进一步确认:
|
||||
|
||||
- 操作者按 Escape 时,组合态 WndProc 观察到的是 `WM_KEYDOWN + VK_PROCESSKEY(229) + scanCode 1`,组合结束后的 KeyUp 才是 `VK_ESCAPE(27)`;因此原生采集规则必须允许用 message、VK 与 scan code 三元组精确描述,不能把 WndProc 层的 `VK_PROCESSKEY` 伪装成已恢复的逻辑 Escape。
|
||||
- `ImmGetVirtualKey` 只允许应用在自身消息循环调用 `TranslateMessage` 前恢复原 VK;当前钩子已经位于 EasyX WndProc,不能依赖该 API 补救时机。
|
||||
- 0B 夹具必须自己引用 0C 已验证的客户区 caret/line rect,并在焦点/IME context 与组合生命周期双时机设置组合窗和候选窗位置;否则“候选框异常”只证明夹具缺少定位,不能证明消费动作破坏 IME。
|
||||
- 宿主安全点复制整批记录会与 WndProc 争用状态锁。0B 修正为双固定缓冲、锁内常数时间交换、锁外写盘;诊断采集不再用 `try-lock` 丢弃 WndProc 观察。
|
||||
- 固定 IME 定位 setter 可能同步重入 WndProc。任何探测或生产输入实现都不得持有状态/输入队列锁调用 IMM32 setter;0B 使用“锁内提交父 enter 和不可变请求 → 锁外 IMM32 → 锁内校验会话并提交 `ime_position` 结果”的三阶段协议,并以线程局部标志阻止递归定位。
|
||||
|
||||
### 2. 分层架构
|
||||
|
||||
```text
|
||||
@@ -250,7 +258,7 @@ IME 消息:采集 + 转发
|
||||
- 非组合态 Button 的 Enter/Space。
|
||||
- 框架明确拥有的 Ctrl 快捷键。
|
||||
|
||||
硬规则:`imeComposingAtCapture == true` 的键不能进入消费白名单。
|
||||
硬规则:`imeComposingAtCapture == true` 或原始 `virtualKey == VK_PROCESSKEY` 的键不能进入消费白名单,也不得进入 Button、Dialog、快捷键或焦点导航等业务路由。后者不依赖标准 Composition 生命周期,因为搜狗实测已证明候选 UI 可见时目标 HWND 仍可能保持 `imeState=idle`。
|
||||
|
||||
### 6. 输入事件模型
|
||||
|
||||
@@ -389,7 +397,7 @@ EasyX HWND/WndProc 线程
|
||||
6. 若改为 lock-free SPSC,生产者写完 slot 后以 release 发布写索引,消费者以 acquire 读取;回收索引反向使用同等内存序。
|
||||
7. 全局 `sequence` 使用 atomic 分配,但事件可见性由互斥锁或 release/acquire 队列协议保证。
|
||||
|
||||
探测器使用的“固定环形缓冲 + 尝试锁 + 允许 `records_lost`”只适用于诊断日志,不能照搬为生产输入队列;生产输入事件比探测记录具有更强的不丢失要求。
|
||||
探测器使用的固定双缓冲和 `records_lost` 失效判定只适用于诊断日志,不能照搬为生产输入队列;生产输入事件比探测记录具有更强的不丢失要求。诊断路径同样禁止持锁调用旧窗口过程、IMM32 setter、用户回调或文件 I/O。
|
||||
|
||||
### 7. Unicode 和文字来源
|
||||
|
||||
@@ -987,17 +995,18 @@ struct DispatchState
|
||||
- 覆盖 100%、125%、150% 和跨屏不同 DPI。
|
||||
- 采集 `COMPOSITIONFORM` / `CANDIDATEFORM` 定位证据。
|
||||
- 详细规格见 [`Module-20261001-0003-阶段0C宽字符绘制与IME坐标探测规格.md`](./Module-20261001-0003-阶段0C宽字符绘制与IME坐标探测规格.md)。
|
||||
- 当前状态:0C-1 自动门槛通过;0C-2 当前 96/144 DPI 自动门槛通过;微软拼音与搜狗三个 anchor 已取得真实视觉证据,搜狗提交后 stale-position 回归通过。当前可用环境的 0C 基线关闭,100%/125%/跨屏作为实机能力缺口继续记录,下一步进入 0B。
|
||||
- 当前状态:0C-1 自动门槛通过;0C-2 当前 96/144 DPI 自动门槛通过;微软拼音与搜狗三个 anchor 已取得真实视觉证据,搜狗提交后 stale-position 回归通过。当前可用环境的 0C 基线已关闭,100%/125%/跨屏作为实机能力缺口继续记录;后续 0B 阶段 1 前置基线也已关闭。
|
||||
|
||||
#### 阶段 0B:隔离消费实验
|
||||
|
||||
使用测试专用规则:
|
||||
使用测试专用规则;详细规格见 [`Module-20261001-0004-阶段0B原生键盘消息隔离消费实验规格.md`](./Module-20261001-0004-阶段0B原生键盘消息隔离消费实验规格.md):
|
||||
|
||||
```cpp
|
||||
struct ProbeConsumeRule
|
||||
{
|
||||
UINT message;
|
||||
std::optional<UINT> virtualKey;
|
||||
std::optional<std::uint8_t> scanCode;
|
||||
ImeStateCondition imeCondition; // Any / IdleOnly / ComposingOnly
|
||||
ProbeAction action; // ObserveAndForward / ObserveAndConsume
|
||||
};
|
||||
@@ -1007,6 +1016,21 @@ struct ProbeConsumeRule
|
||||
- 日志携带实验 ID 和规则 ID。
|
||||
- 同步窗口协议禁止进入规则表。
|
||||
- 正式构建默认没有任何消费规则。
|
||||
- 动作枚举严格保持 `ObserveAndForward / ObserveAndConsume` 两值;“转发但抑制下游业务路由”属于阶段 1,不是 0B 的第三种 WndProc 动作。
|
||||
- 实验结论使用 `SafeToConsume / MustForward / Inconclusive`,与动作枚举分离。
|
||||
- 自动 A/B 必须单独回答:WndProc 消费目标 `WM_KEYDOWN` 后,宿主 `peekmessage(EX_KEY)` 是否仍返回对应虚拟键。
|
||||
- 配置错误、规则模糊、IME 状态不可靠、出现记录丢失或运行环境与 0C baseline 不一致时一律 fail-open,实际动作退回观察并转发。
|
||||
- 当前 F24 实测:`WM_KEYDOWN/UP` 的 Forward 对照均产生一次对应 `EX_KEY`,Consume 后对应 `EX_KEY` 均消失;错误 baseline 请求 Consume 时正确退回 Forward。该结论只证明 F24 的两观察面关系,不自动外推为生产消费白名单。
|
||||
- 自动首键由 F8 改为 F24:当前中文 IME 环境下 F8 的 `SendInput` KeyDown 未到达目标 WndProc,截断层级尚未确认,不能形成有效 A/B 对照。
|
||||
- 0B 自动证据现已强制要求严格序列、零丢失、真实 fixture PID 退出、`WM_CLOSE` 与 `session_end` 完整;宿主 flush 和 WndProc 关闭收口使用独立文件写锁串行。
|
||||
- Composition 人工规则按真实原生观察匹配 `WM_KEYDOWN + VK_PROCESSKEY(229) + scanCode 1`,操作者动作仍为 Escape;规则不尝试在 WndProc 中恢复逻辑键。
|
||||
- 0B 人工夹具使用固定客户区 anchor,并记录 `ImmGetContext` 与两个 setter 的分项结果;位置链未成功时请求 Consume 必须 fail-open。
|
||||
- 0B 日志缓冲采用双固定缓冲,安全点只在状态锁内交换 buffer;文件序列化在锁外完成,避免把探测器自身锁竞争误报成输入链丢失。
|
||||
- 0B 固定 IME 定位采用三阶段拆锁协议,定位结果写独立 `ime_position` 记录并以 `parentSequence` 关联父 enter;setter 同步重入的消息允许正常采集,但不得递归发起定位。
|
||||
- 修复后微软拼音 Forward 人工运行保持响应,Escape 原生规则唯一命中并转发,定位结果 18/18 成功且无孤立父序号;截图确认组合串/候选 UI 位于固定锚点附近。该结论只关闭诊断死锁和 Forward 对照,不代替 Consume 与搜狗矩阵。
|
||||
- 微软拼音 Consume 重跑中 Escape 原生规则唯一命中并返回 0,旧窗口过程未被调用,对应 EasyX `EX_KEY=absent`;定位 7/7 成功、零丢失且没有产生提交结果。与 Forward 的 `EX_KEY=present_once` 对照表明当前受控键在 WndProc 消费后不会再进入 EasyX 键面,但生产白名单仍需搜狗矩阵和最终 0B 评审。
|
||||
- 搜狗候选态实测没有向目标 HWND 发送 START/COMPOSITION/END 生命周期;Escape KeyDown 仍为 `VK_PROCESSKEY + scanCode 1`,但 tracked IME state 保持 Idle。最终 Consume 请求按 `ime_condition_not_met` 运行时 fail-open 为 Forward,EasyX 键可见一次,结论为 `MustForward` 而不是真正 Consume。
|
||||
- 阶段 1 采用默认 capture-and-forward,不建立生产消费白名单;所有 `VK_PROCESSKEY` 和已确认组合态键只供输入法/文本规范化,不进入控件业务路由。微软拼音单点 Consume 成功只作为“WndProc return 0 会阻断 EasyX 键面”的机制证据。
|
||||
|
||||
#### 阶段 1:InputCollector
|
||||
|
||||
@@ -1082,12 +1106,14 @@ struct ProbeConsumeRule
|
||||
26. EasyX 批次必须从主画面进入和退出;工作图像只在批次内部切换,并通过显式合成上屏。
|
||||
27. 在已验证的 DPI-unaware 96 与 Per-Monitor-V2 144 环境中,EasyX 绘制坐标可直接作为 HWND 客户区坐标;不得额外乘 DPI 比例。
|
||||
28. IME 位置必须在焦点/caret/anchor 变化时立即预设,并在组合生命周期消息到达时再次校准;不得假定候选 UI 出现前一定会收到 `WM_IME_STARTCOMPOSITION/WM_IME_COMPOSITION`。
|
||||
29. 原始 `VK_PROCESSKEY` 一律视为 IME 所有:WndProc 层采集并转发,阶段 1 不向 Button、Dialog、快捷键和焦点导航路由;不得依赖 `imeComposingAtCapture` 单独判断搜狗候选态。
|
||||
30. 0B 没有建立跨 IME 生产消费白名单;阶段 1 从默认转发基线开始,后续任何窄消费规则都必须有独立逐键证据。
|
||||
|
||||
## 实现与影响
|
||||
|
||||
- 关键实现点:
|
||||
- 阶段 0A 探测器已经进入框架;0C 独立视觉探测工程已实现;FocusManager、生产 NativeInputQueue 和 TextBox 改造尚未开始。
|
||||
- 独立 EasyX 探测已经推翻 v0.4 的单线程假设,v0.5 据此补入跨线程队列约束;v0.6 根据微软拼音/搜狗真实日志锁定结果串与回声关系,并补入输入布局 request/change 分层;v0.7 根据专用短测区分 TSF 配置文件切换与跨语言 HKL,并增加重新获焦快照约束;v0.8 根据 0C 自动证据锁定宽字符绘制、批次进入顺序与当前 DPI 坐标规则;v0.9 根据搜狗真实失败与修复复验锁定 IME 位置双时机规则。
|
||||
- 独立 EasyX 探测已经推翻 v0.4 的单线程假设,v0.5 据此补入跨线程队列约束;v0.6 根据微软拼音/搜狗真实日志锁定结果串与回声关系,并补入输入布局 request/change 分层;v0.7 根据专用短测区分 TSF 配置文件切换与跨语言 HKL,并增加重新获焦快照约束;v0.8 根据 0C 自动证据锁定宽字符绘制、批次进入顺序与当前 DPI 坐标规则;v0.9 根据搜狗真实失败与修复复验锁定 IME 位置双时机规则;v0.13 根据 0B 微软拼音 Consume 与搜狗运行时 fail-open 证据锁定默认转发、`VK_PROCESSKEY` 路由抑制和无生产消费白名单基线。
|
||||
- 涉及文件 / 类 / 函数:
|
||||
- 预计涉及 `Window`、`Control`、`Canvas`、`Button`、`TextBox`、`Table`、`TabControl`、`Dialog`。
|
||||
- 实际文件和接口必须在阶段 0 与实现前只读检查后确定。
|
||||
@@ -1106,7 +1132,7 @@ struct ProbeConsumeRule
|
||||
|
||||
- 测试范围:
|
||||
- 设计评审覆盖输入采集、同步消息、Unicode、IME、焦点、复合控件、按键归属、TextBox 和模态重入。
|
||||
- 独立线程归属探测、0A 构建、固定消息 smoke、微软拼音/搜狗真实输入链路测试以及当前可用环境的 0C 基线均已完成;0B 消费实验、生产输入队列和焦点系统尚未开始。
|
||||
- 独立线程归属探测、0A 构建、固定消息 smoke、微软拼音/搜狗真实输入链路测试、当前可用环境的 0C 基线,以及 0B 的 F24 KeyDown/KeyUp 自动 A/B、baseline fail-open、微软拼音 Forward/Consume 和搜狗运行时 fail-open 门槛均已完成;生产输入队列和焦点系统尚未开始。
|
||||
- 验证步骤:
|
||||
|
||||
1. 先按关联规格实现阶段 0A 被动探测并取得消息链路证据。
|
||||
@@ -1129,16 +1155,21 @@ struct ProbeConsumeRule
|
||||
- 2026-10-05:微软拼音三个 anchor 自动 IMM 调用和人工位置观察通过;第二轮虽然脚本参数为 `Sogou`,操作者确认实际未切换输入法,因此没有把它误记为搜狗证据。
|
||||
- 2026-10-05 23:51:搜狗首次真实运行按预期门槛失败,F1/F2 未发生 IMM 定位调用,F3 为 2/2;截图确认候选框先位于窗口外,之后沿用 F3 旧位置。
|
||||
- 2026-10-06:v0.9 将 IME 位置刷新改为“焦点/caret/anchor 变化立即预设 + IME 生命周期再次校准”;探测事件新增触发来源与分项计数,并完成三平台构建及真实搜狗回归。
|
||||
- 2026-10-06:搜狗修复后运行自动与人工状态均为 `pass`;三个 anchor 均按请求定位,F3 提交后回到 F1 的截图与初始 F1 裁剪字节一致。当前可用环境 0C-3 关闭,下一步进入 0B。
|
||||
- 2026-10-06:搜狗修复后运行自动与人工状态均为 `pass`;三个 anchor 均按请求定位,F3 提交后回到 F1 的截图与初始 F1 裁剪字节一致。当前可用环境 0C-3 关闭,随后进入 0B。
|
||||
- 2026-10-06:0B F24 `WM_KEYDOWN/UP` 自动 A/B 均通过;Forward 对应 `EX_KEY=present_once`,Consume 对应 `EX_KEY=absent`。错误 baseline 的请求 Consume 正确 fail-open 为 Forward。真实 IME 人工矩阵未完成,因此阶段 1 仍不启动。
|
||||
- 2026-10-06:0B Composition 首轮人工运行无效:夹具未设置 IME 位置,Escape 规则错误匹配 `VK_ESCAPE` 而实际 KeyDown 为 `VK_PROCESSKEY + scanCode 1`,且出现 3 条锁竞争丢失。已实现固定 IMM32 锚点、原生三元组规则与双缓冲采集修正;微软拼音/搜狗 A/B 需重新执行。
|
||||
- 2026-10-07:微软拼音 Forward/Consume 有效复验均通过;Forward 对应 EasyX 键出现一次,Consume 后 EasyX 键消失,位置链分别为 18/18 与 7/7,均零丢失、无孤立定位记录。
|
||||
- 2026-10-07:搜狗候选态没有向目标 HWND 暴露 START/COMPOSITION/END 生命周期;最终 Consume 请求以 `ime_condition_not_met` 正确 fail-open 为 Forward,规则零命中、零消费、EasyX 键出现一次,结构 verdict 为 `MustForward`。
|
||||
- 2026-10-07:最终 Debug x64 单元测试 15/15、UI fixture 1 轮、F24 KeyDown A/B 新运行通过;既有 KeyUp 与 baseline mismatch 证据经当前分析器回放保持有效。阶段 1 以默认转发且无消费白名单为起点。
|
||||
- 已知限制 / 遗留问题:
|
||||
- §5.3 的最终消费白名单必须等待阶段 0B 数据。
|
||||
- §5.3 当前明确不建立生产消费白名单;若后续需要窄消费规则,仍必须补对应消息、虚拟键、IME 和环境的独立 0B 证据。
|
||||
- §7.3 的微软拼音/搜狗回声状态机已有 0A 证据,其他 IME 仍需保持可诊断回退。
|
||||
- 宽字符 GDI 与当前微软拼音/搜狗定位门槛已通过;100%/125% 与跨屏 DPI 仍由阶段 0C 规格作为实机能力缺口承接。
|
||||
|
||||
## 落地信息
|
||||
|
||||
- 关联功能变更 ID:无
|
||||
- 关联 BUG / Fix:无
|
||||
- 关联 BUG / Fix:`BUG-20261006-0001` / `Fix-BUG-20261006-0001`;`BUG-20261006-0002` / `Fix-BUG-20261006-0002`
|
||||
- Commit:`c218c25`(阶段 0A 诊断实现与线程归属复现);`c0eca1d`(探测暴露的原生窗口关闭修复);`43cf4ac`(阶段 0C 视觉与 IME 坐标探测)
|
||||
- PR:无
|
||||
- 发布版本:未发布
|
||||
@@ -1151,6 +1182,7 @@ struct ProbeConsumeRule
|
||||
- [WM_IME_SETCONTEXT](https://learn.microsoft.com/en-us/windows/win32/intl/wm-ime-setcontext)
|
||||
- [WM_IME_COMPOSITION](https://learn.microsoft.com/en-us/windows/win32/intl/wm-ime-composition)
|
||||
- [ImmGetCompositionStringW](https://learn.microsoft.com/en-us/windows/win32/api/imm/nf-imm-immgetcompositionstringw)
|
||||
- [ImmGetVirtualKey](https://learn.microsoft.com/en-us/windows/win32/api/immdev/nf-immdev-immgetvirtualkey)
|
||||
- [ImmNotifyIME](https://learn.microsoft.com/en-us/windows/win32/api/immdev/nf-immdev-immnotifyime)
|
||||
- [COMPOSITIONFORM](https://learn.microsoft.com/en-us/windows/win32/api/imm/ns-imm-compositionform)
|
||||
- [CANDIDATEFORM](https://learn.microsoft.com/en-us/windows/win32/api/imm/ns-imm-candidateform)
|
||||
|
||||
Reference in New Issue
Block a user