Unnamed repository; edit this file 'description' to name the repository.
Emit OSC11 to update terminal background on theme change
| -rw-r--r-- | helix-term/src/application.rs | 34 | ||||
| -rw-r--r-- | helix-term/src/commands/typed.rs | 1 | ||||
| -rw-r--r-- | helix-tui/src/backend/crossterm.rs | 4 | ||||
| -rw-r--r-- | helix-tui/src/backend/mod.rs | 6 | ||||
| -rw-r--r-- | helix-tui/src/backend/termina.rs | 21 | ||||
| -rw-r--r-- | helix-tui/src/backend/test.rs | 4 | ||||
| -rw-r--r-- | helix-view/src/editor.rs | 1 |
7 files changed, 57 insertions, 14 deletions
diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index e14bc7bb..a082a7f7 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -124,7 +124,7 @@ impl Application { let backend = TestBackend::new(120, 150); let theme_mode = backend.get_theme_mode(); - let terminal = Terminal::new(backend)?; + let mut terminal = Terminal::new(backend)?; let area = terminal.size(); let mut compositor = Compositor::new(area); let config = Arc::new(ArcSwap::from_pointee(config)); @@ -138,12 +138,7 @@ impl Application { })), handlers, ); - Self::load_configured_theme( - &mut editor, - &config.load(), - terminal.backend().supports_true_color(), - theme_mode, - ); + Self::load_configured_theme(&mut editor, &config.load(), &mut terminal, theme_mode); let keys = Box::new(Map::new(Arc::clone(&config), |config: &Config| { &config.keys @@ -395,6 +390,15 @@ impl Application { }; self.config.store(Arc::new(app_config)); } + ConfigEvent::ThemeChanged => { + let _ = self.terminal.backend_mut().set_background_color( + self.editor + .theme + .try_get_exact("ui.background") + .and_then(|style| style.bg), + ); + return; + } } // Update all the relevant members in the editor after updating @@ -422,7 +426,7 @@ impl Application { Self::load_configured_theme( &mut self.editor, &default_config, - self.terminal.backend().supports_true_color(), + &mut self.terminal, self.theme_mode, ); @@ -460,10 +464,12 @@ impl Application { fn load_configured_theme( editor: &mut Editor, config: &Config, - terminal_true_color: bool, + terminal: &mut Terminal, mode: Option<theme::Mode>, ) { - let true_color = terminal_true_color || config.editor.true_color || crate::true_color(); + let true_color = terminal.backend().supports_true_color() + || config.editor.true_color + || crate::true_color(); let theme = config .theme .as_ref() @@ -490,7 +496,13 @@ impl Application { }) }) .unwrap_or_else(|| editor.theme_loader.default_theme(true_color)); + let background_color = theme + .try_get_exact("ui.background") + .and_then(|style| style.bg); editor.set_theme(theme); + let _ = terminal + .backend_mut() + .set_background_color(background_color); } #[cfg(windows)] @@ -720,7 +732,7 @@ impl Application { Self::load_configured_theme( &mut self.editor, &self.config.load(), - self.terminal.backend().supports_true_color(), + &mut self.terminal, Some(mode.into()), ); true diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index cf9f8b8c..8b542eb1 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -1051,6 +1051,7 @@ fn theme(cx: &mut compositor::Context, args: Args, event: PromptEvent) -> anyhow bail!("Unsupported theme: theme requires true color support"); } cx.editor.set_theme(theme); + cx.editor.config_events.0.send(ConfigEvent::ThemeChanged)?; } else { let name = cx.editor.theme.name().to_string(); diff --git a/helix-tui/src/backend/crossterm.rs b/helix-tui/src/backend/crossterm.rs index b80f2215..0a789085 100644 --- a/helix-tui/src/backend/crossterm.rs +++ b/helix-tui/src/backend/crossterm.rs @@ -330,6 +330,10 @@ where fn get_theme_mode(&self) -> Option<helix_view::theme::Mode> { None } + + fn set_background_color(&mut self, _color: Option<helix_view::theme::Color>) -> io::Result<()> { + Ok(()) + } } #[derive(Debug)] diff --git a/helix-tui/src/backend/mod.rs b/helix-tui/src/backend/mod.rs index 368a1b66..2810477d 100644 --- a/helix-tui/src/backend/mod.rs +++ b/helix-tui/src/backend/mod.rs @@ -4,7 +4,10 @@ use std::io; use crate::{buffer::Cell, terminal::Config}; -use helix_view::graphics::{CursorKind, Rect}; +use helix_view::{ + graphics::{CursorKind, Rect}, + theme::Color, +}; #[cfg(all(feature = "termina", not(windows)))] mod termina; @@ -45,4 +48,5 @@ pub trait Backend { fn flush(&mut self) -> Result<(), io::Error>; fn supports_true_color(&self) -> bool; fn get_theme_mode(&self) -> Option<helix_view::theme::Mode>; + fn set_background_color(&mut self, color: Option<Color>) -> io::Result<()>; } diff --git a/helix-tui/src/backend/termina.rs b/helix-tui/src/backend/termina.rs index ffc6da9d..97880ca5 100644 --- a/helix-tui/src/backend/termina.rs +++ b/helix-tui/src/backend/termina.rs @@ -9,6 +9,7 @@ use termina::{ escape::{ csi::{self, Csi, SgrAttributes, SgrModifiers}, dcs::{self, Dcs}, + osc::{self, Osc}, }, style::{CursorStyle, RgbColor}, Event, OneBased, PlatformTerminal, Terminal as _, WindowSize, @@ -91,7 +92,7 @@ impl TerminaBackend { terminal.set_panic_hook(move |term| { let _ = write!( term, - "{}{}{}{}{}{}{}{}{}{}{}", + "{}{}{}{}{}{}{}{}{}{}{}{}", Csi::Keyboard(csi::Keyboard::PopFlags(1)), decreset!(MouseTracking), decreset!(ButtonEventMouse), @@ -101,6 +102,7 @@ impl TerminaBackend { &hook_reset_cursor_command, decreset!(BracketedPaste), decreset!(FocusTracking), + Osc::ResetDynamicColor(osc::DynamicColorNumber::TextBackgroundColor), Csi::Edit(csi::Edit::EraseInDisplay(csi::EraseInDisplay::EraseDisplay)), decreset!(ClearAndEnableAlternateScreen), ); @@ -571,6 +573,20 @@ impl Backend for TerminaBackend { fn get_theme_mode(&self) -> Option<theme::Mode> { self.capabilities.theme_mode } + + fn set_background_color(&mut self, color: Option<Color>) -> io::Result<()> { + write!( + self.terminal, + "{}", + match color { + Some(Color::Rgb(r, g, b)) => Osc::ChangeDynamicColors( + osc::DynamicColorNumber::TextBackgroundColor, + vec![RgbColor::new(r, g, b).into()] + ), + _ => Osc::ResetDynamicColor(osc::DynamicColorNumber::TextBackgroundColor), + } + ) + } } impl Drop for TerminaBackend { @@ -582,10 +598,11 @@ impl Drop for TerminaBackend { let _ = self.disable_mouse_capture(); let _ = write!( self.terminal, - "{}{}{}{}", + "{}{}{}{}{}", &self.reset_cursor_command, decreset!(BracketedPaste), decreset!(FocusTracking), + Osc::ResetDynamicColor(osc::DynamicColorNumber::TextBackgroundColor), decreset!(ClearAndEnableAlternateScreen), ); // NOTE: Drop for Platform terminal resets the mode and flushes the buffer when not diff --git a/helix-tui/src/backend/test.rs b/helix-tui/src/backend/test.rs index b048cefc..0c45e455 100644 --- a/helix-tui/src/backend/test.rs +++ b/helix-tui/src/backend/test.rs @@ -164,4 +164,8 @@ impl Backend for TestBackend { fn get_theme_mode(&self) -> Option<helix_view::theme::Mode> { None } + + fn set_background_color(&mut self, _color: Option<helix_view::theme::Color>) -> io::Result<()> { + Ok(()) + } } diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index d33d9c18..51e7094d 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -1273,6 +1273,7 @@ pub enum EditorEvent { pub enum ConfigEvent { Refresh, Update(Box<Config>), + ThemeChanged, } enum ThemeAction { |