From 8d4ee2a9b704a161ab9d7554c1dc0c34dc412e33 Mon Sep 17 00:00:00 2001 From: sxyazi Date: Sat, 18 Nov 2023 15:22:11 +0800 Subject: [PATCH] .. --- yazi-fm/src/app.rs | 40 ++++++++++++++++++++++++++---------- yazi-fm/src/widgets/clear.rs | 40 +++++++++++++++++++++++++++--------- 2 files changed, 59 insertions(+), 21 deletions(-) diff --git a/yazi-fm/src/app.rs b/yazi-fm/src/app.rs index 001574bf..5c66d036 100644 --- a/yazi-fm/src/app.rs +++ b/yazi-fm/src/app.rs @@ -2,7 +2,7 @@ use std::ffi::OsString; use anyhow::{Ok, Result}; use crossterm::event::KeyEvent; -use ratatui::prelude::Rect; +use ratatui::{backend::Backend, prelude::Rect}; use tokio::sync::oneshot; use yazi_config::{keymap::{Exec, Key, KeymapLayer}, BOOT}; use yazi_core::{emit, files::FilesOp, input::InputMode, manager::Manager, Ctx, Event}; @@ -33,7 +33,7 @@ impl App { } Event::Key(key) => app.dispatch_key(key), Event::Paste(str) => app.dispatch_paste(str), - Event::Render(_) => app.dispatch_render(), + Event::Render(_) => app.dispatch_render()?, Event::Resize(cols, rows) => app.dispatch_resize(cols, rows), Event::Stop(state, tx) => app.dispatch_stop(state, tx), Event::Call(exec, layer) => app.dispatch_call(exec, layer), @@ -76,18 +76,36 @@ impl App { } } - fn dispatch_render(&mut self) { - if let Some(term) = &mut self.term { - _ = term.draw(|f| { - yazi_plugin::scope(&self.cx, |_| { - f.render_widget(Root::new(&self.cx), f.size()); - }); + fn dispatch_render(&mut self) -> Result<()> { + let Some(term) = &mut self.term else { + return Ok(()); + }; - if let Some((x, y)) = self.cx.cursor() { - f.set_cursor(x, y); - } + let frame = term.draw(|f| { + yazi_plugin::scope(&self.cx, |_| { + f.render_widget(Root::new(&self.cx), f.size()); }); + })?; + + let mut patches = Vec::new(); + // TODO: find a more efficient way to do this + for x in frame.area.left()..frame.area.right() { + for y in frame.area.top()..frame.area.bottom() { + let cell = frame.buffer.get(x, y); + if cell.skip { + patches.push((x, y, cell.clone())); + } + } } + + term.backend_mut().draw(patches.iter().map(|(x, y, cell)| (*x, *y, cell)))?; + if let Some((x, y)) = self.cx.cursor() { + term.show_cursor()?; + term.set_cursor(x, y)?; + } + + term.backend_mut().flush()?; + Ok(()) } fn dispatch_resize(&mut self, cols: u16, rows: u16) { diff --git a/yazi-fm/src/widgets/clear.rs b/yazi-fm/src/widgets/clear.rs index e1567a27..78f13525 100644 --- a/yazi-fm/src/widgets/clear.rs +++ b/yazi-fm/src/widgets/clear.rs @@ -1,19 +1,39 @@ use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget}; +use yazi_adaptor::ADAPTOR; +use yazi_config::MANAGER; pub(crate) struct Clear; +#[inline] +const fn is_overlapping(a: &Rect, b: &Rect) -> bool { + a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y +} + +fn overlap(a: &Rect, b: &Rect) -> Option { + if !is_overlapping(a, b) { + return None; + } + + let x = a.x.max(b.x); + let y = a.y.max(b.y); + let width = (a.x + a.width).min(b.x + b.width) - x; + let height = (a.y + a.height).min(b.y + b.height) - y; + Some(Rect { x, y, width, height }) +} + impl Widget for Clear { fn render(self, area: Rect, buf: &mut Buffer) { - // let stdout = BufWriter::new(stdout().lock()); - // let s = " ".repeat(area.width as usize); - // _ = Term::move_lock(stdout, (0, 0), |stdout| { - // for y in area.top()..area.bottom() { - // Term::move_to(stdout, area.x, y)?; - // stdout.write_all(s.as_bytes())?; - // } - // Ok(()) - // }); - ratatui::widgets::Clear.render(area, buf); + + let Some(r) = overlap(&area, &MANAGER.layout.image_rect()) else { + return; + }; + + ADAPTOR.image_hide(r).ok(); + for x in r.left()..r.right() { + for y in r.top()..r.bottom() { + buf.get_mut(x, y).set_skip(true); + } + } } }