<item type="id" name="action_move_screen_forwards" />
<item type="id" name="action_resize" />
<item type="id" name="action_deep_shortcuts" />
+ <item type="id" name="action_dismiss_notification" />
</resources>
<!-- Accessibility description for the shortcuts menu shown for an app. -->
<string name="shortcuts_menu_description"><xliff:g id="number_of_shortcuts" example="3">%1$d</xliff:g> shortcuts for <xliff:g id="app_name" example="Messenger">%2$s</xliff:g></string>
+ <!-- Accessibility description when the shortcuts menu has notifications as well as shortcuts. -->
+ <string name="shortcuts_menu_with_notifications_description"><xliff:g id="number_of_shortcuts" example="3">%1$d</xliff:g> shortcuts and <xliff:g id="number_of_notifications" example="3">%2$d</xliff:g> notifications for <xliff:g id="app_name" example="Messenger">%3$s</xliff:g></string>
+
+ <!-- Accessibility action to dismiss a notification in the shortcuts menu for an icon. [CHAR_LIMIT=30] -->
+ <string name="action_dismiss_notification">Dismiss</string>
+
+ <!-- Accessibility confirmation for notification being dismissed. -->
+ <string name="notification_dismissed">Notification dismissed</string>
</resources>
}
/**
- * Returns true if the view can show custom shortcuts.
- */
- public boolean hasDeepShortcuts() {
- return !mLauncher.getPopupDataProvider().getShortcutIdsForItem((ItemInfo) getTag())
- .isEmpty();
- }
-
- /**
* Interface to be implemented by the grand parent to allow click shadow effect.
*/
public interface BubbleTextShadowHandler {
shortcutInfos.add(new KeyboardShortcutInfo(getString(R.string.custom_actions),
KeyEvent.KEYCODE_O, KeyEvent.META_CTRL_ON));
}
- if (currentFocus instanceof BubbleTextView &&
- ((BubbleTextView) currentFocus).hasDeepShortcuts()) {
+ if (currentFocus.getTag() instanceof ItemInfo
+ && DeepShortcutManager.supportsShortcuts((ItemInfo) currentFocus.getTag())) {
shortcutInfos.add(new KeyboardShortcutInfo(getString(R.string.action_deep_shortcut),
KeyEvent.KEYCODE_S, KeyEvent.META_CTRL_ON));
}
import com.android.launcher3.dragndrop.DragController.DragListener;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.folder.Folder;
+import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.util.Thunk;
import java.util.ArrayList;
// If the request came from keyboard, do not add custom shortcuts as that is already
// exposed as a direct shortcut
- if (!fromKeyboard && host instanceof BubbleTextView
- && ((BubbleTextView) host).hasDeepShortcuts()) {
+ if (!fromKeyboard && DeepShortcutManager.supportsShortcuts(item)) {
info.addAction(mActions.get(DEEP_SHORTCUTS));
}
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutInfo;
+import com.android.launcher3.notification.NotificationMainView;
import com.android.launcher3.shortcuts.DeepShortcutView;
import java.util.ArrayList;
*/
public class ShortcutMenuAccessibilityDelegate extends LauncherAccessibilityDelegate {
+ private static final int DISMISS_NOTIFICATION = R.id.action_dismiss_notification;
+
public ShortcutMenuAccessibilityDelegate(Launcher launcher) {
super(launcher);
+ mActions.put(DISMISS_NOTIFICATION, new AccessibilityAction(DISMISS_NOTIFICATION,
+ launcher.getText(R.string.action_dismiss_notification)));
}
@Override
public void addSupportedActions(View host, AccessibilityNodeInfo info, boolean fromKeyboard) {
if ((host.getParent() instanceof DeepShortcutView)) {
info.addAction(mActions.get(ADD_TO_WORKSPACE));
+ } else if (host instanceof NotificationMainView) {
+ NotificationMainView notificationView = (NotificationMainView) host;
+ if (notificationView.canChildBeDismissed(notificationView)) {
+ info.addAction(mActions.get(DISMISS_NOTIFICATION));
+ }
}
}
onComplete.run();
}
return true;
+ } else if (action == DISMISS_NOTIFICATION) {
+ if (!(host instanceof NotificationMainView)) {
+ return false;
+ }
+ NotificationMainView notificationView = (NotificationMainView) host;
+ notificationView.onChildDismissed(notificationView);
+ announceConfirmation(R.string.notification_dismissed);
+ return true;
}
return false;
}
icon.setBackground(info.getIconForBackground(getContext(), mBackgroundColor));
icon.setOnClickListener(info);
icon.setTag(info);
+ icon.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
mIconRow.addView(icon, 0, mIconLayoutParams);
return icon;
}
mSwipeHelper.setDisableHardwareLayers(true);
}
+ public NotificationMainView getMainView() {
+ return mMainView;
+ }
+
public int getHeightMinusFooter() {
int footerHeight = mFooter.getParent() == null ? 0 : mFooter.getHeight();
return getHeight() - footerHeight;
@Override
public boolean canChildBeDismissed(View v) {
- return mNotificationInfo.dismissable;
+ return mNotificationInfo != null && mNotificationInfo.dismissable;
}
@Override
mStartDragThreshold = getResources().getDimensionPixelSize(
R.dimen.deep_shortcuts_start_drag_threshold);
- // TODO: make sure the delegate works for all items, not just shortcuts.
mAccessibilityDelegate = new ShortcutMenuAccessibilityDelegate(mLauncher);
mIsRtl = Utilities.isRtl(getResources());
}
// Add dummy views first, and populate with real info when ready.
PopupPopulator.Item[] itemsToPopulate = PopupPopulator
.getItemsToPopulate(shortcutIds, notificationKeys, systemShortcuts);
- addDummyViews(originalIcon, itemsToPopulate, notificationKeys.size() > 1);
+ addDummyViews(itemsToPopulate, notificationKeys.size() > 1);
measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
orientAboutIcon(originalIcon, arrowHeight + arrowVerticalOffset);
mNotificationItemView = null;
mShortcutsItemView = null;
itemsToPopulate = PopupPopulator.reverseItems(itemsToPopulate);
- addDummyViews(originalIcon, itemsToPopulate, notificationKeys.size() > 1);
+ addDummyViews(itemsToPopulate, notificationKeys.size() > 1);
measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
orientAboutIcon(originalIcon, arrowHeight + arrowVerticalOffset);
updateNotificationHeader();
}
+ int numShortcuts = shortcutViews.size() + systemShortcutViews.size();
+ int numNotifications = notificationKeys.size();
+ if (numNotifications == 0) {
+ setContentDescription(getContext().getString(R.string.shortcuts_menu_description,
+ numShortcuts, originalIcon.getContentDescription().toString()));
+ } else {
+ setContentDescription(getContext().getString(
+ R.string.shortcuts_menu_with_notifications_description, numShortcuts,
+ numNotifications, originalIcon.getContentDescription().toString()));
+ }
+
// Add the arrow.
final int arrowHorizontalOffset = resources.getDimensionPixelSize(isAlignedWithStart() ?
R.dimen.popup_arrow_horizontal_offset_start :
systemShortcuts, systemShortcutViews));
}
- private void addDummyViews(BubbleTextView originalIcon,
- PopupPopulator.Item[] itemTypesToPopulate, boolean notificationFooterHasIcons) {
+ private void addDummyViews(PopupPopulator.Item[] itemTypesToPopulate,
+ boolean notificationFooterHasIcons) {
final Resources res = getResources();
final int spacing = res.getDimensionPixelSize(R.dimen.popup_items_spacing);
final LayoutInflater inflater = mLauncher.getLayoutInflater();
int footerHeight = notificationFooterHasIcons ?
res.getDimensionPixelSize(R.dimen.notification_footer_height) : 0;
item.findViewById(R.id.footer).getLayoutParams().height = footerHeight;
+ mNotificationItemView.getMainView().setAccessibilityDelegate(mAccessibilityDelegate);
+ } else if (itemTypeToPopulate == PopupPopulator.Item.SHORTCUT) {
+ item.setAccessibilityDelegate(mAccessibilityDelegate);
}
boolean shouldAddBottomMargin = nextItemTypeToPopulate != null
&& itemTypeToPopulate.isShortcut ^ nextItemTypeToPopulate.isShortcut;
- item.setAccessibilityDelegate(mAccessibilityDelegate);
if (itemTypeToPopulate.isShortcut) {
if (mShortcutsItemView == null) {
mShortcutsItemView = (ShortcutsItemView) inflater.inflate(
}
}
}
- // TODO: update this, since not all items are shortcuts
- setContentDescription(getContext().getString(R.string.shortcuts_menu_description,
- numItems, originalIcon.getContentDescription().toString()));
}
protected PopupItemView getItemViewAt(int index) {