mirror of
https://github.com/openai/codex.git
synced 2026-04-24 14:45:27 +00:00
Fix TUI issues with Alt-Gr on Windows (#6799)
This PR fixes keyboard handling for the Right Alt (aka "Alt-Gr") key on Windows. This key appears on keyboards in Central and Eastern Europe. Codex has effectively never worked for Windows users in these regions because the code didn't properly handle this key, which is used for typing common symbols like `\` and `@`. A few days ago, I merged a [community-authored PR](https://github.com/openai/codex/pull/6720) that supplied a partial fix for this issue. Upon closer inspect, that PR was 1) too broad (not scoped to Windows only) and 2) incomplete (didn't fix all relevant code paths, so paste was still broken). This improvement is based on another [community-provided PR](https://github.com/openai/codex/pull/3241) by @marektomas-cz. He submitted it back in September and later closed it because it didn't receive any attention. This fix addresses the following bugs: #5922, #3046, #3092, #3519, #5684, #5843.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
use crate::key_hint::has_ctrl_or_alt;
|
||||
use crossterm::event::KeyCode;
|
||||
use crossterm::event::KeyEvent;
|
||||
use crossterm::event::KeyEventKind;
|
||||
@@ -1103,8 +1104,7 @@ impl ChatComposer {
|
||||
..
|
||||
} = input
|
||||
{
|
||||
let has_ctrl_or_alt =
|
||||
modifiers.contains(KeyModifiers::CONTROL) || modifiers.contains(KeyModifiers::ALT);
|
||||
let has_ctrl_or_alt = has_ctrl_or_alt(modifiers);
|
||||
if !has_ctrl_or_alt {
|
||||
// Non-ASCII characters (e.g., from IMEs) can arrive in quick bursts and be
|
||||
// misclassified by paste heuristics. Flush any active burst buffer and insert
|
||||
@@ -1174,8 +1174,7 @@ impl ChatComposer {
|
||||
} = input;
|
||||
match code {
|
||||
KeyCode::Char(_) => {
|
||||
let has_ctrl_or_alt = modifiers.contains(KeyModifiers::CONTROL)
|
||||
|| modifiers.contains(KeyModifiers::ALT);
|
||||
let has_ctrl_or_alt = has_ctrl_or_alt(modifiers);
|
||||
if has_ctrl_or_alt {
|
||||
self.paste_burst.clear_window_after_non_char();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::key_hint::is_altgr;
|
||||
use crossterm::event::KeyCode;
|
||||
use crossterm::event::KeyEvent;
|
||||
use crossterm::event::KeyModifiers;
|
||||
@@ -247,16 +248,13 @@ impl TextArea {
|
||||
} if modifiers == (KeyModifiers::CONTROL | KeyModifiers::ALT) => {
|
||||
self.delete_backward_word()
|
||||
},
|
||||
// Windows AltGr generates ALT|CONTROL; treat as a plain character input unless
|
||||
// we match a specific Control+Alt binding above.
|
||||
KeyEvent {
|
||||
code: KeyCode::Char(c),
|
||||
modifiers,
|
||||
..
|
||||
} if modifiers.contains(KeyModifiers::ALT)
|
||||
&& modifiers.contains(KeyModifiers::CONTROL) =>
|
||||
{
|
||||
// AltGr on many keyboards reports as Ctrl+Alt; treat it as a literal char.
|
||||
self.insert_str(&c.to_string());
|
||||
},
|
||||
} if is_altgr(modifiers) => self.insert_str(&c.to_string()),
|
||||
KeyEvent {
|
||||
code: KeyCode::Backspace,
|
||||
modifiers: KeyModifiers::ALT,
|
||||
@@ -1464,6 +1462,7 @@ mod tests {
|
||||
assert_eq!(t.cursor(), 3);
|
||||
}
|
||||
|
||||
#[cfg_attr(not(windows), ignore = "AltGr modifier only applies on Windows")]
|
||||
#[test]
|
||||
fn altgr_ctrl_alt_char_inserts_literal() {
|
||||
let mut t = ta_with("");
|
||||
|
||||
@@ -89,3 +89,19 @@ impl From<&KeyBinding> for Span<'static> {
|
||||
fn key_hint_style() -> Style {
|
||||
Style::default().dim()
|
||||
}
|
||||
|
||||
pub(crate) fn has_ctrl_or_alt(mods: KeyModifiers) -> bool {
|
||||
(mods.contains(KeyModifiers::CONTROL) || mods.contains(KeyModifiers::ALT)) && !is_altgr(mods)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[inline]
|
||||
pub(crate) fn is_altgr(mods: KeyModifiers) -> bool {
|
||||
mods.contains(KeyModifiers::ALT) && mods.contains(KeyModifiers::CONTROL)
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
#[inline]
|
||||
pub(crate) fn is_altgr(_mods: KeyModifiers) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user