Merge "Fixing several issues with accessibility" into nyc-dev
This commit is contained in:
@@ -34,6 +34,7 @@ import android.util.IntProperty;
|
|||||||
import android.util.Property;
|
import android.util.Property;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
import android.view.ViewParent;
|
import android.view.ViewParent;
|
||||||
import android.view.ViewStub;
|
import android.view.ViewStub;
|
||||||
|
|
||||||
@@ -284,6 +285,26 @@ public class Utilities {
|
|||||||
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
|
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this view, or one of its descendants have accessibility focus.
|
||||||
|
*/
|
||||||
|
public static boolean isDescendentAccessibilityFocused(View v) {
|
||||||
|
if (v.isAccessibilityFocused()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v instanceof ViewGroup) {
|
||||||
|
ViewGroup vg = (ViewGroup) v;
|
||||||
|
int childCount = vg.getChildCount();
|
||||||
|
for (int i = 0; i < childCount; i++) {
|
||||||
|
if (isDescendentAccessibilityFocused(vg.getChildAt(i))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the application configuration, which is independent of the activity's current
|
* Returns the application configuration, which is independent of the activity's current
|
||||||
* configuration in multiwindow.
|
* configuration in multiwindow.
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import android.view.ViewGroup;
|
|||||||
import android.view.accessibility.AccessibilityEvent;
|
import android.view.accessibility.AccessibilityEvent;
|
||||||
import android.view.accessibility.AccessibilityNodeInfo;
|
import android.view.accessibility.AccessibilityNodeInfo;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.ScrollView;
|
||||||
|
|
||||||
import com.android.internal.logging.MetricsLogger;
|
import com.android.internal.logging.MetricsLogger;
|
||||||
import com.android.internal.logging.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.MetricsProto.MetricsEvent;
|
||||||
@@ -170,7 +171,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
@ViewDebug.ExportedProperty(category="recents")
|
@ViewDebug.ExportedProperty(category="recents")
|
||||||
private boolean mEnterAnimationComplete = false;
|
private boolean mEnterAnimationComplete = false;
|
||||||
@ViewDebug.ExportedProperty(category="recents")
|
@ViewDebug.ExportedProperty(category="recents")
|
||||||
private boolean mTouchExplorationEnabled;
|
boolean mTouchExplorationEnabled;
|
||||||
@ViewDebug.ExportedProperty(category="recents")
|
@ViewDebug.ExportedProperty(category="recents")
|
||||||
boolean mScreenPinningEnabled;
|
boolean mScreenPinningEnabled;
|
||||||
|
|
||||||
@@ -579,7 +580,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
if (task.isFreeformTask() || (transform != null && transform.visible)) {
|
if (task.isFreeformTask() || (transform != null && transform.visible)) {
|
||||||
mTmpTaskViewMap.put(task.key, tv);
|
mTmpTaskViewMap.put(task.key, tv);
|
||||||
} else {
|
} else {
|
||||||
if (mTouchExplorationEnabled) {
|
if (mTouchExplorationEnabled && Utilities.isDescendentAccessibilityFocused(tv)) {
|
||||||
lastFocusedTaskIndex = taskIndex;
|
lastFocusedTaskIndex = taskIndex;
|
||||||
resetFocusedTask(task);
|
resetFocusedTask(task);
|
||||||
}
|
}
|
||||||
@@ -630,12 +631,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
|
|
||||||
// Update the focus if the previous focused task was returned to the view pool
|
// Update the focus if the previous focused task was returned to the view pool
|
||||||
if (lastFocusedTaskIndex != -1) {
|
if (lastFocusedTaskIndex != -1) {
|
||||||
if (lastFocusedTaskIndex < visibleTaskRange[1]) {
|
int newFocusedTaskIndex = (lastFocusedTaskIndex < visibleTaskRange[1])
|
||||||
setFocusedTask(visibleTaskRange[1], false /* scrollToTask */,
|
? visibleTaskRange[1]
|
||||||
true /* requestViewFocus */);
|
: visibleTaskRange[0];
|
||||||
} else {
|
setFocusedTask(newFocusedTaskIndex, false /* scrollToTask */,
|
||||||
setFocusedTask(visibleTaskRange[0], false /* scrollToTask */,
|
true /* requestViewFocus */);
|
||||||
true /* requestViewFocus */);
|
TaskView focusedTaskView = getChildViewForTask(mFocusedTask);
|
||||||
|
if (focusedTaskView != null) {
|
||||||
|
focusedTaskView.requestAccessibilityFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -938,24 +941,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
* focus.
|
* focus.
|
||||||
*/
|
*/
|
||||||
public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated) {
|
public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated) {
|
||||||
setRelativeFocusedTask(forward, stackTasksOnly, animated, false);
|
setRelativeFocusedTask(forward, stackTasksOnly, animated, false, 0);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the focused task relative to the currently focused task.
|
|
||||||
*
|
|
||||||
* @param forward whether to go to the next task in the stack (along the curve) or the previous
|
|
||||||
* @param stackTasksOnly if set, will ensure that the traversal only goes along stack tasks, and
|
|
||||||
* if the currently focused task is not a stack task, will set the focus
|
|
||||||
* to the first visible stack task
|
|
||||||
* @param animated determines whether to actually draw the highlight along with the change in
|
|
||||||
* focus.
|
|
||||||
* @param cancelWindowAnimations if set, will attempt to cancel window animations if a scroll
|
|
||||||
* happens.
|
|
||||||
*/
|
|
||||||
public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated,
|
|
||||||
boolean cancelWindowAnimations) {
|
|
||||||
setRelativeFocusedTask(forward, stackTasksOnly, animated, cancelWindowAnimations, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -972,13 +958,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
* @param timerIndicatorDuration the duration to initialize the auto-advance timer indicator
|
* @param timerIndicatorDuration the duration to initialize the auto-advance timer indicator
|
||||||
*/
|
*/
|
||||||
public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated,
|
public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated,
|
||||||
boolean cancelWindowAnimations,
|
boolean cancelWindowAnimations, int timerIndicatorDuration) {
|
||||||
int timerIndicatorDuration) {
|
Task focusedTask = getFocusedTask();
|
||||||
int newIndex = mStack.indexOfStackTask(mFocusedTask);
|
int newIndex = mStack.indexOfStackTask(focusedTask);
|
||||||
if (mFocusedTask != null) {
|
if (focusedTask != null) {
|
||||||
if (stackTasksOnly) {
|
if (stackTasksOnly) {
|
||||||
List<Task> tasks = mStack.getStackTasks();
|
List<Task> tasks = mStack.getStackTasks();
|
||||||
if (mFocusedTask.isFreeformTask()) {
|
if (focusedTask.isFreeformTask()) {
|
||||||
// Try and focus the front most stack task
|
// Try and focus the front most stack task
|
||||||
TaskView tv = getFrontMostTaskView(stackTasksOnly);
|
TaskView tv = getFrontMostTaskView(stackTasksOnly);
|
||||||
if (tv != null) {
|
if (tv != null) {
|
||||||
@@ -1054,6 +1040,25 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
return mFocusedTask;
|
return mFocusedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the accessibility focused task.
|
||||||
|
*/
|
||||||
|
Task getAccessibilityFocusedTask() {
|
||||||
|
List<TaskView> taskViews = getTaskViews();
|
||||||
|
int taskViewCount = taskViews.size();
|
||||||
|
for (int i = 0; i < taskViewCount; i++) {
|
||||||
|
TaskView tv = taskViews.get(i);
|
||||||
|
if (Utilities.isDescendentAccessibilityFocused(tv)) {
|
||||||
|
return tv.getTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TaskView frontTv = getFrontMostTaskView(true /* stackTasksOnly */);
|
||||||
|
if (frontTv != null) {
|
||||||
|
return frontTv.getTask();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
|
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
|
||||||
super.onInitializeAccessibilityEvent(event);
|
super.onInitializeAccessibilityEvent(event);
|
||||||
@@ -1078,21 +1083,23 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
super.onInitializeAccessibilityNodeInfo(info);
|
super.onInitializeAccessibilityNodeInfo(info);
|
||||||
List<TaskView> taskViews = getTaskViews();
|
List<TaskView> taskViews = getTaskViews();
|
||||||
int taskViewCount = taskViews.size();
|
int taskViewCount = taskViews.size();
|
||||||
if (taskViewCount > 1 && mFocusedTask != null) {
|
if (taskViewCount > 1) {
|
||||||
|
// Find the accessibility focused task
|
||||||
|
Task focusedTask = getAccessibilityFocusedTask();
|
||||||
info.setScrollable(true);
|
info.setScrollable(true);
|
||||||
int focusedTaskIndex = mStack.indexOfStackTask(mFocusedTask);
|
int focusedTaskIndex = mStack.indexOfStackTask(focusedTask);
|
||||||
if (focusedTaskIndex > 0) {
|
if (focusedTaskIndex > 0) {
|
||||||
info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
|
|
||||||
}
|
|
||||||
if (focusedTaskIndex < mStack.getTaskCount() - 1) {
|
|
||||||
info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
|
info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
|
||||||
}
|
}
|
||||||
|
if (0 <= focusedTaskIndex && focusedTaskIndex < mStack.getTaskCount() - 1) {
|
||||||
|
info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CharSequence getAccessibilityClassName() {
|
public CharSequence getAccessibilityClassName() {
|
||||||
return TaskStackView.class.getName();
|
return ScrollView.class.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1100,14 +1107,20 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
if (super.performAccessibilityAction(action, arguments)) {
|
if (super.performAccessibilityAction(action, arguments)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
switch (action) {
|
Task focusedTask = getAccessibilityFocusedTask();
|
||||||
case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
|
int taskIndex = mStack.indexOfStackTask(focusedTask);
|
||||||
setRelativeFocusedTask(true, false /* stackTasksOnly */, false /* animated */);
|
if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) {
|
||||||
return true;
|
switch (action) {
|
||||||
}
|
case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
|
||||||
case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
|
setFocusedTask(taskIndex + 1, true /* scrollToTask */, true /* requestViewFocus */,
|
||||||
setRelativeFocusedTask(false, false /* stackTasksOnly */, false /* animated */);
|
0);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
|
||||||
|
setFocusedTask(taskIndex - 1, true /* scrollToTask */, true /* requestViewFocus */,
|
||||||
|
0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -1489,6 +1502,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
unbindTaskView(tv, task);
|
unbindTaskView(tv, task);
|
||||||
|
|
||||||
// Reset the view properties and view state
|
// Reset the view properties and view state
|
||||||
|
tv.clearAccessibilityFocus();
|
||||||
tv.resetViewProperties();
|
tv.resetViewProperties();
|
||||||
tv.setFocusedState(false, false /* requestViewFocus */);
|
tv.setFocusedState(false, false /* requestViewFocus */);
|
||||||
tv.setClipViewInStack(false);
|
tv.setClipViewInStack(false);
|
||||||
@@ -1949,6 +1963,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
RecentsActivityLaunchState launchState = config.getLaunchState();
|
RecentsActivityLaunchState launchState = config.getLaunchState();
|
||||||
setFocusedTask(mStack.indexOfStackTask(mFocusedTask),
|
setFocusedTask(mStack.indexOfStackTask(mFocusedTask),
|
||||||
false /* scrollToTask */, launchState.launchedWithAltTab);
|
false /* scrollToTask */, launchState.launchedWithAltTab);
|
||||||
|
TaskView focusedTaskView = getChildViewForTask(mFocusedTask);
|
||||||
|
if (mTouchExplorationEnabled && focusedTaskView != null) {
|
||||||
|
focusedTaskView.requestAccessibilityFocus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EventBus.getDefault().send(new EnterRecentsTaskStackAnimationCompletedEvent());
|
EventBus.getDefault().send(new EnterRecentsTaskStackAnimationCompletedEvent());
|
||||||
|
|||||||
@@ -343,7 +343,9 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reset the focused task after the user has scrolled
|
// Reset the focused task after the user has scrolled
|
||||||
mSv.resetFocusedTask(mSv.getFocusedTask());
|
if (!mSv.mTouchExplorationEnabled) {
|
||||||
|
mSv.resetFocusedTask(mSv.getFocusedTask());
|
||||||
|
}
|
||||||
} else if (mActiveTaskView == null) {
|
} else if (mActiveTaskView == null) {
|
||||||
// This tap didn't start on a task.
|
// This tap didn't start on a task.
|
||||||
maybeHideRecentsFromBackgroundTap((int) ev.getX(), (int) ev.getY());
|
maybeHideRecentsFromBackgroundTap((int) ev.getX(), (int) ev.getY());
|
||||||
|
|||||||
@@ -133,8 +133,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
|
|||||||
@ViewDebug.ExportedProperty(deepExport=true, prefix="task_")
|
@ViewDebug.ExportedProperty(deepExport=true, prefix="task_")
|
||||||
private Task mTask;
|
private Task mTask;
|
||||||
@ViewDebug.ExportedProperty(category="recents")
|
@ViewDebug.ExportedProperty(category="recents")
|
||||||
private boolean mTaskDataLoaded;
|
|
||||||
@ViewDebug.ExportedProperty(category="recents")
|
|
||||||
private boolean mClipViewInStack = true;
|
private boolean mClipViewInStack = true;
|
||||||
@ViewDebug.ExportedProperty(category="recents")
|
@ViewDebug.ExportedProperty(category="recents")
|
||||||
private boolean mTouchExplorationEnabled;
|
private boolean mTouchExplorationEnabled;
|
||||||
@@ -451,16 +449,12 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
|
|||||||
* Explicitly sets the focused state of this task.
|
* Explicitly sets the focused state of this task.
|
||||||
*/
|
*/
|
||||||
public void setFocusedState(boolean isFocused, boolean requestViewFocus) {
|
public void setFocusedState(boolean isFocused, boolean requestViewFocus) {
|
||||||
SystemServicesProxy ssp = Recents.getSystemServices();
|
|
||||||
if (isFocused) {
|
if (isFocused) {
|
||||||
if (requestViewFocus && !isFocused()) {
|
if (requestViewFocus && !isFocused()) {
|
||||||
requestFocus();
|
requestFocus();
|
||||||
}
|
}
|
||||||
if (requestViewFocus && !isAccessibilityFocused() && ssp.isTouchExplorationEnabled()) {
|
|
||||||
requestAccessibilityFocus();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (isAccessibilityFocused() && ssp.isTouchExplorationEnabled()) {
|
if (isAccessibilityFocused() && mTouchExplorationEnabled) {
|
||||||
clearAccessibilityFocus();
|
clearAccessibilityFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -622,7 +616,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
|
|||||||
// Update each of the views to the new task data
|
// Update each of the views to the new task data
|
||||||
mThumbnailView.onTaskDataLoaded(thumbnailInfo);
|
mThumbnailView.onTaskDataLoaded(thumbnailInfo);
|
||||||
mHeaderView.onTaskDataLoaded();
|
mHeaderView.onTaskDataLoaded();
|
||||||
mTaskDataLoaded = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -631,7 +624,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
|
|||||||
mTask.removeCallback(this);
|
mTask.removeCallback(this);
|
||||||
mThumbnailView.unbindFromTask();
|
mThumbnailView.unbindFromTask();
|
||||||
mHeaderView.unbindFromTask(mTouchExplorationEnabled);
|
mHeaderView.unbindFromTask(mTouchExplorationEnabled);
|
||||||
mTaskDataLoaded = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user