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