Skip to content

fix(windows-ime): force-skip TSF on non-zh hosts to stop ATOK/MS-IME hijack#362

Closed
katanumahotori wants to merge 2 commits intoOpen-Less:betafrom
katanumahotori:fix/windows-ime-tsf-skip-on-non-zh
Closed

fix(windows-ime): force-skip TSF on non-zh hosts to stop ATOK/MS-IME hijack#362
katanumahotori wants to merge 2 commits intoOpen-Less:betafrom
katanumahotori:fix/windows-ime-tsf-skip-on-non-zh

Conversation

@katanumahotori
Copy link
Copy Markdown
Contributor

@katanumahotori katanumahotori commented May 8, 2026

User description

Why

The bundled C++ TSF DLL hard-codes lang_id 0x0804 (zh-CN) in guids.h. On a Japanese host this either:

  • (a) hijacks the active IME to a Chinese-IME profile and leaves it stuck after dictation, or
  • (b) fails activation and falls back via SendInput, which competes with ATOK / Microsoft IME composition state.

End user impact: text comes out reordered (kanji pushed to the end while hiragana is queued in the IME composition window), or the user's IME is silently switched and they have to reset it manually.

What

This PR is a stop-gap that forces prepare_session() in windows_ime_session.rs to return unavailable() so all insertion goes through the clipboard+SendInput fallback in coordinator.rs.

  • windows_ime_session.rsprepare_session() now short-circuits to Unavailable before attempting to load the TSF DLL.
  • windows_ime_profile.rs — bumps OPENLESS_TSF_LANG_ID default from 0x0804 to 0x0411 (Japanese) as a partial mitigation for users who do manage to load the DLL.
  • windows_ime_ipc.rs, windows_ime_protocol.rsdead_code attributes added to the now-unused TSF helpers so the fork builds clean while the path is gated.

Follow-up

The proper fix is a per-host lang_id in both guids.h and windows_ime_profile.rs, plus a DLL rebuild. Not in this PR.


PR Type

Bug fix, Enhancement, Tests


Description

  • Force-skip TSF IME activation on non-Chinese hosts

  • Add runtime host UI language detection on Windows

  • Use dynamic language id for profile activation

  • Suppress dead code warnings for unused TSF helpers


Diagram Walkthrough

flowchart LR
  A["prepare_session() in\nwindows_ime_session.rs"] --> B["host_ui_lang_id()"]
  B --> C{"Primary language\nis Chinese?"}
  C -- "Yes" --> D["openless_tsf_lang_id()"]
  D --> E["activate_openless_profile()\nwith dynamic lang id"]
  C -- "No" --> F["Return unavailable()"]
  F --> G["Fallback to clipboard+SendInput"]
  D -.-> H[windows_ime_profile.rs new functions]
  E -.-> H
Loading

File Walkthrough

Relevant files
Bug fix
windows_ime_session.rs
Gate TSF session preparation on host UI language                 

openless-all/app/src-tauri/src/windows_ime_session.rs

  • Short-circuit prepare_session to return unavailable() on non-zh hosts
  • Add host UI language check using host_ui_lang_id()
  • Keep full TSF activation path for zh hosts
  • Log skipped TSF path info
+20/-0   
Enhancement
windows_ime_profile.rs
Dynamic language‑id resolution and dead‑code suppression 

openless-all/app/src-tauri/src/windows_ime_profile.rs

  • Remove hardcoded OPENLESS_TSF_LANG_ID constant
  • Add host_ui_lang_id() using GetUserDefaultUILanguage on Windows
  • Add openless_tsf_lang_id() that returns 0x0804 for zh hosts or host
    lang id otherwise
  • Update activate_openless_profile() and is_openless_profile_active() to
    use dynamic lang id
  • Add #[allow(dead_code)] to several unused items (profile activation,
    constants, error variants)
  • Adjust test to remove constant assertion
+55/-7   
Miscellaneous
windows_ime_ipc.rs
Suppress dead‑code warnings for unused IPC components       

openless-all/app/src-tauri/src/windows_ime_ipc.rs

  • Add #[allow(dead_code)] on Unavailable variant, WindowsImeIpcServer
    inner field and test helpers
  • Document dead‑code rationale in comments
+10/-0   
windows_ime_protocol.rs
Allow dead code on unused protocol helper                               

openless-all/app/src-tauri/src/windows_ime_protocol.rs

  • Add #[allow(dead_code)] to is_result_for_pending_session function
  • Add comment explaining why it is kept for future IPC client
+3/-0     

…hijack

The bundled C++ TSF DLL hard-codes lang_id 0x0804 (zh-CN) in guids.h,
which on a Japanese host either (a) hijacks the active IME to a
chinese-IME profile and leaves it stuck after dictation, or
(b) fails activation and falls back via SendInput, which competes
with ATOK / Microsoft IME composition state.

This PR is a stop-gap that forces prepare_session() to return
unavailable() so all insertion goes through the clipboard+SendInput
fallback in coordinator.rs. The proper fix is a per-host lang_id in
both guids.h and windows_ime_profile.rs plus a DLL rebuild - tracked
as a follow-up.

Also bumps OPENLESS_TSF_LANG_ID from 0x0804 to 0x0411 (Japanese) in
windows_ime_profile.rs as a partial mitigation for users who do
manage to load the DLL.

dead_code attributes added to the now-unused TSF helpers so the
fork builds clean while the path is gated.
@chatgpt-codex-connector
Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 8, 2026

PR Reviewer Guide 🔍

(Review updated until commit c994675)

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ No major issues detected

@H-Chris233
Copy link
Copy Markdown
Collaborator

H-Chris233 commented May 8, 2026

这就是为什么你直接关闭了整个tsf以及硬编码日文ID?我们不会合并你的pr,至少现在不会。虽然你提出的问题确实有价值,但你的实现方式不是很有用。

@katanumahotori
Copy link
Copy Markdown
Contributor Author

Thanks for the review. You're right that "force-skip + hard-coded lang_id" was a stop-gap. This commit replaces it with a per-host check:

  • prepare_session() now calls GetUserDefaultUILanguage() and only routes through unavailable() when the host UI is not zh. zh hosts go through the existing TSF path unchanged.
  • OPENLESS_TSF_LANG_ID is no longer a hard-coded constant — it's resolved at runtime from the host UI language so a Japanese host registers as 0x0411, an English host as 0x0409, etc.
  • The C++ side (guids.h::kOpenLessLangId = 0x0804) is still hard-coded; that's a follow-up because it requires a DLL rebuild. With this PR, Rust no longer fights the DLL on zh hosts — only on non-zh hosts where the DLL would have caused the IME hijack anyway.

Please take another look — I want to keep the fix minimal but actually useful.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 8, 2026

Persistent review updated to latest commit c994675

@katanumahotori
Copy link
Copy Markdown
Contributor Author

Thanks for the review. You're right — the current Rust-side per-host check is still only a partial fix. The proper solution requires parameterizing kOpenLessLangId in guids.h and rebuilding the C++ TSF DLL with a per-host (or build-time) lang_id, which I haven't done in this PR.

Closing this to avoid noise. I'll resubmit only after the C++/DLL side is also in order. Sorry for the back-and-forth.

@katanumahotori katanumahotori deleted the fix/windows-ime-tsf-skip-on-non-zh branch May 9, 2026 00:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants