diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 5cb2e8d931..26963fa2dd 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -1694,12 +1694,54 @@ impl AppContext { if let Some(invalidation) = invalidation { let appearance = cx.window.platform_window.appearance(); cx.invalidate(invalidation, appearance); - if cx.layout(refreshing).log_err().is_some() { + if let Some(old_parents) = cx.layout(refreshing).log_err() { updated_windows.insert(window_id); - // When the previously-focused view isn't rendered and - // there isn't any pending focus, focus the root view. if let Some(focused_view_id) = cx.focused_view_id() { + let old_ancestors = std::iter::successors( + Some(focused_view_id), + |&view_id| old_parents.get(&view_id).copied(), + ) + .collect::>(); + let new_ancestors = + cx.ancestors(focused_view_id).collect::>(); + + // Notify the old ancestors of the focused view when they don't contain it anymore. + for old_ancestor in old_ancestors.iter().copied() { + if !new_ancestors.contains(&old_ancestor) { + if let Some(mut view) = + cx.views.remove(&(window_id, old_ancestor)) + { + view.focus_out( + focused_view_id, + cx, + old_ancestor, + ); + cx.views + .insert((window_id, old_ancestor), view); + } + } + } + + // Notify the new ancestors of the focused view if they contain it now. + for new_ancestor in new_ancestors.iter().copied() { + if !old_ancestors.contains(&new_ancestor) { + if let Some(mut view) = + cx.views.remove(&(window_id, new_ancestor)) + { + view.focus_in( + focused_view_id, + cx, + new_ancestor, + ); + cx.views + .insert((window_id, new_ancestor), view); + } + } + } + + // When the previously-focused view isn't rendered and + // there isn't any pending focus, focus the root view. let root_view_id = cx.window.root_view().id(); if focused_view_id != root_view_id && !cx.window.parents.contains_key(&focused_view_id) diff --git a/crates/gpui/src/app/window.rs b/crates/gpui/src/app/window.rs index bd9bd6d2db..24a3686563 100644 --- a/crates/gpui/src/app/window.rs +++ b/crates/gpui/src/app/window.rs @@ -29,6 +29,7 @@ use sqlez::{ }; use std::{ any::TypeId, + mem, ops::{Deref, DerefMut, Range}, }; use util::ResultExt; @@ -890,7 +891,7 @@ impl<'a> WindowContext<'a> { Ok(element) } - pub(crate) fn layout(&mut self, refreshing: bool) -> Result<()> { + pub(crate) fn layout(&mut self, refreshing: bool) -> Result> { let window_size = self.window.platform_window.content_size(); let root_view_id = self.window.root_view().id(); let mut rendered_root = self.window.rendered_views.remove(&root_view_id).unwrap(); @@ -923,11 +924,11 @@ impl<'a> WindowContext<'a> { } } - self.window.parents = new_parents; + let old_parents = mem::replace(&mut self.window.parents, new_parents); self.window .rendered_views .insert(root_view_id, rendered_root); - Ok(()) + Ok(old_parents) } pub(crate) fn paint(&mut self) -> Result {