1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-23 21:32:13 +03:00

macos: fixup SUPER+SHIFT+[ key decoding

One of the default key assignments was registered as `SUPER+SHIFT+{`
which worked on macOS, but on Linux, would never match because the
keypress over there was (correctly) reporting as `SUPER+{`.

I originally thought that the user reported issue was a linux
normalization problem, but in looking deeper, the issue is really
that macos is doing something funky!

On macos we collect the interpreted key event as a string, and also
the interpretation of that event without any modifiers applied.

For letters this means that eg: `ALT-l` reports as `¬` for the
processed string and `l` for the unmodified string.  That's good!

However, for punctuation we get a backwards result: SUPER+SHIFT+[
produces `[` for the processed text and `{` for the unmodified
text!

This commit tries to detect this, using a heuristic that is
potentially bad on non-US layouts: if both the processed and
unmodified strings are punctuation then we bias to the unmodified
version.

With that change, that key press is correctly reported as `SUPER+{`,
and we can fix the key assignment registration to reflect that.

I quickly checked the behavior of pressing that same physical key
combination with a DEU layout active, and it appears that the unmodified
stuff is also flipped there; we get a lower-case version of something
that I think should be uppercase.  This commit doesn't change that
behavior:

```
key_event KeyEvent { key: Char('ü'), modifiers: NONE,
        raw_key: Some(Char('Ü')),
        raw_modifiers: SHIFT | SUPER,
        raw_code: Some(33),
        repeat_count: 1, key_is_down: true }
```

refs: https://github.com/wez/wezterm/issues/601
This commit is contained in:
Wez Furlong 2021-04-03 06:24:21 -07:00
parent d7b78b4163
commit fe48951e7a
2 changed files with 21 additions and 9 deletions

View File

@ -357,7 +357,7 @@ impl InputMap {
ActivateTabRelative(-1)
],
[
Modifiers::SUPER | Modifiers::SHIFT,
Modifiers::SUPER,
KeyCode::Char('{'),
ActivateTabRelative(-1)
],
@ -366,11 +366,7 @@ impl InputMap {
KeyCode::Char(']'),
ActivateTabRelative(1)
],
[
Modifiers::SUPER | Modifiers::SHIFT,
KeyCode::Char('}'),
ActivateTabRelative(1)
],
[Modifiers::SUPER, KeyCode::Char('}'), ActivateTabRelative(1)],
[Modifiers::SUPER, KeyCode::Char('r'), ReloadConfiguration],
[Modifiers::CTRL, KeyCode::Char('R'), ReloadConfiguration],
[ctrl_shift, KeyCode::PageUp, MoveTabRelative(-1)],

View File

@ -1715,6 +1715,9 @@ impl WindowView {
}
if let Some(key) = key_string_to_key_code(chars).or_else(|| key_string_to_key_code(unmod)) {
let raw_modifiers = modifiers;
let mut modifiers = modifiers;
let (key, raw_key) = if chars.is_empty() || chars == unmod {
(key, None)
} else {
@ -1722,14 +1725,27 @@ impl WindowView {
match (&key, &raw) {
// Avoid eg: \x01 when we can use CTRL-A
(KeyCode::Char(c), Some(raw)) if c.is_ascii_control() => (raw.clone(), None),
(KeyCode::Char(k), Some(KeyCode::Char(r)))
if k.is_ascii_punctuation() && r.is_ascii_punctuation() =>
{
// Well, `chars` is supposed to represent the processed and modified
// interpretation of the keypress, and `unmod` the same, but ignoring
// any modifier keys. eg: `ALT-l` has unmod=`l` and chars=`¬`.
// However, SUPER+SHIFT+[ yields chars=`[` and unmod=`{` which is
// the opposite of what we want.
// If both chars and unmod are punctuation then let's take unmod,
// and filter out the SHIFT state if present.
modifiers -= Modifiers::SHIFT;
(KeyCode::Char(*r), None)
}
_ => (key, raw),
}
};
let (modifiers, raw_modifiers) = if raw_key.is_some() {
(Modifiers::NONE, modifiers)
let modifiers = if raw_key.is_some() {
Modifiers::NONE
} else {
(modifiers, Modifiers::NONE)
modifiers
};
let event = KeyEvent {