tui: Cache the keyboard enhancement check

Wether the host terminal supports keyboard enhancement can be cached
for the lifetime of a Helix session.

Caching this lookup prevents a potential lockup within crossterm's
event reading system where the query for the keyboard enhancement
support waits on the next keyboard event, which can happen if the
crossterm event stream is checked by `tokio::select!` in another
thread.
This commit is contained in:
Michael Davis 2023-03-05 12:13:11 -06:00 committed by Blaž Hrastnik
parent 3d85024717
commit 611701c362
3 changed files with 14 additions and 2 deletions

1
Cargo.lock generated
View file

@ -1202,6 +1202,7 @@ dependencies = [
"helix-core", "helix-core",
"helix-view", "helix-view",
"log", "log",
"once_cell",
"serde", "serde",
"termini", "termini",
"unicode-segmentation", "unicode-segmentation",

View file

@ -22,6 +22,7 @@ unicode-segmentation = "1.10"
crossterm = { version = "0.26", optional = true } crossterm = { version = "0.26", optional = true }
termini = "0.1" termini = "0.1"
serde = { version = "1", "optional" = true, features = ["derive"]} serde = { version = "1", "optional" = true, features = ["derive"]}
once_cell = "1.17"
log = "~0.4" log = "~0.4"
helix-view = { version = "0.6", path = "../helix-view", features = ["term"] } helix-view = { version = "0.6", path = "../helix-view", features = ["term"] }
helix-core = { version = "0.6", path = "../helix-core" } helix-core = { version = "0.6", path = "../helix-core" }

View file

@ -15,6 +15,7 @@ use crossterm::{
Command, Command,
}; };
use helix_view::graphics::{Color, CursorKind, Modifier, Rect, UnderlineStyle}; use helix_view::graphics::{Color, CursorKind, Modifier, Rect, UnderlineStyle};
use once_cell::sync::OnceCell;
use std::{ use std::{
fmt, fmt,
io::{self, Write}, io::{self, Write},
@ -57,6 +58,7 @@ impl Capabilities {
pub struct CrosstermBackend<W: Write> { pub struct CrosstermBackend<W: Write> {
buffer: W, buffer: W,
capabilities: Capabilities, capabilities: Capabilities,
supports_keyboard_enhancement_protocol: OnceCell<bool>,
} }
impl<W> CrosstermBackend<W> impl<W> CrosstermBackend<W>
@ -67,8 +69,16 @@ where
CrosstermBackend { CrosstermBackend {
buffer, buffer,
capabilities: Capabilities::from_env_or_default(), capabilities: Capabilities::from_env_or_default(),
supports_keyboard_enhancement_protocol: OnceCell::new(),
} }
} }
#[inline]
fn supports_keyboard_enhancement_protocol(&self) -> io::Result<bool> {
self.supports_keyboard_enhancement_protocol
.get_or_try_init(terminal::supports_keyboard_enhancement)
.copied()
}
} }
impl<W> Write for CrosstermBackend<W> impl<W> Write for CrosstermBackend<W>
@ -100,7 +110,7 @@ where
if config.enable_mouse_capture { if config.enable_mouse_capture {
execute!(self.buffer, EnableMouseCapture)?; execute!(self.buffer, EnableMouseCapture)?;
} }
if matches!(terminal::supports_keyboard_enhancement(), Ok(true)) { if self.supports_keyboard_enhancement_protocol()? {
log::debug!("The enhanced keyboard protocol is supported on this terminal"); log::debug!("The enhanced keyboard protocol is supported on this terminal");
execute!( execute!(
self.buffer, self.buffer,
@ -121,7 +131,7 @@ where
if config.enable_mouse_capture { if config.enable_mouse_capture {
execute!(self.buffer, DisableMouseCapture)?; execute!(self.buffer, DisableMouseCapture)?;
} }
if matches!(terminal::supports_keyboard_enhancement(), Ok(true)) { if self.supports_keyboard_enhancement_protocol()? {
execute!(self.buffer, PopKeyboardEnhancementFlags)?; execute!(self.buffer, PopKeyboardEnhancementFlags)?;
} }
execute!( execute!(