1
0
Fork 0
mirror of https://github.com/alacritty/alacritty.git synced 2024-11-25 14:05:41 -05:00

Reset char suppression for every key binding

Previously the character suppression was only reset whenever a key was
released. However this did not take key repetition into account.

Now every key down also resets the character suppression. This should
work since the `ReceivedCharacter` is always received immediately after
the `KeyboardInput` without the chance of a racing condition where
another keyboard event interrupts the two.
This commit is contained in:
Christian Duerr 2023-04-09 22:52:41 +02:00 committed by Kirill Chibisov
parent d40198da53
commit 924a91e3a3
No known key found for this signature in database
GPG key ID: E803FF4B6CE71BCB
2 changed files with 62 additions and 69 deletions

View file

@ -218,6 +218,56 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
self.notifier.notify(val); self.notifier.notify(val);
} }
fn received_char(&mut self, c: char) {
// Don't insert chars when we have IME running.
if self.display().ime.preedit().is_some() {
return;
}
// Handle hint selection over anything else.
if self.display().hint_state.active() && !*self.suppress_chars {
self.hint_input(c);
return;
}
// Pass keys to search and ignore them during `suppress_chars`.
let search_active = self.search_active();
if *self.suppress_chars || search_active || self.terminal().mode().contains(TermMode::VI) {
if search_active && !*self.suppress_chars {
self.search_input(c);
}
return;
}
self.on_typing_start();
if self.terminal().grid().display_offset() != 0 {
self.scroll(Scroll::Bottom);
}
self.clear_selection();
let utf8_len = c.len_utf8();
let mut bytes = vec![0; utf8_len];
c.encode_utf8(&mut bytes[..]);
#[cfg(not(target_os = "macos"))]
let alt_send_esc = true;
// Don't send ESC when `OptionAsAlt` is used. This doesn't handle
// `Only{Left,Right}` variants due to inability to distinguish them.
#[cfg(target_os = "macos")]
let alt_send_esc = self.config().window.option_as_alt != OptionAsAlt::None;
if alt_send_esc && *self.received_count() == 0 && self.modifiers().alt() && utf8_len == 1 {
bytes.insert(0, b'\x1b');
}
self.write_to_pty(bytes);
*self.received_count() += 1;
}
/// Request a redraw. /// Request a redraw.
#[inline] #[inline]
fn mark_dirty(&mut self) { fn mark_dirty(&mut self) {
@ -1288,7 +1338,7 @@ impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> {
self.key_input(input); self.key_input(input);
}, },
WindowEvent::ModifiersChanged(modifiers) => self.modifiers_input(modifiers), WindowEvent::ModifiersChanged(modifiers) => self.modifiers_input(modifiers),
WindowEvent::ReceivedCharacter(c) => self.received_char(c), WindowEvent::ReceivedCharacter(c) => self.ctx.received_char(c),
WindowEvent::MouseInput { state, button, .. } => { WindowEvent::MouseInput { state, button, .. } => {
self.ctx.window().set_mouse_visible(true); self.ctx.window().set_mouse_visible(true);
self.mouse_input(state, button); self.mouse_input(state, button);
@ -1336,7 +1386,7 @@ impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> {
*self.ctx.dirty = true; *self.ctx.dirty = true;
for ch in text.chars() { for ch in text.chars() {
self.received_char(ch); self.ctx.received_char(ch);
} }
self.ctx.update_cursor_blinking(); self.ctx.update_cursor_blinking();

View file

@ -73,6 +73,7 @@ pub struct Processor<T: EventListener, A: ActionContext<T>> {
pub trait ActionContext<T: EventListener> { pub trait ActionContext<T: EventListener> {
fn write_to_pty<B: Into<Cow<'static, [u8]>>>(&self, _data: B) {} fn write_to_pty<B: Into<Cow<'static, [u8]>>>(&self, _data: B) {}
fn received_char(&mut self, _c: char) {}
fn mark_dirty(&mut self) {} fn mark_dirty(&mut self) {}
fn size_info(&self) -> SizeInfo; fn size_info(&self) -> SizeInfo;
fn copy_selection(&mut self, _ty: ClipboardType) {} fn copy_selection(&mut self, _ty: ClipboardType) {}
@ -152,10 +153,9 @@ impl<T: EventListener> Execute<T> for Action {
fn execute<A: ActionContext<T>>(&self, ctx: &mut A) { fn execute<A: ActionContext<T>>(&self, ctx: &mut A) {
match self { match self {
Action::Esc(s) => { Action::Esc(s) => {
ctx.on_typing_start(); for c in s.chars() {
ctx.clear_selection(); ctx.received_char(c);
ctx.scroll(Scroll::Bottom); }
ctx.write_to_pty(s.clone().into_bytes())
}, },
Action::Command(program) => ctx.spawn_daemon(program.program(), program.args()), Action::Command(program) => ctx.spawn_daemon(program.program(), program.args()),
Action::Hint(hint) => { Action::Hint(hint) => {
@ -936,12 +936,12 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
} }
} }
match input.state { // Reset character suppression.
ElementState::Pressed => { *self.ctx.suppress_chars() = false;
if let ElementState::Pressed = input.state {
*self.ctx.received_count() = 0; *self.ctx.received_count() = 0;
self.process_key_bindings(input); self.process_key_bindings(input);
},
ElementState::Released => *self.ctx.suppress_chars() = false,
} }
} }
@ -964,63 +964,6 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
self.ctx.window().set_mouse_cursor(mouse_state); self.ctx.window().set_mouse_cursor(mouse_state);
} }
/// Process a received character.
pub fn received_char(&mut self, c: char) {
let suppress_chars = *self.ctx.suppress_chars();
// Don't insert chars when we have IME running.
if self.ctx.display().ime.preedit().is_some() {
return;
}
// Handle hint selection over anything else.
if self.ctx.display().hint_state.active() && !suppress_chars {
self.ctx.hint_input(c);
return;
}
// Pass keys to search and ignore them during `suppress_chars`.
let search_active = self.ctx.search_active();
if suppress_chars || search_active || self.ctx.terminal().mode().contains(TermMode::VI) {
if search_active && !suppress_chars {
self.ctx.search_input(c);
}
return;
}
self.ctx.on_typing_start();
if self.ctx.terminal().grid().display_offset() != 0 {
self.ctx.scroll(Scroll::Bottom);
}
self.ctx.clear_selection();
let utf8_len = c.len_utf8();
let mut bytes = vec![0; utf8_len];
c.encode_utf8(&mut bytes[..]);
#[cfg(not(target_os = "macos"))]
let alt_send_esc = true;
// Don't send ESC when `OptionAsAlt` is used. This doesn't handle
// `Only{Left,Right}` variants due to inability to distinguish them.
#[cfg(target_os = "macos")]
let alt_send_esc = self.ctx.config().window.option_as_alt != OptionAsAlt::None;
if alt_send_esc
&& *self.ctx.received_count() == 0
&& self.ctx.modifiers().alt()
&& utf8_len == 1
{
bytes.insert(0, b'\x1b');
}
self.ctx.write_to_pty(bytes);
*self.ctx.received_count() += 1;
}
/// Attempt to find a binding and execute its action. /// Attempt to find a binding and execute its action.
/// ///
/// The provided mode, mods, and key must match what is allowed by a binding /// The provided mode, mods, and key must match what is allowed by a binding