From 305778b53a5e7c865cae4010e657d00bb9bf5075 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Tue, 20 May 2014 16:25:33 +0900 Subject: [PATCH] Support accessibility TalkBack in emoji palette Bug: 11452158 Change-Id: I699e4e9f4baec4bb0fb9cd7875f675044f20465f --- .../KeyCodeDescriptionMapper.java | 42 ++++++++++++------- .../keyboard/emoji/EmojiPageKeyboardView.java | 13 ++++++ 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java index 0499a3456..46caef625 100644 --- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java +++ b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java @@ -17,6 +17,7 @@ package com.android.inputmethod.accessibility; import android.content.Context; +import android.content.res.Resources; import android.text.TextUtils; import android.util.Log; import android.util.SparseIntArray; @@ -27,21 +28,18 @@ import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardId; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.utils.CollectionUtils; -import java.util.HashMap; +import java.util.Locale; public final class KeyCodeDescriptionMapper { private static final String TAG = KeyCodeDescriptionMapper.class.getSimpleName(); + private static final String SPOKEN_EMOJI_RESOURCE_NAME_FORMAT = "spoken_emoji_%04X"; // The resource ID of the string spoken for obscured keys private static final int OBSCURED_KEY_RES_ID = R.string.spoken_description_dot; private static KeyCodeDescriptionMapper sInstance = new KeyCodeDescriptionMapper(); - // Map of key labels to spoken description resource IDs - private final HashMap mKeyLabelMap = CollectionUtils.newHashMap(); - // Sparse array of spoken description resource IDs indexed by key codes private final SparseIntArray mKeyCodeMap; @@ -114,17 +112,12 @@ public final class KeyCodeDescriptionMapper { return getDescriptionForActionKey(context, keyboard, key); } - if (!TextUtils.isEmpty(key.getLabel())) { - final String label = key.getLabel().trim(); - - // First, attempt to map the label to a pre-defined description. - if (mKeyLabelMap.containsKey(label)) { - return context.getString(mKeyLabelMap.get(label)); - } + if (code == Constants.CODE_OUTPUT_TEXT) { + return key.getOutputText(); } // Just attempt to speak the description. - if (key.getCode() != Constants.CODE_UNSPECIFIED) { + if (code != Constants.CODE_UNSPECIFIED) { return getDescriptionForKeyCode(context, keyboard, key, shouldObscure); } return null; @@ -139,7 +132,7 @@ public final class KeyCodeDescriptionMapper { * @param keyboard The keyboard on which the key resides. * @return a character sequence describing the action performed by pressing the key */ - private String getDescriptionForSwitchAlphaSymbol(final Context context, + private static String getDescriptionForSwitchAlphaSymbol(final Context context, final Keyboard keyboard) { final KeyboardId keyboardId = keyboard.mId; final int elementId = keyboardId.mElementId; @@ -177,7 +170,8 @@ public final class KeyCodeDescriptionMapper { * @param keyboard The keyboard on which the key resides. * @return A context-sensitive description of the "Shift" key. */ - private String getDescriptionForShiftKey(final Context context, final Keyboard keyboard) { + private static String getDescriptionForShiftKey(final Context context, + final Keyboard keyboard) { final KeyboardId keyboardId = keyboard.mId; final int elementId = keyboardId.mElementId; final int resId; @@ -211,7 +205,7 @@ public final class KeyCodeDescriptionMapper { * @param key The key to describe. * @return Returns a context-sensitive description of the "Enter" action key. */ - private String getDescriptionForActionKey(final Context context, final Keyboard keyboard, + private static String getDescriptionForActionKey(final Context context, final Keyboard keyboard, final Key key) { final KeyboardId keyboardId = keyboard.mId; final int actionId = keyboardId.imeAction(); @@ -280,6 +274,13 @@ public final class KeyCodeDescriptionMapper { if (mKeyCodeMap.indexOfKey(code) >= 0) { return context.getString(mKeyCodeMap.get(code)); } + final int spokenEmojiId = getSpokenDescriptionId( + context, code, SPOKEN_EMOJI_RESOURCE_NAME_FORMAT); + if (spokenEmojiId != 0) { + final String spokenEmoji = context.getString(spokenEmojiId); + mKeyCodeMap.append(code, spokenEmojiId); + return spokenEmoji; + } if (isDefinedNonCtrl) { return Character.toString((char) code); } @@ -288,4 +289,13 @@ public final class KeyCodeDescriptionMapper { } return context.getString(R.string.spoken_description_unknown, code); } + + private static int getSpokenDescriptionId(final Context context, final int code, + final String resourceNameFormat) { + final String resourceName = String.format(Locale.ROOT, resourceNameFormat, code); + final Resources resources = context.getResources(); + final String packageName = resources.getResourcePackageName( + R.string.spoken_description_unknown); + return resources.getIdentifier(resourceName, "string", packageName); + } } diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java index d14ffeef9..48efa17ad 100644 --- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPageKeyboardView.java @@ -22,6 +22,8 @@ import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; +import com.android.inputmethod.accessibility.AccessibilityUtils; +import com.android.inputmethod.accessibility.KeyboardAccessibilityDelegate; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; @@ -53,6 +55,7 @@ final class EmojiPageKeyboardView extends KeyboardView implements private OnKeyEventListener mListener = EMPTY_LISTENER; private final KeyDetector mKeyDetector = new KeyDetector(); private final GestureDetector mGestureDetector; + private final KeyboardAccessibilityDelegate mAccessibilityDelegate; public EmojiPageKeyboardView(final Context context, final AttributeSet attrs) { this(context, attrs, R.attr.keyboardViewStyle); @@ -64,6 +67,7 @@ final class EmojiPageKeyboardView extends KeyboardView implements mGestureDetector = new GestureDetector(context, this); mGestureDetector.setIsLongpressEnabled(false /* isLongpressEnabled */); mHandler = new Handler(); + mAccessibilityDelegate = new KeyboardAccessibilityDelegate<>(this, mKeyDetector); } public void setOnKeyEventListener(final OnKeyEventListener listener) { @@ -79,6 +83,15 @@ final class EmojiPageKeyboardView extends KeyboardView implements mKeyDetector.setKeyboard(keyboard, 0 /* correctionX */, 0 /* correctionY */); } + @Override + public boolean dispatchHoverEvent(final MotionEvent event) { + if (!AccessibilityUtils.getInstance().isTouchExplorationEnabled()) { + // Reflection doesn't support calling superclass methods. + return false; + } + return mAccessibilityDelegate.dispatchHoverEvent(event); + } + /** * {@inheritDoc} */