static nsIFrame*
GetClosest(nsIFrame* aRoot, const nsPoint& aPointRelativeToRootFrame,
           const nsRect& aTargetRect, const EventRadiusPrefs* aPrefs,
           nsIFrame* aRestrictToDescendants, nsTArray<nsIFrame*>& aCandidates)
{
    nsIFrame* bestTarget = nullptr;
    // Lower is better; distance is in appunits
    float bestDistance = 1e6f;
    nsRegion exposedRegion(aTargetRect);
    for (uint32_t i = 0; i < aCandidates.Length(); ++i) {
        nsIFrame* f = aCandidates[i];

        bool preservesAxisAlignedRectangles = false;
        nsRect borderBox = nsLayoutUtils::TransformFrameRectToAncestor(f,
                           nsRect(nsPoint(0, 0), f->GetSize()), aRoot, &preservesAxisAlignedRectangles);
        nsRegion region;
        region.And(exposedRegion, borderBox);

        if (region.IsEmpty()) {
            continue;
        }

        if (preservesAxisAlignedRectangles) {
            // Subtract from the exposed region if we have a transform that won't make
            // the bounds include a bunch of area that we don't actually cover.
            SubtractFromExposedRegion(&exposedRegion, region);
        }

        if (!IsElementClickable(f)) {
            continue;
        }
        // If our current closest frame is a descendant of 'f', skip 'f' (prefer
        // the nested frame).
        if (bestTarget && nsLayoutUtils::IsProperAncestorFrameCrossDoc(f, bestTarget, aRoot)) {
            continue;
        }
        if (!nsLayoutUtils::IsAncestorFrameCrossDoc(aRestrictToDescendants, f, aRoot)) {
            continue;
        }

        // distance is in appunits
        float distance = ComputeDistanceFromRegion(aPointRelativeToRootFrame, region);
        nsIContent* content = f->GetContent();
        if (content && content->IsElement() &&
                content->AsElement()->State().HasState(
                    EventStates(NS_EVENT_STATE_VISITED))) {
            distance *= aPrefs->mVisitedWeight / 100.0f;
        }
        if (distance < bestDistance) {
            bestDistance = distance;
            bestTarget = f;
        }
    }
    return bestTarget;
}
static nsIFrame*
GetClosest(nsIFrame* aRoot, const nsPoint& aPointRelativeToRootFrame,
           const nsRect& aTargetRect, const EventRadiusPrefs* aPrefs,
           nsIFrame* aRestrictToDescendants, nsIContent* aClickableAncestor,
           nsTArray<nsIFrame*>& aCandidates, int32_t* aElementsInCluster)
{
  std::vector<nsIContent*> mContentsInCluster;  // List of content elements in the cluster without duplicate
  nsIFrame* bestTarget = nullptr;
  // Lower is better; distance is in appunits
  float bestDistance = 1e6f;
  nsRegion exposedRegion(aTargetRect);
  for (uint32_t i = 0; i < aCandidates.Length(); ++i) {
    nsIFrame* f = aCandidates[i];
    PET_LOG("Checking candidate %p\n", f);

    bool preservesAxisAlignedRectangles = false;
    nsRect borderBox = nsLayoutUtils::TransformFrameRectToAncestor(f,
        nsRect(nsPoint(0, 0), f->GetSize()), aRoot, &preservesAxisAlignedRectangles);
    nsRegion region;
    region.And(exposedRegion, borderBox);
    if (region.IsEmpty()) {
      PET_LOG("  candidate %p had empty hit region\n", f);
      continue;
    }

    if (preservesAxisAlignedRectangles) {
      // Subtract from the exposed region if we have a transform that won't make
      // the bounds include a bunch of area that we don't actually cover.
      SubtractFromExposedRegion(&exposedRegion, region);
    }

    nsAutoString labelTargetId;
    if (aClickableAncestor && !IsDescendant(f, aClickableAncestor, &labelTargetId)) {
      PET_LOG("  candidate %p is not a descendant of required ancestor\n", f);
      continue;
    }

    nsIContent* clickableContent = GetClickableAncestor(f, nsGkAtoms::body, &labelTargetId);
    if (!aClickableAncestor && !clickableContent) {
      PET_LOG("  candidate %p was not clickable\n", f);
      continue;
    }
    // If our current closest frame is a descendant of 'f', skip 'f' (prefer
    // the nested frame).
    if (bestTarget && nsLayoutUtils::IsProperAncestorFrameCrossDoc(f, bestTarget, aRoot)) {
      PET_LOG("  candidate %p was ancestor for bestTarget %p\n", f, bestTarget);
      continue;
    }
    if (!aClickableAncestor && !nsLayoutUtils::IsAncestorFrameCrossDoc(aRestrictToDescendants, f, aRoot)) {
      PET_LOG("  candidate %p was not descendant of restrictroot %p\n", f, aRestrictToDescendants);
      continue;
    }

    // If the first clickable ancestor of f is a label element
    // and "for" attribute is present in label element, search the frame list for the "for" element
    // If this element is present in the current list, do not count the frame in
    // the cluster elements counter
    if ((labelTargetId.IsEmpty() || !IsElementPresent(aCandidates, labelTargetId)) &&
        !IsLargeElement(f, aPrefs)) {
      if (std::find(mContentsInCluster.begin(), mContentsInCluster.end(), clickableContent) == mContentsInCluster.end()) {
        mContentsInCluster.push_back(clickableContent);
      }
    }

    // distance is in appunits
    float distance = ComputeDistanceFromRegion(aPointRelativeToRootFrame, region);
    nsIContent* content = f->GetContent();
    if (content && content->IsElement() &&
        content->AsElement()->State().HasState(
                                        EventStates(NS_EVENT_STATE_VISITED))) {
      distance *= aPrefs->mVisitedWeight / 100.0f;
    }
    if (distance < bestDistance) {
      PET_LOG("  candidate %p is the new best\n", f);
      bestDistance = distance;
      bestTarget = f;
    }
  }
  *aElementsInCluster = mContentsInCluster.size();
  return bestTarget;
}