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

window: x11/wayland: extract utf8 version of key from key state

Previously, we'd take a couple of guesses at how to map the key
to a utf8 value, but! the keyboard state has a method that can tell
us what to use.

This is important in non-latin keymaps where, for example, the `c`
key generates cyrillic small letter es and we'd end up sending
CTRL + that through to the terminal when CTRL is held down.

If we get the utf8 string from the keyboard layer then we get
CTRL+c instead, and that is what we want.

refs: https://github.com/wez/wezterm/issues/678
This commit is contained in:
Wez Furlong 2022-01-02 11:07:27 -07:00
parent c05491f831
commit 43d9392c52
4 changed files with 47 additions and 27 deletions

View File

@ -17,6 +17,7 @@ As features stabilize some brief notes about them will accumulate here.
#### Fixed
* Regression that broke fontconfig aliases such as `"monospace"` [#1250](https://github.com/wez/wezterm/pull/1250)
* X11/Wayland: CTRL+C in non-latin keyboard layouts wouldn't send CTRL-C [#678](https://github.com/wez/wezterm/issues/678)
### 20220101-133340-7edc5b5a

View File

@ -120,6 +120,19 @@ impl KeyCode {
pub fn normalize_shift(&self, modifiers: Modifiers) -> (KeyCode, Modifiers) {
normalize_shift(self.clone(), modifiers)
}
pub fn composed(s: &str) -> Self {
// Prefer to send along a single Char when the string
// is just a single char, as the keymapping layer cannot
// bind to composed key sequences
let mut iter = s.chars();
let first_char = iter.next();
let next_char = iter.next();
match (first_char, next_char) {
(Some(c), None) => Self::Char(c),
_ => Self::Composed(s.to_string()),
}
}
}
impl ToString for KeyCode {

View File

@ -1425,19 +1425,7 @@ impl WindowView {
let mut inner = myself.inner.borrow_mut();
let key_is_down = inner.key_is_down.take().unwrap_or(true);
// Prefer to send along a single Char when the string
// is just a single char, as the keymapping layer cannot
// bind to composed key sequences and we'll get those
// for example when use_ime=true and the user presses
// `CTRL-A p` - we'd get CTRL-A followed by Composed("p")
// here if we didn't normalize it back to Char.
let mut iter = s.chars();
let first_char = iter.next();
let next_char = iter.next();
let key = match (first_char, next_char) {
(Some(c), None) => KeyCode::Char(c),
_ => KeyCode::Composed(s.to_string()),
};
let key = KeyCode::composed(s);
let event = KeyEvent {
key,

View File

@ -160,6 +160,7 @@ impl Keyboard {
fn process_key_event_impl(&self, xcode: xkb::Keycode, pressed: bool) -> Option<KeyEvent> {
let xsym = self.state.borrow().key_get_one_sym(xcode);
let mut kc = None;
let ksym = if pressed {
self.compose_state.borrow_mut().feed(xsym);
@ -170,11 +171,21 @@ impl Keyboard {
return None;
}
ComposeStatus::Composed => {
let res = self.compose_state.borrow().keysym();
self.compose_state.borrow_mut().reset();
let mut compose_state = self.compose_state.borrow_mut();
let res = compose_state.keysym();
if let Some(utf8) = compose_state.utf8() {
kc.replace(crate::KeyCode::composed(&utf8));
}
compose_state.reset();
res.unwrap_or(xsym)
}
ComposeStatus::Nothing => xsym,
ComposeStatus::Nothing => {
let utf8 = self.state.borrow().key_get_utf8(xcode);
if !utf8.is_empty() {
kc.replace(crate::KeyCode::composed(&utf8));
}
xsym
}
ComposeStatus::Cancelled => {
self.compose_state.borrow_mut().reset();
return None;
@ -184,7 +195,11 @@ impl Keyboard {
xsym
};
let kc = keysym_to_keycode(ksym).or_else(|| keysym_to_keycode(xsym))?;
let kc = match kc {
Some(kc) => kc,
None => keysym_to_keycode(ksym).or_else(|| keysym_to_keycode(xsym))?,
};
let raw_modifiers = self.get_key_modifiers();
// X11 keysyms that map to KeyCode::Char already factor in the SHIFT
// modifier state. eg: SHIFT-c in an US layout produces `Char('C')`.
@ -201,16 +216,19 @@ impl Keyboard {
(_, mods) => mods,
};
Some(KeyEvent {
key: kc,
modifiers,
raw_key: None,
raw_modifiers,
raw_code: Some(xcode),
phys_code: self.phys_code_map.borrow().get(&xcode).copied(),
repeat_count: 1,
key_is_down: pressed,
})
Some(
KeyEvent {
key: kc,
modifiers,
raw_key: None,
raw_modifiers,
raw_code: Some(xcode),
phys_code: self.phys_code_map.borrow().get(&xcode).copied(),
repeat_count: 1,
key_is_down: pressed,
}
.normalize_ctrl(),
)
}
fn mod_is_active(&self, modifier: &str) -> bool {