Jia Sui and fanlusky
3b1206ea82
fix(windows,engine): 提交键回复等待不再因超时重置会话或丢字 ( #1019 )
...
* fix(windows,engine): 提交键回复等待不再因超时重置会话或丢字
服务端按键处理偶发数百毫秒尖峰时,提交键(空格顶首选 / 确定选词 / 标点顶高亮候选)
的回复等待会走到会话内那条 300ms 同步读;一超时就被判成 TransportUnavailable
→ DeliveryAmbiguous → Transport 完整重置(丢键 + 吞队列 + 清组合 + 轮换 epoch),
用户看到的是整段已输入内容消失。
- 删除 FANY_IME_COMMIT_REPLY_SESSION_WAIT_MS 那条破坏性兜底读。会话侧改为非阻塞探测,
拿不到回复返回「未就绪」,由 session 自身在 DoEditSession 内交回,沿用同一个
FANY_IME_COMMIT_REPLY_TIMEOUT_MS 分片轮询窗口,不重开窗口、不新造等待原语。
- 交回必须发生在 session 内部:RequestEditSession 用 TF_ES_ASYNCDONTCARE,TSF 异步授权
时调用方读不到 session 的 HRESULT;若靠调用方读返回值,该键会既不丢也不提交,
deferred 闸门再不打开(后续按键全部只入队)。也不能改用 TF_ES_SYNC(WinWord 上不成立)。
- 真失败(写失败 / 读失败 / 坏帧 / 字节数不符 / 无 request id / 无管道)仍判 Transport 重置。
- 预取覆盖面扩到 candidate 类 finalize(空格顶首选等),堵住原先只能靠那条 300ms
兜底读的路径。
- 新增按键级延迟诊断 bench_key_latency_diag(build 里有同名 exe 但源码已不在树),
以及两份对照测试:commit_reply_not_ready(回复三态与交回状态机)、
candidate_consistency(同配置下候选集合/顺序/分页逐字一致,引擎侧护栏)。
实测(bench_key_latency_diag):稳态逐键 median 0.6~0.8ms / max 12.5ms,尖峰指向内存
压力下的页回收而非稳态算力。在「结果完全不变」的约束下,预热 / 缓存 / 投机预解码均无效
或反向,故本次不改引擎打分路径。
* fix(windows): 直接标点提交会话补齐未就绪交回,并写准窗口沿用边界
审查 `7aca5e5d` 发现的问题:
- `CPunctuationCommitEditSession` 在 `FANY_S_COMMIT_REPLY_NOT_READY` 时只抑制了 token
结算(`applied` / `_FailDeferredKey` 都不走),**没有**像 `CKeyHandlerEditSession` 那样把
请求交回 `_PollCommitReply`。一旦走到这条分支——`_HandleCompositionPunctuation` 的高亮候选
分支要求 `_candidateMode != CANDIDATE_NONE`,而派发该会话的条件是
`_candidateMode == CANDIDATE_NONE`,两者在 session 执行时才求值——deferred token 会永久留在
飞行中,后续所有按键只入队不处理,正是本 PR 在别处修掉的失效模式。现在两处都交回,
并把原因写进注释,避免下一个人再照半个写法抄一遍。
- `_HandOffUnreadyCommitReply` 的两处注释与实现不符或不够具体:交回沿用第一片已经开始的窗口;
只有从未开窗的路径(标点处理函数在派发时高亮候选条件为假、session 执行时条件成立)才在此
开窗,那种情况键一点没等过、`waitedMs` 为 0。另一支(无法保活 → `_FailUnansweredCommitKey`)
只在请求不属于协作轮询时到达,实务上即 `commitReplyMessage == 0`:派发没能用消息窗,
没有可交回的对象。
签名相应扩展:`_RequestDirectPunctuationEditSession` 新增 `commitReplyMessage` /
`commitReplyDeadlineTick`,`CPunctuationCommitEditSession` 携带它们。没有行为回退,两个新参数
默认 0 时与改动前一致(而那正是「无消息窗」的既有降级路径)。
验证:windows x64 Release 构建通过,`ctest` 17/17 通过,`clang-format 18.1.8 --dry-run
--Werror --style=file` 对本次涉及文件全过。
* fix(windows): 把 _HandOffUnreadyCommitReply 移到公共区,修 CI 编译失败
CI 的 Windows x64 与 Windows Win32 两条腿都挂在同一处编译错误:
MetasequoiaIME_AsyncRequests.cpp: error C2248:
“CMetasequoiaIME::_HandOffUnreadyCommitReply”: 无法访问 private 成员
上一提交给 CPunctuationCommitEditSession 补「未就绪交回」时调用了这个成员,但它在 private
区。CKeyHandlerEditSession 能调是因为它在 MetasequoiaIME.h 里被显式声明为 friend;而
CPunctuationCommitEditSession 定义在 MetasequoiaIME_AsyncRequests.cpp 的匿名命名空间里
(该文件 31-254 行),头文件里的 friend 声明指不到它,加 friend 也无效。
处置:把该声明移到公共区,与同样由 session 调用的 _FailDeferredKey、_CompleteDeferredKeyReplay、
_HandleCompositionPunctuation 并列,并在注释里写明「它必须公共」的原因,免得下次有人顺手挪回私区。
仅可见性与注释,行为零变化。
验证(triplet 与 CI 一致,且这次看退出码、不截断构建输出):
- x64-windows-static:cmake --build build --config Release --parallel 退出码 0;
ctest --no-tests=error 17/17。
- x86-windows-static:cmake --build build32 --config Release --parallel 退出码 0;
ctest --no-tests=error 17/17。
- clang-format 18.1.8 --dry-run --Werror --style=file 对本次改动文件通过。
另:上一轮「构建通过」是我误报——当时用 Select-String 过滤构建输出又加了 -Last 8,错误行被截掉,
且没有检查 $LASTEXITCODE;ctest 过的是测试目标,与 DLL 编译失败并不冲突。
* fix(windows): 提交回复交回后轮询不再停摆,同步兜底保留有界等待
- 轮询定时器按请求 id 判断是否仍在等待:session 交回时换了新 token,
按旧 token 查会误判为已结算并 KillTimer,交回的请求从此无人再分发。
- 没有轮询可交回的 session(同步 _InvokeKeyHandler 路径)恢复
FANY_IME_COMMIT_REPLY_SESSION_WAIT_MS 的单次有界等待,不再一读不到就丢键重置。
- 确定并输入在提交回复为传输失败时不再继续键入字符并返回 S_OK。
- session 交回占用新槽位时同样受 kMaxPendingAsyncKeys 约束。
- 修正注释:未就绪由 session 自己的完成钩子交回,不是消息处理函数。
- 测试:覆盖轮询分发、等待上限与满表交回;SAL 剥离按最长前缀匹配;
引擎一致性用例③不再清缓存,否则测不到跨输入的缓存泄漏。
---------
Co-authored-by: fanlusky <1730976608@qq.com >
2026-10-17 16:19:26 +08:00
Lu Fan(SonnyCalcr)
1b875267db
refactor: 移除 WebView2,界面只保留 Direct2D ( #1013 )
...
* refactor(engine): 语音独立工具改用原生托盘菜单,移除 WebView2
托盘菜单改用 Win32 弹出菜单,设置项改为用关联编辑器打开 config.toml,关于页改为消息框。删除 window_webview2 与两份 HTML 资源,windows-app 特性不再依赖 webview2 端口。
* refactor(server): 移除 WebView2,候选窗、工具栏、托盘菜单与设置窗口只保留 Direct2D
删除 src/webview2 与 webview_utils,小窗口的置顶、皮肤重载和工具栏状态缓存移到 window/small_windows,presenter 成为唯一路径,D2D 下的置顶时序与 cloak 行为保持不变。设置进程去掉 WebView2 宿主、鼠标转发与启动图,只构建原生窗口;旧快捷方式传入的 --d2d / --webview2 被忽略。删除 appearance.ui_backend 与 appearance.settings_ui_backend(读取、写入、设置页下拉框与两份配置模板),升级时由模板合并丢弃旧值。设置窗口的图片资源移到 server/assets/settings,安装到数据目录的 assets\settings。不再链接 WebView2Loader,vcpkg 去掉 webview2 端口。
* build(installer): 打包与 CI 不再处理 WebView2 页面和运行时
Prepare-PackageFiles 去掉 -UiHtmlDirectory 与 html 暂存,改为暂存 server/assets/settings;安装器不再检查 WebView2 Runtime、不再创建 ProgramData 下的 WebView2 用户数据目录,升级和卸载时清理旧版留下的 webview2 / webview2-settings 与数据目录里的 html。CI 删除设置页构建、契约同步检查和候选窗 DOM 测试,release 的打包任务不再依赖网页产物;dependabot 去掉 npm。第三方声明去掉 WebView2Loader。
* refactor(ui-html): 删除 WebView2 页面与设置页前端工程
候选窗、工具栏、托盘菜单、设置页、主题和契约副本都已没有使用者;设置窗口用到的图片资源已移到 server/assets/settings。sync-contracts.py 与 pnpm/Vite/TypeScript 工程一并删除,契约仍以 engine/contracts/webview 为唯一来源。
* docs(server): 文档改为只描述 Direct2D 界面
仓库地图去掉 ui-html,组件边界、uiAccess 与置顶时序、设置窗口和配置读写的说明改写为 Direct2D 唯一界面;安装说明去掉 WebView2 Runtime 检查,打包命令去掉 -UiHtmlDirectory;engine/contracts/webview 的说明改为设置窗口是唯一使用者,名字是历史遗留。
* docs(skins): 皮肤说明不再区分 WebView2 与 D2D 渲染器
v2 字段去掉「仅 WebView2」,改为说明由 Direct2D 原生渲染、部分字段仍在补全;颜色必须带 # 改为清单格式约定。随包的 skins/niya-demo/skin.toml 不改,免得用户机器上的同名皮肤在升级时被当成已修改而改名备份。
* docs(ui): demo 说明文字不再提 WebView2
2026-10-17 02:48:02 +08:00
Jia Sui and fanlusky
9beab473f4
fix(windows,server): 提交键慢响应改为分片让出等待,不再丢字或冻结宿主 ( #982 )
...
* fix(windows,server): 提交键慢响应改为分片让出等待,不再丢字或冻结宿主
* fix(windows): 提交回复轮询不阻塞宿主,补齐标点顶候选路径并保持结算顺序
- 标点顶高亮候选(WM_AsyncPunctuationCommit 无预取文本)也在处理函数里分片取回复,
edit session 不再在宿主 UI 线程上阻塞 300 ms
- 轮询改为不阻塞:先查缓存、PeekNamedPipe,有帧才以零超时读,不再每片阻塞 16 ms
- 定时器只重派已开始等待的请求,按请求 id 升序结算,较新的提交排在仍在等的旧提交之后
- 处理函数取到 TransportUnavailable 时直接按歧义丢键并重置,不再交给 edit session
- 已在等回复的提交键在同一焦点下被组合纪元取代时按 DeliveryAmbiguous 处理,避免两端分叉
- 回复缓存淘汰不再淘汰刚写入的条目;CachePendingReply 与提交回复缓存共用一份逻辑
- 停用时显式 KillTimer(TIMER_COMMIT_REPLY_POLL);windows/AGENTS.md 同步新的提交预算
---------
Co-authored-by: fanlusky <1730976608@qq.com >
2026-10-16 02:48:58 +08:00
Lu Fan(SonnyCalcr)
e46294308d
fix: CS2 / Dota 2 / 三角洲行动等游戏里的输入法兼容(加载、候选、翻页、独占全屏、启动崩溃) ( #925 )
...
* fix(installer): TSF DLL 改装到系统目录,CS2 等 Trusted Mode 游戏里可以切出输入法
CS2 的 Trusted Mode 只放行位于系统目录且有代码签名的第三方 in-proc DLL,
装在 Program Files 下的 DLL 会被拒绝加载,游戏里切不出输入法。
x64 DLL 改装到 System32\IME\MetasequoiaIME\msime_v*,x86 装到 SysWOW64 下同名目录,
语言配置图标随之放到两处根目录;升级时清掉旧版留在 Program Files 的版本目录。
* fix(windows): CS2、Dota 2 不理会 UI-less 声明,照常显示候选窗
起源 2 引擎的 Valve 游戏以 UI-less 激活 TSF,但只替白名单里的输入法绘制候选。
我们据声明收起了自己的候选窗,游戏又不画,结果只剩左上角的系统默认 IME 小框,只能盲打。
对 cs2.exe、dota2.exe 忽略 UI-less,照常由 Server 绘制候选窗。
* fix(server): 前台为 D3D 独占全屏时不弹候选窗与光标状态提示
独占全屏下别的进程的窗口画不上去,弹出去反而可能把游戏踢出独占模式(闪黑、切分辨率、卡死)。
在 UI 线程真正显示前用 SHQueryUserNotificationState 判一次(300ms 缓存),独占全屏就收起候选窗,
并清掉已渲染可见标记,数字键与空格选词不再等待不会到来的绘制。
* fix(engine,server,windows): 游戏自绘候选时后台改动的候选列表实时同步给宿主
英雄联盟等 UI-less 宿主自己画候选。云候选、AI 候选、模型重排、英文混排在按键回复之后才改
候选列表,却从不通知 DLL,游戏还画着上一键读到的旧列表,数字键和空格却按新列表上屏,
于是「选的和上屏的不一样」。
- 契约新增 Worker opcode 35 UiLessCandidatesChanged,载荷与 UiLessComposition 同形,
由 uiless_page.h 统一格式化与解析,并附候选页代号;旧 DLL 读选中位时在第三个制表符处停下,兼容。
- Server 在上述后台改动之后把新页推给候选归属的客户端。
- DLL 收到后回到 TSF 线程核对焦点与组合纪元,更新候选 UI 元素并通知宿主重读。推送与按键回复
走不同管道,按代号只接受不旧于当前的页,避免旧页盖掉新页。
- 从共享内存重读到不同的页时高亮回到第一项,与 Server 每次重建都选中首项一致,
不再保留旧高亮造成「高亮这个、空格上屏那个」。
* feat(windows,server,ui-html,installer): 游戏兼容开关,CS2 / Dota 2 独占全屏打字不再黑屏
CS2、Dota 2 只替内置白名单(按输入法登记名称全等比对)里的输入法处理输入法消息。不在名单里时
组合落到 Windows 默认组合窗 CiceroUIWndFrame,左上角弹出编码小框;独占全屏下这个窗口一出现
游戏就被踢出全屏,表现为一打字就黑屏。清风输入法未开兼容时同样如此。
- 设置页帮助页新增「游戏兼容(CS2 / Dota 2)」:开启后把水杉在系统里登记的名称换成白名单里的
名字(默认「拼音输入法」),游戏会自己画候选。需要管理员权限:设置进程以
--apply-game-compat-name 提权重启自身,写 HKLM 记录值并改语言配置的 Description。
- TSF DLL 注册时以记录值为准,安装/升级重新注册不再把用户选的名称冲掉;卸载时删除记录值。
- 开启时不再对 cs2.exe / dota2.exe 忽略「宿主自己画候选」的声明,避免两个候选框。
- Server 的独占全屏判断覆盖进出独占模式时的 QUNS_BUSY 间隙,不在切换途中弹候选窗。
- TSF 诊断日志在组合开始/结束与 BeginUIElement 时记录宿主窗口状态(只有窗口与标志,没有文本)。
* fix(windows): 后台刷新回调持有加载器引用,宿主卸载 TSF DLL 后不再崩溃
当前输入法是水杉时,CS2 启动途中会加载再卸载 TSF DLL。诊断日志的线程池回调
FlushTsfDiagnosticLogs 正在 Sleep(250),只靠 DllAddRef 撑着:那只回答 DllCanUnloadNow,
挡不住宿主直接卸载。DLL 卸载后 SDL3 映射进同一段地址,回调醒来跑进 SDL3 的代码,
游戏崩溃(0xc0000005,崩溃转储里卸载模块的地址范围与崩溃地址吻合)。
- 诊断日志与统计上报的线程池回调改为用 GetModuleHandleEx 取加载器引用,
回调里 FreeLibraryWhenCallbackReturns,函数完全返回后才放手。
- 析构函数把 DllRelease 挪到最后,不在等待 IPC 线程退出之前就让 DLL 可卸载。
* fix(windows): 游戏自绘候选时不再把 Server 的 HTML 候选页当成候选交给游戏
CS2 开了游戏兼容后打一个码,游戏里的候选只有一项且是乱码。宿主要等 BeginUIElement 才说
自己画候选,而那时组合首键已经不带 UI-less 标记发给了 Server;Server 往共享内存写的是给
自己候选窗用的 HTML 页(辅助码、译文 span),DLL 的候选元素从共享内存回读后整串交给了游戏。
- 开了游戏兼容名称的 cs2.exe / dota2.exe 在 ActivateEx 就认定由游戏画候选,每个按键都带标记。
- 候选会话里收到过 Server 的 UI-less 页之后才从共享内存回读,之前一律不读。
* fix(windows): 游戏自绘候选时翻页能刷新,部分上屏后不再出现乱码候选
三角洲行动(虚幻引擎,以 TF_TMF_UIELEMENTENABLEDONLY 激活)里按 = / - / PageUp / PageDown
翻页,Server 已翻到第 N 页,游戏却还画着第一页;接着按空格上屏的是第 N 页的首项(多为单字),
剩下的拼音继续组合时候选框里出现乱码。
- 翻页、移高亮等键走异步的 WM_AsyncServerCandidateKey,以前把回复当作「只是确认」丢掉;
UI-less 下这份回复就是新的候选页,现在应用并通知宿主重读。
- UI-less 的 _SetText 拿不到 Server 的候选页时不再退回本地引擎的占位列表——那不是候选,
宿主会画成一条乱码。部分上屏后从共享内存回读 Server 写好的新页;_ClearList 同时清掉上次
的页记录,页文本相同也会重新载入。
2026-10-13 21:58:15 +08:00
fanlusky
371d651a40
fix(windows,installer): 输入法语言配置图标改用固定路径,升级后任务栏不再显示「简体」
...
TSF DLL 每次升级都装进新的 msime_v* 版本目录,语言配置注册的图标指向 DLL 自身,
注册表里的图标路径随之每次变化。任务栏恰好在换目录时取不到图标,就改显示「简体」文字,
并一直沿用到资源管理器重启。
- 安装器把 windows/image/msime.ico 装成 Program Files 与 Program Files (x86) 下
metasequoiaime\MetasequoiaImeTip.ico,排在 TSF DLL 的 regserver 条目之前
- RegisterProfiles 发现 DLL 上一级目录有这个文件就注册它(索引 0),否则退回 DLL
内嵌的 IDIS_METASEQUOIAIME,开发时从 build 目录注册不受影响
- 打包脚本收集并断言该图标;打包测试检查两份都装、且先于 DLL 安装
2026-10-12 04:20:17 +08:00
Jia Sui
2557ee4a63
docs: 修正 AGENTS.md 与注释中与代码不符的五处描述
...
spec 校对时逐条核对「文件:行号」锚点发现,五处文档描述与代码现状不符:
- windows/AGENTS.md:格式化遵循的是本目录 .clang-format,仓库没有根目录 .clang-format
- 根 AGENTS.md:engine/... 前缀 include 只对 server/ 成立,windows/ 无仓库根,走相对路径
- scripts/format.sh:注释声称 CI 会跑 generate.py --check,实际没有任何 CI 作业调用
- server/AGENTS.md:测试源文件数与三处行号锚点过期
- server/CMakeLists.txt:注释里的 "eleven add_test()" 实际是 24 个,删去具体数字
纯文档与注释改动,无行为变化。
2026-10-03 08:29:50 +08:00
fanlusky
482e43c38e
docs(windows): 按新的失败模型改写 AGENTS.md
...
去掉对按键回放、恢复前缀和「DeliveryAmbiguous 不能无条件本地重放」的描述,
新增「按键失败:不回放」一节:被吃掉的键要么处理、要么有意吞掉,绝不交还宿主、
绝不处理两次;失败时清组合、吞队列,从空开始。列出 Stale / Resync / Transport /
Offline 四类失败的来源与动作,说明新增失败点应走 _FailDeferredKey /
_ResetSessionAfterFailure 而不是单独调用 MarkNamedpipeSessionDirty*,以及翻页和
高亮移动键回复缺失是软错过。并注明派发 token 在代码里仍叫 deferredReplayToken。
2026-09-27 19:06:40 +08:00
fanlusky
a3739fc528
refactor(windows): 按职责拆分 MetasequoiaIME.cpp
...
MetasequoiaIME.cpp 有 3000 多行,激活/停用生命周期、按键路径的 edit
session 请求、Worker Pipe 读线程和消息窗口处理全挤在一个文件里。按职责
拆成以下几个翻译单元:
- MetasequoiaIME.cpp:Server 拉起辅助、CreateInstance、构造/析构、焦点
会话与 composition epoch 校验、本地会话重置、候选 presenter 延迟清理、
QueryInterface/AddRef/Release、ActivateEx/Deactivate、
_WakeServerIfNeeded/_NoteKeyEventIpcFailure 和 ITfFunctionProvider 系列
- MetasequoiaIME_AsyncRequests.cpp:标点、智能标点、延迟应用文本几个
edit session 及其 _Request*EditSession,待取的 Server 候选,异步按键
请求表(_PostAsyncKeyRequest/_TakeAsyncKeyRequest/_ClearAsyncKeyRequests)
和 _ClearPendingIpcRequests
- MetasequoiaIME_IpcWorker.cpp:IpcWorkerThread,以及把它收到的上屏、
语音快照和 compartment 切换交给 TSF 线程的令牌表
- MetasequoiaIME_WindowProc.cpp:CMetasequoiaIME_WindowProc 及其用到的
状态快照发送、CommitCandidateAndContinue edit session,还有主题注册表
监听与语言栏图标刷新
- MetasequoiaIMEInternal.h:上述文件之间共享的声明,只给
MetasequoiaIME*.cpp 包含
纯搬移,不改行为:函数体、注释和格式都没动。原来在匿名命名空间里、现在
要跨文件用的 NextWindowMessageToken 仍定义在 MetasequoiaIME.cpp,改放进
metasequoia_ime_detail 命名空间并在内部头文件里声明;
CONNECT_NAMEDPIPE_RETRY_INTERVAL_MS 常量挪进内部头文件的同一命名空间。
只被一个文件用到的仍留在该文件的匿名命名空间。_bareShiftHookOwner 这个
thread_local 和 #pragma comment 仍只在 MetasequoiaIME.cpp。没有新增全局
构造器或函数内静态变量。
用脚本比对了原文件与拆分后全部文件的非空、非 #include 行多重集:没有缺
失的行,差异只有新增的声明、命名空间包装、using 指令、#pragma once 和文
件头注释。可用 git diff --color-moved 复核。
2026-09-27 17:39:11 +08:00
fanlusky
9c1c4b82b2
refactor(windows): 按职责拆分 KeyEventSink.cpp
...
KeyEventSink.cpp 有 3100 多行,同步按键判定、延迟按键队列与回放、输入模式
热键全挤在一个文件里。按职责拆成以下几个翻译单元:
- KeyEventSink.cpp:_IsKeyEaten、ConvertVKey、_IsKeyboardDisabled、退格
长按与 CapsLock 处理、直通字符统计,以及 ITfKeyEventSink 各回调
(OnSetFocus、OnTestKeyDown、OnKeyDown/_DispatchKeyDown、OnTestKeyUp、
OnKeyUp、OnPreservedKey/_DispatchPreservedKey)和 sink 的注册/注销
- KeyEventSink_DeferredKeys.cpp:延迟按键屏障与容量、预测状态投影、恢复
前缀、_ClassifyDeferredKeyDown,以及入队、清空、完成、重试、丢弃歧义键、
排空调度和 Server 不可用回退
- KeyEventSink_Hotkeys.cpp:mintty 的裸 Shift 键盘钩子、裸修饰键武装、
组合键与修饰键松开热键匹配、_QueueInputHotkey
- KeyEventSinkInternal.h:上述文件之间共享的声明,只给
KeyEventSink*.cpp 包含
纯搬移,不改行为:函数体、注释和格式都没动。原来在匿名命名空间里、现在
要跨文件用的函数(SegmentEditFunction、CaptureIpcModifiers、
IsEnglishInputModeToggle、IsTranslationCommitShortcut、
IsCharacterSetInputModeToggle、PostOwnerMessageWithSyncFallback、
IsShiftVk)仍定义在 KeyEventSink.cpp,改放进 key_event_sink_detail 命名
空间并在内部头文件里声明;只被一个文件用到的仍留在该文件的匿名命名空间。
THIRDPARTY_NEXTPAGE/THIRDPARTY_PREVPAGE 宏和本来就是 inline 的
VKeyFromVKPacketAndWchar 原样挪进内部头文件。唯一的非搬移改动是
PostOwnerMessageWithSyncFallback 的默认实参从定义挪到了头文件里的声明上。
没有新增全局构造器或函数内静态变量。
用脚本比对了原文件与拆分后全部文件的非空、非 #include 行多重集:除上述
函数签名外,差异只有新增的声明、命名空间包装、using 指令、#pragma once
和文件头注释。可用 git diff --color-moved 复核。
2026-09-27 17:38:47 +08:00
fanlusky
a7779d2b05
refactor(engine): 将 engine 从 submodule 内嵌为仓内一等组件
...
`vendor/MetasequoiaImeEngine` submodule 改为 `engine/` 目录,导入的是
product-lock.json 原本钉住的提交 c810d201,逐文件核对过 blob,因此这是一次
搬迁而不是引擎升级。引擎自己的嵌套 submodule(googlepinyinime-rev、utfcpp、
miniaudio)按各自 gitlink 一并展开,来源与提交见 engine/UPSTREAM.md。
Windows 专门化裁掉了不属于本产品的部分:whisper.cpp 与本地推理 provider、
macOS 示例宿主、整个 dictionary/ 建库流水线、上游 CI 与 release-please 配置。
词库仍按 product-lock.json 在构建时取发布产物。
引擎不再进 product-lock.json:没有 gitlink 就没有可比对的东西,锁里写一个上游
commit 等于宣称这棵树仍等于上游,而第一个 Windows 专门化改动落地时这句话就假了。
verify-contracts / verify-checkout 随之移除,verify-published 保留。
CI 与工具链:引擎源码并入根 scripts/format.sh(删掉引擎自己的那份,避免两套排除
列表分叉);引擎 voice.yml 里的 silero_vad.onnx 摘要校验移到本仓 lock job;
engine-bump-triage 工作流与其测试删除;gitsubmodule 的 dependabot 频率由 daily
改为 monthly。
README、README.en、AGENTS.md、CONTRIBUTING、docs/product-release.md 及各子目录
文档同步说明新的位置与边界。
2026-09-12 03:40:48 +08:00
Evan Hu
b2d736cd79
fix(build): finish local tooling migration to the monorepo
2026-09-06 09:02:13 +09:00
Evan Hu
05036a763d
docs: describe one repository instead of six
...
The product README was under windows/ after the move, but it was never a component readme: it is the download page, the feature guide and the contribution guide for the whole product, so it goes back to the root and windows/ gets a real component readme.
AGENTS.md at the root now carries the repository map, the component boundaries that used to be cross-repository rules, and the release process, since the scripts that process drives live at the root. The component files keep what is genuinely theirs and say which paths they are relative to. References that named sibling repositories now name sibling directories, and the lock documentation records that Server, the pages, the GUI framework and the installer are no longer inputs to pin.
2026-09-06 02:40:51 +09:00
Evan Hu
253b068984
refactor: move the Windows TSF frontend under windows/
...
Preparation for folding Server, UI, UiHtml, Installer, ImeLog and TsfEditControl into this repository. The Windows tip's own sources, build files and local build scripts move under windows/ so every component sits at the same level. Product-level files stay at the root: the lock, the release manifest, the shared CI scripts, the integration tests, the docs and the Engine submodule.
2026-09-06 02:24:27 +09:00