Loading quickstep/src/com/android/quickstep/TaskShortcutFactory.java +7 −1 Original line number Diff line number Diff line Loading @@ -72,7 +72,13 @@ public interface TaskShortcutFactory { @Override public SystemShortcut getShortcut(BaseDraggingActivity activity, TaskIdAttributeContainer taskContainer) { return new AppInfo(activity, taskContainer.getItemInfo()); TaskView taskView = taskContainer.getTaskView(); AppInfo.SplitAccessibilityInfo accessibilityInfo = new AppInfo.SplitAccessibilityInfo(taskView.containsMultipleTasks(), TaskUtils.getTitle(taskView.getContext(), taskContainer.getTask()), taskContainer.getA11yNodeId() ); return new AppInfo(activity, taskContainer.getItemInfo(), accessibilityInfo); } @Override Loading quickstep/src/com/android/quickstep/views/TaskView.java +28 −11 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED; import static java.lang.annotation.RetentionPolicy.SOURCE; Loading @@ -38,6 +39,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.annotation.IdRes; import android.app.ActivityOptions; import android.content.Context; import android.content.Intent; Loading Loading @@ -1304,11 +1306,15 @@ public class TaskView extends FrameLayout implements Reusable { getContext().getText(R.string.accessibility_close))); final Context context = getContext(); // TODO(b/200609838) Determine which task to run A11y action on when in split screen for (TaskIdAttributeContainer taskContainer : mTaskIdAttributeContainer) { if (taskContainer == null) { continue; } for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this, mActivity.getDeviceProfile(), mTaskIdAttributeContainer[0])) { mActivity.getDeviceProfile(), taskContainer)) { info.addAction(s.createAccessibilityAction(context)); } } if (mDigitalWellBeingToast.hasLimit()) { info.addAction( Loading Loading @@ -1338,14 +1344,18 @@ public class TaskView extends FrameLayout implements Reusable { return true; } // TODO(b/200609838) Determine which task to run A11y action on when in split screen for (TaskIdAttributeContainer taskContainer : mTaskIdAttributeContainer) { if (taskContainer == null) { continue; } for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this, mActivity.getDeviceProfile(), mTaskIdAttributeContainer[0])) { mActivity.getDeviceProfile(), taskContainer)) { if (s.hasHandlerForAction(action)) { s.onClick(this); return true; } } } return super.performAccessibilityAction(action, arguments); } Loading Loading @@ -1560,7 +1570,6 @@ public class TaskView extends FrameLayout implements Reusable { mScale = previewWidth / (previewWidth + currentInsetsLeft + currentInsetsRight); } } } public class TaskIdAttributeContainer { Loading @@ -1569,6 +1578,8 @@ public class TaskView extends FrameLayout implements Reusable { private final IconView mIconView; /** Defaults to STAGE_POSITION_UNDEFINED if in not a split screen task view */ private @SplitConfigurationOptions.StagePosition int mStagePosition; @IdRes private final int mA11yNodeId; public TaskIdAttributeContainer(Task task, TaskThumbnailView thumbnailView, IconView iconView, int stagePosition) { Loading @@ -1576,6 +1587,8 @@ public class TaskView extends FrameLayout implements Reusable { this.mThumbnailView = thumbnailView; this.mIconView = iconView; this.mStagePosition = stagePosition; this.mA11yNodeId = (stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) ? R.id.split_bottomRight_appInfo : R.id.split_topLeft_appInfo; } public TaskThumbnailView getThumbnailView() { Loading Loading @@ -1605,5 +1618,9 @@ public class TaskView extends FrameLayout implements Reusable { void setStagePosition(@SplitConfigurationOptions.StagePosition int stagePosition) { this.mStagePosition = stagePosition; } public int getA11yNodeId() { return mA11yNodeId; } } } res/values/id.xml +4 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,10 @@ <item type="id" name="view_type_widgets_list" /> <item type="id" name="view_type_widgets_header" /> <item type="id" name="view_type_widgets_search_header" /> <!-- Used for A11y actions in staged split to identify each task uniquely --> <item type="id" name="split_topLeft_appInfo" /> <item type="id" name="split_bottomRight_appInfo" /> <!-- Do not change, must be kept in sync with sysui navbar button IDs for tests! --> <item type="id" name="home" /> Loading res/values/strings.xml +4 −3 Original line number Diff line number Diff line Loading @@ -40,9 +40,10 @@ <!-- Options for recent tasks --> <!-- Title for an option to enter split screen mode for a given app --> <string name="recent_task_option_split_screen">Split screen</string> <string translatable="false" name="split_screen_position_top">Split top</string> <string translatable="false" name="split_screen_position_left">Split left</string> <string translatable="false" name="split_screen_position_right">Split right</string> <string name="split_screen_position_top">Split top</string> <string name="split_screen_position_left">Split left</string> <string name="split_screen_position_right">Split right</string> <string name="split_app_info_accessibility">App info for %1$s</string> <!-- Widgets --> <!-- Message to tell the user to press and hold on a widget to add it [CHAR_LIMIT=50] --> Loading src/com/android/launcher3/popup/SystemShortcut.java +47 −2 Original line number Diff line number Diff line Loading @@ -41,8 +41,8 @@ public abstract class SystemShortcut<T extends Context & ActivityContext> extend implements View.OnClickListener { private final int mIconResId; private final int mLabelResId; private final int mAccessibilityActionId; protected final int mLabelResId; protected int mAccessibilityActionId; protected final T mTarget; protected final ItemInfo mItemInfo; Loading Loading @@ -139,11 +139,43 @@ public abstract class SystemShortcut<T extends Context & ActivityContext> extend public static class AppInfo<T extends Context & ActivityContext> extends SystemShortcut<T> { @Nullable private SplitAccessibilityInfo mSplitA11yInfo; public AppInfo(T target, ItemInfo itemInfo) { super(R.drawable.ic_info_no_shadow, R.string.app_info_drop_target_label, target, itemInfo); } /** * Constructor used by overview for staged split to provide custom A11y information. * * Future improvements considerations: * Have the logic in {@link #createAccessibilityAction(Context)} be moved to super * call in {@link SystemShortcut#createAccessibilityAction(Context)} by having * SystemShortcut be aware of TaskContainers and staged split. * That way it could directly create the correct node info for any shortcut that supports * split, but then we'll need custom resIDs for each pair of shortcuts. */ public AppInfo(T target, ItemInfo itemInfo, SplitAccessibilityInfo accessibilityInfo) { this(target, itemInfo); mSplitA11yInfo = accessibilityInfo; mAccessibilityActionId = accessibilityInfo.nodeId; } @Override public AccessibilityNodeInfo.AccessibilityAction createAccessibilityAction( Context context) { if (mSplitA11yInfo != null && mSplitA11yInfo.containsMultipleTasks) { String accessibilityLabel = context.getString(R.string.split_app_info_accessibility, mSplitA11yInfo.taskTitle); return new AccessibilityNodeInfo.AccessibilityAction(mAccessibilityActionId, accessibilityLabel); } else { return super.createAccessibilityAction(context); } } @Override public void onClick(View view) { dismissTaskMenuView(mTarget); Loading @@ -153,6 +185,19 @@ public abstract class SystemShortcut<T extends Context & ActivityContext> extend mTarget.getStatsLogManager().logger().withItemInfo(mItemInfo) .log(LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP); } public static class SplitAccessibilityInfo { public final boolean containsMultipleTasks; public final CharSequence taskTitle; public final int nodeId; public SplitAccessibilityInfo(boolean containsMultipleTasks, CharSequence taskTitle, int nodeId) { this.containsMultipleTasks = containsMultipleTasks; this.taskTitle = taskTitle; this.nodeId = nodeId; } } } public static final Factory<BaseDraggingActivity> INSTALL = (activity, itemInfo) -> { Loading Loading
quickstep/src/com/android/quickstep/TaskShortcutFactory.java +7 −1 Original line number Diff line number Diff line Loading @@ -72,7 +72,13 @@ public interface TaskShortcutFactory { @Override public SystemShortcut getShortcut(BaseDraggingActivity activity, TaskIdAttributeContainer taskContainer) { return new AppInfo(activity, taskContainer.getItemInfo()); TaskView taskView = taskContainer.getTaskView(); AppInfo.SplitAccessibilityInfo accessibilityInfo = new AppInfo.SplitAccessibilityInfo(taskView.containsMultipleTasks(), TaskUtils.getTitle(taskView.getContext(), taskContainer.getTask()), taskContainer.getA11yNodeId() ); return new AppInfo(activity, taskContainer.getItemInfo(), accessibilityInfo); } @Override Loading
quickstep/src/com/android/quickstep/views/TaskView.java +28 −11 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED; import static java.lang.annotation.RetentionPolicy.SOURCE; Loading @@ -38,6 +39,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.annotation.IdRes; import android.app.ActivityOptions; import android.content.Context; import android.content.Intent; Loading Loading @@ -1304,11 +1306,15 @@ public class TaskView extends FrameLayout implements Reusable { getContext().getText(R.string.accessibility_close))); final Context context = getContext(); // TODO(b/200609838) Determine which task to run A11y action on when in split screen for (TaskIdAttributeContainer taskContainer : mTaskIdAttributeContainer) { if (taskContainer == null) { continue; } for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this, mActivity.getDeviceProfile(), mTaskIdAttributeContainer[0])) { mActivity.getDeviceProfile(), taskContainer)) { info.addAction(s.createAccessibilityAction(context)); } } if (mDigitalWellBeingToast.hasLimit()) { info.addAction( Loading Loading @@ -1338,14 +1344,18 @@ public class TaskView extends FrameLayout implements Reusable { return true; } // TODO(b/200609838) Determine which task to run A11y action on when in split screen for (TaskIdAttributeContainer taskContainer : mTaskIdAttributeContainer) { if (taskContainer == null) { continue; } for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this, mActivity.getDeviceProfile(), mTaskIdAttributeContainer[0])) { mActivity.getDeviceProfile(), taskContainer)) { if (s.hasHandlerForAction(action)) { s.onClick(this); return true; } } } return super.performAccessibilityAction(action, arguments); } Loading Loading @@ -1560,7 +1570,6 @@ public class TaskView extends FrameLayout implements Reusable { mScale = previewWidth / (previewWidth + currentInsetsLeft + currentInsetsRight); } } } public class TaskIdAttributeContainer { Loading @@ -1569,6 +1578,8 @@ public class TaskView extends FrameLayout implements Reusable { private final IconView mIconView; /** Defaults to STAGE_POSITION_UNDEFINED if in not a split screen task view */ private @SplitConfigurationOptions.StagePosition int mStagePosition; @IdRes private final int mA11yNodeId; public TaskIdAttributeContainer(Task task, TaskThumbnailView thumbnailView, IconView iconView, int stagePosition) { Loading @@ -1576,6 +1587,8 @@ public class TaskView extends FrameLayout implements Reusable { this.mThumbnailView = thumbnailView; this.mIconView = iconView; this.mStagePosition = stagePosition; this.mA11yNodeId = (stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) ? R.id.split_bottomRight_appInfo : R.id.split_topLeft_appInfo; } public TaskThumbnailView getThumbnailView() { Loading Loading @@ -1605,5 +1618,9 @@ public class TaskView extends FrameLayout implements Reusable { void setStagePosition(@SplitConfigurationOptions.StagePosition int stagePosition) { this.mStagePosition = stagePosition; } public int getA11yNodeId() { return mA11yNodeId; } } }
res/values/id.xml +4 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,10 @@ <item type="id" name="view_type_widgets_list" /> <item type="id" name="view_type_widgets_header" /> <item type="id" name="view_type_widgets_search_header" /> <!-- Used for A11y actions in staged split to identify each task uniquely --> <item type="id" name="split_topLeft_appInfo" /> <item type="id" name="split_bottomRight_appInfo" /> <!-- Do not change, must be kept in sync with sysui navbar button IDs for tests! --> <item type="id" name="home" /> Loading
res/values/strings.xml +4 −3 Original line number Diff line number Diff line Loading @@ -40,9 +40,10 @@ <!-- Options for recent tasks --> <!-- Title for an option to enter split screen mode for a given app --> <string name="recent_task_option_split_screen">Split screen</string> <string translatable="false" name="split_screen_position_top">Split top</string> <string translatable="false" name="split_screen_position_left">Split left</string> <string translatable="false" name="split_screen_position_right">Split right</string> <string name="split_screen_position_top">Split top</string> <string name="split_screen_position_left">Split left</string> <string name="split_screen_position_right">Split right</string> <string name="split_app_info_accessibility">App info for %1$s</string> <!-- Widgets --> <!-- Message to tell the user to press and hold on a widget to add it [CHAR_LIMIT=50] --> Loading
src/com/android/launcher3/popup/SystemShortcut.java +47 −2 Original line number Diff line number Diff line Loading @@ -41,8 +41,8 @@ public abstract class SystemShortcut<T extends Context & ActivityContext> extend implements View.OnClickListener { private final int mIconResId; private final int mLabelResId; private final int mAccessibilityActionId; protected final int mLabelResId; protected int mAccessibilityActionId; protected final T mTarget; protected final ItemInfo mItemInfo; Loading Loading @@ -139,11 +139,43 @@ public abstract class SystemShortcut<T extends Context & ActivityContext> extend public static class AppInfo<T extends Context & ActivityContext> extends SystemShortcut<T> { @Nullable private SplitAccessibilityInfo mSplitA11yInfo; public AppInfo(T target, ItemInfo itemInfo) { super(R.drawable.ic_info_no_shadow, R.string.app_info_drop_target_label, target, itemInfo); } /** * Constructor used by overview for staged split to provide custom A11y information. * * Future improvements considerations: * Have the logic in {@link #createAccessibilityAction(Context)} be moved to super * call in {@link SystemShortcut#createAccessibilityAction(Context)} by having * SystemShortcut be aware of TaskContainers and staged split. * That way it could directly create the correct node info for any shortcut that supports * split, but then we'll need custom resIDs for each pair of shortcuts. */ public AppInfo(T target, ItemInfo itemInfo, SplitAccessibilityInfo accessibilityInfo) { this(target, itemInfo); mSplitA11yInfo = accessibilityInfo; mAccessibilityActionId = accessibilityInfo.nodeId; } @Override public AccessibilityNodeInfo.AccessibilityAction createAccessibilityAction( Context context) { if (mSplitA11yInfo != null && mSplitA11yInfo.containsMultipleTasks) { String accessibilityLabel = context.getString(R.string.split_app_info_accessibility, mSplitA11yInfo.taskTitle); return new AccessibilityNodeInfo.AccessibilityAction(mAccessibilityActionId, accessibilityLabel); } else { return super.createAccessibilityAction(context); } } @Override public void onClick(View view) { dismissTaskMenuView(mTarget); Loading @@ -153,6 +185,19 @@ public abstract class SystemShortcut<T extends Context & ActivityContext> extend mTarget.getStatsLogManager().logger().withItemInfo(mItemInfo) .log(LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP); } public static class SplitAccessibilityInfo { public final boolean containsMultipleTasks; public final CharSequence taskTitle; public final int nodeId; public SplitAccessibilityInfo(boolean containsMultipleTasks, CharSequence taskTitle, int nodeId) { this.containsMultipleTasks = containsMultipleTasks; this.taskTitle = taskTitle; this.nodeId = nodeId; } } } public static final Factory<BaseDraggingActivity> INSTALL = (activity, itemInfo) -> { Loading