Reduce the stack size of Interactivity at the cost of more allocations

This commit is contained in:
Antonio Scandurra 2023-12-12 11:57:44 +01:00
parent e7094cc98d
commit f312c58b30
3 changed files with 59 additions and 53 deletions

View file

@ -26,7 +26,7 @@ const TOOLTIP_DELAY: Duration = Duration::from_millis(500);
pub struct GroupStyle { pub struct GroupStyle {
pub group: SharedString, pub group: SharedString,
pub style: StyleRefinement, pub style: Box<StyleRefinement>,
} }
pub trait InteractiveElement: Sized + Element { pub trait InteractiveElement: Sized + Element {
@ -61,7 +61,7 @@ pub trait InteractiveElement: Sized + Element {
} }
fn hover(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self { fn hover(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self {
self.interactivity().hover_style = f(StyleRefinement::default()); self.interactivity().hover_style = Some(Box::new(f(StyleRefinement::default())));
self self
} }
@ -72,7 +72,7 @@ pub trait InteractiveElement: Sized + Element {
) -> Self { ) -> Self {
self.interactivity().group_hover_style = Some(GroupStyle { self.interactivity().group_hover_style = Some(GroupStyle {
group: group_name.into(), group: group_name.into(),
style: f(StyleRefinement::default()), style: Box::new(f(StyleRefinement::default())),
}); });
self self
} }
@ -319,7 +319,7 @@ pub trait InteractiveElement: Sized + Element {
TypeId::of::<S>(), TypeId::of::<S>(),
GroupStyle { GroupStyle {
group: group_name.into(), group: group_name.into(),
style: f(StyleRefinement::default()), style: Box::new(f(StyleRefinement::default())),
}, },
)); ));
self self
@ -370,7 +370,7 @@ pub trait StatefulInteractiveElement: InteractiveElement {
where where
Self: Sized, Self: Sized,
{ {
self.interactivity().active_style = f(StyleRefinement::default()); self.interactivity().active_style = Some(Box::new(f(StyleRefinement::default())));
self self
} }
@ -384,7 +384,7 @@ pub trait StatefulInteractiveElement: InteractiveElement {
{ {
self.interactivity().group_active_style = Some(GroupStyle { self.interactivity().group_active_style = Some(GroupStyle {
group: group_name.into(), group: group_name.into(),
style: f(StyleRefinement::default()), style: Box::new(f(StyleRefinement::default())),
}); });
self self
} }
@ -446,7 +446,7 @@ pub trait FocusableElement: InteractiveElement {
where where
Self: Sized, Self: Sized,
{ {
self.interactivity().focus_style = f(StyleRefinement::default()); self.interactivity().focus_style = Some(Box::new(f(StyleRefinement::default())));
self self
} }
@ -454,7 +454,7 @@ pub trait FocusableElement: InteractiveElement {
where where
Self: Sized, Self: Sized,
{ {
self.interactivity().in_focus_style = f(StyleRefinement::default()); self.interactivity().in_focus_style = Some(Box::new(f(StyleRefinement::default())));
self self
} }
@ -532,7 +532,7 @@ pub trait FocusableElement: InteractiveElement {
} }
} }
pub type FocusListeners = SmallVec<[FocusListener; 2]>; pub type FocusListeners = Vec<FocusListener>;
pub type FocusListener = Box<dyn Fn(&FocusHandle, &FocusEvent, &mut WindowContext) + 'static>; pub type FocusListener = Box<dyn Fn(&FocusHandle, &FocusEvent, &mut WindowContext) + 'static>;
@ -710,7 +710,7 @@ impl IntoElement for Div {
} }
pub struct DivState { pub struct DivState {
child_layout_ids: SmallVec<[LayoutId; 4]>, child_layout_ids: SmallVec<[LayoutId; 2]>,
interactive_state: InteractiveElementState, interactive_state: InteractiveElementState,
} }
@ -728,24 +728,24 @@ pub struct Interactivity {
pub scroll_handle: Option<ScrollHandle>, pub scroll_handle: Option<ScrollHandle>,
pub focus_listeners: FocusListeners, pub focus_listeners: FocusListeners,
pub group: Option<SharedString>, pub group: Option<SharedString>,
pub base_style: StyleRefinement, pub base_style: Box<StyleRefinement>,
pub focus_style: StyleRefinement, pub focus_style: Option<Box<StyleRefinement>>,
pub in_focus_style: StyleRefinement, pub in_focus_style: Option<Box<StyleRefinement>>,
pub hover_style: StyleRefinement, pub hover_style: Option<Box<StyleRefinement>>,
pub group_hover_style: Option<GroupStyle>, pub group_hover_style: Option<GroupStyle>,
pub active_style: StyleRefinement, pub active_style: Option<Box<StyleRefinement>>,
pub group_active_style: Option<GroupStyle>, pub group_active_style: Option<GroupStyle>,
pub drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>, pub drag_over_styles: Vec<(TypeId, StyleRefinement)>,
pub group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>, pub group_drag_over_styles: Vec<(TypeId, GroupStyle)>,
pub mouse_down_listeners: SmallVec<[MouseDownListener; 2]>, pub mouse_down_listeners: Vec<MouseDownListener>,
pub mouse_up_listeners: SmallVec<[MouseUpListener; 2]>, pub mouse_up_listeners: Vec<MouseUpListener>,
pub mouse_move_listeners: SmallVec<[MouseMoveListener; 2]>, pub mouse_move_listeners: Vec<MouseMoveListener>,
pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener; 2]>, pub scroll_wheel_listeners: Vec<ScrollWheelListener>,
pub key_down_listeners: SmallVec<[KeyDownListener; 2]>, pub key_down_listeners: Vec<KeyDownListener>,
pub key_up_listeners: SmallVec<[KeyUpListener; 2]>, pub key_up_listeners: Vec<KeyUpListener>,
pub action_listeners: SmallVec<[(TypeId, ActionListener); 8]>, pub action_listeners: Vec<(TypeId, ActionListener)>,
pub drop_listeners: SmallVec<[(TypeId, Box<DropListener>); 2]>, pub drop_listeners: Vec<(TypeId, Box<DropListener>)>,
pub click_listeners: SmallVec<[ClickListener; 2]>, pub click_listeners: Vec<ClickListener>,
pub drag_listener: Option<DragListener>, pub drag_listener: Option<DragListener>,
pub hover_listener: Option<Box<dyn Fn(&bool, &mut WindowContext)>>, pub hover_listener: Option<Box<dyn Fn(&bool, &mut WindowContext)>>,
pub tooltip_builder: Option<TooltipBuilder>, pub tooltip_builder: Option<TooltipBuilder>,
@ -1175,12 +1175,16 @@ impl Interactivity {
style.refine(&self.base_style); style.refine(&self.base_style);
if let Some(focus_handle) = self.tracked_focus_handle.as_ref() { if let Some(focus_handle) = self.tracked_focus_handle.as_ref() {
if focus_handle.within_focused(cx) { if let Some(in_focus_style) = self.in_focus_style.as_ref() {
style.refine(&self.in_focus_style); if focus_handle.within_focused(cx) {
style.refine(in_focus_style);
}
} }
if focus_handle.is_focused(cx) { if let Some(focus_style) = self.focus_style.as_ref() {
style.refine(&self.focus_style); if focus_handle.is_focused(cx) {
style.refine(focus_style);
}
} }
} }
@ -1195,13 +1199,13 @@ impl Interactivity {
} }
} }
} }
if self.hover_style.is_some() { if let Some(hover_style) = self.hover_style.as_ref() {
if bounds if bounds
.intersect(&cx.content_mask().bounds) .intersect(&cx.content_mask().bounds)
.contains(&mouse_position) .contains(&mouse_position)
&& cx.was_top_layer(&mouse_position, cx.stacking_order()) && cx.was_top_layer(&mouse_position, cx.stacking_order())
{ {
style.refine(&self.hover_style); style.refine(hover_style);
} }
} }
@ -1237,8 +1241,10 @@ impl Interactivity {
} }
} }
if clicked_state.element { if let Some(active_style) = self.active_style.as_ref() {
style.refine(&self.active_style) if clicked_state.element {
style.refine(active_style)
}
} }
style style
@ -1253,27 +1259,27 @@ impl Default for Interactivity {
focusable: false, focusable: false,
tracked_focus_handle: None, tracked_focus_handle: None,
scroll_handle: None, scroll_handle: None,
focus_listeners: SmallVec::default(), focus_listeners: Vec::default(),
// scroll_offset: Point::default(), // scroll_offset: Point::default(),
group: None, group: None,
base_style: StyleRefinement::default(), base_style: Box::new(StyleRefinement::default()),
focus_style: StyleRefinement::default(), focus_style: None,
in_focus_style: StyleRefinement::default(), in_focus_style: None,
hover_style: StyleRefinement::default(), hover_style: None,
group_hover_style: None, group_hover_style: None,
active_style: StyleRefinement::default(), active_style: None,
group_active_style: None, group_active_style: None,
drag_over_styles: SmallVec::new(), drag_over_styles: Vec::new(),
group_drag_over_styles: SmallVec::new(), group_drag_over_styles: Vec::new(),
mouse_down_listeners: SmallVec::new(), mouse_down_listeners: Vec::new(),
mouse_up_listeners: SmallVec::new(), mouse_up_listeners: Vec::new(),
mouse_move_listeners: SmallVec::new(), mouse_move_listeners: Vec::new(),
scroll_wheel_listeners: SmallVec::new(), scroll_wheel_listeners: Vec::new(),
key_down_listeners: SmallVec::new(), key_down_listeners: Vec::new(),
key_up_listeners: SmallVec::new(), key_up_listeners: Vec::new(),
action_listeners: SmallVec::new(), action_listeners: Vec::new(),
drop_listeners: SmallVec::new(), drop_listeners: Vec::new(),
click_listeners: SmallVec::new(), click_listeners: Vec::new(),
drag_listener: None, drag_listener: None,
hover_listener: None, hover_listener: None,
tooltip_builder: None, tooltip_builder: None,

View file

@ -41,7 +41,7 @@ where
render_items: Box::new(render_range), render_items: Box::new(render_range),
interactivity: Interactivity { interactivity: Interactivity {
element_id: Some(id.into()), element_id: Some(id.into()),
base_style, base_style: Box::new(base_style),
..Default::default() ..Default::default()
}, },
scroll_handle: None, scroll_handle: None,

View file

@ -4,7 +4,7 @@ use smallvec::SmallVec;
use std::fmt; use std::fmt;
#[derive(Clone, Default, Eq, PartialEq, Hash)] #[derive(Clone, Default, Eq, PartialEq, Hash)]
pub struct KeyContext(SmallVec<[ContextEntry; 8]>); pub struct KeyContext(SmallVec<[ContextEntry; 1]>);
#[derive(Clone, Debug, Eq, PartialEq, Hash)] #[derive(Clone, Debug, Eq, PartialEq, Hash)]
struct ContextEntry { struct ContextEntry {