Track some more panels and be more explicit

This commit is contained in:
MrSubidubi 2026-10-10 23:43:11 +02:00
parent ef09a56a7c
commit 13fdecd4b7
6 changed files with 86 additions and 67 deletions

View file

@ -59,7 +59,7 @@ use util::ResultExt;
use variable_list::VariableList;
use workspace::{
ActivePaneDecorator, DraggedTab, Item, ItemHandle, ItemNavigation, Member, Pane, PaneGroup,
SplitDirection, Workspace, item::TabContentParams, move_item, pane::Event,
PaneNavigation, SplitDirection, Workspace, item::TabContentParams, move_item, pane::Event,
};
static PROCESS_ID_PLACEHOLDER: LazyLock<String> =
@ -654,6 +654,7 @@ pub(crate) fn new_debugger_pane(
Some(can_drop_predicate),
NoAction.boxed_clone(),
true,
PaneNavigation::Disabled,
window,
cx,
);
@ -689,7 +690,6 @@ pub(crate) fn new_debugger_pane(
}
})));
pane.set_can_toggle_zoom(false, cx);
pane.display_nav_history_buttons(None);
pane.set_should_display_tab_bar(|_, _| true);
pane.set_render_tab_bar_buttons(cx, |_, _, _| (None, None));
pane.set_render_tab_bar(cx, {

View file

@ -30,8 +30,8 @@ use workspace::{
ActivateNextPane, ActivatePane, ActivatePaneDown, ActivatePaneLeft, ActivatePaneRight,
ActivatePaneUp, ActivatePreviousPane, DraggedTab, ItemId, MoveItemToPane,
MoveItemToPaneInDirection, MovePaneDown, MovePaneLeft, MovePaneRight, MovePaneUp, Pane,
PaneGroup, SplitDirection, SplitDown, SplitLeft, SplitMode, SplitRight, SplitUp, SwapPaneDown,
SwapPaneLeft, SwapPaneRight, SwapPaneUp, ToggleZoom, Workspace,
PaneGroup, PaneNavigation, SplitDirection, SplitDown, SplitLeft, SplitMode, SplitRight,
SplitUp, SwapPaneDown, SwapPaneLeft, SwapPaneRight, SwapPaneUp, ToggleZoom, Workspace,
dock::{DockPosition, Panel, PanelEvent, PanelHandle},
item::{ItemNavigation, SerializableItem},
move_active_item, pane,
@ -1320,12 +1320,11 @@ pub fn new_terminal_pane(
None,
workspace::NewTerminal::default().boxed_clone(),
false,
PaneNavigation::Disabled,
window,
cx,
);
pane.set_zoomed(zoomed, cx);
pane.set_can_navigate(false, cx);
pane.display_nav_history_buttons(None);
pane.set_should_display_tab_bar(|_, _| true);
pane.set_zoom_out_on_close(false);
@ -1464,7 +1463,7 @@ impl workspace::Item for FailedToSpawnTerminal {
type Event = ();
fn navigation(&self, _: &Entity<Self>, _: &App) -> ItemNavigation {
ItemNavigation::Excluded
ItemNavigation::Visits
}
fn tab_content_text(&self, _detail: usize, _cx: &App) -> SharedString {

View file

@ -1547,7 +1547,7 @@ impl Item for TerminalView {
type Event = ItemEvent;
fn navigation(&self, _: &Entity<Self>, _: &App) -> ItemNavigation {
ItemNavigation::Excluded
ItemNavigation::Visits
}
fn tab_tooltip_content(&self, cx: &App) -> Option<TabTooltipContent> {
@ -2383,6 +2383,48 @@ mod tests {
});
}
#[gpui::test]
async fn center_terminal_is_a_navigation_target(cx: &mut TestAppContext) {
let (project, workspace, window_handle) = init_test_with_window(cx).await;
let (pane, _first_terminal, first_terminal_view) =
add_display_only_terminal(&project, window_handle, true, false, cx);
let (_, _second_terminal, second_terminal_view) =
add_display_only_terminal(&project, window_handle, true, false, cx);
let cx = &mut VisualTestContext::from_window(window_handle.into(), cx);
cx.run_until_parked();
workspace
.update_in(cx, |workspace, window, cx| {
workspace.go_back(pane.downgrade(), window, cx)
})
.await
.unwrap();
cx.run_until_parked();
let active_item_id =
pane.read_with(cx, |pane, _| pane.active_item().map(|item| item.item_id()));
assert_eq!(
active_item_id,
Some(first_terminal_view.entity_id()),
"Back should return to the previously active center terminal"
);
workspace
.update_in(cx, |workspace, window, cx| {
workspace.go_forward(pane.downgrade(), window, cx)
})
.await
.unwrap();
cx.run_until_parked();
let active_item_id =
pane.read_with(cx, |pane, _| pane.active_item().map(|item| item.item_id()));
assert_eq!(
active_item_id,
Some(second_terminal_view.entity_id()),
"Forward should return to the second terminal"
);
}
#[gpui::test]
async fn edit_menu_copy_and_paste_are_available_when_terminal_is_focused(
cx: &mut TestAppContext,

View file

@ -437,9 +437,7 @@ pub struct Pane {
/// This is set to true if a user scroll has occurred more recently than a system scroll
/// We want to suppress certain system scrolls when the user has intentionally scrolled
suppress_scroll: bool,
/// Is None if navigation buttons are permanently turned off (and should not react to setting changes).
/// Otherwise, when `display_nav_history_buttons` is Some, it determines whether nav buttons should be displayed.
display_nav_history_buttons: Option<bool>,
navigation: PaneNavigation,
double_click_dispatch_action: Box<dyn Action>,
save_modals_spawned: HashSet<EntityId>,
close_pane_if_empty: bool,
@ -485,6 +483,17 @@ struct NavHistoryState {
preview_item_id: Option<EntityId>,
}
/// Whether a pane supports going back and forward between its items.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum PaneNavigation {
/// Items are recorded in the navigation history, and the navigation buttons are shown
/// according to the tab bar settings.
Enabled,
/// Nothing is recorded, and neither navigation buttons nor actions are available, e.g. for
/// the terminal panel.
Disabled,
}
#[derive(Debug, Default, Copy, Clone)]
pub(crate) enum NavigationMode {
#[default]
@ -569,6 +578,7 @@ impl Pane {
can_drop_predicate: Option<Arc<dyn Fn(&dyn Any, &mut Window, &mut App) -> bool + 'static>>,
double_click_dispatch_action: Box<dyn Action>,
use_max_tabs: bool,
navigation: PaneNavigation,
window: &mut Window,
cx: &mut Context<Self>,
) -> Self {
@ -628,9 +638,7 @@ impl Pane {
render_tab_bar_buttons: Rc::new(default_render_tab_bar_buttons),
render_tab_bar: Rc::new(Self::render_tab_bar),
show_tab_bar_buttons: TabBarSettings::get_global(cx).show_tab_bar_buttons,
display_nav_history_buttons: Some(
TabBarSettings::get_global(cx).show_nav_history_buttons,
),
navigation,
_subscriptions: subscriptions,
double_click_dispatch_action,
save_modals_spawned: HashSet::default(),
@ -809,10 +817,6 @@ impl Pane {
fn settings_changed(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let tab_bar_settings = TabBarSettings::get_global(cx);
if let Some(display_nav_history_buttons) = self.display_nav_history_buttons.as_mut() {
*display_nav_history_buttons = tab_bar_settings.show_nav_history_buttons;
}
self.show_tab_bar_buttons = tab_bar_settings.show_tab_bar_buttons;
if !PreviewTabsSettings::get_global(cx).enabled {
@ -877,13 +881,6 @@ impl Pane {
cx.notify();
}
pub fn set_can_navigate(&mut self, can_navigate: bool, cx: &mut Context<Self>) {
self.toolbar.update(cx, |toolbar, cx| {
toolbar.set_can_navigate(can_navigate, cx);
});
cx.notify();
}
pub fn set_render_tab_bar<F>(&mut self, cx: &mut Context<Self>, render: F)
where
F: 'static + Fn(&mut Pane, &mut Window, &mut Context<Pane>) -> AnyElement,
@ -914,6 +911,9 @@ impl Pane {
/// Records the item's current location, called when it gets deactivated or closed.
pub(crate) fn record_navigation(&self, item: &dyn ItemHandle, cx: &mut App) {
if self.navigation == PaneNavigation::Disabled {
return;
}
if let Some(location) = item.navigation(cx).capture_location(cx) {
self.nav_history_for_item(item).push(location, cx);
}
@ -3595,7 +3595,8 @@ impl Pane {
) -> TabBar {
tab_bar
.when(
self.display_nav_history_buttons.unwrap_or_default(),
self.navigation == PaneNavigation::Enabled
&& TabBarSettings::get_global(cx).show_nav_history_buttons,
|tab_bar| {
tab_bar
.start_child(navigate_backward)
@ -4264,10 +4265,6 @@ impl Pane {
.log_err();
}
pub fn display_nav_history_buttons(&mut self, display: Option<bool>) {
self.display_nav_history_buttons = display;
}
fn pinned_item_ids(&self) -> Vec<EntityId> {
self.items
.iter()
@ -4492,8 +4489,10 @@ impl Render for Pane {
.on_action(cx.listener(Pane::toggle_zoom))
.on_action(cx.listener(Pane::zoom_in))
.on_action(cx.listener(Pane::zoom_out))
.on_action(cx.listener(Self::navigate_backward))
.on_action(cx.listener(Self::navigate_forward))
.when(self.navigation == PaneNavigation::Enabled, |pane| {
pane.on_action(cx.listener(Self::navigate_backward))
.on_action(cx.listener(Self::navigate_forward))
})
.on_action(cx.listener(Self::go_to_older_tag))
.on_action(cx.listener(Self::go_to_newer_tag))
.on_action(
@ -4716,34 +4715,18 @@ impl Render for Pane {
}),
)
})
.on_mouse_down(
MouseButton::Navigate(NavigationDirection::Back),
cx.listener(|pane, _, window, cx| {
if let Some(workspace) = pane.workspace.upgrade() {
let pane = cx.entity().downgrade();
window.defer(cx, move |window, cx| {
workspace.update(cx, |workspace, cx| {
workspace.go_back(pane, window, cx).detach_and_log_err(cx)
})
})
}
}),
)
.on_mouse_down(
MouseButton::Navigate(NavigationDirection::Forward),
cx.listener(|pane, _, window, cx| {
if let Some(workspace) = pane.workspace.upgrade() {
let pane = cx.entity().downgrade();
window.defer(cx, move |window, cx| {
workspace.update(cx, |workspace, cx| {
workspace
.go_forward(pane, window, cx)
.detach_and_log_err(cx)
})
})
}
}),
)
.when(self.navigation == PaneNavigation::Enabled, |pane| {
pane.on_mouse_down(
MouseButton::Navigate(NavigationDirection::Back),
cx.listener(|pane, _, window, cx| pane.navigate_backward(&GoBack, window, cx)),
)
.on_mouse_down(
MouseButton::Navigate(NavigationDirection::Forward),
cx.listener(|pane, _, window, cx| {
pane.navigate_forward(&GoForward, window, cx)
}),
)
})
}
}

View file

@ -64,7 +64,6 @@ pub enum ToolbarItemLocation {
pub struct Toolbar {
active_item: Option<Box<dyn ItemHandle>>,
hidden: bool,
can_navigate: bool,
items: Vec<(Box<dyn ToolbarItemViewHandle>, ToolbarItemLocation)>,
}
@ -172,15 +171,9 @@ impl Toolbar {
active_item: None,
items: Default::default(),
hidden: false,
can_navigate: true,
}
}
pub fn set_can_navigate(&mut self, can_navigate: bool, cx: &mut Context<Self>) {
self.can_navigate = can_navigate;
cx.notify();
}
pub fn add_item<T>(&mut self, item: Entity<T>, window: &mut Window, cx: &mut Context<Self>)
where
T: 'static + ToolbarItemView,

View file

@ -1909,6 +1909,7 @@ impl Workspace {
None,
NewFile.boxed_clone(),
true,
PaneNavigation::Enabled,
window,
cx,
);
@ -4911,6 +4912,7 @@ impl Workspace {
None,
NewFile.boxed_clone(),
true,
PaneNavigation::Enabled,
window,
cx,
);