Java Code Examples for androidx.core.view.accessibility.AccessibilityNodeInfoCompat#getParent()

The following examples show how to use androidx.core.view.accessibility.AccessibilityNodeInfoCompat#getParent() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: WebInterfaceUtils.java    From talkback with Apache License 2.0 6 votes vote down vote up
public static String @Nullable [] getSupportedHtmlElements(AccessibilityNodeInfoCompat node) {
  HashSet<AccessibilityNodeInfoCompat> visitedNodes = new HashSet<AccessibilityNodeInfoCompat>();

  while (node != null) {
    if (visitedNodes.contains(node)) {
      return null;
    }

    visitedNodes.add(node);

    Bundle bundle = node.getExtras();
    CharSequence supportedHtmlElements =
        bundle.getCharSequence(ACTION_ARGUMENT_HTML_ELEMENT_STRING_VALUES);

    if (supportedHtmlElements != null) {
      return supportedHtmlElements.toString().split(",");
    }

    node = node.getParent();
  }

  return null;
}
 
Example 2
Source File: NodeDescription.java    From talkback with Apache License 2.0 6 votes vote down vote up
public boolean indexMatches(AccessibilityNodeInfoCompat node) {
  if (node == null) {
    return false;
  }
  if (indexType == INDEX_TYPE_COLLECTION) {
    CollectionItemInfoCompat itemInfo = node.getCollectionItemInfo();
    return (itemInfo != null)
        && (itemInfo.getRowIndex() == rowIndex)
        && (itemInfo.getColumnIndex() == columnIndex);
  } else {
    AccessibilityNodeInfoCompat parent = null;
    AccessibilityNodeInfoCompat child = null;
    try {
      parent = node.getParent();
      if (parent == null || parent.getChildCount() <= rawIndexInParent) {
        return false;
      }
      child = parent.getChild(rawIndexInParent);
      return node.equals(child);

    } finally {
      AccessibilityNodeInfoUtils.recycleNodes(parent, child);
    }
  }
}
 
Example 3
Source File: NodeDescription.java    From talkback with Apache License 2.0 6 votes vote down vote up
private static int getRawIndexInParent(AccessibilityNodeInfoCompat node) {
  if (node == null) {
    return UNDEFINED_INDEX;
  }
  AccessibilityNodeInfoCompat parent = node.getParent();
  if (parent == null) {
    return UNDEFINED_INDEX;
  }

  for (int i = 0; i < parent.getChildCount(); i++) {
    AccessibilityNodeInfoCompat child = parent.getChild(i);
    try {
      if (node.equals(child)) {
        return i;
      }
    } finally {
      AccessibilityNodeInfoUtils.recycleNodes(child);
    }
  }
  return UNDEFINED_INDEX;
}
 
Example 4
Source File: AccessibilityNodeInfoUtils.java    From talkback with Apache License 2.0 5 votes vote down vote up
/**
 * Returns the number of ancestors matching the given filter. Does not include the current node in
 * the count, even if it matches the filter. If there is a cycle in the ancestor hierarchy, then
 * this method will return 0.
 */
public static int countMatchingAncestors(
    AccessibilityNodeInfoCompat node, Filter<AccessibilityNodeInfoCompat> filter) {
  if (node == null) {
    return 0;
  }

  final HashSet<AccessibilityNodeInfoCompat> ancestors = new HashSet<>();
  int matchingAncestors = 0;

  try {
    ancestors.add(AccessibilityNodeInfoCompat.obtain(node));
    node = node.getParent();

    while (node != null) {
      if (!ancestors.add(node)) {
        // Already seen this node, so abort!
        node.recycle();
        return 0;
      }

      if (filter.accept(node)) {
        matchingAncestors++;
      }

      node = node.getParent();
    }
  } finally {
    recycleNodes(ancestors);
  }

  return matchingAncestors;
}
 
Example 5
Source File: AccessibilityNodeInfoRef.java    From talkback with Apache License 2.0 5 votes vote down vote up
/**
 * Traverses to the parent of this node, returning {@code true} on success. On failure, returns
 * {@code false} and does not move.
 */
public boolean parent() {
  if (mNode == null) {
    return false;
  }
  Set<AccessibilityNodeInfoCompat> visitedNodes = new HashSet<>();
  visitedNodes.add(AccessibilityNodeInfoCompat.obtain(mNode));
  AccessibilityNodeInfoCompat parentNode = mNode.getParent();
  try {
    while (parentNode != null) {
      if (visitedNodes.contains(parentNode)) {
        parentNode.recycle();
        return false;
      }

      if (AccessibilityNodeInfoUtils.isVisible(parentNode)) {
        reset(parentNode);
        return true;
      }
      visitedNodes.add(parentNode);
      parentNode = parentNode.getParent();
    }
  } finally {
    AccessibilityNodeInfoUtils.recycleNodes(visitedNodes);
  }
  return false;
}
 
Example 6
Source File: WebInterfaceUtils.java    From talkback with Apache License 2.0 5 votes vote down vote up
@Override
public boolean accept(AccessibilityNodeInfoCompat node) {
  if (node == null) {
    return false;
  }
  AccessibilityNodeInfoCompat parent = node.getParent();
  try {
    return Role.getRole(node) == Role.ROLE_WEB_VIEW
        && Role.getRole(parent) != Role.ROLE_WEB_VIEW;
  } finally {
    AccessibilityNodeInfoUtils.recycleNodes(parent);
  }
}
 
Example 7
Source File: AccessibilityNodeInfoUtils.java    From talkback with Apache License 2.0 4 votes vote down vote up
/** Returns the root node of the tree containing {@code node}. */
public static @Nullable AccessibilityNodeInfoCompat getRoot(AccessibilityNodeInfoCompat node) {
  if (node == null) {
    return null;
  }

  AccessibilityWindowInfoCompat window = null;
  try {
    window = getWindow(node);
    if (window != null) {
      return AccessibilityWindowInfoUtils.getRoot(window);
    }
  } finally {
    if (window != null) {
      window.recycle();
    }
  }

  Set<AccessibilityNodeInfoCompat> visitedNodes = new HashSet<>();
  AccessibilityNodeInfoCompat current = null;
  AccessibilityNodeInfoCompat parent = AccessibilityNodeInfoCompat.obtain(node);

  try {
    do {
      if (current != null) {
        if (visitedNodes.contains(current)) {
          current.recycle();
          parent.recycle();
          return null;
        }
        visitedNodes.add(current);
      }

      current = parent;
      parent = current.getParent();
    } while (parent != null);
  } finally {
    recycleNodes(visitedNodes);
  }

  return current;
}
 
Example 8
Source File: AccessibilityNodeInfoUtils.java    From talkback with Apache License 2.0 4 votes vote down vote up
/**
 * Returns the first ancestor of {@code node} that matches the {@code filter}, terminating the
 * search once it reaches {@code end}. The search is exclusive of both {@code node} and {@code
 * end}. Returns {@code null} if no nodes match.
 *
 * <p><strong>Note:</strong> Caller is responsible for recycling the returned node.
 */
private static @Nullable AccessibilityNodeInfoCompat getMatchingAncestor(
    AccessibilityNodeInfoCompat node,
    AccessibilityNodeInfoCompat end,
    Filter<AccessibilityNodeInfoCompat> filter) {
  if (node == null) {
    return null;
  }

  final HashSet<AccessibilityNodeInfoCompat> ancestors = new HashSet<>();

  try {
    ancestors.add(AccessibilityNodeInfoCompat.obtain(node));
    node = node.getParent();

    while (node != null) {
      if (!ancestors.add(node)) {
        // Already seen this node, so abort!
        node.recycle();
        return null;
      }

      if (end != null && node.equals(end)) {
        // Reached the end node, so abort!
        // Don't recycle the node here, it was added to ancestors and will be recycled.
        return null;
      }

      if (filter.accept(node)) {
        // Send a copy since node gets recycled.
        return AccessibilityNodeInfoCompat.obtain(node);
      }

      node = node.getParent();
    }
  } finally {
    recycleNodes(ancestors);
  }

  return null;
}
 
Example 9
Source File: AccessibilityNodeInfoUtils.java    From talkback with Apache License 2.0 4 votes vote down vote up
/**
 * Determines whether a node is a top-level item in a scrollable container.
 *
 * @param node The node to test.
 * @return {@code true} if {@code node} is a top-level item in a scrollable container.
 */
public static boolean isTopLevelScrollItem(AccessibilityNodeInfoCompat node) {
  if (node == null) {
    return false;
  }

  AccessibilityNodeInfoCompat parent = null;
  AccessibilityNodeInfoCompat grandparent = null;

  try {
    parent = node.getParent();
    if (parent == null) {
      // Not a child node of anything.
      return false;
    }

    // Certain scrollable views in M's Android TV SetupWraith are permanently broken and
    // won't ever be fixed because the setup wizard is bundled. This affects <= M only.
    if (!BuildVersionUtils.isAtLeastN() && FILTER_BROKEN_LISTS_TV_M.accept(parent)) {
      return false;
    }

    if (isScrollable(node)) {
      return true;
    }

    // Top-level items in a scrolling pager are actually two levels down since the first
    // level items in pagers are the pages themselves.
    grandparent = parent.getParent();

    if (Role.getRole(grandparent) == Role.ROLE_PAGER) {
      return true;
    }

    @Role.RoleName int parentRole = Role.getRole(parent);
    // Note that ROLE_DROP_DOWN_LIST(Spinner) is not accepted.
    // RecyclerView is classified as a list or grid based on its CollectionInfo.
    // TODO: Check if we should consider AdapterViewAnimator.
    return parentRole == Role.ROLE_LIST
        || parentRole == Role.ROLE_GRID
        || parentRole == Role.ROLE_SCROLL_VIEW
        || parentRole == Role.ROLE_HORIZONTAL_SCROLL_VIEW
        || nodeMatchesAnyClassByType(parent, CLASS_TOUCHWIZ_TWADAPTERVIEW);
  } finally {
    recycleNodes(parent, grandparent);
  }
}