debugger: Improve focus states (#29469)

Closes #ISSUE

Release Notes:

- N/A *or* Added/Fixed/Improved ...
This commit is contained in:
Piotr Osiewicz 2025-04-26 15:02:07 +02:00 committed by GitHub
parent 3fdbc3090d
commit 1e47dfce79
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 34 additions and 13 deletions

View file

@ -54,7 +54,7 @@ pub struct RunningState {
loaded_sources_list: Entity<LoadedSourceList>, loaded_sources_list: Entity<LoadedSourceList>,
pub debug_terminal: Entity<DebugTerminal>, pub debug_terminal: Entity<DebugTerminal>,
module_list: Entity<module_list::ModuleList>, module_list: Entity<module_list::ModuleList>,
_console: Entity<Console>, console: Entity<Console>,
breakpoint_list: Entity<BreakpointList>, breakpoint_list: Entity<BreakpointList>,
panes: PaneGroup, panes: PaneGroup,
active_pane: Option<Entity<Pane>>, active_pane: Option<Entity<Pane>>,
@ -171,9 +171,10 @@ impl Render for SubView {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement { fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
v_flex() v_flex()
.size_full() .size_full()
// Add border uncoditionally to prevent layout shifts on focus changes.
.border_1()
.when(self.pane_focus_handle.contains_focused(window, cx), |el| { .when(self.pane_focus_handle.contains_focused(window, cx), |el| {
// TODO better way of showing focus? el.border_color(cx.theme().colors().pane_focused_border)
el.border_1().border_color(gpui::red())
}) })
.child(self.inner.clone()) .child(self.inner.clone())
} }
@ -315,12 +316,12 @@ pub(crate) fn new_debugger_pane(
.justify_between() .justify_between()
.bg(cx.theme().colors().tab_bar_background) .bg(cx.theme().colors().tab_bar_background)
.border_b_1() .border_b_1()
.px_2()
.border_color(cx.theme().colors().border) .border_color(cx.theme().colors().border)
.track_focus(&focus_handle) .track_focus(&focus_handle)
.child( .child(
h_flex() h_flex()
.w_full() .w_full()
.px_2()
.gap_1() .gap_1()
.h(Tab::container_height(cx)) .h(Tab::container_height(cx))
.drag_over::<DraggedTab>(|bar, _, _, cx| { .drag_over::<DraggedTab>(|bar, _, _, cx| {
@ -336,6 +337,7 @@ pub(crate) fn new_debugger_pane(
let selected = active_pane_item let selected = active_pane_item
.as_ref() .as_ref()
.map_or(false, |active| active.item_id() == item.item_id()); .map_or(false, |active| active.item_id() == item.item_id());
let deemphasized = !pane.has_focus(window, cx);
let item_ = item.boxed_clone(); let item_ = item.boxed_clone();
div() div()
.id(SharedString::from(format!( .id(SharedString::from(format!(
@ -346,10 +348,17 @@ pub(crate) fn new_debugger_pane(
.rounded_md() .rounded_md()
.cursor_pointer() .cursor_pointer()
.map(|this| { .map(|this| {
let theme = cx.theme();
if selected { if selected {
this.bg(cx.theme().colors().tab_active_background) let color = theme.colors().tab_active_background;
let color = if deemphasized {
color.opacity(0.5)
} else {
color
};
this.bg(color)
} else { } else {
let hover_color = cx.theme().colors().element_hover; let hover_color = theme.colors().element_hover;
this.hover(|style| style.bg(hover_color)) this.hover(|style| style.bg(hover_color))
} }
}) })
@ -362,6 +371,7 @@ pub(crate) fn new_debugger_pane(
.child(item.tab_content( .child(item.tab_content(
TabContentParams { TabContentParams {
selected, selected,
deemphasized,
..Default::default() ..Default::default()
}, },
window, window,
@ -395,7 +405,7 @@ pub(crate) fn new_debugger_pane(
IconName::Maximize IconName::Maximize
}, },
) )
.icon_size(IconSize::Small) .icon_size(IconSize::XSmall)
.on_click(cx.listener(move |pane, _, window, cx| { .on_click(cx.listener(move |pane, _, window, cx| {
pane.toggle_zoom(&workspace::ToggleZoom, window, cx); pane.toggle_zoom(&workspace::ToggleZoom, window, cx);
})) }))
@ -585,7 +595,7 @@ impl RunningState {
panes, panes,
active_pane: None, active_pane: None,
module_list, module_list,
_console: console, console,
breakpoint_list, breakpoint_list,
loaded_sources_list: loaded_source_list, loaded_sources_list: loaded_source_list,
pane_close_subscriptions, pane_close_subscriptions,
@ -629,11 +639,11 @@ impl RunningState {
) -> Box<dyn ItemHandle> { ) -> Box<dyn ItemHandle> {
match item_kind { match item_kind {
DebuggerPaneItem::Console => { DebuggerPaneItem::Console => {
let weak_console = self._console.clone().downgrade(); let weak_console = self.console.clone().downgrade();
Box::new(SubView::new( Box::new(SubView::new(
self._console.focus_handle(cx), self.console.focus_handle(cx),
self._console.clone().into(), self.console.clone().into(),
item_kind, item_kind,
Some(Box::new(move |cx| { Some(Box::new(move |cx| {
weak_console weak_console
@ -862,7 +872,7 @@ impl RunningState {
#[cfg(test)] #[cfg(test)]
pub fn console(&self) -> &Entity<Console> { pub fn console(&self) -> &Entity<Console> {
&self._console &self.console
} }
#[cfg(test)] #[cfg(test)]

View file

@ -395,6 +395,7 @@ impl PickerDelegate for TabSwitcherDelegate {
detail: Some(tab_match.detail), detail: Some(tab_match.detail),
selected: true, selected: true,
preview: tab_match.preview, preview: tab_match.preview,
deemphasized: false,
}; };
let label = tab_match.item.tab_content(params, window, cx); let label = tab_match.item.tab_content(params, window, cx);

View file

@ -214,12 +214,20 @@ pub struct TabContentParams {
pub detail: Option<usize>, pub detail: Option<usize>,
pub selected: bool, pub selected: bool,
pub preview: bool, pub preview: bool,
/// Tab content should be deemphasized when active pane does not have focus.
pub deemphasized: bool,
} }
impl TabContentParams { impl TabContentParams {
/// Returns the text color to be used for the tab content. /// Returns the text color to be used for the tab content.
pub fn text_color(&self) -> Color { pub fn text_color(&self) -> Color {
if self.selected { if self.deemphasized {
if self.selected {
Color::Muted
} else {
Color::Hidden
}
} else if self.selected {
Color::Default Color::Default
} else { } else {
Color::Muted Color::Muted

View file

@ -2147,6 +2147,7 @@ impl Pane {
detail: Some(detail), detail: Some(detail),
selected: is_active, selected: is_active,
preview: is_preview, preview: is_preview,
deemphasized: !self.has_focus(window, cx),
}, },
window, window,
cx, cx,
@ -3687,6 +3688,7 @@ impl Render for DraggedTab {
detail: Some(self.detail), detail: Some(self.detail),
selected: false, selected: false,
preview: false, preview: false,
deemphasized: false,
}, },
window, window,
cx, cx,