diff --git a/crates/debugger_ui/src/debugger_panel.rs b/crates/debugger_ui/src/debugger_panel.rs index fce81d49e6551739175536f1c678c58d951388e0..d686206ab06ee50506c2d79a1c3c9026fa09a56a 100644 --- a/crates/debugger_ui/src/debugger_panel.rs +++ b/crates/debugger_ui/src/debugger_panel.rs @@ -542,6 +542,8 @@ impl DebugPanel { project::debugger::session::ThreadStatus::Exited, ); let capabilities = running_state.read(cx).capabilities(cx); + let supports_detach = + running_state.read(cx).session().read(cx).is_attached(); this.map(|this| { if thread_status == ThreadStatus::Running { this.child( @@ -730,27 +732,39 @@ impl DebugPanel { } }), ) - .child( - IconButton::new("debug-disconnect", IconName::DebugDetach) - .icon_size(IconSize::XSmall) - .on_click(window.listener_for( - &running_state, - |this, _, _, cx| { - this.detach_client(cx); - }, - )) - .tooltip({ - let focus_handle = focus_handle.clone(); - move |window, cx| { - Tooltip::for_action_in( - "Detach", - &Detach, - &focus_handle, - window, - cx, - ) - } - }), + .when( + supports_detach, + |div| { + div.child( + IconButton::new( + "debug-disconnect", + IconName::DebugDetach, + ) + .disabled( + thread_status != ThreadStatus::Stopped + && thread_status != ThreadStatus::Running, + ) + .icon_size(IconSize::XSmall) + .on_click(window.listener_for( + &running_state, + |this, _, _, cx| { + this.detach_client(cx); + }, + )) + .tooltip({ + let focus_handle = focus_handle.clone(); + move |window, cx| { + Tooltip::for_action_in( + "Detach", + &Detach, + &focus_handle, + window, + cx, + ) + } + }), + ) + }, ) }, ), diff --git a/crates/debugger_ui/src/debugger_ui.rs b/crates/debugger_ui/src/debugger_ui.rs index 6f8624e2a86166ba1ae56807045e78e760542773..f3909b6a63f7602a51b7b1831cf464d020f14c94 100644 --- a/crates/debugger_ui/src/debugger_ui.rs +++ b/crates/debugger_ui/src/debugger_ui.rs @@ -113,6 +113,7 @@ pub fn init(cx: &mut App) { let caps = running_state.capabilities(cx); let supports_restart = caps.supports_restart_request.unwrap_or_default(); let supports_step_back = caps.supports_step_back.unwrap_or_default(); + let supports_detach = running_state.session().read(cx).is_attached(); let status = running_state.thread_status(cx); let active_item = active_item.downgrade(); @@ -195,6 +196,14 @@ pub fn init(cx: &mut App) { }, )) }) + .when(supports_detach, |div| { + let active_item = active_item.clone(); + div.on_action(move |_: &Detach, _, cx| { + active_item + .update(cx, |item, cx| item.detach_client(cx)) + .ok(); + }) + }) .when(supports_restart, |div| { let active_item = active_item.clone(); div.on_action(move |_: &Restart, _, cx| { diff --git a/crates/project/src/debugger/session.rs b/crates/project/src/debugger/session.rs index 05c83195ed7fa77462b243d08058b7a99c4d4850..f448a28f23af907e803c3a2d902f62dbbbd30ad0 100644 --- a/crates/project/src/debugger/session.rs +++ b/crates/project/src/debugger/session.rs @@ -26,6 +26,7 @@ use dap::{ use dap::{ ExceptionBreakpointsFilter, ExceptionFilterOptions, OutputEvent, OutputEventCategory, RunInTerminalRequestArguments, StackFramePresentationHint, StartDebuggingRequestArguments, + StartDebuggingRequestArgumentsRequest, }; use futures::SinkExt; use futures::channel::{mpsc, oneshot}; @@ -2217,10 +2218,17 @@ impl Session { self.locations.get(&reference).cloned() } + pub fn is_attached(&self) -> bool { + let Mode::Running(local_mode) = &self.mode else { + return false; + }; + local_mode.binary.request_args.request == StartDebuggingRequestArgumentsRequest::Attach + } + pub fn disconnect_client(&mut self, cx: &mut Context) { let command = DisconnectCommand { restart: Some(false), - terminate_debuggee: Some(true), + terminate_debuggee: Some(false), suspend_debuggee: Some(false), };