diff --git a/src/bridge/events.rs b/src/bridge/events.rs index ba4527a..926da29 100644 --- a/src/bridge/events.rs +++ b/src/bridge/events.rs @@ -171,6 +171,9 @@ pub enum RedrawEvent { Clear { grid: u64, }, + Destroy { + grid: u64, + }, CursorGoto { grid: u64, row: u64, @@ -590,15 +593,23 @@ fn parse_grid_line(grid_line_arguments: Vec) -> Result { }) } -fn parse_clear(clear_arguments: Vec) -> Result { - let [grid_id] = extract_values(clear_arguments, [Value::Nil])?; +fn parse_grid_clear(grid_clear_arguments: Vec) -> Result { + let [grid_id] = extract_values(grid_clear_arguments, [Value::Nil])?; Ok(RedrawEvent::Clear { grid: parse_u64(grid_id)?, }) } -fn parse_cursor_goto(cursor_goto_arguments: Vec) -> Result { +fn parse_grid_destroy(grid_destroy_arguments: Vec) -> Result { + let [grid_id] = extract_values(grid_destroy_arguments, [Value::Nil])?; + + Ok(RedrawEvent::Destroy { + grid: parse_u64(grid_id)?, + }) +} + +fn parse_grid_cursor_goto(cursor_goto_arguments: Vec) -> Result { let [grid_id, column, row] = extract_values(cursor_goto_arguments, [Value::Nil, Value::Nil, Value::Nil])?; @@ -691,7 +702,7 @@ fn parse_win_external_pos(win_external_pos_arguments: Vec) -> Result Result> { "default_colors_set" => Some(parse_default_colors(event_parameters)?), "hl_attr_define" => Some(parse_hl_attr_define(event_parameters)?), "grid_line" => Some(parse_grid_line(event_parameters)?), - "grid_clear" => Some(parse_clear(event_parameters)?), - "grid_cursor_goto" => Some(parse_cursor_goto(event_parameters)?), + "grid_clear" => Some(parse_grid_clear(event_parameters)?), + "grid_destroy" => Some(parse_grid_destroy(event_parameters)?), + "grid_cursor_goto" => Some(parse_grid_cursor_goto(event_parameters)?), "grid_scroll" => Some(parse_grid_scroll(event_parameters)?), "win_pos" => Some(parse_win_pos(event_parameters)?), "win_float_pos" => Some(parse_win_float_pos(event_parameters)?), diff --git a/src/bridge/mod.rs b/src/bridge/mod.rs index 0e7a556..9cbfed3 100644 --- a/src/bridge/mod.rs +++ b/src/bridge/mod.rs @@ -160,7 +160,7 @@ async fn start_process(mut receiver: UnboundedReceiver) { .unwrap_or_explained_panic("Could not communicate with neovim process"); let mut options = UiAttachOptions::new(); options.set_linegrid_external(true); - // options.set_multigrid_external(true); + options.set_multigrid_external(true); options.set_rgb(true); if let Err(command_error) = nvim.command("runtime! ginit.vim").await { nvim.command(&format!( diff --git a/src/editor/grid.rs b/src/editor/grid.rs index aa6eaeb..f016e23 100644 --- a/src/editor/grid.rs +++ b/src/editor/grid.rs @@ -23,15 +23,30 @@ impl CharacterGrid { dirty: vec![true; cell_count], width, height, - should_clear: true, + should_clear: false, } } pub fn resize(&mut self, width: u64, height: u64) { trace!("Editor resized"); + let new_cell_count = (width * height) as usize; + let new_dirty = vec![false; new_cell_count]; + let default_cell: GridCell = None; + let mut new_characters = vec![default_cell; new_cell_count]; + + dbg!(self.width); + for x in 0..self.width.min(width) { + for y in 0..self.height.min(height) { + if let Some(existing_cell) = self.get_cell(x, y) { + new_characters[(x + y * width) as usize] = existing_cell.clone(); + } + } + } + self.width = width; self.height = height; - self.clear(); + self.dirty = new_dirty; + self.characters = new_characters; } pub fn clear(&mut self) { diff --git a/src/editor/mod.rs b/src/editor/mod.rs index ad40f75..77117d1 100644 --- a/src/editor/mod.rs +++ b/src/editor/mod.rs @@ -32,8 +32,7 @@ pub struct WindowRenderInfo { pub width: u64, pub height: u64, pub should_clear: bool, - pub draw_commands: Vec, - pub child_windows: Vec, + pub draw_commands: Vec } pub struct Editor { @@ -146,6 +145,7 @@ impl Editor { .get_mut(&grid) .map(|window| window.grid.clear()); } + RedrawEvent::Destroy { grid } => self.close_window(grid), RedrawEvent::Scroll { grid, top, @@ -341,46 +341,39 @@ impl Editor { fn build_window_render_info(&mut self, grid: u64) -> Option { let grid_position = self.get_window_top_left(grid)?; - let window = self.windows.get_mut(&grid)?; - if window.hidden { - return None; - } - let (draw_commands, should_clear) = window.build_draw_commands(); - let children = window.children.clone(); let width = window.grid.width; let height = window.grid.height; - let child_windows = children - .iter() - .filter_map(|child_id| self.build_window_render_info(*child_id)) - .collect(); - Some(WindowRenderInfo { grid_id: grid, grid_position, width, height, should_clear, - draw_commands, - child_windows, + draw_commands }) } pub fn build_render_info(&mut self) -> RenderInfo { let mut windows = Vec::new(); - let root_window_ids: Vec = self - .windows - .values() - .filter(|window| !window.hidden && window.anchor_grid_id.is_none()) - .map(|window| window.grid_id) - .collect(); + let window_ids: Vec = { + let (mut root_windows, mut floating_windows): (Vec<&Window>, Vec<&Window>) = self.windows + .values() + .filter(|window| !window.hidden) + .partition(|window| window.anchor_grid_id.is_none()); + + root_windows.sort_by(|window_a, window_b| window_a.grid_id.partial_cmp(&window_b.grid_id).unwrap()); + floating_windows.sort_by(|window_a, window_b| window_a.grid_id.partial_cmp(&window_b.grid_id).unwrap()); + + root_windows.into_iter().chain(floating_windows.into_iter()).map(|window| window.grid_id).collect() + }; - for root_window_id in root_window_ids.into_iter() { - if let Some(window_render_info) = self.build_window_render_info(root_window_id) { + for window_id in window_ids.into_iter() { + if let Some(window_render_info) = self.build_window_render_info(window_id) { windows.push(window_render_info); } } diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 253d64d..956f1e9 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -4,8 +4,9 @@ use std::sync::Arc; use log::trace; use skulpin::skia_safe::gpu::SurfaceOrigin; use skulpin::skia_safe::{ - colors, dash_path_effect, Budgeted, Canvas, ImageInfo, Paint, Rect, Surface, + colors, dash_path_effect, Budgeted, Canvas, ImageInfo, Paint, Rect, Surface, Color }; +use skulpin::skia_safe::paint::Style as PaintStyle; use skulpin::CoordinateSystemHelper; mod caching_shaper; @@ -201,14 +202,9 @@ impl Renderer { }); if surface.width() != image_width || surface.height() != image_height { - let image = surface.image_snapshot(); - surface = - self.build_window_surface(root_canvas, &default_style, (image_width, image_height)); - let image_destination = - Rect::new(0.0, 0.0, image.width() as f32, image.height() as f32); - surface - .canvas() - .draw_image_rect(image, None, &image_destination, &self.paint); + let mut old_surface = surface; + surface = self.build_window_surface(root_canvas, &default_style, (image_width, image_height)); + old_surface.draw(surface.canvas(), (0.0, 0.0), None); } let mut canvas = surface.canvas(); @@ -234,26 +230,20 @@ impl Renderer { ); } - let image = surface.image_snapshot(); - let (grid_left, grid_top) = window_render_info.grid_position; let image_left = grid_left as f32 * self.font_width; let image_top = grid_top as f32 * self.font_height; - let image_destination = Rect::new( - image_left, - image_top, - image_left + image_width as f32, - image_top + image_height as f32, - ); - root_canvas.draw_image_rect(image, None, &image_destination, &self.paint); + root_canvas.save_layer(&Default::default()); + + unsafe { + surface.draw(root_canvas.surface().unwrap().canvas(), (image_left, image_top), None); + } + + root_canvas.restore(); self.window_surfaces .insert(window_render_info.grid_id, surface); - - for child_window_render_info in window_render_info.child_windows.iter() { - self.draw_window(root_canvas, child_window_render_info, default_style); - } } pub fn draw(