aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2025-01-17 17:52:04 +0100
committerGitHub <noreply@github.com>2025-01-17 17:52:04 +0100
commitce6a08f86bb52d47c6be60eff1afb36aed0eaba3 (patch)
treeeff14fc8fdb0b7e8f6f180b3b18a1f8b29ff059d
parentdocs(changelog): include PR link (diff)
downloadsl0ppij-ce6a08f86bb52d47c6be60eff1afb36aed0eaba3.tar.gz
sl0ppij-ce6a08f86bb52d47c6be60eff1afb36aed0eaba3.tar.xz
sl0ppij-ce6a08f86bb52d47c6be60eff1afb36aed0eaba3.zip
fix(floating-panes): handle uncaught errors (#3944)
* fix(floating-panes): handle uncaught errors * style(fmt): rustfmt
-rw-r--r--zellij-server/src/panes/floating_panes/floating_pane_grid.rs8
-rw-r--r--zellij-server/src/panes/floating_panes/mod.rs129
-rw-r--r--zellij-server/src/tab/layout_applier.rs12
-rw-r--r--zellij-server/src/tab/mod.rs29
4 files changed, 119 insertions, 59 deletions
diff --git a/zellij-server/src/panes/floating_panes/floating_pane_grid.rs b/zellij-server/src/panes/floating_panes/floating_pane_grid.rs
index 127b9b37..a88d6e42 100644
--- a/zellij-server/src/panes/floating_panes/floating_pane_grid.rs
+++ b/zellij-server/src/panes/floating_panes/floating_pane_grid.rs
@@ -761,16 +761,12 @@ impl<'a> FloatingPaneGrid<'a> {
a_pane.y().cmp(&b_pane.y())
}
});
- let active_pane_position = panes
- .iter()
- .position(|(id, _)| id == current_pane_id)
- .unwrap();
+ let active_pane_position = panes.iter().position(|(id, _)| id == current_pane_id)?;
let next_active_pane_id = panes
.get(active_pane_position + 1)
.or_else(|| panes.get(0))
- .map(|p| p.0)
- .unwrap();
+ .map(|p| p.0)?;
Some(next_active_pane_id)
}
pub fn previous_selectable_pane_id(&self, current_pane_id: &PaneId) -> Option<PaneId> {
diff --git a/zellij-server/src/panes/floating_panes/mod.rs b/zellij-server/src/panes/floating_panes/mod.rs
index ff4ca26c..8a84fd3a 100644
--- a/zellij-server/src/panes/floating_panes/mod.rs
+++ b/zellij-server/src/panes/floating_panes/mod.rs
@@ -88,12 +88,16 @@ impl FloatingPanes {
}
pub fn stack(&self) -> Option<FloatingPanesStack> {
if self.panes_are_visible() {
- let layers = self
+ let layers: Vec<PaneGeom> = self
.z_indices
.iter()
- .map(|pane_id| self.panes.get(pane_id).unwrap().position_and_size())
+ .filter_map(|pane_id| self.panes.get(pane_id).map(|p| p.position_and_size()))
.collect();
- Some(FloatingPanesStack { layers })
+ if layers.is_empty() {
+ None
+ } else {
+ Some(FloatingPanesStack { layers })
+ }
} else if self.has_pinned_panes() {
let layers = self
.z_indices
@@ -257,7 +261,8 @@ impl FloatingPanes {
pub fn position_floating_pane_layout(
&mut self,
floating_pane_layout: &FloatingPaneLayout,
- ) -> PaneGeom {
+ ) -> Result<PaneGeom> {
+ let err_context = || format!("failed to find position for floating pane");
let display_area = *self.display_area.borrow();
let viewport = *self.viewport.borrow();
let floating_pane_grid = FloatingPaneGrid::new(
@@ -266,7 +271,9 @@ impl FloatingPanes {
display_area,
viewport,
);
- let mut position = floating_pane_grid.find_room_for_new_pane().unwrap(); // TODO: no unwrap
+ let mut position = floating_pane_grid
+ .find_room_for_new_pane()
+ .with_context(err_context)?;
if let Some(x) = &floating_pane_layout.x {
position.x = x.to_position(viewport.cols);
}
@@ -301,7 +308,7 @@ impl FloatingPanes {
.y
.saturating_sub((position.y + position.rows.as_usize()) - viewport.rows);
}
- position
+ Ok(position)
}
pub fn first_floating_pane_id(&self) -> Option<PaneId> {
self.panes.keys().next().copied()
@@ -432,7 +439,7 @@ impl FloatingPanes {
display_area,
viewport,
);
- floating_pane_grid.resize(new_screen_size).unwrap();
+ floating_pane_grid.resize(new_screen_size).non_fatal();
self.set_force_render();
}
@@ -530,17 +537,20 @@ impl FloatingPanes {
Some(p) => {
// render previously active pane so that its frame does not remain actively
// colored
- let previously_active_pane = self
- .panes
- .get_mut(self.active_panes.get(&client_id).unwrap())
- .unwrap();
+ let Some(previously_active_pane) = self.get_active_pane_mut(client_id) else {
+ log::error!("Failed to get active pane");
+ return Ok(false);
+ };
previously_active_pane.set_should_render(true);
// we render the full viewport to remove any ui elements that might have been
// there before (eg. another user's cursor)
previously_active_pane.render_full_viewport();
- let next_active_pane = self.panes.get_mut(&p).unwrap();
+ let Some(next_active_pane) = self.get_pane_mut(p) else {
+ log::error!("Failed to get next active pane");
+ return Ok(false);
+ };
next_active_pane.set_should_render(true);
// we render the full viewport to remove any ui elements that might have been
// there before (eg. another user's cursor)
@@ -588,9 +598,10 @@ impl FloatingPanes {
display_area,
viewport,
);
- let pane_id = floating_pane_grid.pane_id_on_edge(direction).unwrap();
- self.focus_pane(pane_id, client_id);
- self.set_force_render();
+ if let Some(pane_id) = floating_pane_grid.pane_id_on_edge(direction) {
+ self.focus_pane(pane_id, client_id);
+ self.set_force_render();
+ }
}
pub fn move_active_pane_down(&mut self, client_id: ClientId) {
@@ -641,7 +652,7 @@ impl FloatingPanes {
display_area,
viewport,
);
- floating_pane_grid.move_pane_left(&pane_id).unwrap();
+ floating_pane_grid.move_pane_left(&pane_id).non_fatal();
self.set_force_render();
}
pub fn move_active_pane_right(&mut self, client_id: ClientId) {
@@ -658,7 +669,7 @@ impl FloatingPanes {
display_area,
viewport,
);
- floating_pane_grid.move_pane_right(&pane_id).unwrap();
+ floating_pane_grid.move_pane_right(&pane_id).non_fatal();
self.set_force_render();
}
pub fn move_active_pane(
@@ -667,8 +678,9 @@ impl FloatingPanes {
_os_api: &mut Box<dyn ServerOsApi>,
client_id: ClientId,
) {
- let active_pane_id = self.get_active_pane_id(client_id).unwrap();
- self.move_pane(search_backwards, active_pane_id)
+ if let Some(active_pane_id) = self.get_active_pane_id(client_id) {
+ self.move_pane(search_backwards, active_pane_id)
+ }
}
pub fn move_pane(&mut self, search_backwards: bool, pane_id: PaneId) {
let new_position_id = {
@@ -685,11 +697,17 @@ impl FloatingPanes {
}
};
if let Some(new_position_id) = new_position_id {
- let current_position = self.panes.get(&pane_id).unwrap();
+ let Some(current_position) = self.panes.get(&pane_id) else {
+ log::error!("Failed to find current position");
+ return;
+ };
let prev_geom = current_position.position_and_size();
let prev_geom_override = current_position.geom_override();
- let new_position = self.panes.get_mut(&new_position_id).unwrap();
+ let Some(new_position) = self.panes.get_mut(&new_position_id) else {
+ log::error!("Failed to find new position");
+ return;
+ };
let next_geom = new_position.position_and_size();
let next_geom_override = new_position.geom_override();
new_position.set_geom(prev_geom);
@@ -698,7 +716,10 @@ impl FloatingPanes {
}
new_position.set_should_render(true);
- let current_position = self.panes.get_mut(&pane_id).unwrap();
+ let Some(current_position) = self.panes.get_mut(&pane_id) else {
+ log::error!("Failed to find current position");
+ return;
+ };
current_position.set_geom(next_geom);
if let Some(geom) = next_geom_override {
current_position.set_geom_override(geom);
@@ -801,8 +822,16 @@ impl FloatingPanes {
panes.sort_by(|(a_id, _a_pane), (b_id, _b_pane)| {
// TODO: continue
Ord::cmp(
- &self.z_indices.iter().position(|id| id == *b_id).unwrap(),
- &self.z_indices.iter().position(|id| id == *a_id).unwrap(),
+ &self
+ .z_indices
+ .iter()
+ .position(|id| id == *b_id)
+ .unwrap_or(0),
+ &self
+ .z_indices
+ .iter()
+ .position(|id| id == *a_id)
+ .unwrap_or(0),
)
});
Ok(panes
@@ -832,8 +861,16 @@ impl FloatingPanes {
panes.sort_by(|(a_id, _a_pane), (b_id, _b_pane)| {
// TODO: continue
Ord::cmp(
- &self.z_indices.iter().position(|id| id == *b_id).unwrap(),
- &self.z_indices.iter().position(|id| id == *a_id).unwrap(),
+ &self
+ .z_indices
+ .iter()
+ .position(|id| id == *b_id)
+ .unwrap_or(0),
+ &self
+ .z_indices
+ .iter()
+ .position(|id| id == *a_id)
+ .unwrap_or(0),
)
});
Ok(panes
@@ -850,8 +887,16 @@ impl FloatingPanes {
panes.sort_by(|(a_id, _a_pane), (b_id, _b_pane)| {
Ord::cmp(
- &self.z_indices.iter().position(|id| id == *b_id).unwrap(),
- &self.z_indices.iter().position(|id| id == *a_id).unwrap(),
+ &self
+ .z_indices
+ .iter()
+ .position(|id| id == *b_id)
+ .unwrap_or(0),
+ &self
+ .z_indices
+ .iter()
+ .position(|id| id == *a_id)
+ .unwrap_or(0),
)
});
panes.iter().find(|(_, p)| p.contains(point)).is_some()
@@ -862,7 +907,7 @@ impl FloatingPanes {
search_selectable: bool,
) -> Option<&mut Box<dyn Pane>> {
self.get_pane_id_at(position, search_selectable)
- .unwrap()
+ .ok()?
.and_then(|pane_id| self.panes.get_mut(&pane_id))
}
pub fn set_pane_being_moved_with_mouse(&mut self, pane_id: PaneId, position: Position) {
@@ -875,7 +920,10 @@ impl FloatingPanes {
// true => changed position
let display_area = *self.display_area.borrow();
let viewport = *self.viewport.borrow();
- let (pane_id, previous_position) = self.pane_being_moved_with_mouse.unwrap();
+ let Some((pane_id, previous_position)) = self.pane_being_moved_with_mouse else {
+ log::error!("Pane is not being moved with mousd");
+ return false;
+ };
if click_position == &previous_position {
return false;
}
@@ -889,7 +937,7 @@ impl FloatingPanes {
);
floating_pane_grid
.move_pane_by(pane_id, move_x_by, move_y_by)
- .unwrap();
+ .non_fatal();
self.set_pane_being_moved_with_mouse(pane_id, *click_position);
self.set_force_render();
true
@@ -962,21 +1010,30 @@ impl FloatingPanes {
}
pub fn switch_active_pane_with(&mut self, _os_api: &mut Box<dyn ServerOsApi>, pane_id: PaneId) {
if let Some(active_pane_id) = self.first_active_floating_pane_id() {
- let current_position = self.panes.get(&active_pane_id).unwrap();
+ let Some(current_position) = self.panes.get(&active_pane_id) else {
+ log::error!("Can't find current position");
+ return;
+ };
let prev_geom = current_position.position_and_size();
let prev_geom_override = current_position.geom_override();
- let new_position = self.panes.get_mut(&pane_id).unwrap();
+ let Some(new_position) = self.panes.get_mut(&pane_id) else {
+ log::error!("Can't find position");
+ return;
+ };
let next_geom = new_position.position_and_size();
let next_geom_override = new_position.geom_override();
new_position.set_geom(prev_geom);
if let Some(geom) = prev_geom_override {
new_position.set_geom_override(geom);
}
- resize_pty!(new_position, os_api, self.senders, self.character_cell_size).unwrap();
+ resize_pty!(new_position, os_api, self.senders, self.character_cell_size).non_fatal();
new_position.set_should_render(true);
- let current_position = self.panes.get_mut(&active_pane_id).unwrap();
+ let Some(current_position) = self.panes.get_mut(&active_pane_id) else {
+ log::error!("Can't find current position");
+ return;
+ };
current_position.set_geom(next_geom);
if let Some(geom) = next_geom_override {
current_position.set_geom_override(geom);
@@ -987,7 +1044,7 @@ impl FloatingPanes {
self.senders,
self.character_cell_size
)
- .unwrap();
+ .non_fatal();
current_position.set_should_render(true);
self.focus_pane_for_all_clients(active_pane_id);
}
diff --git a/zellij-server/src/tab/layout_applier.rs b/zellij-server/src/tab/layout_applier.rs
index e2bb5ccb..ed80c39e 100644
--- a/zellij-server/src/tab/layout_applier.rs
+++ b/zellij-server/src/tab/layout_applier.rs
@@ -588,7 +588,7 @@ impl<'a> LayoutApplier<'a> {
for floating_pane_layout in floating_panes_layout {
let position_and_size = self
.floating_panes
- .position_floating_pane_layout(&floating_pane_layout);
+ .position_floating_pane_layout(&floating_pane_layout)?;
let pid_to_focus = if floating_pane_layout.already_running {
self.floating_panes.set_geom_for_pane_with_run(
floating_pane_layout.run.clone(),
@@ -682,7 +682,8 @@ impl<'a> LayoutApplier<'a> {
// contain partial positioning information (eg. just x coords with no y or size) or no
// positioning information at all
for (pane, floating_pane_layout) in panes_to_apply.drain(..) {
- pane_applier.apply_floating_panes_layout_to_floating_pane(pane, floating_pane_layout);
+ pane_applier
+ .apply_floating_panes_layout_to_floating_pane(pane, floating_pane_layout)?;
}
// here we apply positioning on a best-effort basis to any remaining panes we've got (these
@@ -969,17 +970,18 @@ impl<'a> PaneApplier<'a> {
&mut self,
mut pane: Box<dyn Pane>,
floating_panes_layout: FloatingPaneLayout,
- ) {
+ ) -> Result<()> {
let position_and_size = self
.floating_panes
- .position_floating_pane_layout(&floating_panes_layout);
+ .position_floating_pane_layout(&floating_panes_layout)?;
if let Some(pane_title) = floating_panes_layout.name.as_ref() {
pane.set_title(pane_title.into());
}
if floating_panes_layout.focus.unwrap_or(false) {
self.new_focused_pane_id = Some(pane.pid());
}
- self.apply_position_and_size_to_floating_pane(pane, position_and_size)
+ self.apply_position_and_size_to_floating_pane(pane, position_and_size);
+ Ok(())
}
pub fn apply_position_and_size_to_floating_pane(
&mut self,
diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs
index 2c0fed76..489c902e 100644
--- a/zellij-server/src/tab/mod.rs
+++ b/zellij-server/src/tab/mod.rs
@@ -691,7 +691,7 @@ impl Tab {
) -> Result<()> {
self.swap_layouts
.set_base_layout((layout.clone(), floating_panes_layout.clone()));
- let should_show_floating_panes = LayoutApplier::new(
+ if let Ok(should_show_floating_panes) = LayoutApplier::new(
&self.viewport,
&self.senders,
&self.sixel_image_store,
@@ -719,16 +719,19 @@ impl Tab {
new_floating_terminal_ids,
new_plugin_ids,
client_id,
- )?;
- #[allow(clippy::if_same_then_else)]
- if should_show_floating_panes && !self.floating_panes.panes_are_visible() {
- self.toggle_floating_panes(Some(client_id), None)?;
- } else if !should_show_floating_panes && self.floating_panes.panes_are_visible() {
- self.toggle_floating_panes(Some(client_id), None)?;
+ ) {
+ #[allow(clippy::if_same_then_else)]
+ if should_show_floating_panes && !self.floating_panes.panes_are_visible() {
+ self.toggle_floating_panes(Some(client_id), None)
+ .non_fatal();
+ } else if !should_show_floating_panes && self.floating_panes.panes_are_visible() {
+ self.toggle_floating_panes(Some(client_id), None)
+ .non_fatal();
+ }
+ self.tiled_panes.reapply_pane_frames();
+ self.is_pending = false;
+ self.apply_buffered_instructions().non_fatal();
}
- self.tiled_panes.reapply_pane_frames();
- self.is_pending = false;
- self.apply_buffered_instructions()?;
Ok(())
}
pub fn swap_layout_info(&self) -> (Option<String>, bool) {
@@ -771,7 +774,8 @@ impl Tab {
self.styled_underlines,
self.explicitly_disable_kitty_keyboard_protocol,
)
- .apply_floating_panes_layout_to_existing_panes(&layout_candidate)?;
+ .apply_floating_panes_layout_to_existing_panes(&layout_candidate)
+ .non_fatal();
}
self.set_force_render();
Ok(())
@@ -805,7 +809,8 @@ impl Tab {
self.styled_underlines,
self.explicitly_disable_kitty_keyboard_protocol,
)
- .apply_tiled_panes_layout_to_existing_panes(&layout_candidate)?;
+ .apply_tiled_panes_layout_to_existing_panes(&layout_candidate)
+ .non_fatal();
}
self.tiled_panes.reapply_pane_frames();
let display_area = *self.display_area.borrow();