From 81d4e3cd66a9388c47c7dba55240ddf849b31934 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 17 Feb 2012 17:46:01 -0800 Subject: [PATCH] Add language switch key only to the phone layouts Bug: 5759092 Change-Id: Ic7d7d4812976654c0e85fecabd1128eadfc52c5c --- .../sym_keyboard_language_switch.png | Bin 0 -> 2093 bytes .../sym_keyboard_language_switch.png | Bin 0 -> 1290 bytes java/res/values/attrs.xml | 3 ++ java/res/values/keyboard-icons-black.xml | 2 + java/res/values/keyboard-icons-ics.xml | 1 + java/res/values/keyboard-icons-white.xml | 1 + java/res/values/keycodes.xml | 3 +- java/res/values/strings.xml | 7 ++++ java/res/xml/key_styles_common.xml | 8 ++-- java/res/xml/prefs.xml | 11 +++++ java/res/xml/row_qwerty4.xml | 20 +++++++-- .../InputMethodManagerCompatWrapper.java | 21 ++++++++++ .../inputmethod/keyboard/Keyboard.java | 15 +++++-- .../inputmethod/keyboard/KeyboardId.java | 9 +++- .../inputmethod/keyboard/KeyboardSet.java | 7 +++- .../keyboard/KeyboardSwitcher.java | 3 +- .../keyboard/LatinKeyboardView.java | 7 +++- .../keyboard/internal/KeyboardIconsSet.java | 3 +- .../android/inputmethod/latin/LatinIME.java | 27 ++++++++++++ .../android/inputmethod/latin/Settings.java | 16 ++++++- .../inputmethod/latin/SettingsValues.java | 24 +++++++++++ .../com/android/inputmethod/latin/Utils.java | 39 +++++++++++++++++- 22 files changed, 206 insertions(+), 21 deletions(-) create mode 100644 java/res/drawable-hdpi/sym_keyboard_language_switch.png create mode 100644 java/res/drawable-mdpi/sym_keyboard_language_switch.png diff --git a/java/res/drawable-hdpi/sym_keyboard_language_switch.png b/java/res/drawable-hdpi/sym_keyboard_language_switch.png new file mode 100644 index 0000000000000000000000000000000000000000..fa747642d9d91642bf56f769150e095fa372b542 GIT binary patch literal 2093 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 + @@ -296,6 +297,7 @@ + @@ -361,6 +363,7 @@ + diff --git a/java/res/values/keyboard-icons-black.xml b/java/res/values/keyboard-icons-black.xml index 1c5a5f720..44fc2b9c1 100644 --- a/java/res/values/keyboard-icons-black.xml +++ b/java/res/values/keyboard-icons-black.xml @@ -34,5 +34,7 @@ @drawable/sym_bkeyboard_shift_locked @drawable/sym_bkeyboard_voice_off @drawable/sym_keyboard_feedback_tab + + @drawable/sym_keyboard_language_switch diff --git a/java/res/values/keyboard-icons-ics.xml b/java/res/values/keyboard-icons-ics.xml index f68be5f1e..5fba0253d 100644 --- a/java/res/values/keyboard-icons-ics.xml +++ b/java/res/values/keyboard-icons-ics.xml @@ -33,5 +33,6 @@ @drawable/sym_keyboard_shift_locked_holo @drawable/sym_keyboard_voice_off_holo @drawable/sym_keyboard_feedback_tab + @drawable/sym_keyboard_language_switch diff --git a/java/res/values/keyboard-icons-white.xml b/java/res/values/keyboard-icons-white.xml index 35197a1c0..837b1a37a 100644 --- a/java/res/values/keyboard-icons-white.xml +++ b/java/res/values/keyboard-icons-white.xml @@ -31,5 +31,6 @@ @drawable/sym_keyboard_voice_off_holo @drawable/sym_keyboard_feedback_tab + @drawable/sym_keyboard_language_switch diff --git a/java/res/values/keycodes.xml b/java/res/values/keycodes.xml index 7f9e4bda4..d3d9b6324 100644 --- a/java/res/values/keycodes.xml +++ b/java/res/values/keycodes.xml @@ -32,5 +32,6 @@ -7 -8 -9 - -10 + -10 + -11 diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml index d8a3a689e..f2c02d014 100644 --- a/java/res/values/strings.xml +++ b/java/res/values/strings.xml @@ -64,6 +64,13 @@ Options for experts + + Switch to other input methods + + Language switch key covers other input methods too + + Suppress language switch key + Key popup dismiss delay diff --git a/java/res/xml/key_styles_common.xml b/java/res/xml/key_styles_common.xml index 76eacb673..f153a7d96 100644 --- a/java/res/xml/key_styles_common.xml +++ b/java/res/xml/key_styles_common.xml @@ -117,10 +117,10 @@ latin:altCode="@integer/key_space" latin:parentStyle="f1MoreKeysStyle" /> + + - + + + + + + + + + + getEnabledInputMethodSubtypeList( InputMethodInfoCompatWrapper imi, boolean allowsImplicitlySelectedSubtypes) { if (!SUBTYPE_SUPPORTED) { @@ -221,6 +234,14 @@ public class InputMethodManagerCompatWrapper { return (Boolean)CompatUtils.invoke(mImm, false, METHOD_switchToLastInputMethod, token); } + public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) { + if (SubtypeSwitcher.getInstance().isDummyVoiceMode()) { + return true; + } + return (Boolean)CompatUtils.invoke(mImm, false, METHOD_switchToNextInputMethod, token, + onlyCurrentIme); + } + public List getEnabledInputMethodList() { if (mImm == null) return null; List imis = new ArrayList(); diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index c6cdf7986..5660d1942 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -99,8 +99,9 @@ public class Keyboard { public static final int CODE_ACTION_ENTER = -7; public static final int CODE_ACTION_NEXT = -8; public static final int CODE_ACTION_PREVIOUS = -9; + public static final int CODE_LANGUAGE_SWITCH = -10; // Code value representing the code is not specified. - public static final int CODE_UNSPECIFIED = -10; + public static final int CODE_UNSPECIFIED = -11; public final KeyboardId mId; public final int mThemeId; @@ -1076,6 +1077,9 @@ public class Keyboard { R.styleable.Keyboard_Case_shortcutKeyEnabled, id.mShortcutKeyEnabled); final boolean hasShortcutKeyMatched = matchBoolean(a, R.styleable.Keyboard_Case_hasShortcutKey, id.mHasShortcutKey); + final boolean languageSwitchKeyEnabledMatched = matchBoolean(a, + R.styleable.Keyboard_Case_languageSwitchKeyEnabled, + id.mLanguageSwitchKeyEnabled); final boolean isMultiLineMatched = matchBoolean(a, R.styleable.Keyboard_Case_isMultiLine, id.isMultiLine()); final boolean imeActionMatched = matchInteger(a, @@ -1089,11 +1093,12 @@ public class Keyboard { final boolean selected = keyboardSetElementMatched && modeMatched && navigateNextMatched && navigatePreviousMatched && passwordInputMatched && clobberSettingsKeyMatched && shortcutKeyEnabledMatched - && hasShortcutKeyMatched && isMultiLineMatched && imeActionMatched - && localeCodeMatched && languageCodeMatched && countryCodeMatched; + && hasShortcutKeyMatched && languageSwitchKeyEnabledMatched + && isMultiLineMatched && imeActionMatched && localeCodeMatched + && languageCodeMatched && countryCodeMatched; if (DEBUG) { - startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE, + startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE, textAttr(a.getString(R.styleable.Keyboard_Case_keyboardSetElement), "keyboardSetElement"), textAttr(a.getString(R.styleable.Keyboard_Case_mode), "mode"), @@ -1111,6 +1116,8 @@ public class Keyboard { "shortcutKeyEnabled"), booleanAttr(a, R.styleable.Keyboard_Case_hasShortcutKey, "hasShortcutKey"), + booleanAttr(a, R.styleable.Keyboard_Case_languageSwitchKeyEnabled, + "languageSwitchKeyEnabled"), booleanAttr(a, R.styleable.Keyboard_Case_isMultiLine, "isMultiLine"), textAttr(a.getString(R.styleable.Keyboard_Case_localeCode), diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java index f5752962e..6703b9301 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java @@ -62,13 +62,14 @@ public class KeyboardId { public final boolean mClobberSettingsKey; public final boolean mShortcutKeyEnabled; public final boolean mHasShortcutKey; + public final boolean mLanguageSwitchKeyEnabled; public final String mCustomActionLabel; private final int mHashCode; public KeyboardId(int elementId, Locale locale, int orientation, int width, int mode, EditorInfo editorInfo, boolean clobberSettingsKey, boolean shortcutKeyEnabled, - boolean hasShortcutKey) { + boolean hasShortcutKey, boolean languageSwitchKeyEnabled) { this.mLocale = locale; this.mOrientation = orientation; this.mWidth = width; @@ -78,6 +79,7 @@ public class KeyboardId { this.mClobberSettingsKey = clobberSettingsKey; this.mShortcutKeyEnabled = shortcutKeyEnabled; this.mHasShortcutKey = hasShortcutKey; + this.mLanguageSwitchKeyEnabled = languageSwitchKeyEnabled; this.mCustomActionLabel = (editorInfo.actionLabel != null) ? editorInfo.actionLabel.toString() : null; @@ -94,6 +96,7 @@ public class KeyboardId { id.mClobberSettingsKey, id.mShortcutKeyEnabled, id.mHasShortcutKey, + id.mLanguageSwitchKeyEnabled, id.isMultiLine(), id.imeAction(), id.mCustomActionLabel, @@ -114,6 +117,7 @@ public class KeyboardId { && other.mClobberSettingsKey == this.mClobberSettingsKey && other.mShortcutKeyEnabled == this.mShortcutKeyEnabled && other.mHasShortcutKey == this.mHasShortcutKey + && other.mLanguageSwitchKeyEnabled == this.mLanguageSwitchKeyEnabled && other.isMultiLine() == this.isMultiLine() && other.imeAction() == this.imeAction() && TextUtils.equals(other.mCustomActionLabel, this.mCustomActionLabel) @@ -172,7 +176,7 @@ public class KeyboardId { @Override public String toString() { - return String.format("[%s %s %s%d %s %s %s%s%s%s%s%s%s]", + return String.format("[%s %s %s%d %s %s %s%s%s%s%s%s%s%s]", elementIdToName(mElementId), mLocale, (mOrientation == 1 ? "port" : "land"), mWidth, @@ -184,6 +188,7 @@ public class KeyboardId { (passwordInput() ? " passwordInput" : ""), (mShortcutKeyEnabled ? " shortcutKeyEnabled" : ""), (mHasShortcutKey ? " hasShortcutKey" : ""), + (mLanguageSwitchKeyEnabled ? " languageSwitchKeyEnabled" : ""), (isMultiLine() ? "isMultiLine" : "") ); } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java index ee882edc0..731aaf7c5 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java @@ -101,6 +101,7 @@ public class KeyboardSet { boolean mVoiceKeyEnabled; boolean mVoiceKeyOnMain; boolean mNoSettingsKey; + boolean mLanguageSwitchKeyEnabled; Locale mLocale; int mOrientation; int mWidth; @@ -196,7 +197,7 @@ public class KeyboardSet { && (isSymbols != params.mVoiceKeyOnMain); return new KeyboardId(keyboardSetElementId, params.mLocale, params.mOrientation, params.mWidth, params.mMode, params.mEditorInfo, params.mNoSettingsKey, - params.mVoiceKeyEnabled, hasShortcutKey); + params.mVoiceKeyEnabled, hasShortcutKey, params.mLanguageSwitchKeyEnabled); } public static class Builder { @@ -239,7 +240,8 @@ public class KeyboardSet { return this; } - public Builder setOptions(boolean voiceKeyEnabled, boolean voiceKeyOnMain) { + public Builder setOptions(boolean voiceKeyEnabled, boolean voiceKeyOnMain, + boolean languageSwitchKeyEnabled) { @SuppressWarnings("deprecation") final boolean deprecatedNoMicrophone = Utils.inPrivateImeOptions( null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, mEditorInfo); @@ -248,6 +250,7 @@ public class KeyboardSet { || deprecatedNoMicrophone; mParams.mVoiceKeyEnabled = voiceKeyEnabled && !noMicrophone; mParams.mVoiceKeyOnMain = voiceKeyOnMain; + mParams.mLanguageSwitchKeyEnabled = languageSwitchKeyEnabled; return this; } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index e1c6f2604..ac8dd1b95 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -133,7 +133,8 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, LatinIME.SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION)); builder.setOptions( settingsValues.isVoiceKeyEnabled(editorInfo), - settingsValues.isVoiceKeyOnMain()); + settingsValues.isVoiceKeyOnMain(), + settingsValues.isLanguageSwitchKeyEnabled(mThemeContext)); mKeyboardSet = builder.build(); try { mState.onLoadKeyboard(mResources.getString(R.string.layout_switch_back_symbols)); diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 78c371ff0..afc4932e9 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -489,7 +489,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke KeyboardSwitcher.getInstance().hapticAndAudioFeedback(primaryCode); return true; } - if (primaryCode == Keyboard.CODE_SPACE) { + if (primaryCode == Keyboard.CODE_SPACE || primaryCode == Keyboard.CODE_LANGUAGE_SWITCH) { // Long pressing the space key invokes IME switcher dialog. if (invokeCustomRequest(LatinIME.CODE_SHOW_INPUT_METHOD_PICKER)) { tracker.onLongPressed(); @@ -782,6 +782,11 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke && Utils.hasMultipleEnabledIMEsOrSubtypes(true /* include aux subtypes */)) { drawKeyPopupHint(key, canvas, paint, params); } + } else if (key.mCode == Keyboard.CODE_LANGUAGE_SWITCH) { + super.onDrawKeyTopVisuals(key, canvas, paint, params); + if (Utils.hasMultipleEnabledIMEsOrSubtypes(true /* include aux subtypes */)) { + drawKeyPopupHint(key, canvas, paint, params); + } } else { super.onDrawKeyTopVisuals(key, canvas, paint, params); } diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java index 7c8fd1225..ca711ec7d 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java @@ -31,7 +31,7 @@ public class KeyboardIconsSet { // The value should be aligned with the enum value of Key.keyIcon. public static final int ICON_UNDEFINED = 0; - private static final int NUM_ICONS = 13; + private static final int NUM_ICONS = 14; private final Drawable[] mIcons = new Drawable[NUM_ICONS + 1]; @@ -57,6 +57,7 @@ public class KeyboardIconsSet { addIconIdMap(11, "shiftKeyShifted", R.styleable.Keyboard_iconShiftKeyShifted); addIconIdMap(12, "disabledShortcurKey", R.styleable.Keyboard_iconDisabledShortcutKey); addIconIdMap(13, "previewTabKey", R.styleable.Keyboard_iconPreviewTabKey); + addIconIdMap(14, "languageSwitchKey", R.styleable.Keyboard_iconLanguageSwitchKey); } private static void addIconIdMap(int iconId, String name, int attrId) { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 2bcd947f1..cb22b4935 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -29,6 +29,7 @@ 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; @@ -55,6 +56,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; @@ -196,6 +198,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private KeyboardSwitcher mKeyboardSwitcher; private SubtypeSwitcher mSubtypeSwitcher; private VoiceProxy mVoiceProxy; + private boolean mShouldSwitchToLastSubtype = true; private UserDictionary mUserDictionary; private UserBigramDictionary mUserBigramDictionary; @@ -1263,6 +1266,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)}. @@ -1306,6 +1328,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar handleBackspace(spaceState); mDeleteCount++; mExpectingUpdateSelection = true; + mShouldSwitchToLastSubtype = true; LatinImeLogger.logOnDelete(); break; case Keyboard.CODE_SHIFT: @@ -1327,6 +1350,9 @@ 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)) { @@ -1335,6 +1361,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar handleCharacter(primaryCode, x, y, spaceState); } mExpectingUpdateSelection = true; + mShouldSwitchToLastSubtype = true; break; } switcher.onCodeInput(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/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 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 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 imiList = Collections.singletonList(myImi); + return Utils.hasMultipleEnabledSubtypes(shouldIncludeAuxiliarySubtypes, imiList); + } + + private static boolean hasMultipleEnabledSubtypes(final boolean shouldIncludeAuxiliarySubtypes, + List 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 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;