From 6eb853e3136dd320272bd67e2957774869c21e4b Mon Sep 17 00:00:00 2001 From: Joscha Date: Wed, 10 May 2023 19:35:56 +0200 Subject: [PATCH] Reduce tearing when redrawing screen --- Cargo.toml | 2 +- src/terminal.rs | 29 +++++++++++++++++++++-------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b1d625c..9641efb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] async-trait = "0.1.64" -crossterm = "0.26.0" +crossterm = "0.26.1" unicode-linebreak = "0.1.4" unicode-segmentation = "1.10.1" unicode-width = "0.1.10" diff --git a/src/terminal.rs b/src/terminal.rs index e4352f1..db7dcdd 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -9,7 +9,10 @@ use crossterm::event::{ PopKeyboardEnhancementFlags, PushKeyboardEnhancementFlags, }; use crossterm::style::{PrintStyledContent, StyledContent}; -use crossterm::terminal::{Clear, ClearType, EnterAlternateScreen, LeaveAlternateScreen}; +use crossterm::terminal::{ + BeginSynchronizedUpdate, Clear, ClearType, EndSynchronizedUpdate, EnterAlternateScreen, + LeaveAlternateScreen, +}; use crossterm::{ExecutableCommand, QueueableCommand}; use crate::buffer::Buffer; @@ -198,14 +201,11 @@ impl Terminal { /// After calling this function, the frame returned by [`Self::frame`] will /// be empty again and have no cursor position. pub fn present(&mut self) -> io::Result<()> { - if self.full_redraw { - self.out.queue(Clear(ClearType::All))?; - self.prev_frame_buffer.reset(); // Because the screen is now empty - self.full_redraw = false; - } + self.out.queue(BeginSynchronizedUpdate)?; + let result = self.draw_to_screen(); + self.out.queue(EndSynchronizedUpdate)?; + result?; - self.draw_differences()?; - self.update_cursor()?; self.out.flush()?; mem::swap(&mut self.prev_frame_buffer, &mut self.frame.buffer); @@ -244,6 +244,19 @@ impl Terminal { Ok(()) } + fn draw_to_screen(&mut self) -> io::Result<()> { + if self.full_redraw { + self.out.queue(Clear(ClearType::All))?; + self.prev_frame_buffer.reset(); // Because the screen is now empty + self.full_redraw = false; + } + + self.draw_differences()?; + self.update_cursor()?; + + Ok(()) + } + fn draw_differences(&mut self) -> io::Result<()> { for (x, y, cell) in self.frame.buffer.cells() { if self.prev_frame_buffer.at(x, y) == cell {