Unnamed repository; edit this file 'description' to name the repository.
Emit OSC11 to update terminal background on theme change
Michael Davis 4 months ago
parent 8e306af · commit c104065
-rw-r--r--helix-term/src/application.rs34
-rw-r--r--helix-term/src/commands/typed.rs1
-rw-r--r--helix-tui/src/backend/crossterm.rs4
-rw-r--r--helix-tui/src/backend/mod.rs6
-rw-r--r--helix-tui/src/backend/termina.rs21
-rw-r--r--helix-tui/src/backend/test.rs4
-rw-r--r--helix-view/src/editor.rs1
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 {