alacritty: Inconsistent char output using Alt key binds in macOS

Which operating system does the issue occur on? macOS (10.13.6) Alacritty: 0.2.5

I have following in my settings file

  - { key: F,        mods: Alt,         chars: "\x1bf"                  }
  - { key: I,        mods: Alt,         chars: "\x1bi"                  }

Doing a /bin/cat and typing <kbd>Option</kbd>+<kbd>F</kbd> followed by a <kbd>B</kbd> produces ^[fb while <kbd> Option </kbd>+<kbd>I</kbd> followed by a <kbd>B</kbd> produces ^[iˆb

I came across this issue while using kakoune editor. I reported the issue there but it seems it is alacritty’s issue (both iTerm & Terminal print ^[ib)

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 10
  • Comments: 62 (20 by maintainers)

Commits related to this issue

Most upvoted comments

I just found out about Alacritty, and while excited to use it, found that my fingers have the key bindings so ingrained in them. So, I fixed this problem solely in my alacritty.yml file. If this helps anyone else, here is my config. This makes Alacritty behave like Terminal.app. Key repeats and diacritics are all fixed.

env:
  TERM: xterm-24bits
key_bindings:
  - { key: N,           mods: Command,         action: SpawnNewInstance }
  - { key: PageUp,                             action: ScrollPageUp     }
  - { key: PageUp,      mode: Alt,             chars: "\x1B[5~"         }
  - { key: PageUp,      mods: Shift,           chars: "\x1B[5~"         }
  - { key: PageDown,                           action: ScrollPageDown   }
  - { key: PageDown,    mode: Alt,             chars: "\x1B[6~"         }
  - { key: PageDown,    mods: Shift,           chars: "\x1B[6~"         }
  - { key: Home,                               action: ScrollToTop      }
  - { key: Home,        mode: Alt,             chars: "\x1BOH"          }
  - { key: Home,        mods: Shift,           chars: "\x1B[H"          }
  - { key: End,                                action: ScrollToBottom   }
  - { key: End,         mode: Alt,             chars: "\x1BOF"          }
  - { key: End,         mods: Shift,           chars: "\x1B[F"          }
  - { key: Tab,         mods: Alt,             chars: "\x1B\t"          }
  - { key: Tab,         mods: Alt|Shift,       chars: "\x1B\x1B[Z"      }
  - { key: Back,                               chars: "\x7F"            }
  - { key: Back,        mods: Alt,             chars: "\x1B\x7F"        }
  - { key: Back,        mods: Alt|Shift,       chars: "\x1B\x08"        }
  - { key: Space,       mods: Control,         chars: "\x00"            }
  - { key: Space,       mods: Alt,             chars: "\x20"            }
  - { key: Left,        mods: Alt,             chars: "\x1Bb"           }
  - { key: Left,        mods: Alt|Shift,       chars: "\x1B\x1B[D"      }
  - { key: Right,       mods: Alt,             chars: "\x1Bf"           }
  - { key: Right,       mods: Alt|Shift,       chars: "\x1B\x1B[C"      }
  - { key: Down,        mods: Alt,             chars: "\x1B\x1B[B"      }
  - { key: Down,        mods: Alt|Shift,       chars: "\x1B\x1B[B"      }
  - { key: Up,          mods: Alt,             chars: "\x1B\x1B[A"      }
  - { key: Up,          mods: Alt|Shift,       chars: "\x1B\x1B[A"      }
  - { key: A,           mods: Alt,             chars: "\x1Ba"           }
  - { key: A,           mods: Alt|Shift,       chars: "\x1BA"           }
  - { key: B,           mods: Alt,             chars: "\x1Bb"           }
  - { key: B,           mods: Alt|Shift,       chars: "\x1BB"           }
  - { key: C,           mods: Alt,             chars: "\x1Bc"           }
  - { key: C,           mods: Alt|Shift,       chars: "\x1BC"           }
  - { key: D,           mods: Alt,             chars: "\x1Bd"           }
  - { key: D,           mods: Alt|Shift,       chars: "\x1BD"           }
  - { key: E,           mods: Alt,             chars: "\x1Be"           }
  - { key: E,           mods: Alt|Shift,       chars: "\x1BE"           }
  - { key: F,           mods: Alt,             chars: "\x1Bf"           }
  - { key: F,           mods: Alt|Shift,       chars: "\x1BF"           }
  - { key: G,           mods: Alt,             chars: "\x1Bg"           }
  - { key: G,           mods: Alt|Shift,       chars: "\x1BG"           }
  - { key: H,           mods: Alt,             chars: "\x1Bh"           }
  - { key: H,           mods: Alt|Shift,       chars: "\x1BH"           }
  - { key: I,           mods: Alt,             chars: "\x1Bi"           }
  - { key: I,           mods: Alt|Shift,       chars: "\x1BI"           }
  - { key: J,           mods: Alt,             chars: "\x1Bj"           }
  - { key: J,           mods: Alt|Shift,       chars: "\x1BJ"           }
  - { key: K,           mods: Alt,             chars: "\x1Bk"           }
  - { key: K,           mods: Alt|Shift,       chars: "\x1BK"           }
  - { key: L,           mods: Alt,             chars: "\x1Bl"           }
  - { key: L,           mods: Alt|Shift,       chars: "\x1BL"           }
  - { key: M,           mods: Alt,             chars: "\x1Bm"           }
  - { key: M,           mods: Alt|Shift,       chars: "\x1BM"           }
  - { key: N,           mods: Alt,             chars: "\x1Bn"           }
  - { key: N,           mods: Alt|Shift,       chars: "\x1BN"           }
  - { key: O,           mods: Alt,             chars: "\x1Bo"           }
  - { key: O,           mods: Alt|Shift,       chars: "\x1BO"           }
  - { key: P,           mods: Alt,             chars: "\x1Bp"           }
  - { key: P,           mods: Alt|Shift,       chars: "\x1BP"           }
  - { key: Q,           mods: Alt,             chars: "\x1Bq"           }
  - { key: Q,           mods: Alt|Shift,       chars: "\x1BQ"           }
  - { key: R,           mods: Alt,             chars: "\x1Br"           }
  - { key: R,           mods: Alt|Shift,       chars: "\x1BR"           }
  - { key: S,           mods: Alt,             chars: "\x1Bs"           }
  - { key: S,           mods: Alt|Shift,       chars: "\x1BS"           }
  - { key: T,           mods: Alt,             chars: "\x1Bt"           }
  - { key: T,           mods: Alt|Shift,       chars: "\x1BT"           }
  - { key: U,           mods: Alt,             chars: "\x1Bu"           }
  - { key: U,           mods: Alt|Shift,       chars: "\x1BU"           }
  - { key: V,           mods: Alt,             chars: "\x1Bv"           }
  - { key: V,           mods: Alt|Shift,       chars: "\x1BV"           }
  - { key: W,           mods: Alt,             chars: "\x1Bw"           }
  - { key: W,           mods: Alt|Shift,       chars: "\x1BW"           }
  - { key: X,           mods: Alt,             chars: "\x1Bx"           }
  - { key: X,           mods: Alt|Shift,       chars: "\x1BX"           }
  - { key: Y,           mods: Alt,             chars: "\x1By"           }
  - { key: Y,           mods: Alt|Shift,       chars: "\x1BY"           }
  - { key: Z,           mods: Alt,             chars: "\x1Bz"           }
  - { key: Z,           mods: Alt|Shift,       chars: "\x1BZ"           }
  - { key: Key1,        mods: Alt,             chars: "\x1B1"           }
  - { key: Key1,        mods: Alt|Shift,       chars: "\x1B!"           }
  - { key: Key2,        mods: Alt,             chars: "\x1B2"           }
  - { key: Key2,        mods: Alt|Shift,       chars: "\x1B#"           }
  - { key: Key3,        mods: Alt,             chars: "\x1B3"           }
  - { key: Key3,        mods: Alt|Shift,       chars: "\x1B#"           }
  - { key: Key4,        mods: Alt,             chars: "\x1B4"           }
  - { key: Key4,        mods: Alt|Shift,       chars: "\x1B$"           }
  - { key: Key5,        mods: Alt,             chars: "\x1B5"           }
  - { key: Key5,        mods: Alt|Shift,       chars: "\x1B%"           }
  - { key: Key6,        mods: Alt,             chars: "\x1B6"           }
  - { key: Key6,        mods: Alt|Shift,       chars: "\x1B^"           }
  - { key: Key7,        mods: Alt,             chars: "\x1B7"           }
  - { key: Key7,        mods: Alt|Shift,       chars: "\x1B&"           }
  - { key: Key8,        mods: Alt,             chars: "\x1B8"           }
  - { key: Key8,        mods: Alt|Shift,       chars: "\x1B*"           }
  - { key: Key9,        mods: Alt,             chars: "\x1B9"           }
  - { key: Key9,        mods: Alt|Shift,       chars: "\x1B("           }
  - { key: Key0,        mods: Alt,             chars: "\x1B0"           }
  - { key: Key0,        mods: Alt|Shift,       chars: "\x1B)"           }
  - { key: Minus,       mods: Alt,             chars: "\x1B-"           }
  - { key: Minus,       mods: Alt|Shift,       chars: "\x1B_"           }
  - { key: Equals,      mods: Alt,             chars: "\x1B="           }
  - { key: Equals,      mods: Alt|Shift,       chars: "\x1B+"           }
  - { key: LBracket,    mods: Alt,             chars: "\x1B["           }
  - { key: LBracket,    mods: Alt|Shift,       chars: "\x1B{"           }
  - { key: RBracket,    mods: Alt,             chars: "\x1B]"           }
  - { key: RBracket,    mods: Alt|Shift,       chars: "\x1B}"           }
  - { key: Backslash,   mods: Alt,             chars: "\x1B\\"          }
  - { key: Backslash,   mods: Alt|Shift,       chars: "\x1B|"           }
  - { key: Semicolon,   mods: Alt,             chars: "\x1B;"           }
  - { key: Semicolon,   mods: Alt|Shift,       chars: "\x1B:"           }
  - { key: Apostrophe,  mods: Alt,             chars: "\x1B'"           }
  - { key: Apostrophe,  mods: Alt|Shift,       chars: "\x1B\""          }
  - { key: Comma,       mods: Alt,             chars: "\x1B,"           }
  - { key: Comma,       mods: Alt|Shift,       chars: "\x1B<"           }
  - { key: Period,      mods: Alt,             chars: "\x1B."           }
  - { key: Period,      mods: Alt|Shift,       chars: "\x1B>"           }
  - { key: Slash,       mods: Alt,             chars: "\x1B/"           }
  - { key: Slash,       mods: Alt|Shift,       chars: "\x1B?"           }
  - { key: Grave,       mods: Alt,             chars: "\x1B`"           }
  - { key: Grave,       mods: Alt|Shift,       chars: "\x1B~"           }
alt_send_esc: false

There may be a few key combinations that others use, is there anyway we can make a standard MacOS config?

Bump: I’ve been running this for a couple of months now with no issues. Is there anything I can do to help get this merged in for good so I can get back to running a vanilla release?

hi, people

@kjmph any news about fix merge?

Hello @jkp, my apologies on my delayed response, I lost steam trying to get winit to accept my patches. They were focused on having virtual keyboards work as well, which the patch didn’t make any worse than what was previously existing. I moved back to Terminal.app myself, maintaining the patches for about a year got time consuming for me.

To make alacritty use mentioned PR you should also apply

diff --git a/Cargo.toml b/Cargo.toml
index 415ceb9..e0db73b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,3 +13,4 @@ incremental = false

 [patch.crates-io]
 servo-freetype-sys = { path = "servo-freetype-proxy" }
+winit = { git = "https://github.com/kjmph/winit", branch = "fix-alt-modifier" }

If anyone would like to test, the pull request went through a few rounds. I have an open pull request that fixes this issue:

https://github.com/rust-windowing/winit/pull/1449

If anyone can test to provide support for the pull request, there is a single change to alacritty:

diff --git a/alacritty/src/window.rs b/alacritty/src/window.rs
index 71327ba..7bc555a 100644
--- a/alacritty/src/window.rs
+++ b/alacritty/src/window.rs
@@ -265,7 +265,8 @@ impl Window {
             .with_title(title)
             .with_visible(false)
             .with_transparent(true)
-            .with_maximized(window_config.startup_mode() == StartupMode::Maximized);
+            .with_maximized(window_config.startup_mode() == StartupMode::Maximized)
+            .with_ignore_alt_modifier(true);

         match window_config.decorations {
             Decorations::Full => window,

This is a duplicate of #1610 .

Ah, so it turns out that these characters have a utf8 length of 2, so that’s why the escape characters aren’t printed.

So the problem is just that when pressing alt and hitting f/i, that it’s putting down modified characters. I think the only way to resolve this problem would be to request with our window library to not send combined characters whenever the alt key is held down and the alt_send_esc option is enabled.

@kjmph Just built and tested your updated branch and it fixed the ctl-meta-{foo} issue. I will keep testing with this branch for a while and report back any new issues I find. Thanks for all your work on this!

OK - I added one more line to window.rs to hard code .set_option_as_alt(true) and now this works as expected and I can remove all the custom mappings in my config.

I’ll run with this for a while but initially it looks good. One question that you may know the answer to @kjmph - I have some emacs bindings that use both ctl and meta (eg C-M-) but with this patch it seems that emacs only sees M-\ when I press all three keys together. I captured the events that alacritty sees and they look correct:

[2020-11-21 15:36:51.497506000] [INFO ] [alacritty] glutin event: WindowEvent { window_id: WindowId(Id(140448397406320)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 42, state: Pressed, virtual_keycode: Some(Backslash), modifiers: CTRL | ALT }, is_synthetic: false } }
[2020-11-21 15:36:51.584908000] [INFO ] [alacritty] glutin event: WindowEvent { window_id: WindowId(Id(140448397406320)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 42, state: Released, virtual_keycode: Some(Backslash), modifiers: CTRL | ALT }, is_synthetic: false } }
[2020-11-21 15:36:53.009238000] [INFO ] [alacritty] glutin event: WindowEvent { window_id: WindowId(Id(140448397406320)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 59, state: Released, virtual_keycode: Some(LControl), modifiers: ALT }, is_synthetic: false } }
[2020-11-21 15:36:53.014028000] [INFO ] [alacritty] glutin event: WindowEvent { window_id: WindowId(Id(140448397406320)), event: KeyboardInput { device_id: DeviceId(DeviceId), input: KeyboardInput { scancode: 58, state: Released, virtual_keycode: Some(LAlt), modifiers: (empty) }, is_synthetic: false } }

Any ideas whats going on?

Hello @jkp, I live in emacs and running the patch listed in rust-windowing/winit#1449 has covered all emacs bindings that I can realistically test as one person. Would you mind testing out the branch listed in the PR? I can always update against the latest master if you have problems building. I’ve been running the same custom binaries for most of this year, so the branch may need to be refreshed.

yes I am. thanks for your PR. can winit distinguish between L-Option, R-Option? If answer is yes, then maybe it’s possible to keep both behavior of alt, i.e. L-Option can be set to send alt and R-Option continue to modify characters before sending it to alacritty (more acting like a AltGr?

Would this prevent people from using the diacritics if they want to do that instead of remapping them? That seems like it would be a regression for some people. (Not to be annoying, as this patch is how I would need it.)

This would definitely be configurable.

I’ve created an issue upstream to track a solution for this problem: https://github.com/tomaka/winit/issues/768

so other than filing a bug, what would help motivate them to resolve this faster? 😃