Skip to content

Avoid Windows modifier and TSF input hangs#715

Draft
AdonisJC wants to merge 3 commits into
Open-Less:betafrom
AdonisJC:codex/windows-modifier-hotkey-hang-fix
Draft

Avoid Windows modifier and TSF input hangs#715
AdonisJC wants to merge 3 commits into
Open-Less:betafrom
AdonisJC:codex/windows-modifier-hotkey-hang-fix

Conversation

@AdonisJC

@AdonisJC AdonisJC commented Jun 19, 2026

Copy link
Copy Markdown

User description

Summary

This PR addresses a Windows hang pattern where taskbar interactions and already-open app windows appear frozen after OpenLess dictation is used with modifier-only hotkeys such as Right Ctrl or Right Alt.

The current root fix is to keep OpenLess dictation usable while disabling the in-process Windows TSF IME backend by default. OpenLess now inserts through paced Unicode SendInput by default, and the TSF backend is treated as optional/experimental instead of being registered and activated for every Windows install.

Root Cause

Local dump and event-log analysis showed affected Chromium/Electron processes loading the Windows text-input stack together with OpenLess's TSF DLL:

  • OpenLessIme.dll
  • MSCTF.dll
  • TextInputFramework.dll
  • weasel.dll / Rime Weasel text-input chain
  • COM / ASTA / wait and message-send paths such as WaitForSingleObject and SendMessageTimeoutW

The visible symptom can look like Explorer or the taskbar is broken, but the more repeatable failure is that foreground app UI threads hang while Windows text input is participating in the host process. Clicking a minimized Chrome/Codex/Notepad-style window from the taskbar then appears to do nothing because the target app is already stuck.

The earlier modifier-only hotkey fix is still useful because OpenLess should not swallow physical Ctrl/Alt events. However, later captures showed hangs still occurring after changing hotkeys, so the TSF backend itself is the higher-confidence root cause.

Changes

  • Add windows_tsf_backend_enabled, defaulting to false for existing and new users.
  • Skip WindowsImeBackend::prepare_session() unless the experimental TSF backend is explicitly enabled.
  • When TSF is disabled, insert dictated text via paced Unicode SendInput and fall back to clipboard copy if that fails.
  • Stop NSIS and MSI installers from registering OpenLessIme.dll as a TSF TIP by default.
  • Keep uninstall/upgrade cleanup for legacy OpenLess TSF registrations.
  • Update installer smoke tests to assert OpenLess is installed while TSF registry keys are absent by default.
  • Update UI/i18n copy so the Windows TSF backend is described as experimental and optional.
  • Preserve the prior commit that avoids swallowing modifier-only Windows hotkeys.

Local Mitigation Verified

On the affected Windows machine, the installed legacy OpenLess registration pointed to:

  • C:\Program Files\OpenLess\windows-ime\x64\OpenLessIme.dll
  • C:\Program Files\OpenLess\windows-ime\x86\OpenLessIme.dll
  • HKLM\Software\Microsoft\CTF\TIP\{6B9F3F4F-5EE7-42D6-9C61-9F80B03A5D7D}

After removing those OpenLess-specific TSF registration keys, registry re-checks confirmed they were absent. This does not disable OpenLess itself and does not change other Windows input methods.

Validation

Ran locally:

node openless-all/app/scripts/windows-package-msvc.test.mjs
cargo test --manifest-path openless-all/app/src-tauri/Cargo.toml windows_tsf --lib
npm run build
git diff --check

Results:

  • Installer static test passed.
  • New Rust preference/default tests passed.
  • Frontend production build passed.
  • Diff whitespace check passed.
  • Existing Rust warnings are unrelated unused/dead-code warnings already present in the tree.
  • Existing Vite/Rollup circular re-export warnings are unrelated to this change.

Compatibility Notes

This intentionally changes the default Windows insertion path from TSF to Unicode SendInput. That is less invasive because it does not inject an OpenLess text-service DLL into Chromium/Electron/Notepad-style target processes. The packaged TSF DLLs and cleanup hooks remain available so a future explicit opt-in path can be added without leaving legacy registrations behind.


PR Type

Bug fix, Enhancement


Description

  • Disable Windows TSF IME backend by default

  • Avoid swallowing modifier-only hotkeys

  • Update installers to skip TSF registration

  • Add runtime checks to block TSF in shell processes


Diagram Walkthrough

flowchart LR
  A["Dictation session start"] --> B{"Windows TSF backend enabled?"}
  B -->|Yes| C["Prepare TSF IME session (experimental)"]
  B -->|No| D["Insert via paced Unicode SendInput"]
  C --> E["Insert via TSF"]
  D --> F["If SendInput fails, copy to clipboard"]
Loading

File Walkthrough

Relevant files
Enhancement
4 files
coordinator.rs
Adjust log messages in TSF fallback                                           
+3/-13   
dictation.rs
Conditionally prepare TSF IME session                                       
+29/-18 
types.rs
Add windows_tsf_backend_enabled preference                             
+24/-0   
types.ts
Add windowsTsfBackendEnabled field                                             
+2/-1     
Bug fix
3 files
hotkey.rs
Do not suppress modifier-only hotkeys                                       
+29/-13 
dllmain.cpp
Block injection into shell processes                                         
+43/-5   
text_service.cpp
Deactivate TSF in explorer process                                             
+22/-0   
Documentation
6 files
windows_ime_profile.rs
Update status messages for experimental TSF                           
+4/-2     
en.ts
Update descriptions for TSF and fallback                                 
+6/-6     
ja.ts
Update Japanese translations for TSF changes                         
+6/-6     
ko.ts
Update Korean translations for TSF changes                             
+6/-6     
zh-CN.ts
Update Chinese translations for TSF changes                           
+6/-6     
zh-TW.ts
Update Chinese (Taiwan) translations for TSF changes         
+6/-6     
Tests
4 files
mock-data.ts
Add windowsTsfBackendEnabled to mock data                               
+1/-0     
stylePrefs.test.ts
Add windowsTsfBackendEnabled to test data                               
+1/-0     
windows-ime-install-smoke.ps1
Assert TSF registry keys are absent                                           
+25/-38 
windows-package-msvc.test.mjs
Update test assertions for skipped registration                   
+18/-20 
Configuration changes
2 files
openless-ime-hooks.nsh
Skip default TSF registration in NSIS                                       
+1/-2     
openless-ime.wxs
Remove register actions from WiX InstallExecuteSequence   
+0/-2     

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

PR Reviewer Guide 🔍

(Review updated until commit 20dcf2a)

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Possible Path Bug on 32-bit Windows

The function Assert-OpenLessImeInstalled builds the install root candidates by comparing $env:ProgramFiles with ${env:ProgramFiles(x86)}. On 32‑bit Windows, ProgramFiles(x86) is not defined (empty string), so the comparison succeeds and an invalid path \OpenLess is added to the array. This can cause false negatives when searching for openless.exe or failures to locate the IME DLLs. The CI runs on 64‑bit Windows, so this error does not occur there, but it would break the smoke test on 32‑bit systems.

$installRootCandidates = @(
  (Join-Path $env:ProgramFiles "OpenLess")
)
if ($env:ProgramFiles -ne ${env:ProgramFiles(x86)}) {
  $installRootCandidates += (Join-Path ${env:ProgramFiles(x86)} "OpenLess")

@AdonisJC AdonisJC changed the title Avoid swallowing Windows modifier hotkeys Avoid Windows modifier and TSF input hangs Jun 20, 2026
@AdonisJC

Copy link
Copy Markdown
Author

Updated this PR with the follow-up root-cause finding and fix.

The newer local dumps pointed beyond modifier-key swallowing: affected Chromium/Electron-style apps were loading the OpenLess TSF DLL through the Windows text-input stack, then hanging in COM/message-wait paths. The new commit disables OpenLess TSF registration/activation by default and keeps dictation working through paced Unicode SendInput. Legacy OpenLess TSF registration is still cleaned during install/upgrade/uninstall.

This should address the recurring taskbar/app-window hang without disabling OpenLess or requiring users to avoid single Right Ctrl / Right Alt hotkeys.

@github-actions github-actions Bot changed the title Avoid Windows modifier and TSF input hangs Avoid swallowing Windows modifier hotkeys Jun 20, 2026
@AdonisJC AdonisJC changed the title Avoid swallowing Windows modifier hotkeys Avoid Windows modifier and TSF input hangs Jun 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 538d799

@github-actions

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 20dcf2a

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.

1 participant