From 62532704c2000db4f66fb6fc6086c374ed97b818 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Mon, 30 May 2022 07:18:46 -0700 Subject: [PATCH] background: implement attachment scrolling and parallax! ```lua return { background = { { source = {File="/home/wez/Downloads/grey-bricks.png"}, -- attachment = "Scroll", attachment = {Parallax=0.1}, hsb = { brightness = 0.3, }, }, }, } ``` --- config/src/background.rs | 11 +++++++++ wezterm-gui/src/termwindow/background.rs | 29 ++++++++++++++++++------ wezterm-gui/src/termwindow/render.rs | 12 +++++++++- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/config/src/background.rs b/config/src/background.rs index 5950200a6..cf31dfa2f 100644 --- a/config/src/background.rs +++ b/config/src/background.rs @@ -160,6 +160,17 @@ impl Default for BackgroundRepeat { pub enum BackgroundAttachment { Fixed, Scroll, + Parallax(f32), +} + +impl BackgroundAttachment { + pub fn scroll_factor(&self) -> Option { + match self { + Self::Fixed => None, + Self::Scroll => Some(1.0), + Self::Parallax(f) => Some(*f), + } + } } impl Default for BackgroundAttachment { diff --git a/wezterm-gui/src/termwindow/background.rs b/wezterm-gui/src/termwindow/background.rs index 58752ace4..c758f8291 100644 --- a/wezterm-gui/src/termwindow/background.rs +++ b/wezterm-gui/src/termwindow/background.rs @@ -3,13 +3,14 @@ use crate::termwindow::RenderState; use crate::Dimensions; use anyhow::Context; use config::{ - BackgroundLayer, BackgroundRepeat, BackgroundSize, BackgroundSource, ConfigHandle, - GradientOrientation, + BackgroundLayer, BackgroundRepeat, BackgroundSize, BackgroundSource, + ConfigHandle, GradientOrientation, }; use std::collections::HashMap; use std::sync::{Arc, Mutex}; use std::time::SystemTime; use termwiz::image::{ImageData, ImageDataType}; +use wezterm_term::StableRowIndex; lazy_static::lazy_static! { static ref IMAGE_CACHE: Mutex> = Mutex::new(HashMap::new()); @@ -266,10 +267,14 @@ pub fn reload_background_image( } impl crate::TermWindow { - pub fn render_backgrounds(&self, bg_color: LinearRgba) -> anyhow::Result<()> { + pub fn render_backgrounds( + &self, + bg_color: LinearRgba, + top: StableRowIndex, + ) -> anyhow::Result<()> { let gl_state = self.render_state.as_ref().unwrap(); for (idx, layer) in self.window_background.iter().enumerate() { - self.render_background(gl_state, bg_color, layer, idx)?; + self.render_background(gl_state, bg_color, layer, idx, top)?; } Ok(()) } @@ -280,6 +285,7 @@ impl crate::TermWindow { bg_color: LinearRgba, layer: &LoadedBackgroundLayer, layer_index: usize, + top: StableRowIndex, ) -> anyhow::Result<()> { let render_layer = gl_state.layer_for_zindex(-127 + layer_index as i8)?; let vbs = render_layer.vb.borrow(); @@ -351,16 +357,25 @@ impl crate::TermWindow { BackgroundSize::Percent(p) => (pixel_height as f32 * p as f32) / 100., }; let origin_x = pixel_width / -2.; - let origin_y = pixel_height / -2.; + let top_pixel = pixel_height / -2.; + let mut origin_y = top_pixel; + + if let Some(factor) = layer.def.attachment.scroll_factor() { + let distance = top as f32 * self.render_metrics.cell_size.height as f32 * factor; + let num_tiles = distance / height; + origin_y -= num_tiles.fract() * height; + } + + let limit_y = top_pixel + pixel_height; for y_step in 0.. { let offset_y = y_step as f32 * height; - if offset_y >= pixel_height + let origin_y = origin_y + offset_y; + if origin_y >= limit_y || (y_step > 0 && layer.def.repeat_y == BackgroundRepeat::NoRepeat) { break; } - let origin_y = origin_y + offset_y; for x_step in 0.. { let offset_x = x_step as f32 * width; diff --git a/wezterm-gui/src/termwindow/render.rs b/wezterm-gui/src/termwindow/render.rs index 1c7aeb3c6..55bc1bc9f 100644 --- a/wezterm-gui/src/termwindow/render.rs +++ b/wezterm-gui/src/termwindow/render.rs @@ -1613,7 +1613,17 @@ impl super::TermWindow { match (self.window_background.is_empty(), self.allow_images) { (false, true) => { let bg_color = self.palette().background.to_linear(); - self.render_backgrounds(bg_color)?; + + let top = panes + .iter() + .find(|p| p.is_active) + .map(|p| match self.get_viewport(p.pane.pane_id()) { + Some(top) => top, + None => p.pane.get_dimensions().physical_top, + }) + .unwrap_or(0); + + self.render_backgrounds(bg_color, top)?; } _ if window_is_transparent && panes.len() > 1 => { // Avoid doubling up the background color: the panes