diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index af7da8e837..39d0fb0430 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -41,8 +41,8 @@ use git::diff_hunk_to_display; use gpui::{ action, actions, div, point, prelude::*, px, relative, rems, size, uniform_list, AnyElement, AppContext, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Component, Context, - EventEmitter, FocusHandle, FontFeatures, FontStyle, FontWeight, HighlightStyle, Hsla, - InputHandler, KeyContext, Model, MouseButton, ParentComponent, Pixels, Render, Styled, + EventEmitter, FocusHandle, FocusableView, FontFeatures, FontStyle, FontWeight, HighlightStyle, + Hsla, InputHandler, KeyContext, Model, MouseButton, ParentComponent, Pixels, Render, Styled, Subscription, Task, TextStyle, UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WindowContext, }; @@ -9367,6 +9367,12 @@ pub struct EditorReleased(pub WeakView); // impl EventEmitter for Editor {} +impl FocusableView for Editor { + fn focus_handle(&self, cx: &AppContext) -> FocusHandle { + self.focus_handle.clone() + } +} + impl Render for Editor { type Element = EditorElement; diff --git a/crates/editor2/src/items.rs b/crates/editor2/src/items.rs index 09bb2f1182..8efac65ed4 100644 --- a/crates/editor2/src/items.rs +++ b/crates/editor2/src/items.rs @@ -527,10 +527,6 @@ fn deserialize_anchor(buffer: &MultiBufferSnapshot, anchor: proto::EditorAnchor) } impl Item for Editor { - fn focus_handle(&self) -> FocusHandle { - self.focus_handle.clone() - } - fn navigate(&mut self, data: Box, cx: &mut ViewContext) -> bool { todo!(); // if let Ok(data) = data.downcast::() { diff --git a/crates/gpui2/src/app/async_context.rs b/crates/gpui2/src/app/async_context.rs index 24510c18da..5b7f8ce590 100644 --- a/crates/gpui2/src/app/async_context.rs +++ b/crates/gpui2/src/app/async_context.rs @@ -1,7 +1,7 @@ use crate::{ - AnyView, AnyWindowHandle, AppCell, AppContext, BackgroundExecutor, Context, ForegroundExecutor, - Model, ModelContext, Render, Result, Task, View, ViewContext, VisualContext, WindowContext, - WindowHandle, + AnyView, AnyWindowHandle, AppCell, AppContext, BackgroundExecutor, Context, FocusableView, + ForegroundExecutor, Model, ModelContext, Render, Result, Task, View, ViewContext, + VisualContext, WindowContext, WindowHandle, }; use anyhow::{anyhow, Context as _}; use derive_more::{Deref, DerefMut}; @@ -307,4 +307,13 @@ impl VisualContext for AsyncWindowContext { self.window .update(self, |_, cx| cx.replace_root_view(build_view)) } + + fn focus_view(&mut self, view: &View) -> Self::Result<()> + where + V: FocusableView, + { + self.window.update(self, |_, cx| { + view.read(cx).focus_handle(cx).clone().focus(cx); + }) + } } diff --git a/crates/gpui2/src/app/entity_map.rs b/crates/gpui2/src/app/entity_map.rs index 1e01921cd4..4a3cca040b 100644 --- a/crates/gpui2/src/app/entity_map.rs +++ b/crates/gpui2/src/app/entity_map.rs @@ -68,6 +68,7 @@ impl EntityMap { } /// Move an entity to the stack. + #[track_caller] pub fn lease<'a, T>(&mut self, model: &'a Model) -> Lease<'a, T> { self.assert_valid_context(model); let entity = Some( diff --git a/crates/gpui2/src/app/test_context.rs b/crates/gpui2/src/app/test_context.rs index 7eb10c675f..6a80f6aec0 100644 --- a/crates/gpui2/src/app/test_context.rs +++ b/crates/gpui2/src/app/test_context.rs @@ -560,6 +560,14 @@ impl<'a> VisualContext for VisualTestContext<'a> { .update(self.cx, |_, cx| cx.replace_root_view(build_view)) .unwrap() } + + fn focus_view(&mut self, view: &View) -> Self::Result<()> { + self.window + .update(self.cx, |_, cx| { + view.read(cx).focus_handle(cx).clone().focus(cx) + }) + .unwrap() + } } impl AnyWindowHandle { diff --git a/crates/gpui2/src/gpui2.rs b/crates/gpui2/src/gpui2.rs index 51390d6be2..3b98b846c4 100644 --- a/crates/gpui2/src/gpui2.rs +++ b/crates/gpui2/src/gpui2.rs @@ -135,6 +135,10 @@ pub trait VisualContext: Context { ) -> Self::Result> where V: Render; + + fn focus_view(&mut self, view: &View) -> Self::Result<()> + where + V: FocusableView; } pub trait Entity: Sealed { diff --git a/crates/gpui2/src/view.rs b/crates/gpui2/src/view.rs index 3edaa900b0..c9c85a7f59 100644 --- a/crates/gpui2/src/view.rs +++ b/crates/gpui2/src/view.rs @@ -1,7 +1,7 @@ use crate::{ private::Sealed, AnyBox, AnyElement, AnyModel, AnyWeakModel, AppContext, AvailableSpace, - Bounds, Component, Element, ElementId, Entity, EntityId, Flatten, LayoutId, Model, Pixels, - Size, ViewContext, VisualContext, WeakModel, WindowContext, + Bounds, Component, Element, ElementId, Entity, EntityId, Flatten, FocusHandle, FocusableView, + LayoutId, Model, Pixels, Size, ViewContext, VisualContext, WeakModel, WindowContext, }; use anyhow::{Context, Result}; use std::{ @@ -73,6 +73,13 @@ impl View { component: Some(component), } } + + pub fn focus_handle(&self, cx: &AppContext) -> FocusHandle + where + V: FocusableView, + { + self.read(cx).focus_handle(cx) + } } impl Clone for View { diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 0563c107c0..af713bb508 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -185,6 +185,10 @@ impl Drop for FocusHandle { } } +pub trait FocusableView: Render { + fn focus_handle(&self, cx: &AppContext) -> FocusHandle; +} + // Holds the state for a specific window. pub struct Window { pub(crate) handle: AnyWindowHandle, @@ -1550,6 +1554,12 @@ impl VisualContext for WindowContext<'_> { self.window.root_view = Some(view.clone().into()); view } + + fn focus_view(&mut self, view: &View) -> Self::Result<()> { + self.update_view(view, |view, cx| { + view.focus_handle(cx).clone().focus(cx); + }) + } } impl<'a> std::ops::Deref for WindowContext<'a> { @@ -2213,9 +2223,7 @@ impl<'a, V: 'static> ViewContext<'a, V> { .set_input_handler(Box::new(input_handler)); } } -} -impl ViewContext<'_, V> { pub fn emit(&mut self, event: Evt) where Evt: 'static, @@ -2228,6 +2236,13 @@ impl ViewContext<'_, V> { event: Box::new(event), }); } + + pub fn focus_self(&mut self) + where + V: FocusableView, + { + self.defer(|view, cx| view.focus_handle(cx).focus(cx)) + } } impl Context for ViewContext<'_, V> { @@ -2303,6 +2318,10 @@ impl VisualContext for ViewContext<'_, V> { { self.window_cx.replace_root_view(build_view) } + + fn focus_view(&mut self, view: &View) -> Self::Result<()> { + self.window_cx.focus_view(view) + } } impl<'a, V> std::ops::Deref for ViewContext<'a, V> { diff --git a/crates/project_panel2/src/project_panel.rs b/crates/project_panel2/src/project_panel.rs index 79a0f344ae..df7ce966db 100644 --- a/crates/project_panel2/src/project_panel.rs +++ b/crates/project_panel2/src/project_panel.rs @@ -9,10 +9,10 @@ use file_associations::FileAssociations; use anyhow::{anyhow, Result}; use gpui::{ actions, div, px, uniform_list, Action, AppContext, AssetSource, AsyncWindowContext, - ClipboardItem, Component, Div, EventEmitter, FocusHandle, Focusable, InteractiveComponent, - Model, MouseButton, ParentComponent, Pixels, Point, PromptLevel, Render, Stateful, - StatefulInteractiveComponent, Styled, Task, UniformListScrollHandle, View, ViewContext, - VisualContext as _, WeakView, WindowContext, + ClipboardItem, Component, Div, EventEmitter, FocusHandle, Focusable, FocusableView, + InteractiveComponent, Model, MouseButton, ParentComponent, Pixels, Point, PromptLevel, Render, + Stateful, StatefulInteractiveComponent, Styled, Task, UniformListScrollHandle, View, + ViewContext, VisualContext as _, WeakView, WindowContext, }; use menu::{Confirm, SelectNext, SelectPrev}; use project::{ @@ -1524,25 +1524,19 @@ impl workspace::dock::Panel for ProjectPanel { ("Project Panel".into(), Some(Box::new(ToggleFocus))) } - // fn should_change_position_on_event(event: &Self::Event) -> bool { - // matches!(event, Event::DockPositionChanged) - // } - fn has_focus(&self, _: &WindowContext) -> bool { self.has_focus } - fn persistent_name(&self) -> &'static str { + fn persistent_name() -> &'static str { "Project Panel" } +} - fn focus_handle(&self, _cx: &WindowContext) -> FocusHandle { +impl FocusableView for ProjectPanel { + fn focus_handle(&self, _cx: &AppContext) -> FocusHandle { self.focus_handle.clone() } - - // fn is_focus_event(event: &Self::Event) -> bool { - // matches!(event, Event::Focus) - // } } impl ClipboardEntry { diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index 455148391b..78cfd6c921 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -1,8 +1,8 @@ use crate::{status_bar::StatusItemView, Axis, Workspace}; use gpui::{ div, px, Action, AnyView, AppContext, Component, Div, Entity, EntityId, EventEmitter, - FocusHandle, ParentComponent, Render, Styled, Subscription, View, ViewContext, WeakView, - WindowContext, + FocusHandle, FocusableView, ParentComponent, Render, Styled, Subscription, View, ViewContext, + WeakView, WindowContext, }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -17,8 +17,8 @@ pub enum PanelEvent { Focus, } -pub trait Panel: Render + EventEmitter { - fn persistent_name(&self) -> &'static str; +pub trait Panel: FocusableView + EventEmitter { + fn persistent_name() -> &'static str; fn position(&self, cx: &WindowContext) -> DockPosition; fn position_is_valid(&self, position: DockPosition) -> bool; fn set_position(&mut self, position: DockPosition, cx: &mut ViewContext); @@ -35,12 +35,11 @@ pub trait Panel: Render + EventEmitter { fn set_zoomed(&mut self, _zoomed: bool, _cx: &mut ViewContext) {} fn set_active(&mut self, _active: bool, _cx: &mut ViewContext) {} fn has_focus(&self, cx: &WindowContext) -> bool; - fn focus_handle(&self, cx: &WindowContext) -> FocusHandle; } pub trait PanelHandle: Send + Sync { fn id(&self) -> EntityId; - fn persistent_name(&self, cx: &WindowContext) -> &'static str; + fn persistent_name(&self) -> &'static str; fn position(&self, cx: &WindowContext) -> DockPosition; fn position_is_valid(&self, position: DockPosition, cx: &WindowContext) -> bool; fn set_position(&self, position: DockPosition, cx: &mut WindowContext); @@ -53,7 +52,7 @@ pub trait PanelHandle: Send + Sync { fn icon_tooltip(&self, cx: &WindowContext) -> (String, Option>); fn icon_label(&self, cx: &WindowContext) -> Option; fn has_focus(&self, cx: &WindowContext) -> bool; - fn focus_handle(&self, cx: &WindowContext) -> FocusHandle; + fn focus_handle(&self, cx: &AppContext) -> FocusHandle; fn to_any(&self) -> AnyView; } @@ -65,8 +64,8 @@ where self.entity_id() } - fn persistent_name(&self, cx: &WindowContext) -> &'static str { - self.read(cx).persistent_name() + fn persistent_name(&self) -> &'static str { + T::persistent_name() } fn position(&self, cx: &WindowContext) -> DockPosition { @@ -121,7 +120,7 @@ where self.clone().into() } - fn focus_handle(&self, cx: &WindowContext) -> FocusHandle { + fn focus_handle(&self, cx: &AppContext) -> FocusHandle { self.read(cx).focus_handle(cx).clone() } } @@ -139,6 +138,14 @@ pub struct Dock { active_panel_index: usize, } +impl FocusableView for Dock { + fn focus_handle(&self, cx: &AppContext) -> FocusHandle { + self.panel_entries[self.active_panel_index] + .panel + .focus_handle(cx) + } +} + #[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, PartialEq)] #[serde(rename_all = "lowercase")] pub enum DockPosition { @@ -220,12 +227,14 @@ impl Dock { // .position(|entry| entry.panel.as_any().is::()) // } - pub fn panel_index_for_ui_name(&self, _ui_name: &str, _cx: &AppContext) -> Option { - todo!() - // self.panel_entries.iter().position(|entry| { - // let panel = entry.panel.as_any(); - // cx.view_ui_name(panel.window(), panel.id()) == Some(ui_name) - // }) + pub fn panel_index_for_persistent_name( + &self, + ui_name: &str, + _cx: &AppContext, + ) -> Option { + self.panel_entries + .iter() + .position(|entry| entry.panel.persistent_name() == ui_name) } pub fn active_panel_index(&self) -> usize { @@ -647,7 +656,7 @@ impl Render for PanelButtons { div().children( dock.panel_entries .iter() - .map(|panel| panel.panel.persistent_name(cx)), + .map(|panel| panel.panel.persistent_name()), ) } } @@ -698,7 +707,7 @@ pub mod test { } impl Panel for TestPanel { - fn persistent_name(&self) -> &'static str { + fn persistent_name() -> &'static str { "TestPanel" } @@ -746,8 +755,10 @@ pub mod test { fn has_focus(&self, _cx: &WindowContext) -> bool { self.has_focus } + } - fn focus_handle(&self, cx: &WindowContext) -> FocusHandle { + impl FocusableView for TestPanel { + fn focus_handle(&self, cx: &AppContext) -> FocusHandle { unimplemented!() } } diff --git a/crates/workspace2/src/item.rs b/crates/workspace2/src/item.rs index 2b750a9861..7252e7135a 100644 --- a/crates/workspace2/src/item.rs +++ b/crates/workspace2/src/item.rs @@ -12,8 +12,9 @@ use client2::{ Client, }; use gpui::{ - AnyElement, AnyView, AppContext, Entity, EntityId, EventEmitter, FocusHandle, HighlightStyle, - Model, Pixels, Point, Render, SharedString, Task, View, ViewContext, WeakView, WindowContext, + AnyElement, AnyView, AppContext, Entity, EntityId, EventEmitter, FocusHandle, FocusableView, + HighlightStyle, Model, Pixels, Point, SharedString, Task, View, ViewContext, WeakView, + WindowContext, }; use project2::{Project, ProjectEntryId, ProjectPath}; use schemars::JsonSchema; @@ -91,8 +92,7 @@ pub struct BreadcrumbText { pub highlights: Option, HighlightStyle)>>, } -pub trait Item: Render + EventEmitter { - fn focus_handle(&self) -> FocusHandle; +pub trait Item: FocusableView + EventEmitter { fn deactivated(&mut self, _: &mut ViewContext) {} fn workspace_deactivated(&mut self, _: &mut ViewContext) {} fn navigate(&mut self, _: Box, _: &mut ViewContext) -> bool { @@ -286,7 +286,7 @@ impl dyn ItemHandle { impl ItemHandle for View { fn focus_handle(&self, cx: &WindowContext) -> FocusHandle { - self.read(cx).focus_handle() + self.focus_handle(cx) } fn subscribe_to_item_events( diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 6399fe2121..df0282d21f 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -8,8 +8,8 @@ use anyhow::Result; use collections::{HashMap, HashSet, VecDeque}; use gpui::{ actions, prelude::*, register_action, AppContext, AsyncWindowContext, Component, Div, EntityId, - EventEmitter, FocusHandle, Focusable, Model, PromptLevel, Render, Task, View, ViewContext, - VisualContext, WeakView, WindowContext, + EventEmitter, FocusHandle, Focusable, FocusableView, Model, PromptLevel, Render, Task, View, + ViewContext, VisualContext, WeakView, WindowContext, }; use parking_lot::Mutex; use project2::{Project, ProjectEntryId, ProjectPath}; @@ -1899,6 +1899,12 @@ impl Pane { } } +impl FocusableView for Pane { + fn focus_handle(&self, _cx: &AppContext) -> FocusHandle { + self.focus_handle.clone() + } +} + impl Render for Pane { type Element = Focusable>; diff --git a/crates/workspace2/src/pane_group.rs b/crates/workspace2/src/pane_group.rs index 682bde5b0a..d46757ff9f 100644 --- a/crates/workspace2/src/pane_group.rs +++ b/crates/workspace2/src/pane_group.rs @@ -148,6 +148,10 @@ impl PaneGroup { self.root.collect_panes(&mut panes); panes } + + pub(crate) fn first_pane(&self) -> View { + self.root.first_pane() + } } #[derive(Clone, PartialEq)] @@ -181,6 +185,13 @@ impl Member { } } + fn first_pane(&self) -> View { + match self { + Member::Axis(axis) => axis.members[0].first_pane(), + Member::Pane(pane) => pane.clone(), + } + } + pub fn render( &self, project: &Model, diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 6c2d0c0ede..fbf179ad51 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -38,9 +38,9 @@ use futures::{ use gpui::{ actions, div, point, prelude::*, rems, size, Action, AnyModel, AnyView, AnyWeakView, AppContext, AsyncAppContext, AsyncWindowContext, Bounds, Component, Div, Entity, EntityId, - EventEmitter, GlobalPixels, KeyContext, Model, ModelContext, ParentComponent, Point, Render, - Size, Styled, Subscription, Task, View, ViewContext, WeakView, WindowBounds, WindowContext, - WindowHandle, WindowOptions, + EventEmitter, FocusHandle, FocusableView, GlobalPixels, KeyContext, Model, ModelContext, + ParentComponent, Point, Render, Size, Styled, Subscription, Task, View, ViewContext, WeakView, + WindowBounds, WindowContext, WindowHandle, WindowOptions, }; use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem}; use itertools::Itertools; @@ -685,7 +685,7 @@ impl Workspace { fn new_local( abs_paths: Vec, app_state: Arc, - _requesting_window: Option>, + requesting_window: Option>, cx: &mut AppContext, ) -> Task< anyhow::Result<( @@ -703,7 +703,8 @@ impl Workspace { ); cx.spawn(|mut cx| async move { - let serialized_workspace: Option = None; //persistence::DB.workspace_for_roots(&abs_paths.as_slice()); + let serialized_workspace: Option = + persistence::DB.workspace_for_roots(&abs_paths.as_slice()); let paths_to_open = Arc::new(abs_paths); @@ -732,15 +733,14 @@ impl Workspace { DB.next_id().await.unwrap_or(0) }; - // todo!() - let window = /*if let Some(window) = requesting_window { + let window = if let Some(window) = requesting_window { cx.update_window(window.into(), |old_workspace, cx| { cx.replace_root_view(|cx| { Workspace::new(workspace_id, project_handle.clone(), app_state.clone(), cx) }); - }); + })?; window - } else */ { + } else { let window_bounds_override = window_bounds_env_override(&cx); let (bounds, display) = if let Some(bounds) = window_bounds_override { (Some(bounds), None) @@ -754,12 +754,13 @@ impl Workspace { // Stored bounds are relative to the containing display. // So convert back to global coordinates if that screen still exists if let WindowBounds::Fixed(mut window_bounds) = bounds { - let screen = - cx.update(|cx| - cx.displays() - .into_iter() - .find(|display| display.uuid().ok() == Some(serialized_display)) - ).ok()??; + let screen = cx + .update(|cx| { + cx.displays().into_iter().find(|display| { + display.uuid().ok() == Some(serialized_display) + }) + }) + .ok()??; let screen_bounds = screen.bounds(); window_bounds.origin.x += screen_bounds.origin.x; window_bounds.origin.y += screen_bounds.origin.y; @@ -807,12 +808,7 @@ impl Workspace { notify_if_database_failed(window, &mut cx); let opened_items = window .update(&mut cx, |_workspace, cx| { - open_items( - serialized_workspace, - project_paths, - app_state, - cx, - ) + open_items(serialized_workspace, project_paths, app_state, cx) })? .await .unwrap_or_default(); @@ -3043,13 +3039,15 @@ impl Workspace { cx.notify(); } - // fn schedule_serialize(&mut self, cx: &mut ViewContext) { - // self._schedule_serialize = Some(cx.spawn(|this, cx| async move { - // cx.background().timer(Duration::from_millis(100)).await; - // this.read_with(&cx, |this, cx| this.serialize_workspace(cx)) - // .ok(); - // })); - // } + fn schedule_serialize(&mut self, cx: &mut ViewContext) { + self._schedule_serialize = Some(cx.spawn(|this, mut cx| async move { + cx.background_executor() + .timer(Duration::from_millis(100)) + .await; + this.update(&mut cx, |this, cx| this.serialize_workspace(cx)) + .log_err(); + })); + } fn serialize_workspace(&self, cx: &mut ViewContext) { fn serialize_pane_handle(pane_handle: &View, cx: &WindowContext) -> SerializedPane { @@ -3105,7 +3103,7 @@ impl Workspace { let left_visible = left_dock.is_open(); let left_active_panel = left_dock .visible_panel() - .and_then(|panel| Some(panel.persistent_name(cx).to_string())); + .and_then(|panel| Some(panel.persistent_name().to_string())); let left_dock_zoom = left_dock .visible_panel() .map(|panel| panel.is_zoomed(cx)) @@ -3115,7 +3113,7 @@ impl Workspace { let right_visible = right_dock.is_open(); let right_active_panel = right_dock .visible_panel() - .and_then(|panel| Some(panel.persistent_name(cx).to_string())); + .and_then(|panel| Some(panel.persistent_name().to_string())); let right_dock_zoom = right_dock .visible_panel() .map(|panel| panel.is_zoomed(cx)) @@ -3125,7 +3123,7 @@ impl Workspace { let bottom_visible = bottom_dock.is_open(); let bottom_active_panel = bottom_dock .visible_panel() - .and_then(|panel| Some(panel.persistent_name(cx).to_string())); + .and_then(|panel| Some(panel.persistent_name().to_string())); let bottom_dock_zoom = bottom_dock .visible_panel() .map(|panel| panel.is_zoomed(cx)) @@ -3231,45 +3229,34 @@ impl Workspace { // Swap workspace center group workspace.center = PaneGroup::with_root(center_group); - - // Change the focus to the workspace first so that we retrigger focus in on the pane. - // todo!() - // cx.focus_self(); - // if let Some(active_pane) = active_pane { - // cx.focus(&active_pane); - // } else { - // cx.focus(workspace.panes.last().unwrap()); - // } - } else { - // todo!() - // let old_center_handle = old_center_pane.and_then(|weak| weak.upgrade()); - // if let Some(old_center_handle) = old_center_handle { - // cx.focus(&old_center_handle) - // } else { - // cx.focus_self() - // } + workspace.last_active_center_pane = active_pane.as_ref().map(|p| p.downgrade()); + if let Some(active_pane) = active_pane { + workspace.active_pane = active_pane; + cx.focus_self(); + } else { + workspace.active_pane = workspace.center.first_pane().clone(); + } } let docks = serialized_workspace.docks; workspace.left_dock.update(cx, |dock, cx| { dock.set_open(docks.left.visible, cx); if let Some(active_panel) = docks.left.active_panel { - if let Some(ix) = dock.panel_index_for_ui_name(&active_panel, cx) { + if let Some(ix) = dock.panel_index_for_persistent_name(&active_panel, cx) { dock.activate_panel(ix, cx); } } dock.active_panel() .map(|panel| panel.set_zoomed(docks.left.zoom, cx)); if docks.left.visible && docks.left.zoom { - // todo!() - // cx.focus_self() + cx.focus_self() } }); // TODO: I think the bug is that setting zoom or active undoes the bottom zoom or something workspace.right_dock.update(cx, |dock, cx| { dock.set_open(docks.right.visible, cx); if let Some(active_panel) = docks.right.active_panel { - if let Some(ix) = dock.panel_index_for_ui_name(&active_panel, cx) { + if let Some(ix) = dock.panel_index_for_persistent_name(&active_panel, cx) { dock.activate_panel(ix, cx); } } @@ -3277,14 +3264,13 @@ impl Workspace { .map(|panel| panel.set_zoomed(docks.right.zoom, cx)); if docks.right.visible && docks.right.zoom { - // todo!() - // cx.focus_self() + cx.focus_self() } }); workspace.bottom_dock.update(cx, |dock, cx| { dock.set_open(docks.bottom.visible, cx); if let Some(active_panel) = docks.bottom.active_panel { - if let Some(ix) = dock.panel_index_for_ui_name(&active_panel, cx) { + if let Some(ix) = dock.panel_index_for_persistent_name(&active_panel, cx) { dock.activate_panel(ix, cx); } } @@ -3293,8 +3279,7 @@ impl Workspace { .map(|panel| panel.set_zoomed(docks.bottom.zoom, cx)); if docks.bottom.visible && docks.bottom.zoom { - // todo!() - // cx.focus_self() + cx.focus_self() } }); @@ -3699,6 +3684,12 @@ fn notify_if_database_failed(workspace: WindowHandle, cx: &mut AsyncA impl EventEmitter for Workspace {} +impl FocusableView for Workspace { + fn focus_handle(&self, cx: &AppContext) -> FocusHandle { + self.active_pane.focus_handle(cx) + } +} + impl Render for Workspace { type Element = Div;