From e48daa92c0edff0d51454f5f49f4b723807c6e3f Mon Sep 17 00:00:00 2001 From: Cole Miller Date: Mon, 19 May 2025 17:45:37 +0200 Subject: [PATCH] debugger: Remember focused item (#30722) Release Notes: - Debugger Beta: the `debug panel: toggle focus` action now preserves the debug panel's focused item. --- crates/debugger_ui/src/debugger_panel.rs | 31 ++++++++++++++++++++--- crates/debugger_ui/src/debugger_ui.rs | 11 +++++++- crates/debugger_ui/src/session/running.rs | 21 ++++++++------- crates/workspace/src/workspace.rs | 13 +++++++--- 4 files changed, 57 insertions(+), 19 deletions(-) diff --git a/crates/debugger_ui/src/debugger_panel.rs b/crates/debugger_ui/src/debugger_panel.rs index 9106f6e1e8b4090aec2917fc7c898f5d292ddb7f..1edba0e3f5ec0f4e5c33b3c736233edace6c4d01 100644 --- a/crates/debugger_ui/src/debugger_panel.rs +++ b/crates/debugger_ui/src/debugger_panel.rs @@ -69,15 +69,20 @@ pub struct DebugPanel { } impl DebugPanel { - pub fn new(workspace: &Workspace, cx: &mut Context) -> Entity { + pub fn new( + workspace: &Workspace, + _window: &mut Window, + cx: &mut Context, + ) -> Entity { cx.new(|cx| { let project = workspace.project().clone(); + let focus_handle = cx.focus_handle(); let debug_panel = Self { size: px(300.), sessions: vec![], active_session: None, - focus_handle: cx.focus_handle(), + focus_handle, project, workspace: workspace.weak_handle(), context_menu: None, @@ -88,6 +93,24 @@ impl DebugPanel { }) } + pub(crate) fn focus_active_item(&mut self, window: &mut Window, cx: &mut Context) { + let Some(session) = self.active_session.clone() else { + return; + }; + let Some(active_pane) = session + .read(cx) + .running_state() + .read(cx) + .active_pane() + .cloned() + else { + return; + }; + active_pane.update(cx, |pane, cx| { + pane.focus_active_item(window, cx); + }); + } + pub(crate) fn sessions(&self) -> Vec> { self.sessions.clone() } @@ -182,8 +205,8 @@ impl DebugPanel { cx: &mut AsyncWindowContext, ) -> Task>> { cx.spawn(async move |cx| { - workspace.update(cx, |workspace, cx| { - let debug_panel = DebugPanel::new(workspace, cx); + workspace.update_in(cx, |workspace, window, cx| { + let debug_panel = DebugPanel::new(workspace, window, cx); workspace.register_action(|workspace, _: &ClearAllBreakpoints, _, cx| { workspace.project().read(cx).breakpoint_store().update( diff --git a/crates/debugger_ui/src/debugger_ui.rs b/crates/debugger_ui/src/debugger_ui.rs index c8bdcb53dc687e3ae02cd87da4a9a581f164ca34..6df3390bf54f8d06e4d3cbd370cde52e0a217ca5 100644 --- a/crates/debugger_ui/src/debugger_ui.rs +++ b/crates/debugger_ui/src/debugger_ui.rs @@ -60,7 +60,16 @@ pub fn init(cx: &mut App) { cx.when_flag_enabled::(window, |workspace, _, _| { workspace .register_action(|workspace, _: &ToggleFocus, window, cx| { - workspace.toggle_panel_focus::(window, cx); + let did_focus_panel = workspace.toggle_panel_focus::(window, cx); + if !did_focus_panel { + return; + }; + let Some(panel) = workspace.panel::(cx) else { + return; + }; + panel.update(cx, |panel, cx| { + panel.focus_active_item(window, cx); + }) }) .register_action(|workspace, _: &Pause, _, cx| { if let Some(debug_panel) = workspace.panel::(cx) { diff --git a/crates/debugger_ui/src/session/running.rs b/crates/debugger_ui/src/session/running.rs index b85eb5b58e119ad69235cc0a5a7545555f67d45e..3b473a3b9294e3e289156d9eccb32af7a908ea23 100644 --- a/crates/debugger_ui/src/session/running.rs +++ b/crates/debugger_ui/src/session/running.rs @@ -81,6 +81,10 @@ impl RunningState { pub(crate) fn thread_id(&self) -> Option { self.thread_id } + + pub(crate) fn active_pane(&self) -> Option<&Entity> { + self.active_pane.as_ref() + } } impl Render for RunningState { @@ -502,20 +506,15 @@ impl DebugTerminal { impl gpui::Render for DebugTerminal { fn render(&mut self, _window: &mut Window, _: &mut Context) -> impl IntoElement { - if let Some(terminal) = self.terminal.clone() { - terminal.into_any_element() - } else { - div().track_focus(&self.focus_handle).into_any_element() - } + div() + .size_full() + .track_focus(&self.focus_handle) + .children(self.terminal.clone()) } } impl Focusable for DebugTerminal { - fn focus_handle(&self, cx: &App) -> FocusHandle { - if let Some(terminal) = self.terminal.as_ref() { - return terminal.focus_handle(cx); - } else { - self.focus_handle.clone() - } + fn focus_handle(&self, _cx: &App) -> FocusHandle { + self.focus_handle.clone() } } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index b442560be654e53ca721a5dd7721746d2014fd86..069e750593328666f244d1b733e027a4ba053411 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -2776,10 +2776,17 @@ impl Workspace { /// Focus the panel of the given type if it isn't already focused. If it is /// already focused, then transfer focus back to the workspace center. - pub fn toggle_panel_focus(&mut self, window: &mut Window, cx: &mut Context) { + pub fn toggle_panel_focus( + &mut self, + window: &mut Window, + cx: &mut Context, + ) -> bool { + let mut did_focus_panel = false; self.focus_or_unfocus_panel::(window, cx, |panel, window, cx| { - !panel.panel_focus_handle(cx).contains_focused(window, cx) + did_focus_panel = !panel.panel_focus_handle(cx).contains_focused(window, cx); + did_focus_panel }); + did_focus_panel } pub fn activate_panel_for_proto_id( @@ -2813,7 +2820,7 @@ impl Workspace { &mut self, window: &mut Window, cx: &mut Context, - should_focus: impl Fn(&dyn PanelHandle, &mut Window, &mut Context) -> bool, + mut should_focus: impl FnMut(&dyn PanelHandle, &mut Window, &mut Context) -> bool, ) -> Option> { let mut result_panel = None; let mut serialize = false;