aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
diff options
context:
space:
mode:
authorAmin Bandali <bandali@kelar.org>2024-12-16 21:45:41 -0500
committerAmin Bandali <bandali@kelar.org>2025-01-11 14:17:35 -0500
commite9a0e66716dab4dd3184d009d8920de1961efdfa (patch)
tree02dcc096643d74645bf28459c2834c3d4a2ad7f2 /java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
parentfb3b9360d70596d7e921de8bf7d3ca99564a077e (diff)
downloadlatinime-e9a0e66716dab4dd3184d009d8920de1961efdfa.tar.gz
latinime-e9a0e66716dab4dd3184d009d8920de1961efdfa.tar.xz
latinime-e9a0e66716dab4dd3184d009d8920de1961efdfa.zip
Rename to Kelar Keyboard (org.kelar.inputmethod.latin)
Diffstat (limited to 'java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java')
-rw-r--r--java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java365
1 files changed, 0 insertions, 365 deletions
diff --git a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java b/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
deleted file mode 100644
index bbda9f8e2..000000000
--- a/java/src/com/android/inputmethod/accessibility/KeyCodeDescriptionMapper.java
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (C) 2011 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.inputmethod.accessibility;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.SparseIntArray;
-import android.view.inputmethod.EditorInfo;
-
-import com.android.inputmethod.keyboard.Key;
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.KeyboardId;
-import com.android.inputmethod.latin.R;
-import com.android.inputmethod.latin.common.Constants;
-import com.android.inputmethod.latin.common.StringUtils;
-
-import java.util.Locale;
-
-final class KeyCodeDescriptionMapper {
- private static final String TAG = KeyCodeDescriptionMapper.class.getSimpleName();
- private static final String SPOKEN_LETTER_RESOURCE_NAME_FORMAT = "spoken_accented_letter_%04X";
- private static final String SPOKEN_SYMBOL_RESOURCE_NAME_FORMAT = "spoken_symbol_%04X";
- private static final String SPOKEN_EMOJI_RESOURCE_NAME_FORMAT = "spoken_emoji_%04X";
- private static final String SPOKEN_EMOTICON_RESOURCE_NAME_PREFIX = "spoken_emoticon";
- private static final String SPOKEN_EMOTICON_CODE_POINT_FORMAT = "_%02X";
-
- // 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 final KeyCodeDescriptionMapper sInstance = new KeyCodeDescriptionMapper();
-
- public static KeyCodeDescriptionMapper getInstance() {
- return sInstance;
- }
-
- // Sparse array of spoken description resource IDs indexed by key codes
- private final SparseIntArray mKeyCodeMap = new SparseIntArray();
-
- private KeyCodeDescriptionMapper() {
- // Special non-character codes defined in Keyboard
- mKeyCodeMap.put(Constants.CODE_SPACE, R.string.spoken_description_space);
- mKeyCodeMap.put(Constants.CODE_DELETE, R.string.spoken_description_delete);
- mKeyCodeMap.put(Constants.CODE_ENTER, R.string.spoken_description_return);
- mKeyCodeMap.put(Constants.CODE_SETTINGS, R.string.spoken_description_settings);
- mKeyCodeMap.put(Constants.CODE_SHIFT, R.string.spoken_description_shift);
- mKeyCodeMap.put(Constants.CODE_SHORTCUT, R.string.spoken_description_mic);
- mKeyCodeMap.put(Constants.CODE_SWITCH_ALPHA_SYMBOL, R.string.spoken_description_to_symbol);
- mKeyCodeMap.put(Constants.CODE_TAB, R.string.spoken_description_tab);
- mKeyCodeMap.put(Constants.CODE_LANGUAGE_SWITCH,
- R.string.spoken_description_language_switch);
- mKeyCodeMap.put(Constants.CODE_ACTION_NEXT, R.string.spoken_description_action_next);
- mKeyCodeMap.put(Constants.CODE_ACTION_PREVIOUS,
- R.string.spoken_description_action_previous);
- mKeyCodeMap.put(Constants.CODE_EMOJI, R.string.spoken_description_emoji);
- // Because the upper-case and lower-case mappings of the following letters is depending on
- // the locale, the upper case descriptions should be defined here. The lower case
- // descriptions are handled in {@link #getSpokenLetterDescriptionId(Context,int)}.
- // U+0049: "I" LATIN CAPITAL LETTER I
- // U+0069: "i" LATIN SMALL LETTER I
- // U+0130: "İ" LATIN CAPITAL LETTER I WITH DOT ABOVE
- // U+0131: "ı" LATIN SMALL LETTER DOTLESS I
- mKeyCodeMap.put(0x0049, R.string.spoken_letter_0049);
- mKeyCodeMap.put(0x0130, R.string.spoken_letter_0130);
- }
-
- /**
- * Returns the localized description of the action performed by a specified
- * key based on the current keyboard state.
- *
- * @param context The package's context.
- * @param keyboard The keyboard on which the key resides.
- * @param key The key from which to obtain a description.
- * @param shouldObscure {@true} if text (e.g. non-control) characters should be obscured.
- * @return a character sequence describing the action performed by pressing the key
- */
- public String getDescriptionForKey(final Context context, final Keyboard keyboard,
- final Key key, final boolean shouldObscure) {
- final int code = key.getCode();
-
- if (code == Constants.CODE_SWITCH_ALPHA_SYMBOL) {
- final String description = getDescriptionForSwitchAlphaSymbol(context, keyboard);
- if (description != null) {
- return description;
- }
- }
-
- if (code == Constants.CODE_SHIFT) {
- return getDescriptionForShiftKey(context, keyboard);
- }
-
- if (code == Constants.CODE_ENTER) {
- // The following function returns the correct description in all action and
- // regular enter cases, taking care of all modes.
- return getDescriptionForActionKey(context, keyboard, key);
- }
-
- if (code == Constants.CODE_OUTPUT_TEXT) {
- final String outputText = key.getOutputText();
- final String description = getSpokenEmoticonDescription(context, outputText);
- return TextUtils.isEmpty(description) ? outputText : description;
- }
-
- // Just attempt to speak the description.
- if (code != Constants.CODE_UNSPECIFIED) {
- // If the key description should be obscured, now is the time to do it.
- final boolean isDefinedNonCtrl = Character.isDefined(code)
- && !Character.isISOControl(code);
- if (shouldObscure && isDefinedNonCtrl) {
- return context.getString(OBSCURED_KEY_RES_ID);
- }
- final String description = getDescriptionForCodePoint(context, code);
- if (description != null) {
- return description;
- }
- if (!TextUtils.isEmpty(key.getLabel())) {
- return key.getLabel();
- }
- return context.getString(R.string.spoken_description_unknown);
- }
- return null;
- }
-
- /**
- * Returns a context-specific description for the CODE_SWITCH_ALPHA_SYMBOL
- * key or {@code null} if there is not a description provided for the
- * current keyboard context.
- *
- * @param context The package's context.
- * @param keyboard The keyboard on which the key resides.
- * @return a character sequence describing the action performed by pressing the key
- */
- private static String getDescriptionForSwitchAlphaSymbol(final Context context,
- final Keyboard keyboard) {
- final KeyboardId keyboardId = keyboard.mId;
- final int elementId = keyboardId.mElementId;
- final int resId;
-
- switch (elementId) {
- case KeyboardId.ELEMENT_ALPHABET:
- case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED:
- case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED:
- case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED:
- case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED:
- resId = R.string.spoken_description_to_symbol;
- break;
- case KeyboardId.ELEMENT_SYMBOLS:
- case KeyboardId.ELEMENT_SYMBOLS_SHIFTED:
- resId = R.string.spoken_description_to_alpha;
- break;
- case KeyboardId.ELEMENT_PHONE:
- resId = R.string.spoken_description_to_symbol;
- break;
- case KeyboardId.ELEMENT_PHONE_SYMBOLS:
- resId = R.string.spoken_description_to_numeric;
- break;
- default:
- Log.e(TAG, "Missing description for keyboard element ID:" + elementId);
- return null;
- }
- return context.getString(resId);
- }
-
- /**
- * Returns a context-sensitive description of the "Shift" key.
- *
- * @param context The package's context.
- * @param keyboard The keyboard on which the key resides.
- * @return A context-sensitive description of the "Shift" key.
- */
- private static String getDescriptionForShiftKey(final Context context,
- final Keyboard keyboard) {
- final KeyboardId keyboardId = keyboard.mId;
- final int elementId = keyboardId.mElementId;
- final int resId;
-
- switch (elementId) {
- case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCK_SHIFTED:
- case KeyboardId.ELEMENT_ALPHABET_SHIFT_LOCKED:
- resId = R.string.spoken_description_caps_lock;
- break;
- case KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED:
- case KeyboardId.ELEMENT_ALPHABET_MANUAL_SHIFTED:
- resId = R.string.spoken_description_shift_shifted;
- break;
- case KeyboardId.ELEMENT_SYMBOLS:
- resId = R.string.spoken_description_symbols_shift;
- break;
- case KeyboardId.ELEMENT_SYMBOLS_SHIFTED:
- resId = R.string.spoken_description_symbols_shift_shifted;
- break;
- default:
- resId = R.string.spoken_description_shift;
- }
- return context.getString(resId);
- }
-
- /**
- * Returns a context-sensitive description of the "Enter" action key.
- *
- * @param context The package's context.
- * @param keyboard The keyboard on which the key resides.
- * @param key The key to describe.
- * @return Returns a context-sensitive description of the "Enter" action key.
- */
- private static String getDescriptionForActionKey(final Context context, final Keyboard keyboard,
- final Key key) {
- final KeyboardId keyboardId = keyboard.mId;
- final int actionId = keyboardId.imeAction();
- final int resId;
-
- // Always use the label, if available.
- if (!TextUtils.isEmpty(key.getLabel())) {
- return key.getLabel().trim();
- }
-
- // Otherwise, use the action ID.
- switch (actionId) {
- case EditorInfo.IME_ACTION_SEARCH:
- resId = R.string.spoken_description_search;
- break;
- case EditorInfo.IME_ACTION_GO:
- resId = R.string.label_go_key;
- break;
- case EditorInfo.IME_ACTION_SEND:
- resId = R.string.label_send_key;
- break;
- case EditorInfo.IME_ACTION_NEXT:
- resId = R.string.label_next_key;
- break;
- case EditorInfo.IME_ACTION_DONE:
- resId = R.string.label_done_key;
- break;
- case EditorInfo.IME_ACTION_PREVIOUS:
- resId = R.string.label_previous_key;
- break;
- default:
- resId = R.string.spoken_description_return;
- }
- return context.getString(resId);
- }
-
- /**
- * Returns a localized character sequence describing what will happen when
- * the specified key is pressed based on its key code point.
- *
- * @param context The package's context.
- * @param codePoint The code point from which to obtain a description.
- * @return a character sequence describing the code point.
- */
- public String getDescriptionForCodePoint(final Context context, final int codePoint) {
- // If the key description should be obscured, now is the time to do it.
- final int index = mKeyCodeMap.indexOfKey(codePoint);
- if (index >= 0) {
- return context.getString(mKeyCodeMap.valueAt(index));
- }
- final String accentedLetter = getSpokenAccentedLetterDescription(context, codePoint);
- if (accentedLetter != null) {
- return accentedLetter;
- }
- // Here, <code>code</code> may be a base (non-accented) letter.
- final String unsupportedSymbol = getSpokenSymbolDescription(context, codePoint);
- if (unsupportedSymbol != null) {
- return unsupportedSymbol;
- }
- final String emojiDescription = getSpokenEmojiDescription(context, codePoint);
- if (emojiDescription != null) {
- return emojiDescription;
- }
- if (Character.isDefined(codePoint) && !Character.isISOControl(codePoint)) {
- return StringUtils.newSingleCodePointString(codePoint);
- }
- return null;
- }
-
- // TODO: Remove this method once TTS supports those accented letters' verbalization.
- private String getSpokenAccentedLetterDescription(final Context context, final int code) {
- final boolean isUpperCase = Character.isUpperCase(code);
- final int baseCode = isUpperCase ? Character.toLowerCase(code) : code;
- final int baseIndex = mKeyCodeMap.indexOfKey(baseCode);
- final int resId = (baseIndex >= 0) ? mKeyCodeMap.valueAt(baseIndex)
- : getSpokenDescriptionId(context, baseCode, SPOKEN_LETTER_RESOURCE_NAME_FORMAT);
- if (resId == 0) {
- return null;
- }
- final String spokenText = context.getString(resId);
- return isUpperCase ? context.getString(R.string.spoken_description_upper_case, spokenText)
- : spokenText;
- }
-
- // TODO: Remove this method once TTS supports those symbols' verbalization.
- private String getSpokenSymbolDescription(final Context context, final int code) {
- final int resId = getSpokenDescriptionId(context, code, SPOKEN_SYMBOL_RESOURCE_NAME_FORMAT);
- if (resId == 0) {
- return null;
- }
- final String spokenText = context.getString(resId);
- if (!TextUtils.isEmpty(spokenText)) {
- return spokenText;
- }
- // If a translated description is empty, fall back to unknown symbol description.
- return context.getString(R.string.spoken_symbol_unknown);
- }
-
- // TODO: Remove this method once TTS supports emoji verbalization.
- private String getSpokenEmojiDescription(final Context context, final int code) {
- final int resId = getSpokenDescriptionId(context, code, SPOKEN_EMOJI_RESOURCE_NAME_FORMAT);
- if (resId == 0) {
- return null;
- }
- final String spokenText = context.getString(resId);
- if (!TextUtils.isEmpty(spokenText)) {
- return spokenText;
- }
- // If a translated description is empty, fall back to unknown emoji description.
- return context.getString(R.string.spoken_emoji_unknown);
- }
-
- private 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();
- // Note that the resource package name may differ from the context package name.
- final String resourcePackageName = resources.getResourcePackageName(
- R.string.spoken_description_unknown);
- final int resId = resources.getIdentifier(resourceName, "string", resourcePackageName);
- if (resId != 0) {
- mKeyCodeMap.append(code, resId);
- }
- return resId;
- }
-
- // TODO: Remove this method once TTS supports emoticon verbalization.
- private static String getSpokenEmoticonDescription(final Context context,
- final String outputText) {
- final StringBuilder sb = new StringBuilder(SPOKEN_EMOTICON_RESOURCE_NAME_PREFIX);
- final int textLength = outputText.length();
- for (int index = 0; index < textLength; index = outputText.offsetByCodePoints(index, 1)) {
- final int codePoint = outputText.codePointAt(index);
- sb.append(String.format(Locale.ROOT, SPOKEN_EMOTICON_CODE_POINT_FORMAT, codePoint));
- }
- final String resourceName = sb.toString();
- final Resources resources = context.getResources();
- // Note that the resource package name may differ from the context package name.
- final String resourcePackageName = resources.getResourcePackageName(
- R.string.spoken_description_unknown);
- final int resId = resources.getIdentifier(resourceName, "string", resourcePackageName);
- return (resId == 0) ? null : resources.getString(resId);
- }
-}