mirror of
https://github.com/wez/wezterm.git
synced 2024-12-23 13:21:38 +03:00
added new window_background_gradient config option
This commit is contained in:
parent
690d1e3f5e
commit
cbfb6d59c5
35
Cargo.lock
generated
35
Cargo.lock
generated
@ -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"
|
||||
|
@ -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
88
config/src/background.rs
Normal 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"
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
54
docs/config/lua/config/window_background_gradient.md
Normal file
54
docs/config/lua/config/window_background_gradient.md
Normal 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.
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user