Add more view tracking (#24683)

Mikayla Maki created

This should fix a panic in `Window::current_view()`

Release Notes:

- N/A

Change summary

crates/gpui/src/view.rs   | 185 ++++++++++++++++++++--------------------
crates/gpui/src/window.rs |  15 ++
2 files changed, 103 insertions(+), 97 deletions(-)

Detailed changes

crates/gpui/src/view.rs 🔗

@@ -40,7 +40,9 @@ impl<V: Render> Element for Entity<V> {
         cx: &mut App,
     ) -> (LayoutId, Self::RequestLayoutState) {
         let mut element = self.update(cx, |view, cx| view.render(window, cx).into_any_element());
-        let layout_id = element.request_layout(window, cx);
+        let layout_id = window.with_rendered_view(self.entity_id(), |window| {
+            element.request_layout(window, cx)
+        });
         (layout_id, element)
     }
 
@@ -53,7 +55,7 @@ impl<V: Render> Element for Entity<V> {
         cx: &mut App,
     ) {
         window.set_view_id(self.entity_id());
-        element.prepaint(window, cx);
+        window.with_rendered_view(self.entity_id(), |window| element.prepaint(window, cx));
     }
 
     fn paint(
@@ -65,7 +67,7 @@ impl<V: Render> Element for Entity<V> {
         window: &mut Window,
         cx: &mut App,
     ) {
-        element.paint(window, cx);
+        window.with_rendered_view(self.entity_id(), |window| element.paint(window, cx));
     }
 }
 
@@ -150,18 +152,18 @@ impl Element for AnyView {
         window: &mut Window,
         cx: &mut App,
     ) -> (LayoutId, Self::RequestLayoutState) {
-        if let Some(style) = self.cached_style.as_ref() {
-            let mut root_style = Style::default();
-            root_style.refine(style);
-            let layout_id = window.request_layout(root_style, None, cx);
-            (layout_id, None)
-        } else {
-            window.with_rendered_view(self.entity_id(), |window| {
+        window.with_rendered_view(self.entity_id(), |window| {
+            if let Some(style) = self.cached_style.as_ref() {
+                let mut root_style = Style::default();
+                root_style.refine(style);
+                let layout_id = window.request_layout(root_style, None, cx);
+                (layout_id, None)
+            } else {
                 let mut element = (self.render)(self, window, cx);
                 let layout_id = element.request_layout(window, cx);
                 (layout_id, Some(element))
-            })
-        }
+            }
+        })
     }
 
     fn prepaint(
@@ -173,69 +175,66 @@ impl Element for AnyView {
         cx: &mut App,
     ) -> Option<AnyElement> {
         window.set_view_id(self.entity_id());
-        if self.cached_style.is_some() {
-            window.with_element_state::<AnyViewState, _>(
-                global_id.unwrap(),
-                |element_state, window| {
-                    let content_mask = window.content_mask();
-                    let text_style = window.text_style();
-
-                    if let Some(mut element_state) = element_state {
-                        if element_state.cache_key.bounds == bounds
-                            && element_state.cache_key.content_mask == content_mask
-                            && element_state.cache_key.text_style == text_style
-                            && !window.dirty_views.contains(&self.entity_id())
-                            && !window.refreshing
-                        {
-                            let prepaint_start = window.prepaint_index();
-                            window.reuse_prepaint(element_state.prepaint_range.clone());
-                            cx.entities
-                                .extend_accessed(&element_state.accessed_entities);
-                            let prepaint_end = window.prepaint_index();
-                            element_state.prepaint_range = prepaint_start..prepaint_end;
-
-                            return (None, element_state);
+        window.with_rendered_view(self.entity_id(), |window| {
+            if self.cached_style.is_some() {
+                window.with_element_state::<AnyViewState, _>(
+                    global_id.unwrap(),
+                    |element_state, window| {
+                        let content_mask = window.content_mask();
+                        let text_style = window.text_style();
+
+                        if let Some(mut element_state) = element_state {
+                            if element_state.cache_key.bounds == bounds
+                                && element_state.cache_key.content_mask == content_mask
+                                && element_state.cache_key.text_style == text_style
+                                && !window.dirty_views.contains(&self.entity_id())
+                                && !window.refreshing
+                            {
+                                let prepaint_start = window.prepaint_index();
+                                window.reuse_prepaint(element_state.prepaint_range.clone());
+                                cx.entities
+                                    .extend_accessed(&element_state.accessed_entities);
+                                let prepaint_end = window.prepaint_index();
+                                element_state.prepaint_range = prepaint_start..prepaint_end;
+
+                                return (None, element_state);
+                            }
                         }
-                    }
-
-                    let refreshing = mem::replace(&mut window.refreshing, true);
-                    let prepaint_start = window.prepaint_index();
-                    let (mut element, accessed_entities) =
-                        window.with_rendered_view(self.entity_id(), |window| {
-                            cx.detect_accessed_entities(|cx| {
-                                let mut element = (self.render)(self, window, cx);
-                                element.layout_as_root(bounds.size.into(), window, cx);
-                                element.prepaint_at(bounds.origin, window, cx);
-                                element
-                            })
+
+                        let refreshing = mem::replace(&mut window.refreshing, true);
+                        let prepaint_start = window.prepaint_index();
+                        let (mut element, accessed_entities) = cx.detect_accessed_entities(|cx| {
+                            let mut element = (self.render)(self, window, cx);
+                            element.layout_as_root(bounds.size.into(), window, cx);
+                            element.prepaint_at(bounds.origin, window, cx);
+                            element
                         });
 
-                    let prepaint_end = window.prepaint_index();
-                    window.refreshing = refreshing;
-
-                    (
-                        Some(element),
-                        AnyViewState {
-                            accessed_entities,
-                            prepaint_range: prepaint_start..prepaint_end,
-                            paint_range: PaintIndex::default()..PaintIndex::default(),
-                            cache_key: ViewCacheKey {
-                                bounds,
-                                content_mask,
-                                text_style,
+                        let prepaint_end = window.prepaint_index();
+                        window.refreshing = refreshing;
+
+                        (
+                            Some(element),
+                            AnyViewState {
+                                accessed_entities,
+                                prepaint_range: prepaint_start..prepaint_end,
+                                paint_range: PaintIndex::default()..PaintIndex::default(),
+                                cache_key: ViewCacheKey {
+                                    bounds,
+                                    content_mask,
+                                    text_style,
+                                },
                             },
-                        },
-                    )
-                },
-            )
-        } else {
-            let mut element = element.take().unwrap();
-            window.with_rendered_view(self.entity_id(), |window| {
+                        )
+                    },
+                )
+            } else {
+                let mut element = element.take().unwrap();
                 element.prepaint(window, cx);
-            });
 
-            Some(element)
-        }
+                Some(element)
+            }
+        })
     }
 
     fn paint(
@@ -247,33 +246,33 @@ impl Element for AnyView {
         window: &mut Window,
         cx: &mut App,
     ) {
-        if self.cached_style.is_some() {
-            window.with_element_state::<AnyViewState, _>(
-                global_id.unwrap(),
-                |element_state, window| {
-                    let mut element_state = element_state.unwrap();
+        window.with_rendered_view(self.entity_id(), |window| {
+            if self.cached_style.is_some() {
+                window.with_element_state::<AnyViewState, _>(
+                    global_id.unwrap(),
+                    |element_state, window| {
+                        let mut element_state = element_state.unwrap();
 
-                    let paint_start = window.paint_index();
+                        let paint_start = window.paint_index();
 
-                    if let Some(element) = element {
-                        let refreshing = mem::replace(&mut window.refreshing, true);
-                        window.with_rendered_view(self.entity_id(), |window| {
+                        if let Some(element) = element {
+                            let refreshing = mem::replace(&mut window.refreshing, true);
                             element.paint(window, cx);
-                        });
-                        window.refreshing = refreshing;
-                    } else {
-                        window.reuse_paint(element_state.paint_range.clone());
-                    }
-
-                    let paint_end = window.paint_index();
-                    element_state.paint_range = paint_start..paint_end;
-
-                    ((), element_state)
-                },
-            )
-        } else {
-            element.as_mut().unwrap().paint(window, cx);
-        }
+                            window.refreshing = refreshing;
+                        } else {
+                            window.reuse_paint(element_state.paint_range.clone());
+                        }
+
+                        let paint_end = window.paint_index();
+                        element_state.paint_range = paint_start..paint_end;
+
+                        ((), element_state)
+                    },
+                )
+            } else {
+                element.as_mut().unwrap().paint(window, cx);
+            }
+        });
     }
 }
 

crates/gpui/src/window.rs 🔗

@@ -477,6 +477,7 @@ pub(crate) struct TooltipRequest {
 }
 
 pub(crate) struct DeferredDraw {
+    current_view: EntityId,
     priority: usize,
     parent_node: DispatchNodeId,
     element_id_stack: SmallVec<[ElementId; 32]>,
@@ -1750,9 +1751,11 @@ impl Window {
 
             let prepaint_start = self.prepaint_index();
             if let Some(element) = deferred_draw.element.as_mut() {
-                self.with_absolute_element_offset(deferred_draw.absolute_offset, |window| {
-                    element.prepaint(window, cx)
-                });
+                self.with_rendered_view(deferred_draw.current_view, |window| {
+                    window.with_absolute_element_offset(deferred_draw.absolute_offset, |window| {
+                        element.prepaint(window, cx)
+                    });
+                })
             } else {
                 self.reuse_prepaint(deferred_draw.prepaint_range.clone());
             }
@@ -1783,7 +1786,9 @@ impl Window {
 
             let paint_start = self.paint_index();
             if let Some(element) = deferred_draw.element.as_mut() {
-                element.paint(self, cx);
+                self.with_rendered_view(deferred_draw.current_view, |window| {
+                    element.paint(window, cx);
+                })
             } else {
                 self.reuse_paint(deferred_draw.paint_range.clone());
             }
@@ -1841,6 +1846,7 @@ impl Window {
                 [range.start.deferred_draws_index..range.end.deferred_draws_index]
                 .iter()
                 .map(|deferred_draw| DeferredDraw {
+                    current_view: deferred_draw.current_view,
                     parent_node: reused_subtree.refresh_node_id(deferred_draw.parent_node),
                     element_id_stack: deferred_draw.element_id_stack.clone(),
                     text_style_stack: deferred_draw.text_style_stack.clone(),
@@ -2247,6 +2253,7 @@ impl Window {
         self.invalidator.debug_assert_prepaint();
         let parent_node = self.next_frame.dispatch_tree.active_node_id().unwrap();
         self.next_frame.deferred_draws.push(DeferredDraw {
+            current_view: self.current_view(),
             parent_node,
             element_id_stack: self.element_id_stack.clone(),
             text_style_stack: self.text_style_stack.clone(),