diff options
Diffstat (limited to 'java/src')
14 files changed, 139 insertions, 80 deletions
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java index c628c5b09..ae826fe25 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibilityEntityProvider.java @@ -159,8 +159,7 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider // Add the virtual children of the root View. final Keyboard keyboard = mKeyboardView.getKeyboard(); - final Key[] keys = keyboard.getKeys(); - for (Key key : keys) { + for (final Key key : keyboard.getKeys()) { final int childVirtualViewId = generateVirtualViewIdForKey(key); rootInfo.addChild(mKeyboardView, childVirtualViewId); } @@ -308,8 +307,7 @@ public final class AccessibilityEntityProvider extends AccessibilityNodeProvider } mVirtualViewIdToKey.clear(); - final Key[] keys = keyboard.getKeys(); - for (Key key : keys) { + for (final Key key : keyboard.getKeys()) { final int virtualViewId = generateVirtualViewIdForKey(key); mVirtualViewIdToKey.put(virtualViewId, key); } diff --git a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java index 8822ccec9..3c50401fe 100644 --- a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java +++ b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java @@ -58,9 +58,10 @@ import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.ResourceUtils; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.Comparator; import java.util.HashMap; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @@ -123,7 +124,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange "places", "symbols", "emoticons" }; - private static final int[] sCategoryIcon = new int[] { + private static final int[] sCategoryIcon = { R.drawable.ic_emoji_recent_light, R.drawable.ic_emoji_people_light, R.drawable.ic_emoji_objects_light, @@ -133,6 +134,14 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange 0 }; private static final String[] sCategoryLabel = { null, null, null, null, null, null, ":-)" }; + private static final int[] sAccessibilityDescriptionResourceIdsForCategories = { + R.string.spoken_descrption_emoji_category_recents, + R.string.spoken_descrption_emoji_category_people, + R.string.spoken_descrption_emoji_category_objects, + R.string.spoken_descrption_emoji_category_nature, + R.string.spoken_descrption_emoji_category_places, + R.string.spoken_descrption_emoji_category_symbols, + R.string.spoken_descrption_emoji_category_emoticons }; private static final int[] sCategoryElementId = { KeyboardId.ELEMENT_EMOJI_RECENTS, KeyboardId.ELEMENT_EMOJI_CATEGORY1, @@ -142,6 +151,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange KeyboardId.ELEMENT_EMOJI_CATEGORY5, KeyboardId.ELEMENT_EMOJI_CATEGORY6 }; private final SharedPreferences mPrefs; + private final Resources mRes; private final int mMaxPageKeyCount; private final KeyboardLayoutSet mLayoutSet; private final HashMap<String, Integer> mCategoryNameToIdMap = CollectionUtils.newHashMap(); @@ -156,6 +166,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange public EmojiCategory(final SharedPreferences prefs, final Resources res, final KeyboardLayoutSet layoutSet) { mPrefs = prefs; + mRes = res; mMaxPageKeyCount = res.getInteger(R.integer.config_emoji_keyboard_max_page_key_count); mLayoutSet = layoutSet; for (int i = 0; i < sCategoryName.length; ++i) { @@ -206,6 +217,10 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange return sCategoryLabel[categoryId]; } + public String getAccessibilityDescription(final int categoryId) { + return mRes.getString(sAccessibilityDescriptionResourceIdsForCategories[categoryId]); + } + public ArrayList<CategoryProperties> getShownCategories() { return mShownCategories; } @@ -283,7 +298,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange private int getCategoryPageCount(final int categoryId) { final Keyboard keyboard = mLayoutSet.getKeyboard(sCategoryElementId[categoryId]); - return (keyboard.getKeys().length - 1) / mMaxPageKeyCount + 1; + return (keyboard.getKeys().size() - 1) / mMaxPageKeyCount + 1; } // Returns a pair of the category id and the category page id from the view pager's page @@ -380,13 +395,13 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange } }; - private static Key[][] sortKeysIntoPages(final Key[] inKeys, final int maxPageCount) { - final Key[] keys = Arrays.copyOf(inKeys, inKeys.length); - Arrays.sort(keys, 0, keys.length, EMOJI_KEY_COMPARATOR); - final int pageCount = (keys.length - 1) / maxPageCount + 1; + private static Key[][] sortKeysIntoPages(final List<Key> inKeys, final int maxPageCount) { + final ArrayList<Key> keys = CollectionUtils.newArrayList(inKeys); + Collections.sort(keys, EMOJI_KEY_COMPARATOR); + final int pageCount = (keys.size() - 1) / maxPageCount + 1; final Key[][] retval = new Key[pageCount][maxPageCount]; - for (int i = 0; i < keys.length; ++i) { - retval[i / maxPageCount][i % maxPageCount] = keys[i]; + for (int i = 0; i < keys.size(); ++i) { + retval[i / maxPageCount][i % maxPageCount] = keys.get(i); } return retval; } @@ -447,12 +462,14 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange final ImageView iconView = (ImageView)LayoutInflater.from(getContext()).inflate( R.layout.emoji_keyboard_tab_icon, null); iconView.setImageResource(mEmojiCategory.getCategoryIcon(categoryId)); + iconView.setContentDescription(mEmojiCategory.getAccessibilityDescription(categoryId)); tspec.setIndicator(iconView); } if (mEmojiCategory.getCategoryLabel(categoryId) != null) { final TextView textView = (TextView)LayoutInflater.from(getContext()).inflate( R.layout.emoji_keyboard_tab_label, null); textView.setText(mEmojiCategory.getCategoryLabel(categoryId)); + textView.setContentDescription(mEmojiCategory.getAccessibilityDescription(categoryId)); textView.setTextColor(mTabLabelColor); tspec.setIndicator(textView); } diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index 4fd3bac2f..516277035 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -25,6 +25,9 @@ import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.CoordinateUtils; +import java.util.Collections; +import java.util.List; + /** * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard * consists of rows of keys. @@ -74,10 +77,10 @@ public class Keyboard { /** Maximum column for more keys keyboard */ public final int mMaxMoreKeysKeyboardColumn; - /** Array of keys and icons in this keyboard */ - private final Key[] mKeys; - public final Key[] mShiftKeys; - public final Key[] mAltCodeKeysWhileTyping; + /** List of keys in this keyboard */ + private final List<Key> mKeys; + public final List<Key> mShiftKeys; + public final List<Key> mAltCodeKeysWhileTyping; public final KeyboardIconsSet mIconsSet; private final SparseArray<Key> mKeyCache = CollectionUtils.newSparseArray(); @@ -100,10 +103,9 @@ public class Keyboard { mTopPadding = params.mTopPadding; mVerticalGap = params.mVerticalGap; - mKeys = params.mKeys.toArray(new Key[params.mKeys.size()]); - mShiftKeys = params.mShiftKeys.toArray(new Key[params.mShiftKeys.size()]); - mAltCodeKeysWhileTyping = params.mAltCodeKeysWhileTyping.toArray( - new Key[params.mAltCodeKeysWhileTyping.size()]); + mKeys = Collections.unmodifiableList(CollectionUtils.newArrayList(params.mKeys)); + mShiftKeys = Collections.unmodifiableList(params.mShiftKeys); + mAltCodeKeysWhileTyping = Collections.unmodifiableList(params.mAltCodeKeysWhileTyping); mIconsSet = params.mIconsSet; mProximityInfo = new ProximityInfo(params.mId.mLocale.toString(), @@ -152,7 +154,7 @@ public class Keyboard { return mProximityInfo; } - public Key[] getKeys() { + public List<Key> getKeys() { return mKeys; } @@ -209,10 +211,10 @@ public class Keyboard { * Returns the array of the keys that are closest to the given point. * @param x the x-coordinate of the point * @param y the y-coordinate of the point - * @return the array of the nearest keys to the given point. If the given + * @return the list of the nearest keys to the given point. If the given * point is out of range, then an array of size zero is returned. */ - public Key[] getNearestKeys(final int x, final int y) { + public List<Key> getNearestKeys(final int x, final int y) { // Avoid dead pixels at edges of the keyboard final int adjustedX = Math.max(0, Math.min(x, mOccupiedWidth - 1)); final int adjustedY = Math.max(0, Math.min(y, mOccupiedHeight - 1)); diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java index a0316696c..fdb20f8fa 100644 --- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java +++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java @@ -22,9 +22,13 @@ import android.util.Log; import com.android.inputmethod.keyboard.internal.TouchPositionCorrection; import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.JniUtils; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.List; public class ProximityInfo { private static final String TAG = ProximityInfo.class.getSimpleName(); @@ -34,7 +38,7 @@ public class ProximityInfo { public static final int MAX_PROXIMITY_CHARS_SIZE = 16; /** Number of key widths from current touch point to search for nearest keys. */ private static final float SEARCH_DISTANCE = 1.2f; - private static final Key[] EMPTY_KEY_ARRAY = new Key[0]; + private static final List<Key> EMPTY_KEY_LIST = Collections.emptyList(); private static final float DEFAULT_TOUCH_POSITION_CORRECTION_RADIUS = 0.15f; private final int mGridWidth; @@ -47,13 +51,13 @@ public class ProximityInfo { private final int mKeyboardHeight; private final int mMostCommonKeyWidth; private final int mMostCommonKeyHeight; - private final Key[] mKeys; - private final Key[][] mGridNeighbors; + private final List<Key> mKeys; + private final List<Key>[] mGridNeighbors; private final String mLocaleStr; ProximityInfo(final String localeStr, final int gridWidth, final int gridHeight, final int minWidth, final int height, final int mostCommonKeyWidth, - final int mostCommonKeyHeight, final Key[] keys, + final int mostCommonKeyHeight, final List<Key> keys, final TouchPositionCorrection touchPositionCorrection) { if (TextUtils.isEmpty(localeStr)) { mLocaleStr = ""; @@ -70,7 +74,7 @@ public class ProximityInfo { mMostCommonKeyHeight = mostCommonKeyHeight; mMostCommonKeyWidth = mostCommonKeyWidth; mKeys = keys; - mGridNeighbors = new Key[mGridSize][]; + mGridNeighbors = new List[mGridSize]; if (minWidth == 0 || height == 0) { // No proximity required. Keyboard might be more keys keyboard. return; @@ -99,7 +103,7 @@ public class ProximityInfo { return key.getCode() >= Constants.CODE_SPACE; } - private static int getProximityInfoKeysCount(final Key[] keys) { + private static int getProximityInfoKeysCount(final List<Key> keys) { int count = 0; for (final Key key : keys) { if (needsProximityInfo(key)) { @@ -110,14 +114,14 @@ public class ProximityInfo { } private long createNativeProximityInfo(final TouchPositionCorrection touchPositionCorrection) { - final Key[][] gridNeighborKeys = mGridNeighbors; + final List<Key>[] gridNeighborKeys = mGridNeighbors; final int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE]; Arrays.fill(proximityCharsArray, Constants.NOT_A_CODE); for (int i = 0; i < mGridSize; ++i) { - final int proximityCharsLength = gridNeighborKeys[i].length; + final int proximityCharsLength = gridNeighborKeys[i].size(); int infoIndex = i * MAX_PROXIMITY_CHARS_SIZE; for (int j = 0; j < proximityCharsLength; ++j) { - final Key neighborKey = gridNeighborKeys[i][j]; + final Key neighborKey = gridNeighborKeys[i].get(j); // Excluding from proximityCharsArray if (!needsProximityInfo(neighborKey)) { continue; @@ -142,7 +146,7 @@ public class ProximityInfo { } } - final Key[] keys = mKeys; + final List<Key> keys = mKeys; final int keyCount = getProximityInfoKeysCount(keys); final int[] keyXCoordinates = new int[keyCount]; final int[] keyYCoordinates = new int[keyCount]; @@ -153,8 +157,8 @@ public class ProximityInfo { final float[] sweetSpotCenterYs; final float[] sweetSpotRadii; - for (int infoIndex = 0, keyIndex = 0; keyIndex < keys.length; keyIndex++) { - final Key key = keys[keyIndex]; + for (int infoIndex = 0, keyIndex = 0; keyIndex < keys.size(); keyIndex++) { + final Key key = keys.get(keyIndex); // Excluding from key coordinate arrays if (!needsProximityInfo(key)) { continue; @@ -177,8 +181,8 @@ public class ProximityInfo { final int rows = touchPositionCorrection.getRows(); final float defaultRadius = DEFAULT_TOUCH_POSITION_CORRECTION_RADIUS * (float)Math.hypot(mMostCommonKeyWidth, mMostCommonKeyHeight); - for (int infoIndex = 0, keyIndex = 0; keyIndex < keys.length; keyIndex++) { - final Key key = keys[keyIndex]; + for (int infoIndex = 0, keyIndex = 0; keyIndex < keys.size(); keyIndex++) { + final Key key = keys.get(keyIndex); // Excluding from touch position correction arrays if (!needsProximityInfo(key)) { continue; @@ -240,7 +244,7 @@ public class ProximityInfo { private void computeNearestNeighbors() { final int defaultWidth = mMostCommonKeyWidth; - final int keyCount = mKeys.length; + final int keyCount = mKeys.size(); final int gridSize = mGridNeighbors.length; final int threshold = (int) (defaultWidth * SEARCH_DISTANCE); final int thresholdSquared = threshold * threshold; @@ -353,9 +357,13 @@ y |---+---+---+---+-v-+-|-+---+---+---+---+---| | thresholdBase and get } for (int i = 0; i < gridSize; ++i) { - final int base = i * keyCount; - mGridNeighbors[i] = - Arrays.copyOfRange(neighborsFlatBuffer, base, base + neighborCountPerCell[i]); + final int indexStart = i * keyCount; + final int indexEnd = indexStart + neighborCountPerCell[i]; + final ArrayList<Key> neighbords = CollectionUtils.newArrayList(indexEnd - indexStart); + for (int index = indexStart; index < indexEnd; index++) { + neighbords.add(neighborsFlatBuffer[index]); + } + mGridNeighbors[i] = Collections.unmodifiableList(neighbords); } } @@ -369,7 +377,7 @@ y |---+---+---+---+-v-+-|-+---+---+---+---+---| | thresholdBase and get if (primaryKeyCode > Constants.CODE_SPACE) { dest[index++] = primaryKeyCode; } - final Key[] nearestKeys = getNearestKeys(x, y); + final List<Key> nearestKeys = getNearestKeys(x, y); for (Key key : nearestKeys) { if (index >= destLength) { break; @@ -385,9 +393,9 @@ y |---+---+---+---+-v-+-|-+---+---+---+---+---| | thresholdBase and get } } - public Key[] getNearestKeys(final int x, final int y) { + public List<Key> getNearestKeys(final int x, final int y) { if (mGridNeighbors == null) { - return EMPTY_KEY_ARRAY; + return EMPTY_KEY_LIST; } if (x >= 0 && x < mKeyboardMinWidth && y >= 0 && y < mKeyboardHeight) { int index = (y / mCellHeight) * mGridWidth + (x / mCellWidth); @@ -395,6 +403,6 @@ y |---+---+---+---+-v-+-|-+---+---+---+---+---| | thresholdBase and get return mGridNeighbors[index]; } } - return EMPTY_KEY_ARRAY; + return EMPTY_KEY_LIST; } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java b/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java index e2fd39017..dd5ec1def 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java @@ -29,7 +29,9 @@ import com.android.inputmethod.latin.utils.JsonUtils; import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.List; /** @@ -50,7 +52,7 @@ public class DynamicGridKeyboard extends Keyboard { private final ArrayDeque<GridKey> mGridKeys = CollectionUtils.newArrayDeque(); private final ArrayDeque<Key> mPendingKeys = CollectionUtils.newArrayDeque(); - private Key[] mCachedGridKeys; + private List<Key> mCachedGridKeys; public DynamicGridKeyboard(final SharedPreferences prefs, final Keyboard templateKeyboard, final int maxKeyCount, final int categoryId) { @@ -205,18 +207,20 @@ public class DynamicGridKeyboard extends Keyboard { } @Override - public Key[] getKeys() { + public List<Key> getKeys() { synchronized (mLock) { if (mCachedGridKeys != null) { return mCachedGridKeys; } - mCachedGridKeys = mGridKeys.toArray(new Key[mGridKeys.size()]); + final ArrayList<Key> cachedKeys = CollectionUtils.newArrayList(mGridKeys.size()); + cachedKeys.addAll(mGridKeys); + mCachedGridKeys = Collections.unmodifiableList(cachedKeys); return mCachedGridKeys; } } @Override - public Key[] getNearestKeys(final int x, final int y) { + public List<Key> getNearestKeys(final int x, final int y) { // TODO: Calculate the nearest key index in mGridKeys from x and y. return getKeys(); } diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 621eb2dfa..38359fc15 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -260,7 +260,7 @@ public final class BinaryDictionary extends Dictionary { final int inputSize; if (!isGesture) { inputSize = composer.copyCodePointsExceptTrailingSingleQuotesAndReturnCodePointCount( - mInputCodePoints, MAX_WORD_LENGTH); + mInputCodePoints); if (inputSize < 0) { return null; } diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java index 7cb218fbe..0b6258a7f 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java @@ -421,7 +421,19 @@ public class DictionaryFacilitatorForSuggest { final String suggestionLowerCase = suggestion.toLowerCase(dictionaries.mLocale); final String secondWord; if (wasAutoCapitalized) { - secondWord = suggestionLowerCase; + if (isValidWord(suggestion, false /* ignoreCase */) + && !isValidWord(suggestionLowerCase, false /* ignoreCase */)) { + // If the word was auto-capitalized and exists only as a capitalized word in the + // dictionary, then we must not downcase it before registering it. For example, + // the name of the contacts in start-of-sentence position would come here with the + // wasAutoCapitalized flag: if we downcase it, we'd register a lower-case version + // of that contact's name which would end up popping in suggestions. + secondWord = suggestion; + } else { + // If however the word is not in the dictionary, or exists as a lower-case word + // only, then we consider that was a lower-case word that had been auto-capitalized. + secondWord = suggestionLowerCase; + } } else { // HACK: We'd like to avoid adding the capitalized form of common words to the User // History dictionary in order to avoid suggesting them until the dictionary diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 1fdb8d16c..81b02c396 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -237,7 +237,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Otherwise, we'll do it when we can. latinIme.mKeyboardSwitcher.loadKeyboard(latinIme.getCurrentInputEditorInfo(), settingsValues, latinIme.getCurrentAutoCapsState(), - latinIme.getCurrentAutoCapsState()); + latinIme.getCurrentRecapitalizeState()); } break; } @@ -501,7 +501,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final IntentFilter filter = new IntentFilter(); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); - registerReceiver(mReceiver, filter); + registerReceiver(mConnectivityAndRingerModeChangeReceiver, filter); final IntentFilter packageFilter = new IntentFilter(); packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); @@ -630,7 +630,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen public void onDestroy() { mInputLogic.mSuggest.mDictionaryFacilitator.closeDictionaries(); mSettings.onDestroy(); - unregisterReceiver(mReceiver); + unregisterReceiver(mConnectivityAndRingerModeChangeReceiver); if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { ResearchLogger.getInstance().onDestroy(); } @@ -645,6 +645,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen @UsedForTesting public void recycle() { + unregisterReceiver(mDictionaryPackInstallReceiver); + unregisterReceiver(mDictionaryDumpBroadcastReceiver); + unregisterReceiver(mConnectivityAndRingerModeChangeReceiver); mInputLogic.recycle(); } @@ -816,9 +819,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // When rotating, initialSelStart and initialSelEnd sometimes are lying. Make a best // effort to work around this bug. mInputLogic.mConnection.tryFixLyingCursorPosition(); - if (isDifferentTextField) { - mHandler.postResumeSuggestions(); - } + mHandler.postResumeSuggestions(); canReachInputConnection = true; } @@ -1635,7 +1636,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // boolean onKeyMultiple(final int keyCode, final int count, final KeyEvent event); // receive ringer mode change and network state change. - private BroadcastReceiver mReceiver = new BroadcastReceiver() { + private BroadcastReceiver mConnectivityAndRingerModeChangeReceiver = new BroadcastReceiver() { @Override public void onReceive(final Context context, final Intent intent) { final String action = intent.getAction(); diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index 1268e5aac..d755195f2 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -129,22 +129,25 @@ public final class WordComposer { * -1 is returned. * * @param destination the array of ints. - * @param maxSize the size of the array. * @return the number of copied code points. */ public int copyCodePointsExceptTrailingSingleQuotesAndReturnCodePointCount( - final int[] destination, final int maxSize) { - final int i = mTypedWordCache.length() - 1 - trailingSingleQuotesCount(); - if (i < 0) { + final int[] destination) { + // lastIndex is exclusive + final int lastIndex = mTypedWordCache.length() - trailingSingleQuotesCount(); + if (lastIndex <= 0) { // The string is empty or contains only single quotes. return 0; } - final int codePointSize = Character.codePointCount(mTypedWordCache, 0, i); - if (codePointSize > maxSize) { + + // The following function counts the number of code points in the text range which begins + // at index 0 and extends to the character at lastIndex. + final int codePointSize = Character.codePointCount(mTypedWordCache, 0, lastIndex); + if (codePointSize > destination.length) { return -1; } return StringUtils.copyCodePointsAndReturnCodePointCount(destination, mTypedWordCache, 0, - i + 1, true /* downCase */); + lastIndex, true /* downCase */); } public boolean isSingleLetter() { diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index 491d98074..f1f906042 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -1284,6 +1284,10 @@ public final class InputLogic { || !settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces // If no suggestions are requested, don't try restarting suggestions. || !settingsValues.isSuggestionsRequested() + // If we are currently in a batch input, we must not resume suggestions, or the result + // of the batch input will replace the new composition. This may happen in the corner case + // that the app moves the cursor on its own accord during a batch input. + || mInputLogicHandler.isInBatchInput() // If the cursor is not touching a word, or if there is a selection, return right away. || mConnection.hasSelection() // If we don't know the cursor location, return. diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java index 64bba681f..9dbe2c38b 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java @@ -110,6 +110,10 @@ class InputLogicHandler implements Handler.Callback { } } + public boolean isInBatchInput() { + return mInBatchInput; + } + /** * Fetch suggestions corresponding to an update of a batch input. * @param batchPointers the updated pointers, including the part that was passed last time. diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index 3cdd07361..a0793b133 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -240,6 +240,9 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick if (TextUtils.isEmpty(importantNoticeTitle)) { return false; } + if (isShowingMoreSuggestionPanel()) { + dismissMoreSuggestionsPanel(); + } mLayoutHelper.layoutImportantNotice(mImportantNoticeStrip, importantNoticeTitle); mStripVisibilityGroup.showImportantNoticeStrip(); mImportantNoticeStrip.setOnClickListener(this); diff --git a/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java b/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java index ee9718ad3..ed502ed3d 100644 --- a/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java @@ -47,8 +47,13 @@ public class ExecutorUtils { public static void shutdownAllExecutors() { synchronized(sExecutorMap) { for (final PrioritizedSerialExecutor executor : sExecutorMap.values()) { - executor.shutdown(); - sExecutorMap.remove(executor); + executor.execute(new Runnable() { + @Override + public void run() { + executor.shutdown(); + sExecutorMap.remove(executor); + } + }); } } } diff --git a/java/src/com/android/inputmethod/latin/utils/RunInLocale.java b/java/src/com/android/inputmethod/latin/utils/RunInLocale.java index 2c9e3b191..3c632bbc3 100644 --- a/java/src/com/android/inputmethod/latin/utils/RunInLocale.java +++ b/java/src/com/android/inputmethod/latin/utils/RunInLocale.java @@ -30,25 +30,23 @@ public abstract class RunInLocale<T> { * Execute {@link #job(Resources)} method in specified system locale exclusively. * * @param res the resources to use. - * @param newLocale the locale to change to. + * @param newLocale the locale to change to. Run in system locale if null. * @return the value returned from {@link #job(Resources)}. */ public T runInLocale(final Resources res, final Locale newLocale) { synchronized (sLockForRunInLocale) { - final Configuration conf = res.getConfiguration(); - final Locale oldLocale = conf.locale; - final boolean needsChange = (newLocale != null && !newLocale.equals(oldLocale)); + final Configuration savedConf = res.getConfiguration(); + if (newLocale == null || newLocale.equals(savedConf.locale)) { + return job(res); + } + final Configuration newConf = new Configuration(); + newConf.setTo(savedConf); + newConf.setLocale(newLocale); try { - if (needsChange) { - conf.locale = newLocale; - res.updateConfiguration(conf, null); - } + res.updateConfiguration(newConf, null); return job(res); } finally { - if (needsChange) { - conf.locale = oldLocale; - res.updateConfiguration(conf, null); - } + res.updateConfiguration(savedConf, null); } } } |