Repository: alacritty/alacritty (language: rust)

Issue:
Certain modifiers fail in `kakoune`
I found at least two type of modifiers that stopped working on `0.13` that worked before on `0.12`.

-  `ctrl + [` does not trigger `ESC`-equivalent behaviour in `kakoune`.
    - Interestingly enough the same action continues to work in `vim`?
- `alt + shift` combinations fail to register, so I checked eg. `alt + shift + !` (append command output), `alt + K` (keep not matching), `alt + N` (extend reverse search).

I assume these issues have a wider impact than just `kakoune` but I found it the easiest to reproduce it there. It possibly might be a duplicate considering a wave of keyboard input related issues lately but none so far seems to match exactly that. Sorry in advance.

### System

OS: Arch Linux
Version: alacritty 0.13.0 (78fa4d6f)
Linux/BSD: Wayland, sway

### Logs

This should be quite trivial to reproduce, can provide logs if necessary though.


Thanks a lot for looking into it. Fantastic project and amazing work, lots of love <3



Discussion / hints:
@kchibisov Sounds like keyboard protocol stuff? This seems intentional on kakoune's end.
I think it's due to kakoune really wanting associated text, I'll try to write a patch.
Could you try applying that?

```diff
diff --git a/alacritty/src/input/keyboard.rs b/alacritty/src/input/keyboard.rs
index 423f8bae..70bfaf06 100644
--- a/alacritty/src/input/keyboard.rs
+++ b/alacritty/src/input/keyboard.rs
@@ -338,7 +338,15 @@ impl SequenceBuilder {
             let base_character = character.to_lowercase().next().unwrap();

             let codepoint = u32::from(character);
-            let base_codepoint = u32::from(base_character);
+            let mut base_codepoint = u32::from(base_character);
+
+            // Try to get the base for keys which change based on modifier, like `1` for `!`.
+            match key.key_without_modifiers().as_ref() {
+                Key::Character(unmodded) if codepoint == base_codepoint => {
+                    base_codepoint = u32::from(unmodded.chars().next().unwrap_or(base_character));
+                },
+                _ => (),
+            }

             // NOTE: Base layouts are ignored, since winit doesn't expose this information
             // yet.

```

This should probably fix the `alt + shift + 1`, but I'm not sure what could happen with `ctrl + [` or `alt + K`, they work the same compared to e.g. kitty/foot when I look into the generated events.

Could you post the `alacritty -vvv` log when you try to repro the issue after this patch applied?

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9b3e840b35e..5c0f5ef36fd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - `Alt` bindings requiring composed key rather than pre-composed one on macOS
 - `Alt + Control` bindings not working on Windows
 - `chars = "\u000A"` action in bindings inserting `\n`
+- Alternate keys not sent for `Shift + <number>` when using kitty protocol
+- Alternative keys being swapped in kitty protocol implementation
 
 ## 0.13.0
 
diff --git a/alacritty/src/input/keyboard.rs b/alacritty/src/input/keyboard.rs
index 8e559be118d..0968c0de176 100644
--- a/alacritty/src/input/keyboard.rs
+++ b/alacritty/src/input/keyboard.rs
@@ -350,17 +350,25 @@ impl SequenceBuilder {
             let character = character.chars().next().unwrap();
             let base_character = character.to_lowercase().next().unwrap();
 
-            let codepoint = u32::from(character);
-            let base_codepoint = u32::from(base_character);
+            let alternate_key_code = u32::from(character);
+            let mut unicode_key_code = u32::from(base_character);
+
+            // Try to get the base for keys which change based on modifier, like `1` for `!`.
+            match key.key_without_modifiers().as_ref() {
+                Key::Character(unmodded) if alternate_key_code == unicode_key_code => {
+                    unicode_key_code = u32::from(unmodded.chars().next().unwrap_or(base_character));
+                },
+                _ => (),
+            }
 
             // NOTE: Base layouts are ignored, since winit doesn't expose this information
             // yet.
             let payload = if self.mode.contains(TermMode::REPORT_ALTERNATE_KEYS)
-                && codepoint != base_codepoint
+                && alternate_key_code != unicode_key_code
             {
-                format!("{codepoint}:{base_codepoint}")
+                format!("{unicode_key_code}:{alternate_key_code}")
             } else {
-                codepoint.to_string()
+                alternate_key_code.to_string()
             };
 
             Some(SequenceBase::new(payload.into(), SequenceTerminator::Kitty))


Test patch: