Remove initialize from the Element trait (#3338)

Initially, we imagined registering keyboard handlers in the initialize
phase so we would understand the relationships between focus handles
during the layout pass, which would allow us to assign assign `focus_in`
styles that impact layout.

However, we soon realized that many elements aren't created until paint
time anyway, such as within the uniform list. Since it's impossible to
know prior to paint whether an element contains the focused element, it
makes more sense to eliminate the `focus_in` styling helper.

Release Notes:

- N/A
This commit is contained in:
Nathan Sobo 2023-11-15 19:36:35 -07:00 committed by GitHub
commit e5ada92b7b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 147 additions and 316 deletions

View file

@ -2398,21 +2398,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();
@ -2421,7 +2414,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(

View file

@ -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(
&mut self,
view_state: &mut V,
_rendered_element: Option<Self::ElementState>,
cx: &mut ViewContext<V>,
) -> 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,
_: Option<Self::ElementState>,
cx: &mut ViewContext<V>,
) -> LayoutId {
rendered_element.layout(view_state, cx)
) -> (LayoutId, Self::ElementState) {
let render = self.take().unwrap();
let mut rendered_element = (render)(view_state, cx).render();
let layout_id = rendered_element.layout(view_state, cx);
(layout_id, rendered_element)
}
fn paint(

View file

@ -437,14 +437,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,
@ -617,46 +609,36 @@ impl<V: 'static> Element<V> for Div<V> {
self.interactivity.element_id.clone()
}
fn initialize(
fn layout(
&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,
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(
@ -740,7 +722,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>,
@ -766,11 +747,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.
@ -785,17 +767,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(
@ -1130,10 +1104,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);
}
@ -1206,7 +1176,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,
@ -1327,21 +1296,12 @@ where
self.element.element_id()
}
fn initialize(
fn layout(
&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,
cx: &mut ViewContext<V>,
) -> LayoutId {
) -> (LayoutId, Self::ElementState) {
self.element.layout(view_state, element_state, cx)
}
@ -1422,21 +1382,12 @@ where
self.element.element_id()
}
fn initialize(
fn layout(
&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,
cx: &mut ViewContext<V>,
) -> LayoutId {
) -> (LayoutId, Self::ElementState) {
self.element.layout(view_state, element_state, cx)
}

View file

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

View file

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

View file

@ -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(

View file

@ -108,45 +108,30 @@ 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));
let (layout_id, interactive) =
self.interactivity
.layout(&mut element_state.interactive, cx, |style, cx| {
.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
let width =
known_dimensions
.width
.unwrap_or(match available_space.width {
AvailableSpace::Definite(x) => x,
@ -163,7 +148,14 @@ impl<V: 'static> Element<V> for UniformList<V> {
size(width, height)
},
)
})
});
let element_state = UniformListState {
interactive,
item_size,
};
(layout_id, element_state)
}
fn paint(

View file

@ -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);
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(
fn layout(
&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,
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>)
})
})
}

View file

@ -1076,26 +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);
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(AvailableSpace::MinContent, AvailableSpace::MinContent);
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);
});
}
@ -1633,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>,
@ -1644,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

View file

@ -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)