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

The following examples show how to use androidx.core.view.accessibility.AccessibilityNodeInfoCompat#isEditable() . 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: FocusProcessorForScreenStateChange.java    From talkback with Apache License 2.0 6 votes vote down vote up
/**
 * Sets accessibility focus to EditText in the active window. Caller should recycle {@code root}.
 *
 * @param root root node in current active window
 * @param eventId event id
 * @return {@code true} if successfully set accessibility focus on the EditText node.
 */
protected boolean syncA11yFocusToInputFocusedEditText(
    AccessibilityNodeInfoCompat root, EventId eventId) {
  AccessibilityNodeInfoCompat inputFocusedNode = null;
  try {
    if (root != null) {
      inputFocusedNode = root.findFocus(AccessibilityNodeInfoCompat.FOCUS_INPUT);
    }
    return (inputFocusedNode != null)
        && (inputFocusedNode.isEditable()
            || (Role.getRole(inputFocusedNode) == Role.ROLE_EDIT_TEXT))
        && pipeline.returnFeedback(
            eventId, Feedback.focus(inputFocusedNode, FOCUS_ACTION_INFO_SYNCED_EDIT_TEXT));
  } finally {
    AccessibilityNodeInfoUtils.recycleNodes(inputFocusedNode);
  }
}
 
Example 2
Source File: AccessibilityNodeInfoUtils.java    From talkback with Apache License 2.0 5 votes vote down vote up
/**
 * Analyses if the edit text has no text.
 *
 * <p>If there is a text field with hint text and no text, node.getText() returns hint text. Hence
 * this method checks for {@link AccessibilityNodeInfo#ACTION_SET_SELECTION} to disregard the hint
 * text.
 */
public static boolean isEmptyEditTextRegardlessOfHint(
    @Nullable AccessibilityNodeInfoCompat node) {
  if (node == null || !(node.isEditable())) {
    return false;
  }

  if (TextUtils.isEmpty(node.getText())) {
    return true;
  }
  return !supportsAction(node, AccessibilityNodeInfo.ACTION_SET_SELECTION);
}
 
Example 3
Source File: AccessibilityFocusActionHistory.java    From talkback with Apache License 2.0 5 votes vote down vote up
/**
 * Registers the action information. Called immediately after an accessibility focus action is
 * performed.
 *
 * <p><strong>Note:</strong> Caller is responsible for recycling the {@code node}.
 *
 * @param node Node being accessibility focused.
 * @param extraData Extra information of the action.
 * @param actionTime {@link SystemClock#uptimeMillis()} right before performing focus action.
 * @param currentScreenState Current {@link ScreenState}.
 */
public void onAccessibilityFocusAction(
    AccessibilityNodeInfoCompat node,
    FocusActionInfo extraData,
    long actionTime,
    @Nullable ScreenState currentScreenState) {
  // FocusActionRecord handles making a copy of 'node'. We don't nee to call obtain() here.
  FocusActionRecord record = new FocusActionRecord(node, extraData, actionTime);

  // Add to the record queue.
  focusActionRecordList.offer(record);
  if (focusActionRecordList.size() > MAXIMUM_RECORD_QUEUE_SIZE) {
    // Poll and recycle the eldest order if the queue grows up its maximum size.
    focusActionRecordList.pollFirst().recycle();
  }

  final int windowId = node.getWindowId();
  final CharSequence windowTitle =
      (currentScreenState == null) ? null : currentScreenState.getWindowTitle(windowId);
  // Add to the window record map.
  windowIdTitlePairToFocusActionRecordMap.put(
      Pair.create(windowId, windowTitle), FocusActionRecord.copy(record));

  // Update the last editable node focus action.
  if (node.isEditable() || (Role.getRole(node) == Role.ROLE_EDIT_TEXT)) {
    if (lastEditableFocusActionRecord != null) {
      lastEditableFocusActionRecord.recycle();
    }
    lastEditableFocusActionRecord = FocusActionRecord.copy(record);
  }
}
 
Example 4
Source File: InputFocusInterpreter.java    From talkback with Apache License 2.0 5 votes vote down vote up
/**
 * Updates {@code lastTextEditIsPassword} in {@link GlobalVariables}.
 *
 * @param inputFocusedNode Current input focused node. Set to {@code null} if there is no input
 *     focus on screen.
 */
private void updateInputFocusedNodeInGlobalVariables(
    @Nullable AccessibilityNodeInfoCompat inputFocusedNode) {
  if ((inputFocusedNode != null)
      && (inputFocusedNode.isEditable()
          || (Role.getRole(inputFocusedNode) == Role.ROLE_EDIT_TEXT))) {
    globalVariables.setLastTextEditIsPassword(inputFocusedNode.isPassword());
  }
  // Don't update the field if non-edittext node is grabbing the input focus.
  // Some on-screen keyboard keys take input focus when tapped, but we still want the last
  // text-edit to remain the same.
}
 
Example 5
Source File: ProcessorVolumeStream.java    From talkback with Apache License 2.0 5 votes vote down vote up
private boolean attemptNavigation(int button, EventId eventId) {
  AccessibilityNodeInfoCompat node =
      accessibilityFocusMonitor.getAccessibilityFocus(/* useInputFocusIfEmpty= */ true);

  if (node == null) {
    return false;
  }
  try {
    if (Role.getRole(node) == Role.ROLE_SEEK_CONTROL) {
      navigateSlider(button, node, eventId);
      return true;
    }

    // In general, do not allow volume key navigation when the a11y focus is placed but
    // it is not on the edit field that the keyboard is currently editing.
    //
    // Example 1:
    // EditText1 has input focus and EditText2 has accessibility focus.
    // getCursorOrInputCursor() will return EditText2 based on its priority order.
    // EditText2.isFocused() = false, so we should not allow volume keys to control text.
    //
    // Example 2:
    // EditText1 in Window1 has input focus. EditText2 in Window2 has input focus as well.
    // If Window1 is input-focused but Window2 has the accessibility focus, don't allow
    // the volume keys to control the text.
    boolean nodeWindowFocused;
    AccessibilityWindowInfoCompat windowInfo = AccessibilityNodeInfoUtils.getWindow(node);
    nodeWindowFocused = (windowInfo != null) && windowInfo.isFocused();
    if (node.isFocused() && nodeWindowFocused && node.isEditable() && !touchingScreen) {
      navigateEditText(button, node, eventId);
      return true;
    }

    return false;
  } finally {
    AccessibilityNodeInfoUtils.recycleNodes(node);
  }
}
 
Example 6
Source File: DirectionNavigationActor.java    From talkback with Apache License 2.0 5 votes vote down vote up
private boolean isEditingFocusedNode(boolean useInputFocusAsPivotIfEmpty) {
  AccessibilityNodeInfoCompat currentFocus = null;
  try {
    currentFocus = accessibilityFocusMonitor.getAccessibilityFocus(useInputFocusAsPivotIfEmpty);
    return (currentFocus != null)
        && (currentFocus.isEditable() || (Role.getRole(currentFocus) == Role.ROLE_EDIT_TEXT))
        && currentFocus.isFocused();
  } finally {
    AccessibilityNodeInfoUtils.recycleNodes(currentFocus);
  }
}
 
Example 7
Source File: AccessibilityFocusMonitor.java    From talkback with Apache License 2.0 4 votes vote down vote up
/**
 * Returns accessibility focused node if it's visible on screen. Otherwise returns input focused
 * edit field if{@code returnInputFocusedEditFieldIfNullOrInvisible} is set to {@code true}.
 * Called by DirectionNavigationController.
 *
 * <p><strong>Note:</strong>
 *
 * <ul>
 *   <li>The client is responsible for recycling the returned node.
 *   <li>The returned node might not pass {@link
 *       AccessibilityNodeInfoUtils#shouldFocusNode(AccessibilityNodeInfoCompat)}, the caller
 *       should validate the result if needed.
 * </ul>
 */
public @Nullable AccessibilityNodeInfoCompat getAccessibilityFocus(boolean useInputFocusIfEmpty) {
  // Nodes to be recycled.
  AccessibilityNodeInfoCompat root = null;
  AccessibilityNodeInfoCompat a11yFocusedNode = null;
  AccessibilityNodeInfoCompat inputFocusedNode = null;
  AccessibilityNodeInfoCompat lastFocusedEditFieldInHistory = null;

  try {
    // First, see if we've already placed accessibility focus.
    root = AccessibilityServiceCompatUtils.getRootInAccessibilityFocusedWindow(service);
    if (root == null) {
      return null;
    }
    a11yFocusedNode = root.findFocus(AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);

    if ((a11yFocusedNode != null) && AccessibilityNodeInfoUtils.isVisible(a11yFocusedNode)) {
      return AccessibilityNodeInfoUtils.obtain(a11yFocusedNode);
    }

    if (!useInputFocusIfEmpty) {
      return null;
    }

    // TODO: If there's no focused node, we should either mimic following
    // focus from new window or try to be smart for things like list views.
    inputFocusedNode = AccessibilityServiceCompatUtils.getInputFocusedNode(service);
    if ((inputFocusedNode != null)
        && inputFocusedNode.isFocused()
        && (inputFocusedNode.isEditable()
            || (Role.getRole(inputFocusedNode) == Role.ROLE_EDIT_TEXT))) {
      return AccessibilityNodeInfoUtils.obtain(inputFocusedNode);
    }

    // If we can't find the focused node but the keyboard is showing, return the last editable.
    // This will occur if the input-focused view is actually a virtual view (e.g. in WebViews).
    // Note: need to refresh() in order to verify that the node is still available on-screen.
    FocusActionRecord record = history.getLastEditableFocusActionRecord();

    lastFocusedEditFieldInHistory = (record == null) ? null : record.getFocusedNode();

    if ((lastFocusedEditFieldInHistory != null) && lastFocusedEditFieldInHistory.refresh()) {
      // TODO: Shall we check the presence of IME window?
      // IME window check below is copied from legacy CursorController. What if the device is
      // connected to bluetooth keyboard?
      WindowManager windowManager = new WindowManager(false); // RTL state doesn't matter.
      windowManager.setWindows(AccessibilityServiceCompatUtils.getWindows(service));
      if (windowManager.isInputWindowOnScreen()) {
        return AccessibilityNodeInfoCompat.obtain(lastFocusedEditFieldInHistory);
      }
    }
    return null;
  } finally {
    AccessibilityNodeInfoUtils.recycleNodes(
        root, a11yFocusedNode, inputFocusedNode, lastFocusedEditFieldInHistory);
  }
}