diff options
Diffstat (limited to 'src/server/client_shell.rs')
| -rw-r--r-- | src/server/client_shell.rs | 115 |
1 files changed, 87 insertions, 28 deletions
diff --git a/src/server/client_shell.rs b/src/server/client_shell.rs index 554e8167..d542896a 100644 --- a/src/server/client_shell.rs +++ b/src/server/client_shell.rs @@ -276,6 +276,12 @@ pub(super) struct RenderedPaneSurface { pub(super) graphics_delivery: crate::kitty_graphics::surface::DeliveryCache, } +#[derive(Debug)] +pub(super) enum SurfaceRenderDeferred { + Synchronized, + Changed, +} + pub(super) fn render_pane_surface( app: &mut app::App, target: Option<crate::ui::TabSurfaceTarget>, @@ -285,36 +291,54 @@ pub(super) fn render_pane_surface( cell_size: crate::kitty_graphics::HostCellSize, graphics_delivery: &crate::kitty_graphics::surface::DeliveryCache, client_id: u64, -) -> RenderedPaneSurface { - let content_revisions_before = target - .and_then(|target| { - let workspace = app.state.workspaces.get(target.workspace_index)?; - let tab = workspace.tabs.get(target.tab_index)?; - Some( - tab.layout - .pane_ids() - .into_iter() - .filter_map(|pane_id| { - app.state - .runtime_for_pane_in_workspace( - &app.terminal_runtimes, - target.workspace_index, - pane_id, - ) - .map(|runtime| (pane_id, runtime.content_seq())) - }) - .collect::<std::collections::HashMap<_, _>>(), - ) - }) - .unwrap_or_default(); +) -> Result<RenderedPaneSurface, SurfaceRenderDeferred> { + let layout = crate::ui::compute_tab_surface_for( + &app.state, + &app.terminal_runtimes, + target, + area, + resize_panes, + cell_size, + ); + let mut content_revisions_before = std::collections::HashMap::new(); + if let Some(target) = target { + for pane in &layout.pane_infos { + if let Some(runtime) = app.state.runtime_for_pane_in_workspace( + &app.terminal_runtimes, + target.workspace_index, + pane.id, + ) { + let (synchronized, epoch) = runtime.synchronized_output_state(); + if synchronized { + return Err(SurfaceRenderDeferred::Synchronized); + } + let revision = runtime.content_seq(); + content_revisions_before.insert(pane.id, (epoch, revision)); + } + } + } + let popup_revision_before = if show_popup { + app.state + .popup_pane + .as_ref() + .and_then(|popup| app.terminal_runtimes.get(&popup.terminal_id)) + .map(|runtime| { + let (synchronized, epoch) = runtime.synchronized_output_state(); + if synchronized { + return Err(SurfaceRenderDeferred::Synchronized); + } + Ok(epoch) + }) + .transpose()? + } else { + None + }; let (buffer, cursor, hyperlinks, layout) = crate::server::render_stream::render_tab_surface_virtual( &app.state, &app.terminal_runtimes, - target, + layout, area, - resize_panes, - cell_size, ); let panes = target .map(|target| { @@ -343,7 +367,9 @@ pub(super) fn render_pane_surface( }; let content_revision = runtime.map_or(0, |runtime| { let after = runtime.content_seq(); - if content_revisions_before.get(&pane.id).copied() == Some(after) + if content_revisions_before + .get(&pane.id) + .is_some_and(|&(_, before)| before == after) && after.is_multiple_of(2) { after @@ -422,14 +448,47 @@ pub(super) fn render_pane_surface( graphics_delivery, client_id, ); - RenderedPaneSurface { + if let Some(target) = target { + for (&pane_id, &(epoch, _)) in &content_revisions_before { + if let Some(runtime) = app.state.runtime_for_pane_in_workspace( + &app.terminal_runtimes, + target.workspace_index, + pane_id, + ) { + let (synchronized, after_epoch) = runtime.synchronized_output_state(); + if synchronized { + return Err(SurfaceRenderDeferred::Synchronized); + } + if after_epoch != epoch { + return Err(SurfaceRenderDeferred::Changed); + } + } + } + } + if let Some(before) = popup_revision_before { + if let Some(runtime) = app + .state + .popup_pane + .as_ref() + .and_then(|popup| app.terminal_runtimes.get(&popup.terminal_id)) + { + let (synchronized, after_epoch) = runtime.synchronized_output_state(); + if synchronized { + return Err(SurfaceRenderDeferred::Synchronized); + } + if after_epoch != before { + return Err(SurfaceRenderDeferred::Changed); + } + } + } + Ok(RenderedPaneSurface { frame: FrameData::from_ratatui_buffer_with_hyperlinks(&buffer, cursor, &hyperlinks), panes, splits, popup, graphics, graphics_delivery: next_graphics_delivery, - } + }) } fn render_popup_surface( |
