diff --git a/src/bridge/events.rs b/src/bridge/events.rs index 3979be1..44e5eb7 100644 --- a/src/bridge/events.rs +++ b/src/bridge/events.rs @@ -216,6 +216,13 @@ pub enum RedrawEvent { scrolled: bool, separator_character: String, }, + WindowViewport { + grid: u64, + top_line: f64, + bottom_line: f64, + current_line: f64, + current_column: f64, + }, CommandLineShow { content: StyledContent, position: u64, @@ -732,6 +739,27 @@ fn parse_msg_set_pos(msg_set_pos_arguments: Vec) -> Result { }) } +fn parse_win_viewport(win_viewport_arguments: Vec) -> Result { + let values = [ + Value::Nil, + Value::Nil, + Value::Nil, + Value::Nil, + Value::Nil, + Value::Nil, + ]; + let [grid, _window, top_line, bottom_line, current_line, current_column] = + extract_values(win_viewport_arguments, values)?; + + Ok(RedrawEvent::WindowViewport { + grid: parse_u64(grid)?, + top_line: parse_f64(top_line)?, + bottom_line: parse_f64(bottom_line)?, + current_line: parse_f64(current_line)?, + current_column: parse_f64(current_column)?, + }) +} + fn parse_styled_content(line: Value) -> Result { parse_array(line)? .into_iter() @@ -898,6 +926,7 @@ pub fn parse_redraw_event(event_value: Value) -> Result> { "win_hide" => Some(parse_win_hide(event_parameters)?), "win_close" => Some(parse_win_close(event_parameters)?), "msg_set_pos" => Some(parse_msg_set_pos(event_parameters)?), + "win_viewport" => Some(parse_win_viewport(event_parameters)?), "cmdline_show" => Some(parse_cmdline_show(event_parameters)?), "cmdline_pos" => Some(parse_cmdline_pos(event_parameters)?), "cmdline_special_char" => Some(parse_cmdline_special_char(event_parameters)?), diff --git a/src/editor/cursor.rs b/src/editor/cursor.rs index 9ef3076..5900097 100644 --- a/src/editor/cursor.rs +++ b/src/editor/cursor.rs @@ -1,240 +1,238 @@ -use std::collections::HashMap; -use std::sync::Arc; - -use skulpin::skia_safe::Color4f; - -use super::style::{Colors, Style}; - -#[derive(Debug, Clone, PartialEq)] -pub enum CursorShape { - Block, - Horizontal, - Vertical, -} - -impl CursorShape { - pub fn from_type_name(name: &str) -> Option { - match name { - "block" => Some(CursorShape::Block), - "horizontal" => Some(CursorShape::Horizontal), - "vertical" => Some(CursorShape::Vertical), - _ => None, - } - } -} - -#[derive(Default, Debug, Clone, PartialEq)] -pub struct CursorMode { - pub shape: Option, - pub style_id: Option, - pub cell_percentage: Option, - pub blinkwait: Option, - pub blinkon: Option, - pub blinkoff: Option, -} - -#[derive(Clone, PartialEq)] -pub struct Cursor { - pub position: (f64, f64), - pub grid_position: (u64, u64), - pub parent_window_id: u64, - pub shape: CursorShape, - pub cell_percentage: Option, - pub blinkwait: Option, - pub blinkon: Option, - pub blinkoff: Option, - pub style: Option>, - pub enabled: bool, - pub double_width: bool, - pub character: String, -} - -impl Cursor { - pub fn new() -> Cursor { - Cursor { - position: (0.0, 0.0), - grid_position: (0, 0), - parent_window_id: 0, - shape: CursorShape::Block, - style: None, - cell_percentage: None, - blinkwait: None, - blinkon: None, - blinkoff: None, - enabled: true, - double_width: false, - character: " ".to_string(), - } - } - - pub fn foreground(&self, default_colors: &Colors) -> Color4f { - if let Some(style) = &self.style { - style - .colors - .foreground - .clone() - .unwrap_or_else(|| default_colors.background.clone().unwrap()) - } else { - default_colors.background.clone().unwrap() - } - } - - pub fn background(&self, default_colors: &Colors) -> Color4f { - if let Some(style) = &self.style { - style - .colors - .background - .clone() - .unwrap_or_else(|| default_colors.foreground.clone().unwrap()) - } else { - default_colors.foreground.clone().unwrap() - } - } - - pub fn change_mode(&mut self, cursor_mode: &CursorMode, styles: &HashMap>) { - let CursorMode { - shape, - style_id, - cell_percentage, - blinkwait, - blinkon, - blinkoff, - } = cursor_mode; - - if let Some(shape) = shape { - self.shape = shape.clone(); - } - - if let Some(style_id) = style_id { - self.style = styles.get(style_id).cloned(); - } - - self.cell_percentage = *cell_percentage; - self.blinkwait = *blinkwait; - self.blinkon = *blinkon; - self.blinkoff = *blinkoff; - } -} - -#[cfg(test)] -mod tests { - use super::*; - - const COLORS: Colors = Colors { - foreground: Some(Color4f::new(0.1, 0.1, 0.1, 0.1)), - background: Some(Color4f::new(0.2, 0.1, 0.1, 0.1)), - special: Some(Color4f::new(0.3, 0.1, 0.1, 0.1)), - }; - - const DEFAULT_COLORS: Colors = Colors { - foreground: Some(Color4f::new(0.1, 0.2, 0.1, 0.1)), - background: Some(Color4f::new(0.2, 0.2, 0.1, 0.1)), - special: Some(Color4f::new(0.3, 0.2, 0.1, 0.1)), - }; - - const NONE_COLORS: Colors = Colors { - foreground: None, - background: None, - special: None, - }; - - #[test] - fn test_from_type_name() { - assert_eq!( - CursorShape::from_type_name("block"), - Some(CursorShape::Block) - ); - assert_eq!( - CursorShape::from_type_name("horizontal"), - Some(CursorShape::Horizontal) - ); - assert_eq!( - CursorShape::from_type_name("vertical"), - Some(CursorShape::Vertical) - ); - } - - #[test] - fn test_foreground() { - let mut cursor = Cursor::new(); - let style = Some(Arc::new(Style::new(COLORS))); - - assert_eq!( - cursor.foreground(&DEFAULT_COLORS), - DEFAULT_COLORS.background.clone().unwrap() - ); - cursor.style = style.clone(); - assert_eq!( - cursor.foreground(&DEFAULT_COLORS), - COLORS.foreground.clone().unwrap() - ); - - cursor.style = Some(Arc::new(Style::new(NONE_COLORS))); - assert_eq!( - cursor.foreground(&DEFAULT_COLORS), - DEFAULT_COLORS.background.clone().unwrap() - ); - } - - #[test] - fn test_background() { - let mut cursor = Cursor::new(); - let style = Some(Arc::new(Style::new(COLORS))); - - assert_eq!( - cursor.background(&DEFAULT_COLORS), - DEFAULT_COLORS.foreground.clone().unwrap() - ); - cursor.style = style.clone(); - assert_eq!( - cursor.background(&DEFAULT_COLORS), - COLORS.background.clone().unwrap() - ); - - cursor.style = Some(Arc::new(Style::new(NONE_COLORS))); - assert_eq!( - cursor.background(&DEFAULT_COLORS), - DEFAULT_COLORS.foreground.clone().unwrap() - ); - } - - #[test] - fn test_change_mode() { - let cursor_mode = CursorMode { - shape: Some(CursorShape::Horizontal), - style_id: Some(1), - cell_percentage: Some(100.0), - blinkwait: Some(1), - blinkon: Some(1), - blinkoff: Some(1), - }; - let mut styles = HashMap::new(); - styles.insert(1, Arc::new(Style::new(COLORS))); - - let mut cursor = Cursor::new(); - - cursor.change_mode(&cursor_mode, &styles); - assert_eq!(cursor.shape, CursorShape::Horizontal); - assert_eq!(cursor.style, styles.get(&1).cloned()); - assert_eq!(cursor.cell_percentage, Some(100.0)); - assert_eq!(cursor.blinkwait, Some(1)); - assert_eq!(cursor.blinkon, Some(1)); - assert_eq!(cursor.blinkoff, Some(1)); - - let cursor_mode_with_none = CursorMode { - shape: None, - style_id: None, - cell_percentage: None, - blinkwait: None, - blinkon: None, - blinkoff: None, - }; - cursor.change_mode(&cursor_mode_with_none, &styles); - assert_eq!(cursor.shape, CursorShape::Horizontal); - assert_eq!(cursor.style, styles.get(&1).cloned()); - assert_eq!(cursor.cell_percentage, None); - assert_eq!(cursor.blinkwait, None); - assert_eq!(cursor.blinkon, None); - assert_eq!(cursor.blinkoff, None); - } -} +use std::collections::HashMap; +use std::sync::Arc; + +use skulpin::skia_safe::Color4f; + +use super::style::{Colors, Style}; + +#[derive(Debug, Clone, PartialEq)] +pub enum CursorShape { + Block, + Horizontal, + Vertical, +} + +impl CursorShape { + pub fn from_type_name(name: &str) -> Option { + match name { + "block" => Some(CursorShape::Block), + "horizontal" => Some(CursorShape::Horizontal), + "vertical" => Some(CursorShape::Vertical), + _ => None, + } + } +} + +#[derive(Default, Debug, Clone, PartialEq)] +pub struct CursorMode { + pub shape: Option, + pub style_id: Option, + pub cell_percentage: Option, + pub blinkwait: Option, + pub blinkon: Option, + pub blinkoff: Option, +} + +#[derive(Clone, PartialEq)] +pub struct Cursor { + pub grid_position: (u64, u64), + pub parent_window_id: u64, + pub shape: CursorShape, + pub cell_percentage: Option, + pub blinkwait: Option, + pub blinkon: Option, + pub blinkoff: Option, + pub style: Option>, + pub enabled: bool, + pub double_width: bool, + pub character: String, +} + +impl Cursor { + pub fn new() -> Cursor { + Cursor { + grid_position: (0, 0), + parent_window_id: 0, + shape: CursorShape::Block, + style: None, + cell_percentage: None, + blinkwait: None, + blinkon: None, + blinkoff: None, + enabled: true, + double_width: false, + character: " ".to_string(), + } + } + + pub fn foreground(&self, default_colors: &Colors) -> Color4f { + if let Some(style) = &self.style { + style + .colors + .foreground + .clone() + .unwrap_or_else(|| default_colors.background.clone().unwrap()) + } else { + default_colors.background.clone().unwrap() + } + } + + pub fn background(&self, default_colors: &Colors) -> Color4f { + if let Some(style) = &self.style { + style + .colors + .background + .clone() + .unwrap_or_else(|| default_colors.foreground.clone().unwrap()) + } else { + default_colors.foreground.clone().unwrap() + } + } + + pub fn change_mode(&mut self, cursor_mode: &CursorMode, styles: &HashMap>) { + let CursorMode { + shape, + style_id, + cell_percentage, + blinkwait, + blinkon, + blinkoff, + } = cursor_mode; + + if let Some(shape) = shape { + self.shape = shape.clone(); + } + + if let Some(style_id) = style_id { + self.style = styles.get(style_id).cloned(); + } + + self.cell_percentage = *cell_percentage; + self.blinkwait = *blinkwait; + self.blinkon = *blinkon; + self.blinkoff = *blinkoff; + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const COLORS: Colors = Colors { + foreground: Some(Color4f::new(0.1, 0.1, 0.1, 0.1)), + background: Some(Color4f::new(0.2, 0.1, 0.1, 0.1)), + special: Some(Color4f::new(0.3, 0.1, 0.1, 0.1)), + }; + + const DEFAULT_COLORS: Colors = Colors { + foreground: Some(Color4f::new(0.1, 0.2, 0.1, 0.1)), + background: Some(Color4f::new(0.2, 0.2, 0.1, 0.1)), + special: Some(Color4f::new(0.3, 0.2, 0.1, 0.1)), + }; + + const NONE_COLORS: Colors = Colors { + foreground: None, + background: None, + special: None, + }; + + #[test] + fn test_from_type_name() { + assert_eq!( + CursorShape::from_type_name("block"), + Some(CursorShape::Block) + ); + assert_eq!( + CursorShape::from_type_name("horizontal"), + Some(CursorShape::Horizontal) + ); + assert_eq!( + CursorShape::from_type_name("vertical"), + Some(CursorShape::Vertical) + ); + } + + #[test] + fn test_foreground() { + let mut cursor = Cursor::new(); + let style = Some(Arc::new(Style::new(COLORS))); + + assert_eq!( + cursor.foreground(&DEFAULT_COLORS), + DEFAULT_COLORS.background.clone().unwrap() + ); + cursor.style = style.clone(); + assert_eq!( + cursor.foreground(&DEFAULT_COLORS), + COLORS.foreground.clone().unwrap() + ); + + cursor.style = Some(Arc::new(Style::new(NONE_COLORS))); + assert_eq!( + cursor.foreground(&DEFAULT_COLORS), + DEFAULT_COLORS.background.clone().unwrap() + ); + } + + #[test] + fn test_background() { + let mut cursor = Cursor::new(); + let style = Some(Arc::new(Style::new(COLORS))); + + assert_eq!( + cursor.background(&DEFAULT_COLORS), + DEFAULT_COLORS.foreground.clone().unwrap() + ); + cursor.style = style.clone(); + assert_eq!( + cursor.background(&DEFAULT_COLORS), + COLORS.background.clone().unwrap() + ); + + cursor.style = Some(Arc::new(Style::new(NONE_COLORS))); + assert_eq!( + cursor.background(&DEFAULT_COLORS), + DEFAULT_COLORS.foreground.clone().unwrap() + ); + } + + #[test] + fn test_change_mode() { + let cursor_mode = CursorMode { + shape: Some(CursorShape::Horizontal), + style_id: Some(1), + cell_percentage: Some(100.0), + blinkwait: Some(1), + blinkon: Some(1), + blinkoff: Some(1), + }; + let mut styles = HashMap::new(); + styles.insert(1, Arc::new(Style::new(COLORS))); + + let mut cursor = Cursor::new(); + + cursor.change_mode(&cursor_mode, &styles); + assert_eq!(cursor.shape, CursorShape::Horizontal); + assert_eq!(cursor.style, styles.get(&1).cloned()); + assert_eq!(cursor.cell_percentage, Some(100.0)); + assert_eq!(cursor.blinkwait, Some(1)); + assert_eq!(cursor.blinkon, Some(1)); + assert_eq!(cursor.blinkoff, Some(1)); + + let cursor_mode_with_none = CursorMode { + shape: None, + style_id: None, + cell_percentage: None, + blinkwait: None, + blinkon: None, + blinkoff: None, + }; + cursor.change_mode(&cursor_mode_with_none, &styles); + assert_eq!(cursor.shape, CursorShape::Horizontal); + assert_eq!(cursor.style, styles.get(&1).cloned()); + assert_eq!(cursor.cell_percentage, None); + assert_eq!(cursor.blinkwait, None); + assert_eq!(cursor.blinkon, None); + assert_eq!(cursor.blinkoff, None); + } +} diff --git a/src/editor/mod.rs b/src/editor/mod.rs index 3a0d90c..04738af 100644 --- a/src/editor/mod.rs +++ b/src/editor/mod.rs @@ -54,6 +54,7 @@ pub enum DrawCommand { UpdateCursor(Cursor), FontChanged(String), DefaultStyleChanged(Style), + ModeChanged(EditorMode), } pub enum WindowCommand { @@ -71,6 +72,7 @@ impl fmt::Debug for DrawCommand { DrawCommand::UpdateCursor(_) => write!(formatter, "UpdateCursor"), DrawCommand::FontChanged(_) => write!(formatter, "FontChanged"), DrawCommand::DefaultStyleChanged(_) => write!(formatter, "DefaultStyleChanged"), + DrawCommand::ModeChanged(_) => write!(formatter, "ModeChanged"), } } } @@ -80,7 +82,6 @@ pub struct Editor { pub cursor: Cursor, pub defined_styles: HashMap>, pub mode_list: Vec, - pub current_mode: EditorMode, pub draw_command_batcher: Arc, pub window_command_sender: Sender, } @@ -95,7 +96,6 @@ impl Editor { cursor: Cursor::new(), defined_styles: HashMap::new(), mode_list: Vec::new(), - current_mode: EditorMode::Unknown(String::from("")), draw_command_batcher: Arc::new(DrawCommandBatcher::new(batched_draw_command_sender)), window_command_sender, } @@ -113,8 +113,10 @@ impl Editor { RedrawEvent::ModeChange { mode, mode_index } => { if let Some(cursor_mode) = self.mode_list.get(mode_index as usize) { self.cursor.change_mode(cursor_mode, &self.defined_styles); - self.current_mode = mode; } + self.draw_command_batcher + .queue(DrawCommand::ModeChanged(mode)) + .ok(); } RedrawEvent::MouseOn => { self.window_command_sender @@ -218,6 +220,12 @@ impl Editor { RedrawEvent::MessageSetPosition { grid, row, .. } => { self.set_message_position(grid, row) } + RedrawEvent::WindowViewport { + grid, + top_line, + bottom_line, + .. + } => self.send_updated_viewport(grid, top_line, bottom_line), _ => {} }; } @@ -385,23 +393,13 @@ impl Editor { fn send_cursor_info(&mut self) { let (grid_left, grid_top) = self.cursor.grid_position; - match self.get_window_top_left(self.cursor.parent_window_id) { - Some((window_left, window_top)) => { - self.cursor.position = - (window_left + grid_left as f64, window_top + grid_top as f64); - - if let Some(window) = self.windows.get(&self.cursor.parent_window_id) { - let (character, double_width) = - window.get_cursor_character(grid_left, grid_top); - self.cursor.character = character; - self.cursor.double_width = double_width; - } - } - None => { - self.cursor.position = (grid_left as f64, grid_top as f64); - self.cursor.double_width = false; - self.cursor.character = " ".to_string(); - } + if let Some(window) = self.windows.get(&self.cursor.parent_window_id) { + let (character, double_width) = window.get_cursor_character(grid_left, grid_top); + self.cursor.character = character; + self.cursor.double_width = double_width; + } else { + self.cursor.double_width = false; + self.cursor.character = " ".to_string(); } self.draw_command_batcher .queue(DrawCommand::UpdateCursor(self.cursor.clone())) @@ -419,6 +417,14 @@ impl Editor { } } } + + fn send_updated_viewport(&mut self, grid: u64, top_line: f64, bottom_line: f64) { + if let Some(window) = self.windows.get_mut(&grid) { + window.update_viewport(top_line, bottom_line); + } else { + warn!("viewport event received before window initialized"); + } + } } pub fn start_editor( diff --git a/src/editor/window.rs b/src/editor/window.rs index aeb99fb..a34f3fd 100644 --- a/src/editor/window.rs +++ b/src/editor/window.rs @@ -38,6 +38,10 @@ pub enum WindowDrawCommand { Show, Hide, Close, + Viewport { + top_line: f64, + bottom_line: f64, + }, } impl fmt::Debug for WindowDrawCommand { @@ -58,6 +62,14 @@ impl fmt::Debug for WindowDrawCommand { WindowDrawCommand::Show => write!(formatter, "Show"), WindowDrawCommand::Hide => write!(formatter, "Hide"), WindowDrawCommand::Close => write!(formatter, "Close"), + WindowDrawCommand::Viewport { + top_line, + bottom_line, + } => write!( + formatter, + "Viewport {{ top: {}, bottom: {} }}", + top_line, bottom_line + ), } } } @@ -375,4 +387,11 @@ impl Window { pub fn close(&self) { self.send_command(WindowDrawCommand::Close); } + + pub fn update_viewport(&self, top_line: f64, bottom_line: f64) { + self.send_command(WindowDrawCommand::Viewport { + top_line, + bottom_line, + }); + } } diff --git a/src/renderer/cursor_renderer/mod.rs b/src/renderer/cursor_renderer/mod.rs index 4250df9..8814aa3 100644 --- a/src/renderer/cursor_renderer/mod.rs +++ b/src/renderer/cursor_renderer/mod.rs @@ -1,8 +1,12 @@ mod blink; mod cursor_vfx; +use std::collections::HashMap; + use skulpin::skia_safe::{Canvas, Paint, Path, Point}; +use super::RenderedWindow; +use crate::bridge::EditorMode; use crate::editor::{Colors, Cursor, CursorShape}; use crate::redraw_scheduler::REDRAW_SCHEDULER; use crate::renderer::animation_utils::*; @@ -178,6 +182,7 @@ impl Corner { pub struct CursorRenderer { pub corners: Vec, cursor: Cursor, + destination: Point, blink_status: BlinkStatus, previous_cursor_shape: Option, cursor_vfx: Option>, @@ -189,9 +194,9 @@ impl CursorRenderer { let mut renderer = CursorRenderer { corners: vec![Corner::new(); 4], cursor: Cursor::new(), + destination: (0.0, 0.0).into(), blink_status: BlinkStatus::new(), previous_cursor_shape: None, - //cursor_vfx: Box::new(PointHighlight::new(Point{x:0.0, y:0.0}, HighlightMode::Ripple)), cursor_vfx: None, previous_vfx_mode: cursor_vfx::VfxMode::Disabled, }; @@ -233,10 +238,36 @@ impl CursorRenderer { .collect::>(); } + pub fn update_cursor_destination( + &mut self, + font_width: f32, + font_height: f32, + windows: &HashMap, + ) { + let (cursor_grid_x, cursor_grid_y) = self.cursor.grid_position; + + if let Some(window) = windows.get(&self.cursor.parent_window_id) { + self.destination = ( + (cursor_grid_x as f32 + window.grid_current_position.x) * font_width, + (cursor_grid_y as f32 + window.grid_current_position.y + - (window.current_scroll - window.current_surfaces.top_line)) + * font_height, + ) + .into(); + } else { + self.destination = ( + cursor_grid_x as f32 * font_width, + cursor_grid_y as f32 * font_height, + ) + .into(); + } + } + pub fn draw( &mut self, default_colors: &Colors, font_size: (f32, f32), + current_mode: &EditorMode, shaper: &mut CachingShaper, canvas: &mut Canvas, dt: f32, @@ -253,7 +284,6 @@ impl CursorRenderer { let mut paint = Paint::new(skulpin::skia_safe::colors::WHITE, None); paint.set_anti_alias(settings.antialiasing); - let (grid_x, grid_y) = self.cursor.position; let character = self.cursor.character.clone(); let font_width = match (self.cursor.double_width, &self.cursor.shape) { @@ -263,14 +293,9 @@ impl CursorRenderer { let font_dimensions: Point = (font_width, font_height).into(); - let in_insert_mode = false; - // { - // let editor = EDITOR.lock(); - // matches!(editor.current_mode, EditorMode::Insert) - // }; + let in_insert_mode = matches!(current_mode, EditorMode::Insert); - let destination: Point = (grid_x as f32 * font_width, grid_y as f32 * font_height).into(); - let center_destination = destination + font_dimensions * 0.5; + let center_destination = self.destination + font_dimensions * 0.5; let new_cursor = Some(self.cursor.shape.clone()); if self.previous_cursor_shape != new_cursor { @@ -340,7 +365,7 @@ impl CursorRenderer { let blobs = &shaper.shape_cached(&character, false, false); for blob in blobs.iter() { - canvas.draw_text_blob(&blob, destination, &paint); + canvas.draw_text_blob(&blob, self.destination, &paint); } canvas.restore(); diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 7718e4e..6b65b44 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -1,335 +1,368 @@ -use std::collections::HashMap; -use std::sync::mpsc::Receiver; -use std::sync::Arc; - -use log::{error, trace, warn}; -use skulpin::skia_safe::{colors, dash_path_effect, BlendMode, Canvas, Color, Paint, Rect}; -use skulpin::CoordinateSystemHelper; - -pub mod animation_utils; -mod caching_shaper; -pub mod cursor_renderer; -pub mod font_options; -mod rendered_window; - -pub use caching_shaper::CachingShaper; -pub use font_options::*; -pub use rendered_window::{RenderedWindow, WindowDrawDetails}; - -use crate::editor::{Colors, DrawCommand, Style, WindowDrawCommand}; -use crate::settings::*; -use cursor_renderer::CursorRenderer; - -// ---------------------------------------------------------------------------- - -#[derive(Clone)] -pub struct RendererSettings { - animation_length: f32, - floating_opacity: f32, - floating_blur: bool, -} - -pub fn initialize_settings() { - SETTINGS.set(&RendererSettings { - animation_length: 0.15, - floating_opacity: 0.7, - floating_blur: true, - }); - - register_nvim_setting!( - "window_animation_length", - RendererSettings::animation_length - ); - register_nvim_setting!( - "floating_window_opacity", - RendererSettings::floating_opacity - ); - register_nvim_setting!("floating_window_blur", RendererSettings::floating_blur); -} - -// ---------------------------------------------------------------------------- - -pub struct Renderer { - rendered_windows: HashMap, - cursor_renderer: CursorRenderer, - - pub paint: Paint, - pub shaper: CachingShaper, - pub default_style: Arc