Loading packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java +21 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.util.IntProperty; import android.util.Property; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.view.ViewStub; Loading Loading @@ -284,6 +285,26 @@ public class Utilities { 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 * configuration in multiwindow. Loading packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +63 −45 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ScrollView; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; Loading Loading @@ -170,7 +171,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal @ViewDebug.ExportedProperty(category="recents") private boolean mEnterAnimationComplete = false; @ViewDebug.ExportedProperty(category="recents") private boolean mTouchExplorationEnabled; boolean mTouchExplorationEnabled; @ViewDebug.ExportedProperty(category="recents") boolean mScreenPinningEnabled; Loading Loading @@ -579,7 +580,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal if (task.isFreeformTask() || (transform != null && transform.visible)) { mTmpTaskViewMap.put(task.key, tv); } else { if (mTouchExplorationEnabled) { if (mTouchExplorationEnabled && Utilities.isDescendentAccessibilityFocused(tv)) { lastFocusedTaskIndex = taskIndex; resetFocusedTask(task); } Loading Loading @@ -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 if (lastFocusedTaskIndex != -1) { if (lastFocusedTaskIndex < visibleTaskRange[1]) { setFocusedTask(visibleTaskRange[1], false /* scrollToTask */, true /* requestViewFocus */); } else { setFocusedTask(visibleTaskRange[0], false /* scrollToTask */, int newFocusedTaskIndex = (lastFocusedTaskIndex < visibleTaskRange[1]) ? visibleTaskRange[1] : visibleTaskRange[0]; setFocusedTask(newFocusedTaskIndex, false /* scrollToTask */, true /* requestViewFocus */); TaskView focusedTaskView = getChildViewForTask(mFocusedTask); if (focusedTaskView != null) { focusedTaskView.requestAccessibilityFocus(); } } } Loading Loading @@ -938,24 +941,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * focus. */ public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated) { setRelativeFocusedTask(forward, stackTasksOnly, animated, false); } /** * 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); setRelativeFocusedTask(forward, stackTasksOnly, animated, false, 0); } /** Loading @@ -972,13 +958,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * @param timerIndicatorDuration the duration to initialize the auto-advance timer indicator */ public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated, boolean cancelWindowAnimations, int timerIndicatorDuration) { int newIndex = mStack.indexOfStackTask(mFocusedTask); if (mFocusedTask != null) { boolean cancelWindowAnimations, int timerIndicatorDuration) { Task focusedTask = getFocusedTask(); int newIndex = mStack.indexOfStackTask(focusedTask); if (focusedTask != null) { if (stackTasksOnly) { List<Task> tasks = mStack.getStackTasks(); if (mFocusedTask.isFreeformTask()) { if (focusedTask.isFreeformTask()) { // Try and focus the front most stack task TaskView tv = getFrontMostTaskView(stackTasksOnly); if (tv != null) { Loading Loading @@ -1054,6 +1040,25 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal 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 public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); Loading @@ -1078,21 +1083,23 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal super.onInitializeAccessibilityNodeInfo(info); List<TaskView> taskViews = getTaskViews(); int taskViewCount = taskViews.size(); if (taskViewCount > 1 && mFocusedTask != null) { if (taskViewCount > 1) { // Find the accessibility focused task Task focusedTask = getAccessibilityFocusedTask(); info.setScrollable(true); int focusedTaskIndex = mStack.indexOfStackTask(mFocusedTask); int focusedTaskIndex = mStack.indexOfStackTask(focusedTask); if (focusedTaskIndex > 0) { info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); } if (focusedTaskIndex < mStack.getTaskCount() - 1) { info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); } if (0 <= focusedTaskIndex && focusedTaskIndex < mStack.getTaskCount() - 1) { info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); } } } @Override public CharSequence getAccessibilityClassName() { return TaskStackView.class.getName(); return ScrollView.class.getName(); } @Override Loading @@ -1100,16 +1107,22 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal if (super.performAccessibilityAction(action, arguments)) { return true; } Task focusedTask = getAccessibilityFocusedTask(); int taskIndex = mStack.indexOfStackTask(focusedTask); if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) { switch (action) { case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: { setRelativeFocusedTask(true, false /* stackTasksOnly */, false /* animated */); setFocusedTask(taskIndex + 1, true /* scrollToTask */, true /* requestViewFocus */, 0); return true; } case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: { setRelativeFocusedTask(false, false /* stackTasksOnly */, false /* animated */); setFocusedTask(taskIndex - 1, true /* scrollToTask */, true /* requestViewFocus */, 0); return true; } } } return false; } Loading Loading @@ -1489,6 +1502,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal unbindTaskView(tv, task); // Reset the view properties and view state tv.clearAccessibilityFocus(); tv.resetViewProperties(); tv.setFocusedState(false, false /* requestViewFocus */); tv.setClipViewInStack(false); Loading Loading @@ -1949,6 +1963,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal RecentsActivityLaunchState launchState = config.getLaunchState(); setFocusedTask(mStack.indexOfStackTask(mFocusedTask), false /* scrollToTask */, launchState.launchedWithAltTab); TaskView focusedTaskView = getChildViewForTask(mFocusedTask); if (mTouchExplorationEnabled && focusedTaskView != null) { focusedTaskView.requestAccessibilityFocus(); } } EventBus.getDefault().send(new EnterRecentsTaskStackAnimationCompletedEvent()); Loading packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java +3 −1 Original line number Diff line number Diff line Loading @@ -343,7 +343,9 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { } // Reset the focused task after the user has scrolled if (!mSv.mTouchExplorationEnabled) { mSv.resetFocusedTask(mSv.getFocusedTask()); } } else if (mActiveTaskView == null) { // This tap didn't start on a task. maybeHideRecentsFromBackgroundTap((int) ev.getX(), (int) ev.getY()); Loading packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +1 −9 Original line number Diff line number Diff line Loading @@ -133,8 +133,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks @ViewDebug.ExportedProperty(deepExport=true, prefix="task_") private Task mTask; @ViewDebug.ExportedProperty(category="recents") private boolean mTaskDataLoaded; @ViewDebug.ExportedProperty(category="recents") private boolean mClipViewInStack = true; @ViewDebug.ExportedProperty(category="recents") private boolean mTouchExplorationEnabled; Loading Loading @@ -451,16 +449,12 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks * Explicitly sets the focused state of this task. */ public void setFocusedState(boolean isFocused, boolean requestViewFocus) { SystemServicesProxy ssp = Recents.getSystemServices(); if (isFocused) { if (requestViewFocus && !isFocused()) { requestFocus(); } if (requestViewFocus && !isAccessibilityFocused() && ssp.isTouchExplorationEnabled()) { requestAccessibilityFocus(); } } else { if (isAccessibilityFocused() && ssp.isTouchExplorationEnabled()) { if (isAccessibilityFocused() && mTouchExplorationEnabled) { clearAccessibilityFocus(); } } Loading Loading @@ -622,7 +616,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks // Update each of the views to the new task data mThumbnailView.onTaskDataLoaded(thumbnailInfo); mHeaderView.onTaskDataLoaded(); mTaskDataLoaded = true; } @Override Loading @@ -631,7 +624,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks mTask.removeCallback(this); mThumbnailView.unbindFromTask(); mHeaderView.unbindFromTask(mTouchExplorationEnabled); mTaskDataLoaded = false; } @Override Loading Loading
packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java +21 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.util.IntProperty; import android.util.Property; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.view.ViewStub; Loading Loading @@ -284,6 +285,26 @@ public class Utilities { 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 * configuration in multiwindow. Loading
packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +63 −45 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ScrollView; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; Loading Loading @@ -170,7 +171,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal @ViewDebug.ExportedProperty(category="recents") private boolean mEnterAnimationComplete = false; @ViewDebug.ExportedProperty(category="recents") private boolean mTouchExplorationEnabled; boolean mTouchExplorationEnabled; @ViewDebug.ExportedProperty(category="recents") boolean mScreenPinningEnabled; Loading Loading @@ -579,7 +580,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal if (task.isFreeformTask() || (transform != null && transform.visible)) { mTmpTaskViewMap.put(task.key, tv); } else { if (mTouchExplorationEnabled) { if (mTouchExplorationEnabled && Utilities.isDescendentAccessibilityFocused(tv)) { lastFocusedTaskIndex = taskIndex; resetFocusedTask(task); } Loading Loading @@ -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 if (lastFocusedTaskIndex != -1) { if (lastFocusedTaskIndex < visibleTaskRange[1]) { setFocusedTask(visibleTaskRange[1], false /* scrollToTask */, true /* requestViewFocus */); } else { setFocusedTask(visibleTaskRange[0], false /* scrollToTask */, int newFocusedTaskIndex = (lastFocusedTaskIndex < visibleTaskRange[1]) ? visibleTaskRange[1] : visibleTaskRange[0]; setFocusedTask(newFocusedTaskIndex, false /* scrollToTask */, true /* requestViewFocus */); TaskView focusedTaskView = getChildViewForTask(mFocusedTask); if (focusedTaskView != null) { focusedTaskView.requestAccessibilityFocus(); } } } Loading Loading @@ -938,24 +941,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * focus. */ public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated) { setRelativeFocusedTask(forward, stackTasksOnly, animated, false); } /** * 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); setRelativeFocusedTask(forward, stackTasksOnly, animated, false, 0); } /** Loading @@ -972,13 +958,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * @param timerIndicatorDuration the duration to initialize the auto-advance timer indicator */ public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated, boolean cancelWindowAnimations, int timerIndicatorDuration) { int newIndex = mStack.indexOfStackTask(mFocusedTask); if (mFocusedTask != null) { boolean cancelWindowAnimations, int timerIndicatorDuration) { Task focusedTask = getFocusedTask(); int newIndex = mStack.indexOfStackTask(focusedTask); if (focusedTask != null) { if (stackTasksOnly) { List<Task> tasks = mStack.getStackTasks(); if (mFocusedTask.isFreeformTask()) { if (focusedTask.isFreeformTask()) { // Try and focus the front most stack task TaskView tv = getFrontMostTaskView(stackTasksOnly); if (tv != null) { Loading Loading @@ -1054,6 +1040,25 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal 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 public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); Loading @@ -1078,21 +1083,23 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal super.onInitializeAccessibilityNodeInfo(info); List<TaskView> taskViews = getTaskViews(); int taskViewCount = taskViews.size(); if (taskViewCount > 1 && mFocusedTask != null) { if (taskViewCount > 1) { // Find the accessibility focused task Task focusedTask = getAccessibilityFocusedTask(); info.setScrollable(true); int focusedTaskIndex = mStack.indexOfStackTask(mFocusedTask); int focusedTaskIndex = mStack.indexOfStackTask(focusedTask); if (focusedTaskIndex > 0) { info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); } if (focusedTaskIndex < mStack.getTaskCount() - 1) { info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD); } if (0 <= focusedTaskIndex && focusedTaskIndex < mStack.getTaskCount() - 1) { info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); } } } @Override public CharSequence getAccessibilityClassName() { return TaskStackView.class.getName(); return ScrollView.class.getName(); } @Override Loading @@ -1100,16 +1107,22 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal if (super.performAccessibilityAction(action, arguments)) { return true; } Task focusedTask = getAccessibilityFocusedTask(); int taskIndex = mStack.indexOfStackTask(focusedTask); if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) { switch (action) { case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: { setRelativeFocusedTask(true, false /* stackTasksOnly */, false /* animated */); setFocusedTask(taskIndex + 1, true /* scrollToTask */, true /* requestViewFocus */, 0); return true; } case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: { setRelativeFocusedTask(false, false /* stackTasksOnly */, false /* animated */); setFocusedTask(taskIndex - 1, true /* scrollToTask */, true /* requestViewFocus */, 0); return true; } } } return false; } Loading Loading @@ -1489,6 +1502,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal unbindTaskView(tv, task); // Reset the view properties and view state tv.clearAccessibilityFocus(); tv.resetViewProperties(); tv.setFocusedState(false, false /* requestViewFocus */); tv.setClipViewInStack(false); Loading Loading @@ -1949,6 +1963,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal RecentsActivityLaunchState launchState = config.getLaunchState(); setFocusedTask(mStack.indexOfStackTask(mFocusedTask), false /* scrollToTask */, launchState.launchedWithAltTab); TaskView focusedTaskView = getChildViewForTask(mFocusedTask); if (mTouchExplorationEnabled && focusedTaskView != null) { focusedTaskView.requestAccessibilityFocus(); } } EventBus.getDefault().send(new EnterRecentsTaskStackAnimationCompletedEvent()); Loading
packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java +3 −1 Original line number Diff line number Diff line Loading @@ -343,7 +343,9 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { } // Reset the focused task after the user has scrolled if (!mSv.mTouchExplorationEnabled) { mSv.resetFocusedTask(mSv.getFocusedTask()); } } else if (mActiveTaskView == null) { // This tap didn't start on a task. maybeHideRecentsFromBackgroundTap((int) ev.getX(), (int) ev.getY()); Loading
packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +1 −9 Original line number Diff line number Diff line Loading @@ -133,8 +133,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks @ViewDebug.ExportedProperty(deepExport=true, prefix="task_") private Task mTask; @ViewDebug.ExportedProperty(category="recents") private boolean mTaskDataLoaded; @ViewDebug.ExportedProperty(category="recents") private boolean mClipViewInStack = true; @ViewDebug.ExportedProperty(category="recents") private boolean mTouchExplorationEnabled; Loading Loading @@ -451,16 +449,12 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks * Explicitly sets the focused state of this task. */ public void setFocusedState(boolean isFocused, boolean requestViewFocus) { SystemServicesProxy ssp = Recents.getSystemServices(); if (isFocused) { if (requestViewFocus && !isFocused()) { requestFocus(); } if (requestViewFocus && !isAccessibilityFocused() && ssp.isTouchExplorationEnabled()) { requestAccessibilityFocus(); } } else { if (isAccessibilityFocused() && ssp.isTouchExplorationEnabled()) { if (isAccessibilityFocused() && mTouchExplorationEnabled) { clearAccessibilityFocus(); } } Loading Loading @@ -622,7 +616,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks // Update each of the views to the new task data mThumbnailView.onTaskDataLoaded(thumbnailInfo); mHeaderView.onTaskDataLoaded(); mTaskDataLoaded = true; } @Override Loading @@ -631,7 +624,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks mTask.removeCallback(this); mThumbnailView.unbindFromTask(); mHeaderView.unbindFromTask(mTouchExplorationEnabled); mTaskDataLoaded = false; } @Override Loading