aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin/LatinIME.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin/LatinIME.java')
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java616
1 files changed, 295 insertions, 321 deletions
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index d57db8e9a..330be377b 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -16,9 +16,9 @@
package com.android.inputmethod.latin;
-import static com.android.inputmethod.latin.Constants.ImeOption.FORCE_ASCII;
-import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE;
-import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE_COMPAT;
+import static com.android.inputmethod.latin.common.Constants.ImeOption.FORCE_ASCII;
+import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE;
+import static com.android.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE_COMPAT;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
@@ -31,13 +31,11 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.inputmethodservice.InputMethodService;
import android.media.AudioManager;
-import android.net.ConnectivityManager;
import android.os.Debug;
import android.os.IBinder;
import android.os.Message;
import android.preference.PreferenceManager;
import android.text.InputType;
-import android.text.TextUtils;
import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Printer;
@@ -46,19 +44,17 @@ import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
-import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.CompletionInfo;
-import android.view.inputmethod.CursorAnchorInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodSubtype;
-import android.widget.TextView;
import com.android.inputmethod.accessibility.AccessibilityUtils;
import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.compat.CursorAnchorInfoCompatWrapper;
import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
+import com.android.inputmethod.compat.ViewOutlineProviderCompatUtils;
+import com.android.inputmethod.compat.ViewOutlineProviderCompatUtils.InsetsUpdater;
import com.android.inputmethod.dictionarypack.DictionaryPackConstants;
import com.android.inputmethod.event.Event;
import com.android.inputmethod.event.HardwareEventDecoder;
@@ -69,32 +65,29 @@ import com.android.inputmethod.keyboard.KeyboardActionListener;
import com.android.inputmethod.keyboard.KeyboardId;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.MainKeyboardView;
-import com.android.inputmethod.keyboard.TextDecoratorUi;
import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.common.Constants;
+import com.android.inputmethod.latin.common.CoordinateUtils;
+import com.android.inputmethod.latin.common.InputPointers;
import com.android.inputmethod.latin.define.DebugFlags;
import com.android.inputmethod.latin.define.ProductionFlags;
import com.android.inputmethod.latin.inputlogic.InputLogic;
-import com.android.inputmethod.latin.personalization.ContextualDictionaryUpdater;
-import com.android.inputmethod.latin.personalization.DictionaryDecayBroadcastReciever;
-import com.android.inputmethod.latin.personalization.PersonalizationDictionaryUpdater;
import com.android.inputmethod.latin.personalization.PersonalizationHelper;
import com.android.inputmethod.latin.settings.Settings;
import com.android.inputmethod.latin.settings.SettingsActivity;
import com.android.inputmethod.latin.settings.SettingsValues;
import com.android.inputmethod.latin.suggestions.SuggestionStripView;
import com.android.inputmethod.latin.suggestions.SuggestionStripViewAccessor;
+import com.android.inputmethod.latin.touchinputconsumer.GestureConsumer;
import com.android.inputmethod.latin.utils.ApplicationUtils;
-import com.android.inputmethod.latin.utils.CapsModeUtils;
-import com.android.inputmethod.latin.utils.CoordinateUtils;
-import com.android.inputmethod.latin.utils.CursorAnchorInfoUtils;
import com.android.inputmethod.latin.utils.DialogUtils;
-import com.android.inputmethod.latin.utils.DistracterFilterCheckingExactMatchesAndSuggestions;
import com.android.inputmethod.latin.utils.ImportantNoticeUtils;
import com.android.inputmethod.latin.utils.IntentUtils;
import com.android.inputmethod.latin.utils.JniUtils;
import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper;
import com.android.inputmethod.latin.utils.StatsUtils;
+import com.android.inputmethod.latin.utils.StatsUtilsManager;
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
import com.android.inputmethod.latin.utils.ViewLayoutUtils;
@@ -105,6 +98,8 @@ import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
+import javax.annotation.Nonnull;
+
/**
* Input method implementation for Qwerty'ish keyboard.
*/
@@ -112,17 +107,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
SuggestionStripView.Listener, SuggestionStripViewAccessor,
DictionaryFacilitator.DictionaryInitializationListener,
ImportantNoticeDialog.ImportantNoticeDialogListener {
- private static final String TAG = LatinIME.class.getSimpleName();
+ static final String TAG = LatinIME.class.getSimpleName();
private static final boolean TRACE = false;
- private static boolean DEBUG = false;
private static final int EXTENDED_TOUCHABLE_REGION_HEIGHT = 100;
-
- private static final int PENDING_IMS_CALLBACK_DURATION = 800;
-
- private static final int DELAY_WAIT_FOR_DICTIONARY_LOAD = 2000; // 2s
-
private static final int PERIOD_FOR_AUDIO_AND_HAPTIC_FEEDBACK_IN_KEY_REPEAT = 2;
+ private static final int PENDING_IMS_CALLBACK_DURATION_MILLIS = 800;
+ static final long DELAY_WAIT_FOR_DICTIONARY_LOAD_MILLIS = TimeUnit.SECONDS.toMillis(2);
+ static final long DELAY_DEALLOCATE_MEMORY_MILLIS = TimeUnit.SECONDS.toMillis(10);
/**
* The name of the scheme used by the Package Manager to warn of a new package installation,
@@ -130,22 +122,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
*/
private static final String SCHEME_PACKAGE = "package";
- private final Settings mSettings;
+ final Settings mSettings;
private final DictionaryFacilitator mDictionaryFacilitator =
- new DictionaryFacilitator(
- new DistracterFilterCheckingExactMatchesAndSuggestions(this /* context */));
- // TODO: Move from LatinIME.
- private final PersonalizationDictionaryUpdater mPersonalizationDictionaryUpdater =
- new PersonalizationDictionaryUpdater(this /* context */, mDictionaryFacilitator);
- private final ContextualDictionaryUpdater mContextualDictionaryUpdater =
- new ContextualDictionaryUpdater(this /* context */, mDictionaryFacilitator,
- new Runnable() {
- @Override
- public void run() {
- mHandler.postUpdateSuggestionStrip(SuggestedWords.INPUT_STYLE_NONE);
- }
- });
- private final InputLogic mInputLogic = new InputLogic(this /* LatinIME */,
+ DictionaryFacilitatorProvider.getDictionaryFacilitator(
+ false /* isNeededForSpellChecking */);
+ final InputLogic mInputLogic = new InputLogic(this /* LatinIME */,
this /* SuggestionStripViewAccessor */, mDictionaryFacilitator);
// We expect to have only one decoder in almost all cases, hence the default capacity of 1.
// If it turns out we need several, it will get grown seamlessly.
@@ -153,14 +134,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// TODO: Move these {@link View}s to {@link KeyboardSwitcher}.
private View mInputView;
+ private InsetsUpdater mInsetsUpdater;
private SuggestionStripView mSuggestionStripView;
- private TextView mExtractEditText;
private RichInputMethodManager mRichImm;
@UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
- private final SubtypeSwitcher mSubtypeSwitcher;
private final SubtypeState mSubtypeState = new SubtypeState();
- private final SpecialKeyDetector mSpecialKeyDetector;
+ private final EmojiAltPhysicalKeyDetector mEmojiAltPhysicalKeyDetector =
+ new EmojiAltPhysicalKeyDetector(mInputLogic.mConnection);
+ private StatsUtilsManager mStatsUtilsManager;
// Working variable for {@link #startShowingInputView()} and
// {@link #onEvaluateInputViewShown()}.
private boolean mIsExecutingStartShowingInputView;
@@ -176,6 +158,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private final boolean mIsHardwareAcceleratedDrawingEnabled;
+ private GestureConsumer mGestureConsumer = GestureConsumer.NULL_GESTURE_CONSUMER;
+
public final UIHandler mHandler = new UIHandler(this);
public static final class UIHandler extends LeakGuardHandlerWrapper<LatinIME> {
@@ -188,20 +172,21 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private static final int MSG_UPDATE_TAIL_BATCH_INPUT_COMPLETED = 6;
private static final int MSG_RESET_CACHES = 7;
private static final int MSG_WAIT_FOR_DICTIONARY_LOAD = 8;
+ private static final int MSG_DEALLOCATE_MEMORY = 9;
+ private static final int MSG_RESUME_SUGGESTIONS_FOR_START_INPUT = 10;
// Update this when adding new messages
- private static final int MSG_LAST = MSG_WAIT_FOR_DICTIONARY_LOAD;
+ private static final int MSG_LAST = MSG_RESUME_SUGGESTIONS_FOR_START_INPUT;
private static final int ARG1_NOT_GESTURE_INPUT = 0;
private static final int ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1;
private static final int ARG1_SHOW_GESTURE_FLOATING_PREVIEW_TEXT = 2;
private static final int ARG2_UNUSED = 0;
- private static final int ARG1_FALSE = 0;
private static final int ARG1_TRUE = 1;
private int mDelayInMillisecondsToUpdateSuggestions;
private int mDelayInMillisecondsToUpdateShiftState;
- public UIHandler(final LatinIME ownerInstance) {
+ public UIHandler(@Nonnull final LatinIME ownerInstance) {
super(ownerInstance);
}
@@ -245,20 +230,26 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
break;
case MSG_RESUME_SUGGESTIONS:
latinIme.mInputLogic.restartSuggestionsOnWordTouchedByCursor(
- latinIme.mSettings.getCurrent(),
- msg.arg1 == ARG1_TRUE /* shouldIncludeResumedWordInSuggestions */,
+ latinIme.mSettings.getCurrent(), false /* forStartInput */,
+ latinIme.mKeyboardSwitcher.getCurrentKeyboardScriptId());
+ break;
+ case MSG_RESUME_SUGGESTIONS_FOR_START_INPUT:
+ latinIme.mInputLogic.restartSuggestionsOnWordTouchedByCursor(
+ latinIme.mSettings.getCurrent(), true /* forStartInput */,
latinIme.mKeyboardSwitcher.getCurrentKeyboardScriptId());
break;
case MSG_REOPEN_DICTIONARIES:
// We need to re-evaluate the currently composing word in case the script has
// changed.
postWaitForDictionaryLoad();
- latinIme.resetSuggest();
+ latinIme.resetDictionaryFacilitatorIfNecessary();
break;
case MSG_UPDATE_TAIL_BATCH_INPUT_COMPLETED:
+ final SuggestedWords suggestedWords = (SuggestedWords) msg.obj;
latinIme.mInputLogic.onUpdateTailBatchInputCompleted(
latinIme.mSettings.getCurrent(),
- (SuggestedWords) msg.obj, latinIme.mKeyboardSwitcher);
+ suggestedWords, latinIme.mKeyboardSwitcher);
+ latinIme.onTailBatchInputResultShown(suggestedWords);
break;
case MSG_RESET_CACHES:
final SettingsValues settingsValues = latinIme.mSettings.getCurrent();
@@ -275,6 +266,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
case MSG_WAIT_FOR_DICTIONARY_LOAD:
Log.i(TAG, "Timeout waiting for dictionary load");
break;
+ case MSG_DEALLOCATE_MEMORY:
+ latinIme.deallocateMemory();
+ break;
}
}
@@ -287,8 +281,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
sendMessage(obtainMessage(MSG_REOPEN_DICTIONARIES));
}
- public void postResumeSuggestions(final boolean shouldIncludeResumedWordInSuggestions,
- final boolean shouldDelay) {
+ private void postResumeSuggestionsInternal(final boolean shouldDelay,
+ final boolean forStartInput) {
final LatinIME latinIme = getOwnerInstance();
if (latinIme == null) {
return;
@@ -297,17 +291,25 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return;
}
removeMessages(MSG_RESUME_SUGGESTIONS);
+ removeMessages(MSG_RESUME_SUGGESTIONS_FOR_START_INPUT);
+ final int message = forStartInput ? MSG_RESUME_SUGGESTIONS_FOR_START_INPUT
+ : MSG_RESUME_SUGGESTIONS;
if (shouldDelay) {
- sendMessageDelayed(obtainMessage(MSG_RESUME_SUGGESTIONS,
- shouldIncludeResumedWordInSuggestions ? ARG1_TRUE : ARG1_FALSE,
- 0 /* ignored */), mDelayInMillisecondsToUpdateSuggestions);
+ sendMessageDelayed(obtainMessage(message),
+ mDelayInMillisecondsToUpdateSuggestions);
} else {
- sendMessage(obtainMessage(MSG_RESUME_SUGGESTIONS,
- shouldIncludeResumedWordInSuggestions ? ARG1_TRUE : ARG1_FALSE,
- 0 /* ignored */));
+ sendMessage(obtainMessage(message));
}
}
+ public void postResumeSuggestions(final boolean shouldDelay) {
+ postResumeSuggestionsInternal(shouldDelay, false /* forStartInput */);
+ }
+
+ public void postResumeSuggestionsForStartInput(final boolean shouldDelay) {
+ postResumeSuggestionsInternal(shouldDelay, true /* forStartInput */);
+ }
+
public void postResetCaches(final boolean tryResumeSuggestions, final int remainingTries) {
removeMessages(MSG_RESET_CACHES);
sendMessage(obtainMessage(MSG_RESET_CACHES, tryResumeSuggestions ? 1 : 0,
@@ -316,7 +318,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public void postWaitForDictionaryLoad() {
sendMessageDelayed(obtainMessage(MSG_WAIT_FOR_DICTIONARY_LOAD),
- DELAY_WAIT_FOR_DICTIONARY_LOAD);
+ DELAY_WAIT_FOR_DICTIONARY_LOAD_MILLIS);
}
public void cancelWaitForDictionaryLoad() {
@@ -345,6 +347,19 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mDelayInMillisecondsToUpdateShiftState);
}
+ public void postDeallocateMemory() {
+ sendMessageDelayed(obtainMessage(MSG_DEALLOCATE_MEMORY),
+ DELAY_DEALLOCATE_MEMORY_MILLIS);
+ }
+
+ public void cancelDeallocateMemory() {
+ removeMessages(MSG_DEALLOCATE_MEMORY);
+ }
+
+ public boolean hasPendingDeallocateMemory() {
+ return hasMessages(MSG_DEALLOCATE_MEMORY);
+ }
+
@UsedForTesting
public void removeAllMessages() {
for (int i = 0; i <= MSG_LAST; ++i) {
@@ -442,7 +457,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mPendingSuccessiveImsCallback = false;
resetPendingImsCallback();
sendMessageDelayed(obtainMessage(MSG_PENDING_IMS_CALLBACK),
- PENDING_IMS_CALLBACK_DURATION);
+ PENDING_IMS_CALLBACK_DURATION_MILLIS);
}
final LatinIME latinIme = getOwnerInstance();
if (latinIme != null) {
@@ -450,6 +465,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
latinIme.onStartInputViewInternal(editorInfo, restarting);
mAppliedEditorInfo = editorInfo;
}
+ cancelDeallocateMemory();
}
}
@@ -463,6 +479,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
latinIme.onFinishInputViewInternal(finishingInput);
mAppliedEditorInfo = null;
}
+ if (!hasPendingDeallocateMemory()) {
+ postDeallocateMemory();
+ }
}
}
@@ -516,9 +535,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public LatinIME() {
super();
mSettings = Settings.getInstance();
- mSubtypeSwitcher = SubtypeSwitcher.getInstance();
mKeyboardSwitcher = KeyboardSwitcher.getInstance();
- mSpecialKeyDetector = new SpecialKeyDetector(this);
+ mStatsUtilsManager = StatsUtilsManager.getInstance();
mIsHardwareAcceleratedDrawingEnabled =
InputMethodServiceCompatUtils.enableHardwareAcceleration(this);
Log.i(TAG, "Hardware accelerated drawing: " + mIsHardwareAcceleratedDrawingEnabled);
@@ -530,28 +548,25 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
DebugFlags.init(PreferenceManager.getDefaultSharedPreferences(this));
RichInputMethodManager.init(this);
mRichImm = RichInputMethodManager.getInstance();
- SubtypeSwitcher.init(this);
KeyboardSwitcher.init(this);
AudioAndHapticFeedbackManager.init(this);
AccessibilityUtils.init(this);
- StatsUtils.init(this);
-
+ mStatsUtilsManager.onCreate(this /* context */, mDictionaryFacilitator);
super.onCreate();
mHandler.onCreate();
- DEBUG = DebugFlags.DEBUG_ENABLED;
- // TODO: Resolve mutual dependencies of {@link #loadSettings()} and {@link #initSuggest()}.
+ // TODO: Resolve mutual dependencies of {@link #loadSettings()} and
+ // {@link #resetDictionaryFacilitatorIfNecessary()}.
loadSettings();
- resetSuggest();
+ resetDictionaryFacilitatorIfNecessary();
- // Register to receive ringer mode change and network state change.
- // Also receive installation and removal of a dictionary pack.
+ // Register to receive ringer mode change.
final IntentFilter filter = new IntentFilter();
- filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
- registerReceiver(mConnectivityAndRingerModeChangeReceiver, filter);
+ registerReceiver(mRingerModeChangeReceiver, filter);
+ // Register to receive installation and removal of a dictionary pack.
final IntentFilter packageFilter = new IntentFilter();
packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
@@ -566,15 +581,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
dictDumpFilter.addAction(DictionaryDumpBroadcastReceiver.DICTIONARY_DUMP_INTENT_ACTION);
registerReceiver(mDictionaryDumpBroadcastReceiver, dictDumpFilter);
- DictionaryDecayBroadcastReciever.setUpIntervalAlarmForDictionaryDecaying(this);
-
- StatsUtils.onCreate(mSettings.getCurrent());
+ StatsUtils.onCreate(mSettings.getCurrent(), mRichImm);
}
// Has to be package-visible for unit tests
@UsedForTesting
void loadSettings() {
- final Locale locale = mSubtypeSwitcher.getCurrentSubtypeLocale();
+ final Locale locale = mRichImm.getCurrentSubtypeLocale();
final EditorInfo editorInfo = getCurrentInputEditorInfo();
final InputAttributes inputAttributes = new InputAttributes(
editorInfo, isFullscreenMode(), getPackageName());
@@ -585,30 +598,19 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// been displayed. Opening dictionaries never affects responsivity as dictionaries are
// asynchronously loaded.
if (!mHandler.hasPendingReopenDictionaries()) {
- resetSuggestForLocale(locale);
+ resetDictionaryFacilitator(locale);
}
- mDictionaryFacilitator.updateEnabledSubtypes(mRichImm.getMyEnabledInputMethodSubtypeList(
- true /* allowsImplicitlySelectedSubtypes */));
refreshPersonalizationDictionarySession(currentSettingsValues);
- StatsUtils.onLoadSettings(currentSettingsValues);
+ resetDictionaryFacilitatorIfNecessary();
+ mStatsUtilsManager.onLoadSettings(this /* context */, currentSettingsValues);
}
private void refreshPersonalizationDictionarySession(
final SettingsValues currentSettingsValues) {
- mPersonalizationDictionaryUpdater.onLoadSettings(
- currentSettingsValues.mUsePersonalizedDicts,
- mSubtypeSwitcher.isSystemLocaleSameAsLocaleOfAllEnabledSubtypesOfEnabledImes());
- mContextualDictionaryUpdater.onLoadSettings(currentSettingsValues.mUsePersonalizedDicts);
- final boolean shouldKeepUserHistoryDictionaries;
- if (currentSettingsValues.mUsePersonalizedDicts) {
- shouldKeepUserHistoryDictionaries = true;
- } else {
- shouldKeepUserHistoryDictionaries = false;
- }
- if (!shouldKeepUserHistoryDictionaries) {
+ if (!currentSettingsValues.mUsePersonalizedDicts) {
// Remove user history dictionaries.
PersonalizationHelper.removeAllUserHistoryDictionaries(this);
- mDictionaryFacilitator.clearUserHistoryDictionary();
+ mDictionaryFacilitator.clearUserHistoryDictionary(this);
}
}
@@ -621,44 +623,49 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
if (mHandler.hasPendingWaitForDictionaryLoad()) {
mHandler.cancelWaitForDictionaryLoad();
- mHandler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */,
- false /* shouldDelay */);
+ mHandler.postResumeSuggestions(false /* shouldDelay */);
}
}
- private void resetSuggest() {
- final Locale switcherSubtypeLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
- final String switcherLocaleStr = switcherSubtypeLocale.toString();
+ void resetDictionaryFacilitatorIfNecessary() {
+ final Locale subtypeSwitcherLocale = mRichImm.getCurrentSubtypeLocale();
final Locale subtypeLocale;
- if (TextUtils.isEmpty(switcherLocaleStr)) {
+ if (subtypeSwitcherLocale == null) {
// This happens in very rare corner cases - for example, immediately after a switch
// to LatinIME has been requested, about a frame later another switch happens. In this
// case, we are about to go down but we still don't know it, however the system tells
- // us there is no current subtype so the locale is the empty string. Take the best
- // possible guess instead -- it's bound to have no consequences, and we have no way
- // of knowing anyway.
+ // us there is no current subtype.
Log.e(TAG, "System is reporting no current subtype.");
subtypeLocale = getResources().getConfiguration().locale;
} else {
- subtypeLocale = switcherSubtypeLocale;
+ subtypeLocale = subtypeSwitcherLocale;
+ }
+ if (mDictionaryFacilitator.isForLocale(subtypeLocale)
+ && mDictionaryFacilitator.isForAccount(mSettings.getCurrent().mAccount)) {
+ return;
}
- resetSuggestForLocale(subtypeLocale);
+ resetDictionaryFacilitator(subtypeLocale);
}
/**
- * Reset suggest by loading dictionaries for the locale and the current settings values.
+ * Reset the facilitator by loading dictionaries for the given locale and
+ * the current settings values.
*
* @param locale the locale
*/
- private void resetSuggestForLocale(final Locale locale) {
+ // TODO: make sure the current settings always have the right locales, and read from them.
+ private void resetDictionaryFacilitator(final Locale locale) {
final SettingsValues settingsValues = mSettings.getCurrent();
mDictionaryFacilitator.resetDictionaries(this /* context */, locale,
settingsValues.mUseContactsDict, settingsValues.mUsePersonalizedDicts,
- false /* forceReloadMainDictionary */, this);
+ false /* forceReloadMainDictionary */,
+ settingsValues.mAccount, "" /* dictNamePrefix */,
+ this /* DictionaryInitializationListener */);
if (settingsValues.mAutoCorrectionEnabledPerUserSettings) {
mInputLogic.mSuggest.setAutoCorrectionThreshold(
settingsValues.mAutoCorrectionThreshold);
}
+ mInputLogic.mSuggest.setPlausibilityThreshold(settingsValues.mPlausibilityThreshold);
}
/**
@@ -668,19 +675,20 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final SettingsValues settingsValues = mSettings.getCurrent();
mDictionaryFacilitator.resetDictionaries(this /* context */,
mDictionaryFacilitator.getLocale(), settingsValues.mUseContactsDict,
- settingsValues.mUsePersonalizedDicts, true /* forceReloadMainDictionary */, this);
+ settingsValues.mUsePersonalizedDicts,
+ true /* forceReloadMainDictionary */,
+ settingsValues.mAccount, "" /* dictNamePrefix */,
+ this /* DictionaryInitializationListener */);
}
@Override
public void onDestroy() {
mDictionaryFacilitator.closeDictionaries();
- mPersonalizationDictionaryUpdater.onDestroy();
- mContextualDictionaryUpdater.onDestroy();
mSettings.onDestroy();
- unregisterReceiver(mConnectivityAndRingerModeChangeReceiver);
+ unregisterReceiver(mRingerModeChangeReceiver);
unregisterReceiver(mDictionaryPackInstallReceiver);
unregisterReceiver(mDictionaryDumpBroadcastReceiver);
- StatsUtils.onDestroy();
+ mStatsUtilsManager.onDestroy(this /* context */);
super.onDestroy();
}
@@ -688,7 +696,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public void recycle() {
unregisterReceiver(mDictionaryPackInstallReceiver);
unregisterReceiver(mDictionaryDumpBroadcastReceiver);
- unregisterReceiver(mConnectivityAndRingerModeChangeReceiver);
+ unregisterReceiver(mRingerModeChangeReceiver);
mInputLogic.recycle();
}
@@ -715,15 +723,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
cleanupInternalStateForFinishInput();
}
}
- // TODO: Remove this test.
- if (!conf.locale.equals(mPersonalizationDictionaryUpdater.getLocale())) {
- refreshPersonalizationDictionarySession(settingsValues);
- }
super.onConfigurationChanged(conf);
}
@Override
public View onCreateInputView() {
+ StatsUtils.onCreateInputView();
return mKeyboardSwitcher.onCreateInputView(mIsHardwareAcceleratedDrawingEnabled);
}
@@ -731,60 +736,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public void setInputView(final View view) {
super.setInputView(view);
mInputView = view;
+ mInsetsUpdater = ViewOutlineProviderCompatUtils.setInsetsOutlineProvider(view);
+ updateSoftInputWindowLayoutParameters();
mSuggestionStripView = (SuggestionStripView)view.findViewById(R.id.suggestion_strip_view);
if (hasSuggestionStripView()) {
mSuggestionStripView.setListener(this, view);
}
- mInputLogic.setTextDecoratorUi(new TextDecoratorUi(this, view));
- }
-
- @Override
- public void setExtractView(final View view) {
- final TextView prevExtractEditText = mExtractEditText;
- super.setExtractView(view);
- TextView nextExtractEditText = null;
- if (view != null) {
- final View extractEditText = view.findViewById(android.R.id.inputExtractEditText);
- if (extractEditText instanceof TextView) {
- nextExtractEditText = (TextView)extractEditText;
- }
- }
- if (prevExtractEditText == nextExtractEditText) {
- return;
- }
- if (ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK && prevExtractEditText != null) {
- prevExtractEditText.getViewTreeObserver().removeOnPreDrawListener(
- mExtractTextViewPreDrawListener);
- }
- mExtractEditText = nextExtractEditText;
- if (ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK && mExtractEditText != null) {
- mExtractEditText.getViewTreeObserver().addOnPreDrawListener(
- mExtractTextViewPreDrawListener);
- }
- }
-
- private final ViewTreeObserver.OnPreDrawListener mExtractTextViewPreDrawListener =
- new ViewTreeObserver.OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- onExtractTextViewPreDraw();
- return true;
- }
- };
-
- private void onExtractTextViewPreDraw() {
- if (!ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK || !isFullscreenMode()
- || mExtractEditText == null) {
- return;
- }
- final CursorAnchorInfo info = CursorAnchorInfoUtils.getCursorAnchorInfo(mExtractEditText);
- mInputLogic.onUpdateCursorAnchorInfo(CursorAnchorInfoCompatWrapper.fromObject(info));
}
@Override
public void setCandidatesView(final View view) {
// To ensure that CandidatesView will never be set.
- return;
}
@Override
@@ -795,11 +757,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public void onStartInputView(final EditorInfo editorInfo, final boolean restarting) {
mHandler.onStartInputView(editorInfo, restarting);
+ mStatsUtilsManager.onStartInputView();
}
@Override
public void onFinishInputView(final boolean finishingInput) {
+ StatsUtils.onFinishInputView();
mHandler.onFinishInputView(finishingInput);
+ mStatsUtilsManager.onFinishInputView();
+ mGestureConsumer = GestureConsumer.NULL_GESTURE_CONSUMER;
}
@Override
@@ -811,20 +777,27 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public void onCurrentInputMethodSubtypeChanged(final InputMethodSubtype subtype) {
// Note that the calling sequence of onCreate() and onCurrentInputMethodSubtypeChanged()
// is not guaranteed. It may even be called at the same time on a different thread.
- mSubtypeSwitcher.onSubtypeChanged(subtype);
+ InputMethodSubtype oldSubtype = mRichImm.getCurrentSubtype().getRawSubtype();
+ StatsUtils.onSubtypeChanged(oldSubtype, subtype);
+ mRichImm.onSubtypeChanged(subtype);
mInputLogic.onSubtypeChanged(SubtypeLocaleUtils.getCombiningRulesExtraValue(subtype),
mSettings.getCurrent());
loadKeyboard();
}
- private void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) {
+ void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) {
super.onStartInput(editorInfo, restarting);
}
@SuppressWarnings("deprecation")
- private void onStartInputViewInternal(final EditorInfo editorInfo, final boolean restarting) {
+ void onStartInputViewInternal(final EditorInfo editorInfo, final boolean restarting) {
super.onStartInputView(editorInfo, restarting);
- mRichImm.clearSubtypeCaches();
+
+ mDictionaryFacilitator.onStartInput();
+ // Switch to the null consumer to handle cases leading to early exit below, for which we
+ // also wouldn't be consuming gesture data.
+ mGestureConsumer = GestureConsumer.NULL_GESTURE_CONSUMER;
+ mRichImm.refreshSubtypeCaches();
final KeyboardSwitcher switcher = mKeyboardSwitcher;
switcher.updateKeyboardTheme();
final MainKeyboardView mainKeyboardView = switcher.getMainKeyboardView();
@@ -839,7 +812,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
return;
}
- if (DEBUG) {
+ if (DebugFlags.DEBUG_ENABLED) {
Log.d(TAG, "onStartInputView: editorInfo:"
+ String.format("inputType=0x%08x imeOptions=0x%08x",
editorInfo.inputType, editorInfo.imeOptions));
@@ -867,6 +840,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return;
}
+ // Update to a gesture consumer with the current editor and IME state.
+ mGestureConsumer = GestureConsumer.newInstance(editorInfo,
+ mInputLogic.getPrivateCommandPerformer(),
+ mRichImm.getCurrentSubtypeLocale(),
+ switcher.getKeyboard());
+
// Forward this event to the accessibility utilities, if enabled.
final AccessibilityUtils accessUtils = AccessibilityUtils.getInstance();
if (accessUtils.isTouchExplorationEnabled()) {
@@ -875,9 +854,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final boolean inputTypeChanged = !currentSettingsValues.isSameInputType(editorInfo);
final boolean isDifferentTextField = !restarting || inputTypeChanged;
- if (isDifferentTextField) {
- mSubtypeSwitcher.updateParametersOnStartInputView();
- }
+
+ StatsUtils.onStartInputView(editorInfo.inputType,
+ Settings.getInstance().getCurrent().mDisplayOrientation,
+ !isDifferentTextField);
// The EditorInfo might have a flag that affects fullscreen mode.
// Note: This call should be done by InputMethodService?
@@ -897,15 +877,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// span, so we should reset our state unconditionally, even if restarting is true.
// We also tell the input logic about the combining rules for the current subtype, so
// it can adjust its combiners if needed.
- mInputLogic.startInput(mSubtypeSwitcher.getCombiningRulesExtraValueOfCurrentSubtype(),
+ mInputLogic.startInput(mRichImm.getCombiningRulesExtraValueOfCurrentSubtype(),
currentSettingsValues);
- // Note: the following does a round-trip IPC on the main thread: be careful
- final Locale currentLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
- if (null != currentLocale && !currentLocale.equals(suggest.getLocale())) {
- // TODO: Do this automatically.
- resetSuggest();
- }
+ resetDictionaryFacilitatorIfNecessary();
// TODO[IL]: Can the following be moved to InputLogic#startInput?
if (!mInputLogic.mConnection.resetCachesUponCursorMoveAndReturnSuccess(
@@ -919,11 +894,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// mLastSelection{Start,End} are reset later in this method, no need to do it here
needToCallLoadKeyboardLater = true;
} else {
- // When rotating, initialSelStart and initialSelEnd sometimes are lying. Make a best
- // effort to work around this bug.
+ // When rotating, and when input is starting again in a field from where the focus
+ // didn't move (the keyboard having been closed with the back key),
+ // initialSelStart and initialSelEnd sometimes are lying. Make a best effort to
+ // work around this bug.
mInputLogic.mConnection.tryFixLyingCursorPosition();
- mHandler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */,
- true /* shouldDelay */);
+ mHandler.postResumeSuggestionsForStartInput(true /* shouldDelay */);
needToCallLoadKeyboardLater = false;
}
} else {
@@ -943,6 +919,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
suggest.setAutoCorrectionThreshold(
currentSettingsValues.mAutoCorrectionThreshold);
}
+ suggest.setPlausibilityThreshold(currentSettingsValues.mPlausibilityThreshold);
switcher.loadKeyboard(editorInfo, currentSettingsValues, getCurrentAutoCapsState(),
getCurrentRecapitalizeState());
@@ -970,7 +947,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mHandler.cancelUpdateSuggestionStrip();
mainKeyboardView.setMainDictionaryAvailability(
- mDictionaryFacilitator.hasInitializedMainDictionary());
+ mDictionaryFacilitator.hasAtLeastOneInitializedMainDictionary());
mainKeyboardView.setKeyPreviewPopupEnabled(currentSettingsValues.mKeyPreviewPopupOn,
currentSettingsValues.mKeyPreviewPopupDismissDelay);
mainKeyboardView.setSlidingKeyInputPreviewEnabled(
@@ -980,8 +957,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
currentSettingsValues.mGestureTrailEnabled,
currentSettingsValues.mGestureFloatingPreviewTextEnabled);
- // Contextual dictionary should be updated for the current application.
- mContextualDictionaryUpdater.onStartInputView(editorInfo.packageName);
if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
}
@@ -994,45 +969,50 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
- private void onFinishInputInternal() {
+ void onFinishInputInternal() {
super.onFinishInput();
+ mDictionaryFacilitator.onFinishInput();
final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
if (mainKeyboardView != null) {
mainKeyboardView.closing();
}
}
- private void onFinishInputViewInternal(final boolean finishingInput) {
+ void onFinishInputViewInternal(final boolean finishingInput) {
super.onFinishInputView(finishingInput);
cleanupInternalStateForFinishInput();
}
private void cleanupInternalStateForFinishInput() {
- mKeyboardSwitcher.deallocateMemory();
// Remove pending messages related to update suggestions
mHandler.cancelUpdateSuggestionStrip();
// Should do the following in onFinishInputInternal but until JB MR2 it's not called :(
mInputLogic.finishInput();
}
+ protected void deallocateMemory() {
+ mKeyboardSwitcher.deallocateMemory();
+ }
+
@Override
public void onUpdateSelection(final int oldSelStart, final int oldSelEnd,
final int newSelStart, final int newSelEnd,
final int composingSpanStart, final int composingSpanEnd) {
super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
composingSpanStart, composingSpanEnd);
- if (DEBUG) {
+ if (DebugFlags.DEBUG_ENABLED) {
Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart + ", ose=" + oldSelEnd
+ ", nss=" + newSelStart + ", nse=" + newSelEnd
+ ", cs=" + composingSpanStart + ", ce=" + composingSpanEnd);
}
- // This call happens when we have a hardware keyboard as well as when we don't. While we
- // don't support hardware keyboards yet we should avoid doing the processing associated
- // with cursor movement when we have a hardware keyboard since we are not in charge.
+ // This call happens whether our view is displayed or not, but if it's not then we should
+ // not attempt recorrection. This is true even with a hardware keyboard connected: if the
+ // view is not displayed we have no means of showing suggestions anyway, and if it is then
+ // we want to show suggestions anyway.
final SettingsValues settingsValues = mSettings.getCurrent();
- if ((!settingsValues.mHasHardwareKeyboard || ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED)
+ if (isInputViewShown()
&& mInputLogic.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
settingsValues)) {
mKeyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(),
@@ -1040,15 +1020,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
- // We cannot mark this method as @Override until new SDK becomes publicly available.
- // @Override
- public void onUpdateCursorAnchorInfo(final CursorAnchorInfo info) {
- if (!ProductionFlags.ENABLE_CURSOR_ANCHOR_INFO_CALLBACK || isFullscreenMode()) {
- return;
- }
- mInputLogic.onUpdateCursorAnchorInfo(CursorAnchorInfoCompatWrapper.fromObject(info));
- }
-
/**
* This is called when the user has clicked on the extracted text view,
* when running in fullscreen mode. The default implementation hides
@@ -1098,7 +1069,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public void onDisplayCompletions(final CompletionInfo[] applicationSpecifiedCompletions) {
- if (DEBUG) {
+ if (DebugFlags.DEBUG_ENABLED) {
Log.i(TAG, "Received completions:");
if (applicationSpecifiedCompletions != null) {
for (int i = 0; i < applicationSpecifiedCompletions.length; i++) {
@@ -1121,9 +1092,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
SuggestedWords.getFromApplicationSpecifiedCompletions(
applicationSpecifiedCompletions);
final SuggestedWords suggestedWords = new SuggestedWords(applicationSuggestedWords,
- null /* rawSuggestions */, false /* typedWordValid */, false /* willAutoCorrect */,
+ null /* rawSuggestions */,
+ null /* typedWord */,
+ false /* typedWordValid */,
+ false /* willAutoCorrect */,
false /* isObsoleteSuggestions */,
- SuggestedWords.INPUT_STYLE_APPLICATION_SPECIFIED /* inputStyle */);
+ SuggestedWords.INPUT_STYLE_APPLICATION_SPECIFIED /* inputStyle */,
+ SuggestedWords.NOT_A_SEQUENCE_NUMBER);
// When in fullscreen mode, show completions generated by the application forcibly
setSuggestedWords(suggestedWords);
}
@@ -1131,6 +1106,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public void onComputeInsets(final InputMethodService.Insets outInsets) {
super.onComputeInsets(outInsets);
+ // This method may be called before {@link #setInputView(View)}.
+ if (mInputView == null) {
+ return;
+ }
final SettingsValues settingsValues = mSettings.getCurrent();
final View visibleKeyboardView = mKeyboardSwitcher.getVisibleKeyboardView();
if (visibleKeyboardView == null || !hasSuggestionStripView()) {
@@ -1141,8 +1120,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (hasHardwareKeyboard && visibleKeyboardView.getVisibility() == View.GONE) {
// If there is a hardware keyboard and a visible software keyboard view has been hidden,
// no visual element will be shown on the screen.
- outInsets.touchableInsets = inputHeight;
+ outInsets.contentTopInsets = inputHeight;
outInsets.visibleTopInsets = inputHeight;
+ mInsetsUpdater.setInsets(outInsets);
return;
}
final int suggestionsHeight = (!mKeyboardSwitcher.isShowingEmojiPalettes()
@@ -1150,7 +1130,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
? mSuggestionStripView.getHeight() : 0;
final int visibleTopY = inputHeight - visibleKeyboardView.getHeight() - suggestionsHeight;
mSuggestionStripView.setMoreSuggestionsHeight(visibleTopY);
- // Need to set touchable region only if a keyboard view is being shown.
+ // Need to set expanded touchable region only if a keyboard view is being shown.
if (visibleKeyboardView.isShown()) {
final int touchLeft = 0;
final int touchTop = mKeyboardSwitcher.isShowingMoreKeysPanel() ? 0 : visibleTopY;
@@ -1163,14 +1143,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
outInsets.contentTopInsets = visibleTopY;
outInsets.visibleTopInsets = visibleTopY;
+ mInsetsUpdater.setInsets(outInsets);
}
- public void startShowingInputView() {
+ public void startShowingInputView(final boolean needsToLoadKeyboard) {
mIsExecutingStartShowingInputView = true;
// This {@link #showWindow(boolean)} will eventually call back
// {@link #onEvaluateInputViewShown()}.
showWindow(true /* showInput */);
mIsExecutingStartShowingInputView = false;
+ if (needsToLoadKeyboard) {
+ loadKeyboard();
+ }
}
public void stopShowingInputView() {
@@ -1178,6 +1162,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
@Override
+ public boolean onShowInputRequested(final int flags, final boolean configChange) {
+ if (Settings.getInstance().getCurrent().mHasHardwareKeyboard) {
+ return true;
+ }
+ return super.onShowInputRequested(flags, configChange);
+ }
+
+ @Override
public boolean onEvaluateInputViewShown() {
if (mIsExecutingStartShowingInputView) {
return true;
@@ -1207,8 +1199,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public void updateFullscreenMode() {
+ super.updateFullscreenMode();
+ updateSoftInputWindowLayoutParameters();
+ }
+
+ private void updateSoftInputWindowLayoutParameters() {
// Override layout parameters to expand {@link SoftInputWindow} to the entire screen.
- // See {@link InputMethodService#setinputView(View) and
+ // See {@link InputMethodService#setinputView(View)} and
// {@link SoftInputWindow#updateWidthHeight(WindowManager.LayoutParams)}.
final Window window = getWindow().getWindow();
ViewLayoutUtils.updateLayoutHeightOf(window, LayoutParams.MATCH_PARENT);
@@ -1227,22 +1224,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
ViewLayoutUtils.updateLayoutGravityOf(inputArea, Gravity.BOTTOM);
ViewLayoutUtils.updateLayoutHeightOf(mInputView, layoutHeight);
}
- super.updateFullscreenMode();
- mInputLogic.onUpdateFullscreenMode(isFullscreenMode());
}
- private int getCurrentAutoCapsState() {
+ int getCurrentAutoCapsState() {
return mInputLogic.getCurrentAutoCapsState(mSettings.getCurrent());
}
- private int getCurrentRecapitalizeState() {
+ int getCurrentRecapitalizeState() {
return mInputLogic.getCurrentRecapitalizeState();
}
- public Locale getCurrentSubtypeLocale() {
- return mSubtypeSwitcher.getCurrentSubtypeLocale();
- }
-
/**
* @param codePoints code points to get coordinates for.
* @return x,y coordinates for this keyboard, as a flattened array.
@@ -1256,24 +1247,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return keyboard.getCoordinates(codePoints);
}
- // Callback for the {@link SuggestionStripView}, to call when the "add to dictionary" hint is
- // pressed.
- @Override
- public void addWordToUserDictionary(final String word) {
- if (TextUtils.isEmpty(word)) {
- // Probably never supposed to happen, but just in case.
- return;
- }
- final String wordToEdit;
- if (CapsModeUtils.isAutoCapsMode(mInputLogic.mLastComposedWord.mCapitalizedMode)) {
- wordToEdit = word.toLowerCase(getCurrentSubtypeLocale());
- } else {
- wordToEdit = word;
- }
- mDictionaryFacilitator.addWordToUserDictionary(this /* context */, wordToEdit);
- mInputLogic.onAddWordToUserDictionary();
- }
-
// Callback for the {@link SuggestionStripView}, to call when the important notice strip is
// pressed.
@Override
@@ -1284,7 +1257,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Implement {@link ImportantNoticeDialog.ImportantNoticeDialogListener}
@Override
public void onClickSettingsOfImportantNoticeDialog(final int nextVersion) {
- launchSettings();
+ launchSettings(SettingsActivity.EXTRA_ENTRY_VALUE_NOTICE_DIALOG);
}
// Implement {@link ImportantNoticeDialog.ImportantNoticeDialogListener}
@@ -1328,48 +1301,56 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mSubtypeState.switchSubtype(token, mRichImm);
}
+ // TODO: Instead of checking for alphabetic keyboard here, separate keycodes for
+ // alphabetic shift and shift while in symbol layout and get rid of this method.
+ private int getCodePointForKeyboard(final int codePoint) {
+ if (Constants.CODE_SHIFT == codePoint) {
+ final Keyboard currentKeyboard = mKeyboardSwitcher.getKeyboard();
+ if (null != currentKeyboard && currentKeyboard.mId.isAlphabetKeyboard()) {
+ return codePoint;
+ }
+ return Constants.CODE_SYMBOL_SHIFT;
+ }
+ return codePoint;
+ }
+
// Implementation of {@link KeyboardActionListener}.
@Override
public void onCodeInput(final int codePoint, final int x, final int y,
final boolean isKeyRepeat) {
+ // TODO: this processing does not belong inside LatinIME, the caller should be doing this.
final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
// x and y include some padding, but everything down the line (especially native
// code) needs the coordinates in the keyboard frame.
// TODO: We should reconsider which coordinate system should be used to represent
// keyboard event. Also we should pull this up -- LatinIME has no business doing
- // this transformation, it should be done already before calling onCodeInput.
+ // this transformation, it should be done already before calling onEvent.
final int keyX = mainKeyboardView.getKeyX(x);
final int keyY = mainKeyboardView.getKeyY(y);
- final int codeToSend;
- if (Constants.CODE_SHIFT == codePoint) {
- // TODO: Instead of checking for alphabetic keyboard here, separate keycodes for
- // alphabetic shift and shift while in symbol layout.
- final Keyboard currentKeyboard = mKeyboardSwitcher.getKeyboard();
- if (null != currentKeyboard && currentKeyboard.mId.isAlphabetKeyboard()) {
- codeToSend = codePoint;
- } else {
- codeToSend = Constants.CODE_SYMBOL_SHIFT;
- }
- } else {
- codeToSend = codePoint;
- }
- if (Constants.CODE_SHORTCUT == codePoint) {
- mSubtypeSwitcher.switchToShortcutIME(this);
- // Still call the *#onCodeInput methods for readability.
+ final Event event = createSoftwareKeypressEvent(getCodePointForKeyboard(codePoint),
+ keyX, keyY, isKeyRepeat);
+ onEvent(event);
+ }
+
+ // This method is public for testability of LatinIME, but also in the future it should
+ // completely replace #onCodeInput.
+ public void onEvent(@Nonnull final Event event) {
+ if (Constants.CODE_SHORTCUT == event.mKeyCode) {
+ mRichImm.switchToShortcutIme(this);
}
- final Event event = createSoftwareKeypressEvent(codeToSend, keyX, keyY, isKeyRepeat);
final InputTransaction completeInputTransaction =
mInputLogic.onCodeInput(mSettings.getCurrent(), event,
mKeyboardSwitcher.getKeyboardShiftMode(),
mKeyboardSwitcher.getCurrentKeyboardScriptId(), mHandler);
updateStateAfterInputTransaction(completeInputTransaction);
- mKeyboardSwitcher.onCodeInput(codePoint, getCurrentAutoCapsState(),
- getCurrentRecapitalizeState());
+ mKeyboardSwitcher.onEvent(event, getCurrentAutoCapsState(), getCurrentRecapitalizeState());
}
// A helper method to split the code point and the key code. Ultimately, they should not be
// squashed into the same variable, and this method should be removed.
- private static Event createSoftwareKeypressEvent(final int keyCodeOrCodePoint, final int keyX,
+ // public for testing, as we don't want to copy the same logic into test code
+ @Nonnull
+ public static Event createSoftwareKeypressEvent(final int keyCodeOrCodePoint, final int keyX,
final int keyY, final boolean isKeyRepeat) {
final int keyCode;
final int codePoint;
@@ -1387,44 +1368,59 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public void onTextInput(final String rawText) {
// TODO: have the keyboard pass the correct key code when we need it.
- final Event event = Event.createSoftwareTextEvent(rawText, Event.NOT_A_KEY_CODE);
+ final Event event = Event.createSoftwareTextEvent(rawText, Constants.CODE_OUTPUT_TEXT);
final InputTransaction completeInputTransaction =
mInputLogic.onTextInput(mSettings.getCurrent(), event,
mKeyboardSwitcher.getKeyboardShiftMode(), mHandler);
updateStateAfterInputTransaction(completeInputTransaction);
- mKeyboardSwitcher.onCodeInput(Constants.CODE_OUTPUT_TEXT, getCurrentAutoCapsState(),
- getCurrentRecapitalizeState());
+ mKeyboardSwitcher.onEvent(event, getCurrentAutoCapsState(), getCurrentRecapitalizeState());
}
@Override
public void onStartBatchInput() {
mInputLogic.onStartBatchInput(mSettings.getCurrent(), mKeyboardSwitcher, mHandler);
+ mGestureConsumer.onGestureStarted(
+ mRichImm.getCurrentSubtypeLocale(),
+ mKeyboardSwitcher.getKeyboard());
}
@Override
public void onUpdateBatchInput(final InputPointers batchPointers) {
- mInputLogic.onUpdateBatchInput(mSettings.getCurrent(), batchPointers, mKeyboardSwitcher);
+ mInputLogic.onUpdateBatchInput(batchPointers);
}
@Override
public void onEndBatchInput(final InputPointers batchPointers) {
mInputLogic.onEndBatchInput(batchPointers);
+ mGestureConsumer.onGestureCompleted(batchPointers);
}
@Override
public void onCancelBatchInput() {
mInputLogic.onCancelBatchInput(mHandler);
+ mGestureConsumer.onGestureCanceled();
+ }
+
+ /**
+ * To be called after the InputLogic has gotten a chance to act on the suggested words by the
+ * IME for the full gesture, possibly updating the TextView to reflect the first suggestion.
+ * <p>
+ * This method must be run on the UI Thread.
+ * @param suggestedWords suggested words by the IME for the full gesture.
+ */
+ public void onTailBatchInputResultShown(final SuggestedWords suggestedWords) {
+ mGestureConsumer.onImeSuggestionsProcessed(suggestedWords,
+ mInputLogic.getComposingStart(), mInputLogic.getComposingLength(),
+ mDictionaryFacilitator);
}
// This method must run on the UI Thread.
- private void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords,
+ void showGesturePreviewAndSuggestionStrip(@Nonnull final SuggestedWords suggestedWords,
final boolean dismissGestureFloatingPreviewText) {
showSuggestionStrip(suggestedWords);
final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
- mainKeyboardView.showGestureFloatingPreviewText(suggestedWords);
- if (dismissGestureFloatingPreviewText) {
- mainKeyboardView.dismissGestureFloatingPreviewText();
- }
+ mainKeyboardView.showGestureFloatingPreviewText(suggestedWords,
+ dismissGestureFloatingPreviewText /* dismissDelayed */);
}
// Called from PointerTracker through the KeyboardActionListener interface
@@ -1446,22 +1442,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return null != mSuggestionStripView;
}
- @Override
- public boolean isShowingAddToDictionaryHint() {
- return hasSuggestionStripView() && mSuggestionStripView.isShowingAddToDictionaryHint();
- }
-
- @Override
- public void dismissAddToDictionaryHint() {
- if (!hasSuggestionStripView()) {
- return;
- }
- mSuggestionStripView.dismissAddToDictionaryHint();
- }
-
private void setSuggestedWords(final SuggestedWords suggestedWords) {
final SettingsValues currentSettingsValues = mSettings.getCurrent();
- mInputLogic.setSuggestedWords(suggestedWords, currentSettingsValues, mHandler);
+ mInputLogic.setSuggestedWords(suggestedWords);
// TODO: Modify this when we support suggestions with hard keyboard
if (!hasSuggestionStripView()) {
return;
@@ -1471,7 +1454,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
final boolean shouldShowImportantNotice =
- ImportantNoticeUtils.shouldShowImportantNotice(this);
+ ImportantNoticeUtils.shouldShowImportantNotice(this, currentSettingsValues);
final boolean shouldShowSuggestionCandidates =
currentSettingsValues.mInputAttributes.mShouldShowSuggestions
&& currentSettingsValues.isSuggestionsEnabledPerUserSettings();
@@ -1489,7 +1472,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final boolean isEmptyApplicationSpecifiedCompletions =
currentSettingsValues.isApplicationSpecifiedCompletionsOn()
&& suggestedWords.isEmpty();
- final boolean noSuggestionsFromDictionaries = (SuggestedWords.EMPTY == suggestedWords)
+ final boolean noSuggestionsFromDictionaries = suggestedWords.isEmpty()
|| suggestedWords.isPunctuationSuggestions()
|| isEmptyApplicationSpecifiedCompletions;
final boolean isBeginningOfSentencePrediction = (suggestedWords.mInputStyle
@@ -1507,7 +1490,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// We should clear the contextual strip if there is no suggestion from dictionaries.
|| noSuggestionsFromDictionaries) {
mSuggestionStripView.setSuggestions(suggestedWords,
- SubtypeLocaleUtils.isRtlLanguage(mSubtypeSwitcher.getCurrentSubtype()));
+ mRichImm.getCurrentSubtype().isRtlSubtype());
}
}
@@ -1516,26 +1499,23 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final OnGetSuggestedWordsCallback callback) {
final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
if (keyboard == null) {
- callback.onGetSuggestedWords(SuggestedWords.EMPTY);
+ callback.onGetSuggestedWords(SuggestedWords.getEmptyInstance());
return;
}
- mInputLogic.getSuggestedWords(mSettings.getCurrent(), keyboard.getProximityInfo(),
+ mInputLogic.getSuggestedWords(mSettings.getCurrent(), keyboard,
mKeyboardSwitcher.getKeyboardShiftMode(), inputStyle, sequenceNumber, callback);
}
@Override
- public void showSuggestionStrip(final SuggestedWords sourceSuggestedWords) {
- final SuggestedWords suggestedWords =
- sourceSuggestedWords.isEmpty() ? SuggestedWords.EMPTY : sourceSuggestedWords;
- if (SuggestedWords.EMPTY == suggestedWords) {
+ public void showSuggestionStrip(final SuggestedWords suggestedWords) {
+ if (suggestedWords.isEmpty()) {
setNeutralSuggestionStrip();
} else {
setSuggestedWords(suggestedWords);
}
// Cache the auto-correction in accessibility code so we can speak it if the user
// touches a key that will insert it.
- AccessibilityUtils.getInstance().setAutoCorrection(suggestedWords,
- sourceSuggestedWords.mTypedWord);
+ AccessibilityUtils.getInstance().setAutoCorrection(suggestedWords);
}
// Called from {@link SuggestionStripView} through the {@link SuggestionStripView#Listener}
@@ -1550,25 +1530,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
updateStateAfterInputTransaction(completeInputTransaction);
}
- @Override
- public void showAddToDictionaryHint(final String word) {
- if (!hasSuggestionStripView()) {
- return;
- }
- mSuggestionStripView.showAddToDictionaryHint(word);
- }
-
// This will show either an empty suggestion strip (if prediction is enabled) or
// punctuation suggestions (if it's disabled).
@Override
public void setNeutralSuggestionStrip() {
final SettingsValues currentSettings = mSettings.getCurrent();
final SuggestedWords neutralSuggestions = currentSettings.mBigramPredictionEnabled
- ? SuggestedWords.EMPTY : currentSettings.mSpacingAndPunctuations.mSuggestPuncList;
+ ? SuggestedWords.getEmptyInstance()
+ : currentSettings.mSpacingAndPunctuations.mSuggestPuncList;
setSuggestedWords(neutralSuggestions);
}
- // TODO: Make this private
// Outside LatinIME, only used by the {@link InputTestsBase} test suite.
@UsedForTesting
void loadKeyboard() {
@@ -1676,7 +1648,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Hooks for hardware keyboard
@Override
public boolean onKeyDown(final int keyCode, final KeyEvent keyEvent) {
- mSpecialKeyDetector.onKeyDown(keyEvent);
+ // TODO: This should be processed in {@link InputLogic}.
+ mEmojiAltPhysicalKeyDetector.onKeyDown(keyEvent);
if (!ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED) {
return super.onKeyDown(keyCode, keyEvent);
}
@@ -1697,7 +1670,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public boolean onKeyUp(final int keyCode, final KeyEvent keyEvent) {
- mSpecialKeyDetector.onKeyUp(keyEvent);
+ // TODO: This should be processed in {@link InputLogic}.
+ mEmojiAltPhysicalKeyDetector.onKeyUp(keyEvent);
if (!ProductionFlags.IS_HARDWARE_KEYBOARD_SUPPORTED) {
return super.onKeyUp(keyCode, keyEvent);
}
@@ -1713,21 +1687,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// boolean onKeyLongPress(final int keyCode, final KeyEvent event);
// boolean onKeyMultiple(final int keyCode, final int count, final KeyEvent event);
- // receive ringer mode change and network state change.
- private final BroadcastReceiver mConnectivityAndRingerModeChangeReceiver =
- new BroadcastReceiver() {
+ // receive ringer mode change.
+ private final BroadcastReceiver mRingerModeChangeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction();
- if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
- mSubtypeSwitcher.onNetworkStateChanged(intent);
- } else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
+ if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
AudioAndHapticFeedbackManager.getInstance().onRingerModeChanged();
}
}
};
- private void launchSettings() {
+ void launchSettings(final String extraEntryValue) {
mInputLogic.commitTyped(mSettings.getCurrent(), LastComposedWord.NOT_A_SEPARATOR);
requestHideSelf(0);
final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
@@ -1740,6 +1711,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra(SettingsActivity.EXTRA_SHOW_HOME_AS_UP, false);
+ intent.putExtra(SettingsActivity.EXTRA_ENTRY_KEY, extraEntryValue);
startActivity(intent);
}
@@ -1751,6 +1723,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
languageSelectionTitle,
getString(ApplicationUtils.getActivityTitleResId(this, SettingsActivity.class))
};
+ final String imeId = mRichImm.getInputMethodIdOfThisIme();
final OnClickListener listener = new OnClickListener() {
@Override
public void onClick(DialogInterface di, int position) {
@@ -1758,7 +1731,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
switch (position) {
case 0:
final Intent intent = IntentUtils.getInputLanguageSelectionIntent(
- mRichImm.getInputMethodIdOfThisIme(),
+ imeId,
Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -1766,7 +1739,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
startActivity(intent);
break;
case 1:
- launchSettings();
+ launchSettings(SettingsActivity.EXTRA_ENTRY_VALUE_LONG_PRESS_COMMA);
break;
}
}
@@ -1798,45 +1771,45 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
dialog.show();
}
- // TODO: can this be removed somehow without breaking the tests?
@UsedForTesting
- /* package for test */ SuggestedWords getSuggestedWordsForTest() {
+ SuggestedWords getSuggestedWordsForTest() {
// You may not use this method for anything else than debug
- return DEBUG ? mInputLogic.mSuggestedWords : null;
+ return DebugFlags.DEBUG_ENABLED ? mInputLogic.mSuggestedWords : null;
}
// DO NOT USE THIS for any other purpose than testing. This is information private to LatinIME.
@UsedForTesting
- /* package for test */ void waitForLoadingDictionaries(final long timeout, final TimeUnit unit)
+ void waitForLoadingDictionaries(final long timeout, final TimeUnit unit)
throws InterruptedException {
mDictionaryFacilitator.waitForLoadingDictionariesForTesting(timeout, unit);
}
// DO NOT USE THIS for any other purpose than testing. This can break the keyboard badly.
@UsedForTesting
- /* package for test */ void replaceDictionariesForTest(final Locale locale) {
+ void replaceDictionariesForTest(final Locale locale) {
final SettingsValues settingsValues = mSettings.getCurrent();
mDictionaryFacilitator.resetDictionaries(this, locale,
settingsValues.mUseContactsDict, settingsValues.mUsePersonalizedDicts,
- false /* forceReloadMainDictionary */, this /* listener */);
+ false /* forceReloadMainDictionary */,
+ settingsValues.mAccount, "", /* dictionaryNamePrefix */
+ this /* DictionaryInitializationListener */);
}
// DO NOT USE THIS for any other purpose than testing.
@UsedForTesting
- /* package for test */ void clearPersonalizedDictionariesForTest() {
- mDictionaryFacilitator.clearUserHistoryDictionary();
- mDictionaryFacilitator.clearPersonalizationDictionary();
+ void clearPersonalizedDictionariesForTest() {
+ mDictionaryFacilitator.clearUserHistoryDictionary(this);
}
@UsedForTesting
- /* package for test */ List<InputMethodSubtype> getEnabledSubtypesForTest() {
+ List<InputMethodSubtype> getEnabledSubtypesForTest() {
return (mRichImm != null) ? mRichImm.getMyEnabledInputMethodSubtypeList(
true /* allowsImplicitlySelectedSubtypes */) : new ArrayList<InputMethodSubtype>();
}
public void dumpDictionaryForDebug(final String dictName) {
- if (mDictionaryFacilitator.getLocale() == null) {
- resetSuggest();
+ if (!mDictionaryFacilitator.isActive()) {
+ resetDictionaryFacilitatorIfNecessary();
}
mDictionaryFacilitator.dumpDictionaryForDebug(dictName);
}
@@ -1862,6 +1835,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
p.println(" Keyboard mode = " + keyboardMode);
final SettingsValues settingsValues = mSettings.getCurrent();
p.println(settingsValues.dump());
+ p.println(mDictionaryFacilitator.dump(this /* context */));
// TODO: Dump all settings values
}