markNeedsSemanticsUpdate method

void markNeedsSemanticsUpdate ()

Mark this node as needing an update to its semantics description.

This must be called whenever the semantics configuration of this RenderObject as annotated by describeSemanticsConfiguration changes in any way to update the semantics tree.

Implementation

void markNeedsSemanticsUpdate() {
  assert(!attached || !owner._debugDoingSemantics);
  if (!attached || owner._semanticsOwner == null) {
    _cachedSemanticsConfiguration = null;
    return;
  }

  // Dirty the semantics tree starting at `this` until we have reached a
  // RenderObject that is a semantics boundary. All semantics past this
  // RenderObject are still up-to date. Therefore, we will later only rebuild
  // the semantics subtree starting at the identified semantics boundary.

  final bool wasSemanticsBoundary = _semantics != null && _cachedSemanticsConfiguration?.isSemanticBoundary == true;
  _cachedSemanticsConfiguration = null;
  bool isEffectiveSemanticsBoundary = _semanticsConfiguration.isSemanticBoundary && wasSemanticsBoundary;
  RenderObject node = this;

  while (!isEffectiveSemanticsBoundary && node.parent is RenderObject) {
    if (node != this && node._needsSemanticsUpdate)
      break;
    node._needsSemanticsUpdate = true;

    node = node.parent;
    isEffectiveSemanticsBoundary = node._semanticsConfiguration.isSemanticBoundary;
    if (isEffectiveSemanticsBoundary && node._semantics == null) {
      // We have reached a semantics boundary that doesn't own a semantics node.
      // That means the semantics of this branch are currently blocked and will
      // not appear in the semantics tree. We can abort the walk here.
      return;
    }
  }
  if (node != this && _semantics != null && _needsSemanticsUpdate) {
    // If `this` node has already been added to [owner._nodesNeedingSemantics]
    // remove it as it is no longer guaranteed that its semantics
    // node will continue to be in the tree. If it still is in the tree, the
    // ancestor `node` added to [owner._nodesNeedingSemantics] at the end of
    // this block will ensure that the semantics of `this` node actually gets
    // updated.
    // (See semantics_10_test.dart for an example why this is required).
    owner._nodesNeedingSemantics.remove(this);
  }
  if (!node._needsSemanticsUpdate) {
    node._needsSemanticsUpdate = true;
    if (owner != null) {
      assert(node._semanticsConfiguration.isSemanticBoundary || node.parent is! RenderObject);
      owner._nodesNeedingSemantics.add(node);
      owner.requestVisualUpdate();
    }
  }
}