Lu Fan(SonnyCalcr)
c0a9d371f0
feat(server,windows,engine): 横排候选时左右方向键移动高亮 ( #1080 )
...
- 快捷键页「翻页方式」新增「左 / 右(横排时移动候选项)」,与「上 / 下」各自独立,默认关闭,
只在候选窗为横排时生效。配置项 general.candidate_horizontal_arrow_navigation 已写入出厂模板。
- 光标在拼音串尾时右键移动高亮(到页末翻页),左键往回移高亮,高亮回到第一个候选后再按才移动光标;
光标在串中间时右键先把光标移回串尾,再按才移动高亮。Ctrl+左/右与 UILess 宿主不变。
- 新增 worker 消息 HorizontalArrowSelectionChanged(39)和按键标记 FanyImePipeFlags::HorizontalArrowSelection:
开关生效时 TSF 把候选态下的左右键交给 Server 决定,移光标时 Server 用 CompositionRestored 回光标,
移高亮时回 MoveSelection*,TSF 不再自己预测光标。旧 DLL 忽略新消息,保持原行为。
Closes #779
Closes #895
2026-10-19 02:11:25 +08:00
Lu Fan(SonnyCalcr)
75d8c710a9
feat(server,windows,engine): 新增顿号自定义,翻页方式移到快捷键页 ( #1071 )
...
- 设置「输入」页在智能标点上方新增「顿号自定义」:\ 和 / 各一个勾,至少保留一个,
未勾选的键按原样输出。新装默认两个都开;升级用户的配置里没有 / 这一项,
模板合并时补成关,保持原来只有 \ 出顿号。
- 新增 worker 消息 EnumerationCommaKeysChanged(38),载荷见
engine/contracts/enumeration_comma.h;旧 DLL 忽略它,保持只用 \。
- 选候选时按 / 改为按配置上屏「候选 + 、」;未作顿号的 \ 或 / 跟在候选后原样上屏。
小键盘 / 与小键盘 . 一样始终输出原字符。
- 「翻页方式」从「输入」页移到「快捷键」页。
- AtLeastOneChecks 从辅助码页移到公共绑定,两页共用。
2026-10-18 23:49:41 +08:00
Lu Fan(SonnyCalcr)
5de73de7a6
feat(engine,server,windows): 双拼末尾辅助码支持间接触发,句中辅助码单独成区 ( #1068 )
...
双拼辅助码新增「直接辅助码」开关(默认开,行为不变)。关掉后末尾辅助码改由引导键触发:
反引号、分号、大写字母可多选,触发键后接一到两个辅码(如 ulpb;xy、ulpbXy),一码重排、
两码筛选,只在输入末尾生效。触发键在 TSF 缓冲与 Server raw 里统一记成 |,与句中辅助码的
反引号段区分。
两组触发键互斥:一边勾上某个键会取消另一边的同一个键;手改配置两边都勾时归句中辅助码。
新增 Worker 消息 EndHelpcodeTriggersChanged(37),旧 DLL 忽略。
设置页把句中辅助码单独成区(仅双拼),其中间接(引导键)与直接(万象式)两种方式互斥。
新配置项同时写进出厂模板与开发配置。
2026-10-18 22:54:17 +08:00
6072ae7784
fix(windows): 修复临时日语 R 模式无法输入长音符 ( #1000 )
...
* fix(windows): 修复临时日语 R 模式无法输入长音符
* fix(server,windows): 临时日语策略每键只算一次,并去掉多余的帧
- Server 在 HandleImeKey 开头按本次按键所属客户端算一次策略,不再每个谓词都查活动客户端、加锁、构造 payload 再解析回来。
- 普通激活只补发 TemporaryJapanesePolicyChanged;整套输入模式状态(含语言栏刷新)仍只在 FocusRestored 时发送。
- 配置重载时输入方案变了由 ApplyConfiguredInputScheme 统一广播,不再重复广播策略。
- TSF 的 WaitForProtocolReady 不再清零策略:worker 管道先于 Main 注册,可能已收到本次连接的策略;断开时已有清零路径。
---------
Co-authored-by: ranly <ran618ly210805@qq.com >
Co-authored-by: fanlusky <1730976608@qq.com >
2026-10-16 22:30:28 +08:00
chr331 and fanlusky
1c3bd7cb83
feat(server,ui-html,windows): 支持自定义“输入状态切换”中的快捷键 ( #985 )
...
* fix(windows): 支持标点切换快捷键改绑与取消绑定
* fix(shortcut): 对齐虚拟键并处理语音与窗口快捷键冲突
* fix(ui-html): 绑定标点快捷键前提示应用快捷键占用
* fix(ui-html): 仅对已知快捷键冲突提示确认
* feat(shortcuts): 支持自定义输入状态切换快捷键
* fix: keep shortcut editor buttons on one row
* fix(shortcuts): 限定输入状态快捷键为 Ctrl 组合
* fix: clarify shortcut override and punctuation lock behavior
* perf(server,windows): 提前筛选输入状态快捷键
* fix(windows,server,ui-html): 修正输入状态快捷键的兼容与保存问题
- windows: 未协商 InputStateShortcuts 时回退到旧的 Ctrl+Shift+E KeyEvent,
新 DLL 配旧 Server 时英文候选快捷键不再失效
- windows: 全角快捷键与标点快捷键一样可在待处理按键后排队,不再漏给应用
- windows: Server 不可用时排队的英文候选切换按 FUNCTION_CANCEL 离线回放,
不再丢弃其后的按键
- server: 非字符串配置值不再以 "!invalid" 作为 binding 发给设置页
- server: 仅三个输入状态快捷键路径强制回传配置快照;去掉 worker 中与
reader 重复的协商检查;抽出 InputStateShortcutViews 去除重复转换
- ui-html: 保存后 5 秒未收到快照则恢复编辑器并提示重试
---------
Co-authored-by: fanlusky <1730976608@qq.com >
2026-10-16 03:31:19 +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
Lu Fan(SonnyCalcr)
715028e1b9
feat(server): AI 联想上下文跳过密码框、换应用清空、过滤类凭证串 ( #845 )
...
AI 联想会把最近的上屏文本作为上下文发到云端,以前不区分输入框,也跨应用累积。
- 密码 / PIN 输入框:TSF 在一段输入的首键上读 InputScope(IS_PASSWORD、IS_NUMERIC_PIN 等),
按键包带上 FanyImePipeFlags::SensitiveField;Server 收到后不发 AI 请求,上屏也不进上下文
- 只在 AI 联想开启时才检测:Server 通过新的 worker opcode AiContextUploadChanged(34)
告诉 TSF 开关状态,关着时按键路径只多一次 atomic load
- 上下文按焦点会话归属:client_id 或 activation_epoch 变了就清空,不再把 A 应用里打的字带进
B 应用的请求
- 发送前去掉像凭证的 ASCII 串:不含空白、长度 >= 8 且混了字母 / 数字 / 符号中两类以上
2026-10-11 21:58:34 +08:00
AkaneIwasa and fanlusky
568d07f513
feat(windows): 添加中日英三语轮换 ( #717 )
...
* feat(windows): 添加中日英三语轮换
* fix(windows): 三语轮换改为快捷键开关并修复两端状态不同步
- 开关移到「快捷键 → 中英文切换」下的「允许中日英循环切换」,配置键改为
[keybindings] trilingual_cycle;输入模式恢复为中文/日文,二者互不影响
- 循环请求带显式标记位和请求方自身的中英/日文状态,Server 据此计算目标语言;
普通 VK_SHIFT 仍是中英切换,不再被误当成循环
- Server 开关在请求途中被关闭时仍回复,按中英切换处理,TSF 只丢弃后续排队按键,
不再超时重连
- 已发出的循环回复未被应用(含 Superseded)时走完整重连,避免日文状态两端不一致
- 循环切换补上光标处状态提示和标点同步
- 切换语言时复用暂存的另一语言会话,不在按键路径上重建引擎和打开 msime.db
- 配置读取的语言与开关改为原子量;TrilingualCycleChanged 的能力过滤移到发送方
- 中日切换不再重发 TrilingualCycleChanged;结束组合被拒绝时不计入统计
---------
Co-authored-by: fanlusky <1730976608@qq.com >
2026-10-09 15:44:41 +08:00
Lu Fan(SonnyCalcr)
53ee180ec3
feat(engine): 直接辅助码句中四码可用第二位辅码大写结束 ( #630 )
...
直接辅助码的四码在句中原来只能补 / 结束(uiab/),现在也可以把第二位辅码敲成大写(uiaB)。
设置页「直接辅助码句中四码标记」两个勾选框可多选、至少留一个,默认只勾 /。
- 引擎:拼写图新增 Aux2Upper(非缩写)。开着大写标记时大写字母只能当第二位辅码,
走不通再退回不分大小写的旧规则,第一位辅码敲大写(uiAuiQ)照常可用。/ 的收键受勾选控制。
- 协议:DirectHelpcodeChanged 载荷改为 "0"/"1"/"2"(2 = 开着但 / 不是编码键),
TSF 据此决定吃不吃 /。
- 配置:新增 helpcode.shuangpin_direct_helpcode_slash / _uppercase,同步写入出厂模板、
工作配置和两个设置宿主的读写映射。
2026-10-05 20:43:02 +08:00
Lu Fan(SonnyCalcr)
3c79876205
Merge pull request #629 from fanlusky/feat/v-mode
...
feat: 新增 V 模式,数字转中文与算式计算
2026-10-05 17:51:21 +08:00
Lu Fan(SonnyCalcr)
b391fd616b
feat: T 模式支持输入指定的日期和时间 ( #626 )
...
Shift+T 后面除了 rq / sj / xq 唤醒词,还可以直接写数字:
- YYYYMMDD、YYYY/M/D、M/D(年份取今年)出那一天的日期格式,星期按那一天算
- YYYY/M 出年月格式(新增 date:ym_* 五种)
- h:mm、h:mm:ss 出时间格式,写了秒才给带秒的格式
- YYYYMMDDhh[:mm[:ss]] 出日期加时间的格式
指定的日期时间沿用唤醒词的格式 ID,学到的顺序、置顶、固定位置跟着走。
输入形状放在 engine/contracts/date_time_input.h,TSF、Server、引擎共用:
数字、/ 和 : 只在还能接成某种形状时才进输入串,接不上的数字仍是选词键,
/ 和 : 仍是标点,Shift+数字始终选词。小键盘数字同样可以输入。
Refs #531
2026-10-05 03:42:12 +08:00
Lu Fan(SonnyCalcr)
5208753ce8
feat: 句中辅助码新增大写字母触发方式 ( #620 )
...
* feat(engine): add uppercase trigger for shuangpin mid-sentence helpcode
With the uppercase trigger on, an uppercase letter right after a complete
two-key syllable opens a mid-sentence helpcode block by itself, as if the
backtick had been typed before it: ulpbXihfa is ulpb`xihfa, and a following
uppercase letter is still the second code (ulpbXYih is ulpb`xYih). The raw
input keeps the typed letters; the block rules live in
contracts/mid_sentence_helpcode.h so TSF, Server and engine parse alike,
including the semicolon final, which no longer counts uppercase blocks.
The scheme now hands the parsed layout (source index and decorations) to the
request, so selection advance and preedit no longer re-parse the raw input.
Adds the MidSentenceHelpcodeUppercaseChanged worker opcode (31).
* feat(windows): count uppercase helpcode blocks before backtick and semicolon
With MidSentenceHelpcodeUppercaseChanged on, TSF uses the shared block rules
when deciding whether '`' opens a block and whether ';' is the ing final, in
both the synchronous and the deferred key classification.
* feat(server): wire the mid-sentence helpcode uppercase trigger
New helpcode.shuangpin_mid_sentence_helpcode_uppercase (default off) in both
config templates, both settings hosts and the settings page as a third
trigger checkbox. It takes effect only with mid-sentence helpcode on and
direct helpcode off; the Server applies it to the semicolon final rule and
broadcasts MidSentenceHelpcodeUppercaseChanged to TSF.
2026-10-04 21:00:41 +08:00
Lu Fan(SonnyCalcr)
22fb1e2569
Merge pull request #619 from fanlusky/feat/shuangpin-direct-helpcode
...
feat: 双拼直接辅助码(万象式,无需引导键)
2026-10-04 19:32:10 +08:00
fanlusky
233ac9ef33
feat(engine,server,windows,ui-html,installer): 句中辅助码触发键可多选,新增分号
...
设置页「句中辅助码触发键」可勾选反引号和分号,至少保留一个。
- 分号只在 AcceptsMarkerAt 成立(这一节是偶数键)时才当触发键;微软/搜狗/紫光双拼的
ing 韵母只跟在奇数键之后,两者不抢同一个位置,判断时分号先让给 ing 韵母
- 无论按哪个键,TSF 按键缓冲、Server raw 与引擎输入串里都记成反引号,引擎解析不变
- 新配置项 helpcode.shuangpin_mid_sentence_helpcode_backtick / _semicolon 同步写入出厂
模板、工作配置与两个设置宿主
- opcode 28 保持「反引号是否触发」、载荷单个 "0"/"1"(TSF 会丢弃更长的帧);分号走新增
的 opcode 29,旧 DLL 忽略它
2026-10-02 23:55:46 +08:00
fanlusky
31241d22ed
fix(engine,server,windows): 句中辅助码支持光标在句中插入,上屏按不带约束的排序调频
...
光标用箭头或 Ctrl+箭头移回句中后敲反引号,TSF、Server、引擎三处都要求光标在串尾,
反引号被当成标点,光标前的预编辑连同「·」一起上屏。改为只看光标前的部分:光标前是
完整的两键音节就收,落在音节中间或已有段的前面不收。形状规则新增
FanyImeMidSentenceHelpcode::AcceptsMarkerAt,三处共用;引擎的光标插入路径同时接受
句中的第一码和大写第二码。
句中辅助码筛过的列表里,要的词往往已经排第一,选第一个不调频,调了也是在筛过的列表
里排位,下次不敲辅助码时排序不变。现在带句中辅助码上屏词库候选时,改用去掉约束后的
候选作排位参照,选的是第一个也照样调;空格、数字键、鼠标点选都走 ProcessSelectionKey,
引擎自己的上屏路径同样处理。
2026-10-02 12:43:16 +08:00
fanlusky
fae80660c1
feat(engine,server,windows,ui-html): 双拼句中辅助码
...
在完整音节后敲反引号,接着的字母筛这个音节上的字:第一码大小写均可,
紧跟的大写字母是第二码,之后可以接着打,一个输入里可以有多段。开关
helpcode.shuangpin_mid_sentence_helpcode 默认关闭。
约束在整句解码时生效,而不是解完再筛:
- Google 解码器在 add_char_qwerty 里送 extend_mtrx_nd 之前按约束过滤词条,
锁住的字带着上下文重新整句解码;约束变化时整段重解,不污染增量搜索。
- kenlm 词格建图时按约束筛边,受约束的跨度不截断地查词库;神经重排只在
词格 n-best 里挑,自动满足约束。
- 普通词条、云和 AI 候选按同一规则收尾校验;满足不了就不出整句。
反引号段在请求里换成手动分隔符,原串留给宿主回读与预编辑显示;选词推进
时剩余音节上的约束随原串保留。输入形状规则放在 contracts/mid_sentence_helpcode.h,
TSF、Server、引擎共用,新增 Worker opcode MidSentenceHelpcodeChanged = 28。
googlepinyinime-rev 已与上游解绑,AGENTS 与 UPSTREAM.md 同步说明。
2026-10-02 02:20:37 +08:00
fanlusky
b3b3b3303c
feat(windows): 焦点切换到另一个输入框时提示当前中英文状态
...
新增开关 general.caret_state_indicator_on_focus(默认关闭,需同时开启光标
状态提示)。
- DLL 把以下情况视为“换了输入框”:焦点窗口变化(Win32 编辑框、对话框、
其他应用各有自己的窗口);焦点经过一段没有可编辑文档的间隙后落到可
编辑文档上(Chromium、WPF 等单窗口宿主在字段之间就是先失焦再聚焦);
焦点会话真正结束后重新开始。Chromium 打字时在两个可编辑文档之间直接
替换文档管理器,不会触发。从 Win+. 面板返回不计入;线程焦点在真正的
应用切换后返回计入。一次切换的多次回调由定时器合并为一次提示;组字
过程中、以及没有光标的控件都保持静默。每次判断在 TSF 诊断日志里记录
判定标志,不含任何文本
- 协议复用 IMESwitch:wch 改为 FanyImeCaretStateTrigger(UserToggle /
CapsLockEdge / FocusEntered),CapsLockEdge 保持首发时的 VK_CAPITAL
取值,Server 对未知值按 UserToggle 处理
- Server 在开关打开时显示当前的有效模式(Caps Lock 开启时为“英”);
配置项同步写入两份模板和两个设置窗口宿主的读写映射
- 设置页在光标状态提示卡片中增加“切换输入框时提示”开关
2026-09-26 17:09:34 +08:00
fanlusky
597d087580
fix(server): 光标状态提示仅由用户快捷键触发并收紧协议边界
...
- DLL 只在 Shift/Ctrl 切换、Shift+Space、Ctrl+.、Caps Lock 与
Ctrl+Shift+F 处显式请求提示;Server 下发的模式同步、宿主转换模式
同步和激活初始化不再弹出提示,移除 compartment 回调里的推断逻辑
- 恢复文档切换时候选窗的 OnKillThreadFocus,改用 COM 身份比较
- 能力位改名为 CaretStateIndicator,DLL 仅在 Server 确认后发送切换
事件;Server 端这些事件只驱动提示,不再改写工具栏或状态快照
- 标点提示的中英模式由 DLL 随 PuncSwitch 携带
- UILess 宿主不显示提示,会话转为 UILess 时隐藏已显示的提示
- Ctrl+Shift+F 的锚点就地读取,不再覆盖 Global::Point,且只采信
协商了该能力的客户端
- 撤回对所有包默认 point 的修改;提示窗口创建失败不再阻断 Server
启动;提示内容改为结构化 CaretStateBadge
- Caps Lock 在同一按键重复进入 TestKeyDown 时只处理一次
2026-09-26 13:58:22 +08:00
fanlusky
dc7cfa0354
Merge branch 'develop' into feat/issue-229-ime-status-indicator
2026-09-26 13:58:03 +08:00
AaGMix
a855a9c7f4
feat(windows): 发送光标状态切换事件
2026-09-22 21:20:07 +08:00
Jia Sui
536d0a95ef
feat(windows): 五笔四码后继续输入不丢字(顶字)
...
四码(不论是否唯一)之后继续敲字母时,先上屏该码的首选候选,再把这个字母
保留为下一次组合的开头。根因是两侧对「组合里有几个字母」认知不一致:TSF 的
本地按键缓冲跟着敲键涨(raw 预编辑样式下 preedit 就是它),服务端的五笔 raw
被引擎裁在四码;空格提交时组合文本被整段替换成候选并清掉本地缓冲,多敲的
字母随之丢失。
- 新增 worker 消息 CommitCandidateAndContinue(27),payload "<consumed>\t<text>":
TSF 按服务端给出的消费数裁**自己**的组合缓冲,而不是套用服务端按旧视图算好
的剩余串——快打时用户已多敲的字母因此不会被覆盖
- TSF 处理序列全部复用既有原语:_InsertTextToComposition + _HandleCompleteCommitFirst
真提交,_StartComposition + AddVirtualKey + _HandleCompositionInputWorker(NO_REQUEST_ID)
重建余下字母的组合;无组合时退化为直写
- 服务端顶字不看自动上屏开关:开关只决定唯一码要不要多敲一键才上屏,
不决定丢不丢输入;自动上屏那条路也改用同一消息,顺带收掉快打竞态
- 引擎新增 wubi_four_code_is_complete(完整四码、码表作答、不要求唯一;
空码不算——没有候选可提交时不触发顶字)
已知限制:光标在组合中间时的改码行为维持现状;空码继续敲字母仍会被忽略。
2026-09-22 09:23:25 +08:00
Jia Sui
ffcd1aee28
feat: 输入统计(DLL 采集、Server 聚合存储与设置页展示)
...
- windows: 三上屏出口 + OnTestKeyDown 直通字符采集,修复半角数字恒零
- engine: 统计 Web 消息契约(statsRequest/statsResponse)
- server: 统计管道接收、聚合、SQLite 存储、保留策略与每日自动清理
- ui-html: 设置页「统计」模块(卡片、热图、明细、开关、清理)
- docs: PRIVACY / README 改为内置可选统计
2026-09-20 19:08:16 +08:00
Jia Sui
e64195731e
feat(server): Backspace 删空剩余拼音后退选已选分词(#35)
...
已选分词是造词中间态:删空剩余拼音时不再整条 composition 丢弃,
而是退选最后一段并恢复其原始拼音与候选。
engine:
- SelectionTransition 暴露本次选择消费掉的原始输入(保留大小写与双拼按键)
engine/contracts:
- 新增回复类型 CompositionRestored=14 与能力位 CompositionRestore;
MaxKnown 同步抬高,Server 按协商能力位门控发送,旧 DLL 不会收到未知帧
server:
- 造词中间态压 (consumed_raw, previous_creating_word) 快照,边界 Backspace 弹栈退选
- 任何清空 raw 的路径同时清 creating_word 与快照历史,避免跨 composition 泄漏
windows:
- _HandleCompositionBackspace 提示退选时读回包重建 keystroke buffer / word / 预编辑 / 光标
- NeedToCreateWord 与 CompositionRestored 共用载荷解析;旧 Server 与 UiLess 回退旧行为
Closes #35
2026-09-17 18:45:01 +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