Retain request dependencies only when discovery supplies the answer

This commit is contained in:
iris-ai committed 2026-09-20 17:31:53 -04:00
1 parent 8780b40bb7
commit 0e838e9dd1
7 files changed
+183 -50

No files matched your search

+38 -18
View File
@@ -87,29 +87,37 @@ impl<'a> Painter<'a> {
child: &StrongWidget<W>,
axis: Axis,
) -> Option<RequestedLen> {
self.request_deps.push(child.id());
if self.rsc.widgets().size_rules(child.id())[axis].bound() == crate::Bound::ANY
&& let Some(len) = self.size_hint(child, axis)
{
self.request_deps.push(child.id());
return Some(len.into());
}
let rel_base = self.rel_base(axis);
let start = self.request_deps.len();
let mut requests = SizeRequests {
arena: &mut self.state.requests,
measured: None,
widgets: self.rsc.widgets(),
dependencies: &mut self.request_deps,
rel_base,
rel_base: self.rel_base[axis],
};
let request = requests.widget(child, axis)?;
// An intrinsic fixed answer still draws in the offered room and is
// moved afterwards. Only a declaration or a share chooses its ask box.
(request.has_leftover()
|| matches!(
self.rsc.widgets().size_rules(child.id())[axis],
crate::SizeRule::Request(_)
))
.then_some(request)
// Intrinsic fixed content must keep its offered box for wrapping;
// only a declaration or a share chooses the box it is drawn in.
let request = requests.widget(child, axis).filter(|request| {
request.has_leftover()
|| matches!(
self.rsc.widgets().size_rules(child.id())[axis],
crate::SizeRule::Request(_)
)
});
if request.is_some() {
self.rel_base(axis);
} else {
// A discarded request contributes no dependency: the measured
// draw below records the size and box it actually used instead.
self.request_deps.truncate(start);
}
request
}
/// Completes discovery after a child was measured. Only this call may use
@@ -120,20 +128,32 @@ impl<'a> Painter<'a> {
axis: Axis,
len: LayoutLen,
) -> RequestedLen {
let rel_base = self.rel_base(axis);
let start = self.request_deps.len();
let bound = self.rsc.widgets().size_rules(child.id())[axis].bound();
let mut requests = SizeRequests {
arena: &mut self.state.requests,
measured: Some(&self.state.active),
widgets: self.rsc.widgets(),
dependencies: &mut self.request_deps,
rel_base,
rel_base: self.rel_base[axis],
};
match requests.widget(child, axis) {
Some(request) if request.linear().is_none() && request.has_leftover() => request,
_ if len.leftover > Weight::ZERO => requests.bounded(len.into(), bound),
_ => len.into(),
if let Some(request) = requests.widget(child, axis)
&& request.linear().is_none()
&& request.has_leftover()
{
self.rel_base(axis);
return request;
}
let request = if len.leftover > Weight::ZERO {
requests.bounded(len.into(), bound)
} else {
len.into()
};
self.request_deps.truncate(start);
if len.leftover > Weight::ZERO && bound != crate::Bound::ANY {
self.rel_base(axis);
}
request
}
/// A deferred comparison reads this window when the allocation is solved.
+1 -1
View File
@@ -429,7 +429,7 @@ impl UiRenderState {
// rel base is the answer wherever the ask declared a length: it was
// resolved into the rel base when the widget was asked, and resolving
// it again here would take the fraction of a fraction.
let rules = rsc.widgets().size_rules(id);
let rules = rsc.widgets().size_rules(id).clone();
let ruled = |axis: Axis, reported: LayoutLen| {
if matches!(rules[axis], crate::SizeRule::Request(_)) {
return info.rel_base[axis].into();
+2 -2
View File
@@ -128,8 +128,8 @@ impl Widgets {
}
/// The length rules whoever draws this widget applies to its box.
pub fn size_rules(&self, id: impl IdLike) -> SizeRules {
self.data(id).unwrap().size.clone()
pub fn size_rules(&self, id: impl IdLike) -> &SizeRules {
&self.data(id).unwrap().size
}
/// Sets one axis's rule. The widget is marked rather than its parent