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

added new window_background_gradient config option

This commit is contained in:
Wez Furlong 2021-08-12 23:08:38 -07:00
parent 690d1e3f5e
commit cbfb6d59c5
7 changed files with 239 additions and 27 deletions

35
Cargo.lock generated
View File

@ -723,6 +723,15 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "colorgrad"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fe6e84910b5d61e01f64515e4bef312cb7523cac732b776874a6fc41a1b722d"
dependencies = [
"csscolorparser",
]
[[package]]
name = "concurrent-queue"
version = "1.2.2"
@ -741,6 +750,7 @@ dependencies = [
"bitflags",
"bstr 0.2.16",
"chrono",
"colorgrad",
"dirs-next",
"enum-display-derive",
"filenamegen",
@ -946,6 +956,15 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "csscolorparser"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b47d7b15b26d6d53076f0096b9f07dc27b329eeee0c3daa9cb91cd7e4856e638"
dependencies = [
"phf",
]
[[package]]
name = "ctor"
version = "0.1.20"
@ -3092,7 +3111,9 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
dependencies = [
"phf_macros",
"phf_shared",
"proc-macro-hack",
]
[[package]]
@ -3115,6 +3136,20 @@ dependencies = [
"rand 0.7.3",
]
[[package]]
name = "phf_macros"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c"
dependencies = [
"phf_generator",
"phf_shared",
"proc-macro-hack",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "phf_shared"
version = "0.8.0"

View File

@ -16,6 +16,7 @@ battery = "0.7"
bitflags = "1.0"
bstr = "0.2"
chrono = {version="0.4", features=["unstable-locales"]}
colorgrad = "0.4"
dirs-next = "2.0"
enum-display-derive = "0.1"
filenamegen = "0.2"

88
config/src/background.rs Normal file
View File

@ -0,0 +1,88 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
pub enum Interpolation {
Linear,
Basis,
CatmullRom,
}
impl Default for Interpolation {
fn default() -> Self {
Interpolation::Linear
}
}
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
pub enum BlendMode {
Rgb,
LinearRgb,
Hsv,
Oklab,
}
impl Default for BlendMode {
fn default() -> Self {
BlendMode::Rgb
}
}
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
pub enum GradientOrientation {
Horizontal,
Vertical,
}
impl Default for GradientOrientation {
fn default() -> Self {
Self::Horizontal
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Gradient {
#[serde(default)]
pub orientation: GradientOrientation,
pub colors: Vec<String>,
#[serde(default)]
pub interpolation: Interpolation,
#[serde(default)]
pub blend: BlendMode,
#[serde(default)]
pub segment_size: Option<usize>,
#[serde(default)]
pub segment_smoothness: Option<f64>,
}
impl Gradient {
pub fn build(&self) -> anyhow::Result<colorgrad::Gradient> {
use colorgrad::{BlendMode as CGMode, Interpolation as CGInterp};
let colors: Vec<&str> = self.colors.iter().map(|s| s.as_str()).collect();
let mut g = colorgrad::CustomGradient::new();
g.html_colors(&colors);
g.mode(match self.blend {
BlendMode::Rgb => CGMode::Rgb,
BlendMode::LinearRgb => CGMode::LinearRgb,
BlendMode::Hsv => CGMode::Hsv,
BlendMode::Oklab => CGMode::Oklab,
});
g.interpolation(match self.interpolation {
Interpolation::Linear => CGInterp::Linear,
Interpolation::Basis => CGInterp::Basis,
Interpolation::CatmullRom => CGInterp::CatmullRom,
});
let g = g.build()?;
match (self.segment_size, self.segment_smoothness) {
(Some(size), Some(smoothness)) => Ok(g.sharp(size, smoothness)),
(None, None) => Ok(g),
_ => anyhow::bail!(
"Gradient must either specify both segment_size and segment_smoothness, or neither"
),
}
}
}

View File

@ -27,6 +27,7 @@ use termwiz::surface::CursorShape;
use toml;
use wezterm_input_types::{KeyCode, Modifiers, WindowDecorations};
mod background;
mod color;
mod daemon;
mod font;
@ -40,6 +41,7 @@ mod tls;
mod unix;
mod version;
pub use background::*;
pub use color::*;
pub use daemon::*;
pub use font::*;
@ -1031,6 +1033,8 @@ pub struct Config {
#[serde(default)]
pub window_background_image: Option<PathBuf>,
#[serde(default)]
pub window_background_gradient: Option<Gradient>,
#[serde(default)]
pub window_background_image_hsb: Option<HsbTransform>,
#[serde(default)]
pub foreground_text_hsb: HsbTransform,
@ -1550,7 +1554,7 @@ impl Config {
}
}
if let Some(path) = self.window_background_image.as_ref() {
if let Some(path) = &self.window_background_image {
if !path.is_absolute() {
cfg.window_background_image.replace(config_dir.join(path));
}

View File

@ -77,6 +77,7 @@ As features stabilize some brief notes about them will accumulate here.
* Fixed: copying really long lines could falsely introduce line breaks on line wrap boundaries [#874](https://github.com/wez/wezterm/issues/874)
* New: [wezterm.add_to_config_reload_watch_list](config/lua/wezterm/add_to_config_reload_watch_list.md) function to aid with automatically reloading the config when you've split your config across multiple files. Thanks to [@AusCyberman](https://github.com/AusCyberman)! [#989](https://github.com/wez/wezterm/pull/989)
* Improved: wezterm now respects default emoji presentation and explicit emoji variation selectors (VS15 and VS16) so that glyphs that have both textual (usually monochrome, single cell width) and emoji (color, double width) presentations can be more faithfully rendered. [#997](https://github.com/wez/wezterm/issues/997)
* New: [window_background_gradient](config/lua/config/window_background_gradient.md) option to configure color gradients for your window background
### 20210502-154244-3f7122cb

View File

@ -0,0 +1,54 @@
# window_background_gradient
*Since: nightly builds only*
Dynamically generates a `window_background_image` from the provided gradient
specification. When `window_background_gradient` is configured, the value
for `window_background_image` is ignored.
Linear gradients with vertical or horizontal orientation are supported:
```lua
return {
window_background_gradient = {
-- Can be "Vertical" or "Horizontal". Specifies the direction
-- in which the color gradient varies. The default is "Horizontal",
-- with the gradient going from left-to-right
orientation = "Vertical",
-- Specifies the set of colors that are interpolated in the gradient.
-- Accepts CSS style color specs, from named colors, through rgb
-- strings and more
colors = {
"#0f0c29",
"#302b63",
"#24243e"
},
-- Specifies the interpolation style to be used.
-- "Linear", "Basis" and "CatmullRom" as supported.
-- The default is "Linear".
interpolation = "Linear",
-- How the colors are blended in the gradient.
-- "Rgb", "LinearRgb", "Hsv" and "Oklab" are supported.
-- The default is "Rgb".
blend = "Rgb",
-- By default, the gradient smoothly transitions between the colors.
-- You can adjust the sharpness by specifying the segment_size and
-- segment_smoothness parameters.
-- segment_size configures how many segments are present.
-- segment_smoothness is how hard the edge is; 0.0 is a hard edge,
-- 1.0 is a soft edge.
-- segment_size = 11,
-- segment_smoothness = 0.0,
},
}
```
Gradients are implemented using the `colorgrad` crate.
Take a look at <https://github.com/mazznoer/colorgrad-rs#using-web-color-format>
for some usage examples and additional information about gradients.

View File

@ -21,7 +21,9 @@ use anyhow::{anyhow, ensure};
use config::keyassignment::{
ClipboardCopyDestination, ClipboardPasteSource, InputMap, KeyAssignment, SpawnCommand,
};
use config::{configuration, ConfigHandle, TermConfig, WindowCloseConfirmation};
use config::{
configuration, ConfigHandle, GradientOrientation, TermConfig, WindowCloseConfirmation,
};
use luahelper::impl_lua_conversion;
use mlua::FromLua;
use mux::domain::{DomainId, DomainState};
@ -327,7 +329,47 @@ impl TermWindow {
}
}
fn load_background_image(config: &ConfigHandle) -> Option<Arc<ImageData>> {
fn load_background_image(config: &ConfigHandle, dimensions: &Dimensions) -> Option<Arc<ImageData>> {
match &config.window_background_gradient {
Some(g) => match g.build() {
Ok(grad) => {
let width = dimensions.pixel_width as u32;
let height = dimensions.pixel_height as u32;
let mut imgbuf = image::RgbaImage::new(width, height);
let fw = dimensions.pixel_width as f64;
let fh = dimensions.pixel_height as f64;
match g.orientation {
GradientOrientation::Horizontal => {
for (x, _, pixel) in imgbuf.enumerate_pixels_mut() {
let (r, g, b, a) = grad.at(x as f64 / fw).rgba_u8();
*pixel = image::Rgba([r, g, b, a]);
}
}
GradientOrientation::Vertical => {
for (_, y, pixel) in imgbuf.enumerate_pixels_mut() {
let (r, g, b, a) = grad.at(y as f64 / fh).rgba_u8();
*pixel = image::Rgba([r, g, b, a]);
}
}
}
let data = imgbuf.into_vec();
return Some(Arc::new(ImageData::with_data(
ImageDataType::new_single_frame(width, height, data),
)));
}
Err(err) => {
log::error!(
"window_background_gradient: error building gradient: {:#} {:?}",
err,
g
);
return None;
}
},
None => {}
}
match &config.window_background_image {
Some(p) => match std::fs::read(p) {
Ok(data) => {
@ -351,28 +393,14 @@ fn load_background_image(config: &ConfigHandle) -> Option<Arc<ImageData>> {
fn reload_background_image(
config: &ConfigHandle,
image: &Option<Arc<ImageData>>,
dimensions: &Dimensions,
) -> Option<Arc<ImageData>> {
match &config.window_background_image {
Some(p) => match std::fs::read(p) {
Ok(data) => {
let data = ImageDataType::EncodedFile(data).decode();
match image {
Some(existing) if existing.hash() == data.compute_hash() => {
Some(Arc::clone(existing))
}
_ => Some(Arc::new(ImageData::with_data(data))),
}
}
Err(err) => {
log::error!(
"Failed to load window_background_image {}: {}",
p.display(),
err
);
None
}
},
None => None,
let data = load_background_image(config, dimensions)?;
match image {
Some(existing) if existing.hash() == data.data().compute_hash() => {
Some(Arc::clone(existing))
}
_ => Some(data),
}
}
@ -380,8 +408,6 @@ impl TermWindow {
pub async fn new_window(mux_window_id: MuxWindowId) -> anyhow::Result<()> {
let config = configuration();
let window_background = load_background_image(&config);
let dpi = config.dpi.unwrap_or_else(|| ::window::default_dpi()) as usize;
let fontconfig = Rc::new(FontConfiguration::new(Some(config.clone()), dpi)?);
@ -423,6 +449,8 @@ impl TermWindow {
dpi,
};
let window_background = load_background_image(&config, &dimensions);
log::trace!(
"TermWindow::new_window called with mux_window_id {} {:?} {:?}",
mux_window_id,
@ -988,7 +1016,8 @@ impl TermWindow {
self.config = config.clone();
self.palette.take();
self.window_background = reload_background_image(&config, &self.window_background);
self.window_background =
reload_background_image(&config, &self.window_background, &self.dimensions);
let mux = Mux::get().unwrap();
let window = match mux.get_window(self.mux_window_id) {