docs: 输入系统 v0.7 设计与 0A 探测规格
This commit is contained in:
@@ -0,0 +1,377 @@
|
||||
# 新增功能模块 / 模块重构
|
||||
|
||||
> 适用场景:新增模块、重大模块重构、核心架构能力演进。
|
||||
> 不适用场景:小接口或轻量功能变更,请使用“功能变更”模板。
|
||||
|
||||
## 基本信息
|
||||
|
||||
- 模块 ID:Module-20261001-0003
|
||||
- 模块名称:阶段 0C 宽字符绘制与 IME 坐标探测规格
|
||||
- 状态:设计中(评审意见已并入,探测器尚未实现)
|
||||
- 类型:新增模块 / 诊断基础设施
|
||||
- 所属系统 / 子系统:StellarX Core / Window / GDI / IMM32 / DPI
|
||||
- 版本 / 分支:`master`,前置阶段 0A 基线 `c218c25`
|
||||
- 环境:Windows + Visual Studio 2022 + MSVC v143 + EasyX + GDI + IMM32
|
||||
- 负责人:Codex 协作设计
|
||||
- 阶段定位:阶段 0 探测的能力分类之一(0A 消息链路 / 0B 消费实验 / 0C 绘制与坐标)。编号不代表严格执行顺序,建议顺序为 0A → 0C → 0B。
|
||||
|
||||
## 背景与目标
|
||||
|
||||
- 背景:
|
||||
- 设计基线已锁定“绘制优先使用宽字符 GDI,不默认降级 CP936”和“系统候选框定位到 TextBox caret”两条决策。
|
||||
- 两条决策都依赖尚未验证的事实:(1) `TextOutW/DrawTextW/GetTextExtentPoint32W` 能否真正画入 EasyX 当前工作图像;(2) EasyX 绘制坐标空间与 HWND 客户区/屏幕坐标是否一致,尤其是不同 DPI 下。
|
||||
- 这两项属于“EasyX 绘制表面与 Win32 原生坐标空间的兼容边界”,无法从 0A 键盘消息 JSONL 推断,需要独立的视觉与坐标证据。
|
||||
- 当前痛点:
|
||||
- 若宽字符 GDI 实际画不进 EasyX 工作图像,却按“可用”推进,会在阶段 5 TextBox 自绘时集中爆发。
|
||||
- 若 DPI 坐标换算错误,候选框在 125%/150%/跨屏场景整体偏移,且这种 bug 难用单元测试覆盖。
|
||||
- 测量结果、像素证据和人工视觉结论若混在一起,无法定位问题出在测量、绘制还是观察环节。
|
||||
- 目标:
|
||||
- 定义阶段 0C 的验证方法、固定非敏感测试串、证据分层、DPI 矩阵和失败/降级判定。
|
||||
- 为阶段 5 的 TextBox 自绘和阶段 6 的 IME 定位提供“宽字符绘制是否可行、坐标如何换算”的可复核证据与结论。
|
||||
- 非目标:
|
||||
- 不实现 TextBox 自绘、不修改任何控件或框架代码。
|
||||
- 不决定是否降级 CP936,该结论由 0C 证据决定。
|
||||
- 不把视觉/坐标结果并入 0A 键盘 JSONL schema。
|
||||
- 不验证消费消息的影响(属 0B)。
|
||||
|
||||
## 模块边界
|
||||
|
||||
- 职责:
|
||||
- 定义宽字符 GDI 的目标 HDC 与工作图像验证方法。
|
||||
- 定义固定非敏感测试串集合。
|
||||
- 定义绘制、测量、像素、人工视觉四层证据及其记录格式。
|
||||
- 定义 DPI、客户区/屏幕坐标和 caret anchor 的换算验证。
|
||||
- 定义 COMPOSITIONFORM / CANDIDATEFORM 定位证据。
|
||||
- 定义自动检查与必须人工观察的分层。
|
||||
- 定义阶段门槛、失败判定和降级条件。
|
||||
- 不负责什么:
|
||||
- 不新增框架公共 API。
|
||||
- 不在 WndProc 中执行 IME UI 修改。
|
||||
- 不用真实用户输入作为测试串。
|
||||
- 不把结论写入生产代码默认配置。
|
||||
- 外部依赖:
|
||||
- EasyX `SetWorkingImage` / 工作图像 HDC。
|
||||
- GDI `TextOutW` / `DrawTextW` / `GetTextExtentPoint32W`。
|
||||
- `GetDpiForWindow`、进程 DPI awareness。
|
||||
- `COMPOSITIONFORM` / `CANDIDATEFORM` 与 caret anchor。
|
||||
- 对外能力 / API:
|
||||
- 仅定义内部诊断与证据格式,不新增框架公共 API。
|
||||
- 必须由测试/诊断构建开关显式启用,正式默认关闭。
|
||||
- 关键数据 / 状态:
|
||||
- 目标 HDC 与工作图像身份、GDI 状态保存/恢复校验。
|
||||
- 每类测试串的测量结果、像素采样、人工结论。
|
||||
- DPI 值、坐标换算结果、候选框定位证据。
|
||||
|
||||
## 设计说明
|
||||
|
||||
### 1. 证据分层
|
||||
|
||||
四类证据必须分开记录,禁止互相替代:
|
||||
|
||||
| 证据层 | 内容 | 来源 | 可自动化 |
|
||||
|---|---|---|---|
|
||||
| 绘制结果 | 实际调用了哪些 GDI 函数、目标 HDC、返回值 | 运行日志 | 是 |
|
||||
| 测量结果 | `GetTextExtentPoint32W` 返回的宽高 | 运行日志 | 是 |
|
||||
| 像素证据 | 工作图像指定区域的像素采样/截图 | 位图采样 | 是(采样点) |
|
||||
| 人工视觉结论 | 候选框实际位置、缺字/方框、对齐是否正常 | 人工观察 | 否 |
|
||||
|
||||
### 2. 固定非敏感测试串
|
||||
|
||||
只使用预先约定的非敏感串,不使用用户输入。测试实现必须根据下表的 Unicode scalar 序列构造 UTF-16,不得把源文件中的可见文字字面量作为判定依据。
|
||||
|
||||
| `testStringId` | Unicode scalar 序列 | 便于人工识别的显示 | 目的 |
|
||||
|---|---|---|---|
|
||||
| `ascii` | `U+0053 U+0074 U+0065 U+006C U+006C U+0061 U+0072 U+0058 U+0020 U+0030 U+0043 U+0020 U+0050 U+0072 U+006F U+0062 U+0065` | `StellarX 0C Probe` | ASCII 基线 |
|
||||
| `cjk_bmp` | `U+661F U+57A3 U+7ED8 U+5236 U+6D4B U+8BD5` | `星垣绘制测试` | BMP 中文与字体覆盖 |
|
||||
| `supplementary` | `U+1F600` | `😀` | 增补平面字符;UTF-16 应为 `D83D DE00` |
|
||||
| `combining_nfd` | `U+0065 U+0301` | `e` + combining acute | 明确验证 NFD 组合序列,不允许换成预组字符 `U+00E9` |
|
||||
| `mixed` | `U+661F U+57A3 U+0020 U+0041 U+1F600 U+0042 U+0020 U+0065 U+0301` | `星垣 A😀B é` | 混合相邻布局、代理对和组合字符 |
|
||||
|
||||
每个用例在绘制前记录构造后的 UTF-16 code unit 序列和有效性。字体不包含某个 glyph 时,应归类为字体覆盖问题,不能据此认定宽字符 API 不可用。
|
||||
|
||||
### 3. 宽字符 GDI 目标 HDC 验证
|
||||
|
||||
验证对象:
|
||||
|
||||
- 默认主画面(未调用 `SetWorkingImage`)上的 `TextOutW/DrawTextW/GetTextExtentPoint32W`。
|
||||
- 调用 `SetWorkingImage` 之后的目标工作图像 HDC。
|
||||
|
||||
单纯比较 HDC handle 不足以证明绘制表面身份。每个目标必须记录以下表面指纹:
|
||||
|
||||
```text
|
||||
HDC handle
|
||||
GetCurrentObject(hdc, OBJ_BITMAP) 返回的 HBITMAP
|
||||
HBITMAP 宽高、位深和 stride(能够取得时)
|
||||
GetCurrentObject(hdc, OBJ_FONT) 返回的 HFONT 与 LOGFONTW
|
||||
GetMapMode / viewport origin / window origin / viewport extent / window extent
|
||||
GetClipBox
|
||||
GetBkMode / GetTextColor / GetBkColor / GetTextAlign
|
||||
GetTextCharacterExtra
|
||||
```
|
||||
|
||||
主画面和工作图像分别使用不同的固定哨兵底色,并按以下步骤验证:
|
||||
|
||||
1. `SetWorkingImage` 切换前后分别采集 HDC、selected bitmap 和 GDI 状态。
|
||||
2. 对目标表面与非目标表面记录绘制前像素摘要。
|
||||
3. 调用 `SaveDC`,设置受控字体、颜色、背景模式、mapping mode 和 clip。
|
||||
4. 使用 W 版本 API 绘制唯一的固定测试图案和测试串。
|
||||
5. 从目标表面回读像素,验证目标发生预期变化。
|
||||
6. 从非目标表面回读相同区域,验证没有串画。
|
||||
7. 调用 `RestoreDC`,重新采集状态并验证未污染 EasyX 后续绘制。
|
||||
|
||||
宽字符能力与字体覆盖分开判定:
|
||||
|
||||
- `TextOutW/DrawTextW` 调用成功、目标表面变化且非目标表面不变,证明 W 绘制链可达。
|
||||
- 出现缺字方框、空 glyph 或黑白 emoji 时,记录字体覆盖/字体回退结论,不直接判定 W 绘制失败。
|
||||
- `GetTextExtentPoint32W` 返回当前 HDC、字体和文字状态下的逻辑 advance,不是像素墨迹包围盒,也不考虑裁剪。
|
||||
- 不要求 `SIZE.cx` 与像素 ink bounds 严格相等;应比较同一 HDC/字体/状态下的 caret advance、裁剪安全性和相邻文本是否重叠。
|
||||
- 若 `DrawTextW` 使用特定 flags,应额外使用相同 flags 的 `DT_CALCRECT` 结果比较,不能把不同 API/flags 的结果强行等同。
|
||||
|
||||
### 4. DPI 与坐标空间
|
||||
|
||||
验证 EasyX 绘制坐标空间与 HWND 客户区坐标是否一致:
|
||||
|
||||
- 记录进程、线程和目标窗口的 DPI awareness context,以及 `GetDpiForWindow(hwnd)`。
|
||||
- 记录 EasyX 工作表面尺寸、HWND 客户区尺寸和窗口屏幕矩形。
|
||||
- 验证 EasyX 逻辑坐标是否等于 HWND 目标坐标,还是需要显式换算。
|
||||
- IMM 输入链只定义为:合成控件局部坐标 → EasyX 绘制坐标 → 目标 HWND 相对坐标 → `COMPOSITIONFORM/CANDIDATEFORM`。
|
||||
- 同时把目标 HWND 相对坐标换算为屏幕坐标,作为截图标注和诊断证据;屏幕坐标不是预设的 IMM 输入中间态。
|
||||
|
||||
规则:只有实测发现 EasyX 坐标空间与目标 HWND 坐标空间不一致时,才引入显式换算;否则直接使用,避免双重缩放。
|
||||
|
||||
验收预期必须服从实际 DPI awareness:
|
||||
|
||||
| Awareness | `GetDpiForWindow` 预期 | 跨屏预期 |
|
||||
|---|---|---|
|
||||
| DPI unaware | 96 | 不要求随显示器改变;记录系统虚拟化 |
|
||||
| System aware | 系统 DPI | 不要求随显示器改变;记录系统虚拟化 |
|
||||
| Per-monitor aware | 窗口所在显示器 DPI | 跨屏后应更新,并重新计算证据 |
|
||||
|
||||
如果实际 awareness 无法支持某项跨屏预期,该用例标记为 `not_available`,不能误判为坐标实现失败。
|
||||
|
||||
### 5. IME 定位证据
|
||||
|
||||
0C 发生在阶段 5 TextBox 自绘之前,因此不依赖真实 TextBox。探测 Fixture 必须提供以下合成 anchor:
|
||||
|
||||
```text
|
||||
anchor_top_left_safe
|
||||
anchor_center
|
||||
anchor_bottom_right_safe
|
||||
```
|
||||
|
||||
三个 anchor 均与屏幕边缘保留足够安全距离,用于区分框架换算错误和系统为避开屏幕边界进行的主动调整。
|
||||
|
||||
每个 anchor 记录:
|
||||
|
||||
```text
|
||||
controlLocalCaretTopLeft
|
||||
controlLocalCaretBottom
|
||||
controlLocalLineRect
|
||||
easyxSurfacePoint/Rect
|
||||
targetHwndRelativePoint/Rect
|
||||
diagnosticScreenPoint/Rect
|
||||
COMPOSITIONFORM 输入值与 API 返回值
|
||||
CANDIDATEFORM 输入值与 API 返回值
|
||||
```
|
||||
|
||||
测试至少覆盖微软拼音和搜狗输入法,并记录输入法标识、版本(可取得时)、HKL 和测试时间。不同 IME 可能主动调整位置或不显示独立组合窗口:
|
||||
|
||||
- API 返回成功不能代替视觉验收。
|
||||
- 组合窗口不存在但候选窗口可观察时,只验收实际存在的系统 UI,不把“未显示组合窗口”自动判失败。
|
||||
- 系统因避让屏幕边缘进行的调整应记录为 `system_adjusted`,不能直接归因于框架坐标错误。
|
||||
- 候选框/组合窗口实际位置必须截图并人工标注,不能只写“正常”。
|
||||
|
||||
阶段 6 再使用真实 TextBox 的 `caretTopLeft/caretLineRect` 重跑定位矩阵。0C 通过只证明坐标转换和 IMM 调用链可行,不证明 TextBox 自身 anchor 生成正确。
|
||||
|
||||
### 6. DPI 矩阵
|
||||
|
||||
基础矩阵:
|
||||
|
||||
```text
|
||||
显示缩放:100% / 125% / 150%
|
||||
跨屏:主屏 100% + 副屏 150%(或反向)
|
||||
IME:微软拼音 / 搜狗输入法
|
||||
anchor:top_left_safe / center / bottom_right_safe
|
||||
表面:主画面 / EasyX 工作图像
|
||||
```
|
||||
|
||||
执行时记录实际 awareness,并按 §4 的 awareness 规则确定预期。单显示器每档 DPI 至少验证一次两类表面和 center anchor;跨屏场景必须验证窗口完全位于每块显示器时的 DPI、坐标和候选窗口定位,窗口跨越两块显示器但未完成归属切换的瞬态只记录、不作为稳定验收点。
|
||||
|
||||
### 7. 自动与人工分层
|
||||
|
||||
- 自动检查:HDC/selected bitmap 身份、GDI 返回值、GDI 状态恢复、逻辑测量、目标/非目标表面像素摘要、DPI/坐标换算数值。
|
||||
- 必须人工观察:候选框/组合窗口的实际屏幕位置、字体缺字/回退外观、组合字符外观、跨屏拖动后的定位。
|
||||
|
||||
自动检查结果不能替代人工观察,人工观察也必须留下记录(截图 + 结论),不能只写“正常”。
|
||||
|
||||
### 8. 结果格式
|
||||
|
||||
使用独立的视觉/坐标结果格式,不并入 0A 键盘 JSONL schema。
|
||||
|
||||
建议输出:
|
||||
|
||||
```text
|
||||
TestResults/VisualProbe/<sessionId>/manifest-v1.json
|
||||
TestResults/VisualProbe/<sessionId>/evidence/*.png
|
||||
```
|
||||
|
||||
`visualProbeSchemaVersion` 初始为 1。manifest 必须包含:
|
||||
|
||||
| 字段 | 必需 | 说明 |
|
||||
|---|---:|---|
|
||||
| `visualProbeSchemaVersion` | 是 | 初始为 1 |
|
||||
| `sessionId` | 是 | 本次 0C 会话 UUID |
|
||||
| `startedAtUtc` | 是 | UTC 时间 |
|
||||
| `processId/threadId` | 是 | 进程和 GUI 线程 |
|
||||
| `osBuild/easyxVersion` | 是 | 能取得的运行环境版本 |
|
||||
| `testCaseId` | 是 | 矩阵中唯一用例 ID |
|
||||
| `testStringId/codePoints/utf16Units` | 绘制用例 | 固定测试串身份与实际构造结果 |
|
||||
| `surfaceId` | 绘制用例 | `main` 或指定 working image |
|
||||
| `hdc/hbitmap/hfont/logFont` | 绘制用例 | 表面和字体指纹 |
|
||||
| `gdiStateBefore/gdiStateAfter` | 绘制用例 | mapping、clip、颜色、对齐等 |
|
||||
| `apiResults` | 绘制用例 | 各 GDI API 的函数特定返回语义 |
|
||||
| `logicalExtent` | 绘制用例 | 相同 HDC/字体/状态下的测量结果 |
|
||||
| `targetPixelsBefore/After` | 绘制用例 | 目标区域摘要 |
|
||||
| `controlPixelsBefore/After` | 绘制用例 | 非目标表面未串画证据 |
|
||||
| `dpiAwareness/windowDpi` | 坐标用例 | 实际 awareness 与 DPI |
|
||||
| `clientRect/windowScreenRect/surfaceSize` | 坐标用例 | 坐标空间基线 |
|
||||
| `syntheticAnchorId` | 坐标用例 | 合成 anchor |
|
||||
| `anchorCoordinates` | 坐标用例 | local/surface/HWND-relative/screen 四组坐标 |
|
||||
| `compositionForm/candidateForm` | IME 用例 | 输入值、style、API 结果 |
|
||||
| `imeId/imeVersion/hkl` | IME 用例 | 输入法身份 |
|
||||
| `positionDisposition` | IME 用例 | `as_requested/system_adjusted/not_observable` |
|
||||
| `automatedStatus` | 是 | `pass/fail/inconclusive/not_available` |
|
||||
| `manualStatus` | 是 | `pass/fail/inconclusive/not_reviewed/not_available` |
|
||||
| `failureCategory` | 否 | 失败分类,不得只写自由文本 |
|
||||
| `evidenceFiles` | 是 | 相对路径、用途、SHA-256、裁剪区域 |
|
||||
| `notes` | 否 | 补充说明,不能替代结构化结论 |
|
||||
|
||||
截图只能包含探测窗口和固定非敏感测试内容;不得截取其他应用或真实用户输入。每个 evidence 文件记录 SHA-256,防止结果文件和图片错配。
|
||||
|
||||
`failureCategory` 只允许以下初始枚举;新增类别必须提升或兼容扩展 schema:
|
||||
|
||||
```text
|
||||
surface_unreachable
|
||||
surface_cross_write
|
||||
gdi_state_not_restored
|
||||
measurement_relation_invalid
|
||||
font_coverage_missing
|
||||
coordinate_transform_invalid
|
||||
ime_position_invalid
|
||||
awareness_not_supported
|
||||
evidence_missing
|
||||
```
|
||||
|
||||
`positionDisposition=system_adjusted` 不是自动失败。它必须结合安全 anchor 复测、截图和人工结论,最终落到 `manualStatus`。
|
||||
|
||||
示例只展示核心字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"visualProbeSchemaVersion": 1,
|
||||
"sessionId": "c73ab2ee-5f83-4d38-a253-58d1d775ca95",
|
||||
"startedAtUtc": "2026-10-02T08:00:00Z",
|
||||
"processId": 12000,
|
||||
"threadId": 12400,
|
||||
"testCases": [
|
||||
{
|
||||
"testCaseId": "gdi-working-cjk-150",
|
||||
"testStringId": "cjk_bmp",
|
||||
"codePoints": ["U+661F", "U+57A3", "U+7ED8", "U+5236", "U+6D4B", "U+8BD5"],
|
||||
"utf16Units": ["661F", "57A3", "7ED8", "5236", "6D4B", "8BD5"],
|
||||
"surfaceId": "working-image-1",
|
||||
"hdc": "0x0000000012345678",
|
||||
"hbitmap": "0x0000000087654321",
|
||||
"logicalExtent": {"cx": 144, "cy": 24},
|
||||
"targetPixelsBefore": "sha256:...",
|
||||
"targetPixelsAfter": "sha256:...",
|
||||
"controlPixelsBefore": "sha256:...",
|
||||
"controlPixelsAfter": "sha256:...",
|
||||
"dpiAwareness": "per_monitor_aware_v2",
|
||||
"windowDpi": 144,
|
||||
"automatedStatus": "pass",
|
||||
"manualStatus": "not_reviewed",
|
||||
"failureCategory": null,
|
||||
"evidenceFiles": [
|
||||
{"path": "evidence/gdi-working-cjk-150.png", "purpose": "target_crop", "sha256": "..."}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 9. 阶段门槛、失败判定与降级
|
||||
|
||||
| 结果 | 判定 | 后续动作 |
|
||||
|---|---|---|
|
||||
| W API 成功、目标表面变化、非目标表面不变 | 通过 | 阶段 5 可采用宽字符 GDI 路径 |
|
||||
| W API 失败或无法写入 EasyX 目标表面 | 阻塞 | 排查 HDC/selected bitmap/clip/state;确认宽字符路径确实不可用后才评估降级 |
|
||||
| 绘制成功但逻辑测量、caret advance 或裁剪关系异常 | 阻塞 | 排查字体、mapping mode、字符间距和 flags;不得直接降级 CP936 |
|
||||
| 某些 glyph 缺失但其他宽字符正常 | 字体问题 | 选择覆盖字体或字体回退;不得按编码问题降级 CP936 |
|
||||
| 坐标空间一致且当前 awareness 下定位正确 | 通过 | 使用目标 HWND 相对坐标,不额外缩放 |
|
||||
| 坐标空间不一致但换算规则经矩阵验证 | 条件通过 | 固化显式换算和适用 awareness,防双重缩放 |
|
||||
| awareness 不支持所测跨屏预期 | 不可用 | 标记 `not_available`,不当作实现失败 |
|
||||
| API 成功但候选框视觉位置异常 | 未通过 | 阻塞阶段 6,排查 anchor、坐标转换和 IME 差异 |
|
||||
| 系统因屏幕边界调整候选框 | 系统调整 | 记录 `system_adjusted`,在安全 anchor 复测后判定 |
|
||||
|
||||
CP936 只允许作为已证实宽字符绘制链无法使用后的显式显示降级;测量差异、字体缺字或单个 IME 定位异常都不是 CP936 降级依据。任何降级必须带证据并保留 UTF-16 内部原文。
|
||||
|
||||
## 实现与影响
|
||||
|
||||
- 关键实现点:
|
||||
- 当前只形成规格清单,尚未增加任何探测代码。
|
||||
- 实现时根据 Unicode scalar 列表构造固定测试串,使用合成 anchor、预定义采样区域和主/工作图像双表面哨兵,不依赖用户输入或真实 TextBox。
|
||||
- 实现结果由版本化 manifest 和独立 PNG 证据组成,不复用 0A 键盘 JSONL schema。
|
||||
- 涉及文件 / 类 / 函数:
|
||||
- 预计观察现有 `Window`、EasyX 工作图像和 GDI 调用链。
|
||||
- 具体文件名必须在实现前只读检查后确定,本规格不授权修改框架代码。
|
||||
- 兼容性影响:
|
||||
- 探测关闭时不应产生文件、线程、定时器或公共 API 变化。
|
||||
- 性能影响:
|
||||
- 仅测试构建开启,对正式路径无影响。
|
||||
- 风险点:
|
||||
- 视觉结论依赖人眼,必须与表面指纹、目标/非目标像素摘要和截图证据相互印证。
|
||||
- 跨屏 DPI 依赖真实多显示器环境,CI 环境可能不具备,需人工实测。
|
||||
- HDC handle 可能复用,若不同时记录 selected bitmap 和 GDI 状态,可能得到错误的表面身份结论。
|
||||
- IME 可能主动调整候选窗口,必须在安全 anchor、不同 IME 和实际 awareness 下区分系统调整与框架换算错误。
|
||||
|
||||
## 测试与验证
|
||||
|
||||
- 测试范围:
|
||||
- 当前仅验证规格完整性,探测器未实现。
|
||||
- 验证步骤:
|
||||
|
||||
1. 实现前只读定位 EasyX `SetWorkingImage`、主画面/工作图像 HDC、selected bitmap 和 GDI 调用位置。
|
||||
2. 实现 0C 后,根据明确码点构造固定测试串,使用双表面哨兵验证目标表面变化、非目标表面不变和 GDI 状态恢复。
|
||||
3. 使用合成 anchor,在实际 DPI awareness 下完成 100%/125%/150%、跨屏、微软拼音和搜狗矩阵,保存结构化 manifest 与截图证据。
|
||||
4. 依据 §9 分别判定宽字符链、测量链、字体覆盖、坐标换算和 IME 定位;禁止把不同失败类型合并成 CP936 降级。
|
||||
5. 阶段 6 使用真实 TextBox anchor 重跑坐标与 IME 定位集成验证。
|
||||
|
||||
- 验证结果:
|
||||
- 截至 2026-10-02,仅完成规格评审意见并入与文档归档,未执行任何绘制或坐标探测。
|
||||
- 已知限制 / 遗留问题:
|
||||
- 跨屏不同 DPI 结论依赖实机环境。
|
||||
- 字体回退行为与 EasyX 字体设置的耦合需要实测确认。
|
||||
- 0C 使用合成 anchor,只验证坐标转换和 IMM 调用链;真实 TextBox anchor 必须在阶段 6 复验。
|
||||
- 某些 IME 不显示独立组合窗口或会主动调整候选框,允许用例得到 `not_available`、`system_adjusted` 或 `inconclusive`,但必须保留证据。
|
||||
|
||||
## 落地信息
|
||||
|
||||
- 关联功能变更 ID:无
|
||||
- 关联 BUG / Fix:无
|
||||
- Commit:无实现提交(本文件仅归档 0C 规格;0C 探测器尚未实现)
|
||||
- PR:无
|
||||
- 发布版本:未发布
|
||||
- 相关文档:
|
||||
- [`Module-20261001-0001-通用输入焦点与键盘路由系统设计.md`](./Module-20261001-0001-通用输入焦点与键盘路由系统设计.md)
|
||||
- [`Module-20261001-0002-阶段0A输入链路被动探测规格.md`](./Module-20261001-0002-阶段0A输入链路被动探测规格.md)
|
||||
- [TextOutW](https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-textoutw)
|
||||
- [DrawTextW](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-drawtextw)
|
||||
- [GetTextExtentPoint32W](https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-gettextextentpoint32w)
|
||||
- [GetCurrentObject](https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-getcurrentobject)
|
||||
- [SaveDC](https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-savedc)
|
||||
- [RestoreDC](https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-restoredc)
|
||||
- [GetDpiForWindow](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpiforwindow)
|
||||
- [GetWindowDpiAwarenessContext](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowdpiawarenesscontext)
|
||||
- [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