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 复核。
Metasequoia IME Server(水杉输入法 Server 端)
This is the server end of MSIME-Windows.
How to build
Prerequisites
- Visual Studio 2026
- CMake
- vcpkg
- Python3.10+
- Boost
- Node.js and pnpm 10 (settings page build)
Make sure vcpkg and Boost are installed by Scoop.
Build steps(For Dev)
Clone the product and provision the reviewed dictionary release from its root:
git clone --recursive https://github.com/metasequoiaime/MSIME-Windows.git
cd MSIME-Windows
python scripts/product_lock.py fetch-dictionaries --staging-root .
if ($LASTEXITCODE -ne 0) { throw 'Dictionary verification failed' }
$devLocalData = Join-Path $PWD 'build/dev-local'
$devData = Join-Path $devLocalData 'metasequoiaime'
New-Item -ItemType Directory -Force $devData | Out-Null
Copy-Item MetasequoiaImeDict/out/* $devData -Force
Copy-Item engine/helpcode/helpcodes $devData -Recurse -Force
Copy-Item server/assets/tables/* $devData -Force
Copy-Item server/assets/config/config.toml $devData -Force
Push-Location ui-html/webview2/settings/ime-settings
try {
pnpm install --frozen-lockfile
if ($LASTEXITCODE -ne 0) { throw 'Settings dependencies failed' }
pnpm build
if ($LASTEXITCODE -ne 0) { throw 'Settings page build failed' }
} finally { Pop-Location }
$devWebview = Join-Path $devData 'html/webview2'
New-Item -ItemType Directory -Force $devWebview | Out-Null
foreach ($part in @('shared', 'candwnd', 'ftb', 'menu')) {
Copy-Item "ui-html/webview2/$part" $devWebview -Recurse -Force
}
$devSettings = Join-Path $devWebview 'settings/ime-settings'
New-Item -ItemType Directory -Force $devSettings | Out-Null
Copy-Item ui-html/webview2/settings/ime-settings/dist $devSettings -Recurse -Force
python server/scripts/prepare_env.py
if ($LASTEXITCODE -ne 0) { throw 'Server environment setup failed' }
$env:LOCALAPPDATA = $devLocalData
$env:METASEQUOIA_IME_DATA_DIR = $devData
cd server
Use a dedicated PowerShell terminal. These steps stage the same locked data as CI
and the current product pages in a separate development directory. Both
LOCALAPPDATA (Windows config/pages) and METASEQUOIA_IME_DATA_DIR (Engine data)
are set for that terminal; setting only the latter would still use installed
Windows configuration and pages. Close the terminal after development.
Dictionary source changes belong in Engine's dictionary/; use its root build_profile.py
to build data instead of calling internal stages in the archived Dict repository.
Then, build and run,
.\scripts\lcompile.ps1
.\scripts\lrun.ps1
If you want to build and run in one step, run the following command,
.\scripts\llaunch.ps1
Watchdog
MetasequoiaImeWatchdog.exe is built next to the server. Starting the server directly also starts the watchdog,
which monitors the server from the same directory and restarts it after an unexpected exit. Repeated early crashes use
an exponential restart delay (up to 30 seconds) to avoid a restart storm.
The developer terminate shortcut stops both processes. The restart shortcut asks the watchdog to start a fresh server after the current process exits.
English prefix candidates
Place english.db next to msime.db in %LOCALAPPDATA%\metasequoiaime. Set
general.cn_en_mixed_input = true in config.toml to enable asynchronous English prefix candidates for Quanpin and
Shuangpin.
Developer Shortcuts
The server process includes a few built-in global shortcuts that are useful during development:
Ctrl + Shift + Alt + T- terminate
MetasequoiaImeServerimmediately
- terminate
Ctrl + Shift + Alt + R- restart
MetasequoiaImeServer - Settings exposes the same restart under 外观 → 重启输入法进程; it reaches the server over the Aux pipe because Settings runs in its own process
- restart
Ctrl + Shift + Alt + C- clear IME engine cache
Ctrl + Shift + Alt + 1toCtrl + Shift + Alt + 8- delete candidate
1to8from the current candidate window - this only works while the candidate window is visible
- delete candidate
Screenshots
Shared voice providers
The server links Engine VoiceCapture and Voice. WAV encoding and batch transcription/polish codecs come from the public library; Windows keeps provider configuration, SiliconFlow padding/retry behavior and Doubao streaming. Batch uploads are bounded to 20 MiB and responses to 1 MiB. Failed or empty polish responses retain the original transcript.
本地 Release 构建脚本可通过 -ManifestTool <mt.exe 路径> 使用其他 Windows SDK;未指定时沿用现有 SDK 路径。配置、编译或 manifest 嵌入失败都会中止,避免安装器收集旧产物。






