diff --git a/src/editor/mod.rs b/src/editor/mod.rs index 3645c61..3c816dd 100644 --- a/src/editor/mod.rs +++ b/src/editor/mod.rs @@ -197,15 +197,15 @@ impl Editor { } add_command(&mut draw_commands, command); } - let should_clear = self.grid.should_clear; + let should_clear = self.grid.should_clear; let draw_commands = draw_commands .into_iter() .filter(|command| { let (x, y) = command.grid_position; - let min = (x as i64 - 1).max(0) as u64; let max = (x + command.cell_width + 1).min(self.grid.width); + for char_index in min..max { if self.grid.is_dirty_cell(char_index, y) { return true; @@ -230,6 +230,7 @@ impl Editor { }; let mut text = cell.text; + if let Some(times) = cell.repeat { text = text.repeat(times as usize); } @@ -250,6 +251,7 @@ impl Editor { } *column_pos += text.graphemes(true).count() as u64; } + self.previous_style = style; } diff --git a/src/redraw_scheduler.rs b/src/redraw_scheduler.rs index e67d577..46cf56b 100644 --- a/src/redraw_scheduler.rs +++ b/src/redraw_scheduler.rs @@ -48,6 +48,7 @@ impl RedrawScheduler { pub fn schedule(&self, new_scheduled: Instant) { trace!("Redraw scheduled for {:?}", new_scheduled); let mut scheduled_frame = self.scheduled_frame.lock().unwrap(); + if let Some(previous_scheduled) = *scheduled_frame { if new_scheduled < previous_scheduled { *scheduled_frame = Some(new_scheduled); @@ -60,18 +61,21 @@ impl RedrawScheduler { pub fn queue_next_frame(&self) { trace!("Next frame queued"); let buffer_frames = SETTINGS.get::().extra_buffer_frames; + self.frames_queued .store(buffer_frames as u16, Ordering::Relaxed); } pub fn should_draw(&self) -> bool { let frames_queued = self.frames_queued.load(Ordering::Relaxed); + if frames_queued > 0 { self.frames_queued .store(frames_queued - 1, Ordering::Relaxed); true } else { let mut next_scheduled_frame = self.scheduled_frame.lock().unwrap(); + if let Some(scheduled_frame) = *next_scheduled_frame { if scheduled_frame < Instant::now() { *next_scheduled_frame = None; diff --git a/src/renderer/cursor_renderer/cursor_vfx.rs b/src/renderer/cursor_renderer/cursor_vfx.rs index d069a66..2113e73 100644 --- a/src/renderer/cursor_renderer/cursor_vfx.rs +++ b/src/renderer/cursor_renderer/cursor_vfx.rs @@ -134,12 +134,14 @@ impl CursorVfx for PointHighlight { if self.t == 1.0 { return; } + let mut paint = Paint::new(skulpin::skia_safe::colors::WHITE, None); paint.set_blend_mode(BlendMode::SrcOver); let base_color: Color = cursor.background(&colors).to_color(); let alpha = ease(ease_in_quad, settings.vfx_opacity, 0.0, self.t) as u8; let color = Color::from_argb(alpha, base_color.r(), base_color.g(), base_color.b()); + paint.set_color(color); let size = 3.0 * font_size.1; diff --git a/src/renderer/cursor_renderer/mod.rs b/src/renderer/cursor_renderer/mod.rs index ee048ed..f4e9e5c 100644 --- a/src/renderer/cursor_renderer/mod.rs +++ b/src/renderer/cursor_renderer/mod.rs @@ -215,6 +215,7 @@ impl CursorRenderer { .enumerate() .map(|(i, corner)| { let (x, y) = STANDARD_CORNERS[i]; + Corner { relative_position: match cursor_shape { CursorShape::Block => (x, y).into(), @@ -261,8 +262,10 @@ impl CursorRenderer { let editor = EDITOR.lock(); let (_, grid_y) = cursor.position; let (_, previous_y) = self.previous_position; + if grid_y == editor.grid.height - 1 && previous_y != grid_y { self.command_line_delay += 1; + if self.command_line_delay < COMMAND_LINE_DELAY_FRAMES { self.previous_position } else { @@ -342,23 +345,29 @@ impl CursorRenderer { // The cursor is made up of four points, so I create a path with each of the four // corners. let mut path = Path::new(); + path.move_to(self.corners[0].current_position); path.line_to(self.corners[1].current_position); path.line_to(self.corners[2].current_position); path.line_to(self.corners[3].current_position); path.close(); + canvas.draw_path(&path, &paint); // Draw foreground paint.set_color(cursor.foreground(&default_colors).to_color()); + canvas.save(); canvas.clip_path(&path, None, Some(false)); let blobs = &shaper.shape_cached(&character, false, false); + for blob in blobs.iter() { canvas.draw_text_blob(&blob, destination, &paint); } + canvas.restore(); + if let Some(vfx) = self.cursor_vfx.as_ref() { vfx.render( &settings, diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index c37a49a..49948e5 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -215,6 +215,7 @@ impl Renderer { &default_style, ); } + for command in draw_commands.iter() { self.draw_foreground( &mut canvas, @@ -234,10 +235,10 @@ impl Renderer { window_size.width as f32, window_size.height as f32, ); + gpu_canvas.draw_image_rect(image, None, &image_destination, &self.paint); self.surface = Some(surface); - self.cursor_renderer.draw( cursor, &default_style.colors, diff --git a/src/settings.rs b/src/settings.rs index cb7616c..70a37e1 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -206,6 +206,7 @@ impl Settings { pub async fn read_initial_values(&self, nvim: &Neovim>) { let keys: Vec = self.listeners.read().keys().cloned().collect(); + for name in keys { let variable_name = format!("neovide_{}", name.to_string()); match nvim.get_var(&variable_name).await { @@ -223,6 +224,7 @@ impl Settings { pub async fn setup_changed_listeners(&self, nvim: &Neovim>) { let keys: Vec = self.listeners.read().keys().cloned().collect(); + for name in keys { let vimscript = format!( concat!( diff --git a/src/window.rs b/src/window.rs index a69becb..18ac555 100644 --- a/src/window.rs +++ b/src/window.rs @@ -97,6 +97,7 @@ pub fn window_geometry() -> Result<(u64, u64), String> { .map_err(|msg| msg.to_owned()) }) } + pub fn window_geometry_or_default() -> (u64, u64) { window_geometry().unwrap_or(INITIAL_DIMENSIONS) } @@ -218,11 +219,13 @@ impl WindowWrapper { } } } + self.fullscreen = !self.fullscreen; } pub fn synchronize_settings(&mut self) { let editor_title = { EDITOR.lock().title.clone() }; + if self.title != editor_title { self.title = editor_title; self.window @@ -231,6 +234,7 @@ impl WindowWrapper { } let transparency = { SETTINGS.get::().transparency }; + if let Ok(opacity) = self.window.opacity() { if opacity != transparency { self.window.set_opacity(transparency).ok(); @@ -239,6 +243,7 @@ impl WindowWrapper { } let fullscreen = { SETTINGS.get::().fullscreen }; + if self.fullscreen != fullscreen { self.toggle_fullscreen(); } @@ -268,6 +273,7 @@ impl WindowWrapper { pub fn handle_pointer_motion(&mut self, x: i32, y: i32) { let previous_position = self.mouse_position; + if let Ok(new_mouse_position) = LogicalSize::from_physical_size_tuple( ( (x as f32 / self.renderer.font_width) as u32, @@ -276,6 +282,7 @@ impl WindowWrapper { &self.window, ) { self.mouse_position = new_mouse_position; + if self.mouse_down && previous_position != self.mouse_position { BRIDGE.queue_command(UiCommand::Drag( self.mouse_position.width, @@ -357,6 +364,7 @@ impl WindowWrapper { if let Ok(new_dpis) = dpis(&self.window) { if self.previous_dpis != new_dpis { let physical_size = PhysicalSize::new(&self.window); + self.window .set_size( (physical_size.width as f32 * new_dpis.0 / self.previous_dpis.0) as u32, @@ -368,9 +376,12 @@ impl WindowWrapper { } debug!("Render Triggered"); + let current_size = self.previous_size; + if REDRAW_SCHEDULER.should_draw() || SETTINGS.get::().no_idle { let renderer = &mut self.renderer; + if self .skulpin_renderer .draw(&self.window, |canvas, coordinate_system_helper| { @@ -386,6 +397,7 @@ impl WindowWrapper { return false; } } + return true; } } @@ -424,6 +436,7 @@ pub fn ui_loop() { .context .event_pump() .expect("Could not create sdl event pump"); + loop { let frame_start = Instant::now();