1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.launcher3.keyboard; 18 19 import android.view.Menu; 20 import android.view.MenuItem; 21 import android.view.View; 22 import android.view.accessibility.AccessibilityNodeInfo; 23 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; 24 import android.widget.PopupMenu; 25 import android.widget.PopupMenu.OnMenuItemClickListener; 26 27 import com.android.launcher3.ItemInfo; 28 import com.android.launcher3.Launcher; 29 import com.android.launcher3.accessibility.LauncherAccessibilityDelegate; 30 import com.android.launcher3.popup.PopupContainerWithArrow; 31 32 import java.util.ArrayList; 33 import java.util.Collections; 34 import java.util.List; 35 36 /** 37 * Handles showing a popup menu with available custom actions for a launcher icon. 38 * This allows exposing various custom actions using keyboard shortcuts. 39 */ 40 public class CustomActionsPopup implements OnMenuItemClickListener { 41 42 private final Launcher mLauncher; 43 private final LauncherAccessibilityDelegate mDelegate; 44 private final View mIcon; 45 CustomActionsPopup(Launcher launcher, View icon)46 public CustomActionsPopup(Launcher launcher, View icon) { 47 mLauncher = launcher; 48 mIcon = icon; 49 PopupContainerWithArrow container = PopupContainerWithArrow.getOpen(launcher); 50 if (container != null) { 51 mDelegate = container.getAccessibilityDelegate(); 52 } else { 53 mDelegate = launcher.getAccessibilityDelegate(); 54 } 55 } 56 getActionList()57 private List<AccessibilityAction> getActionList() { 58 if (mIcon == null || !(mIcon.getTag() instanceof ItemInfo)) { 59 return Collections.EMPTY_LIST; 60 } 61 62 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(); 63 mDelegate.addSupportedActions(mIcon, info, true); 64 List<AccessibilityAction> result = new ArrayList<>(info.getActionList()); 65 info.recycle(); 66 return result; 67 } 68 canShow()69 public boolean canShow() { 70 return !getActionList().isEmpty(); 71 } 72 show()73 public boolean show() { 74 List<AccessibilityAction> actions = getActionList(); 75 if (actions.isEmpty()) { 76 return false; 77 } 78 79 PopupMenu popup = new PopupMenu(mLauncher, mIcon); 80 popup.setOnMenuItemClickListener(this); 81 Menu menu = popup.getMenu(); 82 for (AccessibilityAction action : actions) { 83 menu.add(Menu.NONE, action.getId(), Menu.NONE, action.getLabel()); 84 } 85 popup.show(); 86 return true; 87 } 88 89 @Override onMenuItemClick(MenuItem menuItem)90 public boolean onMenuItemClick(MenuItem menuItem) { 91 return mDelegate.performAction(mIcon, (ItemInfo) mIcon.getTag(), menuItem.getItemId()); 92 } 93 } 94