fix(windows): restore ENABLE_WINDOW_INPUT console flag after enable_raw_mode for IME support

This commit is contained in:
donglovejava
2026-05-29 08:46:27 +08:00
committed by Hunter Bown
parent 1ff5db1663
commit 09d3131dc2
+39
View File
@@ -24,6 +24,7 @@ use crossterm::{
use crossterm::event::{
KeyboardEnhancementFlags, PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags,
};
#[cfg(target_os = "windows")]
use ratatui::{
Frame, Terminal,
layout::{Constraint, Direction, Layout, Rect, Size},
@@ -32,6 +33,8 @@ use ratatui::{
widgets::Block,
};
use tracing;
#[cfg(target_os = "windows")]
use windows::Win32::System::Console::{GetConsoleMode, GetStdHandle, SetConsoleMode};
use crate::audit::log_sensitive_event;
use crate::automation_manager::{AutomationManager, AutomationSchedulerConfig, spawn_scheduler};
@@ -280,6 +283,9 @@ pub async fn run_tui(config: &Config, options: TuiOptions) -> Result<()> {
}
}
#[cfg(target_os = "windows")]
enable_windows_ime_console_mode();
let mut stdout = io::stdout();
if use_alt_screen {
execute!(stdout, EnterAlternateScreen)?;
@@ -7042,6 +7048,36 @@ pub fn emergency_restore_terminal() {
let _ = execute!(stdout, LeaveAlternateScreen);
}
/// On Windows, ensure the console input handle has `ENABLE_WINDOW_INPUT`
/// (0x0008) set. crossterm's `enable_raw_mode()` removes this flag, which
/// breaks IME composition (Chinese/Japanese/Korean input methods cannot
/// commit characters) on some Windows configurations (e.g. Windows Terminal
/// in conhost compatibility mode, or the legacy console with VT input).
///
/// Best-effort and idempotent. Silently ignored if the console handle or
/// mode query fails.
#[cfg(target_os = "windows")]
fn enable_windows_ime_console_mode() {
use windows::Win32::System::Console::CONSOLE_MODE;
const ENABLE_WINDOW_INPUT: CONSOLE_MODE = CONSOLE_MODE(0x0008);
// SAFETY: Win32 console API is safe to call from any thread.
// Failures (console handle invalid, mode query fails) are silently
// ignored — this is a best-effort IME compatibility tweak.
unsafe {
let Ok(handle) = GetStdHandle(windows::Win32::System::Console::STD_INPUT_HANDLE) else {
return;
};
let mut mode = CONSOLE_MODE(0);
if GetConsoleMode(handle, &mut mode).is_err() {
return;
}
if mode.0 & ENABLE_WINDOW_INPUT.0 == 0 {
let _ = SetConsoleMode(handle, mode | ENABLE_WINDOW_INPUT);
}
}
}
/// Re-establish terminal mode flags. Idempotent and best-effort: each
/// underlying flag is silently discarded by terminals that don't support
/// it, and a single flag's failure doesn't prevent later flags from being
@@ -7066,6 +7102,9 @@ fn recover_terminal_modes<W: Write>(
use_mouse_capture: bool,
use_bracketed_paste: bool,
) {
#[cfg(target_os = "windows")]
enable_windows_ime_console_mode();
push_keyboard_enhancement_flags(writer);
if use_mouse_capture && let Err(err) = execute!(writer, EnableMouseCapture) {
tracing::debug!(?err, "EnableMouseCapture ignored");