fanlusky
|
ec00892121
|
feat(server): 新增仿微软拼音的内置皮肤 microsoft
- 候选窗:深色 #2C2C2C 底、#383838 选中底、#E183D9 紫色选中条,序号与候选同字号,
横排每项最小 4.35em、间距 0.28em(换行的行间同样隔 0.28em);尺寸均按字号缩放
- 翻页:默认开启,实心圆角三角,与候选行等高,横排前加分隔线
- 悬浮工具栏沿用默认页面,拖拽条改为紫色
- ui:PagerArrows 新增 Glyph::Triangle 与分隔线,三角用单一路径填充,半透明时不出现描边重叠;
CandidateList 新增 minItemWidth 与 selectedBarInside
- 设置页新增皮肤卡片与预览;更新内置皮肤列表、文档与配置注释,补充测试
|
2026-09-30 17:35:38 +08:00 |
|
fanlusky
|
9f5572c525
|
fix(build): 所有 MSVC 目标显式按 UTF-8 编译源文件
#548 修了 ngram,同类问题还有几处:源文件或头文件是无 BOM 的 UTF-8,
目标却没有 /utf-8,在代码页 936 的系统上注释会吞掉换行。
- ui:Controls.h 让 msimeui 与各 demo 单独构建失败,/utf-8 设为 PUBLIC
- server/tests/portable:input_key_policy.h 让 MSVC 构建失败
- engine test_windows_ipc_contract、tests/pipe-probe、windows/tests:C4819
- windows DLL:此前只靠 fmt 的 INTERFACE 选项带来 /utf-8,改为显式设置,
否则 L"“" 等宽字符标点会在去掉 fmt 后静默变成乱码
|
2026-09-30 15:37:13 +08:00 |
|
Lu Fan(SonnyCalcr)
|
03911aab61
|
Merge pull request #547 from ouchihao/codex/fix-505-tray-menu-placement
fix(server): keep tray menus inside the icon monitor work area
|
2026-09-30 15:09:25 +08:00 |
|
fanlusky
|
8c2a177a80
|
fix(server): 托盘菜单延迟弹出时保留右键时的图标位置
图标矩形改由任务线程在读完管道数据后立刻取下,随 WM_LANGBAR_RIGHTCLICK 的
lParam 传给菜单宿主。WebView 就绪后补发的消息 lParam 为 0,沿用已保存的锚点,
不再从已被按键和候选窗移动改写的 Global::Point / Keycode / ModifiersDown 重读。
|
2026-09-30 14:57:45 +08:00 |
|
fanlusky
|
dde06afd7f
|
feat(server): 候选框显示翻页箭头并接入设置页预览
- D2D:横排在候选右侧多一窄列,竖排在最后一行下方、「‹」与序号左对齐;开关或排列方式变化时重建场景
- WebView2:页面按 data-page-arrows 显示箭头,点击经 candidatePage 翻页
- 箭头点击走 WM_PAGE_CANDIDATE_ARROW,不受鼠标滚轮翻页开关影响;页面快照带上一页 / 下一页可用状态
- 两个设置窗口宿主下发内置皮肤的 page_arrows,外部皮肤条目带解析后的 pageArrows
- 安装包把 skins/default 以 onlyifdoesntexist 放到数据目录,升级不覆盖用户改过的清单
|
2026-09-30 12:42:25 +08:00 |
|
fanlusky
|
4582550862
|
feat(skins): 内置皮肤抽出为 skins/default 设置清单并支持 page_arrows
五个内置皮肤各有一份 skins/default/<id>/skin.toml,承载皮肤级开关;
[candidate_window] page_arrows 控制候选框翻页箭头,出厂与缺省均为关闭。
外部皮肤可自行设置,不写时沿用 base 对应的默认清单。
皮肤扫描跳过 default 目录,且不允许用它作外部皮肤 ID。
|
2026-09-30 12:42:24 +08:00 |
|
Ouchihao
|
b2719cd0aa
|
fix(server): keep tray menus inside the icon monitor work area
|
2026-09-30 02:54:39 +08:00 |
|
Ouchihao
|
d867037308
|
fix(server): explain duplicate quick phrase conflicts
|
2026-09-30 02:22:35 +08:00 |
|
fanlusky
|
52041513b2
|
fix(server): 杨柳青横排翻译贴底、行尾留白且末项高亮不铺满
行高里的底部内边距原先夹在候选与翻译之间,改为放在翻译下面。
卡片为防闪烁保持同一输入下更宽的尺寸时,多出的宽度均分给同一行各项,末项高亮贴到卡片右边。
|
2026-09-30 01:33:47 +08:00 |
|
fanlusky
|
2b7cd6a96f
|
fix(server): D2D 候选配色支持 #rgba 并拒绝含非十六进制字符的颜色
|
2026-09-29 22:43:52 +08:00 |
|
fanlusky
|
7ad6a42f12
|
feat(server): 外部皮肤新增细分配色、菜单、外框线宽、高亮圆角、阴影与字体族
|
2026-09-29 22:08:00 +08:00 |
|
fanlusky
|
f1b6622ac5
|
fix(server): 候选配色按 CSS 颜色字符过滤,WebView2 候选文字色生效
候选配色此前只按字符串读取就拼进 WebView2 样式表,含 ; 或 } 的值能跳出声明改写候选窗;改用与工具栏相同的 ReadCssColor 过滤。WebView2 的 .text 读 var(--cand-text),皮肤的 text 只设在 .container 的 color 上不起作用,现在同时写入 :root 的 --cand-text;设置页的候选文字色仍以内联样式优先。
|
2026-09-29 21:56:14 +08:00 |
|
fanlusky
|
e3eb9fc9d8
|
feat(server): 快捷短语混入候选默认关闭
|
2026-09-29 19:19:51 +08:00 |
|
fanlusky
|
30e10fc887
|
fix(server): 五笔纯汉字导入忽略用户自造单字码并放行扩展区汉字
- 取单字码时排除用户词库日志里 user_inserted=1 的单字行,出厂码优先;
自造码只给出厂码表里没有的字兜底
- 五笔路径不再沿用 cpp-pinyin 的 U+4E00–U+9FFF 限制,扩展 A、兼容表意字
及 2/3 平面扩展区都可导入
|
2026-09-29 18:56:14 +08:00 |
|
Jia Sui
|
81ca402936
|
test(server): 修复临时目录隔离与真实词库污染
三件事:
1. 临时目录加 PID 后缀并在析构时删除。原先 msime-empty-hans-import 是固定名
且从不清理;固定名在并行 ctest 或多个工作树同时跑时会互相删掉(同样的
理由见 test_caret_prefix_input_session.cpp:27)。
2. 修复上一提交的端到端用例污染用户真实词库。ScopedDataDir 原来只调
SetEnvironmentVariableW:server 的 get_ime_data_path() 走
GetEnvironmentVariableW 读 Win32 环境块,重定向确实生效;但引擎的
data_file_path()(default_user_db_path 用它)走 _wdupenv_s 读 CRT 自己
那份副本,看不到新值。于是 record_user_insert 仍然写进
%LOCALAPPDATA%\metasequoiaime\msime_user.db——实测写入了 3 条
环境/计算机/诸葛亮。改为两处环境变量都写。
验证:跑测试前后各取一次快照逐行比对,944 -> 944,0 增 0 删(文件字节有
变化,是 SQLite 页复用,不是数据写入);端到端用例断言 count==3 也只有在
读临时库时才成立——真实库有 4 条 wubi 行,多出来的那条是用户自己导入的。
3. 补 WubiPhraseCodeRejectsCharsWhoseCodeIsShorterThanTheRuleNeeds,锁住上一
次提交的短码防御;同时修正我先前写错的一条断言——4 字以上每位只取 1 位,
1 位码够用,守卫不该误伤长词。
|
2026-09-29 18:44:53 +08:00 |
|
Jia Sui
|
65ff492611
|
fix(server): 五笔取码拒绝不足位的短码
code.append 按 full.size() 截断。某个字只有 1 位码时,2 字词会拼出一个 3 位
key 填 4 位槽:它能查得到、能上屏,但永远凑不满 has_complete_code() 要求的
4 位,还会以合法词码的形态留在 wubi86 里,成为一条永远选不中的垃圾词条。
出厂词库的有效最短码长是 2(20004 个字 4 位、1581 个 3 位、1 个 2 位),
所以当前数据下不可达。这是给已经进了公共头的函数补一道防御:词库一旦变动,
不必等某个用户导出一份名单才发现导入静默产生了废码。
单字走 npos「全取」分支,不设长度下限,1 位码原样出码。
|
2026-09-29 18:44:53 +08:00 |
|
Jia Sui
|
e3086f4985
|
test(server): 补五笔纯汉字导入的端到端用例
上一提交只验证了取码纯函数与 importHans 的分发路由,没有验证「导入真的能写
进去」。这轮补一个针对真实 TU 的端到端用例:在临时目录建一个只含 wubi86 表的
msime.db(种子单字码与取码用例一致),把 METASEQUOIA_IME_DATA_DIR 指过去,
再走 HandleRequest 完成一次真实导入。
覆盖此前未验证的验收项:
- 规则推出的码与权重 30 确实落库,而不是拼音的 10000
- record_user_insert 落到用户词库,「导出五笔用户词库」才收得回这些词条
- 非法行(非汉字、码表缺字)计为失败并带行号,且不中断整批
- 重复导入判为已存在,不产生重复行
写测试时踩到两个自己的错误假设,都由用例本身暴露:
- 「观」在出厂 wubi86 里其实有码(cmqn),不能用它演示缺码
- 重跑一批(含失败行)时 ok 为 false 是 SummarizeImport 的既有语义
inserted>0 || (failed==0 && skipped>0),与拼音路径一致,不是缺陷
全临时目录,不触碰任何真实词库。
|
2026-09-29 18:44:53 +08:00 |
|
Jia Sui
|
301944a2dd
|
feat(server,ui-html): 五笔词库支持纯汉字词组批量导入
设置页词库管理新增「批量导入纯汉字词组到五笔词库」,把一份纯汉字名单
(人名、地名)直接变成五笔可打出的词条。
取码按 86 词组取码规则从 wubi86 单字码组合:2 字取首/次各 2 位,3 字取首/次
各 1 位加末字 2 位,4 字以上取首/次/三/末各 1 位。规则不是猜的——拿出厂词库
反推拟合,62601/62636 = 99.94% 命中;未命中的 0.06% 是作者为避重码手工改过
的词,正是规则正确的证据。单字保持自然码长不补 z,否则「节」会同时存在 abj
与 abjz 两条重复词条。
wubi86 没有 value 首列索引,逐字查码是全表扫描(实测 3.38ms/字,2000 字名单
要 6.8 秒),因此一次性把单字行读进内存(约 25ms)后纯内存查。
缺省权重按词库区分。实测拼音 2 字词 p50=2805/max=9931703,五笔 p50=10/max=110:
同一个 10000 落在拼音 p50~p60 的合理区间,搬到五笔则是全库 max 的 91 倍,
导入的词会碾压原生词条。拆出 kDefaultPinyinImportWeight=10000 与
kDefaultWubiImportWeight=30,ImportWubi 同步改用后者——这是行为变更。
顺带把四份逐字重复的导入结果汇总块收口为 SummarizeImport。ImportQuickPhrase
刻意留在外面:它原本不调 NotifyImeServerClearDictCache(快捷短语不由活动输入
会话消费,缓存失效对它无意义),一并收口会凭空加上这次调用。
协议零改动:importHans 与 wubi 都已在契约枚举内,因此不触碰 engine/contracts/
与 ui-html/webview2/shared/ 的生成物链条。
测试新增 7 个用例,覆盖四种取码规则、单字码长、缺字失败、权重刻度,以及
importHans 的分发路由——路由链的是真实 TU,用空数据目录让三条分支都在写库
前返回,因此不碰任何真实词库。
|
2026-09-29 18:44:53 +08:00 |
|
fanlusky
|
f8a83d28d1
|
fix(server): 扩大 Main 管道入站缓冲
原 4 KiB 只容得下 13 帧,TSF 端突发写入时容易被拒绝并触发重连。
提高到 128 帧,为宿主的密集事件留出余量。
|
2026-09-29 15:47:49 +08:00 |
|
fanlusky
|
2415da274f
|
feat(server): 候选中混排快捷短语并参与调频
- 全拼 / 双拼(非五笔、无辅助码、非造词)编码精确匹配时,把快捷短语组放到固定位置候选
之后,翻页扩展时重新放置;Shift+K 模式不变
- 新增 utility.quick_phrase_candidates(混入候选)和 utility.quick_phrase_frequency
(参与调频),默认都开,utility.quick_phrase 仍只管 Shift+K;两份配置模板与两个设置宿主
同步读写
- 选中快捷短语或越过它选普通候选时异步写入槽位,K 模式里的选择不学;英文最高权重提升
忽略快捷短语
|
2026-09-29 14:31:51 +08:00 |
|
fanlusky
|
c9b86e0026
|
feat(engine): 支持用户自定义双拼方案
用户在数据目录 shuangpin\custom\ 下放 TOML 文件,在设置页以 custom/<文件名>
选用。零声母规则从 o、a、first_letter、full_pinyin 四种里选,声母和韵母
映射由文件指定,可用 [zero_initials] 覆盖个别零声母音节。
- 引擎:新增 CustomShuangpinLayout 与 BuildCustomShuangpinProfile,校验缺键、
声母撞键,并对全部音节做往返解码,冲突时给出可读的错误信息;新增运行时
方案注册表,按需加载。
- Server:扫描并解析自定义方案,配置快照带上方案列表与目录;文件缺失或无效
时回退到小鹤。
- 设置页:仿照自定义辅助码,新增打开目录和刷新按钮;无效方案列出但禁用,
悬停时显示错误。
- 安装器:覆盖安装与迁移数据目录时保留 shuangpin 目录。
- 文档:docs/custom-shuangpin.example.toml 提供带详细注释的示例。
|
2026-09-29 11:33:23 +08:00 |
|
Lu Fan(SonnyCalcr)
|
4042a503be
|
Merge branch 'develop' into fix/voice-keep-composition
|
2026-09-29 04:06:53 +08:00 |
|
fanlusky
|
78f8bd6174
|
fix(server): 语音已定句子不再提前上屏,保持 TSF composition 连续
#524 在句子判定后立即提交上屏,会结束当前 composition,把一段话从中间截断。
撤回逐句提交:录音期间整段识别文本始终留在同一个预编辑里,松键时再整段提交。保留按静音分句(end_window_size / force_to_speech_time),让已说完那句的标点在按住快捷键时就能出现在预编辑中。
|
2026-09-29 03:55:31 +08:00 |
|
fanlusky
|
f56551c34b
|
feat(engine): 内置搜狗、紫光、智能ABC、国标和拼音加加双拼方案
新增五套双拼方案表,零声母规则:
- 搜狗、紫光、智能ABC:o + 韵母所在键
- 国标:a + 韵母所在键
- 拼音加加:韵母第一个字母 + 韵母所在键
搜狗和紫光与微软一样把 ing 放在分号上。分号作韵母键原先按方案名写死为
microsoft,现改为 ShuangpinProfileUsesSemicolonFinal 按方案表判断,
引擎、Server 按键处理和下发给 TSF 的开关一并生效。
智能ABC 键位图把 ve 也标在 V 上,但这样 lv/nv 会同时解成 lü 与 lüe,
这里按标准智能ABC 把 ve 放在 M(与 ue 同键)。
Server 配置校验改为按方案解析结果判断;设置页下拉框、配置模板注释和
README 同步更新;新增各方案键位、零声母、分号及全方案逐音节往返测试。
|
2026-09-29 03:52:19 +08:00 |
|
fanlusky
|
1794aa8741
|
fix(server): 切换到其他输入法时前台线程的停用不再因路由归属被丢弃
路由被 TextInputHost、任务栏或后挂起的线程占着时,前台应用切走输入法发来的
终止停用会因为不是路由所有者而被静默丢弃,g_is_ime_active 保持为 true,
悬浮工具栏不隐藏。现在来自前台窗口(或其焦点窗口)所在线程的终止停用会退役
残留路由并推进 epoch,照常投递 ClientDeactivated;后台线程仍被忽略。
|
2026-09-29 03:18:58 +08:00 |
|
fanlusky
|
338b8bf7c2
|
feat(server): 豆包流式语音按静音分句,已定句子在录音中即时上屏
此前请求沿用默认语义分句且不返回 utterances,最后一句要到音频结束(松开快捷键)才判定并补上标点;Server 也只在 Finish 之后整段提交。
改为按静音分句(end_window_size=800ms、force_to_speech_time=1000ms)并开启 show_utterances,从中解析已判定的句子前缀。行内预编辑模式下,句子一经判定即提交上屏,剩余部分继续作为预编辑;松键时只提交未上屏的部分。配置了文本润色时仍在松键后整段提交。
|
2026-09-29 02:57:05 +08:00 |
|
fanlusky
|
738435b002
|
fix(engine): 全拼长句不再为更短的前缀补 Google 整句
前缀查不到词时 query_single_path 会补一条 Google 整句,长句候选后面于是缀上一串越来越短的〔Unigram〕子串。整句联想只对完整输入出一句,前缀只取词库里的词,查不到就交给更短的前缀。
|
2026-09-29 02:22:57 +08:00 |
|
fanlusky
|
995174af47
|
feat(server): 造词时 Esc 可只清除未选拼音、保留已选词
新增 input.escape_keeps_selected_word(默认 false)。开启后,造词中按 Esc
只清掉还没选的拼音,保留已选的词,候选窗只显示该词作为 preedit;
再按一次 Esc 整体取消(小狼毫风格)。R 模式下仍整体取消。
- server:HandleCreatingWordEscape 以 CompositionRestored 帧回复
- windows:_HandleEscapeCancel 读取回复并应用,超时或不支持时回退到原取消
- ui-html:设置页「输入」增加开关
- 配置模板、两个设置宿主同步新增该键
|
2026-09-29 01:58:38 +08:00 |
|
Lu Fan(SonnyCalcr)
|
97049ffd7c
|
Merge pull request #517 from metasequoiaime/refactor/wubi-pinyin-mixed-input
feat(engine,server,ui-html,installer): 五笔拼音混输改为同时混排并拆出独立开关
|
2026-09-29 00:37:40 +08:00 |
|
fanlusky
|
378f4d43c0
|
fix(server): 整句候选的来源标签默认不显示
出厂模板、开发配置、代码默认值和设置页开关的初始状态一并改为关闭。
|
2026-09-28 21:52:25 +08:00 |
|
fanlusky
|
852444d82b
|
fix(server): 外部皮肤背景图铺满候选框边框下方,不再露出一圈底色
候选框 .container 是 overflow 滚动容器,::before 垫的背景图只能画到内边距盒,半透明边框下面露出的是底色,浅色主题下就是一圈白边。改为把背景图放进 .container 自己的背景层(origin/clip 都是 border-box),与 D2D 一样让边框画在图上;图层不能单独设透明度,就在图上盖一层 (1 - opacity) 的底色,底色取 D2D 同一份调色板。
|
2026-09-28 20:42:43 +08:00 |
|
fanlusky
|
0b4a3d374a
|
feat(server): 外部皮肤用 skin.toml 的 [toolbar] 表配置悬浮工具栏,替代 toolbar.css
toolbar_stylesheet 只注入 WebView2 页面,D2D 工具栏完全看不到,两个渲染器的工具栏配色因此不一致。
改为在 skin.toml 里用 [toolbar] corner_radius_dip 与 [toolbar.dark]/[toolbar.light] 的
background、border、handle、divider、icon、hover 声明覆盖:D2D 在基础皮肤之上叠加这些值,
WebView2 由 Server 生成当前主题的 CSS。颜色只放行颜色值会用到的字符,避免跳出 CSS 声明。
toolbar_stylesheet 随之移除,不做兼容:外部皮肤里的 toolbar.css 不再生效。
|
2026-09-28 20:07:30 +08:00 |
|
fanlusky
|
facafdcd7b
|
refactor(server): 移除外部皮肤 manifest 中已无用途的 preview 字段
preview 原本只用来充当候选框装饰图;装饰图改由 decoration.image 指定后,它不再被任何渲染或设置页使用。
|
2026-09-28 19:51:51 +08:00 |
|
fanlusky
|
24b2444a3d
|
feat(server): 外部皮肤支持候选框背景图、自定义圆角与装饰图对齐
- skin.toml 新增 candidate_window.corner_radius_dip、candidate_window.background(image / fit / opacity)和 decoration.image / decoration.align
- decoration 表改为可选;存在时 image、top_inset_dip、width_dip 必填且图片必须存在,不再回退到 preview
- D2D 候选框的装饰图与卡片同列排布,按 width_dip × top_inset_dip 等比缩放、贴在卡片上方且不重叠,卡片最小宽度遵守 min_width_dip 和装饰宽度,与 WebView2 渲染一致
- WebView2 端生成对应的背景、圆角和对齐 CSS;皮肤重载后 D2D 场景随之重建
|
2026-09-28 19:36:37 +08:00 |
|
Jia Sui
|
825fdebdfa
|
refactor(server): 去掉五笔混输无来源的配置迁移分支
|
2026-09-28 18:30:40 +08:00 |
|
Jia Sui
|
456fdb819c
|
feat(engine,server,ui-html,installer): 五笔拼音混输改为同时混排并拆出独立开关
Signed-off-by: Jia Sui <jsfaint@gmail.com>
|
2026-09-28 17:55:36 +08:00 |
|
fanlusky
|
f486da52b9
|
fix(ui-html): 悬停在选中候选上不再改变高亮色
fluent 与石墨的 .hover-active .cand:hover 特异度高于 .first,悬停选中项会换成
悬停色;改为 :not(.first),与微信绿、杨柳青、秋桂一致。自定义皮肤的 selected
同时写入 .hover-active .cand.first:hover,避免被 base 皮肤的选中悬停色(如微信绿
#07c160)覆盖。设置页预览样式同步。
|
2026-09-28 14:20:17 +08:00 |
|
fanlusky
|
b8c6a18ca2
|
fix(server): D2D 候选窗横排首尾高亮与外框同 R,自定义皮肤按 base 取几何
fluent、微信绿横排设置 outerItemRadius,对应 CSS 的首尾项圆角规则。
自定义皮肤包先加载,皮肤分支按 package->base 判断,与 WebView2 注入
base 皮肤 CSS 的行为一致,颜色仍由包覆盖。
|
2026-09-28 13:11:40 +08:00 |
|
fanlusky
|
841b846f64
|
feat(server): 整句候选来源标签可在设置页关闭
新增 association.sentence_source_badge(默认开启,保持现有行为),
控制候选窗整句候选后的〔Trigram〕〔Unigram〕〔神经D〕〔神经K〕标签是否显示。
关闭只隐藏标签,不影响候选内容与排序;云/AI 角标不受影响。
同步更新出厂模板、开发配置、两个设置窗口宿主的读写映射和设置页开关。
|
2026-09-28 12:04:43 +08:00 |
|
fanlusky
|
4e17d27ea7
|
feat(server,ui-html,installer): 悬浮工具栏支持无交互自动隐藏
新增 general.floating_toolbar_auto_hide(默认关闭)和
general.floating_toolbar_auto_hide_delay(1–60 秒,默认 5)。开启后,工具栏显示满延时且
无交互时约 0.4 秒淡出并隐藏;鼠标悬停在工具栏上时倒计时重置,淡出中移入会立即恢复。
中英、全半角、标点、Caps Lock、英文模式、简繁或日文模式真正变化时重新显示并重新计时;
普通的焦点切换和 IME 激活不会把已自动隐藏的工具栏带回来。
悬停用 GetCursorPos 与 GetWindowRect 轮询判断,两者同为物理像素,不涉及 DPI 换算,
也不需要页面侧新增消息,D2D 与 WebView2 两种后端共用。预热、首帧宽限和 cloak 期间不计时。
淡出结束时以 alpha 0 隐藏,下次显示之前再恢复 255,避免在隐藏瞬间闪出一帧不透明画面。
两个新键已写入出厂模板和开发配置,两个设置宿主的字段列表与分发都已补上,并放在
general.floating_toolbar_ 按钮项前缀兜底之前。设置页在工具栏卡片内新增开关和缩进的
延时行,延时用新增的通用 −/+ 步进器,开关关闭时延时行置灰。
|
2026-09-28 01:09:10 +08:00 |
|
fanlusky
|
396bd21715
|
feat(server,ui-html,installer): 整句联想默认开启词格、Google 和神经速度档
sentence_wordlattice、sentence_google、sentence_neural_keyboard 出厂默认改为 true;
sentence_neural_desktop 与 sentence_show_next_on_duplicate 保持关闭。出厂模板、开发配置、
代码缺键回退和设置页开关初始状态一并改。这几个开关尚未发版,不涉及老用户配置迁移。
Prepare-PackageFiles.ps1 增加断言:这三个开关在出厂模板里未开启时打包失败。
|
2026-09-27 23:43:13 +08:00 |
|
fanlusky
|
0a1b302b1c
|
feat(server,ui-html,installer): 设置窗口后台驻留默认改为关闭后立即退出
settings_window_linger 的出厂默认值从 "10m" 改为 "off"。出厂模板、开发配置、
缺键/非法值回退、设置进程初始值和设置页下拉框初始文字一并改;该功能尚未发版,
不涉及老用户配置迁移。
Prepare-PackageFiles.ps1 增加断言:出厂模板的驻留值不是 off 时打包失败。
|
2026-09-27 23:02:34 +08:00 |
|
Lu Fan(SonnyCalcr)
|
bb8c5e9be8
|
Merge pull request #495 from fanlusky/refactor/split-config-and-controls
refactor(server,ui): 按职责拆分 ime_config.cpp 与 Controls.cpp
|
2026-09-27 18:06:05 +08:00 |
|
fanlusky
|
b5def6a2e3
|
refactor(server): 按职责拆分 ime_config.cpp
ime_config.cpp 有 4000 行,配置状态与加载、TOML 文本编辑、升级时的模板合并、
写回与通知 Server,以及上百对 GetConfigured* / SetConfigured* 全挤在一个文件里。
按职责拆成以下几个翻译单元:
- ime_config.cpp:全部配置全局变量的定义(顺序与初始值不变)、语音配置的读写锁
快照与发布、各项校验白名单、LoadImeConfig(读取与缺省值)、旧版语音配置迁移、
InitImeConfig / ReloadImeConfigIfChanged / InvalidateImeConfigWriteTime
- ime_config_toml.cpp:保留格式的键值替换与插入、跨行值定位、赋值遍历与解析、
读文件、原子写文件与 TOML 解析校验
- ime_config_template.cpp:凭证兜底重放、MergeTomlIntoTemplate /
MergeConfigIntoTemplate、损坏配置的留证与抢救、SyncConfigWithInstalledTemplate、
旧 ACP 乱码目录的配置找回
- ime_config_write.cpp:WriteConfiguredValues / WriteConfiguredValue 与
NotifyImeServer*(Aux 管道与窗口消息两条通知路径)
- ime_config_appearance.cpp:每页候选数、字体与字号、文字颜色、候选窗布局与跟随
光标、小窗 UI 后端、皮肤、预编辑样式、固定徽标、设置窗口保留时长
- ime_config_fonts.cpp:ResolveSystemFontFamilyForCss 与 GetSystemFontFamilies
- ime_config_theme.cpp:主题模式、各界面主题覆盖与 ResolveConfiguredTheme
- ime_config_input.cpp:输入方案与中日文模式、简繁、中英切换键、双拼与五笔方案、
上屏样式、辅助码、全拼纠错、模糊音、调频
- ime_config_keys.cpp:翻页键、方向键选词、以词定字、智能标点、配对标点、标点锁定
及发给 TSF 的载荷
- ime_config_toolbar.cpp:悬浮工具栏与光标状态角标
- ime_config_general.cpp:诊断日志、输入统计、中英与表情混输、候选翻译、云候选、
整句联想、工具模式与剪贴板历史
- ime_config_services.cpp:语音输入、AI 助手、腾讯 TMT、自定义翻译与小牛翻译
- ime_config_internal.h:上述文件之间共享的声明,只给 ime_config*.cpp 包含
纯搬移,不改行为:函数体、注释和格式都没动。原来在匿名命名空间里、现在
要跨文件用的符号放进 ime_config_detail 命名空间并在内部头文件里声明,
避免与 Server 其他翻译单元里的同名内部符号冲突;只被一个文件用到的仍留在
该文件的匿名命名空间,包括 g_session_backend、两个语音 token 槽位补写标记、
g_config_last_write_time、PublishVoiceInput、AiAssistantProviders、LoadImeConfig
和各文件自己的小工具。全局变量的定义都还在 ime_config.cpp,按原顺序排列,
初始化顺序不变;函数内的 static(字体缓存、DirectWrite 工厂、凭证键表、剪贴板
首次加载标记等)仍各自只有一份定义。取值范围常量、kFuzzyPinyinRuleKeys、
ConfigFileLock、ParseScheme 前置声明、模板文件名、TomlAssignmentVisitor 和
ConfigValueUpdate 原样挪进内部头文件。MetasequoiaImeServer、
MetasequoiaImeSettings 和测试工程都编译 ime_config.cpp,三处源文件列表一并
补上新文件。
非搬移改动只有两处:NotifyImeServer 的默认实参从定义挪到了头文件里的声明上;
测试里 kFuzzyPinyinRuleKeys 副本的注释改指 ime_config_internal.h。
用脚本比对了原文件与拆分后全部文件的非空、非 #include 行多重集:除上述
函数签名外,差异只有新增的声明、extern、命名空间包装、using 指令、
#pragma once 和文件头注释。可用 git diff --color-moved 复核。
|
2026-09-27 17:22:17 +08:00 |
|
fanlusky
|
4b30659fca
|
ci: 单独构建并运行引擎自己的测试
Server 任务以 BUILD_TESTING=OFF 把引擎当库引入(避免 EXCLUDE_FROM_ALL 下的测试
找不到可执行文件),于是引擎的 23 组测试从来没在 CI 里跑过,只在开发机上跑。
server/tests 覆盖不到的行为——比如用户日志的连接管理、关闭它时要放开数据目录里
所有缓存句柄——只有这些测试能发现;#491 的一个回归就是这样在本地才测出来的。
新增 Engine 任务:按 engine/vcpkg.json 单独配置引擎、构建、再用
scripts/ci/test-engine.ps1 在与 Server 相同的锁定词库上跑 ctest。数据目录与
LOCALAPPDATA 都隔离到临时目录,布局与 test-server.ps1 一致。同步更新
server/CMakeLists.txt 里「引擎测试经 server/tests 覆盖」的旧说法。
本地按同样命令(不设 BOOST_ROOT,只靠 vcpkg 清单)配置、构建并运行:23/23 通过。
|
2026-09-27 16:54:20 +08:00 |
|
fanlusky
|
8f2c81dd0f
|
perf(server,engine): 选词学习的写库挪出按键线程
权重调整(AdjustCandidateRanking)和输入过的英文词(LearnEnteredEnglishWord)
原本和按键排在同一个 worker 队列里:每次选非首位候选都要在下一个键之前付一次
用户日志的提交和 fsync,触发阈值时还有 msime.db 的一次提交。磁盘忙或杀软扫描
时,这就是肉眼可见的卡顿。
- server/src/utils/serial_task_runner:单线程、按提交顺序执行、低优先级,Stop()
先执行完队列再退出,选词不会在退出时丢失。附单元测试。
- 两类写入改为投递给这个执行器。它们只调用 user_dictionary,不碰输入会话;唯一
的会话副作用——权重变化后清引擎候选缓存——经 EnqueueResetInputSessionCacheTask
回到 worker。删除对应的 TaskType 和 Task 字段。main 在 worker join 之后调用
ShutdownDictionaryWriter()。
- user_dictionary:默认日志连接改为每线程一条。FULLMUTEX 只保证单次调用安全,
保证不了事务:连接只有一个事务状态,写线程的 BEGIN IMMEDIATE..COMMIT 会把
worker 的读卷进来,worker 侧 UserDatabase 析构时还会把它回滚。
close_default_user_database() 递增代号,各线程下次访问时关闭旧连接。
- WorkerThread 取任务改为 move,不再每次复制整个 Task。
行为变化:选词后如果写入还没完成就立刻再打同一串,会短暂看到旧顺序;写完后
worker 清缓存,下一次查询即是新顺序。此前的“下一个键之前一定写完”换成了不阻塞
按键。
|
2026-09-27 16:09:51 +08:00 |
|
fanlusky
|
a8b5246852
|
refactor(server): 按职责拆分 ime_windows.cpp
ime_windows.cpp 有 4600 行,窗口创建与总窗口过程、候选窗定位与裁剪、WebView2
候选窗显示流程、候选窗消息处理、悬浮工具栏、托盘菜单、设置窗口和光标状态角标
全挤在一个文件里。按职责拆成以下几个翻译单元:
- ime_windows.cpp:共享状态与全局变量、系统明暗切换判定、宿主 cloak 与状态
描述(DescribeCandidateHostState、DescribeTrayMenuHostState 等)、
SyncHostWebViewBounds、ApplyConfiguredInputScheme / ApplyConfiguredShuangpinSchema、
窗口类与消息注册、CreateCandidateWindow、WndProc 分发,以及光标状态角标的
WndProcCaretStateWindow
- ime_windows_candidate_layout.cpp:光标锚点、四分之一屏宿主尺寸、装饰偏移、
翻转与裁剪记忆、ReanchorCandidateHostToPaintedCard、
ClipCandidateWindowToContent / SetWindowRgn、KeepCandidateCardInsideHostAndMonitor
- ime_windows_candidate_show.cpp:RefreshCandidateClipAfterPaint、
PlaceCandidateHostNearCaret、槽位测量扩展裁剪、FinishCandidateShowAfterSlots
和两遍测量的 FineTuneWindow
- ime_windows_candidate.cpp:WndProcCandWindow(显示 / 隐藏 / 移动消息、去重与
隐藏宽限、DPI 变化、状态切换转发、配置同步定时器、候选鼠标动作)
- ime_windows_toolbar.cpp:悬浮工具栏的配置尺寸、拖动后收回可见屏幕、
LayoutFloatingToolbar、显隐决策与绘制宽限、ApplyConfiguredFloatingToolbarSize、
WndProcFtbWindow
- ime_windows_menu.cpp:托盘菜单的 DIP 到物理像素换算与 WndProcMenuWindow
- ime_windows_settings.cpp:设置窗口的前台激活与重试、非客户区与最大化按钮、
鼠标输入转发、WndProcSettingsWindow
- ime_windows_internal.h:上述文件之间共享的声明,只给 ime_windows*.cpp 包含
纯搬移,不改行为:函数体、注释和格式都没动。原来在匿名命名空间里、现在
要跨文件用的符号放进 ime_windows_detail 命名空间并在内部头文件里声明,
避免与 Server 其他翻译单元里的同名内部符号冲突;只被一个文件用到的仍留在
该文件的匿名命名空间,包括只有候选窗消息处理用到的强制重排、隐藏宽限与
去重签名状态,以及只有设置窗口用到的激活重试计数。其余共享全局变量的定义
仍在 ime_windows.cpp。WEBVIEW_DIAG_LOGF 宏、定时器 ID 与时长常量、
FineTuneWindow 等前置声明和 SuppressCandidateDpiChange 原样挪进内部头文件。
非搬移改动只有两处:LogCandidatePositionAudit 和 PlaceCandidateHostNearCaret
的默认实参从定义挪到了头文件里的声明上;DescribeTrayMenuHostState 上方注释
里的文件名改成 windows_webview2_menu.cpp,菜单的生命周期事件在上一次拆分后
已经搬到那里。
用脚本比对了原文件与拆分后全部文件的非空、非 #include 行多重集:除上述
两个函数签名和那一行注释外,差异只有新增的声明、命名空间包装、using 指令、
#pragma once 和文件头注释。可用 git diff --color-moved 复核。
|
2026-09-27 15:49:35 +08:00 |
|
fanlusky
|
f4aba3bcfc
|
refactor(server): 按职责拆分 windows_webview2.cpp
windows_webview2.cpp 有 5500 行,小窗 WebView2 环境与 controller 的排队创建、
Topmost 分阶段提升、皮肤注入、候选窗脚本、托盘菜单、设置窗口和悬浮工具栏全挤
在一个文件里。按职责拆成以下几个翻译单元:
- windows_webview2.cpp:共享状态与全局变量、小窗 WebView2 environment 创建与
controller 排队重试、导航就绪门控、lazy-topmost 分阶段提升、内容截断回退、
DPI / RasterizationScale 辅助、可见性与状态查询,以及 GetAppdataPath、
InitSmallWindowWebviews、PrepareTrayMenuWebviewForShow、ShutdownWebviews
- windows_webview2_skin.cpp:读取页面 HTML、外部候选皮肤 CSS 注入与资源内嵌、
PrepareHtmlForWnds,以及候选窗、悬浮工具栏的布局 / 主题 / 外观应用
- windows_webview2_candidate.cpp:候选内容与测量区脚本、悬停锁与粘性卡片脚本、
候选槽位增量更新、测量 bounds、OnControllerCreatedCandWnd 与页面消息处理
- windows_webview2_menu.cpp:托盘菜单 controller 创建与页面消息处理、
SyncMenuFloatingToolbarToggle
- windows_webview2_settings.cpp:设置窗口的 DirectComposition 视觉树、
composition controller、设置页消息与 configUpdate 分发、
PostSettingsWindowState、PostSettingsConfig、InitWebviewSettingsWnd
- windows_webview2_toolbar.cpp:悬浮工具栏状态缓存与渲染脚本、
OnControllerCreatedFtbWnd 与页面消息处理、各个 UpdateFtb*
- windows_webview2_internal.h:上述文件之间共享的声明,只给
windows_webview2*.cpp 包含
纯搬移,不改行为:函数体、注释和格式都没动。原来在匿名命名空间里、现在
要跨文件用的符号(导航就绪标志、工具栏导航重试与绘制宽限标志、内容截断冷却
时间戳、JsonNumberAsDouble、HandleContentTruncatedMessage、
OnSmallWindowControllerSettled、NotifySmallWindowNavigationReady)放进
windows_webview2_detail 命名空间并在内部头文件里声明,避免与 Server 其他
翻译单元里的同名内部符号冲突;只被一个文件用到的仍留在该文件的匿名命名空间。
共享全局变量的定义仍在 windows_webview2.cpp。诊断日志的屏蔽宏、json 别名、
前置声明和 kTruncationSizeFactor 原样挪进内部头文件,每个拆出的文件都先包含
它,日志宏在各文件里仍是同样的空展开。
用脚本比对了原文件与拆分后全部文件的非空、非 #include 行多重集:原文件的
每一行都恰好出现一次,差异只有新增的声明、命名空间包装、using 指令、
#pragma once 和文件头注释。可用 git diff --color-moved 复核。
|
2026-09-27 15:38:01 +08:00 |
|
fanlusky
|
b6ca8bd8ba
|
refactor(server): 按职责拆分 event_listener.cpp
event_listener.cpp 有 5700 行,按键、候选组页、异步候选合并、选词、任务
队列和命名管道服务端全挤在一个文件里。按职责拆成以下几个翻译单元:
- event_listener.cpp:共享状态(特殊模式开关、UILess、译文缓存、异步请求
来源、状态快照、候选 UI 归属)、模式判定与候选窗显隐辅助,以及
CancelCloudCandidateRequest、RegisterStatusSnapshotWindow、
SendCurrentDataToClient、SendUiLessCompositionToClient、ClearState
- event_listener_worker.cpp:Task 定义、任务队列、顶字 Hide 抑制记账、
WorkerThread 分发循环、ReplayDeferredClientActivation 和各个 Enqueue*
- event_listener_pipes.cpp:管道握手与日志辅助、各管道监听线程、主管道
客户端线程、RegisteredPipeMonitorThread、关停时唤醒监听
- event_listener_candidates.cpp:候选组页与发布(BuildCurrentCandidatePage、
RefreshCandidatePageUi 等)、调频排序键、翻页扩展、PrepareCandidateList
- event_listener_async_candidates.cpp:云联想、AI、神经重排、英文、译文、
emoji、颜文字的 Apply* 合并
- event_listener_keys.cpp:按键分类、ApplyCompositionEditKey、译文副候选页、
五笔顶字负载、PublishRestoredCompositionCandidates、HandleImeKey
- event_listener_selection.cpp:ResolveCandidateItem、
WaitForCandidateRenderSync、ProcessSelectionKey
- event_listener_internal.h:上述文件之间共享的声明,只给
event_listener*.cpp 包含
纯搬移,不改行为:函数体、注释和格式都没动。原来在匿名命名空间里、现在
要跨文件用的符号放进 event_listener_detail 命名空间并在内部头文件里声明,
避免与 Server 其他翻译单元里的同名内部符号冲突;只被一个文件用到的仍留在
该文件的匿名命名空间。共享全局变量的定义仍在 event_listener.cpp。唯一的
非搬移改动是 UpdateCloudInput/UpdateEnglishInput/UpdateEmojiInput/
UpdateKaomojiInput/UpdateAiInput 的默认实参从定义挪到了头文件里的声明上。
用脚本比对了原文件与拆分后全部文件的非空、非 #include 行多重集:除上述
五个函数签名外,差异只有新增的声明、命名空间包装、using 指令、
#pragma once 和文件头注释。可用 git diff --color-moved 复核。
|
2026-09-27 15:26:19 +08:00 |
|
fanlusky
|
356884bf0a
|
perf(server): 译文没有变化时不重绘候选页
ApplyCandidateTranslations 每次收到译文结果都 RefreshCandidatePageUi(true),
即使译文与已有的完全相同。候选页构建时本就从 g_candidate_translation_glosses
读译文,新按键的候选大多已在上一页查过,于是每键多出一次整页发布和绘制,
还会让随后的空格/数字选词多等一次渲染同步。
只有译文表确实新增、改写或删除条目时才刷新。
|
2026-09-27 15:03:17 +08:00 |
|