Skip to main content

inset_rendering/
object.rs

1//! Flutter counterpart: `rendering/object.dart` (`Constraints`, `ParentData`,
2//! `RenderObject` tree / layout / paint marks). `PaintingContext` is in
3//! `painting_context.rs`, `PipelineOwner` in `pipeline_owner.rs`.
4//!
5//! Semantics wait. A concrete node is [`RenderHandle<T>`] over the authored
6//! struct. A link to another node is the type-erased handle [`AnyRenderObject`].
7//! Authored methods take `self: RenderHandle<Self>`.
8
9use std::any::{Any, TypeId};
10use std::cell::Cell;
11use std::fmt::{self, Debug, Display};
12use std::hash::{Hash, Hasher};
13use std::ops::Receiver;
14use std::rc::Rc;
15use std::time::Duration;
16
17use inset_animation::Curve;
18use inset_embedder::{Matrix4, Offset, Rect};
19use inset_foundation::{App, Handle, HandleId};
20use inset_services::MouseTrackerAnnotation;
21
22use crate::layer::{
23    AnyContainerLayer, AnyOffsetLayer, ErasedLayer, LayerHandle, OffsetLayer, OffsetLayerMixin,
24};
25use crate::painting_context::PaintingContext;
26use crate::pipeline_owner::PipelineOwner;
27
28thread_local! {
29    static DEBUG_ACTIVE_LAYOUT: Cell<Option<AnyRenderObject>> = const { Cell::new(None) };
30    static DEBUG_ACTIVE_PAINT: Cell<Option<AnyRenderObject>> = const { Cell::new(None) };
31    static DEBUG_CHECKING_INTRINSICS: Cell<bool> = const { Cell::new(false) };
32}
33
34/// Whether the framework is currently checking a render object's intrinsic sizes, dry layout, or
35/// dry baseline against its real layout.
36///
37/// Flutter's `RenderObject.debugCheckingIntrinsics`. While this is true, an intrinsic
38/// computation neither caches its result nor throws where it cannot answer.
39pub fn debug_checking_intrinsics() -> bool {
40    DEBUG_CHECKING_INTRINSICS.get()
41}
42
43/// Sets [`debug_checking_intrinsics`].
44pub fn set_debug_checking_intrinsics(value: bool) {
45    DEBUG_CHECKING_INTRINSICS.set(value);
46}
47
48/// Immutable layout constraints.
49///
50/// Flutter's counterpart is the abstract `Constraints` class.
51pub trait Constraints {
52    /// Whether there is exactly one size possible given these constraints.
53    fn is_tight(&self) -> bool;
54
55    /// Whether the constraint is expressed in a consistent manner.
56    fn is_normalized(&self) -> bool;
57
58    /// Asserts that the constraints are valid.
59    ///
60    /// Returns the same as [`is_normalized`](Self::is_normalized) if asserts
61    /// are disabled.
62    fn debug_assert_is_valid(&self, is_applied_constraint: bool) -> bool {
63        let _ = is_applied_constraint;
64        debug_assert!(self.is_normalized());
65        self.is_normalized()
66    }
67}
68
69/// Data associated with a child by its parent.
70///
71/// Flutter's counterpart is the `ParentData` class. Subclasses are ordinary
72/// Rust types that implement this trait.
73pub trait ParentData: Any + Debug + Display {
74    /// Called when the render object is removed from the tree.
75    fn detach(&mut self) {}
76
77    /// The half of this parent data whose type is `id`, if it embeds one.
78    ///
79    /// Dart's `parentData as BoxParentData` and `parentData is KeepAliveParentDataMixin`: a
80    /// half answers for its own type, and a type that embeds one answers for its own type first
81    /// and then asks the half, so a chain of halves composes. Every box parent must answer
82    /// [`crate::BoxParentData`], or a child of it cannot be positioned by the box protocol.
83    fn provide(&self, id: TypeId) -> Option<&dyn Any> {
84        let _ = id;
85        None
86    }
87
88    /// See [`provide`](Self::provide); mirrors it exactly.
89    fn provide_mut(&mut self, id: TypeId) -> Option<&mut dyn Any> {
90        let _ = id;
91        None
92    }
93}
94
95impl dyn ParentData {
96    /// The `P` half of this parent data: [`provide`](ParentData::provide), typed.
97    pub fn part<P: 'static>(&self) -> Option<&P> {
98        self.provide(TypeId::of::<P>())?.downcast_ref()
99    }
100
101    /// The `P` half of this parent data, mutably: [`provide_mut`](ParentData::provide_mut), typed.
102    pub fn part_mut<P: 'static>(&mut self) -> Option<&mut P> {
103        self.provide_mut(TypeId::of::<P>())?.downcast_mut()
104    }
105}
106
107/// Flutter's `ParentData()` — no subclass fields.
108#[derive(Debug, Default)]
109pub struct EmptyParentData;
110
111impl ParentData for EmptyParentData {}
112
113impl Display for EmptyParentData {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        f.write_str("<none>")
116    }
117}
118
119/// Flutter's `RenderObject` fields.
120pub struct RenderObjectData {
121    /// The erased vtable, recorded by the protocol constructor (`RenderHandle::new_box`,
122    /// `RenderHandle::new_sliver`). Dart upcasts a subclass reference to `RenderObject` for
123    /// free; here the fat pointer has to be built, and only the protocol knows the table.
124    pub(crate) object_vtable: Option<&'static RenderObjectVTable>,
125    pub(crate) parent: Option<AnyRenderObject>,
126    pub(crate) owner: Option<Handle<PipelineOwner>>,
127    pub(crate) depth: i32,
128    pub(crate) parent_data: Option<Box<dyn ParentData>>,
129    pub(crate) needs_layout: bool,
130    pub(crate) needs_paint: bool,
131    pub(crate) needs_composited_layer_update: bool,
132    pub(crate) needs_compositing_bits_update: bool,
133    pub(crate) needs_compositing: bool,
134    pub(crate) was_repaint_boundary: bool,
135    /// Flutter's `_layerHandle`.
136    pub(crate) layer: LayerHandle<AnyContainerLayer>,
137    pub(crate) is_relayout_boundary: Option<bool>,
138    pub(crate) doing_this_layout_with_callback: bool,
139    pub(crate) debug_doing_this_layout: bool,
140    pub(crate) debug_doing_this_resize: bool,
141    pub(crate) debug_doing_this_paint: bool,
142    pub(crate) debug_can_parent_use_size: Option<bool>,
143    pub(crate) debug_mutations_locked: bool,
144}
145
146impl RenderObjectData {
147    /// Empty tree state for a newly constructed render object.
148    pub fn new() -> RenderObjectData {
149        RenderObjectData {
150            object_vtable: None,
151            parent: None,
152            owner: None,
153            depth: 0,
154            parent_data: None,
155            needs_layout: true,
156            needs_paint: true,
157            needs_composited_layer_update: false,
158            needs_compositing_bits_update: false,
159            needs_compositing: false,
160            was_repaint_boundary: false,
161            layer: LayerHandle::new(),
162            is_relayout_boundary: None,
163            doing_this_layout_with_callback: false,
164            debug_doing_this_layout: false,
165            debug_doing_this_resize: false,
166            debug_doing_this_paint: false,
167            debug_can_parent_use_size: None,
168            debug_mutations_locked: false,
169        }
170    }
171}
172
173impl Default for RenderObjectData {
174    fn default() -> RenderObjectData {
175        RenderObjectData::new()
176    }
177}
178
179/// Flutter's `RenderObjectWithChildMixin` child slot.
180pub struct RenderObjectWithChildData<C> {
181    pub(crate) child: Option<C>,
182}
183
184impl<C> RenderObjectWithChildData<C> {
185    /// No child.
186    pub const fn new() -> RenderObjectWithChildData<C> {
187        RenderObjectWithChildData { child: None }
188    }
189}
190
191impl<C> Default for RenderObjectWithChildData<C> {
192    fn default() -> RenderObjectWithChildData<C> {
193        RenderObjectWithChildData::new()
194    }
195}
196
197/// Flutter's `ContainerParentDataMixin` fields: the links of a doubly-linked child list.
198#[derive(Debug)]
199pub struct ContainerParentData<ChildType> {
200    pub(crate) previous_sibling: Option<ChildType>,
201    pub(crate) next_sibling: Option<ChildType>,
202}
203
204impl<ChildType> ContainerParentData<ChildType> {
205    /// No siblings.
206    pub const fn new() -> ContainerParentData<ChildType> {
207        ContainerParentData {
208            previous_sibling: None,
209            next_sibling: None,
210        }
211    }
212}
213
214impl<ChildType> Default for ContainerParentData<ChildType> {
215    fn default() -> ContainerParentData<ChildType> {
216        ContainerParentData::new()
217    }
218}
219
220/// Parent data to support a doubly-linked list of children.
221///
222/// The children can be traversed using [`next_sibling`](Self::next_sibling) or
223/// [`previous_sibling`](Self::previous_sibling), which can be called on the parent data of the
224/// render objects obtained via [`crate::ContainerRenderObjectMixin::first_child`] or
225/// [`crate::ContainerRenderObjectMixin::last_child`].
226///
227/// Flutter's `ContainerParentDataMixin`. The links live in a [`ContainerParentData`] field.
228pub trait ContainerParentDataMixin: ParentData {
229    /// The type-erased handle of a child in the list. `AnyRenderBox` for a box container.
230    type ChildType: Copy + PartialEq;
231
232    /// Mixin field access.
233    fn container_parent_data(&self) -> &ContainerParentData<Self::ChildType>;
234
235    /// See [`container_parent_data`](Self::container_parent_data).
236    fn container_parent_data_mut(&mut self) -> &mut ContainerParentData<Self::ChildType>;
237
238    /// The previous sibling in the parent's child list.
239    fn previous_sibling(&self) -> Option<Self::ChildType> {
240        self.container_parent_data().previous_sibling
241    }
242
243    /// Sets [`previous_sibling`](Self::previous_sibling).
244    fn set_previous_sibling(&mut self, value: Option<Self::ChildType>) {
245        self.container_parent_data_mut().previous_sibling = value;
246    }
247
248    /// The next sibling in the parent's child list.
249    fn next_sibling(&self) -> Option<Self::ChildType> {
250        self.container_parent_data().next_sibling
251    }
252
253    /// Sets [`next_sibling`](Self::next_sibling).
254    fn set_next_sibling(&mut self, value: Option<Self::ChildType>) {
255        self.container_parent_data_mut().next_sibling = value;
256    }
257
258    /// Clear the sibling pointers.
259    ///
260    /// The body of Flutter's `detach` override; call it from [`ParentData::detach`].
261    fn detach(&mut self) {
262        debug_assert!(
263            self.previous_sibling().is_none(),
264            "Pointers to siblings must be nulled before detaching ParentData."
265        );
266        debug_assert!(
267            self.next_sibling().is_none(),
268            "Pointers to siblings must be nulled before detaching ParentData."
269        );
270    }
271}
272
273/// Flutter's `ContainerRenderObjectMixin` fields: the head and tail of the child list, and its
274/// length.
275pub struct ContainerRenderObjectData<ChildType> {
276    pub(crate) child_count: usize,
277    pub(crate) first_child: Option<ChildType>,
278    pub(crate) last_child: Option<ChildType>,
279}
280
281impl<ChildType> ContainerRenderObjectData<ChildType> {
282    /// No children.
283    pub const fn new() -> ContainerRenderObjectData<ChildType> {
284        ContainerRenderObjectData {
285            child_count: 0,
286            first_child: None,
287            last_child: None,
288        }
289    }
290}
291
292impl<ChildType> Default for ContainerRenderObjectData<ChildType> {
293    fn default() -> ContainerRenderObjectData<ChildType> {
294        ContainerRenderObjectData::new()
295    }
296}
297
298/// An erased render object a parent can hold as a child: Dart's `ChildType extends RenderObject`
299/// type argument of `RenderObjectWithChildMixin` and `ContainerRenderObjectMixin`.
300///
301/// Implemented by [`crate::AnyRenderBox`] and [`crate::AnyRenderSliver`].
302pub trait ErasedRenderObject: Copy + PartialEq + Debug + 'static {
303    /// The `RenderObject` view of this handle.
304    fn as_object(self) -> AnyRenderObject;
305
306    /// Dart's implicit downcast of a `RenderObject` to `ChildType`.
307    ///
308    /// # Panics
309    ///
310    /// If `object` does not use this protocol.
311    fn from_object(object: AnyRenderObject) -> Self;
312}
313
314/// A render object with a single child.
315///
316/// Flutter's `RenderObjectWithChildMixin`. The child slot lives in a
317/// [`RenderObjectWithChildData`] field.
318pub trait RenderObjectWithChildMixin: RenderObject {
319    /// Flutter's `ChildType`: the protocol of this render object's child.
320    type ChildType: ErasedRenderObject;
321
322    /// Mixin field access.
323    fn child_data(
324        self: RenderHandle<Self>,
325        app: &App,
326    ) -> &RenderObjectWithChildData<Self::ChildType>;
327
328    /// See [`child_data`](Self::child_data).
329    fn child_data_mut(
330        self: RenderHandle<Self>,
331        app: &mut App,
332    ) -> &mut RenderObjectWithChildData<Self::ChildType>;
333
334    /// The render object's unique child.
335    fn child(self: RenderHandle<Self>, app: &App) -> Option<Self::ChildType> {
336        self.child_data(app).child
337    }
338
339    /// Sets the unique child, adopting or dropping as Flutter's setter does.
340    fn set_child(self: RenderHandle<Self>, app: &mut App, value: Option<Self::ChildType>) {
341        if let Some(old) = self.child(app) {
342            self.as_render_object(app).drop_child(app, old.as_object());
343        }
344        self.child_data_mut(app).child = value;
345        if let Some(new) = value {
346            self.as_render_object(app).adopt_child(app, new.as_object());
347        }
348    }
349}
350
351/// Generic mixin for render objects with a list of children.
352///
353/// Provides a child model for a render object that has a doubly-linked list of children.
354///
355/// [`ParentDataType`](ContainerRenderObjectMixin::ParentDataType) stores parent container data
356/// on its child render objects. It must be a [`ContainerParentDataMixin`], which provides the
357/// interface for visiting children. This data is populated by the `setup_parent_data`
358/// implemented by the render object using this mixin.
359///
360/// Flutter's `ContainerRenderObjectMixin`. Its two type arguments are the associated types
361/// [`ChildType`](ContainerRenderObjectMixin::ChildType) and
362/// [`ParentDataType`](ContainerRenderObjectMixin::ParentDataType).
363pub trait ContainerRenderObjectMixin: RenderObject {
364    /// Flutter's `ChildType`: the protocol of this render object's children.
365    type ChildType: ErasedRenderObject;
366
367    /// Flutter's `ParentDataType`: the parent data this render object installs on its children.
368    type ParentDataType: ContainerParentDataMixin<ChildType = Self::ChildType> + 'static;
369
370    /// Mixin field access.
371    fn container_data(
372        self: RenderHandle<Self>,
373        app: &App,
374    ) -> &ContainerRenderObjectData<Self::ChildType>;
375
376    /// See [`container_data`](Self::container_data).
377    fn container_data_mut(
378        self: RenderHandle<Self>,
379        app: &mut App,
380    ) -> &mut ContainerRenderObjectData<Self::ChildType>;
381
382    /// The number of children.
383    fn child_count(self: RenderHandle<Self>, app: &App) -> usize {
384        self.container_data(app).child_count
385    }
386
387    /// Insert child into this render object's child list after the given child.
388    ///
389    /// If `after` is `None`, then this inserts the child at the start of the list, and the child
390    /// becomes the new [`first_child`](Self::first_child).
391    fn insert(
392        self: RenderHandle<Self>,
393        app: &mut App,
394        child: Self::ChildType,
395        after: Option<Self::ChildType>,
396    ) {
397        ContainerRenderObjectBase::insert(self, app, child, after)
398    }
399
400    /// Append child to the end of this render object's child list.
401    fn add(self: RenderHandle<Self>, app: &mut App, child: Self::ChildType) {
402        let last_child = self.last_child(app);
403        self.insert(app, child, last_child);
404    }
405
406    /// Add all the children to the end of this render object's child list.
407    fn add_all(self: RenderHandle<Self>, app: &mut App, children: Option<Vec<Self::ChildType>>) {
408        for child in children.into_iter().flatten() {
409            self.add(app, child);
410        }
411    }
412
413    /// Remove this child from the child list.
414    ///
415    /// Requires the child to be present in the child list.
416    fn remove(self: RenderHandle<Self>, app: &mut App, child: Self::ChildType) {
417        ContainerRenderObjectBase::remove(self, app, child)
418    }
419
420    /// Remove all their children from this render object's child list.
421    ///
422    /// More efficient than removing them individually.
423    fn remove_all(self: RenderHandle<Self>, app: &mut App) {
424        ContainerRenderObjectBase::remove_all(self, app)
425    }
426
427    /// Move the given `child` in the child list to be after another child.
428    ///
429    /// Dart's `move`. More efficient than removing and re-adding the child. Requires the child
430    /// to already be in the child list at some position. Pass `None` for `after` to move the
431    /// child to the start of the child list.
432    fn move_child(
433        self: RenderHandle<Self>,
434        app: &mut App,
435        child: Self::ChildType,
436        after: Option<Self::ChildType>,
437    ) {
438        ContainerRenderObjectBase::move_child(self, app, child, after)
439    }
440
441    /// The body of Flutter's `attach` override: attaches every child in the list.
442    fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
443        let mut child = self.first_child(app);
444        while let Some(current) = child {
445            current.as_object().attach(app, owner);
446            child = current
447                .as_object()
448                .parent_data_of::<Self::ParentDataType>(app)
449                .next_sibling();
450        }
451    }
452
453    /// The body of Flutter's `detach` override: detaches every child in the list.
454    fn did_detach(self: RenderHandle<Self>, app: &mut App) {
455        let mut child = self.first_child(app);
456        while let Some(current) = child {
457            current.as_object().detach(app);
458            child = current
459                .as_object()
460                .parent_data_of::<Self::ParentDataType>(app)
461                .next_sibling();
462        }
463    }
464
465    /// Flutter's `redepthChildren`: walks the child list.
466    fn redepth_children(self: RenderHandle<Self>, app: &mut App) {
467        let mut child = self.first_child(app);
468        while let Some(current) = child {
469            self.as_render_object(app)
470                .redepth_child(app, current.as_object());
471            child = current
472                .as_object()
473                .parent_data_of::<Self::ParentDataType>(app)
474                .next_sibling();
475        }
476    }
477
478    /// Flutter's `visitChildren`: walks the child list.
479    fn visit_children(
480        self: RenderHandle<Self>,
481        app: &App,
482        visitor: &mut dyn FnMut(AnyRenderObject),
483    ) {
484        let mut child = self.first_child(app);
485        while let Some(current) = child {
486            visitor(current.as_object());
487            child = current
488                .as_object()
489                .parent_data_of::<Self::ParentDataType>(app)
490                .next_sibling();
491        }
492    }
493
494    /// The first child in the child list.
495    fn first_child(self: RenderHandle<Self>, app: &App) -> Option<Self::ChildType> {
496        self.container_data(app).first_child
497    }
498
499    /// The last child in the child list.
500    fn last_child(self: RenderHandle<Self>, app: &App) -> Option<Self::ChildType> {
501        self.container_data(app).last_child
502    }
503
504    /// The previous child before the given child in the child list.
505    fn child_before(
506        self: RenderHandle<Self>,
507        app: &App,
508        child: Self::ChildType,
509    ) -> Option<Self::ChildType> {
510        debug_assert_eq!(
511            child.as_object().parent(app),
512            Some(self.as_render_object(app))
513        );
514        child
515            .as_object()
516            .parent_data_of::<Self::ParentDataType>(app)
517            .previous_sibling()
518    }
519
520    /// The next child after the given child in the child list.
521    fn child_after(
522        self: RenderHandle<Self>,
523        app: &App,
524        child: Self::ChildType,
525    ) -> Option<Self::ChildType> {
526        debug_assert_eq!(
527            child.as_object().parent(app),
528            Some(self.as_render_object(app))
529        );
530        child
531            .as_object()
532            .parent_data_of::<Self::ParentDataType>(app)
533            .next_sibling()
534    }
535
536    /// Returns a list containing the children of this render object.
537    ///
538    /// Dart's `RenderBoxContainerDefaultsMixin.getChildrenAsList`, useful for any container.
539    fn children_as_list(self: RenderHandle<Self>, app: &App) -> Vec<Self::ChildType> {
540        let mut result = Vec::new();
541        let mut child = self.first_child(app);
542        while let Some(current) = child {
543            result.push(current);
544            child = current
545                .as_object()
546                .parent_data_of::<Self::ParentDataType>(app)
547                .next_sibling();
548        }
549        result
550    }
551}
552
553/// Flutter's `ContainerRenderObjectMixin` bodies that an override calls through `super`.
554///
555/// Blanket-implemented for every container, and repeats the default bodies of the four child-list
556/// mutators: a leaf's own override shadows the default it would otherwise call.
557pub trait ContainerRenderObjectBase: ContainerRenderObjectMixin {
558    /// Flutter's `ContainerRenderObjectMixin.insert`.
559    fn insert(
560        self: RenderHandle<Self>,
561        app: &mut App,
562        child: Self::ChildType,
563        after: Option<Self::ChildType>,
564    ) {
565        debug_assert!(
566            child.as_object() != self.as_render_object(app),
567            "A RenderObject cannot be inserted into itself."
568        );
569        debug_assert!(
570            after.is_none_or(|after| after.as_object() != self.as_render_object(app)),
571            "A RenderObject cannot simultaneously be both the parent and the sibling of another \
572             RenderObject."
573        );
574        debug_assert!(
575            after != Some(child),
576            "A RenderObject cannot be inserted after itself."
577        );
578        debug_assert!(Some(child) != self.first_child(app));
579        debug_assert!(Some(child) != self.last_child(app));
580        self.as_render_object(app)
581            .adopt_child(app, child.as_object());
582        debug_assert!(
583            child
584                .as_object()
585                .parent_data_is::<Self::ParentDataType>(app),
586            "A child has parent data that does not conform to this render object's \
587             ParentDataType. Override setup_parent_data to install it."
588        );
589        insert_into_child_list(self, app, child, after);
590    }
591
592    /// Flutter's `ContainerRenderObjectMixin.remove`.
593    fn remove(self: RenderHandle<Self>, app: &mut App, child: Self::ChildType) {
594        remove_from_child_list(self, app, child);
595        self.as_render_object(app)
596            .drop_child(app, child.as_object());
597    }
598
599    /// Flutter's `ContainerRenderObjectMixin.removeAll`.
600    fn remove_all(self: RenderHandle<Self>, app: &mut App) {
601        let mut child = self.first_child(app);
602        while let Some(current) = child {
603            let child_parent_data = current
604                .as_object()
605                .parent_data_of_mut::<Self::ParentDataType>(app);
606            let next = child_parent_data.next_sibling();
607            child_parent_data.set_previous_sibling(None);
608            child_parent_data.set_next_sibling(None);
609            self.as_render_object(app)
610                .drop_child(app, current.as_object());
611            child = next;
612        }
613        let container = self.container_data_mut(app);
614        container.first_child = None;
615        container.last_child = None;
616        container.child_count = 0;
617    }
618
619    /// Flutter's `ContainerRenderObjectMixin.move`.
620    fn move_child(
621        self: RenderHandle<Self>,
622        app: &mut App,
623        child: Self::ChildType,
624        after: Option<Self::ChildType>,
625    ) {
626        debug_assert!(child.as_object() != self.as_render_object(app));
627        debug_assert!(after.is_none_or(|after| after.as_object() != self.as_render_object(app)));
628        debug_assert!(after != Some(child));
629        debug_assert_eq!(
630            child.as_object().parent(app),
631            Some(self.as_render_object(app)),
632            "the child must already be a child of this render object"
633        );
634        if child
635            .as_object()
636            .parent_data_of::<Self::ParentDataType>(app)
637            .previous_sibling()
638            == after
639        {
640            return;
641        }
642        remove_from_child_list(self, app, child);
643        insert_into_child_list(self, app, child, after);
644        self.as_render_object(app).mark_needs_layout(app);
645    }
646}
647
648impl<T: ContainerRenderObjectMixin> ContainerRenderObjectBase for T {}
649
650/// Flutter's `_debugUltimatePreviousSiblingOf`.
651fn debug_ultimate_previous_sibling_of<P>(
652    app: &App,
653    child: P::ChildType,
654    equals: Option<P::ChildType>,
655) -> bool
656where
657    P: ContainerParentDataMixin + 'static,
658    P::ChildType: ErasedRenderObject,
659{
660    let mut child = child;
661    while let Some(previous) = child
662        .as_object()
663        .parent_data_of::<P>(app)
664        .previous_sibling()
665    {
666        debug_assert!(previous != child);
667        child = previous;
668    }
669    Some(child) == equals
670}
671
672/// Flutter's `_debugUltimateNextSiblingOf`.
673fn debug_ultimate_next_sibling_of<P>(
674    app: &App,
675    child: P::ChildType,
676    equals: Option<P::ChildType>,
677) -> bool
678where
679    P: ContainerParentDataMixin + 'static,
680    P::ChildType: ErasedRenderObject,
681{
682    let mut child = child;
683    while let Some(next) = child.as_object().parent_data_of::<P>(app).next_sibling() {
684        debug_assert!(next != child);
685        child = next;
686    }
687    Some(child) == equals
688}
689
690/// Flutter's `_insertIntoChildList`.
691fn insert_into_child_list<T: ContainerRenderObjectMixin>(
692    this: RenderHandle<T>,
693    app: &mut App,
694    child: T::ChildType,
695    after: Option<T::ChildType>,
696) {
697    type ParentDataOf<T> = <T as ContainerRenderObjectMixin>::ParentDataType;
698
699    debug_assert!(
700        child
701            .as_object()
702            .parent_data_of::<ParentDataOf<T>>(app)
703            .next_sibling()
704            .is_none()
705    );
706    debug_assert!(
707        child
708            .as_object()
709            .parent_data_of::<ParentDataOf<T>>(app)
710            .previous_sibling()
711            .is_none()
712    );
713    this.container_data_mut(app).child_count += 1;
714    let Some(after) = after else {
715        // insert at the start (first_child)
716        let first_child = this.first_child(app);
717        child
718            .as_object()
719            .parent_data_of_mut::<ParentDataOf<T>>(app)
720            .set_next_sibling(first_child);
721        if let Some(first_child) = first_child {
722            first_child
723                .as_object()
724                .parent_data_of_mut::<ParentDataOf<T>>(app)
725                .set_previous_sibling(Some(child));
726        }
727        let container = this.container_data_mut(app);
728        container.first_child = Some(child);
729        container.last_child.get_or_insert(child);
730        return;
731    };
732    debug_assert!(this.first_child(app).is_some());
733    debug_assert!(this.last_child(app).is_some());
734    debug_assert!(debug_ultimate_previous_sibling_of::<ParentDataOf<T>>(
735        app,
736        after,
737        this.first_child(app)
738    ));
739    debug_assert!(debug_ultimate_next_sibling_of::<ParentDataOf<T>>(
740        app,
741        after,
742        this.last_child(app)
743    ));
744    let after_next_sibling = after
745        .as_object()
746        .parent_data_of::<ParentDataOf<T>>(app)
747        .next_sibling();
748    let Some(after_next_sibling) = after_next_sibling else {
749        // insert at the end (last_child); we'll end up with two or more children
750        debug_assert_eq!(Some(after), this.last_child(app));
751        child
752            .as_object()
753            .parent_data_of_mut::<ParentDataOf<T>>(app)
754            .set_previous_sibling(Some(after));
755        after
756            .as_object()
757            .parent_data_of_mut::<ParentDataOf<T>>(app)
758            .set_next_sibling(Some(child));
759        this.container_data_mut(app).last_child = Some(child);
760        return;
761    };
762    // insert in the middle; we'll end up with three or more children
763    // set up links from child to siblings
764    let child_parent_data = child.as_object().parent_data_of_mut::<ParentDataOf<T>>(app);
765    child_parent_data.set_next_sibling(Some(after_next_sibling));
766    child_parent_data.set_previous_sibling(Some(after));
767    // set up links from siblings to child
768    after
769        .as_object()
770        .parent_data_of_mut::<ParentDataOf<T>>(app)
771        .set_next_sibling(Some(child));
772    after_next_sibling
773        .as_object()
774        .parent_data_of_mut::<ParentDataOf<T>>(app)
775        .set_previous_sibling(Some(child));
776}
777
778/// Flutter's `_removeFromChildList`.
779fn remove_from_child_list<T: ContainerRenderObjectMixin>(
780    this: RenderHandle<T>,
781    app: &mut App,
782    child: T::ChildType,
783) {
784    type ParentDataOf<T> = <T as ContainerRenderObjectMixin>::ParentDataType;
785
786    debug_assert!(debug_ultimate_previous_sibling_of::<ParentDataOf<T>>(
787        app,
788        child,
789        this.first_child(app)
790    ));
791    debug_assert!(debug_ultimate_next_sibling_of::<ParentDataOf<T>>(
792        app,
793        child,
794        this.last_child(app)
795    ));
796    let child_parent_data = child.as_object().parent_data_of::<ParentDataOf<T>>(app);
797    let (previous_sibling, next_sibling) = (
798        child_parent_data.previous_sibling(),
799        child_parent_data.next_sibling(),
800    );
801    match previous_sibling {
802        None => {
803            debug_assert_eq!(this.first_child(app), Some(child));
804            this.container_data_mut(app).first_child = next_sibling;
805        }
806        Some(previous_sibling) => previous_sibling
807            .as_object()
808            .parent_data_of_mut::<ParentDataOf<T>>(app)
809            .set_next_sibling(next_sibling),
810    }
811    match next_sibling {
812        None => {
813            debug_assert_eq!(this.last_child(app), Some(child));
814            this.container_data_mut(app).last_child = previous_sibling;
815        }
816        Some(next_sibling) => next_sibling
817            .as_object()
818            .parent_data_of_mut::<ParentDataOf<T>>(app)
819            .set_previous_sibling(previous_sibling),
820    }
821    let child_parent_data = child.as_object().parent_data_of_mut::<ParentDataOf<T>>(app);
822    child_parent_data.set_previous_sibling(None);
823    child_parent_data.set_next_sibling(None);
824    this.container_data_mut(app).child_count -= 1;
825}
826
827/// Class-specific render object: the data accessors and the virtuals, nothing else. Methods
828/// take [`RenderHandle<Self>`] so they can re-enter the same slot through [`App`].
829///
830/// Tree operations (`mark_needs_layout`, `adopt_child`, `parent`, …) live on the erased
831/// [`AnyRenderObject`]; a typed handle reaches them through its protocol trait,
832/// [`crate::RenderBox`] or [`crate::RenderSliver`].
833pub trait RenderObject: 'static + Sized {
834    /// Mixin field access.
835    fn render_object_data(self: RenderHandle<Self>, app: &App) -> &RenderObjectData;
836
837    /// See [`render_object_data`](Self::render_object_data).
838    fn render_object_data_mut(self: RenderHandle<Self>, app: &mut App) -> &mut RenderObjectData;
839
840    /// Dart's implicit upcast of a concrete render object to `RenderObject`: this object's
841    /// type-erased handle, through the vtable the protocol recorded when it created it.
842    fn as_render_object(self: RenderHandle<Self>, app: &App) -> AnyRenderObject {
843        let vtable = self
844            .render_object_data(app)
845            .object_vtable
846            .expect("a render object records its vtable when the protocol creates it");
847        AnyRenderObject::from_vtable(self.id(), vtable)
848    }
849
850    /// Do the work of computing the layout for this render object.
851    ///
852    /// Do not call this function directly: call `layout` on the protocol handle instead.
853    /// Read the constraints with `constraints` on the protocol trait.
854    fn perform_layout(self: RenderHandle<Self>, app: &mut App);
855
856    /// Updates the render object's size using only the constraints.
857    ///
858    /// Called by `layout` only when [`sized_by_parent`](Self::sized_by_parent) is true.
859    ///
860    /// A box overrides [`crate::RenderBox::compute_dry_layout`] instead: the box protocol's
861    /// [`crate::RenderBox::perform_resize`] sizes itself from it.
862    fn perform_resize(self: RenderHandle<Self>, _app: &mut App) {
863        let _ = self;
864        panic!("RenderObject::perform_resize was called; override it when sized_by_parent is true")
865    }
866
867    /// Calls `visitor` for each immediate child.
868    fn visit_children(
869        self: RenderHandle<Self>,
870        app: &App,
871        visitor: &mut dyn FnMut(AnyRenderObject),
872    ) {
873        let _ = (self, app, visitor);
874    }
875
876    /// Sets up parent data for `child` if it has none.
877    ///
878    /// For a box, override [`crate::RenderBox::setup_parent_data`] instead; an implementation
879    /// here is not called for boxes.
880    fn setup_parent_data(self: RenderHandle<Self>, app: &mut App, child: AnyRenderObject) {
881        if child.parent_data(app).is_none() {
882            child.set_parent_data(app, EmptyParentData);
883        }
884    }
885
886    /// The body of Flutter's `attach` override after `super.attach(owner)`; the base body has
887    /// already run. The default attaches the children reported by
888    /// [`visit_children`](Self::visit_children).
889    fn did_attach(self: RenderHandle<Self>, app: &mut App, owner: Handle<PipelineOwner>) {
890        for child in collect_children(app, self) {
891            child.attach(app, owner);
892        }
893    }
894
895    /// The body of Flutter's `detach` override after `super.detach()`. The default detaches
896    /// the children reported by [`visit_children`](Self::visit_children).
897    fn did_detach(self: RenderHandle<Self>, app: &mut App) {
898        for child in collect_children(app, self) {
899            child.detach(app);
900        }
901    }
902
903    /// Adjusts the depth of each child reported by [`visit_children`](Self::visit_children).
904    fn redepth_children(self: RenderHandle<Self>, app: &mut App) {
905        let depth = self.render_object_data(app).depth;
906        let owner = self.render_object_data(app).owner;
907        for child in collect_children(app, self) {
908            debug_assert_eq!(child.owner(app), owner);
909            child.redepth_below(app, depth);
910        }
911    }
912
913    /// Whether the constraints are the only input to the sizing algorithm.
914    fn sized_by_parent(self: RenderHandle<Self>, _app: &App) -> bool {
915        let _ = self;
916        false
917    }
918
919    /// Applies the transform that would be applied when painting the given child to the
920    /// given matrix.
921    ///
922    /// Used by coordinate conversion functions ([`AnyRenderObject::get_transform_to`]) to
923    /// translate coordinates local to one render object into coordinates local to another
924    /// render object.
925    ///
926    /// Some RenderObjects will provide a zeroed out matrix in this method, indicating that
927    /// the child should not paint anything or respond to hit tests currently. A parent may
928    /// supply a non-zero matrix even if it does not paint its child currently, for example
929    /// if the parent is a `RenderOffstage` with `offstage` set to true. In both of these
930    /// cases, the parent must return `false` from `paintsChild`.
931    ///
932    /// The box protocol's default translates by the child's `BoxParentData` offset; this
933    /// object-level default only asserts, as Dart's `RenderObject.applyPaintTransform`.
934    fn apply_paint_transform(
935        self: RenderHandle<Self>,
936        app: &App,
937        child: AnyRenderObject,
938        transform: &mut Matrix4,
939    ) {
940        let _ = transform;
941        debug_assert!(child.parent(app).map(AnyRenderObject::id) == Some(self.id()));
942    }
943
944    /// Whether this render object repaints separately from its parent.
945    ///
946    /// Override this in subclasses to indicate that instances of your class ought
947    /// to repaint independently. For example, render objects that repaint
948    /// frequently might want to repaint themselves without requiring their parent
949    /// to repaint.
950    ///
951    /// If this getter returns true, the [`paint_bounds`](Self::paint_bounds) are applied to this
952    /// object and all descendants. The framework invokes
953    /// [`update_composited_layer`](Self::update_composited_layer) to create an [`OffsetLayer`]
954    /// and assigns it to the [`layer`](AnyRenderObject::layer) field.
955    /// Render objects that declare themselves as repaint boundaries must not replace
956    /// the layer created by the framework.
957    ///
958    /// If the value of this getter changes, [`AnyRenderObject::mark_needs_compositing_bits_update`]
959    /// must be called.
960    fn is_repaint_boundary(self: RenderHandle<Self>, _app: &App) -> bool {
961        let _ = self;
962        false
963    }
964
965    /// Whether this render object always needs compositing.
966    ///
967    /// Override this in subclasses to indicate that your paint function always
968    /// creates at least one composited layer. For example, videos should return
969    /// true if they use hardware decoders.
970    ///
971    /// You must call [`AnyRenderObject::mark_needs_compositing_bits_update`] if the value of this
972    /// getter changes. (This is implied when [`AnyRenderObject::adopt_child`] or
973    /// [`AnyRenderObject::drop_child`] are called.)
974    fn always_needs_compositing(self: RenderHandle<Self>, _app: &App) -> bool {
975        let _ = self;
976        false
977    }
978
979    /// Dart's `this is MouseTrackerAnnotation`: the annotation this render object implements,
980    /// read live each time the mouse tracker consults it. `None` for a render object that is
981    /// not an annotation, which is the default.
982    fn mouse_tracker_annotation(
983        self: RenderHandle<Self>,
984        _app: &App,
985    ) -> Option<MouseTrackerAnnotation> {
986        let _ = self;
987        None
988    }
989
990    /// Update the composited layer owned by this render object.
991    ///
992    /// This method is called by the framework when [`is_repaint_boundary`](Self::is_repaint_boundary)
993    /// is true.
994    ///
995    /// If `old_layer` is `None`, this method must return a new [`OffsetLayer`]
996    /// (or subtype thereof). If `old_layer` is not `None`, then this method must
997    /// reuse the layer instance that is provided — it is an error to create a new
998    /// layer in this instance. The layer will be disposed by the framework when
999    /// either the render object is disposed or if it is no longer a repaint
1000    /// boundary.
1001    ///
1002    /// The [`OffsetLayerMixin::offset`](crate::OffsetLayerMixin::offset) property will be managed
1003    /// by the framework and must not be updated by this method.
1004    ///
1005    /// If a property of the composited layer needs to be updated, the render object
1006    /// must call [`AnyRenderObject::mark_needs_composited_layer_update`] which will schedule this
1007    /// method to be called without repainting children. If this widget was marked as
1008    /// needing to paint and needing a composited layer update, this method is only
1009    /// called once.
1010    fn update_composited_layer(
1011        self: RenderHandle<Self>,
1012        app: &mut App,
1013        old_layer: Option<AnyOffsetLayer>,
1014    ) -> AnyOffsetLayer {
1015        debug_assert!(self.is_repaint_boundary(app));
1016        old_layer.unwrap_or_else(|| OffsetLayer::new(app, Offset::ZERO).as_offset_layer())
1017    }
1018
1019    /// Attempt to make (a portion of) this or a descendant [`RenderObject`] visible on screen.
1020    ///
1021    /// If `descendant` is provided, that render object is made visible. If `descendant` is
1022    /// omitted, this render object is made visible.
1023    ///
1024    /// The optional `rect` parameter describes which area of that render object should be
1025    /// shown on screen. If `rect` is `None`, the entire render object (as defined by its
1026    /// paint bounds) will be revealed. The `rect` parameter is interpreted relative to the
1027    /// coordinate system of `descendant` if that argument is provided and relative to this
1028    /// render object otherwise.
1029    ///
1030    /// The `duration` parameter can be set to a non-zero value to bring the target object on
1031    /// screen in an animation defined by `curve`.
1032    ///
1033    /// See also:
1034    ///
1035    /// * [`crate::show_in_viewport`], which `RenderViewportBase` delegates
1036    ///   this method to.
1037    fn show_on_screen(
1038        self: RenderHandle<Self>,
1039        app: &mut App,
1040        descendant: Option<AnyRenderObject>,
1041        rect: Option<Rect>,
1042        duration: Duration,
1043        curve: Rc<dyn Curve>,
1044    ) {
1045        RenderObjectBase::show_on_screen(self, app, descendant, rect, duration, curve)
1046    }
1047
1048    /// Dart's `object is RenderAbstractViewport` for any interface: the erased handle of the
1049    /// interface `id` names, if this type implements it.
1050    ///
1051    /// An implementor answers each interface it implements with that interface's type-erased
1052    /// handle, boxed; [`AnyRenderObject::interface`] unboxes it. The default implements none.
1053    fn interface(self: RenderHandle<Self>, id: TypeId) -> Option<Box<dyn Any>> {
1054        let _ = (self, id);
1055        None
1056    }
1057
1058    /// Release any resources held by this render object.
1059    ///
1060    /// The object that creates a [`RenderObject`] is in charge of disposing it. If this render
1061    /// object has created any children directly, it must dispose of those children in this method
1062    /// as well. It must not dispose of any children that were created by some other object, such
1063    /// as a `RenderObjectElement`. Those children will be disposed when that element unmounts,
1064    /// which may be delayed if the element is moved to another part of the tree.
1065    ///
1066    /// Implementations of this method must end with a call to the inherited method,
1067    /// `RenderObjectBase::dispose(self, app)`, as in Dart's `super.dispose()`.
1068    ///
1069    /// The object is no longer usable after calling dispose. The arena has no collector, so
1070    /// [`AnyRenderObject::dispose`] destroys the slot after this hook returns.
1071    fn dispose(self: RenderHandle<Self>, app: &mut App) {
1072        RenderObjectBase::dispose(self, app);
1073    }
1074
1075    /// Paint this render object into the given context at the given offset.
1076    ///
1077    /// Do not call this function directly: [`PaintingContext::paint_child`] does. Paint children
1078    /// with `context.paint_child(app, child, offset + child_offset)`; do not use the canvas to
1079    /// translate, and do not use it after painting a child.
1080    fn paint(
1081        self: RenderHandle<Self>,
1082        app: &mut App,
1083        context: &mut PaintingContext,
1084        offset: Offset,
1085    ) {
1086        let _ = (self, app, context, offset);
1087    }
1088}
1089
1090fn collect_children<T: RenderObject>(app: &App, this: RenderHandle<T>) -> Vec<AnyRenderObject> {
1091    let mut children = Vec::new();
1092    this.visit_children(app, &mut |child| children.push(child));
1093    children
1094}
1095
1096/// Implements the [`RenderObject`] field accessors for a `render_object` field.
1097#[macro_export]
1098macro_rules! render_object_accessors {
1099    () => {
1100        fn render_object_data(
1101            self: $crate::RenderHandle<Self>,
1102            app: &::inset_foundation::App,
1103        ) -> &$crate::RenderObjectData {
1104            &self.get(app).render_object
1105        }
1106        fn render_object_data_mut(
1107            self: $crate::RenderHandle<Self>,
1108            app: &mut ::inset_foundation::App,
1109        ) -> &mut $crate::RenderObjectData {
1110            &mut self.get_mut(app).render_object
1111        }
1112    };
1113}
1114
1115/// Typed access to a concrete render object's class-specific state.
1116///
1117/// [`get`](Self::get) / [`get_mut`](Self::get_mut) are point access: drop the
1118/// borrow before any call that can re-enter this slot.
1119pub struct RenderHandle<T>(Handle<T>);
1120
1121impl<T> Clone for RenderHandle<T> {
1122    fn clone(&self) -> RenderHandle<T> {
1123        *self
1124    }
1125}
1126
1127impl<T> Copy for RenderHandle<T> {}
1128
1129impl<T> Receiver for RenderHandle<T> {
1130    type Target = T;
1131}
1132
1133impl<T> PartialEq for RenderHandle<T> {
1134    fn eq(&self, other: &RenderHandle<T>) -> bool {
1135        self.0 == other.0
1136    }
1137}
1138
1139impl<T> Eq for RenderHandle<T> {}
1140
1141impl<T> Hash for RenderHandle<T> {
1142    fn hash<H: Hasher>(&self, state: &mut H) {
1143        self.0.hash(state);
1144    }
1145}
1146
1147impl<T> Debug for RenderHandle<T> {
1148    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1149        write!(
1150            f,
1151            "RenderHandle<{}>({:?})",
1152            std::any::type_name::<T>(),
1153            self.0.id()
1154        )
1155    }
1156}
1157
1158impl<T: 'static> RenderHandle<T> {
1159    /// The concrete state. Drop the borrow before a virtual call.
1160    pub fn get(self, app: &App) -> &T {
1161        app.get(self.0)
1162    }
1163
1164    /// See [`get`](Self::get).
1165    pub fn get_mut(self, app: &mut App) -> &mut T {
1166        app.get_mut(self.0)
1167    }
1168
1169    pub(crate) fn id(self) -> HandleId {
1170        self.0.id()
1171    }
1172
1173    /// The foundation handle, for a [`inset_foundation::Listener::handle_method`] tear-off.
1174    pub fn handle(self) -> Handle<T> {
1175        self.0
1176    }
1177
1178    /// The render handle for a foundation handle, which is what such a tear-off is called with.
1179    pub fn from_handle(handle: Handle<T>) -> RenderHandle<T> {
1180        RenderHandle(handle)
1181    }
1182}
1183
1184/// The typed handle for an erased id. Free: nothing is looked up; `get` checks the slot.
1185pub(crate) fn resolve<T: 'static>(id: HandleId) -> RenderHandle<T> {
1186    RenderHandle(Handle::from_id(id))
1187}
1188
1189pub(crate) fn create<T: 'static>(app: &mut App, object: T) -> RenderHandle<T> {
1190    RenderHandle(app.create(object))
1191}
1192
1193/// The dispatch signature of [`RenderObject::show_on_screen`].
1194pub(crate) type ShowOnScreenFn =
1195    fn(&mut App, HandleId, Option<AnyRenderObject>, Option<Rect>, Duration, Rc<dyn Curve>);
1196
1197/// The vtable of an erased [`AnyRenderObject`]: one `&'static` table per type, built from the
1198/// trait impl by the protocol. Copied out of the handle before a virtual call, so the slot is not
1199/// borrowed across it.
1200pub(crate) struct RenderObjectVTable {
1201    pub object_data: fn(&App, HandleId) -> &RenderObjectData,
1202    pub object_data_mut: fn(&mut App, HandleId) -> &mut RenderObjectData,
1203    pub visit_children: fn(&App, HandleId, &mut dyn FnMut(AnyRenderObject)),
1204    pub did_attach: fn(&mut App, HandleId, Handle<PipelineOwner>),
1205    pub did_detach: fn(&mut App, HandleId),
1206    pub redepth_children: fn(&mut App, HandleId),
1207    pub setup_parent_data: fn(&mut App, HandleId, AnyRenderObject),
1208    pub sized_by_parent: fn(&App, HandleId) -> bool,
1209    pub perform_layout: fn(&mut App, HandleId),
1210    pub perform_resize: fn(&mut App, HandleId),
1211    pub mark_needs_layout: fn(&mut App, HandleId),
1212    pub paint_bounds: fn(&App, HandleId) -> Rect,
1213    pub apply_paint_transform: fn(&App, HandleId, AnyRenderObject, &mut Matrix4),
1214    pub is_repaint_boundary: fn(&App, HandleId) -> bool,
1215    pub always_needs_compositing: fn(&App, HandleId) -> bool,
1216    pub mouse_tracker_annotation: fn(&App, HandleId) -> Option<MouseTrackerAnnotation>,
1217    pub update_composited_layer: fn(&mut App, HandleId, Option<AnyOffsetLayer>) -> AnyOffsetLayer,
1218    pub show_on_screen: ShowOnScreenFn,
1219    pub interface: fn(HandleId, TypeId) -> Option<Box<dyn Any>>,
1220    pub paint: fn(&mut App, HandleId, &mut PaintingContext, Offset),
1221    pub dispose: fn(&mut App, HandleId),
1222    /// The protocol table this object table is nested in. Exactly one is `Some`.
1223    pub as_box: Option<fn() -> &'static crate::box_::RenderBoxVTable>,
1224    pub as_sliver: Option<fn() -> &'static crate::sliver::RenderSliverVTable>,
1225}
1226
1227impl RenderObjectVTable {
1228    /// `setup_parent_data`, `apply_paint_transform`, `perform_resize` and `mark_needs_layout`
1229    /// are passed in because the box protocol has its own defaults; `paint_bounds` because each
1230    /// protocol defines it.
1231    pub(crate) const fn of<T: RenderObject>(
1232        setup_parent_data: fn(&mut App, HandleId, AnyRenderObject),
1233        paint_bounds: fn(&App, HandleId) -> Rect,
1234        apply_paint_transform: fn(&App, HandleId, AnyRenderObject, &mut Matrix4),
1235        perform_resize: fn(&mut App, HandleId),
1236        mark_needs_layout: fn(&mut App, HandleId),
1237        as_box: Option<fn() -> &'static crate::box_::RenderBoxVTable>,
1238        as_sliver: Option<fn() -> &'static crate::sliver::RenderSliverVTable>,
1239    ) -> RenderObjectVTable {
1240        RenderObjectVTable {
1241            object_data: |app, id| T::render_object_data(resolve(id), app),
1242            object_data_mut: |app, id| T::render_object_data_mut(resolve(id), app),
1243            visit_children: |app, id, visitor| T::visit_children(resolve(id), app, visitor),
1244            did_attach: |app, id, owner| T::did_attach(resolve(id), app, owner),
1245            did_detach: |app, id| T::did_detach(resolve(id), app),
1246            redepth_children: |app, id| T::redepth_children(resolve(id), app),
1247            setup_parent_data,
1248            sized_by_parent: |app, id| T::sized_by_parent(resolve(id), app),
1249            perform_layout: |app, id| T::perform_layout(resolve(id), app),
1250            perform_resize,
1251            mark_needs_layout,
1252            paint_bounds,
1253            apply_paint_transform,
1254            is_repaint_boundary: |app, id| T::is_repaint_boundary(resolve(id), app),
1255            always_needs_compositing: |app, id| T::always_needs_compositing(resolve(id), app),
1256            mouse_tracker_annotation: |app, id| T::mouse_tracker_annotation(resolve(id), app),
1257            update_composited_layer: |app, id, old_layer| {
1258                T::update_composited_layer(resolve(id), app, old_layer)
1259            },
1260            show_on_screen: |app, id, descendant, rect, duration, curve| {
1261                T::show_on_screen(resolve(id), app, descendant, rect, duration, curve)
1262            },
1263            interface: |id, interface| T::interface(resolve(id), interface),
1264            paint: |app, id, context, offset| T::paint(resolve(id), app, context, offset),
1265            dispose: |app, id| T::dispose(resolve(id), app),
1266            as_box,
1267            as_sliver,
1268        }
1269    }
1270}
1271
1272/// Erased `RenderObject`: one identity and a static vtable, the fat pointer rustc cannot build
1273/// for an arena id. No lease.
1274///
1275/// Equality is Dart's `==` on an object reference.
1276#[derive(Clone, Copy)]
1277pub struct AnyRenderObject {
1278    id: HandleId,
1279    vtable: &'static RenderObjectVTable,
1280}
1281
1282impl PartialEq for AnyRenderObject {
1283    fn eq(&self, other: &AnyRenderObject) -> bool {
1284        self.id == other.id
1285    }
1286}
1287
1288impl Eq for AnyRenderObject {}
1289
1290impl Hash for AnyRenderObject {
1291    fn hash<H: Hasher>(&self, state: &mut H) {
1292        self.id.hash(state);
1293    }
1294}
1295
1296impl From<AnyRenderObject> for HandleId {
1297    fn from(object: AnyRenderObject) -> HandleId {
1298        object.id
1299    }
1300}
1301
1302impl Debug for AnyRenderObject {
1303    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1304        write!(f, "AnyRenderObject({:?})", self.id)
1305    }
1306}
1307
1308impl AnyRenderObject {
1309    pub(crate) fn from_vtable(
1310        id: HandleId,
1311        vtable: &'static RenderObjectVTable,
1312    ) -> AnyRenderObject {
1313        AnyRenderObject { id, vtable }
1314    }
1315
1316    /// Dart's `object as RenderBox`, as an `Option`.
1317    pub fn as_box(self) -> Option<crate::box_::AnyRenderBox> {
1318        self.vtable
1319            .as_box
1320            .map(|vtable| crate::box_::AnyRenderBox::from_vtable(self.id, vtable()))
1321    }
1322
1323    /// Dart's `object as RenderSliver`, as an `Option`.
1324    pub fn as_sliver(self) -> Option<crate::sliver::AnyRenderSliver> {
1325        self.vtable
1326            .as_sliver
1327            .map(|vtable| crate::sliver::AnyRenderSliver::from_vtable(self.id, vtable()))
1328    }
1329
1330    /// The render object that is actively computing layout.
1331    ///
1332    /// Only meaningful when asserts are enabled.
1333    pub fn debug_active_layout() -> Option<AnyRenderObject> {
1334        DEBUG_ACTIVE_LAYOUT.get()
1335    }
1336
1337    pub(crate) fn set_debug_active_layout(node: Option<AnyRenderObject>) {
1338        DEBUG_ACTIVE_LAYOUT.set(node);
1339    }
1340
1341    /// The render object that is actively painting.
1342    ///
1343    /// Only meaningful when asserts are enabled.
1344    pub fn debug_active_paint() -> Option<AnyRenderObject> {
1345        DEBUG_ACTIVE_PAINT.get()
1346    }
1347
1348    fn data(self, app: &App) -> &RenderObjectData {
1349        (self.vtable.object_data)(app, self.id)
1350    }
1351
1352    pub(crate) fn data_mut(self, app: &mut App) -> &mut RenderObjectData {
1353        (self.vtable.object_data_mut)(app, self.id)
1354    }
1355
1356    /// Data for use by the parent render object.
1357    pub fn parent_data(self, app: &App) -> Option<&dyn ParentData> {
1358        self.data(app).parent_data.as_deref()
1359    }
1360
1361    /// Mutable parent data.
1362    pub fn parent_data_mut(self, app: &mut App) -> Option<&mut dyn ParentData> {
1363        self.data_mut(app).parent_data.as_deref_mut()
1364    }
1365
1366    /// Whether parent data is `P`. Dart's `parentData is P`.
1367    pub fn parent_data_is<P: ParentData + 'static>(self, app: &App) -> bool {
1368        self.parent_data(app)
1369            .is_some_and(|data| (data as &dyn Any).is::<P>())
1370    }
1371
1372    /// Dart's `parentData! as P`.
1373    ///
1374    /// # Panics
1375    ///
1376    /// If parent data is missing or not `P`.
1377    pub fn parent_data_of<P: ParentData + 'static>(self, app: &App) -> &P {
1378        self.parent_data(app)
1379            .and_then(|data| (data as &dyn Any).downcast_ref::<P>())
1380            .unwrap_or_else(|| panic!("parent data is not {}", std::any::type_name::<P>()))
1381    }
1382
1383    /// See [`parent_data_of`](Self::parent_data_of).
1384    pub fn parent_data_of_mut<P: ParentData + 'static>(self, app: &mut App) -> &mut P {
1385        self.parent_data_mut(app)
1386            .and_then(|data| (data as &mut dyn Any).downcast_mut::<P>())
1387            .unwrap_or_else(|| panic!("parent data is not {}", std::any::type_name::<P>()))
1388    }
1389
1390    /// Installs parent data. Dart's `child.parentData = …`.
1391    pub fn set_parent_data(self, app: &mut App, parent_data: impl ParentData + 'static) {
1392        self.data_mut(app).parent_data = Some(Box::new(parent_data));
1393    }
1394
1395    fn clear_parent_data(self, app: &mut App) {
1396        self.data_mut(app).parent_data = None;
1397    }
1398
1399    /// The parent of this render object in the render tree.
1400    pub fn parent(self, app: &App) -> Option<AnyRenderObject> {
1401        self.data(app).parent
1402    }
1403
1404    fn set_parent(self, app: &mut App, parent: Option<AnyRenderObject>) {
1405        self.data_mut(app).parent = parent;
1406    }
1407
1408    /// The owner for this render object (`None` if unattached).
1409    pub fn owner(self, app: &App) -> Option<Handle<PipelineOwner>> {
1410        self.data(app).owner
1411    }
1412
1413    /// Whether this render object belongs to a [`PipelineOwner`].
1414    pub fn attached(self, app: &App) -> bool {
1415        self.owner(app).is_some()
1416    }
1417
1418    /// The depth of this render object in the render tree.
1419    pub fn depth(self, app: &App) -> i32 {
1420        self.data(app).depth
1421    }
1422
1423    fn set_depth(self, app: &mut App, depth: i32) {
1424        self.data_mut(app).depth = depth;
1425    }
1426
1427    pub(crate) fn needs_layout(self, app: &App) -> bool {
1428        self.data(app).needs_layout
1429    }
1430
1431    fn set_needs_layout(self, app: &mut App, value: bool) {
1432        self.data_mut(app).needs_layout = value;
1433    }
1434
1435    /// Whether this render object's layout information is dirty.
1436    ///
1437    /// Always `false` when debug assertions are disabled.
1438    pub fn debug_needs_layout(self, app: &App) -> bool {
1439        if !cfg!(debug_assertions) {
1440            return false;
1441        }
1442        self.needs_layout(app)
1443    }
1444
1445    pub(crate) fn is_relayout_boundary(self, app: &App) -> Option<bool> {
1446        self.data(app).is_relayout_boundary
1447    }
1448
1449    fn set_is_relayout_boundary(self, app: &mut App, value: Option<bool>) {
1450        self.data_mut(app).is_relayout_boundary = value;
1451    }
1452
1453    fn doing_this_layout_with_callback(self, app: &App) -> bool {
1454        self.data(app).doing_this_layout_with_callback
1455    }
1456
1457    pub(crate) fn debug_doing_this_layout(self, app: &App) -> bool {
1458        self.data(app).debug_doing_this_layout
1459    }
1460
1461    fn set_debug_doing_this_layout(self, app: &mut App, value: bool) {
1462        self.data_mut(app).debug_doing_this_layout = value;
1463    }
1464
1465    pub(crate) fn debug_doing_this_resize(self, app: &App) -> bool {
1466        self.data(app).debug_doing_this_resize
1467    }
1468
1469    fn set_debug_doing_this_resize(self, app: &mut App, value: bool) {
1470        self.data_mut(app).debug_doing_this_resize = value;
1471    }
1472
1473    fn set_debug_can_parent_use_size(self, app: &mut App, value: Option<bool>) {
1474        self.data_mut(app).debug_can_parent_use_size = value;
1475    }
1476
1477    fn debug_mutations_locked(self, app: &App) -> bool {
1478        self.data(app).debug_mutations_locked
1479    }
1480
1481    fn set_debug_mutations_locked(self, app: &mut App, value: bool) {
1482        self.data_mut(app).debug_mutations_locked = value;
1483    }
1484
1485    fn sized_by_parent(self, app: &App) -> bool {
1486        (self.vtable.sized_by_parent)(app, self.id)
1487    }
1488
1489    /// Calls `visitor` for each immediate child.
1490    pub fn visit_children(self, app: &App, visitor: &mut dyn FnMut(AnyRenderObject)) {
1491        (self.vtable.visit_children)(app, self.id, visitor)
1492    }
1493
1494    /// Override point used by [`adopt_child`](Self::adopt_child).
1495    pub fn setup_parent_data(self, app: &mut App, child: AnyRenderObject) {
1496        (self.vtable.setup_parent_data)(app, self.id, child)
1497    }
1498
1499    /// Adjust the depth of `child` to be greater than this node's own depth.
1500    pub fn redepth_child(self, app: &mut App, child: AnyRenderObject) {
1501        debug_assert_eq!(child.owner(app), self.owner(app));
1502        child.redepth_below(app, self.depth(app));
1503    }
1504
1505    /// Flutter's `redepthChild` from the child's side: `parent_depth` is the parent's depth.
1506    pub(crate) fn redepth_below(self, app: &mut App, parent_depth: i32) {
1507        if self.depth(app) <= parent_depth {
1508            self.set_depth(app, parent_depth + 1);
1509            (self.vtable.redepth_children)(app, self.id);
1510        }
1511    }
1512
1513    /// Called by subclasses when they decide a render object is a child.
1514    pub fn adopt_child(self, app: &mut App, child: AnyRenderObject) {
1515        debug_assert!(child.parent(app).is_none());
1516        if cfg!(debug_assertions) {
1517            let mut node = Some(self);
1518            while let Some(current) = node {
1519                debug_assert_ne!(current, child, "adopt_child would create a cycle");
1520                node = current.parent(app);
1521            }
1522        }
1523        self.setup_parent_data(app, child);
1524        self.mark_needs_layout(app);
1525        self.mark_needs_compositing_bits_update(app);
1526        child.set_parent(app, Some(self));
1527        if self.attached(app) {
1528            child.attach(app, self.owner(app).expect("attached parent has an owner"));
1529        }
1530        self.redepth_child(app, child);
1531    }
1532
1533    /// Called by subclasses when they decide a render object is no longer a child.
1534    pub fn drop_child(self, app: &mut App, child: AnyRenderObject) {
1535        debug_assert_eq!(child.parent(app), Some(self));
1536        debug_assert_eq!(child.attached(app), self.attached(app));
1537        debug_assert!(child.parent_data(app).is_some());
1538        if !child.is_relayout_boundary(app).unwrap_or(true) {
1539            child.set_is_relayout_boundary(app, None);
1540        }
1541        if let Some(parent_data) = child.parent_data_mut(app) {
1542            parent_data.detach();
1543        }
1544        child.clear_parent_data(app);
1545        child.set_parent(app, None);
1546        if self.attached(app) {
1547            child.detach(app);
1548        }
1549        self.mark_needs_layout(app);
1550        self.mark_needs_compositing_bits_update(app);
1551    }
1552
1553    /// Mark this render object as attached to `owner`.
1554    ///
1555    /// Flutter's `RenderObject.attach` body, then the [`RenderObject::did_attach`] hook, which
1556    /// by default attaches the children.
1557    pub fn attach(self, app: &mut App, owner: Handle<PipelineOwner>) {
1558        debug_assert!(
1559            !app.is_disposed(self.id),
1560            "attach on a disposed render object"
1561        );
1562        debug_assert!(self.owner(app).is_none());
1563        self.data_mut(app).owner = Some(owner);
1564        if self.needs_layout(app) && self.is_relayout_boundary(app).is_some() {
1565            self.set_needs_layout(app, false);
1566            self.mark_needs_layout(app);
1567        }
1568        if self.needs_compositing_bits_update(app) {
1569            self.set_needs_compositing_bits_update(app, false);
1570            self.mark_needs_compositing_bits_update(app);
1571        }
1572        if self.needs_paint(app) && self.layer(app).is_some() {
1573            self.set_needs_paint(app, false);
1574            self.mark_needs_paint(app);
1575        }
1576        (self.vtable.did_attach)(app, self.id, owner)
1577    }
1578
1579    /// Mark this render object as detached from its [`PipelineOwner`].
1580    ///
1581    /// Flutter's `RenderObject.detach` body, then the [`RenderObject::did_detach`] hook, which
1582    /// by default detaches the children.
1583    pub fn detach(self, app: &mut App) {
1584        debug_assert!(self.owner(app).is_some());
1585        self.data_mut(app).owner = None;
1586        debug_assert!(
1587            self.parent(app).is_none()
1588                || self.attached(app)
1589                    == self.parent(app).is_some_and(|parent| parent.attached(app))
1590        );
1591        (self.vtable.did_detach)(app, self.id)
1592    }
1593
1594    /// Mark this render object's layout information as dirty.
1595    ///
1596    /// The box protocol overrides this with [`crate::RenderBox::mark_needs_layout`], which
1597    /// clears the intrinsics and dry-layout caches first.
1598    pub fn mark_needs_layout(self, app: &mut App) {
1599        debug_assert!(
1600            !app.is_disposed(self.id),
1601            "mark_needs_layout on a disposed render object"
1602        );
1603        (self.vtable.mark_needs_layout)(app, self.id)
1604    }
1605
1606    /// Mark this render object's layout information as dirty, and then defer to
1607    /// the parent.
1608    pub fn mark_parent_needs_layout(self, app: &mut App) {
1609        self.set_needs_layout(app, true);
1610        let parent = self
1611            .parent(app)
1612            .expect("mark_parent_needs_layout requires a parent");
1613        if !self.doing_this_layout_with_callback(app) {
1614            parent.mark_needs_layout(app);
1615        } else {
1616            debug_assert!(parent.debug_doing_this_layout(app));
1617        }
1618        debug_assert_eq!(Some(parent), self.parent(app));
1619    }
1620
1621    /// Mark layout dirty and also mark the parent, for a `sized_by_parent` change.
1622    /// Allows mutations to be made to this object's child list (and any descendants) as
1623    /// well as to any other dirty nodes in the render tree owned by the same `PipelineOwner`
1624    /// as this object. The `callback` argument is invoked synchronously, and the mutations
1625    /// are allowed only during that callback's execution.
1626    ///
1627    /// This exists to allow child lists to be built on-demand during layout (e.g. based on
1628    /// the object's size), and to enable nodes to be moved around the tree as this happens
1629    /// (e.g. to handle `GlobalKey` reparenting), while still ensuring that any particular
1630    /// node is only laid out once per frame.
1631    ///
1632    /// Calling this function disables a number of asserts that are intended to catch likely
1633    /// bugs. As such, using this function is generally discouraged.
1634    ///
1635    /// This function can only be called during layout.
1636    pub fn invoke_layout_callback(self, app: &mut App, callback: impl FnOnce(&mut App)) {
1637        debug_assert!(self.debug_mutations_locked(app));
1638        debug_assert!(self.debug_doing_this_layout(app));
1639        debug_assert!(!self.doing_this_layout_with_callback(app));
1640        self.data_mut(app).doing_this_layout_with_callback = true;
1641        let owner = self.owner(app).expect("a laying-out object is attached");
1642        owner.enable_mutations_to_dirty_subtrees(app, callback);
1643        self.data_mut(app).doing_this_layout_with_callback = false;
1644    }
1645
1646    pub fn mark_needs_layout_for_sized_by_parent_change(self, app: &mut App) {
1647        self.mark_needs_layout(app);
1648        self.mark_parent_needs_layout(app);
1649    }
1650
1651    /// Bootstrap the rendering pipeline by scheduling the very first layout.
1652    pub fn schedule_initial_layout(self, app: &mut App) {
1653        debug_assert!(self.attached(app));
1654        debug_assert!(self.parent(app).is_none());
1655        debug_assert!(!self.owner(app).expect("attached").debug_doing_layout(app));
1656        debug_assert!(self.is_relayout_boundary(app).is_none());
1657        self.set_is_relayout_boundary(app, Some(true));
1658        if cfg!(debug_assertions) {
1659            self.set_debug_can_parent_use_size(app, Some(false));
1660        }
1661        let owner = self.owner(app).expect("attached");
1662        owner.add_node_needing_layout(app, self);
1663    }
1664
1665    pub(crate) fn layout_without_resize(self, app: &mut App) {
1666        debug_assert!(self.needs_layout(app));
1667        debug_assert!(self.is_relayout_boundary(app).unwrap_or(false));
1668        let perform_layout = self.vtable.perform_layout;
1669        let previous = if cfg!(debug_assertions) {
1670            debug_assert!(!self.doing_this_layout_with_callback(app));
1671            self.set_debug_mutations_locked(app, true);
1672            self.set_debug_doing_this_layout(app, true);
1673            let previous = AnyRenderObject::debug_active_layout();
1674            AnyRenderObject::set_debug_active_layout(Some(self));
1675            if crate::debug::debug_print_layouts() {
1676                eprintln!("Laying out (without resize) {self:?}");
1677            }
1678            previous
1679        } else {
1680            None
1681        };
1682        perform_layout(app, self.id);
1683        if cfg!(debug_assertions) {
1684            AnyRenderObject::set_debug_active_layout(previous);
1685            self.set_debug_doing_this_layout(app, false);
1686            self.set_debug_mutations_locked(app, false);
1687        }
1688        self.set_needs_layout(app, false);
1689        self.mark_needs_paint(app);
1690    }
1691
1692    /// Shared `layout` body. Protocol types store their own constraints.
1693    pub(crate) fn run_layout(
1694        self,
1695        app: &mut App,
1696        parent_uses_size: bool,
1697        constraints_tight: bool,
1698        same_constraints: bool,
1699        store_constraints: impl FnOnce(&mut App),
1700    ) {
1701        debug_assert!(!self.debug_doing_this_resize(app));
1702        debug_assert!(!self.debug_doing_this_layout(app));
1703        if cfg!(debug_assertions) {
1704            self.set_debug_can_parent_use_size(app, Some(parent_uses_size));
1705        }
1706
1707        let sized_by_parent = self.sized_by_parent(app);
1708        self.set_is_relayout_boundary(
1709            app,
1710            Some(
1711                !parent_uses_size
1712                    || sized_by_parent
1713                    || constraints_tight
1714                    || self.parent(app).is_none(),
1715            ),
1716        );
1717        if !self.needs_layout(app) && same_constraints {
1718            return;
1719        }
1720        store_constraints(app);
1721
1722        if sized_by_parent {
1723            if cfg!(debug_assertions) {
1724                self.set_debug_doing_this_resize(app, true);
1725            }
1726            (self.vtable.perform_resize)(app, self.id);
1727            if cfg!(debug_assertions) {
1728                self.set_debug_doing_this_resize(app, false);
1729            }
1730        }
1731
1732        let previous = if cfg!(debug_assertions) {
1733            debug_assert!(!self.doing_this_layout_with_callback(app));
1734            self.set_debug_mutations_locked(app, true);
1735            self.set_debug_doing_this_layout(app, true);
1736            let previous = AnyRenderObject::debug_active_layout();
1737            AnyRenderObject::set_debug_active_layout(Some(self));
1738            if crate::debug::debug_print_layouts() {
1739                eprintln!(
1740                    "Laying out ({}) {self:?}",
1741                    if sized_by_parent {
1742                        "with separate resize"
1743                    } else {
1744                        "with resize allowed"
1745                    }
1746                );
1747            }
1748            previous
1749        } else {
1750            None
1751        };
1752        (self.vtable.perform_layout)(app, self.id);
1753        if cfg!(debug_assertions) {
1754            AnyRenderObject::set_debug_active_layout(previous);
1755            self.set_debug_doing_this_layout(app, false);
1756            self.set_debug_mutations_locked(app, false);
1757        }
1758        self.set_needs_layout(app, false);
1759        self.mark_needs_paint(app);
1760    }
1761
1762    // ---- paint ------------------------------------------------------------------------------
1763
1764    pub(crate) fn needs_paint(self, app: &App) -> bool {
1765        self.data(app).needs_paint
1766    }
1767
1768    fn set_needs_paint(self, app: &mut App, value: bool) {
1769        self.data_mut(app).needs_paint = value;
1770    }
1771
1772    /// Whether this render object's paint information is dirty.
1773    ///
1774    /// Always `false` when debug assertions are disabled.
1775    pub fn debug_needs_paint(self, app: &App) -> bool {
1776        if !cfg!(debug_assertions) {
1777            return false;
1778        }
1779        self.needs_paint(app)
1780    }
1781
1782    pub(crate) fn needs_composited_layer_update(self, app: &App) -> bool {
1783        self.data(app).needs_composited_layer_update
1784    }
1785
1786    pub(crate) fn set_needs_composited_layer_update(self, app: &mut App, value: bool) {
1787        self.data_mut(app).needs_composited_layer_update = value;
1788    }
1789
1790    /// Whether this render object's layer information is dirty.
1791    ///
1792    /// Always `false` when debug assertions are disabled.
1793    pub fn debug_needs_composited_layer_update(self, app: &App) -> bool {
1794        if !cfg!(debug_assertions) {
1795            return false;
1796        }
1797        self.needs_composited_layer_update(app)
1798    }
1799
1800    pub(crate) fn was_repaint_boundary(self, app: &App) -> bool {
1801        self.data(app).was_repaint_boundary
1802    }
1803
1804    /// The arena id behind this handle.
1805    pub fn id(self) -> HandleId {
1806        self.id
1807    }
1808
1809    /// Dart's `renderObject as T`: the typed handle when this object is a `T`, else `None`.
1810    pub fn downcast<T: RenderObject>(self, app: &App) -> Option<RenderHandle<T>> {
1811        app.handle::<T>(self.id).map(RenderHandle::from_handle)
1812    }
1813
1814    /// Release any resources held by this render object and free its arena slot. Dart's
1815    /// `dispose` nulls the layer handle and leaves the object to the collector; the arena has no
1816    /// collector, so the slot is destroyed here after the virtual [`RenderObject::dispose`].
1817    ///
1818    /// The object must be detached. Its parent may still hold a handle to it: the widget layer
1819    /// unmounts bottom-up and disposes the parent next, as Dart does.
1820    pub fn dispose(self, app: &mut App) {
1821        debug_assert!(!self.attached(app));
1822        (self.vtable.dispose)(app, self.id);
1823        app.destroy(self.id);
1824    }
1825
1826    /// Whether this render object repaints separately from its parent.
1827    pub fn is_repaint_boundary(self, app: &App) -> bool {
1828        (self.vtable.is_repaint_boundary)(app, self.id)
1829    }
1830
1831    /// An estimate of the bounds within which this render object will paint.
1832    pub fn paint_bounds(self, app: &App) -> Rect {
1833        (self.vtable.paint_bounds)(app, self.id)
1834    }
1835
1836    /// See [`RenderObject::apply_paint_transform`].
1837    pub fn apply_paint_transform(self, app: &App, child: AnyRenderObject, transform: &mut Matrix4) {
1838        (self.vtable.apply_paint_transform)(app, self.id, child, transform)
1839    }
1840
1841    /// Applies the paint transform from this [`AnyRenderObject`] to the `target`
1842    /// [`AnyRenderObject`].
1843    ///
1844    /// Returns a matrix that maps the local paint coordinate system to the coordinate system
1845    /// of `target`, or a `Matrix4::zero()` if the paint transform can not be computed.
1846    ///
1847    /// This method throws an exception when the `target` is not in the same render tree as
1848    /// this render object.
1849    ///
1850    /// The `target` argument defaults to the root of the render tree (`None`).
1851    pub fn get_transform_to(self, app: &App, target: Option<AnyRenderObject>) -> Matrix4 {
1852        debug_assert!(self.attached(app));
1853        // The paths from to fromRenderObject and toRenderObject's common ancestor.
1854        // Each list's length is greater than 1 if not null.
1855        //
1856        // [this, ...., commonAncestorRenderObject], or null if `this` is the common
1857        // ancestor.
1858        let mut from_path: Option<Vec<AnyRenderObject>> = None;
1859        // [target, ...., commonAncestorRenderObject], or null if `target` is the
1860        // common ancestor.
1861        let mut to_path: Option<Vec<AnyRenderObject>> = None;
1862
1863        let mut from = self;
1864        let mut to = target.unwrap_or_else(|| {
1865            self.owner(app)
1866                .and_then(|owner| owner.root_node(app))
1867                .expect("an attached render object has a root")
1868        });
1869
1870        while from != to {
1871            let from_depth = from.depth(app);
1872            let to_depth = to.depth(app);
1873
1874            if from_depth >= to_depth {
1875                let from_parent = from.parent(app).unwrap_or_else(|| {
1876                    panic!("{target:?} and {self:?} are not in the same render tree.")
1877                });
1878                from_path
1879                    .get_or_insert_with(|| vec![self])
1880                    .push(from_parent);
1881                from = from_parent;
1882            }
1883            if from_depth <= to_depth {
1884                let to_parent = to.parent(app).unwrap_or_else(|| {
1885                    panic!("{target:?} and {self:?} are not in the same render tree.")
1886                });
1887                debug_assert!(
1888                    target.is_some(),
1889                    "{self:?} has a depth that is less than or equal to the root node"
1890                );
1891                to_path
1892                    .get_or_insert_with(|| vec![target.expect("checked above")])
1893                    .push(to_parent);
1894                to = to_parent;
1895            }
1896        }
1897
1898        let mut from_transform: Option<Matrix4> = None;
1899        if let Some(from_path) = &from_path {
1900            debug_assert!(from_path.len() > 1);
1901            let mut transform = Matrix4::IDENTITY;
1902            let last_index = if target.is_none() {
1903                from_path.len() - 2
1904            } else {
1905                from_path.len() - 1
1906            };
1907            for index in (1..=last_index).rev() {
1908                from_path[index].apply_paint_transform(app, from_path[index - 1], &mut transform);
1909            }
1910            from_transform = Some(transform);
1911        }
1912        let Some(to_path) = to_path else {
1913            return from_transform.unwrap_or(Matrix4::IDENTITY);
1914        };
1915
1916        debug_assert!(to_path.len() > 1);
1917        let mut to_transform = Matrix4::IDENTITY;
1918        for index in (1..to_path.len()).rev() {
1919            to_path[index].apply_paint_transform(app, to_path[index - 1], &mut to_transform);
1920        }
1921        let Some(to_transform) = to_transform.invert() else {
1922            // If the matrix is singular then `invert()` doesn't do anything.
1923            return zero_matrix();
1924        };
1925        match from_transform {
1926            Some(mut from_transform) => {
1927                multiply(&mut from_transform, &to_transform);
1928                from_transform
1929            }
1930            None => to_transform,
1931        }
1932    }
1933
1934    /// See [`RenderObject::mouse_tracker_annotation`]. Also `None` once the object has left
1935    /// the arena: Dart's tracker keeps a stale annotation object alive, the arena does not.
1936    pub fn mouse_tracker_annotation(self, app: &App) -> Option<MouseTrackerAnnotation> {
1937        if !app.contains(self.id) {
1938            return None;
1939        }
1940        (self.vtable.mouse_tracker_annotation)(app, self.id)
1941    }
1942
1943    /// See [`RenderObject::interface`]: Dart's `object is RenderAbstractViewport`, as
1944    /// `interface::<AnyRenderAbstractViewport>()`.
1945    pub fn interface<I: 'static>(self) -> Option<I> {
1946        (self.vtable.interface)(self.id, TypeId::of::<I>())?
1947            .downcast()
1948            .ok()
1949            .map(|handle| *handle)
1950    }
1951
1952    /// See [`RenderObject::show_on_screen`].
1953    pub fn show_on_screen(
1954        self,
1955        app: &mut App,
1956        descendant: Option<AnyRenderObject>,
1957        rect: Option<Rect>,
1958        duration: Duration,
1959        curve: Rc<dyn Curve>,
1960    ) {
1961        (self.vtable.show_on_screen)(app, self.id, descendant, rect, duration, curve)
1962    }
1963
1964    /// See [`RenderObject::update_composited_layer`].
1965    pub fn update_composited_layer(
1966        self,
1967        app: &mut App,
1968        old_layer: Option<AnyOffsetLayer>,
1969    ) -> AnyOffsetLayer {
1970        (self.vtable.update_composited_layer)(app, self.id, old_layer)
1971    }
1972
1973    /// Whether this render object always needs compositing.
1974    pub fn always_needs_compositing(self, app: &App) -> bool {
1975        (self.vtable.always_needs_compositing)(app, self.id)
1976    }
1977
1978    /// The compositing layer that this render object uses to repaint.
1979    ///
1980    /// If this render object is not a repaint boundary, it is the responsibility
1981    /// of the [`RenderObject::paint`] method to populate this field. If
1982    /// [`needs_compositing`](Self::needs_compositing) is true, this field may be populated with
1983    /// the root-most layer used by the render object implementation. When repainting, instead of
1984    /// creating a new layer the render object may update the layer stored in this field for
1985    /// better performance. It is also OK to leave this field as `None` and create a new layer
1986    /// on every repaint, but without the performance benefit. If [`needs_compositing`](Self::needs_compositing)
1987    /// is false, this field must be set to `None` either by never populating this field, or by
1988    /// setting it to `None` when the value of [`needs_compositing`](Self::needs_compositing)
1989    /// changes from true to false.
1990    ///
1991    /// If this render object is a repaint boundary, the framework automatically
1992    /// creates an [`OffsetLayer`] and populates this field prior to calling the
1993    /// [`RenderObject::paint`] method. The paint method must not replace the value of this
1994    /// field.
1995    pub fn layer(self, app: &App) -> Option<AnyContainerLayer> {
1996        debug_assert!(
1997            !self.is_repaint_boundary(app)
1998                || self.data(app).layer.layer().is_none()
1999                || self
2000                    .data(app)
2001                    .layer
2002                    .layer()
2003                    .is_some_and(|layer| layer.as_offset_layer().is_some())
2004        );
2005        self.data(app).layer.layer()
2006    }
2007
2008    /// Dart's `layer = newLayer`. The setter asserts this is not a repaint boundary: the
2009    /// framework creates and assigns an [`OffsetLayer`] to a repaint boundary automatically.
2010    pub fn set_layer(self, app: &mut App, new_layer: Option<AnyContainerLayer>) {
2011        debug_assert!(
2012            !self.is_repaint_boundary(app),
2013            "Attempted to set a layer to a repaint boundary render object.\n\
2014             The framework creates and assigns an OffsetLayer to a repaint \
2015             boundary automatically."
2016        );
2017        LayerHandle::set_layer(app, |app| &mut self.data_mut(app).layer, new_layer);
2018    }
2019
2020    /// Dart's `layer as T?`.
2021    pub fn layer_as<T: 'static>(self, app: &App) -> Option<Handle<T>> {
2022        self.layer(app)
2023            .and_then(|layer| app.handle::<T>(layer.id()))
2024    }
2025
2026    /// In debug mode, the compositing layer that this render object uses to repaint.
2027    ///
2028    /// This getter is intended for debugging purposes only. In release builds, it
2029    /// always returns `None`. In debug builds, it returns the layer even if the layer
2030    /// is dirty.
2031    ///
2032    /// For production code, consider [`layer`](Self::layer).
2033    pub fn debug_layer(self, app: &App) -> Option<AnyContainerLayer> {
2034        if !cfg!(debug_assertions) {
2035            return None;
2036        }
2037        self.data(app).layer.layer()
2038    }
2039
2040    pub(crate) fn needs_compositing_bits_update(self, app: &App) -> bool {
2041        self.data(app).needs_compositing_bits_update
2042    }
2043
2044    fn set_needs_compositing_bits_update(self, app: &mut App, value: bool) {
2045        self.data_mut(app).needs_compositing_bits_update = value;
2046    }
2047
2048    /// Mark the compositing state for this render object as dirty.
2049    ///
2050    /// This is called to indicate that the value for [`needs_compositing`](Self::needs_compositing)
2051    /// needs to be recomputed during the next [`PipelineOwner::flush_compositing_bits`] engine
2052    /// phase.
2053    ///
2054    /// When the subtree is mutated, we need to recompute our
2055    /// [`needs_compositing`](Self::needs_compositing) bit, and some of our ancestors need to do
2056    /// the same (in case ours changed in a way that will change theirs). To this end,
2057    /// [`adopt_child`](Self::adopt_child) and [`drop_child`](Self::drop_child) call this method,
2058    /// and, as necessary, this method calls the parent's, etc, walking up the tree to mark all
2059    /// the nodes that need updating.
2060    ///
2061    /// This method does not schedule a rendering frame, because since it cannot be the case
2062    /// that _only_ the compositing bits changed, something else will have scheduled a frame for
2063    /// us.
2064    pub fn mark_needs_compositing_bits_update(self, app: &mut App) {
2065        debug_assert!(
2066            !app.is_disposed(self.id),
2067            "mark_needs_compositing_bits_update on a disposed render object"
2068        );
2069        if self.needs_compositing_bits_update(app) {
2070            return;
2071        }
2072        self.set_needs_compositing_bits_update(app, true);
2073        if let Some(parent) = self.parent(app) {
2074            if parent.needs_compositing_bits_update(app) {
2075                return;
2076            }
2077            if (!self.was_repaint_boundary(app) || !self.is_repaint_boundary(app))
2078                && !parent.is_repaint_boundary(app)
2079            {
2080                parent.mark_needs_compositing_bits_update(app);
2081                return;
2082            }
2083        }
2084        // parent is fine (or there isn't one), but we are dirty
2085        if let Some(owner) = self.owner(app) {
2086            owner.add_node_needing_compositing_bits_update(app, self);
2087        }
2088    }
2089
2090    /// Whether we or one of our descendants has a compositing layer.
2091    ///
2092    /// If this node needs compositing as indicated by this bit, then all ancestor
2093    /// nodes will also need compositing.
2094    ///
2095    /// Only legal to call after [`PipelineOwner::flush_layout`] and
2096    /// [`PipelineOwner::flush_compositing_bits`] have been called.
2097    pub fn needs_compositing(self, app: &App) -> bool {
2098        debug_assert!(
2099            !self.needs_compositing_bits_update(app),
2100            "make sure we don't use this bit when it is dirty"
2101        );
2102        self.data(app).needs_compositing
2103    }
2104
2105    /// Flutter's `_updateCompositingBits`.
2106    pub(crate) fn update_compositing_bits(self, app: &mut App) {
2107        if !self.needs_compositing_bits_update(app) {
2108            return;
2109        }
2110        let old_needs_compositing = self.data(app).needs_compositing;
2111        self.data_mut(app).needs_compositing = false;
2112        let mut children = Vec::new();
2113        self.visit_children(app, &mut |child| children.push(child));
2114        for child in children {
2115            child.update_compositing_bits(app);
2116            if child.needs_compositing(app) {
2117                self.data_mut(app).needs_compositing = true;
2118            }
2119        }
2120        if self.is_repaint_boundary(app) || self.always_needs_compositing(app) {
2121            self.data_mut(app).needs_compositing = true;
2122        }
2123        // If a node was previously a repaint boundary, but no longer is one, then
2124        // regardless of its compositing state we need to find a new parent to
2125        // paint from. To do this, we mark it clean again so that the traversal
2126        // in markNeedsPaint is not short-circuited. It is removed from _nodesNeedingPaint
2127        // so that we do not attempt to paint from it after locating a parent.
2128        if !self.is_repaint_boundary(app) && self.was_repaint_boundary(app) {
2129            self.set_needs_paint(app, false);
2130            self.set_needs_composited_layer_update(app, false);
2131            if let Some(owner) = self.owner(app) {
2132                owner.remove_node_needing_paint(app, self);
2133            }
2134            self.set_needs_compositing_bits_update(app, false);
2135            self.mark_needs_paint(app);
2136        } else if old_needs_compositing != self.data(app).needs_compositing {
2137            self.set_needs_compositing_bits_update(app, false);
2138            self.mark_needs_paint(app);
2139        } else {
2140            self.set_needs_compositing_bits_update(app, false);
2141        }
2142    }
2143
2144    /// Mark this render object as having changed its visual appearance.
2145    ///
2146    /// Rather than eagerly updating this render object's display list in response to writes,
2147    /// we instead mark the render object as needing to paint, which schedules a visual update.
2148    /// As part of the visual update, the rendering pipeline will give this render object an
2149    /// opportunity to update its display list.
2150    pub fn mark_needs_paint(self, app: &mut App) {
2151        debug_assert!(
2152            !app.is_disposed(self.id),
2153            "mark_needs_paint on a disposed render object"
2154        );
2155        debug_assert!(
2156            self.owner(app)
2157                .is_none_or(|owner| !owner.debug_doing_paint(app))
2158        );
2159        if self.needs_paint(app) {
2160            return;
2161        }
2162        self.set_needs_paint(app, true);
2163        if self.is_repaint_boundary(app) && self.was_repaint_boundary(app) {
2164            if crate::debug::debug_print_mark_needs_paint_stacks() {
2165                eprintln!("markNeedsPaint() called for {self:?}");
2166            }
2167            debug_assert!(
2168                self.layer(app)
2169                    .is_some_and(|layer| layer.as_offset_layer().is_some())
2170            );
2171            if let Some(owner) = self.owner(app) {
2172                owner.add_node_needing_paint(app, self);
2173                owner.request_visual_update(app);
2174            }
2175        } else if let Some(parent) = self.parent(app) {
2176            parent.mark_needs_paint(app);
2177        } else {
2178            if crate::debug::debug_print_mark_needs_paint_stacks() {
2179                eprintln!("markNeedsPaint() called for {self:?} (root of render tree)");
2180            }
2181            if let Some(owner) = self.owner(app) {
2182                owner.request_visual_update(app);
2183            }
2184        }
2185    }
2186
2187    /// Mark this render object as having changed a property on its composited
2188    /// layer.
2189    ///
2190    /// Render objects that have a composited layer have [`is_repaint_boundary`](Self::is_repaint_boundary)
2191    /// equal to true may update the properties of that composited layer without repainting
2192    /// their children. If this render object is a repaint boundary but does
2193    /// not yet have a composited layer created for it, this method will instead
2194    /// mark the nearest repaint boundary parent as needing to be painted.
2195    ///
2196    /// If this method is called on a render object that is not a repaint boundary
2197    /// or is a repaint boundary but hasn't been composited yet, it is equivalent
2198    /// to calling [`mark_needs_paint`](Self::mark_needs_paint).
2199    pub fn mark_needs_composited_layer_update(self, app: &mut App) {
2200        debug_assert!(
2201            !app.is_disposed(self.id),
2202            "mark_needs_composited_layer_update on a disposed render object"
2203        );
2204        debug_assert!(
2205            self.owner(app)
2206                .is_none_or(|owner| !owner.debug_doing_paint(app))
2207        );
2208        if self.needs_composited_layer_update(app) || self.needs_paint(app) {
2209            return;
2210        }
2211        self.set_needs_composited_layer_update(app, true);
2212        if self.is_repaint_boundary(app) && self.was_repaint_boundary(app) {
2213            debug_assert!(self.layer(app).is_some());
2214            if let Some(owner) = self.owner(app) {
2215                owner.add_node_needing_paint(app, self);
2216                owner.request_visual_update(app);
2217            }
2218        } else {
2219            self.mark_needs_paint(app);
2220        }
2221    }
2222
2223    /// Flutter's `_skippedPaintingOnLayer`: this boundary's layer is detached, so the first
2224    /// attached ancestor boundary will repaint it when it repaints.
2225    pub(crate) fn skipped_painting_on_layer(self, app: &mut App) {
2226        debug_assert!(self.attached(app));
2227        debug_assert!(self.is_repaint_boundary(app));
2228        debug_assert!(self.needs_paint(app) || self.needs_composited_layer_update(app));
2229        debug_assert!(self.layer(app).is_some());
2230        debug_assert!(
2231            self.layer(app)
2232                .is_some_and(|layer| !layer.as_layer().attached(app))
2233        );
2234        let mut node = self.parent(app);
2235        while let Some(current) = node {
2236            if current.is_repaint_boundary(app) {
2237                match current.layer(app) {
2238                    None => break,
2239                    Some(layer) if layer.as_layer().attached(app) => break,
2240                    Some(_) => current.set_needs_paint(app, true),
2241                }
2242            }
2243            node = current.parent(app);
2244        }
2245    }
2246
2247    /// Bootstrap the rendering pipeline by scheduling the very first paint.
2248    ///
2249    /// Requires that this render object is attached, is the root of the render
2250    /// tree, and has a composited layer.
2251    pub fn schedule_initial_paint(self, app: &mut App, root_layer: AnyContainerLayer) {
2252        debug_assert!(root_layer.as_layer().attached(app));
2253        debug_assert!(self.attached(app));
2254        debug_assert!(self.parent(app).is_none());
2255        debug_assert!(!self.owner(app).expect("attached").debug_doing_paint(app));
2256        debug_assert!(self.is_repaint_boundary(app));
2257        debug_assert!(self.layer(app).is_none());
2258        LayerHandle::set_layer(app, |app| &mut self.data_mut(app).layer, Some(root_layer));
2259        debug_assert!(self.needs_paint(app));
2260        let owner = self.owner(app).expect("attached");
2261        owner.add_node_needing_paint(app, self);
2262    }
2263
2264    /// Replace the layer. This is only valid for the root of a render
2265    /// object subtree (whatever object [`schedule_initial_paint`](Self::schedule_initial_paint)
2266    /// was called on).
2267    ///
2268    /// This might be called if, e.g., the device pixel ratio changed.
2269    pub fn replace_root_layer(self, app: &mut App, root_layer: AnyOffsetLayer) {
2270        debug_assert!(
2271            !app.is_disposed(self.id),
2272            "replace_root_layer on a disposed render object"
2273        );
2274        debug_assert!(root_layer.as_layer().attached(app));
2275        debug_assert!(self.attached(app));
2276        debug_assert!(self.parent(app).is_none());
2277        debug_assert!(!self.owner(app).expect("attached").debug_doing_paint(app));
2278        debug_assert!(self.is_repaint_boundary(app));
2279        debug_assert!(
2280            self.layer(app).is_some(),
2281            "use schedule_initial_paint the first time"
2282        );
2283        self.layer(app).expect("checked").as_layer().detach(app);
2284        LayerHandle::set_layer(
2285            app,
2286            |app| &mut self.data_mut(app).layer,
2287            Some(root_layer.as_container_layer()),
2288        );
2289        self.mark_needs_paint(app);
2290    }
2291
2292    /// Flutter's `_paintWithContext`: the framework wrapper around the `paint` virtual.
2293    pub(crate) fn paint_with_context(
2294        self,
2295        app: &mut App,
2296        context: &mut PaintingContext,
2297        offset: Offset,
2298    ) {
2299        debug_assert!(
2300            !self.data(app).debug_doing_this_paint,
2301            "Tried to paint a RenderObject reentrantly: {self:?}"
2302        );
2303        if self.needs_layout(app) {
2304            return;
2305        }
2306        debug_assert!(
2307            !self.needs_compositing_bits_update(app),
2308            "Tried to paint a RenderObject before its compositing bits were updated.\n\
2309             The following RenderObject was marked as having dirty compositing bits \
2310             at the time that it was painted: {self:?}\n\
2311             A RenderObject that still has dirty compositing bits cannot be painted \
2312             because this indicates that the tree has not yet been properly configured \
2313             for creating the layer tree.\n\
2314             This usually indicates an error in the Flutter framework itself."
2315        );
2316        let debug_last_active_paint = if cfg!(debug_assertions) {
2317            self.data_mut(app).debug_doing_this_paint = true;
2318            let previous = DEBUG_ACTIVE_PAINT.replace(Some(self));
2319            debug_assert!(!self.is_repaint_boundary(app) || self.layer(app).is_some());
2320            previous
2321        } else {
2322            None
2323        };
2324        self.set_needs_paint(app, false);
2325        self.set_needs_composited_layer_update(app, false);
2326        let is_repaint_boundary = self.is_repaint_boundary(app);
2327        self.data_mut(app).was_repaint_boundary = is_repaint_boundary;
2328        (self.vtable.paint)(app, self.id, context, offset);
2329        debug_assert!(!self.needs_layout(app));
2330        debug_assert!(!self.needs_paint(app));
2331        if cfg!(debug_assertions) {
2332            DEBUG_ACTIVE_PAINT.set(debug_last_active_paint);
2333            self.data_mut(app).debug_doing_this_paint = false;
2334        }
2335    }
2336}
2337
2338/// Flutter's `RenderObject` bodies that an override calls through `super`.
2339///
2340/// Blanket-implemented for every [`RenderObject`], and repeats the default bodies of the
2341/// virtuals above: a leaf's own override shadows the default it would otherwise call.
2342pub trait RenderObjectBase: RenderObject {
2343    /// Flutter's `RenderObject.dispose` body: releases the layer handle. An override calls it
2344    /// last, where Dart writes `super.dispose()`.
2345    fn dispose(self: RenderHandle<Self>, app: &mut App) {
2346        LayerHandle::set_layer(app, |app| &mut self.render_object_data_mut(app).layer, None);
2347    }
2348
2349    /// Flutter's `RenderObject.markNeedsLayout` body; an override calls it where Dart writes
2350    /// `super.markNeedsLayout()`.
2351    fn mark_needs_layout(self: RenderHandle<Self>, app: &mut App) {
2352        let this = self.as_render_object(app);
2353        if this.needs_layout(app) {
2354            return;
2355        }
2356        this.set_needs_layout(app, true);
2357        if let Some(owner) = this.owner(app)
2358            && this.is_relayout_boundary(app).unwrap_or(false)
2359        {
2360            if crate::debug::debug_print_mark_needs_layout_stacks() {
2361                eprintln!("markNeedsLayout() called for {this:?}");
2362            }
2363            owner.add_node_needing_layout(app, this);
2364            owner.request_visual_update(app);
2365        } else if this.parent(app).is_some() {
2366            this.mark_parent_needs_layout(app);
2367        }
2368    }
2369
2370    /// Flutter's `RenderObject.showOnScreen`.
2371    fn show_on_screen(
2372        self: RenderHandle<Self>,
2373        app: &mut App,
2374        descendant: Option<AnyRenderObject>,
2375        rect: Option<Rect>,
2376        duration: Duration,
2377        curve: Rc<dyn Curve>,
2378    ) {
2379        let this = self.as_render_object(app);
2380        if let Some(parent) = this.parent(app) {
2381            parent.show_on_screen(app, Some(descendant.unwrap_or(this)), rect, duration, curve);
2382        }
2383    }
2384}
2385
2386impl<T: RenderObject> RenderObjectBase for T {}
2387
2388/// vector_math's `Matrix4.zero()`.
2389pub(crate) fn zero_matrix() -> Matrix4 {
2390    Matrix4::from_flutter_array(&[0.0; 16])
2391}
2392
2393/// vector_math's `transform.multiply(other)`: `transform = transform * other`, so `other`
2394/// applies first to a point.
2395pub(crate) fn multiply(transform: &mut Matrix4, other: &Matrix4) {
2396    *transform = transform.then(other);
2397}
2398
2399/// vector_math's `transform.translate(dx, dy)`.
2400pub(crate) fn translate(transform: &mut Matrix4, dx: f64, dy: f64) {
2401    multiply(transform, &Matrix4::translation(dx as f32, dy as f32));
2402}
2403
2404/// vector_math's `Matrix4.perspectiveTransform(Vector3)`: transforms the point and divides by
2405/// the resulting `w`.
2406pub(crate) fn perspective_transform(transform: &Matrix4, point: [f64; 3]) -> [f64; 3] {
2407    let m = transform.to_flutter_array().map(f64::from);
2408    let [x, y, z] = point;
2409    let out = |row: usize| m[row] * x + m[4 + row] * y + m[8 + row] * z + m[12 + row];
2410    let w = out(3);
2411    [out(0) / w, out(1) / w, out(2) / w]
2412}
2413
2414/// The bag of [`RenderObjectWithLayoutCallbackMixin`].
2415#[derive(Debug)]
2416pub struct RenderObjectWithLayoutCallbackData {
2417    // The initial value of this flag must be set to true to prevent the layout
2418    // callback from being scheduled when the subtree has never been laid out (in
2419    // which case the `constraints` or any other layout information is unknown).
2420    needs_rebuild: bool,
2421}
2422
2423impl Default for RenderObjectWithLayoutCallbackData {
2424    fn default() -> RenderObjectWithLayoutCallbackData {
2425        RenderObjectWithLayoutCallbackData {
2426            needs_rebuild: true,
2427        }
2428    }
2429}
2430
2431/// A mixin for `RenderObject`s that run a layout callback (typically one that builds a
2432/// widget subtree) during `perform_layout`, as `LayoutBuilder`'s render object does.
2433///
2434/// Implementers keep the bag under a field named `layout_callback`, implement
2435/// [`layout_callback`](Self::layout_callback), and call
2436/// [`run_layout_callback`](Self::run_layout_callback) in their `perform_layout`. The mixin
2437/// is on the box protocol here because scheduling needs the tree methods.
2438pub trait RenderObjectWithLayoutCallbackMixin: crate::box_::RenderBox {
2439    /// The mixin's bag.
2440    fn layout_callback_data(
2441        self: RenderHandle<Self>,
2442        app: &App,
2443    ) -> &RenderObjectWithLayoutCallbackData;
2444
2445    /// See [`layout_callback_data`](Self::layout_callback_data).
2446    fn layout_callback_data_mut(
2447        self: RenderHandle<Self>,
2448        app: &mut App,
2449    ) -> &mut RenderObjectWithLayoutCallbackData;
2450
2451    /// The layout callback to run in `perform_layout`, through
2452    /// [`run_layout_callback`](Self::run_layout_callback), which invokes it with
2453    /// [`AnyRenderObject::invoke_layout_callback`].
2454    fn layout_callback(self: RenderHandle<Self>, app: &mut App);
2455
2456    /// Invokes [`layout_callback`](Self::layout_callback) with
2457    /// [`AnyRenderObject::invoke_layout_callback`].
2458    ///
2459    /// Must be called in `perform_layout`, and only after the callback was scheduled.
2460    fn run_layout_callback(self: RenderHandle<Self>, app: &mut App) {
2461        debug_assert!(self.as_object().debug_doing_this_layout(app));
2462        self.as_object()
2463            .invoke_layout_callback(app, |app| Self::layout_callback(self, app));
2464        self.layout_callback_data_mut(app).needs_rebuild = false;
2465    }
2466
2467    /// Schedules the layout callback to be run in the next layout pass, marking this object
2468    /// for layout.
2469    fn schedule_layout_callback(self: RenderHandle<Self>, app: &mut App) {
2470        if self.layout_callback_data(app).needs_rebuild {
2471            debug_assert!(self.as_object().needs_layout(app));
2472            return;
2473        }
2474        self.layout_callback_data_mut(app).needs_rebuild = true;
2475        // This ensures that the layout callback will be run even if an ancestor
2476        // chooses to not lay out this subtree (for example, obstructed OverlayEntries
2477        // with `maintainState` set to true), to maintain the widget tree integrity
2478        // (making sure global keys are unique, for example).
2479        if let Some(owner) = self.as_object().owner(app) {
2480            owner.add_node_needing_layout(app, self.as_object());
2481        }
2482        // In an active tree, markNeedsLayout is needed to inform the layout boundary
2483        // that its child size may change.
2484        self.as_object().mark_needs_layout(app);
2485    }
2486}
2487
2488#[cfg(test)]
2489mod tests {
2490    use std::cell::Cell;
2491    use std::rc::Rc;
2492
2493    use inset_foundation::{App, AppCell, Listener};
2494
2495    use super::*;
2496    use crate::box_::{BoxConstraints, RenderBox, RenderBoxData};
2497    use crate::pipeline_owner::PipelineOwner;
2498
2499    struct TestLeaf {
2500        render_object: RenderObjectData,
2501        render_box: RenderBoxData,
2502        layouts: Rc<Cell<u32>>,
2503    }
2504
2505    impl RenderObject for TestLeaf {
2506        render_object_accessors!();
2507
2508        fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2509            let layouts = self.get(app).layouts.clone();
2510            layouts.set(layouts.get() + 1);
2511            let size = self.constraints(app).smallest();
2512            self.set_size(app, size);
2513        }
2514    }
2515
2516    impl RenderBox for TestLeaf {
2517        crate::render_box_accessors!();
2518    }
2519
2520    struct TestParent {
2521        render_object: RenderObjectData,
2522        render_box: RenderBoxData,
2523        child: Option<crate::AnyRenderBox>,
2524        layouts: Rc<Cell<u32>>,
2525        parent_uses_size: bool,
2526        lay_out_child: bool,
2527    }
2528
2529    impl RenderObject for TestParent {
2530        render_object_accessors!();
2531
2532        fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2533            let layouts = self.get(app).layouts.clone();
2534            layouts.set(layouts.get() + 1);
2535            let child = self.get(app).child;
2536            let parent_uses_size = self.get(app).parent_uses_size;
2537            let lay_out_child = self.get(app).lay_out_child;
2538            let constraints = self.constraints(app);
2539            if let Some(child) = child
2540                && lay_out_child
2541            {
2542                child.layout(app, constraints, parent_uses_size);
2543                let _again = self.get(app).layouts.get();
2544                if parent_uses_size {
2545                    self.set_size(app, child.size(app));
2546                    return;
2547                }
2548            }
2549            self.set_size(app, constraints.smallest());
2550        }
2551
2552        fn visit_children(
2553            self: RenderHandle<Self>,
2554            app: &App,
2555            visitor: &mut dyn FnMut(AnyRenderObject),
2556        ) {
2557            if let Some(child) = self.get(app).child {
2558                visitor(child.as_object());
2559            }
2560        }
2561    }
2562
2563    impl RenderBox for TestParent {
2564        crate::render_box_accessors!();
2565    }
2566
2567    fn tight() -> BoxConstraints {
2568        BoxConstraints::tight_for_finite(100.0, 100.0)
2569    }
2570
2571    fn loose() -> BoxConstraints {
2572        BoxConstraints::new()
2573    }
2574
2575    fn leaf(layouts: Rc<Cell<u32>>) -> TestLeaf {
2576        TestLeaf {
2577            render_object: RenderObjectData::new(),
2578            render_box: RenderBoxData::new(),
2579            layouts,
2580        }
2581    }
2582
2583    fn parent(
2584        child: Option<crate::AnyRenderBox>,
2585        layouts: Rc<Cell<u32>>,
2586        parent_uses_size: bool,
2587        lay_out_child: bool,
2588    ) -> TestParent {
2589        TestParent {
2590            render_object: RenderObjectData::new(),
2591            render_box: RenderBoxData::new(),
2592            child,
2593            layouts,
2594            parent_uses_size,
2595            lay_out_child,
2596        }
2597    }
2598
2599    /// `object_test.dart`: `nodesNeedingLayout updated with layout changes`.
2600    #[test]
2601    fn nodes_needing_layout_updated_with_layout_changes() {
2602        let cell = AppCell::new();
2603        let mut app = cell.borrow_mut();
2604        let owner = PipelineOwner::new(&mut app, None, None);
2605        let node = RenderHandle::new_box(&mut app, leaf(Rc::new(Cell::new(0))));
2606        node.as_object().attach(&mut app, owner);
2607        assert!(owner.nodes_needing_layout(&app).is_empty());
2608
2609        node.layout(&mut app, tight(), false);
2610        node.as_object().mark_needs_layout(&mut app);
2611        assert!(owner.nodes_needing_layout(&app).contains(&node.as_object()));
2612
2613        owner.flush_layout(&mut app);
2614        assert!(owner.nodes_needing_layout(&app).is_empty());
2615    }
2616
2617    #[test]
2618    fn clean_layout_skips_perform_layout() {
2619        let cell = AppCell::new();
2620        let mut app = cell.borrow_mut();
2621        let layouts = Rc::new(Cell::new(0));
2622        let node = RenderHandle::new_box(&mut app, leaf(Rc::clone(&layouts)));
2623        node.layout(&mut app, tight(), false);
2624        assert_eq!(layouts.get(), 1);
2625        node.layout(&mut app, tight(), false);
2626        assert_eq!(layouts.get(), 1);
2627        node.as_object().mark_needs_layout(&mut app);
2628        node.layout(&mut app, tight(), false);
2629        assert_eq!(layouts.get(), 2);
2630    }
2631
2632    #[test]
2633    fn parent_uses_size_marks_parent() {
2634        let cell = AppCell::new();
2635        let mut app = cell.borrow_mut();
2636        let owner = PipelineOwner::new(&mut app, None, None);
2637        let child = RenderHandle::new_box(&mut app, leaf(Rc::new(Cell::new(0))));
2638        let parent = RenderHandle::new_box(
2639            &mut app,
2640            parent(Some(child.as_box()), Rc::new(Cell::new(0)), true, true),
2641        );
2642        parent.adopt_child(&mut app, child.as_object());
2643        parent.as_object().attach(&mut app, owner);
2644        parent.layout(&mut app, loose(), false);
2645        assert!(!parent.debug_needs_layout(&app));
2646        assert!(!child.debug_needs_layout(&app));
2647
2648        child.as_object().mark_needs_layout(&mut app);
2649        assert!(parent.debug_needs_layout(&app));
2650        assert!(
2651            owner
2652                .nodes_needing_layout(&app)
2653                .contains(&parent.as_object())
2654        );
2655    }
2656
2657    #[test]
2658    fn adopt_drop_attach_detach() {
2659        let cell = AppCell::new();
2660        let mut app = cell.borrow_mut();
2661        let owner = PipelineOwner::new(&mut app, None, None);
2662        let child = RenderHandle::new_box(&mut app, leaf(Rc::new(Cell::new(0))));
2663        let parent = RenderHandle::new_box(
2664            &mut app,
2665            parent(Some(child.as_box()), Rc::new(Cell::new(0)), false, true),
2666        );
2667        parent.adopt_child(&mut app, child.as_object());
2668        assert_eq!(child.parent(&app), Some(parent.as_object()));
2669        assert_eq!(
2670            child.as_object().depth(&app),
2671            parent.as_object().depth(&app) + 1
2672        );
2673        assert!(!child.attached(&app));
2674
2675        parent.as_object().attach(&mut app, owner);
2676        assert!(parent.attached(&app));
2677        assert!(child.attached(&app));
2678        assert_eq!(child.owner(&app), Some(owner));
2679
2680        parent.drop_child(&mut app, child.as_object());
2681        assert!(child.parent(&app).is_none());
2682        assert!(!child.attached(&app));
2683        assert!(parent.attached(&app));
2684    }
2685
2686    #[test]
2687    fn parent_reenters_itself_after_child_layout() {
2688        let cell = AppCell::new();
2689        let mut app = cell.borrow_mut();
2690        let layouts = Rc::new(Cell::new(0));
2691        let child = RenderHandle::new_box(&mut app, leaf(Rc::new(Cell::new(0))));
2692        let parent = RenderHandle::new_box(
2693            &mut app,
2694            parent(Some(child.as_box()), Rc::clone(&layouts), true, true),
2695        );
2696        parent.adopt_child(&mut app, child.as_object());
2697        parent.layout(&mut app, loose(), false);
2698        assert_eq!(layouts.get(), 1);
2699        assert_eq!(parent.size(&app), child.size(&app));
2700    }
2701
2702    #[test]
2703    fn flush_layout_orders_by_depth() {
2704        let cell = AppCell::new();
2705        let mut app = cell.borrow_mut();
2706        let owner = PipelineOwner::new(&mut app, None, None);
2707        let order = Rc::new(std::cell::RefCell::new(Vec::new()));
2708        let child_order = Rc::clone(&order);
2709        let parent_order = Rc::clone(&order);
2710
2711        struct OrderLeaf {
2712            render_object: RenderObjectData,
2713            render_box: RenderBoxData,
2714            name: &'static str,
2715            order: Rc<std::cell::RefCell<Vec<&'static str>>>,
2716        }
2717        impl RenderObject for OrderLeaf {
2718            render_object_accessors!();
2719
2720            fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2721                let name = self.get(app).name;
2722                self.get(app).order.borrow_mut().push(name);
2723                let size = self.constraints(app).smallest();
2724                self.set_size(app, size);
2725            }
2726        }
2727        impl RenderBox for OrderLeaf {
2728            crate::render_box_accessors!();
2729        }
2730
2731        struct OrderParent {
2732            render_object: RenderObjectData,
2733            render_box: RenderBoxData,
2734            name: &'static str,
2735            child: Option<crate::AnyRenderBox>,
2736            order: Rc<std::cell::RefCell<Vec<&'static str>>>,
2737        }
2738        impl RenderObject for OrderParent {
2739            render_object_accessors!();
2740
2741            fn perform_layout(self: RenderHandle<Self>, app: &mut App) {
2742                let name = self.get(app).name;
2743                self.get(app).order.borrow_mut().push(name);
2744                let size = self.constraints(app).smallest();
2745                self.set_size(app, size);
2746            }
2747            fn visit_children(
2748                self: RenderHandle<Self>,
2749                app: &App,
2750                visitor: &mut dyn FnMut(AnyRenderObject),
2751            ) {
2752                if let Some(child) = self.get(app).child {
2753                    visitor(child.as_object());
2754                }
2755            }
2756        }
2757        impl RenderBox for OrderParent {
2758            crate::render_box_accessors!();
2759        }
2760
2761        let child = RenderHandle::new_box(
2762            &mut app,
2763            OrderLeaf {
2764                render_object: RenderObjectData::new(),
2765                render_box: RenderBoxData::new(),
2766                name: "child",
2767                order: child_order,
2768            },
2769        );
2770        let parent = RenderHandle::new_box(
2771            &mut app,
2772            OrderParent {
2773                render_object: RenderObjectData::new(),
2774                render_box: RenderBoxData::new(),
2775                name: "parent",
2776                child: Some(child.as_box()),
2777                order: parent_order,
2778            },
2779        );
2780        parent.adopt_child(&mut app, child.as_object());
2781        parent.as_object().attach(&mut app, owner);
2782        parent.layout(&mut app, tight(), false);
2783        child.layout(&mut app, tight(), false);
2784        parent.as_object().mark_needs_layout(&mut app);
2785        child.as_object().mark_needs_layout(&mut app);
2786        order.borrow_mut().clear();
2787        owner.flush_layout(&mut app);
2788        assert_eq!(*order.borrow(), ["parent", "child"]);
2789    }
2790
2791    #[test]
2792    fn mark_needs_layout_requests_visual_update() {
2793        let cell = AppCell::new();
2794        let mut app = cell.borrow_mut();
2795        let updates = Rc::new(Cell::new(0));
2796        let updates_cb = Rc::clone(&updates);
2797        let owner = PipelineOwner::new(
2798            &mut app,
2799            Some(Listener::new(move |_| {
2800                updates_cb.set(updates_cb.get() + 1);
2801            })),
2802            None,
2803        );
2804        let node = RenderHandle::new_box(&mut app, leaf(Rc::new(Cell::new(0))));
2805        owner.set_root_node(&mut app, Some(node.as_object()));
2806        node.layout(&mut app, tight(), false);
2807        assert_eq!(updates.get(), 0);
2808        node.as_object().mark_needs_layout(&mut app);
2809        assert_eq!(updates.get(), 1);
2810    }
2811}