mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Fix Windows TUI navigation key handling (#34625)
## Why Crossterm's Windows event backend expects Win32 input records. When the console inherits virtual terminal input mode, or another console client restores it, navigation keys instead arrive as literal escape bytes. ## What changed - Keep the Windows console in input-record mode while the event stream is polled, and disable focus-change reporting on Windows. - Preserve and restore the console's original virtual terminal input setting when the TUI shuts down. ## Testing - Add unit coverage for clearing and restoring the virtual terminal input bit. GitOrigin-RevId: 792b99e354fce357d51810a6c3b437e972ad11ce
This commit is contained in:
1 parent
9b33613db6
commit
bbad09a83b
3 files changed
+151
-1
No files matched your search
@@ -19,6 +19,7 @@ use crossterm::cursor::SetCursorStyle;
|
||||
use crossterm::event::DisableBracketedPaste;
|
||||
use crossterm::event::DisableFocusChange;
|
||||
use crossterm::event::EnableBracketedPaste;
|
||||
#[cfg(not(windows))]
|
||||
use crossterm::event::EnableFocusChange;
|
||||
use crossterm::event::KeyEvent;
|
||||
use crossterm::terminal::EnterAlternateScreen;
|
||||
@@ -62,6 +63,8 @@ mod keyboard_modes;
|
||||
mod terminal_stderr;
|
||||
#[cfg(test)]
|
||||
pub(crate) mod test_support;
|
||||
#[cfg(any(windows, test))]
|
||||
mod windows_console;
|
||||
|
||||
/// Target frame interval for UI redraw scheduling.
|
||||
pub(crate) const TARGET_FRAME_INTERVAL: Duration = frame_rate_limiter::MIN_FRAME_INTERVAL;
|
||||
@@ -123,6 +126,26 @@ mod tests {
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn windows_console_input_modes_preserve_original_vt_input_state() {
|
||||
let input_record_mode = super::windows_console::input_record_mode(/*mode*/ 0x398);
|
||||
assert_eq!(input_record_mode, 0x198);
|
||||
assert_eq!(
|
||||
super::windows_console::restored_input_mode(
|
||||
input_record_mode,
|
||||
super::windows_console::VirtualTerminalInput::Enabled,
|
||||
),
|
||||
0x398
|
||||
);
|
||||
assert_eq!(
|
||||
super::windows_console::restored_input_mode(
|
||||
/*mode*/ 0x198,
|
||||
super::windows_console::VirtualTerminalInput::Disabled,
|
||||
),
|
||||
0x198
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unfocused_notification_condition_emits_when_unfocused() {
|
||||
assert!(should_emit_notification(
|
||||
@@ -193,6 +216,8 @@ pub fn set_modes() -> Result<()> {
|
||||
execute!(stdout(), EnableBracketedPaste)?;
|
||||
|
||||
enable_raw_mode()?;
|
||||
#[cfg(windows)]
|
||||
windows_console::set_input_record_mode()?;
|
||||
// Enable keyboard enhancement flags so modifiers for keys like Enter are disambiguated.
|
||||
// chat_composer.rs is using a keyboard event listener to enter for any modified keys
|
||||
// to create a new line that require this.
|
||||
@@ -201,7 +226,10 @@ pub fn set_modes() -> Result<()> {
|
||||
// gracefully if unsupported.
|
||||
keyboard_modes::enable_keyboard_enhancement();
|
||||
|
||||
#[cfg(not(windows))]
|
||||
let _ = execute!(stdout(), EnableFocusChange);
|
||||
#[cfg(windows)]
|
||||
let _ = execute!(stdout(), DisableFocusChange);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -279,6 +307,10 @@ fn restore_common(
|
||||
{
|
||||
first_error.get_or_insert(err);
|
||||
}
|
||||
#[cfg(windows)]
|
||||
if let Err(err) = windows_console::restore_input_mode() {
|
||||
first_error.get_or_insert(err);
|
||||
}
|
||||
if let Err(err) = execute!(
|
||||
stdout(),
|
||||
SetCursorStyle::DefaultUserShape,
|
||||
|
||||
Reference in new issue
Block a user