diff options
Diffstat (limited to 'java/src/com/android/inputmethod/latin')
9 files changed, 259 insertions, 56 deletions
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 742328256..1858db949 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -25,10 +25,12 @@ import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.res.Configuration; import android.content.res.Resources; +import android.graphics.Rect; 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.os.SystemClock; import android.preference.PreferenceActivity; @@ -43,6 +45,7 @@ import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; +import android.view.ViewGroup.LayoutParams; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.ExtractedText; @@ -55,6 +58,7 @@ import com.android.inputmethod.compat.EditorInfoCompatUtils; import com.android.inputmethod.compat.InputConnectionCompatUtils; import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; import com.android.inputmethod.compat.InputMethodServiceCompatWrapper; +import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper; import com.android.inputmethod.compat.InputTypeCompatUtils; import com.android.inputmethod.compat.SuggestionSpanUtils; import com.android.inputmethod.compat.VibratorCompatWrapper; @@ -193,9 +197,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private InputMethodManagerCompatWrapper mImm; private Resources mResources; private SharedPreferences mPrefs; - private KeyboardSwitcher mKeyboardSwitcher; - private SubtypeSwitcher mSubtypeSwitcher; + private final KeyboardSwitcher mKeyboardSwitcher; + private final SubtypeSwitcher mSubtypeSwitcher; private VoiceProxy mVoiceProxy; + private boolean mShouldSwitchToLastSubtype = true; private UserDictionary mUserDictionary; private UserBigramDictionary mUserBigramDictionary; @@ -223,9 +228,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private VibratorCompatWrapper mVibrator; - // TODO: Move this flag to VoiceProxy - private boolean mConfigurationChanging; - // Member variables for remembering the current device orientation. private int mDisplayOrientation; @@ -489,6 +491,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } } + public LatinIME() { + super(); + mSubtypeSwitcher = SubtypeSwitcher.getInstance(); + mKeyboardSwitcher = KeyboardSwitcher.getInstance(); + } + @Override public void onCreate() { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); @@ -503,8 +511,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar super.onCreate(); mImm = InputMethodManagerCompatWrapper.getInstance(); - mSubtypeSwitcher = SubtypeSwitcher.getInstance(); - mKeyboardSwitcher = KeyboardSwitcher.getInstance(); mVibrator = VibratorCompatWrapper.getInstance(this); mHandler.onCreate(); DEBUG = LatinImeLogger.sDBG; @@ -552,7 +558,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Has to be package-visible for unit tests /* package */ void loadSettings() { if (null == mPrefs) mPrefs = PreferenceManager.getDefaultSharedPreferences(this); - if (null == mSubtypeSwitcher) mSubtypeSwitcher = SubtypeSwitcher.getInstance(); mSettingsValues = new SettingsValues(mPrefs, this, mSubtypeSwitcher.getInputLocaleStr()); resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary()); } @@ -664,10 +669,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mOptionsDialog.dismiss(); } - mConfigurationChanging = true; + mVoiceProxy.startChangingConfiguration(); super.onConfigurationChanged(conf); mVoiceProxy.onConfigurationChanged(conf); - mConfigurationChanging = false; + mVoiceProxy.finishChangingConfiguration(); // This will work only when the subtype is not supported. LanguageSwitcherProxy.onConfigurationChanged(conf); @@ -728,10 +733,17 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final KeyboardSwitcher switcher = mKeyboardSwitcher; LatinKeyboardView inputView = switcher.getKeyboardView(); + if (editorInfo == null) { + Log.e(TAG, "Null EditorInfo in onStartInputView()"); + if (LatinImeLogger.sDBG) { + throw new NullPointerException("Null EditorInfo in onStartInputView()"); + } + return; + } if (DEBUG) { - Log.d(TAG, "onStartInputView: editorInfo:" + ((editorInfo == null) ? "none" - : String.format("inputType=0x%08x imeOptions=0x%08x", - editorInfo.inputType, editorInfo.imeOptions))); + Log.d(TAG, "onStartInputView: editorInfo:" + + String.format("inputType=0x%08x imeOptions=0x%08x", + editorInfo.inputType, editorInfo.imeOptions)); } if (Utils.inPrivateImeOptions(null, IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo)) { Log.w(TAG, "Deprecated private IME option specified: " @@ -761,7 +773,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Most such things we decide below in initializeInputAttributesAndGetMode, but we need to // know now whether this is a password text field, because we need to know now whether we // want to enable the voice button. - final int inputType = (editorInfo != null) ? editorInfo.inputType : 0; + final int inputType = editorInfo.inputType; mVoiceProxy.resetVoiceStates(InputTypeCompatUtils.isPasswordInputType(inputType) || InputTypeCompatUtils.isVisiblePasswordInputType(inputType)); @@ -823,7 +835,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar LatinImeLogger.commit(); - mVoiceProxy.flushVoiceInputLogs(mConfigurationChanging); + mVoiceProxy.flushVoiceInputLogs(); KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); if (inputView != null) inputView.closing(); @@ -953,7 +965,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mOptionsDialog.dismiss(); mOptionsDialog = null; } - mVoiceProxy.hideVoiceWindow(mConfigurationChanging); + mVoiceProxy.hideVoiceWindow(); super.hideWindow(); } @@ -1011,12 +1023,34 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar setSuggestionStripShownInternal(shown, /* needsInputViewShown */true); } + private void adjustInputViewHeight() { + if (mKeyPreviewBackingView.getHeight() > 0) { + return; + } + + final KeyboardView keyboardView = mKeyboardSwitcher.getKeyboardView(); + if (keyboardView == null) return; + final int keyboardHeight = keyboardView.getHeight(); + final int suggestionsHeight = mSuggestionsContainer.getHeight(); + final int displayHeight = mResources.getDisplayMetrics().heightPixels; + final Rect rect = new Rect(); + mKeyPreviewBackingView.getWindowVisibleDisplayFrame(rect); + final int notificationBarHeight = rect.top; + final int remainingHeight = displayHeight - notificationBarHeight - suggestionsHeight + - keyboardHeight; + + final LayoutParams params = mKeyPreviewBackingView.getLayoutParams(); + params.height = mSuggestionsView.setMoreSuggestionsHeight(remainingHeight); + mKeyPreviewBackingView.setLayoutParams(params); + } + @Override public void onComputeInsets(InputMethodService.Insets outInsets) { super.onComputeInsets(outInsets); final KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); if (inputView == null || mSuggestionsContainer == null) return; + adjustInputViewHeight(); // In fullscreen mode, the height of the extract area managed by InputMethodService should // be considered. // See {@link android.inputmethodservice.InputMethodService#onComputeInsets}. @@ -1245,12 +1279,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar return mOptionsDialog != null && mOptionsDialog.isShowing(); } - private void insertPunctuationFromSuggestionStrip(final int code) { - onCodeInput(code, new int[] { code }, - KeyboardActionListener.SUGGESTION_STRIP_COORDINATE, - KeyboardActionListener.SUGGESTION_STRIP_COORDINATE); - } - private static int getActionId(Keyboard keyboard) { return keyboard != null ? keyboard.mId.imeActionId() : EditorInfo.IME_ACTION_NONE; } @@ -1262,6 +1290,25 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } } + private void handleLanguageSwitchKey() { + final boolean includesOtherImes = !mSettingsValues.mIncludesOtherImesInLanguageSwitchList; + final IBinder token = getWindow().getWindow().getAttributes().token; + if (mShouldSwitchToLastSubtype) { + final InputMethodSubtypeCompatWrapper lastSubtype = mImm.getLastInputMethodSubtype(); + final boolean lastSubtypeBelongsToThisIme = Utils.checkIfSubtypeBelongsToThisIme( + this, lastSubtype); + if ((includesOtherImes || lastSubtypeBelongsToThisIme) + && mImm.switchToLastInputMethod(token)) { + mShouldSwitchToLastSubtype = false; + } else { + mImm.switchToNextInputMethod(token, !includesOtherImes); + mShouldSwitchToLastSubtype = true; + } + } else { + mImm.switchToNextInputMethod(token, !includesOtherImes); + } + } + private void sendKeyCodePoint(int code) { // TODO: Remove this special handling of digit letters. // For backward compatibility. See {@link InputMethodService#sendKeyChar(char)}. @@ -1279,7 +1326,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Implementation of {@link KeyboardActionListener}. @Override - public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { + public void onCodeInput(int primaryCode, int x, int y) { final long when = SystemClock.uptimeMillis(); if (primaryCode != Keyboard.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) { mDeleteCount = 0; @@ -1305,6 +1352,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar handleBackspace(spaceState); mDeleteCount++; mExpectingUpdateSelection = true; + mShouldSwitchToLastSubtype = true; LatinImeLogger.logOnDelete(); break; case Keyboard.CODE_SHIFT: @@ -1326,14 +1374,18 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar case Keyboard.CODE_ACTION_PREVIOUS: EditorInfoCompatUtils.performEditorActionPrevious(getCurrentInputConnection()); break; + case Keyboard.CODE_LANGUAGE_SWITCH: + handleLanguageSwitchKey(); + break; default: mSpaceState = SPACE_STATE_NONE; if (mSettingsValues.isWordSeparator(primaryCode)) { didAutoCorrect = handleSeparator(primaryCode, x, y, spaceState); } else { - handleCharacter(primaryCode, keyCodes, x, y, spaceState); + handleCharacter(primaryCode, x, y, spaceState); } mExpectingUpdateSelection = true; + mShouldSwitchToLastSubtype = true; break; } switcher.onCodeInput(primaryCode); @@ -1498,18 +1550,18 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } } - private void handleCharacter(final int primaryCode, final int[] keyCodes, final int x, + private void handleCharacter(final int primaryCode, final int x, final int y, final int spaceState) { mVoiceProxy.handleCharacter(); final InputConnection ic = getCurrentInputConnection(); if (null != ic) ic.beginBatchEdit(); // TODO: if ic is null, does it make any sense to call this? - handleCharacterWhileInBatchEdit(primaryCode, keyCodes, x, y, spaceState, ic); + handleCharacterWhileInBatchEdit(primaryCode, x, y, spaceState, ic); if (null != ic) ic.endBatchEdit(); } // "ic" may be null without this crashing, but the behavior will be really strange - private void handleCharacterWhileInBatchEdit(final int primaryCode, final int[] keyCodes, + private void handleCharacterWhileInBatchEdit(final int primaryCode, final int x, final int y, final int spaceState, final InputConnection ic) { boolean isComposingWord = mWordComposer.isComposingWord(); @@ -1541,7 +1593,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } } if (isComposingWord) { - mWordComposer.add(primaryCode, keyCodes, x, y); + mWordComposer.add( + primaryCode, x, y, mKeyboardSwitcher.getKeyboardView().getKeyDetector()); if (ic != null) { // If it's the first letter, make note of auto-caps state if (mWordComposer.size() == 1) { @@ -1893,6 +1946,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mVoiceProxy.flushAndLogAllTextModificationCounters(index, suggestion, mSettingsValues.mWordSeparators); + if (SPACE_STATE_PHANTOM == mSpaceState && suggestion.length() > 0) { + int firstChar = Character.codePointAt(suggestion, 0); + if ((!mSettingsValues.isWeakSpaceStripper(firstChar)) + && (!mSettingsValues.isWeakSpaceSwapper(firstChar))) { + sendKeyCodePoint(Keyboard.CODE_SPACE); + } + } + if (mInputAttributes.mApplicationSpecifiedCompletionOn && mApplicationSpecifiedCompletions != null && index >= 0 && index < mApplicationSpecifiedCompletions.length) { @@ -1916,7 +1977,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar LatinImeLogger.logOnManualSuggestion("", suggestion.toString(), index, suggestedWords); // Rely on onCodeInput to do the complicated swapping/stripping logic consistently. final int primaryCode = suggestion.charAt(0); - onCodeInput(primaryCode, new int[] { primaryCode }, + onCodeInput(primaryCode, KeyboardActionListener.SUGGESTION_STRIP_COORDINATE, KeyboardActionListener.SUGGESTION_STRIP_COORDINATE); return; @@ -2162,7 +2223,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final String originallyTypedWord = mLastComposedWord.mTypedWord; final CharSequence committedWord = mLastComposedWord.mCommittedWord; final int cancelLength = committedWord.length(); - final int separatorLength = mLastComposedWord.getSeparatorLength( + final int separatorLength = LastComposedWord.getSeparatorLength( mLastComposedWord.mSeparatorCode); // TODO: should we check our saved separator against the actual contents of the text view? if (DEBUG) { @@ -2264,6 +2325,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } initSuggest(); loadSettings(); + // Since we just changed languages, we should re-evaluate suggestions with whatever word + // we are currently composing. If we are not composing anything, we may want to display + // predictions or punctuation signs (which is done by updateBigramPredictions anyway). + if (isCursorTouchingWord()) { + mHandler.postUpdateSuggestions(); + } else { + mHandler.postUpdateBigramPredictions(); + } } public void hapticAndAudioFeedback(int primaryCode) { diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java index 3029057be..305cef22d 100644 --- a/java/src/com/android/inputmethod/latin/Settings.java +++ b/java/src/com/android/inputmethod/latin/Settings.java @@ -43,7 +43,6 @@ import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; import com.android.inputmethod.compat.CompatUtils; -import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; import com.android.inputmethod.compat.InputMethodServiceCompatWrapper; import com.android.inputmethod.compat.VibratorCompatWrapper; import com.android.inputmethod.deprecated.VoiceProxy; @@ -73,6 +72,10 @@ public class Settings extends InputMethodSettingsActivity public static final String PREF_MISC_SETTINGS = "misc_settings"; public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; public static final String PREF_ADVANCED_SETTINGS = "pref_advanced_settings"; + public static final String PREF_SUPPRESS_LANGUAGE_SWITCH_KEY = + "pref_suppress_language_switch_key"; + public static final String PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST = + "pref_include_other_imes_in_language_switch_list"; public static final String PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY = "pref_key_preview_popup_dismiss_delay"; public static final String PREF_KEY_USE_CONTACTS_DICT = "pref_key_use_contacts_dict"; @@ -204,6 +207,11 @@ public class Settings extends InputMethodSettingsActivity } } + final CheckBoxPreference includeOtherImesInLanguageSwitchList = + (CheckBoxPreference)findPreference(PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST); + includeOtherImesInLanguageSwitchList.setEnabled( + !SettingsValues.isLanguageSwitchKeySupressed(prefs)); + mKeyPreviewPopupDismissDelay = (ListPreference)findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY); final String[] entries = new String[] { @@ -316,6 +324,12 @@ public class Settings extends InputMethodSettingsActivity if (null != popupDismissDelay) { popupDismissDelay.setEnabled(prefs.getBoolean(PREF_POPUP_ON, true)); } + } else if (key.equals(PREF_SUPPRESS_LANGUAGE_SWITCH_KEY)) { + final CheckBoxPreference includeOtherImesInLanguageSwicthList = + (CheckBoxPreference)findPreference( + PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST); + includeOtherImesInLanguageSwicthList.setEnabled( + !SettingsValues.isLanguageSwitchKeySupressed(prefs)); } ensureConsistencyOfAutoCorrectionSettings(); mVoiceOn = !(prefs.getString(PREF_VOICE_MODE, mVoiceModeOff) diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java index 6d65a74c8..69e45f619 100644 --- a/java/src/com/android/inputmethod/latin/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -23,11 +23,14 @@ import android.os.Build; import android.util.Log; import android.view.inputmethod.EditorInfo; +import com.android.inputmethod.compat.InputMethodInfoCompatWrapper; import com.android.inputmethod.compat.InputTypeCompatUtils; import com.android.inputmethod.compat.VibratorCompatWrapper; import com.android.inputmethod.keyboard.internal.KeySpecParser; import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.Locale; public class SettingsValues { @@ -55,6 +58,8 @@ public class SettingsValues { public final String mShowSuggestionsSetting; @SuppressWarnings("unused") // TODO: Use this private final boolean mUsabilityStudyMode; + public final boolean mIncludesOtherImesInLanguageSwitchList; + public final boolean mIsLanguageSwitchKeySuppressed; @SuppressWarnings("unused") // TODO: Use this private final String mKeyPreviewPopupDismissDelayRawValue; public final boolean mUseContactsDict; @@ -127,6 +132,9 @@ public class SettingsValues { mShowSuggestionsSetting = prefs.getString(Settings.PREF_SHOW_SUGGESTIONS_SETTING, res.getString(R.string.prefs_suggestion_visibility_default_value)); mUsabilityStudyMode = getUsabilityStudyMode(prefs); + mIncludesOtherImesInLanguageSwitchList = prefs.getBoolean( + Settings.PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST, false); + mIsLanguageSwitchKeySuppressed = isLanguageSwitchKeySupressed(prefs); mKeyPreviewPopupDismissDelayRawValue = prefs.getString( Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, Integer.toString(res.getInteger(R.integer.config_key_preview_linger_timeout))); @@ -309,6 +317,22 @@ public class SettingsValues { return mVoiceKeyOnMain; } + public static boolean isLanguageSwitchKeySupressed(SharedPreferences sp) { + return sp.getBoolean(Settings.PREF_SUPPRESS_LANGUAGE_SWITCH_KEY, false); + } + + public boolean isLanguageSwitchKeyEnabled(Context context) { + if (mIsLanguageSwitchKeySuppressed) { + return false; + } + if (mIncludesOtherImesInLanguageSwitchList) { + return Utils.hasMultipleEnabledIMEsOrSubtypes(/* include aux subtypes */false); + } else { + return Utils.hasMultipleEnabledSubtypesInThisIme( + context, /* include aux subtypes */false); + } + } + public boolean isFullscreenModeAllowed(Resources res) { return res.getBoolean(R.bool.config_use_fullscreen_mode); } diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index f6e177aaf..298ead665 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -323,7 +323,6 @@ public class Suggest implements Dictionary.WordCallback { } } else { // Word entered: return only bigrams that match the first char of the typed word - @SuppressWarnings("null") final char currentChar = consideredWord.charAt(0); // TODO: Must pay attention to locale when changing case. final char currentCharUpper = Character.toUpperCase(currentChar); diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java index 33d4b877e..a8679e07a 100644 --- a/java/src/com/android/inputmethod/latin/Utils.java +++ b/java/src/com/android/inputmethod/latin/Utils.java @@ -52,6 +52,7 @@ import java.io.PrintWriter; import java.nio.channels.FileChannel; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Locale; @@ -117,16 +118,51 @@ public class Utils { } } + // TODO: Move InputMethodSubtype related utility methods to its own utility class. + // TODO: Cache my InputMethodInfo and/or InputMethodSubtype list. + public static boolean checkIfSubtypeBelongsToThisIme(Context context, + InputMethodSubtypeCompatWrapper ims) { + final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); + if (imm == null) return false; + + final InputMethodInfoCompatWrapper myImi = Utils.getInputMethodInfo( + context.getPackageName()); + final List<InputMethodSubtypeCompatWrapper> subtypes = + imm.getEnabledInputMethodSubtypeList(myImi, true); + for (final InputMethodSubtypeCompatWrapper subtype : subtypes) { + if (subtype.equals(ims)) { + return true; + } + } + return false; + } + public static boolean hasMultipleEnabledIMEsOrSubtypes( final boolean shouldIncludeAuxiliarySubtypes) { final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); if (imm == null) return false; + final List<InputMethodInfoCompatWrapper> enabledImis = imm.getEnabledInputMethodList(); + return hasMultipleEnabledSubtypes(shouldIncludeAuxiliarySubtypes, enabledImis); + } + + public static boolean hasMultipleEnabledSubtypesInThisIme(Context context, + final boolean shouldIncludeAuxiliarySubtypes) { + final InputMethodInfoCompatWrapper myImi = Utils.getInputMethodInfo( + context.getPackageName()); + final List<InputMethodInfoCompatWrapper> imiList = Collections.singletonList(myImi); + return Utils.hasMultipleEnabledSubtypes(shouldIncludeAuxiliarySubtypes, imiList); + } + + private static boolean hasMultipleEnabledSubtypes(final boolean shouldIncludeAuxiliarySubtypes, + List<InputMethodInfoCompatWrapper> imiList) { + final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); + if (imm == null) return false; // Number of the filtered IMEs int filteredImisCount = 0; - for (InputMethodInfoCompatWrapper imi : enabledImis) { + for (InputMethodInfoCompatWrapper imi : imiList) { // We can return true immediately after we find two or more filtered IMEs. if (filteredImisCount > 1) return true; final List<InputMethodSubtypeCompatWrapper> subtypes = @@ -564,6 +600,7 @@ public class Utils { } } + // TODO: Move this method to KeyboardSet class. public static int getKeyboardMode(EditorInfo editorInfo) { if (editorInfo == null) return KeyboardId.MODE_TEXT; diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index 8121ada7f..3324a3793 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -19,6 +19,9 @@ package com.android.inputmethod.latin; import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.keyboard.KeyboardActionListener; +import com.android.inputmethod.latin.spellcheck.AndroidSpellCheckerService; +import com.android.inputmethod.latin.spellcheck.SpellCheckerProximityInfo; import java.util.ArrayList; import java.util.Arrays; @@ -119,19 +122,66 @@ public class WordComposer { return previous && !Character.isUpperCase(codePoint); } + // TODO: remove input keyDetector + public void add(int primaryCode, int x, int y, KeyDetector keyDetector) { + final int[] codes; + final int keyX; + final int keyY; + if (x == KeyboardActionListener.SPELL_CHECKER_COORDINATE + || y == KeyboardActionListener.SPELL_CHECKER_COORDINATE) { + // only used for tests in InputLogicTests + addKeyForSpellChecker(primaryCode, AndroidSpellCheckerService.SCRIPT_LATIN); + return; + } else if (x == KeyboardActionListener.SUGGESTION_STRIP_COORDINATE + || y == KeyboardActionListener.SUGGESTION_STRIP_COORDINATE + || x == KeyboardActionListener.NOT_A_TOUCH_COORDINATE + || y == KeyboardActionListener.NOT_A_TOUCH_COORDINATE) { + codes = new int[] { primaryCode }; + keyX = x; + keyY = y; + } else { + codes = keyDetector.newCodeArray(); + keyDetector.getKeyAndNearbyCodes(x, y, codes); + keyX = keyDetector.getTouchX(x); + keyY = keyDetector.getTouchX(y); + } + add(primaryCode, codes, keyX, keyY); + } + + // TODO: remove this function + public void addKeyForSpellChecker(int primaryCode, int script) { + final int[] proximities; + final int proximityIndex = + SpellCheckerProximityInfo.getIndexOfCodeForScript(primaryCode, script); + if (-1 == proximityIndex) { + proximities = new int[] { primaryCode }; + } else { + // TODO: an initial examination seems to reveal this is actually used + // read-only. It should be possible to compute the arrays statically once + // and skip doing a copy each time here. + proximities = Arrays.copyOfRange( + SpellCheckerProximityInfo.getProximityForScript(script), + proximityIndex, + proximityIndex + SpellCheckerProximityInfo.ROW_SIZE); + } + add(primaryCode, proximities, + KeyboardActionListener.NOT_A_TOUCH_COORDINATE, + KeyboardActionListener.NOT_A_TOUCH_COORDINATE); + } + /** * Add a new keystroke, with codes[0] containing the pressed key's unicode and the rest of * the array containing unicode for adjacent keys, sorted by reducing probability/proximity. * @param codes the array of unicode values */ - public void add(int primaryCode, int[] codes, int x, int y) { + private void add(int primaryCode, int[] codes, int keyX, int keyY) { final int newIndex = mCodes.size(); mTypedWord.appendCodePoint(primaryCode); correctPrimaryJuxtapos(primaryCode, codes); mCodes.add(codes); if (newIndex < BinaryDictionary.MAX_WORD_LENGTH) { - mXCoordinates[newIndex] = x; - mYCoordinates[newIndex] = y; + mXCoordinates[newIndex] = keyX; + mYCoordinates[newIndex] = keyY; } mIsFirstCharCapitalized = isFirstCharCapitalized( newIndex, primaryCode, mIsFirstCharCapitalized); diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 8ac82ee5b..755c75b2e 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -570,23 +570,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService final WordComposer composer = new WordComposer(); final int length = text.length(); for (int i = 0; i < length; i = text.offsetByCodePoints(i, 1)) { - final int character = text.codePointAt(i); - final int proximityIndex = - SpellCheckerProximityInfo.getIndexOfCodeForScript(character, mScript); - final int[] proximities; - if (-1 == proximityIndex) { - proximities = new int[] { character }; - } else { - // TODO: an initial examination seems to reveal this is actually used - // read-only. It should be possible to compute the arrays statically once - // and skip doing a copy each time here. - proximities = Arrays.copyOfRange( - SpellCheckerProximityInfo.getProximityForScript(mScript), - proximityIndex, - proximityIndex + SpellCheckerProximityInfo.ROW_SIZE); - } - composer.add(character, proximities, - WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); + composer.addKeyForSpellChecker(text.codePointAt(i), mScript); } final int capitalizeType = getCapitalizationType(text); diff --git a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java index cd83c3e21..1f7214777 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestionsView.java @@ -66,7 +66,7 @@ public class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel { } @Override - public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { + public void onCodeInput(int primaryCode, int x, int y) { final int index = primaryCode - MoreSuggestions.SUGGESTION_CODE_BASE; if (index >= 0 && index < SuggestionsView.MAX_SUGGESTIONS) { mListener.onCustomRequest(index); diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java index d3362940f..075fb68ee 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java @@ -137,7 +137,8 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, public final int mDividerWidth; public final int mSuggestionsStripHeight; public final int mSuggestionsCountInStrip; - public final int mMaxMoreSuggestionsRow; + public final int mMoreSuggestionsRowHeight; + private int mMaxMoreSuggestionsRow; public final float mMinMoreSuggestionsWidth; public final int mMoreSuggestionsBottomGap; @@ -225,12 +226,34 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, mCenterSuggestionIndex = mSuggestionsCountInStrip / 2; mMoreSuggestionsBottomGap = res.getDimensionPixelOffset( R.dimen.more_suggestions_bottom_gap); + mMoreSuggestionsRowHeight = res.getDimensionPixelSize( + R.dimen.more_suggestions_row_height); final LayoutInflater inflater = LayoutInflater.from(context); mWordToSaveView = (TextView)inflater.inflate(R.layout.suggestion_word, null); mHintToSaveView = (TextView)inflater.inflate(R.layout.suggestion_word, null); } + public int getMaxMoreSuggestionsRow() { + return mMaxMoreSuggestionsRow; + } + + private int getMoreSuggestionsHeight() { + return mMaxMoreSuggestionsRow * mMoreSuggestionsRowHeight + mMoreSuggestionsBottomGap; + } + + public int setMoreSuggestionsHeight(int remainingHeight) { + final int currentHeight = getMoreSuggestionsHeight(); + if (currentHeight <= remainingHeight) { + return currentHeight; + } + + mMaxMoreSuggestionsRow = (remainingHeight - mMoreSuggestionsBottomGap) + / mMoreSuggestionsRowHeight; + final int newHeight = getMoreSuggestionsHeight(); + return newHeight; + } + private static Drawable getMoreSuggestionsHint(Resources res, float textSize, int color) { final Paint paint = new Paint(); paint.setAntiAlias(true); @@ -645,6 +668,9 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, mParams.layout(mSuggestedWords, mSuggestionsStrip, this, getWidth()); } + public int setMoreSuggestionsHeight(int remainingHeight) { + return mParams.setMoreSuggestionsHeight(remainingHeight); + } public boolean isShowingAddToDictionaryHint() { return mSuggestionsStrip.getChildCount() > 0 @@ -735,7 +761,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, final MoreSuggestions.Builder builder = mMoreSuggestionsBuilder; builder.layout(mSuggestedWords, params.mSuggestionsCountInStrip, maxWidth, (int)(maxWidth * params.mMinMoreSuggestionsWidth), - params.mMaxMoreSuggestionsRow); + params.getMaxMoreSuggestionsRow()); mMoreSuggestionsView.setKeyboard(builder.build()); container.measure( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); |