/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.android.talkback.controller;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import com.android.talkback.CursorGranularity;
/**
* Handles screen reader cursor management.
*/
public interface CursorController {
/**
* Add a new listener for granularity change events.
*
* @param listener The new listener.
*/
void addGranularityListener(GranularityChangeListener listener);
void removeGranularityListener(GranularityChangeListener listener);
void addScrollListener(ScrollListener listener);
void addCursorListener(CursorListener listener);
/**
* Releases all resources held by this controller and save any persistent preferences.
*/
void shutdown();
/**
* Clears and replaces focus for the currently focused node.
*
* @return Whether the current node was refocused.
*/
boolean refocus();
/**
* Attempts to move to the next item using the current navigation mode.
*
* @param shouldWrap Whether navigating past the last item on the screen
* should wrap around to the first item on the screen.
* @param shouldScroll Whether navigating past the last visible item in a
* scrollable container should automatically scroll to the next
* visible item.
* @param useInputFocusAsPivotIfEmpty Whether navigation should start from node that has input
* focused editable node if there is no node with
* accessibility focus
* @param inputMode input mode used for this navigation. See InputModeManager.
* @return {@code true} if successful.
*/
boolean next(boolean shouldWrap, boolean shouldScroll, boolean useInputFocusAsPivotIfEmpty,
int inputMode);
/**
* Attempts to move to the previous item using the current navigation mode.
*
* @param shouldWrap Whether navigating past the last item on the screen
* should wrap around to the first item on the screen.
* @param shouldScroll Whether navigating past the last visible item in a
* scrollable container should automatically scroll to the next
* visible item.
* @param useInputFocusAsPivotIfEmpty Whether navigation should start from node that has input
* focused editable node if there is no node with
* accessibility focus
* @param inputMode input mode used for this navigation. See InputModeManager.
* @return {@code true} if successful.
*/
boolean previous(boolean shouldWrap, boolean shouldScroll, boolean useInputFocusAsPivotIfEmpty,
int inputMode);
/**
* Attempts to move to the item leftwards from the current item if the current SDK version
* supports it. Otherwise, does nothing and returns {@code false}.
*
* @param shouldWrap Whether navigating past the last item on the screen
* should wrap around to the first item on the screen.
* @param shouldScroll Whether navigating past the last visible item in a
* scrollable container should automatically scroll to the next
* visible item.
* @param useInputFocusAsPivotIfEmpty Whether navigation should start from node that has input
* focused editable node if there is no node with accessibility focus
* @param inputMode input mode used for this navigation. See InputModeManager.
* @return {@code true} if successful.
*/
boolean left(boolean shouldWrap, boolean shouldScroll, boolean useInputFocusAsPivotIfEmpty,
int inputMode);
/**
* Attempts to move to the item rightwards from the current item if the current SDK version
* supports it. Otherwise, does nothing and returns {@code false}.
*
* @param shouldWrap Whether navigating past the last item on the screen
* should wrap around to the first item on the screen.
* @param shouldScroll Whether navigating past the last visible item in a
* scrollable container should automatically scroll to the next
* visible item.
* @param useInputFocusAsPivotIfEmpty Whether navigation should start from node that has input
* focused editable node if there is no node with accessibility focus
* @param inputMode input mode used for this navigation. See InputModeManager.
* @return {@code true} if successful.
*/
boolean right(boolean shouldWrap, boolean shouldScroll, boolean useInputFocusAsPivotIfEmpty,
int inputMode);
/**
* Attempts to move to the item up from the current item if the current SDK version supports it.
* Otherwise, does nothing and returns {@code false}.
*
* @param shouldWrap Whether navigating past the last item on the screen
* should wrap around to the first item on the screen.
* @param shouldScroll Whether navigating past the last visible item in a
* scrollable container should automatically scroll to the next
* visible item.
* @param useInputFocusAsPivotIfEmpty Whether navigation should start from node that has input
* focused editable node if there is no node with accessibility focus
* @param inputMode input mode used for this navigation. See InputModeManager.
* @return {@code true} if successful.
*/
boolean up(boolean shouldWrap, boolean shouldScroll, boolean useInputFocusAsPivotIfEmpty,
int inputMode);
/**
* Attempts to move to the item down from the current item if the current SDK version supports
* it. Otherwise, does nothing and returns {@code false}.
*
* @param shouldWrap Whether navigating past the last item on the screen
* should wrap around to the first item on the screen.
* @param shouldScroll Whether navigating past the last visible item in a
* scrollable container should automatically scroll to the next
* visible item.
* @param useInputFocusAsPivotIfEmpty Whether navigation should start from node that has input
* focused editable node if there is no node with accessibility focus
* @param inputMode input mode used for this navigation. See InputModeManager.
* @return {@code true} if successful.
*/
boolean down(boolean shouldWrap, boolean shouldScroll, boolean useInputFocusAsPivotIfEmpty,
int inputMode);
/**
* Attempts to jump to the first item that appears on the screen.
*
* @param inputMode input mode used for this navigation. See InputModeManager.
* @return {@code true} if successful.
*/
boolean jumpToTop(int inputMode);
/**
* Attempts to jump to the last item that appears on the screen.
*
* @param inputMode input mode used for this navigation. See InputModeManager.
* @return {@code true} if successful.
*/
boolean jumpToBottom(int inputMode);
/**
* Attempts to scroll forward within the current cursor.
*
* @return {@code true} if successful.
*/
boolean more();
/**
* Attempts to scroll backward within the current cursor.
*
* @return {@code true} if successful.
*/
boolean less();
/**
* Attempts to navigate to next item with specified granularity.
*/
boolean nextWithSpecifiedGranularity(CursorGranularity granularity, boolean shouldWrap,
boolean shouldScroll, boolean useInputFocusAsPivotIfEmpty, int inputMode);
/**
* Attempts to navigate to previous item with specified granularity.
*/
boolean previousWithSpecifiedGranularity(CursorGranularity granularity, boolean shouldWrap,
boolean shouldScroll, boolean useInputFocusAsPivotIfEmpty, int inputMode);
/**
* Attempts to navigate to next html element.
*/
boolean nextHtmlElement(String htmlElement, int inputMode);
/**
* Attempts to navigate to previous html element.
*/
boolean previousHtmlElement(String htmlElement, int inputMode);
/**
* Attempts to click on the center of the current cursor.
*
* @return {@code true} if successful.
*/
boolean clickCurrent();
/**
* Attempts to click on the current cursor, or its first clickable ancestor.
* This is useful in approximating the same behavior you get when double-tapping in touch
* exploration.
*/
boolean clickCurrentHierarchical();
/**
* Attempts to long click on the current cursor.
*/
boolean longClickCurrent();
/**
* Attempts to move to the next reading level.
*
* @return {@code true} if successful.
*/
boolean nextGranularity();
/**
* Attempts to move to the previous reading level.
*
* @return {@code true} if successful.
*/
public boolean previousGranularity();
/**
* Adjust the cursor's granularity by moving it directly to the specified
* granularity. If the granularity is {@link CursorGranularity#DEFAULT},
* unlocks navigation; otherwise, locks navigation to the current cursor.
*
* @param granularity The {@link CursorGranularity} to request.
* @return {@code true} if the granularity change was successful,
* {@code false} otherwise.
*/
boolean setGranularity(CursorGranularity granularity, boolean fromUser);
boolean setGranularity(CursorGranularity granularity, AccessibilityNodeInfoCompat node,
boolean fromUser);
/**
* Sets the current cursor position.
*
* @param node The node to set as the cursor.
* @return {@code true} if successful.
*/
boolean setCursor(AccessibilityNodeInfoCompat node);
/**
* Sets the current state of selection mode for navigation within text
* content. When enabled, the manager will attempt to extend selection
* during navigation. If the target node of selection mode is not locked to
* a granularity, calling this method will switch to
* {@link CursorGranularity#CHARACTER}
*
* @param node The node on which selection mode should be enabled.
* @param active {@code true} to activate selection mode, {@code false} to
* deactivate.
*/
void setSelectionModeActive(AccessibilityNodeInfoCompat node, boolean active);
/**
* @return {@code true} if selection mode is active, {@code false}
* otherwise.
*/
boolean isSelectionModeActive();
/**
* Clears the current cursor position.
*/
void clearCursor();
/**
* Clears the given current cursor position.
* Caller have to make sure currentNode get recycled
* @param currentNode given node to clear focus
*/
void clearCursor(AccessibilityNodeInfoCompat currentNode);
/**
* Returns the node in the active window that has accessibility focus. If no
* node has focus, or if the focused node is invisible, returns the root
* node.
* <p>
* The client is responsible for recycling the resulting node.
*
* @return The node in the active window that has accessibility focus.
*/
AccessibilityNodeInfoCompat getCursor();
/**
* Returns a node satisfying one of the following criteria, in descending order:
* (1) the current accessibility-focused node in the active window, or
* (2) the current editable input-focused node in the active window if there is no
* accessibility focus, or
* (3) {@code null} if no node meets any of the above criteria.
*
* The client is responsible for recycling the resulting node.
*
* @return An accessibility-focused or input-focused node in the active window.
*/
AccessibilityNodeInfoCompat getCursorOrInputCursor();
/**
* Return the current granularity at the specified node, or
* {@link CursorGranularity#DEFAULT} if none is set. Always returns
* {@link CursorGranularity#DEFAULT} if granular navigation is not locked to
* the specified node.
*
* @param node The node to check.
* @return A cursor granularity.
*/
CursorGranularity getGranularityAt(AccessibilityNodeInfoCompat node);
/**
* Listener for scroll events.
*/
public interface ScrollListener {
/**
* Informs of a scroll caused by the CursorControler.
*
* @param action Direction of the scroll.
* @param auto If {@code true}, then the scroll was initiated automatically. If
* {@code false}, then the user initiated the scroll action.
*/
public void onScroll(AccessibilityNodeInfoCompat scrolledNode, int action, boolean auto);
}
/**
* Listener for granularity changes.
*/
public interface GranularityChangeListener {
/**
* Informs of a granularity change.
*
* @param granularity The new granularity after the change occurred.
*/
void onGranularityChanged(CursorGranularity granularity);
}
/**
* Listener for cursor change events.
*/
public interface CursorListener {
/**
* Triggered right before a cursor change caused by the CursorController.
*/
void beforeSetCursor(AccessibilityNodeInfoCompat newCursor, int action);
/**
* Triggered right after a cursor change caused by the CursorController.
*/
void onSetCursor(AccessibilityNodeInfoCompat newCursor, int action);
}
}