Merge branch 'main' into collab_ui2

Conrad Irwin created

Change summary

crates/editor2/src/element.rs             |  14 --
crates/gpui2/src/element.rs               |  88 +++-----------------
crates/gpui2/src/elements/div.rs          | 105 ++++++------------------
crates/gpui2/src/elements/img.rs          |  13 --
crates/gpui2/src/elements/svg.rs          |  13 --
crates/gpui2/src/elements/text.rs         |  16 --
crates/gpui2/src/elements/uniform_list.rs |  86 +++++++++-----------
crates/gpui2/src/view.rs                  |  89 +++++++--------------
crates/gpui2/src/window.rs                |  39 +++++----
crates/storybook2/src/stories/focus.rs    |   1 
10 files changed, 146 insertions(+), 318 deletions(-)

Detailed changes

crates/editor2/src/element.rs 🔗

@@ -2400,21 +2400,14 @@ impl Element<Editor> for EditorElement {
         Some(self.editor_id.into())
     }
 
-    fn initialize(
+    fn layout(
         &mut self,
         editor: &mut Editor,
         element_state: Option<Self::ElementState>,
         cx: &mut gpui::ViewContext<Editor>,
-    ) -> Self::ElementState {
+    ) -> (gpui::LayoutId, Self::ElementState) {
         editor.style = Some(self.style.clone()); // Long-term, we'd like to eliminate this.
-    }
 
-    fn layout(
-        &mut self,
-        editor: &mut Editor,
-        element_state: &mut Self::ElementState,
-        cx: &mut gpui::ViewContext<Editor>,
-    ) -> gpui::LayoutId {
         let rem_size = cx.rem_size();
         let mut style = Style::default();
         style.size.width = relative(1.).into();
@@ -2423,7 +2416,8 @@ impl Element<Editor> for EditorElement {
             EditorMode::AutoHeight { .. } => todo!(),
             EditorMode::Full => relative(1.).into(),
         };
-        cx.request_layout(&style, None)
+        let layout_id = cx.request_layout(&style, None);
+        (layout_id, ())
     }
 
     fn paint(

crates/gpui2/src/element.rs 🔗

@@ -10,21 +10,12 @@ pub trait Element<V: 'static> {
 
     fn element_id(&self) -> Option<ElementId>;
 
-    /// Called to initialize this element for the current frame. If this
-    /// element had state in a previous frame, it will be passed in for the 3rd argument.
-    fn initialize(
-        &mut self,
-        view_state: &mut V,
-        element_state: Option<Self::ElementState>,
-        cx: &mut ViewContext<V>,
-    ) -> Self::ElementState;
-
     fn layout(
         &mut self,
         view_state: &mut V,
-        element_state: &mut Self::ElementState,
+        previous_element_state: Option<Self::ElementState>,
         cx: &mut ViewContext<V>,
-    ) -> LayoutId;
+    ) -> (LayoutId, Self::ElementState);
 
     fn paint(
         &mut self,
@@ -96,7 +87,6 @@ pub trait ParentComponent<V: 'static> {
 }
 
 trait ElementObject<V> {
-    fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
     fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId;
     fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
     fn measure(
@@ -123,9 +113,6 @@ struct RenderedElement<V: 'static, E: Element<V>> {
 enum ElementRenderPhase<V> {
     #[default]
     Start,
-    Initialized {
-        frame_state: Option<V>,
-    },
     LayoutRequested {
         layout_id: LayoutId,
         frame_state: Option<V>,
@@ -157,42 +144,19 @@ where
     E: Element<V>,
     E::ElementState: 'static,
 {
-    fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
-        let frame_state = if let Some(id) = self.element.element_id() {
-            cx.with_element_state(id, |element_state, cx| {
-                let element_state = self.element.initialize(view_state, element_state, cx);
-                ((), element_state)
-            });
-            None
-        } else {
-            let frame_state = self.element.initialize(view_state, None, cx);
-            Some(frame_state)
-        };
-
-        self.phase = ElementRenderPhase::Initialized { frame_state };
-    }
-
     fn layout(&mut self, state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
-        let layout_id;
-        let mut frame_state;
-        match mem::take(&mut self.phase) {
-            ElementRenderPhase::Initialized {
-                frame_state: initial_frame_state,
-            } => {
-                frame_state = initial_frame_state;
+        let (layout_id, frame_state) = match mem::take(&mut self.phase) {
+            ElementRenderPhase::Start => {
                 if let Some(id) = self.element.element_id() {
-                    layout_id = cx.with_element_state(id, |element_state, cx| {
-                        let mut element_state = element_state.unwrap();
-                        let layout_id = self.element.layout(state, &mut element_state, cx);
-                        (layout_id, element_state)
+                    let layout_id = cx.with_element_state(id, |element_state, cx| {
+                        self.element.layout(state, element_state, cx)
                     });
+                    (layout_id, None)
                 } else {
-                    layout_id = self
-                        .element
-                        .layout(state, frame_state.as_mut().unwrap(), cx);
+                    let (layout_id, frame_state) = self.element.layout(state, None, cx);
+                    (layout_id, Some(frame_state))
                 }
             }
-            ElementRenderPhase::Start => panic!("must call initialize before layout"),
             ElementRenderPhase::LayoutRequested { .. }
             | ElementRenderPhase::LayoutComputed { .. }
             | ElementRenderPhase::Painted { .. } => {
@@ -244,10 +208,6 @@ where
         cx: &mut ViewContext<V>,
     ) -> Size<Pixels> {
         if matches!(&self.phase, ElementRenderPhase::Start) {
-            self.initialize(view_state, cx);
-        }
-
-        if matches!(&self.phase, ElementRenderPhase::Initialized { .. }) {
             self.layout(view_state, cx);
         }
 
@@ -284,16 +244,13 @@ where
 
     fn draw(
         &mut self,
-        mut origin: Point<Pixels>,
+        origin: Point<Pixels>,
         available_space: Size<AvailableSpace>,
         view_state: &mut V,
         cx: &mut ViewContext<V>,
     ) {
         self.measure(available_space, view_state, cx);
-        // Ignore the element offset when drawing this element, as the origin is already specified
-        // in absolute terms.
-        origin -= cx.element_offset();
-        cx.with_element_offset(origin, |cx| self.paint(view_state, cx))
+        cx.with_absolute_element_offset(origin, |cx| self.paint(view_state, cx))
     }
 }
 
@@ -309,10 +266,6 @@ impl<V> AnyElement<V> {
         AnyElement(Box::new(RenderedElement::new(element)))
     }
 
-    pub fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
-        self.0.initialize(view_state, cx);
-    }
-
     pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
         self.0.layout(view_state, cx)
     }
@@ -393,25 +346,16 @@ where
         None
     }
 
-    fn initialize(
+    fn layout(
         &mut self,
         view_state: &mut V,
-        _rendered_element: Option<Self::ElementState>,
+        _: Option<Self::ElementState>,
         cx: &mut ViewContext<V>,
-    ) -> Self::ElementState {
+    ) -> (LayoutId, Self::ElementState) {
         let render = self.take().unwrap();
         let mut rendered_element = (render)(view_state, cx).render();
-        rendered_element.initialize(view_state, cx);
-        rendered_element
-    }
-
-    fn layout(
-        &mut self,
-        view_state: &mut V,
-        rendered_element: &mut Self::ElementState,
-        cx: &mut ViewContext<V>,
-    ) -> LayoutId {
-        rendered_element.layout(view_state, cx)
+        let layout_id = rendered_element.layout(view_state, cx);
+        (layout_id, rendered_element)
     }
 
     fn paint(

crates/gpui2/src/elements/div.rs 🔗

@@ -436,14 +436,6 @@ pub trait FocusableComponent<V: 'static>: InteractiveComponent<V> {
         self
     }
 
-    fn focus_in(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
-    where
-        Self: Sized,
-    {
-        self.interactivity().focus_in_style = f(StyleRefinement::default());
-        self
-    }
-
     fn in_focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
     where
         Self: Sized,
@@ -616,46 +608,36 @@ impl<V: 'static> Element<V> for Div<V> {
         self.interactivity.element_id.clone()
     }
 
-    fn initialize(
-        &mut self,
-        view_state: &mut V,
-        element_state: Option<Self::ElementState>,
-        cx: &mut ViewContext<V>,
-    ) -> Self::ElementState {
-        let interactive_state = self
-            .interactivity
-            .initialize(element_state.map(|s| s.interactive_state), cx);
-
-        for child in &mut self.children {
-            child.initialize(view_state, cx);
-        }
-
-        DivState {
-            interactive_state,
-            child_layout_ids: SmallVec::new(),
-        }
-    }
-
     fn layout(
         &mut self,
         view_state: &mut V,
-        element_state: &mut Self::ElementState,
+        element_state: Option<Self::ElementState>,
         cx: &mut ViewContext<V>,
-    ) -> crate::LayoutId {
+    ) -> (LayoutId, Self::ElementState) {
+        let mut child_layout_ids = SmallVec::new();
         let mut interactivity = mem::take(&mut self.interactivity);
-        let layout_id =
-            interactivity.layout(&mut element_state.interactive_state, cx, |style, cx| {
+        let (layout_id, interactive_state) = interactivity.layout(
+            element_state.map(|s| s.interactive_state),
+            cx,
+            |style, cx| {
                 cx.with_text_style(style.text_style().cloned(), |cx| {
-                    element_state.child_layout_ids = self
+                    child_layout_ids = self
                         .children
                         .iter_mut()
                         .map(|child| child.layout(view_state, cx))
                         .collect::<SmallVec<_>>();
-                    cx.request_layout(&style, element_state.child_layout_ids.iter().copied())
+                    cx.request_layout(&style, child_layout_ids.iter().copied())
                 })
-            });
+            },
+        );
         self.interactivity = interactivity;
-        layout_id
+        (
+            layout_id,
+            DivState {
+                interactive_state,
+                child_layout_ids,
+            },
+        )
     }
 
     fn paint(
@@ -739,7 +721,6 @@ pub struct Interactivity<V> {
     pub group: Option<SharedString>,
     pub base_style: StyleRefinement,
     pub focus_style: StyleRefinement,
-    pub focus_in_style: StyleRefinement,
     pub in_focus_style: StyleRefinement,
     pub hover_style: StyleRefinement,
     pub group_hover_style: Option<GroupStyle>,
@@ -765,11 +746,12 @@ impl<V> Interactivity<V>
 where
     V: 'static,
 {
-    pub fn initialize(
+    pub fn layout(
         &mut self,
         element_state: Option<InteractiveElementState>,
         cx: &mut ViewContext<V>,
-    ) -> InteractiveElementState {
+        f: impl FnOnce(Style, &mut ViewContext<V>) -> LayoutId,
+    ) -> (LayoutId, InteractiveElementState) {
         let mut element_state = element_state.unwrap_or_default();
 
         // Ensure we store a focus handle in our element state if we're focusable.
@@ -784,17 +766,9 @@ where
             });
         }
 
-        element_state
-    }
-
-    pub fn layout(
-        &mut self,
-        element_state: &mut InteractiveElementState,
-        cx: &mut ViewContext<V>,
-        f: impl FnOnce(Style, &mut ViewContext<V>) -> LayoutId,
-    ) -> LayoutId {
-        let style = self.compute_style(None, element_state, cx);
-        f(style, cx)
+        let style = self.compute_style(None, &mut element_state, cx);
+        let layout_id = f(style, cx);
+        (layout_id, element_state)
     }
 
     pub fn paint(
@@ -1129,10 +1103,6 @@ where
         style.refine(&self.base_style);
 
         if let Some(focus_handle) = self.tracked_focus_handle.as_ref() {
-            if focus_handle.contains_focused(cx) {
-                style.refine(&self.focus_in_style);
-            }
-
             if focus_handle.within_focused(cx) {
                 style.refine(&self.in_focus_style);
             }
@@ -1205,7 +1175,6 @@ impl<V: 'static> Default for Interactivity<V> {
             group: None,
             base_style: StyleRefinement::default(),
             focus_style: StyleRefinement::default(),
-            focus_in_style: StyleRefinement::default(),
             in_focus_style: StyleRefinement::default(),
             hover_style: StyleRefinement::default(),
             group_hover_style: None,
@@ -1326,21 +1295,12 @@ where
         self.element.element_id()
     }
 
-    fn initialize(
-        &mut self,
-        view_state: &mut V,
-        element_state: Option<Self::ElementState>,
-        cx: &mut ViewContext<V>,
-    ) -> Self::ElementState {
-        self.element.initialize(view_state, element_state, cx)
-    }
-
     fn layout(
         &mut self,
         view_state: &mut V,
-        element_state: &mut Self::ElementState,
+        element_state: Option<Self::ElementState>,
         cx: &mut ViewContext<V>,
-    ) -> LayoutId {
+    ) -> (LayoutId, Self::ElementState) {
         self.element.layout(view_state, element_state, cx)
     }
 
@@ -1421,21 +1381,12 @@ where
         self.element.element_id()
     }
 
-    fn initialize(
-        &mut self,
-        view_state: &mut V,
-        element_state: Option<Self::ElementState>,
-        cx: &mut ViewContext<V>,
-    ) -> Self::ElementState {
-        self.element.initialize(view_state, element_state, cx)
-    }
-
     fn layout(
         &mut self,
         view_state: &mut V,
-        element_state: &mut Self::ElementState,
+        element_state: Option<Self::ElementState>,
         cx: &mut ViewContext<V>,
-    ) -> LayoutId {
+    ) -> (LayoutId, Self::ElementState) {
         self.element.layout(view_state, element_state, cx)
     }
 

crates/gpui2/src/elements/img.rs 🔗

@@ -48,21 +48,12 @@ impl<V> Element<V> for Img<V> {
         self.interactivity.element_id.clone()
     }
 
-    fn initialize(
-        &mut self,
-        _view_state: &mut V,
-        element_state: Option<Self::ElementState>,
-        cx: &mut ViewContext<V>,
-    ) -> Self::ElementState {
-        self.interactivity.initialize(element_state, cx)
-    }
-
     fn layout(
         &mut self,
         _view_state: &mut V,
-        element_state: &mut Self::ElementState,
+        element_state: Option<Self::ElementState>,
         cx: &mut ViewContext<V>,
-    ) -> LayoutId {
+    ) -> (LayoutId, Self::ElementState) {
         self.interactivity.layout(element_state, cx, |style, cx| {
             cx.request_layout(&style, None)
         })

crates/gpui2/src/elements/svg.rs 🔗

@@ -37,21 +37,12 @@ impl<V> Element<V> for Svg<V> {
         self.interactivity.element_id.clone()
     }
 
-    fn initialize(
-        &mut self,
-        _view_state: &mut V,
-        element_state: Option<Self::ElementState>,
-        cx: &mut ViewContext<V>,
-    ) -> Self::ElementState {
-        self.interactivity.initialize(element_state, cx)
-    }
-
     fn layout(
         &mut self,
         _view_state: &mut V,
-        element_state: &mut Self::ElementState,
+        element_state: Option<Self::ElementState>,
         cx: &mut ViewContext<V>,
-    ) -> LayoutId {
+    ) -> (LayoutId, Self::ElementState) {
         self.interactivity.layout(element_state, cx, |style, cx| {
             cx.request_layout(&style, None)
         })

crates/gpui2/src/elements/text.rs 🔗

@@ -76,21 +76,13 @@ impl<V: 'static> Element<V> for Text<V> {
         None
     }
 
-    fn initialize(
-        &mut self,
-        _view_state: &mut V,
-        element_state: Option<Self::ElementState>,
-        _cx: &mut ViewContext<V>,
-    ) -> Self::ElementState {
-        element_state.unwrap_or_default()
-    }
-
     fn layout(
         &mut self,
         _view: &mut V,
-        element_state: &mut Self::ElementState,
+        element_state: Option<Self::ElementState>,
         cx: &mut ViewContext<V>,
-    ) -> LayoutId {
+    ) -> (LayoutId, Self::ElementState) {
+        let element_state = element_state.unwrap_or_default();
         let text_system = cx.text_system().clone();
         let text_style = cx.text_style();
         let font_size = text_style.font_size.to_pixels(cx.rem_size());
@@ -148,7 +140,7 @@ impl<V: 'static> Element<V> for Text<V> {
             }
         });
 
-        layout_id
+        (layout_id, element_state)
     }
 
     fn paint(

crates/gpui2/src/elements/uniform_list.rs 🔗

@@ -108,62 +108,54 @@ impl<V: 'static> Element<V> for UniformList<V> {
         Some(self.id.clone())
     }
 
-    fn initialize(
+    fn layout(
         &mut self,
         view_state: &mut V,
         element_state: Option<Self::ElementState>,
         cx: &mut ViewContext<V>,
-    ) -> Self::ElementState {
-        if let Some(mut element_state) = element_state {
-            element_state.interactive = self
-                .interactivity
-                .initialize(Some(element_state.interactive), cx);
-            element_state
-        } else {
-            let item_size = self.measure_item(view_state, None, cx);
-            UniformListState {
-                interactive: self.interactivity.initialize(None, cx),
-                item_size,
-            }
-        }
-    }
-
-    fn layout(
-        &mut self,
-        _view_state: &mut V,
-        element_state: &mut Self::ElementState,
-        cx: &mut ViewContext<V>,
-    ) -> LayoutId {
+    ) -> (LayoutId, Self::ElementState) {
         let max_items = self.item_count;
-        let item_size = element_state.item_size;
         let rem_size = cx.rem_size();
+        let item_size = element_state
+            .as_ref()
+            .map(|s| s.item_size)
+            .unwrap_or_else(|| self.measure_item(view_state, None, cx));
 
-        self.interactivity
-            .layout(&mut element_state.interactive, cx, |style, cx| {
-                cx.request_measured_layout(
-                    style,
-                    rem_size,
-                    move |known_dimensions: Size<Option<Pixels>>,
-                          available_space: Size<AvailableSpace>| {
-                        let desired_height = item_size.height * max_items;
-                        let width = known_dimensions
-                            .width
-                            .unwrap_or(match available_space.width {
-                                AvailableSpace::Definite(x) => x,
+        let (layout_id, interactive) =
+            self.interactivity
+                .layout(element_state.map(|s| s.interactive), cx, |style, cx| {
+                    cx.request_measured_layout(
+                        style,
+                        rem_size,
+                        move |known_dimensions: Size<Option<Pixels>>,
+                              available_space: Size<AvailableSpace>| {
+                            let desired_height = item_size.height * max_items;
+                            let width =
+                                known_dimensions
+                                    .width
+                                    .unwrap_or(match available_space.width {
+                                        AvailableSpace::Definite(x) => x,
+                                        AvailableSpace::MinContent | AvailableSpace::MaxContent => {
+                                            item_size.width
+                                        }
+                                    });
+                            let height = match available_space.height {
+                                AvailableSpace::Definite(x) => desired_height.min(x),
                                 AvailableSpace::MinContent | AvailableSpace::MaxContent => {
-                                    item_size.width
+                                    desired_height
                                 }
-                            });
-                        let height = match available_space.height {
-                            AvailableSpace::Definite(x) => desired_height.min(x),
-                            AvailableSpace::MinContent | AvailableSpace::MaxContent => {
-                                desired_height
-                            }
-                        };
-                        size(width, height)
-                    },
-                )
-            })
+                            };
+                            size(width, height)
+                        },
+                    )
+                });
+
+        let element_state = UniformListState {
+            interactive,
+            item_size,
+        };
+
+        (layout_id, element_state)
     }
 
     fn paint(

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,
+    BorrowWindow, Bounds, Component, Element, ElementId, Entity, EntityId, Flatten, LayoutId,
+    Model, Pixels, Point, Size, ViewContext, VisualContext, WeakModel, WindowContext,
 };
 use anyhow::{Context, Result};
 use std::{
@@ -155,8 +155,7 @@ impl<V> Eq for WeakView<V> {}
 #[derive(Clone, Debug)]
 pub struct AnyView {
     model: AnyModel,
-    initialize: fn(&AnyView, &mut WindowContext) -> AnyBox,
-    layout: fn(&AnyView, &mut AnyBox, &mut WindowContext) -> LayoutId,
+    layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, Box<dyn Any>),
     paint: fn(&AnyView, &mut AnyBox, &mut WindowContext),
 }
 
@@ -164,7 +163,6 @@ impl AnyView {
     pub fn downgrade(&self) -> AnyWeakView {
         AnyWeakView {
             model: self.model.downgrade(),
-            initialize: self.initialize,
             layout: self.layout,
             paint: self.paint,
         }
@@ -175,7 +173,6 @@ impl AnyView {
             Ok(model) => Ok(View { model }),
             Err(model) => Err(Self {
                 model,
-                initialize: self.initialize,
                 layout: self.layout,
                 paint: self.paint,
             }),
@@ -186,13 +183,19 @@ impl AnyView {
         self.model.entity_type
     }
 
-    pub(crate) fn draw(&self, available_space: Size<AvailableSpace>, cx: &mut WindowContext) {
-        let mut rendered_element = (self.initialize)(self, cx);
-        let layout_id = (self.layout)(self, &mut rendered_element, cx);
-        cx.window
-            .layout_engine
-            .compute_layout(layout_id, available_space);
-        (self.paint)(self, &mut rendered_element, cx);
+    pub(crate) fn draw(
+        &self,
+        origin: Point<Pixels>,
+        available_space: Size<AvailableSpace>,
+        cx: &mut WindowContext,
+    ) {
+        cx.with_absolute_element_offset(origin, |cx| {
+            let (layout_id, mut rendered_element) = (self.layout)(self, cx);
+            cx.window
+                .layout_engine
+                .compute_layout(layout_id, available_space);
+            (self.paint)(self, &mut rendered_element, cx);
+        })
     }
 }
 
@@ -206,7 +209,6 @@ impl<V: Render> From<View<V>> for AnyView {
     fn from(value: View<V>) -> Self {
         AnyView {
             model: value.model.into_any(),
-            initialize: any_view::initialize::<V>,
             layout: any_view::layout::<V>,
             paint: any_view::paint::<V>,
         }
@@ -220,22 +222,13 @@ impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
         Some(self.model.entity_id.into())
     }
 
-    fn initialize(
-        &mut self,
-        _view_state: &mut ParentViewState,
-        _element_state: Option<Self::ElementState>,
-        cx: &mut ViewContext<ParentViewState>,
-    ) -> Self::ElementState {
-        (self.initialize)(self, cx)
-    }
-
     fn layout(
         &mut self,
         _view_state: &mut ParentViewState,
-        rendered_element: &mut Self::ElementState,
+        _element_state: Option<Self::ElementState>,
         cx: &mut ViewContext<ParentViewState>,
-    ) -> LayoutId {
-        (self.layout)(self, rendered_element, cx)
+    ) -> (LayoutId, Self::ElementState) {
+        (self.layout)(self, cx)
     }
 
     fn paint(
@@ -251,8 +244,7 @@ impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
 
 pub struct AnyWeakView {
     model: AnyWeakModel,
-    initialize: fn(&AnyView, &mut WindowContext) -> AnyBox,
-    layout: fn(&AnyView, &mut AnyBox, &mut WindowContext) -> LayoutId,
+    layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, Box<dyn Any>),
     paint: fn(&AnyView, &mut AnyBox, &mut WindowContext),
 }
 
@@ -261,7 +253,6 @@ impl AnyWeakView {
         let model = self.model.upgrade()?;
         Some(AnyView {
             model,
-            initialize: self.initialize,
             layout: self.layout,
             paint: self.paint,
         })
@@ -272,7 +263,6 @@ impl<V: Render> From<WeakView<V>> for AnyWeakView {
     fn from(view: WeakView<V>) -> Self {
         Self {
             model: view.model.into(),
-            initialize: any_view::initialize::<V>,
             layout: any_view::layout::<V>,
             paint: any_view::paint::<V>,
         }
@@ -319,28 +309,19 @@ where
         Some(self.view.entity_id().into())
     }
 
-    fn initialize(
+    fn layout(
         &mut self,
         _: &mut ParentViewState,
         _: Option<Self::ElementState>,
         cx: &mut ViewContext<ParentViewState>,
-    ) -> Self::ElementState {
+    ) -> (LayoutId, Self::ElementState) {
         self.view.update(cx, |view, cx| {
             let mut element = self.component.take().unwrap().render();
-            element.initialize(view, cx);
-            element
+            let layout_id = element.layout(view, cx);
+            (layout_id, element)
         })
     }
 
-    fn layout(
-        &mut self,
-        _: &mut ParentViewState,
-        element: &mut Self::ElementState,
-        cx: &mut ViewContext<ParentViewState>,
-    ) -> LayoutId {
-        self.view.update(cx, |view, cx| element.layout(view, cx))
-    }
-
     fn paint(
         &mut self,
         _: Bounds<Pixels>,
@@ -356,27 +337,17 @@ mod any_view {
     use crate::{AnyElement, AnyView, BorrowWindow, LayoutId, Render, WindowContext};
     use std::any::Any;
 
-    pub(crate) fn initialize<V: Render>(view: &AnyView, cx: &mut WindowContext) -> Box<dyn Any> {
-        cx.with_element_id(Some(view.model.entity_id), |cx| {
-            let view = view.clone().downcast::<V>().unwrap();
-            let element = view.update(cx, |view, cx| {
-                let mut element = AnyElement::new(view.render(cx));
-                element.initialize(view, cx);
-                element
-            });
-            Box::new(element)
-        })
-    }
-
     pub(crate) fn layout<V: Render>(
         view: &AnyView,
-        element: &mut Box<dyn Any>,
         cx: &mut WindowContext,
-    ) -> LayoutId {
+    ) -> (LayoutId, Box<dyn Any>) {
         cx.with_element_id(Some(view.model.entity_id), |cx| {
             let view = view.clone().downcast::<V>().unwrap();
-            let element = element.downcast_mut::<AnyElement<V>>().unwrap();
-            view.update(cx, |view, cx| element.layout(view, cx))
+            view.update(cx, |view, cx| {
+                let mut element = AnyElement::new(view.render(cx));
+                let layout_id = element.layout(view, cx);
+                (layout_id, Box::new(element) as Box<dyn Any>)
+            })
         })
     }
 

crates/gpui2/src/window.rs 🔗

@@ -1076,29 +1076,22 @@ impl<'a> WindowContext<'a> {
 
         self.with_z_index(0, |cx| {
             let available_space = cx.window.viewport_size.map(Into::into);
-            root_view.draw(available_space, cx);
+            root_view.draw(Point::zero(), available_space, cx);
         });
 
         if let Some(active_drag) = self.app.active_drag.take() {
             self.with_z_index(1, |cx| {
                 let offset = cx.mouse_position() - active_drag.cursor_offset;
-                cx.with_element_offset(offset, |cx| {
-                    let available_space =
-                        size(AvailableSpace::MinContent, AvailableSpace::MinContent);
-                    active_drag.view.draw(available_space, cx);
-                    cx.active_drag = Some(active_drag);
-                });
+                let available_space = size(AvailableSpace::MinContent, AvailableSpace::MinContent);
+                active_drag.view.draw(offset, available_space, cx);
+                cx.active_drag = Some(active_drag);
             });
         } else if let Some(active_tooltip) = self.app.active_tooltip.take() {
             self.with_z_index(1, |cx| {
-                cx.with_element_offset(active_tooltip.cursor_offset, |cx| {
-                    let available_space = Size {
-                        width: cx.window.viewport_size.width - active_tooltip.cursor_offset.x,
-                        height: cx.window.viewport_size.height - active_tooltip.cursor_offset.y,
-                    }
-                    .map(Into::into);
-                    active_tooltip.view.draw(available_space, cx);
-                });
+                let available_space = size(AvailableSpace::MinContent, AvailableSpace::MinContent);
+                active_tooltip
+                    .view
+                    .draw(active_tooltip.cursor_offset, available_space, cx);
             });
         }
 
@@ -1636,8 +1629,8 @@ pub trait BorrowWindow: BorrowMut<Window> + BorrowMut<AppContext> {
         }
     }
 
-    /// Update the global element offset based on the given offset. This is used to implement
-    /// scrolling and position drag handles.
+    /// Update the global element offset relative to the current offset. This is used to implement
+    /// scrolling.
     fn with_element_offset<R>(
         &mut self,
         offset: Point<Pixels>,
@@ -1647,7 +1640,17 @@ pub trait BorrowWindow: BorrowMut<Window> + BorrowMut<AppContext> {
             return f(self);
         };
 
-        let offset = self.element_offset() + offset;
+        let abs_offset = self.element_offset() + offset;
+        self.with_absolute_element_offset(abs_offset, f)
+    }
+
+    /// Update the global element offset based on the given offset. This is used to implement
+    /// drag handles and other manual painting of elements.
+    fn with_absolute_element_offset<R>(
+        &mut self,
+        offset: Point<Pixels>,
+        f: impl FnOnce(&mut Self) -> R,
+    ) -> R {
         self.window_mut()
             .current_frame
             .element_offset_stack

crates/storybook2/src/stories/focus.rs 🔗

@@ -57,7 +57,6 @@ impl Render for FocusStory {
             .size_full()
             .bg(color_1)
             .focus(|style| style.bg(color_2))
-            .focus_in(|style| style.bg(color_3))
             .child(
                 div()
                     .track_focus(&self.child_1_focus)