Take a strong widget to depend on, and use the question mark

`depend_on_size` took a bare `WidgetId`, which any id at all satisfies.
It takes a `&StrongWidget` now, so `DrawResult` carries the handle it
was drawn from rather than an id copied out of it and nothing can claim
a dependency on a widget it does not hold.

`UiSpan::outside` matched on a pair of `Option`s where `?` says it. It
was written that way while the method was still `const`, and it is not.

No call site changed. Checked: fmt, clippy and 35 tests; `tabs`, `view`,
`minimal` and `text` render unchanged, and the live sway resize round
trip still matches a cold start at each size.
This commit is contained in:
iris-ai committed 2026-09-14 02:44:40 -04:00
1 parent 53e61289f5
commit 46547563c1
2 files changed
+24 -25

No files matched your search

+4 -4
View File
@@ -279,10 +279,10 @@ impl UiSpan {
}
pub fn outside(&self, parent: &Self) -> Option<Self> {
match (self.start.outside(parent), self.end.outside(parent)) {
(Some(start), Some(end)) => Some(Self { start, end }),
_ => None,
}
Some(Self {
start: self.start.outside(parent)?,
end: self.end.outside(parent)?,
})
}
pub const fn len(&self) -> UiScalar {
+20 -21
View File
@@ -71,34 +71,33 @@ impl<'a> Painter<'a> {
}
/// Draws a widget within this widget's region.
pub fn widget<W: ?Sized>(&mut self, id: &StrongWidget<W>) -> DrawResult<'_, 'a> {
pub fn widget<'s, W: ?Sized>(&'s mut self, id: &'s StrongWidget<W>) -> DrawResult<'s, 'a, W> {
self.widget_at(id, self.region)
}
/// Draws a widget somewhere within this one. Drawing one a second time
/// gives it a new box, keeping the drawing it already has where it can.
pub fn widget_within<W: ?Sized>(
&mut self,
id: &StrongWidget<W>,
pub fn widget_within<'s, W: ?Sized>(
&'s mut self,
id: &'s StrongWidget<W>,
region: UiRegion,
) -> DrawResult<'_, 'a> {
) -> DrawResult<'s, 'a, W> {
let region = region.within(&self.region);
self.widget_at(id, region)
}
fn widget_at<W: ?Sized>(
&mut self,
id: &StrongWidget<W>,
fn widget_at<'s, W: ?Sized>(
&'s mut self,
id: &'s StrongWidget<W>,
region: UiRegion,
) -> DrawResult<'_, 'a> {
let child = id.id();
) -> DrawResult<'s, 'a, W> {
// A child listed twice would be moved twice.
if !self.children.contains(&child) {
self.children.push(child);
if !self.children.contains(&id.id()) {
self.children.push(id.id());
}
let size = self.state.draw_inner(
self.layer,
child,
id.id(),
region,
Some(self.id),
self.mask,
@@ -106,7 +105,7 @@ impl<'a> Painter<'a> {
self.rsc,
);
DrawResult {
child,
child: id,
painter: self,
size,
}
@@ -116,13 +115,13 @@ impl<'a> Painter<'a> {
/// Asking counts as reading its size.
pub fn size_hint<W: ?Sized>(&mut self, id: &StrongWidget<W>, axis: Axis) -> Option<Len> {
let hint = self.rsc.widgets().get_dyn(id.id())?.size_hint(axis)?;
self.depend_on_size(id.id());
self.depend_on_size(id);
Some(hint)
}
fn depend_on_size(&mut self, child: WidgetId) {
if !self.size_deps.contains(&child) {
self.size_deps.push(child);
fn depend_on_size<W: ?Sized>(&mut self, child: &StrongWidget<W>) {
if !self.size_deps.contains(&child.id()) {
self.size_deps.push(child.id());
}
}
@@ -202,13 +201,13 @@ impl<'a> Painter<'a> {
/// A child that has just been drawn. Reading its size records that this
/// widget's own size depends on it; dropping it without reading draws the
/// child and leaves the parent independent of what it came to.
pub struct DrawResult<'p, 'a> {
pub struct DrawResult<'p, 'a, W: ?Sized> {
painter: &'p mut Painter<'a>,
child: WidgetId,
child: &'p StrongWidget<W>,
size: Size,
}
impl DrawResult<'_, '_> {
impl<W: ?Sized> DrawResult<'_, '_, W> {
pub fn size(self) -> Size {
self.painter.depend_on_size(self.child);
self.size