summaryrefslogtreecommitdiffstats
path: root/zellij-server/src/tab/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'zellij-server/src/tab/mod.rs')
-rw-r--r--zellij-server/src/tab/mod.rs146
1 files changed, 143 insertions, 3 deletions
diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs
index a2eb79203..1c1a77ac8 100644
--- a/zellij-server/src/tab/mod.rs
+++ b/zellij-server/src/tab/mod.rs
@@ -18,7 +18,7 @@ use zellij_utils::{position::Position, serde};
use crate::background_jobs::BackgroundJob;
use crate::pty_writer::PtyWriteInstruction;
use crate::screen::CopyOptions;
-use crate::ui::pane_boundaries_frame::FrameParams;
+use crate::ui::{loading_indication::LoadingIndication, pane_boundaries_frame::FrameParams};
use layout_applier::LayoutApplier;
use swap_layouts::SwapLayouts;
@@ -28,7 +28,7 @@ use crate::{
output::{CharacterChunk, Output, SixelImageChunk},
panes::sixel::SixelImageStore,
panes::{FloatingPanes, TiledPanes},
- panes::{LinkHandler, PaneId, TerminalPane},
+ panes::{LinkHandler, PaneId, PluginPane, TerminalPane},
plugins::PluginInstruction,
pty::{ClientOrTabIndex, PtyInstruction, VteBytes},
thread_bus::ThreadSenders,
@@ -438,6 +438,8 @@ pub trait Pane {
fn frame_color_override(&self) -> Option<PaletteColor>;
fn invoked_with(&self) -> &Option<Run>;
fn set_title(&mut self, title: String);
+ fn update_loading_indication(&mut self, _loading_indication: LoadingIndication) {} // only relevant for plugins
+ fn progress_animation_offset(&mut self) {} // only relevant for plugins
}
#[derive(Clone, Debug)]
@@ -599,6 +601,7 @@ impl Tab {
&self.terminal_emulator_colors,
&self.terminal_emulator_color_codes,
&self.character_cell_size,
+ &self.connected_clients,
&self.style,
&self.display_area,
&mut self.tiled_panes,
@@ -657,6 +660,7 @@ impl Tab {
&self.terminal_emulator_colors,
&self.terminal_emulator_color_codes,
&self.character_cell_size,
+ &self.connected_clients,
&self.style,
&self.display_area,
&mut self.tiled_panes,
@@ -709,6 +713,7 @@ impl Tab {
&self.terminal_emulator_colors,
&self.terminal_emulator_color_codes,
&self.character_cell_size,
+ &self.connected_clients,
&self.style,
&self.display_area,
&mut self.tiled_panes,
@@ -1104,6 +1109,114 @@ impl Tab {
}
Ok(())
}
+ pub fn new_plugin_pane(
+ &mut self,
+ pid: PaneId,
+ initial_pane_title: String,
+ should_float: Option<bool>,
+ run_plugin: Run,
+ client_id: Option<ClientId>,
+ ) -> Result<()> {
+ let err_context = || format!("failed to create new pane with id {pid:?}");
+
+ match should_float {
+ Some(true) => self.show_floating_panes(),
+ Some(false) => self.hide_floating_panes(),
+ None => {},
+ };
+ if self.floating_panes.panes_are_visible() {
+ if let Some(new_pane_geom) = self.floating_panes.find_room_for_new_pane() {
+ if let PaneId::Plugin(plugin_pid) = pid {
+ let mut new_pane = PluginPane::new(
+ plugin_pid,
+ new_pane_geom,
+ self.senders
+ .to_plugin
+ .as_ref()
+ .with_context(err_context)?
+ .clone(),
+ initial_pane_title,
+ String::new(),
+ self.sixel_image_store.clone(),
+ self.terminal_emulator_colors.clone(),
+ self.terminal_emulator_color_codes.clone(),
+ self.link_handler.clone(),
+ self.character_cell_size.clone(),
+ self.connected_clients.borrow().iter().copied().collect(),
+ self.style,
+ Some(run_plugin),
+ );
+ new_pane.set_active_at(Instant::now());
+ new_pane.set_content_offset(Offset::frame(1)); // floating panes always have a frame
+ resize_pty!(
+ new_pane,
+ self.os_api,
+ self.senders,
+ self.character_cell_size
+ )
+ .with_context(err_context)?;
+ self.floating_panes.add_pane(pid, Box::new(new_pane));
+ self.floating_panes.focus_pane_for_all_clients(pid);
+ }
+ if self.auto_layout && !self.swap_layouts.is_floating_damaged() {
+ // only do this if we're already in this layout, otherwise it might be
+ // confusing and not what the user intends
+ self.swap_layouts.set_is_floating_damaged(); // we do this so that we won't skip to the
+ // next layout
+ self.next_swap_layout(client_id, true)?;
+ }
+ }
+ } else {
+ if self.tiled_panes.fullscreen_is_active() {
+ self.tiled_panes.unset_fullscreen();
+ }
+ let should_auto_layout = self.auto_layout && !self.swap_layouts.is_tiled_damaged();
+ if self.tiled_panes.has_room_for_new_pane() {
+ if let PaneId::Plugin(plugin_pid) = pid {
+ let mut new_pane = PluginPane::new(
+ plugin_pid,
+ PaneGeom::default(), // the initial size will be set later
+ self.senders
+ .to_plugin
+ .as_ref()
+ .with_context(err_context)?
+ .clone(),
+ initial_pane_title,
+ String::new(),
+ self.sixel_image_store.clone(),
+ self.terminal_emulator_colors.clone(),
+ self.terminal_emulator_color_codes.clone(),
+ self.link_handler.clone(),
+ self.character_cell_size.clone(),
+ self.connected_clients.borrow().iter().copied().collect(),
+ self.style,
+ Some(run_plugin),
+ );
+ new_pane.set_active_at(Instant::now());
+ if should_auto_layout {
+ // no need to relayout here, we'll do it when reapplying the swap layout
+ // below
+ self.tiled_panes
+ .insert_pane_without_relayout(pid, Box::new(new_pane));
+ } else {
+ self.tiled_panes.insert_pane(pid, Box::new(new_pane));
+ }
+ self.should_clear_display_before_rendering = true;
+ if let Some(client_id) = client_id {
+ self.tiled_panes.focus_pane(pid, client_id);
+ }
+ }
+ }
+ if should_auto_layout {
+ // only do this if we're already in this layout, otherwise it might be
+ // confusing and not what the user intends
+ self.swap_layouts.set_is_tiled_damaged(); // we do this so that we won't skip to the
+ // next layout
+ self.next_swap_layout(client_id, true)?;
+ }
+ }
+ Ok(())
+ }
pub fn suppress_active_pane(&mut self, pid: PaneId, client_id: ClientId) -> Result<()> {
// this method creates a new pane from pid and replaces it with the active pane
// the active pane is then suppressed (hidden and not rendered) until the current
@@ -3220,7 +3333,34 @@ impl Tab {
pane.clear_pane_frame_color_override();
}
}
-
+ pub fn update_plugin_loading_stage(&mut self, pid: u32, loading_indication: LoadingIndication) {
+ if let Some(plugin_pane) = self
+ .tiled_panes
+ .get_pane_mut(PaneId::Plugin(pid))
+ .or_else(|| self.floating_panes.get_pane_mut(PaneId::Plugin(pid)))
+ .or_else(|| {
+ self.suppressed_panes
+ .values_mut()
+ .find(|s_p| s_p.pid() == PaneId::Plugin(pid))
+ })
+ {
+ plugin_pane.update_loading_indication(loading_indication);
+ }
+ }
+ pub fn progress_plugin_loading_offset(&mut self, pid: u32) {
+ if let Some(plugin_pane) = self
+ .tiled_panes
+ .get_pane_mut(PaneId::Plugin(pid))
+ .or_else(|| self.floating_panes.get_pane_mut(PaneId::Plugin(pid)))
+ .or_else(|| {
+ self.suppressed_panes
+ .values_mut()
+ .find(|s_p| s_p.pid() == PaneId::Plugin(pid))
+ })
+ {
+ plugin_pane.progress_animation_offset();
+ }
+ }
fn show_floating_panes(&mut self) {
// this function is to be preferred to directly invoking floating_panes.toggle_show_panes(true)
self.floating_panes.toggle_show_panes(true);