Merge "Implement AccessibilityDelegateImpl for the Taskbar"
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index 31c0f5f..3a4bb10 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -39,4 +39,8 @@
     <string name="wellbeing_provider_pkg" translatable="false"/>
 
     <integer name="max_depth_blur_radius">23</integer>
+
+    <!-- Accessibility actions -->
+    <item type="id" name="action_move_to_top_or_left" />
+    <item type="id" name="action_move_to_bottom_or_right" />
 </resources>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 151b8e4..70a4a7d 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -233,4 +233,9 @@
     <string name="taskbar_edu_close">Close</string>
     <!-- Text on button to finish a tutorial [CHAR_LIMIT=16] -->
     <string name="taskbar_edu_done">Done</string>
+
+    <!-- Label for moving drop target to the top or left side of the screen, depending on orientation (from the taskbar only). -->
+    <string name="move_drop_target_top_or_left">Move to top&#47;left</string>
+    <!-- Label for moving drop target to the bottom or right side of the screen, depending on orientation (from the taskbar only). -->
+    <string name="move_drop_target_bottom_or_right">Move to bottom&#47;right</string>
 </resources>
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 33d6533..883515e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -53,6 +53,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.R;
@@ -113,6 +114,8 @@
     // The flag to know if the window is excluded from magnification region computation.
     private boolean mIsExcludeFromMagnificationRegion = false;
 
+    private final TaskbarShortcutMenuAccessibilityDelegate mAccessibilityDelegate;
+
     public TaskbarActivityContext(Context windowContext, DeviceProfile dp,
             TaskbarNavButtonController buttonController, ScopedUnfoldTransitionProgressProvider
             unfoldTransitionProgressProvider) {
@@ -148,6 +151,8 @@
         mLeftCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT);
         mRightCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT);
 
+        mAccessibilityDelegate = new TaskbarShortcutMenuAccessibilityDelegate(this);
+
         // Construct controllers.
         mControllers = new TaskbarControllers(this,
                 new TaskbarDragController(this),
@@ -333,6 +338,11 @@
         return mControllers.taskbarPopupController.getPopupDataProvider();
     }
 
+    @Override
+    public View.AccessibilityDelegate getAccessibilityDelegate() {
+        return mAccessibilityDelegate;
+    }
+
     /**
      * Sets a new data-source for this taskbar instance
      */
@@ -564,4 +574,9 @@
         }
         mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
     }
+
+    public void showPopupMenuForIcon(BubbleTextView btv) {
+        setTaskbarWindowFullscreen(true);
+        btv.post(() -> mControllers.taskbarPopupController.showForIcon(btv));
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarShortcutMenuAccessibilityDelegate.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarShortcutMenuAccessibilityDelegate.java
new file mode 100644
index 0000000..1589582
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarShortcutMenuAccessibilityDelegate.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * 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.launcher3.taskbar;
+
+import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.DEEP_SHORTCUTS;
+import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.SHORTCUTS_AND_NOTIFICATIONS;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
+
+import android.content.Intent;
+import android.content.pm.LauncherApps;
+import android.view.KeyEvent;
+import android.view.View;
+
+import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.R;
+import com.android.launcher3.accessibility.BaseAccessibilityDelegate;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.notification.NotificationListener;
+import com.android.launcher3.util.ShortcutUtil;
+import com.android.quickstep.SystemUiProxy;
+import com.android.systemui.shared.system.LauncherAppsCompat;
+
+import java.util.List;
+
+/**
+ * Accessibility delegate for the Taskbar. This provides an accessible interface for taskbar
+ * features.
+ */
+public class TaskbarShortcutMenuAccessibilityDelegate
+        extends BaseAccessibilityDelegate<TaskbarActivityContext> {
+
+    public static final int MOVE_TO_TOP_OR_LEFT = R.id.action_move_to_top_or_left;
+    public static final int MOVE_TO_BOTTOM_OR_RIGHT = R.id.action_move_to_bottom_or_right;
+
+    private final LauncherApps mLauncherApps;
+
+    public TaskbarShortcutMenuAccessibilityDelegate(TaskbarActivityContext context) {
+        super(context);
+        mLauncherApps = context.getSystemService(LauncherApps.class);
+
+        mActions.put(DEEP_SHORTCUTS, new LauncherAction(DEEP_SHORTCUTS,
+                R.string.action_deep_shortcut, KeyEvent.KEYCODE_S));
+        mActions.put(SHORTCUTS_AND_NOTIFICATIONS, new LauncherAction(DEEP_SHORTCUTS,
+                R.string.shortcuts_menu_with_notifications_description, KeyEvent.KEYCODE_S));
+        mActions.put(MOVE_TO_TOP_OR_LEFT, new LauncherAction(
+                MOVE_TO_TOP_OR_LEFT, R.string.move_drop_target_top_or_left, KeyEvent.KEYCODE_L));
+        mActions.put(MOVE_TO_BOTTOM_OR_RIGHT, new LauncherAction(
+                MOVE_TO_BOTTOM_OR_RIGHT,
+                R.string.move_drop_target_bottom_or_right,
+                KeyEvent.KEYCODE_R));
+    }
+
+    @Override
+    protected void getSupportedActions(View host, ItemInfo item, List<LauncherAction> out) {
+        if (ShortcutUtil.supportsShortcuts(item) && FeatureFlags.ENABLE_TASKBAR_POPUP_MENU.get()) {
+            out.add(mActions.get(NotificationListener.getInstanceIfConnected() != null
+                    ? SHORTCUTS_AND_NOTIFICATIONS : DEEP_SHORTCUTS));
+        }
+        out.add(mActions.get(MOVE_TO_TOP_OR_LEFT));
+        out.add(mActions.get(MOVE_TO_BOTTOM_OR_RIGHT));
+    }
+
+    @Override
+    protected boolean performAction(View host, ItemInfo item, int action, boolean fromKeyboard) {
+        if (item instanceof WorkspaceItemInfo
+                && (action == MOVE_TO_TOP_OR_LEFT || action == MOVE_TO_BOTTOM_OR_RIGHT)) {
+            WorkspaceItemInfo info = (WorkspaceItemInfo) item;
+            int side = action == MOVE_TO_TOP_OR_LEFT
+                    ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT;
+
+            if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
+                SystemUiProxy.INSTANCE.get(mContext).startShortcut(
+                        info.getIntent().getPackage(),
+                        info.getDeepShortcutId(),
+                        side,
+                        /* bundleOpts= */ null,
+                        info.user);
+            } else {
+                SystemUiProxy.INSTANCE.get(mContext).startIntent(
+                        LauncherAppsCompat.getMainActivityLaunchIntent(
+                                mLauncherApps,
+                                item.getIntent().getComponent(),
+                                /* startActivityOptions= */null,
+                                item.user),
+                        new Intent(), side, null);
+            }
+            return true;
+        } else if (action == DEEP_SHORTCUTS || action == SHORTCUTS_AND_NOTIFICATIONS) {
+            mContext.showPopupMenuForIcon((BubbleTextView) host);
+
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    protected boolean beginAccessibleDrag(View item, ItemInfo info, boolean fromKeyboard) {
+        return false;
+    }
+}