diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index 02ba09f2b2..dabc9e6581 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -1138,10 +1138,10 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im assert(_debugCanPerformMutations); assert(child != null); setupParentData(child); - super.adoptChild(child); markNeedsLayout(); markNeedsCompositingBitsUpdate(); markNeedsSemanticsUpdate(); + super.adoptChild(child); } /// Called by subclasses when they decide a render object is no longer a child. @@ -1830,6 +1830,9 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im bool _needsCompositingBitsUpdate = false; // set to true when a child is added /// Mark the compositing state for this render object as dirty. /// + /// This is called to indicate that the value for [needsCompositing] needs to + /// be recomputed during the next [flushCompositingBits] engine phase. + /// /// When the subtree is mutated, we need to recompute our /// [needsCompositing] bit, and some of our ancestors need to do the /// same (in case ours changed in a way that will change theirs). To @@ -1867,6 +1870,9 @@ abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin im bool _needsCompositing; // initialised in the constructor /// Whether we or one of our descendants has a compositing layer. /// + /// If this node needs compositing as indicated by this bit, then all ancestor + /// nodes will also need compositing. + /// /// Only legal to call after [PipelineOwner.flushLayout] and /// [PipelineOwner.flushCompositingBits] have been called. bool get needsCompositing { diff --git a/packages/flutter/test/rendering/repaint_boundary_test.dart b/packages/flutter/test/rendering/repaint_boundary_test.dart index 9f69d4333e..fe8c1e3fd0 100644 --- a/packages/flutter/test/rendering/repaint_boundary_test.dart +++ b/packages/flutter/test/rendering/repaint_boundary_test.dart @@ -34,4 +34,21 @@ void main() { c.opacity = 0.7; pumpFrame(phase: EnginePhase.flushSemantics); }); + + test('Repaint boundary can get new parent after markNeedsCompositingBitsUpdate', () { + // Regression test for https://github.com/flutter/flutter/issues/24029. + + final RenderRepaintBoundary repaintBoundary = RenderRepaintBoundary(); + layout(repaintBoundary, phase: EnginePhase.flushSemantics); + + repaintBoundary.markNeedsCompositingBitsUpdate(); + + renderer.renderView.child = null; + final RenderPadding padding = RenderPadding( + padding: const EdgeInsets.all(50), + ); + renderer.renderView.child = padding; + padding.child = repaintBoundary; + pumpFrame(phase: EnginePhase.flushSemantics); + }); }