Rely on root getting re-focused when panel isn't rendered

Antonio Scandurra created

This achieves two things:

- When a panel like `TerminalPanel` closes its last tab, the focus
is returned to the root view (the `Workspace`)
- When a panel is moved from a dock to another, it will get rendered
in another spot but the focus will be kept on the panel

This also ensures the focus is not lost when a panel is moved from
a dock to another because that view

Change summary

crates/workspace/src/dock.rs      | 11 ++-------
crates/workspace/src/workspace.rs | 35 +++++++++++---------------------
2 files changed, 15 insertions(+), 31 deletions(-)

Detailed changes

crates/workspace/src/dock.rs 🔗

@@ -81,10 +81,6 @@ impl From<&dyn PanelHandle> for AnyViewHandle {
     }
 }
 
-pub enum Event {
-    Close,
-}
-
 pub struct Dock {
     position: DockPosition,
     panels: Vec<PanelEntry>,
@@ -182,7 +178,6 @@ impl Dock {
     }
 
     pub fn toggle_open(&mut self, cx: &mut ViewContext<Self>) {
-        if self.is_open {}
         self.is_open = !self.is_open;
         cx.notify();
     }
@@ -200,7 +195,7 @@ impl Dock {
                         this.activate_item(ix, cx);
                     }
                 } else if view.read(cx).should_close_on_event(event, cx) {
-                    cx.emit(Event::Close);
+                    this.set_open(false, cx);
                 }
             }),
         ];
@@ -226,7 +221,7 @@ impl Dock {
         {
             if panel_ix == self.active_item_ix {
                 self.active_item_ix = 0;
-                cx.emit(Event::Close);
+                self.set_open(false, cx);
             }
             self.panels.remove(panel_ix);
             cx.notify();
@@ -261,7 +256,7 @@ impl Dock {
 }
 
 impl Entity for Dock {
-    type Event = Event;
+    type Event = ();
 }
 
 impl View for Dock {

crates/workspace/src/workspace.rs 🔗

@@ -612,9 +612,18 @@ impl Workspace {
                     .spawn(DB.set_window_bounds(workspace_id, bounds, display))
                     .detach_and_log_err(cx);
             }),
-            Self::register_dock(&left_dock, cx),
-            Self::register_dock(&bottom_dock, cx),
-            Self::register_dock(&right_dock, cx),
+            cx.observe(&left_dock, |this, _, cx| {
+                this.serialize_workspace(cx);
+                cx.notify();
+            }),
+            cx.observe(&bottom_dock, |this, _, cx| {
+                this.serialize_workspace(cx);
+                cx.notify();
+            }),
+            cx.observe(&right_dock, |this, _, cx| {
+                this.serialize_workspace(cx);
+                cx.notify();
+            }),
         ];
 
         let mut this = Workspace {
@@ -1359,26 +1368,6 @@ impl Workspace {
         }
     }
 
-    fn register_dock(dock: &ViewHandle<Dock>, cx: &mut ViewContext<Self>) -> Subscription {
-        cx.subscribe(dock, Self::handle_dock_event)
-    }
-
-    fn handle_dock_event(
-        &mut self,
-        dock: ViewHandle<Dock>,
-        event: &dock::Event,
-        cx: &mut ViewContext<Self>,
-    ) {
-        match event {
-            dock::Event::Close => {
-                dock.update(cx, |dock, cx| dock.set_open(false, cx));
-                self.serialize_workspace(cx);
-                cx.focus_self();
-                cx.notify();
-            }
-        }
-    }
-
     pub fn toggle_dock(&mut self, dock_side: DockPosition, cx: &mut ViewContext<Self>) {
         let dock = match dock_side {
             DockPosition::Left => &mut self.left_dock,