void sendSemanticsUpdate()

Update the semantics using ui.window.updateSemantics.

Source

void sendSemanticsUpdate() {
  for (SemanticsNode oldNode in _detachedNodes) {
    // The other side will have forgotten this node if we even send
    // it again, so make sure to mark it dirty so that it'll get
    // sent if it is resurrected.
    oldNode._dirty = true;
  }
  _detachedNodes.clear();
  if (_dirtyNodes.isEmpty)
    return;
  List<SemanticsNode> visitedNodes = <SemanticsNode>[];
  while (_dirtyNodes.isNotEmpty) {
    List<SemanticsNode> localDirtyNodes = _dirtyNodes.toList();
    _dirtyNodes.clear();
    localDirtyNodes.sort((SemanticsNode a, SemanticsNode b) => a.depth - b.depth);
    visitedNodes.addAll(localDirtyNodes);
    for (SemanticsNode node in localDirtyNodes) {
      assert(node._dirty);
      assert(node.parent == null || !node.parent._shouldMergeAllDescendantsIntoThisNode || node._inheritedMergeAllDescendantsIntoThisNode);
      if (node._shouldMergeAllDescendantsIntoThisNode) {
        assert(node.mergeAllDescendantsIntoThisNode || node.parent != null);
        if (node.mergeAllDescendantsIntoThisNode ||
            node.parent != null && node.parent._shouldMergeAllDescendantsIntoThisNode) {
          // if we're merged into our parent, make sure our parent is added to the list
          if (node.parent != null && node.parent._shouldMergeAllDescendantsIntoThisNode)
            node.parent._markDirty(); // this can add the node to the dirty list
          // make sure all the descendants are also marked, so that if one gets marked dirty later we know to walk up then too
          if (node._children != null) {
            for (SemanticsNode child in node._children)
              child._inheritedMergeAllDescendantsIntoThisNode = true; // this can add the node to the dirty list
          }
        } else {
          // we previously were being merged but aren't any more
          // update our bits and all our descendants'
          assert(node._inheritedMergeAllDescendantsIntoThisNode);
          assert(!node.mergeAllDescendantsIntoThisNode);
          assert(node.parent == null || !node.parent._shouldMergeAllDescendantsIntoThisNode);
          node._inheritedMergeAllDescendantsIntoThisNode = false;
          if (node._children != null) {
            for (SemanticsNode child in node._children)
              child._inheritedMergeAllDescendantsIntoThisNode = false; // this can add the node to the dirty list
          }
        }
      }
    }
  }
  visitedNodes.sort((SemanticsNode a, SemanticsNode b) => a.depth - b.depth);
  ui.SemanticsUpdateBuilder builder = new ui.SemanticsUpdateBuilder();
  for (SemanticsNode node in visitedNodes) {
    assert(node.parent?._dirty != true); // could be null (no parent) or false (not dirty)
    // The _serialize() method marks the node as not dirty, and
    // recurses through the tree to do a deep serialization of all
    // contiguous dirty nodes. This means that when we return here,
    // it's quite possible that subsequent nodes are no longer
    // dirty. We skip these here.
    // We also skip any nodes that were reset and subsequently
    // dropped entirely (RenderObject.markNeedsSemanticsUpdate()
    // calls reset() on its SemanticsNode if onlyChanges isn't set,
    // which happens e.g. when the node is no longer contributing
    // semantics).
    if (node._dirty && node.attached)
      node._addToUpdate(builder);
  }
  _dirtyNodes.clear();
  ui.window.updateSemantics(builder.build());
  notifyListeners();
}