Skip to content

Commit

Permalink
Add property tree to Masonry
Browse files Browse the repository at this point in the history
  • Loading branch information
PoignardAzur committed Feb 18, 2025
1 parent f081107 commit 3746736
Show file tree
Hide file tree
Showing 13 changed files with 201 additions and 53 deletions.
3 changes: 2 additions & 1 deletion masonry/src/app/event_loop_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,8 @@ impl MasonryState<'_> {
window.show_window_menu(position);
}
RenderRootSignal::WidgetSelectedInInspector(widget_id) => {
let (widget, state) = self.render_root.widget_arena.get_pair(widget_id);
let (widget, state, _properties) =
self.render_root.widget_arena.get_all(widget_id);
let widget_name = widget.item.short_type_name();
let display_name = if let Some(debug_text) = widget.item.get_debug_text() {
format!("{widget_name}<{debug_text}>")
Expand Down
11 changes: 7 additions & 4 deletions masonry/src/app/render_root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,7 @@ impl RenderRoot {
fn request_render_all_in(
mut widget: ArenaMut<'_, Box<dyn Widget>>,
state: ArenaMut<'_, WidgetState>,
properties: ArenaMut<'_, anymap3::AnyMap>,
) {
state.item.needs_paint = true;
state.item.needs_accessibility = true;
Expand All @@ -644,14 +645,16 @@ impl RenderRoot {
id,
widget.reborrow_mut(),
state.children,
|widget, mut state| {
request_render_all_in(widget, state.reborrow_mut());
properties.children,
|widget, state, properties| {
request_render_all_in(widget, state, properties);
},
);
}

let (root_widget, mut root_state) = self.widget_arena.get_pair_mut(self.root.id());
request_render_all_in(root_widget, root_state.reborrow_mut());
let (root_widget, root_state, root_properties) =
self.widget_arena.get_all_mut(self.root.id());
request_render_all_in(root_widget, root_state, root_properties);
self.global_state
.emit_signal(RenderRootSignal::RequestRedraw);
}
Expand Down
3 changes: 0 additions & 3 deletions masonry/src/core/contexts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ pub struct EventCtx<'a> {
pub struct RegisterCtx<'a> {
pub(crate) widget_state_children: ArenaMutList<'a, WidgetState>,
pub(crate) widget_children: ArenaMutList<'a, Box<dyn Widget>>,
pub(crate) properties_children: ArenaMutList<'a, AnyMap>,
#[cfg(debug_assertions)]
pub(crate) registered_ids: Vec<WidgetId>,
}
Expand Down Expand Up @@ -112,7 +111,6 @@ pub struct ComposeCtx<'a> {
pub(crate) widget_state: &'a mut WidgetState,
pub(crate) widget_state_children: ArenaMutList<'a, WidgetState>,
pub(crate) widget_children: ArenaMutList<'a, Box<dyn Widget>>,
pub(crate) properties_children: ArenaMutList<'a, AnyMap>,
}

/// A context passed to [`Widget::paint`] method.
Expand All @@ -121,7 +119,6 @@ pub struct PaintCtx<'a> {
pub(crate) widget_state: &'a WidgetState,
pub(crate) widget_state_children: ArenaMutList<'a, WidgetState>,
pub(crate) widget_children: ArenaMutList<'a, Box<dyn Widget>>,
pub(crate) properties_children: ArenaMutList<'a, AnyMap>,
pub(crate) debug_paint: bool,
}

Expand Down
28 changes: 22 additions & 6 deletions masonry/src/core/widget_arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,14 @@ impl WidgetArena {
}

#[track_caller]
pub(crate) fn get_pair(
pub(crate) fn get_all(
&self,
widget_id: WidgetId,
) -> (ArenaRef<Box<dyn Widget>>, ArenaRef<WidgetState>) {
) -> (
ArenaRef<Box<dyn Widget>>,
ArenaRef<WidgetState>,
ArenaRef<anymap3::AnyMap>,
) {
let widget = self
.widgets
.find(widget_id)
Expand All @@ -41,14 +45,22 @@ impl WidgetArena {
.states
.find(widget_id)
.expect("get_pair: widget state not in widget tree");
(widget, state)
let properties = self
.properties
.find(widget_id)
.expect("get_pair: widget properties not in widget tree");
(widget, state, properties)
}

#[track_caller]
pub(crate) fn get_pair_mut(
pub(crate) fn get_all_mut(
&mut self,
widget_id: WidgetId,
) -> (ArenaMut<Box<dyn Widget>>, ArenaMut<WidgetState>) {
) -> (
ArenaMut<Box<dyn Widget>>,
ArenaMut<WidgetState>,
ArenaMut<anymap3::AnyMap>,
) {
let widget = self
.widgets
.find_mut(widget_id)
Expand All @@ -57,7 +69,11 @@ impl WidgetArena {
.states
.find_mut(widget_id)
.expect("get_pair_mut: widget state not in widget tree");
(widget, state)
let properties = self
.properties
.find_mut(widget_id)
.expect("get_pair_mut: widget properties not in widget tree");
(widget, state, properties)
}

#[allow(dead_code)]
Expand Down
17 changes: 14 additions & 3 deletions masonry/src/passes/accessibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ fn build_accessibility_tree(
tree_update: &mut TreeUpdate,
mut widget: ArenaMut<'_, Box<dyn Widget>>,
mut state: ArenaMut<'_, WidgetState>,
mut properties: ArenaMut<'_, anymap3::AnyMap>,
rebuild_all: bool,
scale_factor: Option<f64>,
) {
Expand All @@ -24,6 +25,7 @@ fn build_accessibility_tree(
global_state,
widget.reborrow(),
state.reborrow(),
properties.reborrow(),
);
let id = state.item.id;

Expand All @@ -45,6 +47,7 @@ fn build_accessibility_tree(
widget_state: state.item,
widget_state_children: state.children.reborrow_mut(),
widget_children: widget.children.reborrow_mut(),
properties_children: properties.children.reborrow_mut(),
tree_update,
rebuild_all,
};
Expand All @@ -67,14 +70,16 @@ fn build_accessibility_tree(
id,
widget.reborrow_mut(),
state.children,
|widget, mut state| {
properties.children,
|widget, mut state, properties| {
// TODO - We don't skip updating stashed items because doing so
// is error-prone. We may want to revisit that decision.
build_accessibility_tree(
global_state,
tree_update,
widget,
state.reborrow_mut(),
properties,
rebuild_all,
None,
);
Expand Down Expand Up @@ -154,7 +159,7 @@ pub(crate) fn run_accessibility_pass(root: &mut RenderRoot, scale_factor: f64) -
.into(),
};

let (root_widget, root_state) = {
let (root_widget, root_state, root_properties) = {
let widget_id = root.root.id();
let widget = root
.widget_arena
Expand All @@ -166,7 +171,12 @@ pub(crate) fn run_accessibility_pass(root: &mut RenderRoot, scale_factor: f64) -
.states
.find_mut(widget_id)
.expect("root_accessibility: root state not in widget tree");
(widget, state)
let properties = root
.widget_arena
.properties
.find_mut(widget_id)
.expect("root_accessibility: root properties not in widget tree");
(widget, state, properties)
};

if root.rebuild_access_tree {
Expand All @@ -177,6 +187,7 @@ pub(crate) fn run_accessibility_pass(root: &mut RenderRoot, scale_factor: f64) -
&mut tree_update,
root_widget,
root_state,
root_properties,
root.rebuild_access_tree,
Some(scale_factor),
);
Expand Down
18 changes: 15 additions & 3 deletions masonry/src/passes/anim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ fn update_anim_for_widget(
global_state: &mut RenderRootState,
mut widget: ArenaMut<'_, Box<dyn Widget>>,
mut state: ArenaMut<'_, WidgetState>,
mut properties: ArenaMut<'_, anymap3::AnyMap>,
elapsed_ns: u64,
) {
let _span = enter_span_if(
global_state.trace.anim,
global_state,
widget.reborrow(),
state.reborrow(),
properties.reborrow(),
);
if !state.item.needs_anim {
return;
Expand All @@ -36,6 +38,7 @@ fn update_anim_for_widget(
widget_state: state.item,
widget_state_children: state.children.reborrow_mut(),
widget_children: widget.children.reborrow_mut(),
properties_children: properties.children.reborrow_mut(),
};
widget.item.on_anim_frame(&mut ctx, elapsed_ns);
}
Expand All @@ -46,8 +49,15 @@ fn update_anim_for_widget(
id,
widget.reborrow_mut(),
state.children,
|widget, mut state| {
update_anim_for_widget(global_state, widget, state.reborrow_mut(), elapsed_ns);
properties.children,
|widget, mut state, properties| {
update_anim_for_widget(
global_state,
widget,
state.reborrow_mut(),
properties,
elapsed_ns,
);
parent_state.merge_up(state.item);
},
);
Expand All @@ -63,11 +73,13 @@ fn update_anim_for_widget(
pub(crate) fn run_update_anim_pass(root: &mut RenderRoot, elapsed_ns: u64) {
let _span = info_span!("update_anim").entered();

let (root_widget, mut root_state) = root.widget_arena.get_pair_mut(root.root.id());
let (root_widget, mut root_state, root_properties) =
root.widget_arena.get_all_mut(root.root.id());
update_anim_for_widget(
&mut root.global_state,
root_widget,
root_state.reborrow_mut(),
root_properties,
elapsed_ns,
);
}
9 changes: 7 additions & 2 deletions masonry/src/passes/compose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ fn compose_widget(
global_state: &mut RenderRootState,
mut widget: ArenaMut<'_, Box<dyn Widget>>,
mut state: ArenaMut<'_, WidgetState>,
mut properties: ArenaMut<'_, anymap3::AnyMap>,
parent_transformed: bool,
parent_window_transform: Affine,
) {
Expand All @@ -22,6 +23,7 @@ fn compose_widget(
global_state,
widget.reborrow(),
state.reborrow(),
properties.reborrow(),
);

let transformed = parent_transformed || state.item.transform_changed;
Expand Down Expand Up @@ -65,11 +67,13 @@ fn compose_widget(
id,
widget.reborrow_mut(),
state.children,
|widget, mut state| {
properties.children,
|widget, mut state, properties| {
compose_widget(
global_state,
widget,
state.reborrow_mut(),
properties,
transformed,
parent_transform,
);
Expand Down Expand Up @@ -103,11 +107,12 @@ pub(crate) fn run_compose_pass(root: &mut RenderRoot) {
root.global_state.needs_pointer_pass = true;
}

let (root_widget, root_state) = root.widget_arena.get_pair_mut(root.root.id());
let (root_widget, root_state, root_properties) = root.widget_arena.get_all_mut(root.root.id());
compose_widget(
&mut root.global_state,
root_widget,
root_state,
root_properties,
false,
Affine::IDENTITY,
);
Expand Down
5 changes: 4 additions & 1 deletion masonry/src/passes/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,22 @@ fn run_event_pass<E>(
let mut is_handled = false;
while let Some(widget_id) = target_widget_id {
let parent_id = root.widget_arena.parent_of(widget_id);
let (mut widget_mut, mut state_mut) = root.widget_arena.get_pair_mut(widget_id);
let (mut widget_mut, mut state_mut, mut properties_mut) =
root.widget_arena.get_all_mut(widget_id);

if !is_handled {
let _span = enter_span(
&root.global_state,
widget_mut.reborrow(),
state_mut.reborrow(),
properties_mut.reborrow(),
);
let mut ctx = EventCtx {
global_state: &mut root.global_state,
widget_state: state_mut.item,
widget_state_children: state_mut.children,
widget_children: widget_mut.children,
properties_children: properties_mut.children.reborrow_mut(),
target: original_target.unwrap(),
allow_pointer_capture,
is_handled: false,
Expand Down
9 changes: 8 additions & 1 deletion masonry/src/passes/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ pub(crate) fn run_layout_on<W: Widget + ?Sized>(
let id = pod.id();
let mut widget = parent_ctx.widget_children.item_mut(id).unwrap();
let mut state = parent_ctx.widget_state_children.item_mut(id).unwrap();
let mut properties = parent_ctx.properties_children.item_mut(id).unwrap();

let trace = parent_ctx.global_state.trace.layout;
let _span = enter_span_if(
trace,
parent_ctx.global_state,
widget.reborrow(),
state.reborrow(),
properties.reborrow(),
);

let mut children_ids = SmallVec::new();
Expand Down Expand Up @@ -86,7 +88,8 @@ pub(crate) fn run_layout_on<W: Widget + ?Sized>(
pod.id(),
widget.reborrow_mut(),
state.children.reborrow_mut(),
|_, state| {
properties.children.reborrow_mut(),
|_, state, _| {
if state.item.is_stashed {
state.item.needs_layout = false;
state.item.request_layout = false;
Expand All @@ -99,6 +102,7 @@ pub(crate) fn run_layout_on<W: Widget + ?Sized>(
widget_state: state.item,
widget_state_children: state.children.reborrow_mut(),
widget_children: widget.children,
properties_children: properties.children.reborrow_mut(),
global_state: parent_ctx.global_state,
};

Expand Down Expand Up @@ -206,11 +210,14 @@ pub(crate) fn run_layout_pass(root: &mut RenderRoot) {
let mut dummy_state = WidgetState::synthetic(root.root.id(), root.get_kurbo_size());
let root_state_token = root.widget_arena.states.roots_mut();
let root_widget_token = root.widget_arena.widgets.roots_mut();
let root_properties_token = root.widget_arena.properties.roots_mut();

let mut ctx = LayoutCtx {
global_state: &mut root.global_state,
widget_state: &mut dummy_state,
widget_state_children: root_state_token,
widget_children: root_widget_token,
properties_children: root_properties_token,
};

let size = run_layout_on(&mut ctx, &mut root.root, &bc);
Expand Down
Loading

0 comments on commit 3746736

Please sign in to comment.