workspace: Add setting to make dock resize apply to all panels (#30551)

Aaron Ruan and Mikayla Maki created

Re: #19015
Close #12667

When dragging a dock’s resize handle, only the active panel grows or
shrinks. This patch introduces an opt-in behaviour that lets users
resize every panel hosted by that dock at once.

Release Notes:

- Added new `resize_all_panels_in_dock` setting to optionally resize
every panel in a dock together.

Co-authored-by: Mikayla Maki <mikayla@zed.dev>

Change summary

assets/settings/default.json               |  3 ++
crates/workspace/src/dock.rs               | 13 +++++++++++
crates/workspace/src/workspace.rs          | 27 +++++++++++++++++++++--
crates/workspace/src/workspace_settings.rs |  6 +++++
4 files changed, 46 insertions(+), 3 deletions(-)

Detailed changes

assets/settings/default.json 🔗

@@ -533,6 +533,9 @@
       "function": false
     }
   },
+  // Whether to resize all the panels in a dock when resizing the dock.
+  // Can be a combination of "left", "right" and "bottom".
+  "resize_all_panels_in_dock": ["left"],
   "project_panel": {
     // Whether to show the project panel button in the status bar
     "button": true,

crates/workspace/src/dock.rs 🔗

@@ -686,6 +686,19 @@ impl Dock {
         }
     }
 
+    pub fn resize_all_panels(
+        &mut self,
+        size: Option<Pixels>,
+        window: &mut Window,
+        cx: &mut Context<Self>,
+    ) {
+        for entry in &mut self.panel_entries {
+            let size = size.map(|size| size.max(RESIZE_HANDLE_SIZE).round());
+            entry.panel.set_size(size, window, cx);
+        }
+        cx.notify();
+    }
+
     pub fn toggle_action(&self) -> Box<dyn Action> {
         match self.position {
             DockPosition::Left => crate::ToggleLeftDock.boxed_clone(),

crates/workspace/src/workspace.rs 🔗

@@ -6240,7 +6240,14 @@ fn resize_bottom_dock(
     let size =
         new_size.min(workspace.bounds.bottom() - RESIZE_HANDLE_SIZE - workspace.bounds.top());
     workspace.bottom_dock.update(cx, |bottom_dock, cx| {
-        bottom_dock.resize_active_panel(Some(size), window, cx);
+        if WorkspaceSettings::get_global(cx)
+            .resize_all_panels_in_dock
+            .contains(&DockPosition::Bottom)
+        {
+            bottom_dock.resize_all_panels(Some(size), window, cx);
+        } else {
+            bottom_dock.resize_active_panel(Some(size), window, cx);
+        }
     });
 }
 
@@ -6252,7 +6259,14 @@ fn resize_right_dock(
 ) {
     let size = new_size.max(workspace.bounds.left() - RESIZE_HANDLE_SIZE);
     workspace.right_dock.update(cx, |right_dock, cx| {
-        right_dock.resize_active_panel(Some(size), window, cx);
+        if WorkspaceSettings::get_global(cx)
+            .resize_all_panels_in_dock
+            .contains(&DockPosition::Right)
+        {
+            right_dock.resize_all_panels(Some(size), window, cx);
+        } else {
+            right_dock.resize_active_panel(Some(size), window, cx);
+        }
     });
 }
 
@@ -6265,7 +6279,14 @@ fn resize_left_dock(
     let size = new_size.min(workspace.bounds.right() - RESIZE_HANDLE_SIZE);
 
     workspace.left_dock.update(cx, |left_dock, cx| {
-        left_dock.resize_active_panel(Some(size), window, cx);
+        if WorkspaceSettings::get_global(cx)
+            .resize_all_panels_in_dock
+            .contains(&DockPosition::Left)
+        {
+            left_dock.resize_all_panels(Some(size), window, cx);
+        } else {
+            left_dock.resize_active_panel(Some(size), window, cx);
+        }
     });
 }
 

crates/workspace/src/workspace_settings.rs 🔗

@@ -1,5 +1,6 @@
 use std::num::NonZeroUsize;
 
+use crate::DockPosition;
 use anyhow::Result;
 use collections::HashMap;
 use gpui::App;
@@ -26,6 +27,7 @@ pub struct WorkspaceSettings {
     pub max_tabs: Option<NonZeroUsize>,
     pub when_closing_with_no_tabs: CloseWindowWhenNoItems,
     pub on_last_window_closed: OnLastWindowClosed,
+    pub resize_all_panels_in_dock: Vec<DockPosition>,
     pub close_on_file_delete: bool,
 }
 
@@ -192,6 +194,10 @@ pub struct WorkspaceSettingsContent {
     ///
     /// Default: auto (nothing on macOS, "app quit" otherwise)
     pub on_last_window_closed: Option<OnLastWindowClosed>,
+    /// Whether to resize all the panels in a dock when resizing the dock.
+    ///
+    /// Default: ["left"]
+    pub resize_all_panels_in_dock: Option<Vec<DockPosition>>,
     /// Whether to automatically close files that have been deleted on disk.
     ///
     /// Default: false