Files
msime-windows/server
fanlusky eadcca9f1b fix(server): 候选窗贴边后不再随内容变化上下左右乱飘
候选窗一旦贴住屏幕右边缘,删字后右边缘就会离开边缘;靠近屏幕下边缘时,它有时
正常停在当前行上方,有时却盖住当前行的文字。两者是同一个病根:最终定位用的不是
候选卡片本身,或者压根没有重新定位。

D2D:PlaceAndShow 末尾的水平夹取用的是宿主窗口宽度。宿主带透明阴影内边距、向上
取整到 64px、而且打字过程中只增不减,于是卡片被这些余量整体推离右边缘;删字后过
大的宿主宽度被保留,卡片左边缘就被冻住。改成夹取不透明卡片,和紧随其后的垂直夹取
用同一条规则,透明宿主允许越过屏幕边缘。

WebView2:内容更新只走「重绘不重排」的两条路径,它们从不重做上下翻转判定,只是
(a) 用「MarginTop -= 高度差」这个累加器去粘住底边,(b) 交给
KeepCandidateCardInsideHostAndMonitor 夹取,而后者在卡片底边越过工作区下边界时
直接把卡片往上推。于是本来在光标下方勉强放得下的候选窗,一旦下一个键多出一行释义
变高,就被径直推到当前行文字上面。现在两条路径都改为用实际绘制出来的尺寸重新推导
锚点(ReanchorCandidateHostToPaintedCard)——翻转判定只能信这个高度——两个累加器
随之删除。

另有两处一致性修补:MarginLeft/MarginTop 超出宿主可用余量时改为平移宿主而不是截断,
截断会让卡片毫无理由地吸到宿主的另一端;翻转判定的下边界改用 coordinates.bottom -
edgePadPx,与下游所有夹取共用一条线,否则会判定「下方放得下」,再被 2 DIP 边距顶
回来压到文字上。

已知未处理:翻转时的行高仍是写死的 24 DIP,因为 IPC 只传了文本范围的 left 和
bottom,行高在 GetPhysicalTextAnchor 里就被丢掉了。宿主报出的行比 24 DIP 高时,
翻转后的卡片底边仍会压进那一行——但现在是稳定的偏低,不再忽上忽下。
2026-09-13 03:07:52 +08:00
..
2026-03-12 01:34:41 +08:00
2025-04-16 02:03:11 +08:00
2025-11-10 21:10:36 +08:00

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 MetasequoiaImeServer immediately
  • 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
  • Ctrl + Shift + Alt + C
    • clear IME engine cache
  • Ctrl + Shift + Alt + 1 to Ctrl + Shift + Alt + 8
    • delete candidate 1 to 8 from the current candidate window
    • this only works while the candidate window is visible

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 嵌入失败都会中止,避免安装器收集旧产物。