From d61ba14b6b26b2988646b6426519a1c0a938187a Mon Sep 17 00:00:00 2001 From: tianrking Date: Thu, 16 Jul 2026 20:39:34 +0800 Subject: [PATCH] fix: support AltGr text input --- CHANGELOG.md | 1 + src/components/textinput.rs | 59 +++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68c2158509..8804409652 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * support rewording non-HEAD commits when `commit.gpgsign` is enabled (gpg format only) [[@guerinoni](https://github.com/guerinoni)] ([#2959](https://github.com/gitui-org/gitui/pull/2959)) ### Fixes +* allow entering AltGr-bound characters in text inputs on Windows ([#2848](https://github.com/gitui-org/gitui/issues/2848)) * crash when opening submodule ([#2895](https://github.com/gitui-org/gitui/issues/2895)) * when staging the last file in a directory, the first item after the directory is no longer skipped [[@Tillerino](https://github.com/Tillerino)] ([#2748](https://github.com/gitui-org/gitui/issues/2748)) * index-out-of-bounds panic when unstaging lines near the end of a diff ([#2953](https://github.com/gitui-org/gitui/issues/2953)) diff --git a/src/components/textinput.rs b/src/components/textinput.rs index 357fef1df1..669886bbcd 100644 --- a/src/components/textinput.rs +++ b/src/components/textinput.rs @@ -610,6 +610,17 @@ impl TextInputComponent { ta.scroll(Scrolling::PageUp); true } + // On Windows, AltGr is reported as Ctrl+Alt. Handle any characters + // not reserved for existing Ctrl+Alt editing shortcuts as text input. + Input { + key: Key::Char(c), + ctrl: true, + alt: true, + .. + } => { + ta.insert_char(*c); + true + } _ => false, } } @@ -733,6 +744,54 @@ impl Component for TextInputComponent { #[cfg(test)] mod tests { use super::*; + use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; + + #[test] + fn test_altgr_character_input() { + let env = Environment::test_env(); + let mut comp = TextInputComponent::new(&env, "", "", false); + comp.show_inner_textarea(); + + comp.event(&Event::Key(KeyEvent::new( + KeyCode::Char('{'), + KeyModifiers::CONTROL | KeyModifiers::ALT, + ))) + .unwrap(); + + assert_eq!(comp.get_text(), "{"); + } + + #[test] + fn test_alt_character_input_is_not_inserted() { + let env = Environment::test_env(); + let mut comp = TextInputComponent::new(&env, "", "", false); + comp.show_inner_textarea(); + + comp.event(&Event::Key(KeyEvent::new( + KeyCode::Char('{'), + KeyModifiers::ALT, + ))) + .unwrap(); + + assert_eq!(comp.get_text(), ""); + } + + #[test] + fn test_ctrl_alt_editor_shortcut_is_preserved() { + let env = Environment::test_env(); + let mut comp = TextInputComponent::new(&env, "", "", false); + comp.show_inner_textarea(); + comp.set_text("text".to_string()); + comp.textarea.as_mut().unwrap().move_cursor(CursorMove::End); + + comp.event(&Event::Key(KeyEvent::new( + KeyCode::Char('b'), + KeyModifiers::CONTROL | KeyModifiers::ALT, + ))) + .unwrap(); + + assert_eq!(comp.textarea.as_ref().unwrap().cursor(), (0, 0)); + } #[test] fn test_smoke() {