1
1
mirror of https://github.com/wez/wezterm.git synced 2024-09-21 03:39:16 +03:00

window: allow for stronger separation between raw and composed keys

The goal at the window layer is to preserve enough useful information
for other layers.  In this specific circumstance on macos we'd like
to be able know both that eg: ALT-1 was pressed and that ALT-1 composes
to a different unmodified sequence and then allow the user's key
binding assignment to potentially match on both.

We sort of allowed for this, but didn't separate out the modifier keys.
This commit adds a `raw_modifiers` concept to the underlying event
struct so that we can carry both the raw key and modifier information
as well as the composed key and modifier information.

In the scenario above, we want the raw key/modifier tuple to be ALT-1
but the composed key/modifier to be eg: unmodified `¡` in my english
keymap.

refs: https://github.com/wez/wezterm/issues/158
This commit is contained in:
Wez Furlong 2020-05-28 06:33:37 -07:00
parent 71d98d84ca
commit 9ff9bf15fd
6 changed files with 32 additions and 10 deletions

View File

@ -196,6 +196,7 @@ fn mouse_press_to_tmb(press: &MousePress) -> TMB {
}
}
#[derive(Debug)]
enum Key {
Code(::termwiz::input::KeyCode),
Composed(String),
@ -377,19 +378,20 @@ impl WindowCallbacks for TermWindow {
None => return false,
};
let modifiers = window_mods_to_termwiz_mods(key.modifiers);
let raw_modifiers = window_mods_to_termwiz_mods(key.raw_modifiers);
// First chance to operate on the raw key; if it matches a
// user-defined key binding then we execute it and stop there.
if let Some(key) = &key.raw_key {
if let Key::Code(key) = self.win_key_code_to_termwiz_key_code(&key) {
if let Some(assignment) = self.input_map.lookup_key(key, modifiers) {
if let Some(assignment) = self.input_map.lookup_key(key, raw_modifiers) {
self.perform_key_assignment(&tab, &assignment).ok();
return true;
}
if !configuration().send_composed_key_when_alt_is_pressed
&& modifiers.contains(::termwiz::input::Modifiers::ALT)
&& tab.key_down(key, modifiers).is_ok()
&& raw_modifiers.contains(::termwiz::input::Modifiers::ALT)
&& tab.key_down(key, raw_modifiers).is_ok()
{
if !key.is_modifier() {
self.maybe_scroll_to_bottom_for_input(&tab);

View File

@ -139,13 +139,13 @@ pub struct KeyEvent {
/// This is the potentially processed/composed version
/// of the input.
pub key: KeyCode,
/// Which modifiers are down
pub modifiers: Modifiers,
/// The raw unprocessed key press if it was different from
/// the processed/composed version
pub raw_key: Option<KeyCode>,
/// Which modifiers are down
pub modifiers: Modifiers,
pub raw_modifiers: Modifiers,
/// How many times this key repeats
pub repeat_count: u16,

View File

@ -790,6 +790,7 @@ impl WindowView {
key,
raw_key: None,
modifiers,
raw_modifiers: Modifiers::NONE,
repeat_count: 1,
key_is_down: true,
};
@ -825,7 +826,8 @@ impl WindowView {
let event = KeyEvent {
key: KeyCode::Composed(s.to_string()),
raw_key: None,
modifiers: Modifiers::default(),
modifiers: Modifiers::NONE,
raw_modifiers: Modifiers::NONE,
repeat_count: 1,
key_is_down: true,
};
@ -1109,10 +1111,17 @@ impl WindowView {
}
};
let (modifiers, raw_modifiers) = if raw_key.is_some() {
(Modifiers::NONE, modifiers)
} else {
(modifiers, Modifiers::NONE)
};
let event = KeyEvent {
key,
raw_key,
modifiers,
raw_modifiers,
repeat_count: 1,
key_is_down,
};

View File

@ -286,18 +286,26 @@ impl WaylandWindowInner {
None => return,
},
};
// Avoid redundant key == raw_key
let (key, raw_key) = match (key, raw_key) {
// Avoid eg: \x01 when we can use CTRL-A
(KeyCode::Char(c), Some(raw)) if c.is_ascii_control() => (raw, None),
// Avoid redundant key == raw_key
(key, Some(raw)) if key == raw => (key, None),
pair => pair,
};
let (modifiers, raw_modifiers) = if raw_key.is_some() {
(Modifiers::NONE, self.modifiers)
} else {
(self.modifiers, Modifiers::NONE)
};
let key_event = KeyEvent {
key_is_down: is_down,
key,
raw_key,
modifiers: self.modifiers,
modifiers,
raw_modifiers,
repeat_count: 1,
};
self.callbacks

View File

@ -919,7 +919,8 @@ unsafe fn ime_composition(
let key = KeyEvent {
key: KeyCode::Composed(s),
raw_key: None,
modifiers: Modifiers::default(),
raw_modifiers: Modifiers::NONE,
modifiers: Modifiers::NONE,
repeat_count: 1,
key_is_down: true,
};
@ -1194,6 +1195,7 @@ unsafe fn key(hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM) -> Option<L
let key = KeyEvent {
key,
raw_key: None,
raw_modifiers: Modifiers::NONE,
modifiers,
repeat_count: repeat,
key_is_down: !releasing,

View File

@ -303,6 +303,7 @@ impl XWindowInner {
let key = KeyEvent {
key: code,
raw_key: None,
raw_modifiers: Default::default(),
modifiers: mods,
repeat_count: 1,
key_is_down: r == xcb::KEY_PRESS,