hitTest method

List<String> hitTest(
  1. double x,
  2. double y
)

The nodes under a point, outermost first.

Answers "what is at these pixels", which is one question asked by two callers: a panel turning a click into a selection, and an agent turning a screenshot into a node id. Both get the chain rather than the innermost hit, because the useful answer is usually a few levels out — the thing under the cursor is a RenderParagraph and the thing you meant is the button around it.

x and y are in the guest's own coordinates, the same space InspectLayout.x reports and a capture is taken in.

Implementation

List<String> hitTest(double x, double y) {
  var (:tree, :byRenderObject) = _build();
  if (tree.root == null) return const [];
  var root = rootOf()?.renderObject;
  if (root is! RenderBox || !root.hasSize) return const [];

  // In the demo root's own coordinates — the window's for an embedder
  // guest, whose root is the window, and the picture's for a guest drawn
  // inside its host. The boxes the tree reports are in the same space.
  var result = BoxHitTestResult();
  root.hitTest(result, position: Offset(x, y));

  // Innermost first out of the framework, and reversed on the way out: a
  // caller reading a chain wants it the way the tree reads.
  var ids = <String>[];
  for (var entry in result.path) {
    var id = byRenderObject[entry.target];
    // The hit path is render objects, and most of them belong to widgets no
    // summary tree mentions. Those are not "no answer", they are the
    // framework's internals, so they are skipped rather than reported.
    if (id != null && !ids.contains(id)) ids.add(id);
  }
  return ids.reversed.toList();
}