Pre-submit Checks
Describe the bug
Warp becomes completely unresponsive (freezes, white screen, requires force-quit) when switching from English input method to Chinese IME (WeChat Input / 微信输入法) while typing inside WSL.
Key observations:
- Typing in exclusively English IME works fine.
- Typing in exclusively Chinese IME works fine.
- The freeze happens only at the moment of switching from English IME to Chinese IME (or vice versa) after having typed some text.
- The freeze occurs reliably with WeChat Input method. Other Chinese IMEs (Microsoft Pinyin, Sogou) likely affected as well.
- The freeze is not limited to the
/name scenario — it also happens in other contexts when switching IME while a TUI application is running.
Related Issues
This appears to be the same underlying class of bug as:
These are all manifestations of the same root issue: IME state transitions / input method switching triggers a deadlock (or infinite loop) in Warp's event processing pipeline.
To reproduce
- Windows 10/11 with Warp installed.
- Install WeChat Input Method (微信输入法) as a Chinese IME.
- Open Warp, enter WSL (wsl.exe).
- Run a TUI application that accepts text input (e.g.,
pi coding agent, nvim, tmux, etc.).
- Type a few characters in English (e.g.,
/name).
- Switch IME from English to Chinese (using Win+Space, language bar, or any other method).
- Result: Warp immediately freezes — the window goes white/unresponsive, and the process must be force-killed.
This can also be reproduced more directly without WSL:
- Open Warp on Windows (any shell: PowerShell, CMD, WSL).
- Press a shortcut that triggers IME/language switching (e.g., AutoHotkey script sending
WM_INPUTLANGCHANGE, or using Win+Space).
- Warp freezes.
Expected behavior
Warp should handle IME switching gracefully without freezing, just like every other terminal emulator on Windows (Windows Terminal, ConEmu, etc.).
Technical analysis (from source code)
I examined the relevant source code and believe the root cause is one or both of:
1. std::sync::Mutex re-entrancy deadlock in winit's WNDPROC (Windows message handler)
In the Windows event loop, IME events from winit are handled in handle_ime_event(). The winit fork (at commit 7ef01853ae3fe952e6014080a88dc4352662dfb1) processes Windows IME messages in its WNDPROC callback in event_loop.rs:
WM_IME_STARTCOMPOSITION => {
let ime_allowed = userdata.window_state_lock().ime_allowed;
// ...
userdata.send_event(Event::WindowEvent { event: WindowEvent::Ime(Ime::Enabled) });
}
The window_state field is Arc<Mutex<WindowState>> — a non-reentrant std::sync::Mutex. The event handler dispatched by send_event() flows into Warp's UI framework and may trigger calls back into winit (e.g., set_ime_position() → ImmSetCompositionWindow), which can generate Windows messages synchronously. If those messages re-enter the WNDPROC and try to acquire window_state_lock(), the std::sync::Mutex deadlocks on the same thread.
2. LAYOUT_CACHE mutex + PeekMessageW re-entrancy
In keyboard.rs, next_kbd_msg() calls PeekMessageW():
pub fn next_kbd_msg(hwnd: HWND) -> Option<MSG> {
let peek_retval = PeekMessageW(next_msg.as_mut_ptr(), hwnd, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE);
PeekMessageW can dispatch sent messages (via SendMessage from other threads) even when called with PM_NOREMOVE. If a sent message handler (e.g., from the IME) tries to acquire the same LAYOUT_CACHE mutex or window_state mutex while the current thread already holds it, deadlock.
3. IMM32 API re-entrancy
When IME is enabled, Warp calls set_ime_position() which invokes ImmSetCompositionWindow and ImmSetCandidateWindow. These IMM32 APIs can generate synchronous window messages that are processed immediately within the current stack frame, potentially causing re-entrant WNDPROC invocations.
Screenshots, videos, and logs
Will add if needed.
Operating system (OS)
Windows
Operating system and version
Windows 11
Shell Version
WSL2 (Ubuntu) + zsh
Current Warp version
Latest stable as of 2026-05-03
Regression
No, this bug or issue has existed throughout my experience using Warp
Does this block you from using Warp daily?
Yes, this issue prevents me from using Warp daily because I need to switch between English and Chinese when coding.
Is this an issue only in Warp?
Yes, I confirmed that this only happens in Warp, not other terminals (Windows Terminal works fine).
Suggested fix direction
- Replace
std::sync::Mutex with a re-entrant mutex (e.g., parking_lot::ReentrantMutex) for window_state in winit's Windows platform, OR ensure the mutex is never held across any call that can process Windows messages.
- Ensure
LAYOUT_CACHE mutex is not held when next_kbd_msg() is called, or use a re-entrant mutex there as well.
- Guard against re-entrant WNDPROC invocations by tracking re-entrancy depth (similar to the existing
recurse_depth field in WindowData).
The existing recurse_depth field in WindowData suggests the developers are already aware of re-entrancy concerns in the Windows message handler. This IME switching scenario is likely hitting an unprotected re-entrant path.
Pre-submit Checks
Describe the bug
Warp becomes completely unresponsive (freezes, white screen, requires force-quit) when switching from English input method to Chinese IME (WeChat Input / 微信输入法) while typing inside WSL.
Key observations:
/namescenario — it also happens in other contexts when switching IME while a TUI application is running.Related Issues
This appears to be the same underlying class of bug as:
These are all manifestations of the same root issue: IME state transitions / input method switching triggers a deadlock (or infinite loop) in Warp's event processing pipeline.
To reproduce
picoding agent,nvim,tmux, etc.)./name).This can also be reproduced more directly without WSL:
WM_INPUTLANGCHANGE, or using Win+Space).Expected behavior
Warp should handle IME switching gracefully without freezing, just like every other terminal emulator on Windows (Windows Terminal, ConEmu, etc.).
Technical analysis (from source code)
I examined the relevant source code and believe the root cause is one or both of:
1.
std::sync::Mutexre-entrancy deadlock in winit's WNDPROC (Windows message handler)In the Windows event loop, IME events from winit are handled in
handle_ime_event(). The winit fork (at commit 7ef01853ae3fe952e6014080a88dc4352662dfb1) processes Windows IME messages in its WNDPROC callback in event_loop.rs:The
window_statefield isArc<Mutex<WindowState>>— a non-reentrantstd::sync::Mutex. The event handler dispatched bysend_event()flows into Warp's UI framework and may trigger calls back into winit (e.g.,set_ime_position()→ImmSetCompositionWindow), which can generate Windows messages synchronously. If those messages re-enter the WNDPROC and try to acquirewindow_state_lock(), thestd::sync::Mutexdeadlocks on the same thread.2.
LAYOUT_CACHEmutex + PeekMessageW re-entrancyIn keyboard.rs,
next_kbd_msg()callsPeekMessageW():PeekMessageWcan dispatch sent messages (viaSendMessagefrom other threads) even when called withPM_NOREMOVE. If a sent message handler (e.g., from the IME) tries to acquire the sameLAYOUT_CACHEmutex orwindow_statemutex while the current thread already holds it, deadlock.3. IMM32 API re-entrancy
When IME is enabled, Warp calls
set_ime_position()which invokesImmSetCompositionWindowandImmSetCandidateWindow. These IMM32 APIs can generate synchronous window messages that are processed immediately within the current stack frame, potentially causing re-entrant WNDPROC invocations.Screenshots, videos, and logs
Will add if needed.
Operating system (OS)
Windows
Operating system and version
Windows 11
Shell Version
WSL2 (Ubuntu) + zsh
Current Warp version
Latest stable as of 2026-05-03
Regression
No, this bug or issue has existed throughout my experience using Warp
Does this block you from using Warp daily?
Yes, this issue prevents me from using Warp daily because I need to switch between English and Chinese when coding.
Is this an issue only in Warp?
Yes, I confirmed that this only happens in Warp, not other terminals (Windows Terminal works fine).
Suggested fix direction
std::sync::Mutexwith a re-entrant mutex (e.g.,parking_lot::ReentrantMutex) forwindow_statein winit's Windows platform, OR ensure the mutex is never held across any call that can process Windows messages.LAYOUT_CACHEmutex is not held whennext_kbd_msg()is called, or use a re-entrant mutex there as well.recurse_depthfield inWindowData).The existing
recurse_depthfield inWindowDatasuggests the developers are already aware of re-entrancy concerns in the Windows message handler. This IME switching scenario is likely hitting an unprotected re-entrant path.