Commit Graph
730 Commits
Author SHA1 Message Date
Jia Sui d495ea2ad0 fix(engine,server,installer): octagram 加成收敛为单一注入,校正量纲与参数,修复〔万象〕同音乱码 2026-10-12 13:12:21 +08:00
fanlusky 1fd6bebbe2 fix(server): 设为默认改为把水杉排到中文第一位
原实现只写「替代默认输入法」(InputMethodOverride),水杉在中文(简体)的键盘列表里
仍排在末尾,系统设置里看不到它是默认,Win + Space 切到中文时也不是水杉。

- SetAsDefault 不在列表时先 InstallLayoutOrTip 加入,再 SetDefaultLayoutOrTip
  挪到第一位并复核;不改语言列表顺序,也就不动界面语言
- 不再写替代默认输入法,旧版写下且仍指向水杉的在设置成功后清掉
- QueryStatus 改为判断水杉是否在所在语言排第一
- 加入失败时区分「输入法未注册」与「未添加中文(简体)语言」
- 「系统设置」按钮改开「语言和区域」
- 卸载时清理仍指向水杉的替代默认输入法
2026-10-12 03:56:28 +08:00
fanlusky 797c0f5652 feat(server,ui,ui-html): 候选窗可严格按文字宽度收紧
皮肤新增 [candidate_window] fit_content,设置页「外观」新增「候选窗口按文字收紧宽度」
(appearance.candidate_window_fit_content),两者取或。打开后:

- D2D 不再垫 160 DIP 卡片最小宽度和列表 80 DIP 下限,行尾不再多留 6 DIP,
  右侧留白与序号左侧留白相同;
- WebView2 去掉 .container 的 7em 下限;
- 同一输入里宽度不再只增不减,高度仍保持。

皮肤的 min_width_dip 与装饰图宽度照常生效;内置皮肤清单出厂为 false。
2026-10-12 02:03:59 +08:00
MSIME(MetaSequoia IME) fe12f90b2a Merge pull request #857 from fanlusky/fix/toolbar-trilingual-cycle
fix(server): 工具栏语言按钮在开启中日英循环时按循环切换
2026-10-12 01:23:06 +08:00
fanlusky 29adbe76f0 fix(server): 工具栏语言按钮在开启中日英循环时按循环切换 2026-10-12 01:19:32 +08:00
fanlusky c821e5addc fix(installer,server): 新用户默认关闭候选词翻译 2026-10-12 01:04:52 +08:00
Lu Fan(SonnyCalcr) f64da66e6c fix(server): 混输 emoji 最匹配的一个放首页末位,其余排在所有候选末尾 (#853)
此前所有混输 emoji 都追加在候选列表末尾,候选一多就全落到最后一页。现在知道每页候选数时,
查询结果里最匹配的那个 emoji 放在首页末位,其余 emoji 仍排在末尾,颜文字照旧紧随其后。

- 补全词的默认位置和学到的英文槽位在有 emoji 时让到首页倒数第二位,两者都留在首页;
  用户固定位置的英文仍然优先。
- CurrentEnglishPlacement 在没有英文候选时也带上每页候选数,emoji 才能定位。
- 选中 emoji、颜文字不再算越过英文,不会让英文槽位后退;否则首页末位的 emoji 每选一次
  都会把英文往后推。
2026-10-12 01:02:02 +08:00
Lu Fan(SonnyCalcr) 19543ead61 fix(server,installer): 升级不再改掉老用户设置和效果档模型,SimplySign 打包前构建词库 (#852)
* fix(server): 升级不再把只给新装用户的出厂默认值推给老用户

* fix(installer): 升级时把 0.9.x 随包的效果档模型挪到 models\neural-desktop,不再删掉

* fix(installer): SimplySign 完整包打包前从同级 msime-dictionary 构建词库并备好模型
2026-10-12 00:27:59 +08:00
Lu Fan(SonnyCalcr) 0d7ae4ca79 feat(server): 翻译里的词性与分隔符单独配色 (#848)
候选翻译(如 "adj. spreading; n. sound of laughter")由 Server 切成单词、词性、
分隔符三段:WebView2 端包成 .cand-pos / .cand-sep,D2D 端经
CandidateList::Item::translationRuns 用分段画刷绘制,两端同一切法。

新增皮肤键 translation_pos / translation_separator 及选中行的
selected_translation_pos / selected_translation_separator,留空时与翻译同色。

内置皮肤的翻译改用 Notion 调色板:词性取相邻的另一个色相并降到 50% 不透明度,
分隔符为单词色 45%;铺实色高亮的选中行另配一组。仓库内的外部皮肤同步补上词性与
分隔符配色。
2026-10-11 23:28:30 +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
luo jiyin 950649a3a4 fix(server): include page state in candidate frame deduplication (#834)
* fix(server): include page state in candidate frame deduplication

* test(server): cover existing candidate frame state
2026-10-11 20:39:46 +09:00
Lu Fan(SonnyCalcr) 331d0012f5 feat(server): config.toml 中的 API 凭证改用 DPAPI 加密存储 (#840)
翻译、语音、AI 助手的 token / key / secret 以前明文写在 config.toml 里。现在落盘时
用 DPAPI(当前用户范围)加密,存成 "dpapi:<base64>",加载后在内存中还原成明文,
业务代码和设置页的行为都不变。

- 加密统一在 WriteConfiguredValues 里做,所有凭证 setter 自动生效
- 启动时把旧版本留下的明文凭证就地换成密文,用户无需重新填写
- 出厂占位符和空值保持明文,升级时的模板合并仍能识别「未填写」
- 解不开的密文(配置被拷到别的账户或机器)按未填写处理,不会把密文当 token 发出去
- IsCredentialKey 从 ime_config_template.cpp 移到新的 ime_config_credentials.cpp 共用
2026-10-11 18:15:12 +08:00
Lu Fan(SonnyCalcr) 649747f8cd feat(server): 神经网络整句效果优先模型改为按需下载 (#838)
效果优先模型(sentence-model-desktop.safetensors,约 25 MB)不再随安装包分发,
改为和八股文模型一样在设置页下载后才能使用。

- engine:SentenceAssociationOptions 新增 neural_desktop_model 路径,留空即模型缺席、
  静默不重排;词典不再从资源目录固定加载效果档。load_file 按 UTF-8 打开路径,
  数据目录在非 ASCII 用户目录下也能读到模型
- server:新增 settings/neural_model,下载到 <数据目录>\models\neural-desktop\,
  下载与导入都按 neural-model/lock.json 的字节数和 SHA256 校验后原子落位;
  会话层只在开关打开时解析模型路径
- ui-html:设置页增加下载 / 导入 / 删除 / 浏览器下载,模型未就绪时开关置灰
- installer:不再打包效果档模型;旧版装进数据目录根下的那份在覆盖安装与卸载时清掉

原有配置项 sentence_neural_desktop 保持不变,用户的开关状态升级后保留。
2026-10-11 18:08:33 +08:00
Lu Fan(SonnyCalcr) f273dccd18 feat(server): AI 联想与语音润色支持设置 DeepSeek 思考强度 (#821) (#824)
新增 [ai_assistant] thinking 与 [voice_input] polish_thinking,可选 disabled / low / high / max,
默认 disabled 保持原行为。非 disabled 时向 DeepSeek 发送 thinking: enabled 与 reasoning_effort,
其他提供商不受影响。开启思考时 AI 联想超时放宽到 30 秒、max_tokens 提到 8192,润色超时放宽到 30 秒;
AI 联想缓存键纳入思考强度。设置页 AI 辅助与文本润色 API 各加「思考强度」下拉框。

Closes #821
2026-10-11 15:23:46 +08:00
Lu Fan(SonnyCalcr) f019cbdad0 fix(server): 悬浮工具栏的大小写状态不再与 Caps Lock 反向 (#822)
Server 在低级键盘钩子里逢 Caps Lock 按下就翻转一次自记的状态,从不与系统
对账。长按 Caps Lock 时钩子会收到不带重复标记的自动重复,而 Windows 只在
首次按下时切换,重复次数为奇数时状态就此反向;锁屏、UAC 等安全桌面上的
切换钩子看不到,也会造成同样的漂移。反向的状态还会经 CapsLockChanged 广播
回 TSF,连带英文标点跟随和语言栏图标一起错。

- 钩子记录 Caps Lock 是否按住,松开前的重复按下不再翻转。
- TSF 在 Caps Lock 切换与焦点进入时发来的 IMESwitch 带有前台线程读到的
  真实状态,Server 据此校正自记状态,有变化时刷新工具栏并通知 TSF。
2026-10-11 15:03:15 +08:00
Lu Fan(SonnyCalcr) 42c2666a4d feat(server): 悬浮工具栏改用候选窗的柔和阴影,开着阴影也能贴边,并可在设置中关闭阴影 (#809)
* feat(server): 悬浮工具栏改用候选窗的柔和阴影,并可在设置中关闭阴影

- D2D 工具栏改用与候选窗相同的两层阴影(light α .18/.10,dark α .34/.22),
  透明边距与候选窗一致(16/14/32/34 DIP)
- 新增配置 general.floating_toolbar_shadow(默认开启),设置页「悬浮工具栏」
  加「工具栏阴影」开关;关闭后去掉阴影边距,工具栏可贴住屏幕边缘
- 关闭阴影时保留 1 DIP 边距,避免居中描边的外半边被窗口边缘裁掉
- WebView2 工具栏:开关同样生效;默认页阴影改为候选窗的近接层(宿主只留 8px)

* feat(server): 悬浮工具栏开着阴影也能贴住屏幕边缘

- 阴影边距允许伸出屏幕:拖动结束、改尺寸和默认位置都只要求工具栏本体
  (含描边)留在工作区内;伸出工作区的部分用窗口区域裁掉,不绘制、
  不挡任务栏点击,拖动时实时更新
- 伸出量按宿主实际像素尺寸和卡片位置计算,消除向上取整留下的 1-3 px
  缝隙;关掉阴影时同样贴边
- 切换阴影时保持工具栏本体位置不动,并按工作区重新判定边界,
  避免工具栏一部分跑到任务栏下面
- 设置页「工具栏阴影」说明改为「在工具栏周围显示与候选窗一致的柔和阴影」
2026-10-11 13:07:27 +08:00
Lu Fan(SonnyCalcr) b4479974b8 fix(server): 改用 SetInputMethodOverride 设置默认输入法 (#807)
input.dll 的 SetDefaultLayoutOrTip 在 Windows 11 上返回成功,但只改了语言内排序、
Preload 和 CTF 的语言默认项,不写 InputMethodOverride,默认输入法实际不变,复核
因此报「系统没有应用这项设置」。改为调用 bcp47langs.dll 的 SetInputMethodOverride,
与系统设置「替代默认输入法」及 Set-WinDefaultInputMethodOverride 写同一项;仅在缺少
该导出的旧系统上回退到 SetDefaultLayoutOrTip。

同时给两个按钮单独的样式:原先复用的 restart-server-button 在浅色主题下悬停前后
背景几乎相同,看不出是按钮。「设为默认」改为强调色主按钮,两者都有悬停、按下和
键盘焦点反馈。
2026-10-11 02:53:36 +08:00
Lu Fan(SonnyCalcr) 85edddc988 feat(server): 设置页支持把水杉设为默认输入法 (#802)
帮助页新增「默认输入法」卡片:显示当前是否为默认,提供「设为默认」和
「系统设置」两个按钮。设置走 input.dll 的 InstallLayoutOrTip /
SetDefaultLayoutOrTip,完成后按 HKCU International\User Profile 复核;
EnumEnabledLayoutOrTip 在 Windows 10/11 上对 TSF 输入法返回空列表,
因此状态直接读注册表。只在用户点击时执行,不在启动或升级时改写。

新增 defaultImeRequest / defaultImeResponse WebView 契约并同步 ui-html。

同时在帮助页加入 Wiki 与 FAQ 链接,在关于页加入官网 msime.app。
2026-10-11 02:22:01 +08:00
Lu Fan(SonnyCalcr) 5aed0fcbf0 fix: 修复部分用户打不开设置页,WebView2 缺失时仍可正常打字 (#801)
* fix(installer): VC++ 运行库要求提到 14.40 并给出直接下载链接

服务端程序用 MSVC 14.40+ 编译并导入 msvcp140.dll,配上更旧的运行库,
std::mutex 首次加锁即访问冲突、进程无声闪退,设置页因此打不开;原先
14.20 的门槛放过了装着 2019 / 早期 2022 运行库的机器。

- 缺失与「已装但过旧」分开提示,并显示当前版本
- 「是」直接下载 VC++ x64 运行库与 WebView2 Evergreen Bootstrapper
- 更正 WebView2 缺失的影响:只有设置页需要它,默认 D2D 候选窗照常打字

* fix(server): WebView2 不可用时设置页给出提示,候选窗退回 D2D

- 设置进程不再忽略 WebView2 environment / controller 创建失败(运行时缺失
  时同步失败、回调不来,界面会一直停在启动画面),改为弹框说明原因、错误码
  与下载直链后退出
- ui_backend = webview2 而检测不到运行时时,本次进程改用 D2D 渲染,保证能
  正常打字;不改配置,装好运行时后下次启动自动恢复
- WebView2 下载地址统一为 Evergreen Bootstrapper 直链
2026-10-11 02:21:40 +08:00
luo jiyinandfanlusky 66e0a6dc76 fix(server): 保留候选文本中的逗号和私用字符 (#766)
* fix(server): 保留候选文本中的逗号和私用字符

* fix(server): render candidate frame from one snapshot

* fix(server): use captured preedit for sticky card key

* fix(server): dedup candidate frames by item-aware signature

Candidate text now keeps raw commas, so the comma-joined candidate_string
could make ["a,b","c"] and ["a","b,c"] share one frame signature and drop
a real page change as a duplicate repaint. Length-prefix each item instead.

Also serialize the WebView candidate items with the replace error handler
so an invalid UTF-8 translation gloss cannot throw on the UI thread, and
let CandidateWindowContent own its preedit and page snapshot rather than
referencing caller locals.

---------

Co-authored-by: fanlusky <1730976608@qq.com>
2026-10-11 02:08:25 +08:00
fanlusky 90e812fe4e fix(installer): start fresh installs in Chinese and ship opt-in features off
- input.default_ime_mode defaults to chinese, matching the Server and TSF fallbacks
- utility.emoji_mode / kaomoji_mode default off so Shift+E / Shift+M no longer swallow
  English words that start with a capital letter
- voice_input, ai_assistant and tencent_tmt default off; without a token they only pop a
  prompt (voice on Right Alt, which is also AltGr) or do nothing
- doubao_enable_ddc defaults off, matching its comment and the code fallback
- drop general.enable_emoji, which nothing reads

cloud_candidates stays on: the installer's network page asks the user and only writes
false when unchecked. Code fallbacks in ime_config are aligned with the template.
2026-10-10 23:02:15 +08:00
Jia Suiandfanlusky e10f845e04 refactor(server): 移除服务端内嵌设置宿主死代码 (#764)
* refactor(server): 移除服务端内嵌设置宿主死代码

InitWebviewSettingsWnd 全仓无调用点,webviewSettingsWnd 恒空,这条内嵌设置 WebView 宿主及其上的 configUpdate 分发、PostSettingsConfig() 空转调用链从不执行。设置页由独立进程 MetasequoiaImeSettings.exe 承载并自行轮询配置,删死路径与 7 个空转调用点不改变可观察行为。

- 整删 windows_webview2_settings.cpp、ime_windows_settings.cpp
- 清除仅服务该宿主的全局/声明/常量,及 windows_webview2.cpp、windows_webview2_skin.cpp 中的引用
- 删 PostSettingsConfig() 调用点,两处 if 块塌缩为直接调用 setter
- 同步根 AGENTS.md 与 server/AGENTS.md 的「两个设置宿主」表述

* docs: 配置同步规则补回设置页 configSnapshot 字段列表

---------

Co-authored-by: fanlusky <1730976608@qq.com>
2026-10-10 21:33:25 +08:00
Lu Fan(SonnyCalcr) 5e03628a7e feat(installer): build cn-en translations into the local dictionary (#784)
* fix(server): drop part-of-speech labels from Ctrl+Enter translation senses

The machine-translated Chinese-to-English glosses prefix each sense with a
label ("n. silver medal", "proper n. Wanshan District"). The candidate
window keeps showing the whole gloss, but splitting it for Ctrl+Enter now
strips the label so it never reaches the committed text.

* feat(installer): build cn-en translations into the local dictionary

build-dictionary.py gains a cn-en-translations stage that loads
sources/cn-en/machine-translations.txt from msime-dictionary into
zh_en_glosses verbatim, keeping every sense instead of the two the ECDICT
derivation keeps. It runs after english-glosses and before
custom-translations, so it overrides ECDICT and custom/translations.txt
still overrides it.

Local full test packages now always build the dictionary from the sibling
msime-dictionary checkout instead of downloading the product-lock release:
Invoke-LocalTest.ps1 and prepare-package-inputs.ps1 call
build-dictionary.py --if-stale, which skips only when out/ was built from
the current clean source commit by the current builder. CI and releases
still take the dictionary from product-lock.json.
2026-10-10 21:17:03 +08:00
Lu Fan(SonnyCalcr) 49f22b5c25 fix(server): 手写识别板按钮改用图标字体,修复撤销图标显示为缺字方框 (#749)
撤销按钮的 ↶ (U+21B6) 直接写在文字里,Noto Sans SC 没有这个字形,
DirectWrite 也回退不到,画成了缺字方框。

两个按钮的图标改由 ResolveIconGlyph 解析:Windows 11 用 Segoe Fluent Icons,
Windows 10 回退 Segoe MDL2 Assets(撤销 U+E7A7,重写 U+E711),并以 SemiBold
模拟加粗与旁边文字协调;两种字体都没有该字形时只画文字标签,与悬浮工具栏一致。
2026-10-09 21:33:03 +08:00
AkaneIwasaandfanlusky 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
時崎 ギャラクシー aa5c632ea9 Merge pull request #711 from Tokisaki-Galaxy/feat/llm-model-fetch
feat: AI 辅助新增获取模型、测试连接与 Custom 提供商
2026-10-08 23:13:01 +08:00
normaltank c2bd59d448 fix(server): 翻页扩展时保留混输候选并同步 Emoji 末尾排序 2026-10-08 22:10:13 +08:00
normaltank 6489d4be17 feat(server): 调整 Emoji 混输候选项位置至候选列表末尾 2026-10-08 22:10:13 +08:00
fanlusky 799d6361e5 feat(server): 候选翻译目标语种新增泰语、越南语和意大利语 2026-10-08 17:20:58 +08:00
MSIME(MetaSequoia IME) 53020b2945 Merge pull request #657 from Hush-Jr/fix/ftb-cross-monitor-drag
fix(server): 悬浮工具栏跨屏拖动不再被拉回原显示器
2026-10-08 16:39:54 +08:00
fanlusky d830c75e59 fix(server): 悬浮工具栏跨屏拖动改用建议矩形并统一两后端的放置逻辑
- 拖动中的 WM_DPICHANGED 也采用 lParam 的建议矩形,避免固定左上角改尺寸
  导致 DPI 在分界线两侧来回翻转、窗口脱离光标
- 是否处于拖动改用 GetGUIThreadInfo(GUI_INMOVESIZE) 判定,去掉文件级标志,
  拖动中 HWND 被销毁也不会残留拖动状态
- WebView2 与 D2D 共用 PlaceResizedHost:D2D 的 ApplyAppearance 在拖动中
  也不再夹取;半屏尺寸上限按即将落到的显示器计算
- 尺寸变化的夹取恢复为整块显示器(允许压任务栏),拖动结束的兜底夹取仍用工作区
- WM_EXITSIZEMOVE 先执行挂起的 DPI 重测再夹取,避免松手后跳两次
2026-10-08 16:13:44 +08:00
fanlusky 06fb8f87ba fix(server): 关闭顶字且混输关闭时第五码仍走顶字,避免丢字与两端分叉
混输关闭时码表答得出的完整四码保留四码上限,关掉顶字后第五个字母会被 Server
裁掉,而 raw 预编辑样式的 TSF 已经显示了它,两边缓冲就此分叉。顶字开关改为只在
混输开启时生效(字母并入混输串),混输关闭时仍按顶字上屏首选。

同时修正第四键注释(两个开关作用在不同按键上)、设置页与配置模板的说明文字,
以及 settings_app.cpp 新增行的缩进。
2026-10-08 14:10:36 +08:00
Jia Sui 3d31a40a74 feat(server): 五笔四码自动上屏与顶字各加一个设置开关
「四码唯一时自动上屏」和「第五码将首选上屏」此前都是无条件行为,用户遇到
误上屏没有任何出口。四家主流五笔(搜狗/QQ/百度/微软)都提供这两个开关且
默认开启,这里补上并保持默认开,升级用户零行为变化。

- input.wubi_four_code_auto_commit(默认 true)门控四码唯一自动上屏
- input.wubi_fifth_code_top_commit(默认 true)门控真顶字
- 开关只落在 Server 判定层,引擎完全不知道:WubiInputOptions 不加字段,
  避免测试里大量聚合初始化静默取默认值
- 顶字关闭后第五个字母落回引擎既有四码上限(混输关=裁掉,混输开=并入混输
  串),与搜狗 PC 一致,不补新分支
- 顺带修正 input_key_policy.h 与 event_listener_keys.cpp 中把不存在的开关
  当既成事实引用的注释,以及两个把「无条件」写进名字的用例
2026-10-08 13:24:25 +08:00
Hush-Jr 61f40a6b66 fix(server): 悬浮工具栏跨屏拖动不再被拉回原显示器
不同缩放比例的双屏之间拖动悬浮工具栏时,Windows 会在指针越过屏幕
边界(窗口主体已进入新屏)时发送 WM_DPICHANGED,而捕获到的窗口此时仍
属于旧屏:

- LayoutFloatingToolbar/RelayoutHost 用 MonitorFromWindow + rcMonitor
  把窗口夹回当前显示器,于是刚跨过去就被拉回旧屏左/右缘,永远拖不过去。
- WM_EXITSIZEMOVE 的兜底夹取用 MonitorFromRect(最大交集)选屏,在副屏
  比主屏高的错位布局下也会把窗口拉回原屏。

改为:
- WM_DPICHANGED 期间若处于用户拖动(WM_ENTERSIZEMOVE..WM_EXITSIZEMOVE)
  的模态移动循环内,只改尺寸、绝不动位置;不在拖动中时应用系统 lParam
  建议位置。
- 所有保持位置的夹取(含 D2D presenter)只要求窗口落在各屏工作区的
  并集内,仅在完全离开所有屏幕时才按窗口中心就近收回。
- 夹取目标显示器改用窗口中心判定,避免跨缝窗口被判定为旧屏。
2026-10-08 04:37:11 +08:00
Ehtasham Yasin 6bd2452dc4 Merge branch 'develop' into feat/shuangpin-shift-enter 2026-10-07 08:53:14 +02:00
Jia Sui 9e46ccb427 feat(server): HandleImeKey 分段计时埋点,定位提交超时类吞字卡顿
诊断日志新增 handle-read-packet / handle-engine / handle-selection /
handle-worker-push / handle-async-query / handle-candidates 六类分段
(>=8ms 才输出),用于定位 server 按键处理偶发数百毫秒卡顿——昨晚
request=628 卡 344ms 导致空格排队超 TSF 300ms 提交预算、整会话重置
吞掉 "juede"。纯观测改动,零行为变化;.gitignore 忽略本地测试暂存
目录 .tmp-test/。
2026-10-07 09:00:47 +08:00
Ehtasham-Yasin 0fe601e259 feat(server): submit converted shuangpin with Shift+Enter 2026-10-06 15:09:29 +02:00
Lu Fan(SonnyCalcr) 5d6eaa5bd1 feat(server): 全拼纠错候选的 * 标记可在设置中关闭 (#631)
新增 quanpin.autocorrect_marker 开关,默认开启(显示 *),关闭后纠错得到的候选
不再在末尾附加 * 标记。只影响候选窗显示,不影响上屏文字和词频。

同步出厂模板、工作配置、两个设置宿主的读写映射和设置页「输入」分区的开关,
并在配置持久化测试里覆盖默认值、落盘重读和缺键回退。
2026-10-05 22:04:06 +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
fanlusky b986c3496f refactor(server): D2D 候选组页时只读一次翻译开关 2026-10-05 13:02:46 +08:00
fanlusky 70d76ce52a perf(server): 神经重排完成时队列里最多排一个重查任务
每批重排完成都排一个 ApplyRescoredOrder,每个都清整句缓存并重查一遍词格,
两个模型同开时更多,且都排在按键前面。重查本身会读所有模型已算完的结果,
所以排队期间再完成的批次不必各排一个;出队即放行,之后完成的批次还能再排。
2026-10-05 13:02:46 +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) ae353d142c feat(server): 语言栏右键菜单新增输入方案二级菜单 (#625)
在托盘语言栏菜单第二项加入「输入方案」,悬停展开全拼/双拼/五笔二级菜单,
当前方案打勾,点击即切换(与设置页走同一条 SetConfiguredInputScheme 路径)。

- D2D:TrayMenuPresenter 用 Popup 实现子菜单,展开时宿主窗口向有空间的一侧加宽,收起时还原
- WebView2:页面通过 inputSchemeSubmenu 请求宿主加宽窗口,再由 PlaceInputSchemeSubmenu 摆放;
  changeInputScheme 切换方案
- 契约:messages.json 新增 changeInputScheme / inputSchemeSubmenu,并重新生成 ui-html/webview2/shared
2026-10-05 02:44:59 +08:00
Lu Fan(SonnyCalcr) 1b74617eed feat(server): make direct and mid-sentence helpcode mutually exclusive (#621)
Turning either one on now turns the other off, in the config setters both
settings hosts go through, so the snapshot pushed back to the settings page
shows the change; the page also flips the other toggle immediately. Turning
one off leaves the other alone. Configs saved before this with both on load
with mid-sentence helpcode treated as off in memory, matching the behaviour
direct helpcode already had, without rewriting the user's file.
2026-10-04 22:04:32 +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
Jia Sui 6b4f8e5398 fix(server): 速度分母加下限避免零散输入日算出离谱速率 (#614)
活跃时间只累加相邻两次上屏之间的间隔,首键之前与末键之后的时间不在其中。零散输入的日子分母可能只剩几秒,按它外推会得到没人打过的速率:本机 20261004 记录 81 个可读字符 / 1.9 秒活跃,页面显示 2503 字/分。

CharsPerMinute 在 active_ms > 0 时改用 max(active_ms, kMinSpeedActiveMs) 作分母。active_ms <= 0 仍返回 0——那是没有测量,不是测量小,不该被下限救活。

kMinSpeedActiveMs 与 kFastestSpeedMinActiveMs 保持为两个常量、两个理由:下限管数值,排名门槛管资格。没有门槛的话,被下限压到「每分钟字数」量级的爆发日仍会拿下最快日。

前端 speedOf 是同一公式的手写副本,一并改,并把运算顺序对齐 C++ 的 chars / (ms / 60000),否则两侧会差一个 ulp。落库口径不变,无需迁移历史数据。
2026-10-04 14:24:53 +08:00
Lu Fan(SonnyCalcr) 1b462a9e2a fix(server): keep default AI endpoint and model out of provider slots (#610) 2026-10-04 00:02:50 +08:00
HowGeGe 5e77dffabf fix(server): preserve endpoint and model per provider (#605) 2026-10-03 23:18:41 +08:00