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 { 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 { if self.panes_are_visible() { - let layers = self + let layers: Vec = 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 { + 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 { 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, 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> { 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, 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, 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, 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();