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:
parent
71d98d84ca
commit
9ff9bf15fd
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user