diff options
Diffstat (limited to 'java/src')
10 files changed, 201 insertions, 121 deletions
diff --git a/java/src/com/android/inputmethod/compat/AppWorkaroundsUtils.java b/java/src/com/android/inputmethod/compat/AppWorkaroundsUtils.java index 7e9e2e37b..6e43cc9a7 100644 --- a/java/src/com/android/inputmethod/compat/AppWorkaroundsUtils.java +++ b/java/src/com/android/inputmethod/compat/AppWorkaroundsUtils.java @@ -23,10 +23,10 @@ import android.os.Build.VERSION_CODES; * A class to encapsulate work-arounds specific to particular apps. */ public class AppWorkaroundsUtils { - private PackageInfo mPackageInfo; // May be null - private boolean mIsBrokenByRecorrection = false; + private final PackageInfo mPackageInfo; // May be null + private final boolean mIsBrokenByRecorrection; - public void setPackageInfo(final PackageInfo packageInfo) { + public AppWorkaroundsUtils(final PackageInfo packageInfo) { mPackageInfo = packageInfo; mIsBrokenByRecorrection = AppWorkaroundsHelper.evaluateIsBrokenByRecorrection( packageInfo); diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 80f61b695..291cc8d96 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -22,8 +22,8 @@ import android.os.SystemClock; import android.util.Log; import android.view.MotionEvent; -import com.android.inputmethod.accessibility.AccessibilityUtils; import com.android.inputmethod.keyboard.internal.BogusMoveEventDetector; +import com.android.inputmethod.keyboard.internal.GestureEnabler; import com.android.inputmethod.keyboard.internal.GestureStroke; import com.android.inputmethod.keyboard.internal.GestureStroke.GestureStrokeParams; import com.android.inputmethod.keyboard.internal.GestureStrokeWithPreviewPoints; @@ -50,12 +50,6 @@ public final class PointerTracker implements PointerTrackerQueue.Element { private static final boolean DEBUG_LISTENER = false; private static boolean DEBUG_MODE = LatinImeLogger.sDBG || DEBUG_EVENT; - /** True if {@link PointerTracker}s should handle gesture events. */ - private static boolean sShouldHandleGesture = false; - private static boolean sMainDictionaryAvailable = false; - private static boolean sGestureHandlingEnabledByInputField = false; - private static boolean sGestureHandlingEnabledByUser = false; - public interface DrawingProxy { public void invalidateKey(Key key); public void showKeyPreview(Key key); @@ -137,6 +131,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } } + private static GestureEnabler sGestureEnabler = new GestureEnabler(); + // Parameters for pointer handling. private static PointerTrackerParams sParams; private static GestureStrokeParams sGestureStrokeParams; @@ -229,22 +225,13 @@ public final class PointerTracker implements PointerTrackerQueue.Element { sDrawingProxy = drawingProxy; } - private static void updateGestureHandlingMode() { - sShouldHandleGesture = sMainDictionaryAvailable - && sGestureHandlingEnabledByInputField - && sGestureHandlingEnabledByUser - && !AccessibilityUtils.getInstance().isTouchExplorationEnabled(); - } - // Note that this method is called from a non-UI thread. public static void setMainDictionaryAvailability(final boolean mainDictionaryAvailable) { - sMainDictionaryAvailable = mainDictionaryAvailable; - updateGestureHandlingMode(); + sGestureEnabler.setMainDictionaryAvailability(mainDictionaryAvailable); } public static void setGestureHandlingEnabledByUser(final boolean gestureHandlingEnabledByUser) { - sGestureHandlingEnabledByUser = gestureHandlingEnabledByUser; - updateGestureHandlingMode(); + sGestureEnabler.setGestureHandlingEnabledByUser(gestureHandlingEnabledByUser); } public static PointerTracker getPointerTracker(final int id) { @@ -278,8 +265,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { tracker.setKeyDetectorInner(keyDetector); } final Keyboard keyboard = keyDetector.getKeyboard(); - sGestureHandlingEnabledByInputField = !keyboard.mId.passwordInput(); - updateGestureHandlingMode(); + sGestureEnabler.setPasswordMode(keyboard.mId.passwordInput()); } public static void setReleasedKeyGraphicsToAllKeys() { @@ -484,7 +470,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } private static boolean needsToSuppressKeyPreviewPopup(final long eventTime) { - if (!sShouldHandleGesture) return false; + if (!sGestureEnabler.shouldHandleGesture()) return false; return sTypingTimeRecorder.needsToSuppressKeyPreviewPopup(eventTime); } @@ -761,7 +747,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } sPointerTrackerQueue.add(this); onDownEventInternal(x, y, eventTime); - if (!sShouldHandleGesture) { + if (!sGestureEnabler.shouldHandleGesture()) { return; } // A gesture should start only from a non-modifier key. Note that the gesture detection is @@ -862,7 +848,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { return; } - if (sShouldHandleGesture && me != null) { + if (sGestureEnabler.shouldHandleGesture() && me != null) { // Add historical points to gesture path. final int pointerIndex = me.findPointerIndex(mPointerId); final int historicalSize = me.getHistorySize(); @@ -1014,7 +1000,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { final Key oldKey = mCurrentKey; final Key newKey = onMoveKey(x, y); - if (sShouldHandleGesture) { + if (sGestureEnabler.shouldHandleGesture()) { // Register move event on gesture tracker. onGestureMoveEvent(x, y, eventTime, true /* isMajorEvent */, newKey); if (sInGesture) { diff --git a/java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java b/java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java index 5a996ff53..2e80f7962 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java @@ -87,7 +87,7 @@ public final class EmojiPageKeyboardView extends KeyboardView implements return true; } - // {@link GestureDetector#OnGestureListener} methods. + // {@link GestureEnabler#OnGestureListener} methods. private Key mCurrentKey; private Key getKey(final MotionEvent e) { diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureEnabler.java b/java/src/com/android/inputmethod/keyboard/internal/GestureEnabler.java new file mode 100644 index 000000000..7d14ae924 --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/internal/GestureEnabler.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2013 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.keyboard.internal; + +import com.android.inputmethod.accessibility.AccessibilityUtils; + +public final class GestureEnabler { + /** True if we should handle gesture events. */ + private boolean mShouldHandleGesture; + private boolean mMainDictionaryAvailable; + private boolean mGestureHandlingEnabledByInputField; + private boolean mGestureHandlingEnabledByUser; + + private void updateGestureHandlingMode() { + mShouldHandleGesture = mMainDictionaryAvailable + && mGestureHandlingEnabledByInputField + && mGestureHandlingEnabledByUser + && !AccessibilityUtils.getInstance().isTouchExplorationEnabled(); + } + + // Note that this method is called from a non-UI thread. + public void setMainDictionaryAvailability(final boolean mainDictionaryAvailable) { + mMainDictionaryAvailable = mainDictionaryAvailable; + updateGestureHandlingMode(); + } + + public void setGestureHandlingEnabledByUser(final boolean gestureHandlingEnabledByUser) { + mGestureHandlingEnabledByUser = gestureHandlingEnabledByUser; + updateGestureHandlingMode(); + } + + public void setPasswordMode(final boolean passwordMode) { + mGestureHandlingEnabledByInputField = !passwordMode; + updateGestureHandlingMode(); + } + + public boolean shouldHandleGesture() { + return mShouldHandleGesture; + } +} diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java index fcf043031..b01bc4ba5 100644 --- a/java/src/com/android/inputmethod/latin/InputAttributes.java +++ b/java/src/com/android/inputmethod/latin/InputAttributes.java @@ -29,6 +29,7 @@ import com.android.inputmethod.latin.utils.StringUtils; public final class InputAttributes { private final String TAG = InputAttributes.class.getSimpleName(); + final public String mTargetApplicationPackageName; final public boolean mInputTypeNoAutoCorrect; final public boolean mIsSettingsSuggestionStripOn; final public boolean mApplicationSpecifiedCompletionOn; @@ -36,6 +37,7 @@ public final class InputAttributes { final private int mInputType; public InputAttributes(final EditorInfo editorInfo, final boolean isFullscreenMode) { + mTargetApplicationPackageName = null != editorInfo ? editorInfo.packageName : null; final int inputType = null != editorInfo ? editorInfo.inputType : 0; final int inputClass = inputType & InputType.TYPE_MASK_CLASS; mInputType = inputType; diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index a941dc3f4..f8909e86a 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -28,7 +28,6 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; -import android.content.pm.PackageInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Rect; @@ -61,7 +60,6 @@ import android.view.inputmethod.InputMethodSubtype; import com.android.inputmethod.accessibility.AccessibilityUtils; import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy; import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.compat.AppWorkaroundsUtils; import com.android.inputmethod.compat.InputMethodServiceCompatUtils; import com.android.inputmethod.dictionarypack.DictionaryPackConstants; import com.android.inputmethod.keyboard.Keyboard; @@ -89,7 +87,6 @@ import com.android.inputmethod.latin.utils.IntentUtils; import com.android.inputmethod.latin.utils.JniUtils; import com.android.inputmethod.latin.utils.LatinImeLoggerUtils; import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper; -import com.android.inputmethod.latin.utils.TargetPackageInfoGetterTask; import com.android.inputmethod.latin.utils.TextRange; import com.android.inputmethod.research.ResearchLogger; @@ -102,8 +99,7 @@ import java.util.Locale; * Input method implementation for Qwerty'ish keyboard. */ public class LatinIME extends InputMethodService implements KeyboardActionListener, - SuggestionStripView.Listener, TargetPackageInfoGetterTask.OnTargetPackageInfoKnownListener, - Suggest.SuggestInitializationListener { + SuggestionStripView.Listener, Suggest.SuggestInitializationListener { private static final String TAG = LatinIME.class.getSimpleName(); private static final boolean TRACE = false; private static boolean DEBUG = false; @@ -128,8 +124,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen private SuggestionStripView mSuggestionStripView; private CompletionInfo[] mApplicationSpecifiedCompletions; - // TODO[IL]: Make this an AsyncResultHolder or a Future in SettingsValues - public AppWorkaroundsUtils mAppWorkAroundsUtils = new AppWorkaroundsUtils(); private RichInputMethodManager mRichImm; @UsedForTesting final KeyboardSwitcher mKeyboardSwitcher; @@ -519,9 +513,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen @UsedForTesting void loadSettings() { final Locale locale = mSubtypeSwitcher.getCurrentSubtypeLocale(); - final InputAttributes inputAttributes = - new InputAttributes(getCurrentInputEditorInfo(), isFullscreenMode()); - mSettings.loadSettings(locale, inputAttributes); + final EditorInfo editorInfo = getCurrentInputEditorInfo(); + final InputAttributes inputAttributes = new InputAttributes(editorInfo, isFullscreenMode()); + mSettings.loadSettings(this, locale, inputAttributes); AudioAndHapticFeedbackManager.getInstance().onSettingsChanged(mSettings.getCurrent()); // To load the keyboard we need to load all the settings once, but resetting the // contacts dictionary should be deferred until after the new layout has been displayed @@ -798,13 +792,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (isDifferentTextField) { mainKeyboardView.closing(); loadSettings(); - final PackageInfo packageInfo = - TargetPackageInfoGetterTask.getCachedPackageInfo(editorInfo.packageName); - mAppWorkAroundsUtils.setPackageInfo(packageInfo); - if (null == packageInfo) { - new TargetPackageInfoGetterTask(this /* context */, this /* listener */) - .execute(editorInfo.packageName); - } currentSettingsValues = mSettings.getCurrent(); if (suggest != null && currentSettingsValues.mCorrectionEnabled) { @@ -912,12 +899,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } } - // Callback for the TargetPackageInfoGetterTask - @Override - public void onTargetPackageInfoKnown(final PackageInfo info) { - mAppWorkAroundsUtils.setPackageInfo(info); - } - @Override public void onWindowHidden() { super.onWindowHidden(); @@ -1321,35 +1302,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } // Called from PointerTracker through the KeyboardActionListener interface - // TODO[IL]: Move this to InputLogic @Override public void onTextInput(final String rawText) { - mInputLogic.mConnection.beginBatchEdit(); - if (mInputLogic.mWordComposer.isComposingWord()) { - mInputLogic.commitCurrentAutoCorrection(mSettings.getCurrent(), rawText, mHandler); - } else { - mInputLogic.resetComposingState(true /* alsoResetLastComposedWord */); - } - mHandler.postUpdateSuggestionStrip(); - if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS - && ResearchLogger.RESEARCH_KEY_OUTPUT_TEXT.equals(rawText)) { - ResearchLogger.getInstance().onResearchKeySelected(this); - return; - } - final String text = specificTldProcessingOnTextInput(rawText); - if (SpaceState.PHANTOM == mInputLogic.mSpaceState) { - mInputLogic.promotePhantomSpace(mSettings.getCurrent()); - } - mInputLogic.mConnection.commitText(text, 1); - if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { - ResearchLogger.latinIME_onTextInput(text, false /* isBatchMode */); - } - mInputLogic.mConnection.endBatchEdit(); - // Space state must be updated before calling updateShiftState - mInputLogic.mSpaceState = SpaceState.NONE; - mKeyboardSwitcher.updateShiftState(); - mKeyboardSwitcher.onCodeInput(Constants.CODE_OUTPUT_TEXT); - mInputLogic.mEnteredText = text; + mInputLogic.onTextInput(mSettings.getCurrent(), rawText, mKeyboardSwitcher, mHandler); } @Override @@ -1633,25 +1588,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mInputUpdater.onEndBatchInput(batchPointers); } - private String specificTldProcessingOnTextInput(final String text) { - if (text.length() <= 1 || text.charAt(0) != Constants.CODE_PERIOD - || !Character.isLetter(text.charAt(1))) { - // Not a tld: do nothing. - return text; - } - // We have a TLD (or something that looks like this): make sure we don't add - // a space even if currently in phantom mode. - mInputLogic.mSpaceState = SpaceState.NONE; - // TODO: use getCodePointBeforeCursor instead to improve performance and simplify the code - final CharSequence lastOne = mInputLogic.mConnection.getTextBeforeCursor(1, 0); - if (lastOne != null && lastOne.length() == 1 - && lastOne.charAt(0) == Constants.CODE_PERIOD) { - return text.substring(1); - } else { - return text; - } - } - // Called from PointerTracker through the KeyboardActionListener interface @Override public void onFinishSlidingInput() { @@ -1991,12 +1927,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // HACK: We may want to special-case some apps that exhibit bad behavior in case of // recorrection. This is a temporary, stopgap measure that will be removed later. // TODO: remove this. - if (mAppWorkAroundsUtils.isBrokenByRecorrection()) return; + final SettingsValues settingsValues = mSettings.getCurrent(); + if (settingsValues.isBrokenByRecorrection()) return; // A simple way to test for support from the TextView. if (!isSuggestionsStripVisible()) return; // Recorrection is not supported in languages without spaces because we don't know // how to segment them yet. - if (!mSettings.getCurrent().mCurrentLanguageHasSpaces) return; + if (!settingsValues.mCurrentLanguageHasSpaces) return; // If the cursor is not touching a word, or if there is a selection, return right away. if (mInputLogic.mLastSelectionStart != mInputLogic.mLastSelectionEnd) return; // If we don't know the cursor location, return. @@ -2322,8 +2259,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } public void debugDumpStateAndCrashWithException(final String context) { - final StringBuilder s = new StringBuilder(mAppWorkAroundsUtils.toString()); - s.append("\nAttributes : ").append(mSettings.getCurrent().mInputAttributes) + final SettingsValues settingsValues = mSettings.getCurrent(); + final StringBuilder s = new StringBuilder(settingsValues.toString()); + s.append("\nAttributes : ").append(settingsValues.mInputAttributes) .append("\nContext : ").append(context); throw new RuntimeException(s.toString()); } @@ -2348,5 +2286,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen p.println(" mVibrateOn=" + settingsValues.mVibrateOn); p.println(" mKeyPreviewPopupOn=" + settingsValues.mKeyPreviewPopupOn); p.println(" inputAttributes=" + settingsValues.mInputAttributes); + // TODO: Dump all settings values } } diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index db27d22b7..b9c96555b 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -121,6 +121,46 @@ public final class InputLogic { } /** + * React to a string input. + * + * This is triggered by keys that input many characters at once, like the ".com" key or + * some additional keys for example. + * + * @param settingsValues the current values of the settings. + * @param rawText the text to input. + */ + public void onTextInput(final SettingsValues settingsValues, final String rawText, + // TODO: remove these arguments + final KeyboardSwitcher keyboardSwitcher, final LatinIME.UIHandler handler) { + mConnection.beginBatchEdit(); + if (mWordComposer.isComposingWord()) { + commitCurrentAutoCorrection(settingsValues, rawText, handler); + } else { + resetComposingState(true /* alsoResetLastComposedWord */); + } + handler.postUpdateSuggestionStrip(); + if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS + && ResearchLogger.RESEARCH_KEY_OUTPUT_TEXT.equals(rawText)) { + ResearchLogger.getInstance().onResearchKeySelected(mLatinIME); + return; + } + final String text = performSpecificTldProcessingOnTextInput(rawText); + if (SpaceState.PHANTOM == mSpaceState) { + promotePhantomSpace(settingsValues); + } + mConnection.commitText(text, 1); + if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { + ResearchLogger.latinIME_onTextInput(text, false /* isBatchMode */); + } + mConnection.endBatchEdit(); + // Space state must be updated before calling updateShiftState + mSpaceState = SpaceState.NONE; + keyboardSwitcher.updateShiftState(); + keyboardSwitcher.onCodeInput(Constants.CODE_OUTPUT_TEXT); + mEnteredText = text; + } + + /** * React to a code input. It may be a code point to insert, or a symbolic value that influences * the keyboard behavior. * @@ -387,7 +427,7 @@ public final class InputLogic { final boolean swapWeakSpace = maybeStripSpace(settingsValues, codePoint, spaceState, Constants.SUGGESTION_STRIP_COORDINATE == x); - sendKeyCodePoint(codePoint); + sendKeyCodePoint(settingsValues, codePoint); if (swapWeakSpace) { swapSwapperAndSpace(keyboardSwitcher); @@ -449,7 +489,7 @@ public final class InputLogic { } if (!shouldAvoidSendingCode) { - sendKeyCodePoint(codePoint); + sendKeyCodePoint(settingsValues, codePoint); } if (Constants.CODE_SPACE == codePoint) { @@ -593,7 +633,7 @@ public final class InputLogic { // This should never happen. Log.e(TAG, "Backspace when we don't know the selection position"); } - if (mLatinIME.mAppWorkAroundsUtils.isBeforeJellyBean() || + if (settingsValues.isBeforeJellyBean() || settingsValues.mInputAttributes.isTypeNull()) { // There are two possible reasons to send a key event: either the field has // type TYPE_NULL, in which case the keyboard should send events, or we are @@ -1070,6 +1110,37 @@ public final class InputLogic { } /** + * Perform the processing specific to inputting TLDs. + * + * Some keys input a TLD (specifically, the ".com" key) and this warrants some specific + * processing. First, if this is a TLD, we ignore PHANTOM spaces -- this is done by type + * of character in onCodeInput, but since this gets inputted as a whole string we need to + * do it here specifically. Then, if the last character before the cursor is a period, then + * we cut the dot at the start of ".com". This is because humans tend to type "www.google." + * and then press the ".com" key and instinctively don't expect to get "www.google..com". + * + * @param text the raw text supplied to onTextInput + * @return the text to actually send to the editor + */ + private String performSpecificTldProcessingOnTextInput(final String text) { + if (text.length() <= 1 || text.charAt(0) != Constants.CODE_PERIOD + || !Character.isLetter(text.charAt(1))) { + // Not a tld: do nothing. + return text; + } + // We have a TLD (or something that looks like this): make sure we don't add + // a space even if currently in phantom mode. + mSpaceState = SpaceState.NONE; + final int codePointBeforeCursor = mConnection.getCodePointBeforeCursor(); + // If no code point, #getCodePointBeforeCursor returns NOT_A_CODE_POINT. + if (Constants.CODE_PERIOD == codePointBeforeCursor) { + return text.substring(1); + } else { + return text; + } + } + + /** * Handle a press on the settings key. */ private void onSettingsKeyPressed() { @@ -1167,9 +1238,10 @@ public final class InputLogic { * Normally we send code points with commitText, but there are some cases (where backward * compatibility is a concern for example) where we want to use deprecated methods. * + * @param settingsValues the current values of the settings. * @param codePoint the code point to send. */ - private void sendKeyCodePoint(final int codePoint) { + private void sendKeyCodePoint(final SettingsValues settingsValues, final int codePoint) { if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { ResearchLogger.latinIME_sendKeyCodePoint(codePoint); } @@ -1181,8 +1253,7 @@ public final class InputLogic { } // TODO: we should do this also when the editor has TYPE_NULL - if (Constants.CODE_ENTER == codePoint - && mLatinIME.mAppWorkAroundsUtils.isBeforeJellyBean()) { + if (Constants.CODE_ENTER == codePoint && settingsValues.isBeforeJellyBean()) { // Backward compatibility mode. Before Jelly bean, the keyboard would simulate // a hardware keyboard event on pressing enter or delete. This is bad for many // reasons (there are race conditions with commits) but some applications are @@ -1209,7 +1280,7 @@ public final class InputLogic { if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { ResearchLogger.latinIME_promotePhantomSpace(); } - sendKeyCodePoint(Constants.CODE_SPACE); + sendKeyCodePoint(settingsValues, Constants.CODE_SPACE); } } diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java index 94f145813..9bd2b9389 100644 --- a/java/src/com/android/inputmethod/latin/settings/Settings.java +++ b/java/src/com/android/inputmethod/latin/settings/Settings.java @@ -101,6 +101,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang public static final String PREF_EMOJI_CATEGORY_LAST_TYPED_ID = "emoji_category_last_typed_id"; public static final String PREF_LAST_SHOWN_EMOJI_CATEGORY_ID = "last_shown_emoji_category_id"; + private Context mContext; private Resources mRes; private SharedPreferences mPrefs; private SettingsValues mSettingsValues; @@ -121,6 +122,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang } private void onCreate(final Context context) { + mContext = context; mRes = context.getResources(); mPrefs = PreferenceManager.getDefaultSharedPreferences(context); mPrefs.registerOnSharedPreferenceChangeListener(this); @@ -140,20 +142,22 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang Log.w(TAG, "onSharedPreferenceChanged called before loadSettings."); return; } - loadSettings(mSettingsValues.mLocale, mSettingsValues.mInputAttributes); + loadSettings(mContext, mSettingsValues.mLocale, mSettingsValues.mInputAttributes); } finally { mSettingsValuesLock.unlock(); } } - public void loadSettings(final Locale locale, final InputAttributes inputAttributes) { + public void loadSettings(final Context context, final Locale locale, + final InputAttributes inputAttributes) { mSettingsValuesLock.lock(); + mContext = context; try { final SharedPreferences prefs = mPrefs; final RunInLocale<SettingsValues> job = new RunInLocale<SettingsValues>() { @Override protected SettingsValues job(final Resources res) { - return new SettingsValues(prefs, locale, res, inputAttributes); + return new SettingsValues(context, prefs, locale, res, inputAttributes); } }; mSettingsValues = job.runInLocale(mRes, locale); diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java index d98e547fc..f97e9e1fc 100644 --- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java @@ -16,13 +16,16 @@ package com.android.inputmethod.latin.settings; +import android.content.Context; import android.content.SharedPreferences; +import android.content.pm.PackageInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.util.Log; import android.view.inputmethod.EditorInfo; import com.android.inputmethod.annotations.UsedForTesting; +import com.android.inputmethod.compat.AppWorkaroundsUtils; import com.android.inputmethod.keyboard.internal.KeySpecParser; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Dictionary; @@ -31,8 +34,10 @@ import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.RichInputMethodManager; import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.latin.utils.AsyncResultHolder; import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.StringUtils; +import com.android.inputmethod.latin.utils.TargetPackageInfoGetterTask; import java.util.ArrayList; import java.util.Arrays; @@ -48,6 +53,7 @@ public final class SettingsValues { // Float.NEGATIVE_INFINITE and Float.MAX_VALUE. Currently used for auto-correction settings. private static final String FLOAT_MAX_VALUE_MARKER_STRING = "floatMaxValue"; private static final String FLOAT_NEGATIVE_INFINITY_MARKER_STRING = "floatNegativeInfinity"; + private static final int TIMEOUT_TO_GET_TARGET_PACKAGE = 5; // seconds // From resources: public final int mDelayUpdateOldSuggestions; @@ -95,6 +101,7 @@ public final class SettingsValues { public final int mSuggestionVisibility; public final boolean mBoostPersonalizationDictionaryForDebug; public final boolean mUseOnlyPersonalizationDictionaryForDebug; + private final AsyncResultHolder<AppWorkaroundsUtils> mAppWorkarounds; // Setting values for additional features public final int[] mAdditionalFeaturesSettingValues = @@ -103,8 +110,8 @@ public final class SettingsValues { // Debug settings public final boolean mIsInternal; - public SettingsValues(final SharedPreferences prefs, final Locale locale, final Resources res, - final InputAttributes inputAttributes) { + public SettingsValues(final Context context, final SharedPreferences prefs, final Locale locale, + final Resources res, final InputAttributes inputAttributes) { mLocale = locale; // Get the resources mDelayUpdateOldSuggestions = res.getInteger(R.integer.config_delay_update_old_suggestions); @@ -177,6 +184,15 @@ public final class SettingsValues { Settings.readBoostPersonalizationDictionaryForDebug(prefs); mUseOnlyPersonalizationDictionaryForDebug = Settings.readUseOnlyPersonalizationDictionaryForDebug(prefs); + mAppWorkarounds = new AsyncResultHolder<AppWorkaroundsUtils>(); + final PackageInfo packageInfo = TargetPackageInfoGetterTask.getCachedPackageInfo( + mInputAttributes.mTargetApplicationPackageName); + if (null != packageInfo) { + mAppWorkarounds.set(new AppWorkaroundsUtils(packageInfo)); + } else { + new TargetPackageInfoGetterTask(context, mAppWorkarounds) + .execute(mInputAttributes.mTargetApplicationPackageName); + } } // Only for tests @@ -225,6 +241,8 @@ public final class SettingsValues { mIsInternal = false; mBoostPersonalizationDictionaryForDebug = false; mUseOnlyPersonalizationDictionaryForDebug = false; + mAppWorkarounds = new AsyncResultHolder<AppWorkaroundsUtils>(); + mAppWorkarounds.set(null); } @UsedForTesting @@ -288,6 +306,14 @@ public final class SettingsValues { return mInputAttributes.isSameInputType(editorInfo); } + public boolean isBeforeJellyBean() { + return mAppWorkarounds.get(null, TIMEOUT_TO_GET_TARGET_PACKAGE).isBeforeJellyBean(); + } + + public boolean isBrokenByRecorrection() { + return mAppWorkarounds.get(null, TIMEOUT_TO_GET_TARGET_PACKAGE).isBrokenByRecorrection(); + } + // Helper functions to create member values. private static SuggestedWords createSuggestPuncList(final String[] puncs) { final ArrayList<SuggestedWordInfo> puncList = CollectionUtils.newArrayList(); diff --git a/java/src/com/android/inputmethod/latin/utils/TargetPackageInfoGetterTask.java b/java/src/com/android/inputmethod/latin/utils/TargetPackageInfoGetterTask.java index afbe2ecad..42ea3c959 100644 --- a/java/src/com/android/inputmethod/latin/utils/TargetPackageInfoGetterTask.java +++ b/java/src/com/android/inputmethod/latin/utils/TargetPackageInfoGetterTask.java @@ -22,6 +22,8 @@ import android.content.pm.PackageManager; import android.os.AsyncTask; import android.util.LruCache; +import com.android.inputmethod.compat.AppWorkaroundsUtils; + public final class TargetPackageInfoGetterTask extends AsyncTask<String, Void, PackageInfo> { private static final int MAX_CACHE_ENTRIES = 64; // arbitrary @@ -37,17 +39,13 @@ public final class TargetPackageInfoGetterTask extends sCache.remove(packageName); } - public interface OnTargetPackageInfoKnownListener { - public void onTargetPackageInfoKnown(final PackageInfo info); - } - private Context mContext; - private final OnTargetPackageInfoKnownListener mListener; + private final AsyncResultHolder<AppWorkaroundsUtils> mResult; public TargetPackageInfoGetterTask(final Context context, - final OnTargetPackageInfoKnownListener listener) { + final AsyncResultHolder<AppWorkaroundsUtils> result) { mContext = context; - mListener = listener; + mResult = result; } @Override @@ -65,6 +63,6 @@ public final class TargetPackageInfoGetterTask extends @Override protected void onPostExecute(final PackageInfo info) { - mListener.onTargetPackageInfoKnown(info); + mResult.set(new AppWorkaroundsUtils(info)); } } |