1 /*
<lambda>null2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package androidx.compose.ui.node
17 
18 import androidx.compose.runtime.ComposeNodeLifecycleCallback
19 import androidx.compose.runtime.CompositionLocalMap
20 import androidx.compose.runtime.collection.MutableVector
21 import androidx.compose.runtime.collection.mutableVectorOf
22 import androidx.compose.runtime.tooling.CompositionErrorContext
23 import androidx.compose.runtime.tooling.LocalCompositionErrorContext
24 import androidx.compose.ui.ComposeUiFlags
25 import androidx.compose.ui.ExperimentalComposeUiApi
26 import androidx.compose.ui.InternalComposeUiApi
27 import androidx.compose.ui.Modifier
28 import androidx.compose.ui.geometry.Offset
29 import androidx.compose.ui.graphics.Canvas
30 import androidx.compose.ui.graphics.layer.GraphicsLayer
31 import androidx.compose.ui.input.pointer.PointerInputFilter
32 import androidx.compose.ui.input.pointer.PointerInputModifier
33 import androidx.compose.ui.input.pointer.PointerType
34 import androidx.compose.ui.internal.checkPrecondition
35 import androidx.compose.ui.internal.checkPreconditionNotNull
36 import androidx.compose.ui.internal.requirePrecondition
37 import androidx.compose.ui.layout.IntrinsicMeasurable
38 import androidx.compose.ui.layout.IntrinsicMeasureScope
39 import androidx.compose.ui.layout.LayoutCoordinates
40 import androidx.compose.ui.layout.LayoutInfo
41 import androidx.compose.ui.layout.LayoutNodeSubcompositionsState
42 import androidx.compose.ui.layout.Measurable
43 import androidx.compose.ui.layout.MeasurePolicy
44 import androidx.compose.ui.layout.MeasureScope
45 import androidx.compose.ui.layout.ModifierInfo
46 import androidx.compose.ui.layout.OnGloballyPositionedModifier
47 import androidx.compose.ui.layout.Placeable
48 import androidx.compose.ui.layout.Remeasurement
49 import androidx.compose.ui.node.LayoutNode.LayoutState.Idle
50 import androidx.compose.ui.node.LayoutNode.LayoutState.LayingOut
51 import androidx.compose.ui.node.LayoutNode.LayoutState.LookaheadLayingOut
52 import androidx.compose.ui.node.LayoutNode.LayoutState.LookaheadMeasuring
53 import androidx.compose.ui.node.LayoutNode.LayoutState.Measuring
54 import androidx.compose.ui.node.Nodes.PointerInput
55 import androidx.compose.ui.platform.LocalDensity
56 import androidx.compose.ui.platform.LocalLayoutDirection
57 import androidx.compose.ui.platform.LocalViewConfiguration
58 import androidx.compose.ui.platform.ViewConfiguration
59 import androidx.compose.ui.platform.simpleIdentityToString
60 import androidx.compose.ui.semantics.SemanticsConfiguration
61 import androidx.compose.ui.semantics.SemanticsInfo
62 import androidx.compose.ui.semantics.generateSemanticsId
63 import androidx.compose.ui.unit.Constraints
64 import androidx.compose.ui.unit.Density
65 import androidx.compose.ui.unit.DpSize
66 import androidx.compose.ui.unit.IntOffset
67 import androidx.compose.ui.unit.IntSize
68 import androidx.compose.ui.unit.LayoutDirection
69 import androidx.compose.ui.viewinterop.InteropView
70 import androidx.compose.ui.viewinterop.InteropViewFactoryHolder
71 
72 /** Enable to log changes to the LayoutNode tree. This logging is quite chatty. */
73 private const val DebugChanges = false
74 
75 private val DefaultDensity = Density(1f)
76 
77 /** An element in the layout hierarchy, built with compose UI. */
78 @OptIn(InternalComposeUiApi::class)
79 internal class LayoutNode(
80     // Virtual LayoutNode is the temporary concept allows us to a node which is not a real node,
81     // but just a holder for its children - allows us to combine some children into something we
82     // can subcompose in(LayoutNode) without being required to define it as a real layout - we
83     // don't want to define the layout strategy for such nodes, instead the children of the
84     // virtual nodes will be treated as the direct children of the virtual node parent.
85     // This whole concept will be replaced with a proper subcomposition logic which allows to
86     // subcompose multiple times into the same LayoutNode and define offsets.
87     private val isVirtual: Boolean = false,
88     // The unique semantics ID that is used by all semantics modifiers attached to this LayoutNode.
89     // TODO(b/281907968): Implement this with a getter that returns the compositeKeyHash.
90     override var semanticsId: Int = generateSemanticsId(),
91 ) :
92     ComposeNodeLifecycleCallback,
93     Remeasurement,
94     OwnerScope,
95     LayoutInfo,
96     SemanticsInfo,
97     ComposeUiNode,
98     InteroperableComposeUiNode,
99     Owner.OnLayoutCompletedListener {
100 
101     internal var offsetFromRoot: IntOffset = IntOffset.Max
102     internal var lastSize: IntSize = IntSize.Zero
103     internal var outerToInnerOffset: IntOffset = IntOffset.Max
104     internal var outerToInnerOffsetDirty: Boolean = true
105 
106     var forceUseOldLayers: Boolean = false
107 
108     override var compositeKeyHash: Int = 0
109 
110     internal var isVirtualLookaheadRoot: Boolean = false
111 
112     /**
113      * This lookaheadRoot references the closest root to the LayoutNode, not the top-level lookahead
114      * root.
115      */
116     internal var lookaheadRoot: LayoutNode? = null
117         private set(newRoot) {
118             if (newRoot != field) {
119                 field = newRoot
120                 if (newRoot != null) {
121                     layoutDelegate.ensureLookaheadDelegateCreated()
122                     forEachCoordinatorIncludingInner { it.ensureLookaheadDelegateCreated() }
123                 } else {
124                     // When lookahead root is set to null, clear the lookahead pass delegate.
125                     // This can happen when lookaheadScope is removed in one of the parents, or
126                     // more likely when movableContent moves from a parent in a LookaheadScope to
127                     // a parent not in a LookaheadScope.
128                     layoutDelegate.onRemovedFromLookaheadScope()
129                 }
130                 invalidateMeasurements()
131             }
132         }
133 
134     val isPlacedInLookahead: Boolean?
135         get() = lookaheadPassDelegate?.isPlaced
136 
137     private var virtualChildrenCount = 0
138 
139     // the list of nodes containing the virtual children as is
140     private val _foldedChildren =
141         MutableVectorWithMutationTracking(mutableVectorOf<LayoutNode>()) {
142             layoutDelegate.markChildrenDirty()
143         }
144     internal val foldedChildren: List<LayoutNode>
145         get() = _foldedChildren.asList()
146 
147     // the list of nodes where the virtual children are unfolded (their children are represented
148     // as our direct children)
149     private var _unfoldedChildren: MutableVector<LayoutNode>? = null
150 
151     private fun recreateUnfoldedChildrenIfDirty() {
152         if (unfoldedVirtualChildrenListDirty) {
153             unfoldedVirtualChildrenListDirty = false
154             val unfoldedChildren =
155                 _unfoldedChildren ?: mutableVectorOf<LayoutNode>().also { _unfoldedChildren = it }
156             unfoldedChildren.clear()
157             _foldedChildren.forEach {
158                 if (it.isVirtual) {
159                     unfoldedChildren.addAll(it._children)
160                 } else {
161                     unfoldedChildren.add(it)
162                 }
163             }
164             layoutDelegate.markChildrenDirty()
165         }
166     }
167 
168     internal val childMeasurables: List<Measurable>
169         get() = measurePassDelegate.childDelegates
170 
171     internal val childLookaheadMeasurables: List<Measurable>
172         get() = lookaheadPassDelegate!!.childDelegates
173 
174     // when the list of our children is modified it will be set to true if we are a virtual node
175     // or it will be set to true on a parent if the parent is a virtual node
176     private var unfoldedVirtualChildrenListDirty = false
177 
178     private fun invalidateUnfoldedVirtualChildren() {
179         if (virtualChildrenCount > 0) {
180             unfoldedVirtualChildrenListDirty = true
181         }
182         if (isVirtual) {
183             // Invalidate all virtual unfolded parent until we reach a non-virtual one
184             this._foldedParent?.invalidateUnfoldedVirtualChildren()
185         }
186     }
187 
188     /**
189      * This should **not** be mutated or even accessed directly from outside of [LayoutNode]. Use
190      * [forEachChild]/[forEachChildIndexed] when there's a need to iterate through the vector.
191      */
192     internal val _children: MutableVector<LayoutNode>
193         get() {
194             updateChildrenIfDirty()
195             return if (virtualChildrenCount == 0) {
196                 _foldedChildren.vector
197             } else {
198                 _unfoldedChildren!!
199             }
200         }
201 
202     /** Update children if the list is not up to date. */
203     internal fun updateChildrenIfDirty() {
204         if (virtualChildrenCount > 0) {
205             recreateUnfoldedChildrenIfDirty()
206         }
207     }
208 
209     inline fun forEachChild(block: (LayoutNode) -> Unit) = _children.forEach(block)
210 
211     inline fun forEachChildIndexed(block: (Int, LayoutNode) -> Unit) =
212         _children.forEachIndexed(block)
213 
214     /** The children of this LayoutNode, controlled by [insertAt], [move], and [removeAt]. */
215     internal val children: List<LayoutNode>
216         get() = _children.asMutableList()
217 
218     /**
219      * The parent node in the LayoutNode hierarchy. This is `null` when the [LayoutNode] is not
220      * attached to a hierarchy or is the root of the hierarchy.
221      */
222     private var _foldedParent: LayoutNode? = null
223 
224     /*
225      * The parent node in the LayoutNode hierarchy, skipping over virtual nodes.
226      */
227     internal val parent: LayoutNode?
228         get() {
229             var parent = _foldedParent
230             while (parent?.isVirtual == true) {
231                 parent = parent._foldedParent
232             }
233             return parent
234         }
235 
236     /** The view system [Owner]. This `null` until [attach] is called */
237     internal var owner: Owner? = null
238         private set
239 
240     /**
241      * The [InteropViewFactoryHolder] associated with this node, which is used to instantiate and
242      * manage platform View instances that are hosted in Compose.
243      */
244     internal var interopViewFactoryHolder: InteropViewFactoryHolder? = null
245 
246     @InternalComposeUiApi
247     override fun getInteropView(): InteropView? = interopViewFactoryHolder?.getInteropView()
248 
249     /**
250      * Returns true if this [LayoutNode] currently has an [LayoutNode.owner]. Semantically, this
251      * means that the LayoutNode is currently a part of a component tree.
252      */
253     override val isAttached: Boolean
254         get() = owner != null
255 
256     /**
257      * The tree depth of the [LayoutNode]. This is valid only when it is attached to a hierarchy.
258      */
259     internal var depth: Int = 0
260 
261     /**
262      * The layout state the node is currently in.
263      *
264      * The mutation of [layoutState] is confined to [LayoutNode], and is therefore read-only outside
265      * LayoutNode. This makes the state machine easier to reason about.
266      */
267     internal val layoutState
268         get() = layoutDelegate.layoutState
269 
270     /**
271      * The lookahead pass delegate for the [LayoutNode]. This should only be used for measure and
272      * layout related impl during *lookahead*. For the actual measure & layout, use
273      * [measurePassDelegate].
274      */
275     internal val lookaheadPassDelegate
276         get() = layoutDelegate.lookaheadPassDelegate
277 
278     /**
279      * The measure pass delegate for the [LayoutNode]. This delegate is responsible for the actual
280      * measure & layout, after lookahead if any.
281      */
282     internal val measurePassDelegate
283         get() = layoutDelegate.measurePassDelegate
284 
285     /** [requestRemeasure] calls will be ignored while this flag is true. */
286     private var ignoreRemeasureRequests = false
287 
288     /**
289      * Inserts a child [LayoutNode] at a particular index. If this LayoutNode [owner] is not `null`
290      * then [instance] will become [attach]ed also. [instance] must have a `null` [parent].
291      */
292     internal fun insertAt(index: Int, instance: LayoutNode) {
293         checkPrecondition(instance._foldedParent == null || instance.owner == null) {
294             exceptionMessageForParentingOrOwnership(instance)
295         }
296 
297         if (DebugChanges) {
298             println("$instance added to $this at index $index")
299         }
300 
301         instance._foldedParent = this
302         _foldedChildren.add(index, instance)
303         onZSortedChildrenInvalidated()
304 
305         if (instance.isVirtual) {
306             virtualChildrenCount++
307         }
308         invalidateUnfoldedVirtualChildren()
309 
310         val owner = this.owner
311         if (owner != null) {
312             instance.attach(owner)
313         }
314 
315         if (instance.layoutDelegate.childrenAccessingCoordinatesDuringPlacement > 0) {
316             layoutDelegate.childrenAccessingCoordinatesDuringPlacement++
317         }
318     }
319 
320     private fun exceptionMessageForParentingOrOwnership(instance: LayoutNode) =
321         "Cannot insert $instance because it already has a parent or an owner." +
322             " This tree: " +
323             debugTreeToString() +
324             " Other tree: " +
325             instance._foldedParent?.debugTreeToString()
326 
327     internal fun onZSortedChildrenInvalidated() {
328         if (isVirtual) {
329             parent?.onZSortedChildrenInvalidated()
330         } else {
331             zSortedChildrenInvalidated = true
332         }
333     }
334 
335     /** Removes one or more children, starting at [index]. */
336     internal fun removeAt(index: Int, count: Int) {
337         requirePrecondition(count >= 0) { "count ($count) must be greater than 0" }
338         for (i in index + count - 1 downTo index) {
339             // Call detach callbacks before removing from _foldedChildren, so the child is still
340             // visible to parents traversing downwards, such as when clearing focus.
341             onChildRemoved(_foldedChildren[i])
342             val child = _foldedChildren.removeAt(i)
343             if (DebugChanges) {
344                 println("$child removed from $this at index $i")
345             }
346         }
347     }
348 
349     /** Removes all children. */
350     internal fun removeAll() {
351         for (i in _foldedChildren.size - 1 downTo 0) {
352             onChildRemoved(_foldedChildren[i])
353         }
354         _foldedChildren.clear()
355 
356         if (DebugChanges) {
357             println("Removed all children from $this")
358         }
359     }
360 
361     private fun onChildRemoved(child: LayoutNode) {
362         if (child.layoutDelegate.childrenAccessingCoordinatesDuringPlacement > 0) {
363             layoutDelegate.childrenAccessingCoordinatesDuringPlacement--
364         }
365         if (owner != null) {
366             child.detach()
367         }
368         child._foldedParent = null
369         child.outerCoordinator.wrappedBy = null
370 
371         if (child.isVirtual) {
372             virtualChildrenCount--
373             child._foldedChildren.forEach { it.outerCoordinator.wrappedBy = null }
374         }
375         invalidateUnfoldedVirtualChildren()
376         onZSortedChildrenInvalidated()
377     }
378 
379     /**
380      * Moves [count] elements starting at index [from] to index [to]. The [to] index is related to
381      * the position before the change, so, for example, to move an element at position 1 to after
382      * the element at position 2, [from] should be `1` and [to] should be `3`. If the elements were
383      * LayoutNodes A B C D E, calling `move(1, 3, 1)` would result in the LayoutNodes being
384      * reordered to A C B D E.
385      */
386     internal fun move(from: Int, to: Int, count: Int) {
387         if (from == to) {
388             return // nothing to do
389         }
390 
391         for (i in 0 until count) {
392             // if "from" is after "to," the from index moves because we're inserting before it
393             val fromIndex = if (from > to) from + i else from
394             val toIndex = if (from > to) to + i else to + count - 2
395             val child = _foldedChildren.removeAt(fromIndex)
396 
397             if (DebugChanges) {
398                 println("$child moved in $this from index $fromIndex to $toIndex")
399             }
400 
401             _foldedChildren.add(toIndex, child)
402         }
403         onZSortedChildrenInvalidated()
404 
405         invalidateUnfoldedVirtualChildren()
406         invalidateMeasurements()
407     }
408 
409     override fun isTransparent(): Boolean = outerCoordinator.isTransparent()
410 
411     internal var isSemanticsInvalidated = false
412 
413     internal fun requestAutofill() {
414         // Ignore calls while semantics are being applied (b/378114177).
415         if (isCurrentlyCalculatingSemanticsConfiguration) return
416 
417         val owner = requireOwner()
418         owner.requestAutofill(this)
419     }
420 
421     internal fun invalidateSemantics() {
422         // Ignore calls to invalidate Semantics while semantics are being applied (b/378114177).
423         if (isCurrentlyCalculatingSemanticsConfiguration) return
424 
425         if (@OptIn(ExperimentalComposeUiApi::class) !ComposeUiFlags.isSemanticAutofillEnabled) {
426             _semanticsConfiguration = null
427 
428             // TODO(lmr): this ends up scheduling work that diffs the entire tree, but we should
429             //  eventually move to marking just this node as invalidated since we are invalidating
430             //  on a per-node level. This should preserve current behavior for now..
431             requireOwner().onSemanticsChange()
432         } else if (nodes.isUpdating || applyingModifierOnAttach) {
433             // We are currently updating the modifier, so just schedule an invalidation. After
434             // applying the modifier, we will notify listeners of semantics changes.
435             isSemanticsInvalidated = true
436         } else {
437             // We are not currently updating the modifier, so instead of scheduling invalidation,
438             // we update the semantics configuration and send the notification event right away.
439             val prev = _semanticsConfiguration
440             _semanticsConfiguration = calculateSemanticsConfiguration()
441             isSemanticsInvalidated = false
442 
443             val owner = requireOwner()
444             owner.semanticsOwner.notifySemanticsChange(this, prev)
445 
446             // This is needed for Accessibility and ContentCapture. Remove after these systems
447             // are migrated to use SemanticsInfo and SemanticListeners.
448             owner.onSemanticsChange()
449         }
450     }
451 
452     // This is needed until we completely move to the new world where we always pre-compute the
453     // semantics configuration. At that point, this can just be a property with a private setter.
454     private var _semanticsConfiguration: SemanticsConfiguration? = null
455     override val semanticsConfiguration: SemanticsConfiguration?
456         get() {
457             // TODO: investigate if there's a better way to approach "half attached" state and
458             // whether or not deactivated nodes should be considered removed or not.
459             if (!isAttached || isDeactivated || !nodes.has(Nodes.Semantics)) return null
460 
461             @OptIn(ExperimentalComposeUiApi::class)
462             if (!ComposeUiFlags.isSemanticAutofillEnabled && _semanticsConfiguration == null) {
463                 _semanticsConfiguration = calculateSemanticsConfiguration()
464             }
465             return _semanticsConfiguration
466         }
467 
468     private var isCurrentlyCalculatingSemanticsConfiguration = false
469 
470     private fun calculateSemanticsConfiguration(): SemanticsConfiguration {
471         // Ignore calls to invalidate Semantics while semantics are being calculated.
472         isCurrentlyCalculatingSemanticsConfiguration = true
473 
474         var config = SemanticsConfiguration()
475         requireOwner().snapshotObserver.observeSemanticsReads(this) {
476             nodes.tailToHead(Nodes.Semantics) {
477                 if (it.shouldClearDescendantSemantics) {
478                     config = SemanticsConfiguration()
479                     config.isClearingSemantics = true
480                 }
481                 if (it.shouldMergeDescendantSemantics) {
482                     config.isMergingSemanticsOfDescendants = true
483                 }
484                 with(it) { config.applySemantics() }
485             }
486         }
487 
488         isCurrentlyCalculatingSemanticsConfiguration = false
489 
490         return config
491     }
492 
493     /**
494      * Set the [Owner] of this LayoutNode. This LayoutNode must not already be attached. [owner]
495      * must match its [parent].[owner].
496      */
497     internal fun attach(owner: Owner) {
498         checkPrecondition(this.owner == null) {
499             "Cannot attach $this as it already is attached.  Tree: " + debugTreeToString()
500         }
501         checkPrecondition(_foldedParent == null || _foldedParent?.owner == owner) {
502             "Attaching to a different owner($owner) than the parent's owner(${parent?.owner})." +
503                 " This tree: " +
504                 debugTreeToString() +
505                 " Parent tree: " +
506                 _foldedParent?.debugTreeToString()
507         }
508         val parent = this.parent
509         if (parent == null) {
510             measurePassDelegate.isPlaced = true
511             lookaheadPassDelegate?.onAttachedToNullParent()
512         }
513 
514         // Use the inner coordinator of first non-virtual parent
515         outerCoordinator.wrappedBy = parent?.innerCoordinator
516 
517         this.owner = owner
518         this.depth = (parent?.depth ?: -1) + 1
519 
520         pendingModifier?.let { applyModifier(it) }
521         pendingModifier = null
522 
523         // Note: With precomputed semantics config, calling invalidateSemantics() before the
524         // layoutNode is marked as attached would result in semantics not being calculated..
525         @OptIn(ExperimentalComposeUiApi::class)
526         if (!ComposeUiFlags.isSemanticAutofillEnabled && nodes.has(Nodes.Semantics)) {
527             invalidateSemantics()
528         }
529         owner.onPreAttach(this)
530 
531         // Update lookahead root when attached. For nested cases, we'll always use the
532         // closest lookahead root
533         if (isVirtualLookaheadRoot) {
534             lookaheadRoot = this
535         } else {
536             // Favor lookahead root from parent than locally created scope, unless current node
537             // is a virtual lookahead root
538             lookaheadRoot = _foldedParent?.lookaheadRoot ?: lookaheadRoot
539             if (lookaheadRoot == null && nodes.has(Nodes.ApproachMeasure)) {
540                 // This could happen when movableContent containing intermediateLayout is moved
541                 lookaheadRoot = this
542             }
543         }
544         if (!isDeactivated) {
545             nodes.markAsAttached()
546         }
547         _foldedChildren.forEach { child -> child.attach(owner) }
548         if (!isDeactivated) {
549             nodes.runAttachLifecycle()
550         }
551 
552         invalidateMeasurements()
553         parent?.invalidateMeasurements()
554 
555         forEachCoordinatorIncludingInner { it.onLayoutNodeAttach() }
556         onAttach?.invoke(owner)
557 
558         layoutDelegate.updateParentData()
559 
560         if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isSemanticAutofillEnabled) {
561             if (!isDeactivated && nodes.has(Nodes.Semantics)) {
562                 invalidateSemantics()
563             }
564         }
565 
566         owner.onPostAttach(this)
567     }
568 
569     /**
570      * Remove the LayoutNode from the [Owner]. The [owner] must not be `null` before this call and
571      * its [parent]'s [owner] must be `null` before calling this. This will also [detach] all
572      * children. After executing, the [owner] will be `null`.
573      */
574     internal fun detach() {
575         val owner = owner
576         checkPreconditionNotNull(owner) {
577             "Cannot detach node that is already detached!  Tree: " + parent?.debugTreeToString()
578         }
579         val parent = this.parent
580         if (parent != null) {
581             parent.invalidateLayer()
582             parent.invalidateMeasurements()
583             measurePassDelegate.measuredByParent = UsageByParent.NotUsed
584             lookaheadPassDelegate?.let { it.measuredByParent = UsageByParent.NotUsed }
585         }
586         layoutDelegate.resetAlignmentLines()
587         onDetach?.invoke(owner)
588 
589         @OptIn(ExperimentalComposeUiApi::class)
590         if (!ComposeUiFlags.isSemanticAutofillEnabled && nodes.has(Nodes.Semantics)) {
591             invalidateSemantics()
592         }
593         nodes.runDetachLifecycle()
594         ignoreRemeasureRequests { _foldedChildren.forEach { child -> child.detach() } }
595         nodes.markAsDetached()
596         owner.onDetach(this)
597         this.owner = null
598 
599         lookaheadRoot = null
600         depth = 0
601         measurePassDelegate.onNodeDetached()
602         lookaheadPassDelegate?.onNodeDetached()
603 
604         // Note: Don't call invalidateSemantics() from within detach() because the modifier nodes
605         // are detached before the LayoutNode, and invalidateSemantics() can trigger a call to
606         // calculateSemanticsConfiguration() which will encounter unattached nodes. Instead, just
607         // set the semantics configuration to null over here since we know the node is detached.
608         @OptIn(ExperimentalComposeUiApi::class)
609         if (ComposeUiFlags.isSemanticAutofillEnabled && nodes.has(Nodes.Semantics)) {
610             val prev = _semanticsConfiguration
611             _semanticsConfiguration = null
612             isSemanticsInvalidated = false
613             owner.semanticsOwner.notifySemanticsChange(this, prev)
614 
615             // This is needed for Accessibility and ContentCapture. Remove after these systems
616             // are migrated to use SemanticsInfo and SemanticListeners.
617             owner.onSemanticsChange()
618         }
619     }
620 
621     private val _zSortedChildren = mutableVectorOf<LayoutNode>()
622     private var zSortedChildrenInvalidated = true
623 
624     /**
625      * Returns the children list sorted by their [LayoutNode.zIndex] first (smaller first) and the
626      * order they were placed via [Placeable.placeAt] by parent (smaller first). Please note that
627      * this list contains not placed items as well, so you have to manually filter them.
628      *
629      * Note that the object is reused so you shouldn't save it for later.
630      */
631     @PublishedApi
632     internal val zSortedChildren: MutableVector<LayoutNode>
633         get() {
634             if (zSortedChildrenInvalidated) {
635                 _zSortedChildren.clear()
636                 _zSortedChildren.addAll(_children)
637                 _zSortedChildren.sortWith(ZComparator)
638                 zSortedChildrenInvalidated = false
639             }
640             return _zSortedChildren
641         }
642 
643     override val isValidOwnerScope: Boolean
644         get() = isAttached
645 
646     override fun toString(): String {
647         return "${simpleIdentityToString(this, null)} children: ${children.size} " +
648             "measurePolicy: $measurePolicy"
649     }
650 
651     internal val hasFixedInnerContentConstraints: Boolean
652         get() {
653             // it is the constraints we have after all the modifiers applied on this node,
654             // the one to be passed into user provided [measurePolicy.measure]. if those
655             // constraints are fixed this means the children size changes can't affect
656             // this LayoutNode size.
657             val innerContentConstraints = innerCoordinator.lastMeasurementConstraints
658             return innerContentConstraints.hasFixedWidth && innerContentConstraints.hasFixedHeight
659         }
660 
661     /** Call this method from the debugger to see a dump of the LayoutNode tree structure */
662     @Suppress("unused")
663     private fun debugTreeToString(depth: Int = 0): String {
664         val tree = StringBuilder()
665         for (i in 0 until depth) {
666             tree.append("  ")
667         }
668         tree.append("|-")
669         tree.append(toString())
670         tree.append('\n')
671 
672         forEachChild { child -> tree.append(child.debugTreeToString(depth + 1)) }
673 
674         var treeString = tree.toString()
675         if (depth == 0) {
676             // Delete trailing newline
677             treeString = treeString.substring(0, treeString.length - 1)
678         }
679 
680         return treeString
681     }
682 
683     internal abstract class NoIntrinsicsMeasurePolicy(private val error: String) : MeasurePolicy {
684         override fun IntrinsicMeasureScope.minIntrinsicWidth(
685             measurables: List<IntrinsicMeasurable>,
686             height: Int
687         ) = error(error)
688 
689         override fun IntrinsicMeasureScope.minIntrinsicHeight(
690             measurables: List<IntrinsicMeasurable>,
691             width: Int
692         ) = error(error)
693 
694         override fun IntrinsicMeasureScope.maxIntrinsicWidth(
695             measurables: List<IntrinsicMeasurable>,
696             height: Int
697         ) = error(error)
698 
699         override fun IntrinsicMeasureScope.maxIntrinsicHeight(
700             measurables: List<IntrinsicMeasurable>,
701             width: Int
702         ) = error(error)
703     }
704 
705     /** Blocks that define the measurement and intrinsic measurement of the layout. */
706     override var measurePolicy: MeasurePolicy = ErrorMeasurePolicy
707         set(value) {
708             if (field != value) {
709                 field = value
710                 intrinsicsPolicy?.updateFrom(measurePolicy)
711                 invalidateMeasurements()
712             }
713         }
714 
715     /**
716      * The intrinsic measurements of this layout, backed up by states to trigger correct
717      * remeasurement for layouts using the intrinsics of this layout when the [measurePolicy] is
718      * changing.
719      */
720     private var intrinsicsPolicy: IntrinsicsPolicy? = null
721 
722     private fun getOrCreateIntrinsicsPolicy(): IntrinsicsPolicy {
723         return intrinsicsPolicy
724             ?: IntrinsicsPolicy(this, measurePolicy).also { intrinsicsPolicy = it }
725     }
726 
727     fun minLookaheadIntrinsicWidth(height: Int) =
728         getOrCreateIntrinsicsPolicy().minLookaheadIntrinsicWidth(height)
729 
730     fun minLookaheadIntrinsicHeight(width: Int) =
731         getOrCreateIntrinsicsPolicy().minLookaheadIntrinsicHeight(width)
732 
733     fun maxLookaheadIntrinsicWidth(height: Int) =
734         getOrCreateIntrinsicsPolicy().maxLookaheadIntrinsicWidth(height)
735 
736     fun maxLookaheadIntrinsicHeight(width: Int) =
737         getOrCreateIntrinsicsPolicy().maxLookaheadIntrinsicHeight(width)
738 
739     fun minIntrinsicWidth(height: Int) = getOrCreateIntrinsicsPolicy().minIntrinsicWidth(height)
740 
741     fun minIntrinsicHeight(width: Int) = getOrCreateIntrinsicsPolicy().minIntrinsicHeight(width)
742 
743     fun maxIntrinsicWidth(height: Int) = getOrCreateIntrinsicsPolicy().maxIntrinsicWidth(height)
744 
745     fun maxIntrinsicHeight(width: Int) = getOrCreateIntrinsicsPolicy().maxIntrinsicHeight(width)
746 
747     /** The screen density to be used by this layout. */
748     override var density: Density = DefaultDensity
749         set(value) {
750             if (field != value) {
751                 field = value
752                 onDensityOrLayoutDirectionChanged()
753 
754                 nodes.headToTail { it.onDensityChange() }
755             }
756         }
757 
758     /** The layout direction of the layout node. */
759     override var layoutDirection: LayoutDirection = LayoutDirection.Ltr
760         set(value) {
761             if (field != value) {
762                 field = value
763                 onDensityOrLayoutDirectionChanged()
764 
765                 nodes.headToTail { it.onLayoutDirectionChange() }
766             }
767         }
768 
769     override var viewConfiguration: ViewConfiguration = DummyViewConfiguration
770         set(value) {
771             if (field != value) {
772                 field = value
773 
774                 nodes.headToTail(type = PointerInput) { it.onViewConfigurationChange() }
775             }
776         }
777 
778     override var compositionLocalMap = CompositionLocalMap.Empty
779         set(value) {
780             field = value
781             density = value[LocalDensity]
782             layoutDirection = value[LocalLayoutDirection]
783             viewConfiguration = value[LocalViewConfiguration]
784             nodes.headToTail(Nodes.CompositionLocalConsumer) { modifierNode ->
785                 val delegatedNode = modifierNode.node
786                 if (delegatedNode.isAttached) {
787                     autoInvalidateUpdatedNode(delegatedNode)
788                 } else {
789                     delegatedNode.updatedNodeAwaitingAttachForInvalidation = true
790                 }
791             }
792         }
793 
794     private val traceContext: CompositionErrorContext?
795         get() = compositionLocalMap[LocalCompositionErrorContext]
796 
797     fun rethrowWithComposeStackTrace(e: Throwable): Nothing =
798         throw e.also { traceContext?.apply { e.attachComposeStackTrace(this@LayoutNode) } }
799 
800     private fun onDensityOrLayoutDirectionChanged() {
801         // TODO(b/242120396): it seems like we need to update some densities in the node
802         // coordinators here
803         // measure/layout modifiers on the node
804         invalidateMeasurements()
805         // draw modifiers on the node
806         parent?.invalidateLayer()
807         // and draw modifiers after graphics layers on the node
808         invalidateLayers()
809     }
810 
811     /** The measured width of this layout and all of its [modifier]s. Shortcut for `size.width`. */
812     override val width: Int
813         get() = layoutDelegate.width
814 
815     /**
816      * The measured height of this layout and all of its [modifier]s. Shortcut for `size.height`.
817      */
818     override val height: Int
819         get() = layoutDelegate.height
820 
821     internal val alignmentLinesRequired: Boolean
822         get() =
823             layoutDelegate.run {
824                 alignmentLinesOwner.alignmentLines.required ||
825                     lookaheadAlignmentLinesOwner?.alignmentLines?.required == true
826             }
827 
828     internal val mDrawScope: LayoutNodeDrawScope
829         get() = requireOwner().sharedDrawScope
830 
831     /**
832      * Whether or not this [LayoutNode] and all of its parents have been placed in the hierarchy.
833      */
834     override val isPlaced: Boolean
835         get() = measurePassDelegate.isPlaced
836 
837     /**
838      * Whether or not this [LayoutNode] was placed by its parent. The node can still be considered
839      * not placed if some of the modifiers on it not placed the placeable.
840      */
841     val isPlacedByParent: Boolean
842         get() = measurePassDelegate.isPlacedByParent
843 
844     /**
845      * The order in which this node was placed by its parent during the previous `layoutChildren`.
846      * Before the placement the order is set to [NotPlacedPlaceOrder] to all the children. Then
847      * every placed node assigns this variable to [parent]s MeasurePassDelegate's
848      * nextChildPlaceOrder and increments this counter. Not placed items will still have
849      * [NotPlacedPlaceOrder] set.
850      */
851     internal val placeOrder: Int
852         get() = measurePassDelegate.placeOrder
853 
854     /** Remembers how the node was measured by the parent. */
855     internal val measuredByParent: UsageByParent
856         get() = measurePassDelegate.measuredByParent
857 
858     /** Remembers how the node was measured by the parent in lookahead. */
859     internal val measuredByParentInLookahead: UsageByParent
860         get() = lookaheadPassDelegate?.measuredByParent ?: UsageByParent.NotUsed
861 
862     /** Remembers how the node was measured using intrinsics by an ancestor. */
863     internal var intrinsicsUsageByParent: UsageByParent = UsageByParent.NotUsed
864 
865     /**
866      * We must cache a previous value of [intrinsicsUsageByParent] because measurement is sometimes
867      * skipped. When it is skipped, the subtree must be restored to this value.
868      */
869     private var previousIntrinsicsUsageByParent: UsageByParent = UsageByParent.NotUsed
870 
871     @Deprecated("Temporary API to support ConstraintLayout prototyping.")
872     internal var canMultiMeasure: Boolean = false
873 
874     internal val nodes = NodeChain(this)
875     internal val innerCoordinator: NodeCoordinator
876         get() = nodes.innerCoordinator
877 
878     internal val layoutDelegate = LayoutNodeLayoutDelegate(this)
879     internal val outerCoordinator: NodeCoordinator
880         get() = nodes.outerCoordinator
881 
882     /**
883      * zIndex defines the drawing order of the LayoutNode. Children with larger zIndex are drawn on
884      * top of others (the original order is used for the nodes with the same zIndex). Default zIndex
885      * is 0. We use sum of the values passed as zIndex to place() by the parent layout and all the
886      * applied modifiers.
887      */
888     private val zIndex: Float
889         get() = measurePassDelegate.zIndex
890 
891     /** The inner state associated with [androidx.compose.ui.layout.SubcomposeLayout]. */
892     internal var subcompositionsState: LayoutNodeSubcompositionsState? = null
893 
894     /** The inner-most layer coordinator. Used for performance for NodeCoordinator.findLayer(). */
895     private var _innerLayerCoordinator: NodeCoordinator? = null
896     internal var innerLayerCoordinatorIsDirty = true
897     internal val innerLayerCoordinator: NodeCoordinator?
898         get() {
899             if (innerLayerCoordinatorIsDirty) {
900                 var coordinator: NodeCoordinator? = innerCoordinator
901                 val final = outerCoordinator.wrappedBy
902                 _innerLayerCoordinator = null
903                 while (coordinator != final) {
904                     if (coordinator?.layer != null) {
905                         _innerLayerCoordinator = coordinator
906                         break
907                     }
908                     coordinator = coordinator?.wrappedBy
909                 }
910             }
911             val layerCoordinator = _innerLayerCoordinator
912             if (layerCoordinator != null) {
913                 checkPreconditionNotNull(layerCoordinator.layer) { "layer was not set" }
914             }
915             return layerCoordinator
916         }
917 
918     /**
919      * Invalidates the inner-most layer as part of this LayoutNode or from the containing
920      * LayoutNode. This is added for performance so that NodeCoordinator.invalidateLayer() can be
921      * faster.
922      */
923     internal fun invalidateLayer() {
924         val innerLayerCoordinator = innerLayerCoordinator
925         if (innerLayerCoordinator != null) {
926             innerLayerCoordinator.invalidateLayer()
927         } else {
928             val parent = this.parent
929             parent?.invalidateLayer()
930         }
931     }
932 
933     private var _modifier: Modifier = Modifier
934     private var pendingModifier: Modifier? = null
935     internal val applyingModifierOnAttach
936         get() = pendingModifier != null
937 
938     /** The [Modifier] currently applied to this node. */
939     override var modifier: Modifier
940         get() = _modifier
941         set(value) {
942             requirePrecondition(!isVirtual || modifier === Modifier) {
943                 "Modifiers are not supported on virtual LayoutNodes"
944             }
945             requirePrecondition(!isDeactivated) { "modifier is updated when deactivated" }
946             if (isAttached) {
947                 applyModifier(value)
948                 if (isSemanticsInvalidated) {
949                     invalidateSemantics()
950                 }
951             } else {
952                 pendingModifier = value
953             }
954         }
955 
956     private fun applyModifier(modifier: Modifier) {
957         val hadPointerInput = nodes.has(Nodes.PointerInput)
958         val hadFocusTarget = nodes.has(Nodes.FocusTarget)
959         _modifier = modifier
960         nodes.updateFrom(modifier)
961         val hasPointerInput = nodes.has(Nodes.PointerInput)
962         val hasFocusTarget = nodes.has(Nodes.FocusTarget)
963         layoutDelegate.updateParentData()
964         if (lookaheadRoot == null && nodes.has(Nodes.ApproachMeasure)) {
965             lookaheadRoot = this
966         }
967 
968         if (hadPointerInput != hasPointerInput || hadFocusTarget != hasFocusTarget) {
969             requireOwner().rectManager.updateFlagsFor(this, hasFocusTarget, hasPointerInput)
970         }
971     }
972 
973     private fun resetModifierState() {
974         nodes.resetState()
975     }
976 
977     internal fun invalidateParentData() {
978         layoutDelegate.invalidateParentData()
979     }
980 
981     /**
982      * Coordinates of just the contents of the [LayoutNode], after being affected by all modifiers.
983      */
984     override val coordinates: LayoutCoordinates
985         get() = innerCoordinator
986 
987     /** Callback to be executed whenever the [LayoutNode] is attached to a new [Owner]. */
988     internal var onAttach: ((Owner) -> Unit)? = null
989 
990     /** Callback to be executed whenever the [LayoutNode] is detached from an [Owner]. */
991     internal var onDetach: ((Owner) -> Unit)? = null
992 
993     /**
994      * Flag used by [OnPositionedDispatcher] to identify LayoutNodes that have already had their
995      * [OnGloballyPositionedModifier]'s dispatch called so that they aren't called multiple times.
996      */
997     internal var needsOnPositionedDispatch = false
998 
999     internal fun place(x: Int, y: Int) {
1000         if (intrinsicsUsageByParent == UsageByParent.NotUsed) {
1001             // This LayoutNode may have asked children for intrinsics. If so, we should
1002             // clear the intrinsics usage for everything that was requested previously.
1003             clearSubtreePlacementIntrinsicsUsage()
1004         }
1005         with(parent?.innerCoordinator?.placementScope ?: requireOwner().placementScope) {
1006             measurePassDelegate.placeRelative(x, y)
1007         }
1008     }
1009 
1010     /** Place this layout node again on the same position it was placed last time */
1011     internal fun replace() {
1012         if (intrinsicsUsageByParent == UsageByParent.NotUsed) {
1013             // This LayoutNode may have asked children for intrinsics. If so, we should
1014             // clear the intrinsics usage for everything that was requested previously.
1015             clearSubtreePlacementIntrinsicsUsage()
1016         }
1017         measurePassDelegate.replace()
1018     }
1019 
1020     internal fun lookaheadReplace() {
1021         if (intrinsicsUsageByParent == UsageByParent.NotUsed) {
1022             // This LayoutNode may have asked children for intrinsics. If so, we should
1023             // clear the intrinsics usage for everything that was requested previously.
1024             clearSubtreePlacementIntrinsicsUsage()
1025         }
1026         lookaheadPassDelegate!!.replace()
1027     }
1028 
1029     internal fun draw(canvas: Canvas, graphicsLayer: GraphicsLayer?) =
1030         withComposeStackTrace(this) { outerCoordinator.draw(canvas, graphicsLayer) }
1031 
1032     /**
1033      * Carries out a hit test on the [PointerInputModifier]s associated with this [LayoutNode] and
1034      * all [PointerInputModifier]s on all descendant [LayoutNode]s.
1035      *
1036      * If [pointerPosition] is within the bounds of any tested [PointerInputModifier]s, the
1037      * [PointerInputModifier] is added to [hitTestResult] and true is returned.
1038      *
1039      * @param pointerPosition The tested pointer position, which is relative to the LayoutNode.
1040      * @param hitTestResult The collection that the hit [PointerInputFilter]s will be added to if
1041      *   hit.
1042      */
1043     internal fun hitTest(
1044         pointerPosition: Offset,
1045         hitTestResult: HitTestResult,
1046         pointerType: PointerType = PointerType.Unknown,
1047         isInLayer: Boolean = true
1048     ) {
1049         val positionInWrapped = outerCoordinator.fromParentPosition(pointerPosition)
1050         outerCoordinator.hitTest(
1051             NodeCoordinator.PointerInputSource,
1052             positionInWrapped,
1053             hitTestResult,
1054             pointerType,
1055             isInLayer
1056         )
1057     }
1058 
1059     @Suppress("UNUSED_PARAMETER")
1060     internal fun hitTestSemantics(
1061         pointerPosition: Offset,
1062         hitSemanticsEntities: HitTestResult,
1063         pointerType: PointerType = PointerType.Touch,
1064         isInLayer: Boolean = true
1065     ) {
1066         val positionInWrapped = outerCoordinator.fromParentPosition(pointerPosition)
1067         outerCoordinator.hitTest(
1068             NodeCoordinator.SemanticsSource,
1069             positionInWrapped,
1070             hitSemanticsEntities,
1071             pointerType = PointerType.Touch,
1072             isInLayer = isInLayer
1073         )
1074     }
1075 
1076     internal fun rescheduleRemeasureOrRelayout(it: LayoutNode) {
1077         when (it.layoutState) {
1078             Idle -> {
1079                 // this node was scheduled for remeasure or relayout while it was not
1080                 // placed. such requests are ignored for non-placed nodes so we have to
1081                 // re-schedule remeasure or relayout.
1082                 if (it.lookaheadMeasurePending) {
1083                     it.requestLookaheadRemeasure(forceRequest = true)
1084                 } else {
1085                     if (it.lookaheadLayoutPending) {
1086                         it.requestLookaheadRelayout(forceRequest = true)
1087                     }
1088                     if (it.measurePending) {
1089                         it.requestRemeasure(forceRequest = true)
1090                     } else if (it.layoutPending) {
1091                         it.requestRelayout(forceRequest = true)
1092                     }
1093                 }
1094             }
1095             else -> throw IllegalStateException("Unexpected state ${it.layoutState}")
1096         }
1097     }
1098 
1099     /** Used to request a new measurement + layout pass from the owner. */
1100     internal fun requestRemeasure(
1101         forceRequest: Boolean = false,
1102         scheduleMeasureAndLayout: Boolean = true,
1103         invalidateIntrinsics: Boolean = true
1104     ) {
1105         if (!ignoreRemeasureRequests && !isVirtual) {
1106             val owner = owner ?: return
1107             owner.onRequestMeasure(
1108                 layoutNode = this,
1109                 forceRequest = forceRequest,
1110                 scheduleMeasureAndLayout = scheduleMeasureAndLayout
1111             )
1112             if (invalidateIntrinsics) {
1113                 measurePassDelegate.invalidateIntrinsicsParent(forceRequest)
1114             }
1115         }
1116     }
1117 
1118     /**
1119      * Used to request a new lookahead measurement, lookahead layout, and subsequently measure and
1120      * layout from the owner.
1121      */
1122     internal fun requestLookaheadRemeasure(
1123         forceRequest: Boolean = false,
1124         scheduleMeasureAndLayout: Boolean = true,
1125         invalidateIntrinsics: Boolean = true
1126     ) {
1127         checkPrecondition(lookaheadRoot != null) {
1128             "Lookahead measure cannot be requested on a node that is not a part of the " +
1129                 "LookaheadScope"
1130         }
1131         val owner = owner ?: return
1132         if (!ignoreRemeasureRequests && !isVirtual) {
1133             owner.onRequestMeasure(
1134                 layoutNode = this,
1135                 affectsLookahead = true,
1136                 forceRequest = forceRequest,
1137                 scheduleMeasureAndLayout = scheduleMeasureAndLayout
1138             )
1139             if (invalidateIntrinsics) {
1140                 lookaheadPassDelegate!!.invalidateIntrinsicsParent(forceRequest)
1141             }
1142         }
1143     }
1144 
1145     /**
1146      * This gets called when both lookahead measurement (if in a LookaheadScope) and actual
1147      * measurement need to be re-done. Such events include modifier change, attach/detach, etc.
1148      */
1149     internal fun invalidateMeasurements() {
1150         if (isVirtual) {
1151             // If the node is virtual, we need to invalidate the parent node (as it is non-virtual)
1152             // instead so that children get properly invalidated.
1153             parent?.invalidateMeasurements()
1154             return
1155         }
1156         outerToInnerOffsetDirty = true
1157         if (lookaheadRoot != null) {
1158             requestLookaheadRemeasure()
1159         } else {
1160             requestRemeasure()
1161         }
1162     }
1163 
1164     internal fun invalidateOnPositioned() {
1165         // If we've already scheduled a measure, the positioned callbacks will get called anyway
1166         if (layoutPending || measurePending || needsOnPositionedDispatch) return
1167         requireOwner().requestOnPositionedCallback(this)
1168     }
1169 
1170     internal inline fun <T> ignoreRemeasureRequests(block: () -> T): T {
1171         ignoreRemeasureRequests = true
1172         val result = block()
1173         ignoreRemeasureRequests = false
1174         return result
1175     }
1176 
1177     /** Used to request a new layout pass from the owner. */
1178     internal fun requestRelayout(forceRequest: Boolean = false) {
1179         outerToInnerOffsetDirty = true
1180         if (!isVirtual) {
1181             owner?.onRequestRelayout(this, forceRequest = forceRequest)
1182         }
1183     }
1184 
1185     internal fun requestLookaheadRelayout(forceRequest: Boolean = false) {
1186         if (!isVirtual) {
1187             owner?.onRequestRelayout(this, affectsLookahead = true, forceRequest)
1188         }
1189     }
1190 
1191     internal fun dispatchOnPositionedCallbacks() {
1192         if (layoutState != Idle || layoutPending || measurePending || isDeactivated) {
1193             return // it hasn't yet been properly positioned, so don't make a call
1194         }
1195         if (!isPlaced) {
1196             return // it hasn't been placed, so don't make a call
1197         }
1198         nodes.headToTail(Nodes.GlobalPositionAware) {
1199             it.onGloballyPositioned(it.requireCoordinator(Nodes.GlobalPositionAware))
1200         }
1201     }
1202 
1203     /**
1204      * This returns a new List of Modifiers and the coordinates and any extra information that may
1205      * be useful. This is used for tooling to retrieve layout modifier and layer information.
1206      */
1207     override fun getModifierInfo(): List<ModifierInfo> = nodes.getModifierInfo()
1208 
1209     /** Invalidates layers defined on this LayoutNode. */
1210     internal fun invalidateLayers() {
1211         forEachCoordinator { coordinator -> coordinator.layer?.invalidate() }
1212         innerCoordinator.layer?.invalidate()
1213     }
1214 
1215     internal fun lookaheadRemeasure(
1216         constraints: Constraints? = layoutDelegate.lastLookaheadConstraints
1217     ): Boolean {
1218         // Only lookahead remeasure when the constraints are valid and the node is in
1219         // a LookaheadScope (by checking whether the lookaheadScope is set)
1220         return if (constraints != null && lookaheadRoot != null) {
1221             lookaheadPassDelegate!!.remeasure(constraints)
1222         } else {
1223             false
1224         }
1225     }
1226 
1227     /** Return true if the measured size has been changed */
1228     internal fun remeasure(constraints: Constraints? = layoutDelegate.lastConstraints): Boolean {
1229         return if (constraints != null) {
1230             if (intrinsicsUsageByParent == UsageByParent.NotUsed) {
1231                 // This LayoutNode may have asked children for intrinsics. If so, we should
1232                 // clear the intrinsics usage for everything that was requested previously.
1233                 clearSubtreeIntrinsicsUsage()
1234             }
1235             measurePassDelegate.remeasure(constraints)
1236         } else {
1237             false
1238         }
1239     }
1240 
1241     /**
1242      * Tracks whether another measure pass is needed for the LayoutNode. Mutation to
1243      * [measurePending] is confined to LayoutNodeLayoutDelegate. It can only be set true from
1244      * outside of LayoutNode via [markMeasurePending]. It is cleared (i.e. set false) during the
1245      * measure pass ( i.e. in [LayoutNodeLayoutDelegate.performMeasure]).
1246      */
1247     internal val measurePending: Boolean
1248         get() = layoutDelegate.measurePending
1249 
1250     /**
1251      * Tracks whether another layout pass is needed for the LayoutNode. Mutation to [layoutPending]
1252      * is confined to LayoutNode. It can only be set true from outside of LayoutNode via
1253      * [markLayoutPending]. It is cleared (i.e. set false) during the layout pass (i.e. in
1254      * layoutChildren).
1255      */
1256     internal val layoutPending: Boolean
1257         get() = layoutDelegate.layoutPending
1258 
1259     internal val lookaheadMeasurePending: Boolean
1260         get() = layoutDelegate.lookaheadMeasurePending
1261 
1262     internal val lookaheadLayoutPending: Boolean
1263         get() = layoutDelegate.lookaheadLayoutPending
1264 
1265     /** Marks the layoutNode dirty for another layout pass. */
1266     internal fun markLayoutPending() = layoutDelegate.markLayoutPending()
1267 
1268     /** Marks the layoutNode dirty for another measure pass. */
1269     internal fun markMeasurePending() = layoutDelegate.markMeasurePending()
1270 
1271     /** Marks the layoutNode dirty for another lookahead layout pass. */
1272     internal fun markLookaheadLayoutPending() = layoutDelegate.markLookaheadLayoutPending()
1273 
1274     fun invalidateSubtree(isRootOfInvalidation: Boolean = true) {
1275         if (isRootOfInvalidation) {
1276             parent?.invalidateLayer()
1277         }
1278         invalidateSemantics()
1279         requestRemeasure()
1280         nodes.headToTail(Nodes.Layout) { it.requireCoordinator(Nodes.Layout).layer?.invalidate() }
1281         // TODO: invalidate parent data
1282         _children.forEach { it.invalidateSubtree(false) }
1283     }
1284 
1285     /** Marks the layoutNode dirty for another lookahead measure pass. */
1286     internal fun markLookaheadMeasurePending() = layoutDelegate.markLookaheadMeasurePending()
1287 
1288     override fun forceRemeasure() {
1289         // we do not schedule measure and layout as we are going to call it manually right after
1290         if (lookaheadRoot != null) {
1291             requestLookaheadRemeasure(scheduleMeasureAndLayout = false)
1292         } else {
1293             requestRemeasure(scheduleMeasureAndLayout = false)
1294         }
1295         val lastConstraints = layoutDelegate.lastConstraints
1296         if (lastConstraints != null) {
1297             owner?.measureAndLayout(this, lastConstraints)
1298         } else {
1299             owner?.measureAndLayout()
1300         }
1301     }
1302 
1303     override fun onLayoutComplete() {
1304         innerCoordinator.visitNodes(Nodes.LayoutAware) { it.onPlaced(innerCoordinator) }
1305     }
1306 
1307     /** Calls [block] on all [LayoutModifierNodeCoordinator]s in the NodeCoordinator chain. */
1308     internal inline fun forEachCoordinator(block: (LayoutModifierNodeCoordinator) -> Unit) {
1309         var coordinator: NodeCoordinator? = outerCoordinator
1310         val inner = innerCoordinator
1311         while (coordinator !== inner) {
1312             block(coordinator as LayoutModifierNodeCoordinator)
1313             coordinator = coordinator.wrapped
1314         }
1315     }
1316 
1317     /** Calls [block] on all [NodeCoordinator]s in the NodeCoordinator chain. */
1318     internal inline fun forEachCoordinatorIncludingInner(block: (NodeCoordinator) -> Unit) {
1319         var delegate: NodeCoordinator? = outerCoordinator
1320         val final = innerCoordinator.wrapped
1321         while (delegate != final && delegate != null) {
1322             block(delegate)
1323             delegate = delegate.wrapped
1324         }
1325     }
1326 
1327     /**
1328      * Walks the subtree and clears all [intrinsicsUsageByParent] that this LayoutNode's measurement
1329      * used intrinsics on.
1330      *
1331      * The layout that asks for intrinsics of its children is the node to call this to request all
1332      * of its subtree to be cleared.
1333      *
1334      * We can't do clearing as part of measure() because the child's measure() call is normally done
1335      * after the intrinsics is requested and we don't want to clear the usage at that point.
1336      */
1337     internal fun clearSubtreeIntrinsicsUsage() {
1338         // save the usage in case we short-circuit the measure call
1339         previousIntrinsicsUsageByParent = intrinsicsUsageByParent
1340         intrinsicsUsageByParent = UsageByParent.NotUsed
1341         forEachChild {
1342             if (it.intrinsicsUsageByParent != UsageByParent.NotUsed) {
1343                 it.clearSubtreeIntrinsicsUsage()
1344             }
1345         }
1346     }
1347 
1348     /**
1349      * Walks the subtree and clears all [intrinsicsUsageByParent] that this LayoutNode's layout
1350      * block used intrinsics on.
1351      *
1352      * The layout that asks for intrinsics of its children is the node to call this to request all
1353      * of its subtree to be cleared.
1354      *
1355      * We can't do clearing as part of measure() because the child's measure() call is normally done
1356      * after the intrinsics is requested and we don't want to clear the usage at that point.
1357      */
1358     private fun clearSubtreePlacementIntrinsicsUsage() {
1359         // save the usage in case we short-circuit the measure call
1360         previousIntrinsicsUsageByParent = intrinsicsUsageByParent
1361         intrinsicsUsageByParent = UsageByParent.NotUsed
1362         forEachChild {
1363             if (it.intrinsicsUsageByParent == UsageByParent.InLayoutBlock) {
1364                 it.clearSubtreePlacementIntrinsicsUsage()
1365             }
1366         }
1367     }
1368 
1369     /**
1370      * For a subtree that skips measurement, this resets the [intrinsicsUsageByParent] to what it
1371      * was prior to [clearSubtreeIntrinsicsUsage].
1372      */
1373     internal fun resetSubtreeIntrinsicsUsage() {
1374         forEachChild {
1375             it.intrinsicsUsageByParent = it.previousIntrinsicsUsageByParent
1376             if (it.intrinsicsUsageByParent != UsageByParent.NotUsed) {
1377                 it.resetSubtreeIntrinsicsUsage()
1378             }
1379         }
1380     }
1381 
1382     override val parentInfo: SemanticsInfo?
1383         get() = parent
1384 
1385     override val childrenInfo: List<SemanticsInfo>
1386         get() = children
1387 
1388     override var isDeactivated = false
1389         private set
1390 
1391     override fun onReuse() {
1392         requirePrecondition(isAttached) { "onReuse is only expected on attached node" }
1393         if (@OptIn(ExperimentalComposeUiApi::class) !ComposeUiFlags.isRemoveFocusedViewFixEnabled) {
1394             interopViewFactoryHolder?.onReuse()
1395             subcompositionsState?.onReuse()
1396         }
1397         isCurrentlyCalculatingSemanticsConfiguration = false
1398         if (isDeactivated) {
1399             isDeactivated = false
1400             if (@OptIn(ExperimentalComposeUiApi::class) !ComposeUiFlags.isSemanticAutofillEnabled) {
1401                 invalidateSemantics()
1402             }
1403             // we don't need to reset state as it was done when deactivated
1404         } else {
1405             resetModifierState()
1406         }
1407         val oldSemanticsId = semanticsId
1408         semanticsId = generateSemanticsId()
1409         owner?.onPreLayoutNodeReused(this, oldSemanticsId)
1410         if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isRemoveFocusedViewFixEnabled) {
1411             interopViewFactoryHolder?.onReuse()
1412             subcompositionsState?.onReuse()
1413         }
1414         // resetModifierState detaches all nodes, so we need to re-attach them upon reuse.
1415         nodes.markAsAttached()
1416         nodes.runAttachLifecycle()
1417         @OptIn(ExperimentalComposeUiApi::class)
1418         if (ComposeUiFlags.isSemanticAutofillEnabled && nodes.has(Nodes.Semantics)) {
1419             invalidateSemantics()
1420         }
1421         rescheduleRemeasureOrRelayout(this)
1422         owner?.onPostLayoutNodeReused(this, oldSemanticsId)
1423     }
1424 
1425     override fun onDeactivate() {
1426         if (@OptIn(ExperimentalComposeUiApi::class) !ComposeUiFlags.isRemoveFocusedViewFixEnabled) {
1427             interopViewFactoryHolder?.onDeactivate()
1428             subcompositionsState?.onDeactivate()
1429         }
1430         isDeactivated = true
1431         resetModifierState()
1432         // if the node is detached the semantics were already updated without this node.
1433         if (isAttached) {
1434             if (@OptIn(ExperimentalComposeUiApi::class) !ComposeUiFlags.isSemanticAutofillEnabled) {
1435                 invalidateSemantics()
1436             } else {
1437                 _semanticsConfiguration = null
1438                 isSemanticsInvalidated = false
1439             }
1440         }
1441         owner?.onLayoutNodeDeactivated(this)
1442         if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isRemoveFocusedViewFixEnabled) {
1443             interopViewFactoryHolder?.onDeactivate()
1444             subcompositionsState?.onDeactivate()
1445         }
1446     }
1447 
1448     override fun onRelease() {
1449         if (@OptIn(ExperimentalComposeUiApi::class) !ComposeUiFlags.isRemoveFocusedViewFixEnabled) {
1450             interopViewFactoryHolder?.onRelease()
1451             subcompositionsState?.onRelease()
1452         }
1453         forEachCoordinatorIncludingInner { it.onRelease() }
1454         if (@OptIn(ExperimentalComposeUiApi::class) ComposeUiFlags.isRemoveFocusedViewFixEnabled) {
1455             interopViewFactoryHolder?.onRelease()
1456             subcompositionsState?.onRelease()
1457         }
1458     }
1459 
1460     internal companion object {
1461         private val ErrorMeasurePolicy: NoIntrinsicsMeasurePolicy =
1462             object :
1463                 NoIntrinsicsMeasurePolicy(error = "Undefined intrinsics block and it is required") {
1464                 override fun MeasureScope.measure(
1465                     measurables: List<Measurable>,
1466                     constraints: Constraints
1467                 ) = error("Undefined measure and it is required")
1468             }
1469 
1470         /** Constant used by [placeOrder]. */
1471         @Suppress("ConstPropertyName") internal const val NotPlacedPlaceOrder = Int.MAX_VALUE
1472 
1473         /** Pre-allocated constructor to be used with ComposeNode */
1474         internal val Constructor: () -> LayoutNode = { LayoutNode() }
1475 
1476         /**
1477          * All of these values are only used in tests. The real ViewConfiguration should be set in
1478          * Layout()
1479          */
1480         internal val DummyViewConfiguration =
1481             object : ViewConfiguration {
1482                 override val longPressTimeoutMillis: Long
1483                     get() = 400L
1484 
1485                 override val doubleTapTimeoutMillis: Long
1486                     get() = 300L
1487 
1488                 override val doubleTapMinTimeMillis: Long
1489                     get() = 40L
1490 
1491                 override val touchSlop: Float
1492                     get() = 16f
1493 
1494                 override val minimumTouchTargetSize: DpSize
1495                     get() = DpSize.Zero
1496             }
1497 
1498         /** Comparator allowing to sort nodes by zIndex and placement order. */
1499         internal val ZComparator =
1500             Comparator<LayoutNode> { node1, node2 ->
1501                 if (node1.zIndex == node2.zIndex) {
1502                     // if zIndex is the same we use the placement order
1503                     node1.placeOrder.compareTo(node2.placeOrder)
1504                 } else {
1505                     node1.zIndex.compareTo(node2.zIndex)
1506                 }
1507             }
1508     }
1509 
1510     /**
1511      * Describes the current state the [LayoutNode] is in. A [LayoutNode] is expected to be in
1512      * [LookaheadMeasuring] first, followed by [LookaheadLayingOut] if it is in a LookaheadScope.
1513      * After the lookahead is finished, [Measuring] and then [LayingOut] will happen as needed.
1514      */
1515     internal enum class LayoutState {
1516         /** Node is currently being measured. */
1517         Measuring,
1518 
1519         /** Node is being measured in lookahead. */
1520         LookaheadMeasuring,
1521 
1522         /** Node is currently being laid out. */
1523         LayingOut,
1524 
1525         /** Node is being laid out in lookahead. */
1526         LookaheadLayingOut,
1527 
1528         /**
1529          * Node is not currently measuring or laying out. It could be pending measure or pending
1530          * layout depending on the [measurePending] and [layoutPending] flags.
1531          */
1532         Idle,
1533     }
1534 
1535     internal enum class UsageByParent {
1536         InMeasureBlock,
1537         InLayoutBlock,
1538         NotUsed,
1539     }
1540 }
1541 
withComposeStackTracenull1542 internal inline fun <T> withComposeStackTrace(layoutNode: LayoutNode, block: () -> T): T =
1543     try {
1544         block()
1545     } catch (e: Throwable) {
1546         layoutNode.rethrowWithComposeStackTrace(e)
1547     }
1548 
1549 /** Returns [LayoutNode.owner] or throws if it is null. */
requireOwnernull1550 internal fun LayoutNode.requireOwner(): Owner {
1551     val owner = owner
1552     checkPreconditionNotNull(owner) { "LayoutNode should be attached to an owner" }
1553     return owner
1554 }
1555 
1556 /**
1557  * Inserts a child [LayoutNode] at a last index. If this LayoutNode [LayoutNode.isAttached] then
1558  * [child] will become [LayoutNode.isAttached] also. [child] must have a `null` [LayoutNode.parent].
1559  */
addnull1560 internal fun LayoutNode.add(child: LayoutNode) {
1561     insertAt(children.size, child)
1562 }
1563