workspace: Add command to reset pane sizes (#59046)

## Summary

Exposes the existing recursive pane-size reset as a command-palette
action, so it can be invoked outside of vim mode.

The center pane grid's sizes can already be evened out by
double-clicking a divider, or via `vim::ResetPaneSizes` (`ctrl-w =`)
when vim mode is on, but there is no general action for it — so users
not in vim mode have no discoverable way to undo a drifted split layout
in one step.

## How it works

`workspace::ResetPaneSizes` (palette: "workspace: reset pane sizes")
calls the existing `Workspace::reset_pane_sizes`, which resets every
`PaneAxis` in the center pane group to equal flexes, recursing into
nested splits. The split structure is preserved — no panes are added,
removed, or rearranged, only their sizes are equalized. This is the same
path the vim `ctrl-w =` binding and the divider double-click already
use.

## Out of scope

- Docks (left/right/bottom panels) — they keep their existing `Reset
Active Dock Size` / `Reset Open Docks Size` actions.
- The terminal panel's internal splits — it is a separate panel, not
part of the center pane group.
- No default keybinding (palette-only); vim users keep `ctrl-w =`.

## Testing

Added `test_reset_pane_sizes`: builds a nested split (a horizontal axis
of three panes whose last child is a vertical split), skews every axis's
flexes, dispatches the action, and asserts every axis returns to uniform
sizes.

Release Notes:

- Added a `workspace: reset pane sizes` command that equalizes the sizes
of all panes in the center group
This commit is contained in:
Ânderson Q. authored and GitHub committed 2026-06-11 04:03:48 +00:00
1 parent 03a8544040
commit dde7c1c07f
1 file changed
+75
+75
View File
@@ -303,6 +303,8 @@ actions!(
ResetActiveDockSize,
/// Resets all open docks to their default sizes.
ResetOpenDocksSize,
/// Resets all panes in the center group to equal sizes, preserving the split layout.
ResetPaneSizes,
/// Reloads the application
Reload,
/// Formats and saves the current file, regardless of the format_on_save setting.
@@ -7651,6 +7653,11 @@ impl Workspace {
}
},
))
.on_action(cx.listener(
|workspace: &mut Workspace, _: &ResetPaneSizes, _window, cx| {
workspace.reset_pane_sizes(cx);
},
))
.on_action(cx.listener(
|workspace: &mut Workspace, act: &IncreaseActiveDockSize, window, cx| {
adjust_active_dock_size_by_px(
@@ -12771,6 +12778,74 @@ mod tests {
});
}
#[gpui::test]
async fn test_reset_pane_sizes(cx: &mut gpui::TestAppContext) {
init_test(cx);
let fs = FakeFs::new(cx.executor());
let project = Project::test(fs, [], cx).await;
let (multi_workspace, cx) =
cx.add_window_view(|window, cx| MultiWorkspace::test_new(project, window, cx));
let workspace = multi_workspace.read_with(cx, |mw, _| mw.workspace().clone());
// A horizontal split of three panes whose last child is itself a vertical
// split, so equalizing has to recurse into the nested axis.
workspace.update_in(cx, |workspace, window, cx| {
let item = cx.new(|cx| {
TestItem::new(cx).with_project_items(&[TestProjectItem::new(1, "1.txt", cx)])
});
workspace.add_item_to_active_pane(Box::new(item), None, true, window, cx);
workspace.split_pane(
workspace.active_pane().clone(),
SplitDirection::Right,
window,
cx,
);
workspace.split_pane(
workspace.active_pane().clone(),
SplitDirection::Right,
window,
cx,
);
workspace.split_pane(
workspace.active_pane().clone(),
SplitDirection::Down,
window,
cx,
);
});
let nested_axis = |workspace: &Workspace| {
let Member::Axis(top) = &workspace.center.root else {
panic!("expected the center to be a split axis");
};
let nested = top
.members
.iter()
.find_map(|member| match member {
Member::Axis(axis) => Some(axis.clone()),
Member::Pane(_) => None,
})
.expect("expected a nested split axis");
(top.clone(), nested)
};
// Skew every axis away from uniform sizes.
workspace.update(cx, |workspace, _| {
let (top, nested) = nested_axis(workspace);
*top.flexes.lock() = vec![1.6, 0.7, 0.7];
*nested.flexes.lock() = vec![1.3, 0.7];
});
cx.run_until_parked();
cx.dispatch_action(ResetPaneSizes);
workspace.update(cx, |workspace, _| {
let (top, nested) = nested_axis(workspace);
assert_eq!(*top.flexes.lock(), vec![1.0; top.members.len()]);
assert_eq!(*nested.flexes.lock(), vec![1.0; nested.members.len()]);
});
}
#[gpui::test]
async fn test_toggle_docks_and_panels(cx: &mut gpui::TestAppContext) {
init_test(cx);