From 81d4e3cd66a9388c47c7dba55240ddf849b31934 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" <takaoka@google.com> 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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 X*b7b0w?%ow00000NkvXXu0mjf-jC-! literal 0 HcmV?d00001 diff --git a/java/res/drawable-mdpi/sym_keyboard_language_switch.png b/java/res/drawable-mdpi/sym_keyboard_language_switch.png new file mode 100644 index 0000000000000000000000000000000000000000..f30c1b640ab60b07865cec8340143a7b1d9303ff GIT binary patch literal 1290 zcmV+l1@-!gP)<h;3K|Lk000e1NJLTq000;O001Hg1^@s6MV1*e0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU$tVu*cRCwC#R%=X~RT%Equ5#JNz*1KT zgTlf(3lyXv7$CtAm;?;+(}YU6Mo5+zLO>XQxNGn?AV~JZkQgojG29GfjLQZQ5IZs4 zf(1j1Yyt{nqm_O>FF7BnRh*hE{Mnm4Ip25A`QF=kpZ9zm&-0?^DPqxcmKO%j-T?P6 z)+N9>24VjZ@H-o=0RLYNP-IfzJa7TH2skn$q|6K)0DHhb@RS+kpJhPsm=wzZkHEk{ zKb=k&saC6ftyZg;<2ZgFGCVx|T}w;L4EC6SpMhQAkVSNAG*YHm1I1}WLqlUvAp9w^ zy}i9tTU%R?{ci$F=Gdv{O5wi@XtT1iZqdiK%1TN~z8D`L|F*fgd4NXSwaLlJZ}8n) zfG^<mcd6%CuGQJu*`<Qlq^Q5Y|9)Fr+a0Xk>hA6y%+JsN)Z5$pBXWR@3XU)%aeybw z#GlHPymtk>%gf7eIzo1Kc6JL33-4+)8f8&Y(FoQaVfv}Fv-95i`nsvJvvbPN&(9U- zaF-NBL_~x&Ha6<;r~sVpqag1?nwpw!lQ&CCOF!1t)pgTI(ag`!>-+lpzA_jLi!(Db z_eMrW?wCxb4O*iJDH8gQ-l6Ah;0km4q_)YTdvbE}4Vuiz$mp1um{?XSl?NF2J32b_ zTCG;@>FMbT?+w$_(`&J@v7c>iZPg|wCN|)cOG!yds;H=_5S-CFIXO9NnEQoFSIpAn zgsSl%F&d4VP-?{7V>dT92Y7Al?d>&IR8;7p@DU;~R99C&ATI3g?mmQ5#F4$$)>b+L z5mFk&cq0|gfZ&jll5(9U^m@I4MI~0LRO<Hjb_1*JqvL7-4+I9o_*!Ua=qohe(9p0- zqf91qw;|<8io_rh#}4cI^78UcsZ?r_%jI4J0|Os2r6Ly>7kNlXh!!b05Z;4>gTs*0 zLyN_7tPn@RF{e3^4fT&C63MZLQ&Uq5$ZI=Q&En$X2L%NMw<$&R0gUNJM@PS}si~n9 zSqBFP-$f}usI06s`1ttvBBC;z2zenz^m15LRW-wMs1!V)6u{%lHqB1(klKm#RR~h} z6TPRUrCp_U6al?cHCb#UppbuEg`l?ma&vP7P_nZiktI4hI;ga?RP68X?+$$`g+d{N z5iuEZaBw)ku&_V|FQ%ubzd;ITXJ_Xy{3aNX*f7~KC@4sQLwgM+sfdh>lqV!4L_x92 zY&KI9<D8tFUfSH;-1hSF@`#Cvc^$r7O-)Vp$9`FSe0&&@GcGRfW9(gHMot=^lu<l> zWo2cRNVBoAVG>#b_)w0u_i+Yag596sxq#XSk&z(uq~hXYQm$cT%GviK>V*CQ0Riuk za)HsLh}ep?vaYVKuk-TqngqkNCiJbIo}PZ}i2;N&`-@PzT&UrJbUML^Af$|%AC2~F zAXx`%*;g0`PQ59~$R*$!aHGDy{&V}bZ7Xwgb3bHeW|m<u9k3T`)#7JenG)uO8$c|* zjQb%pJUsjwdXb#!d~9rN9^60=oL^(N*+X`Hn(ePm?jLTqbIi~M24_|bR(1zJX7}+E zo2!!lKYta1F$n{2_gBG-&QiD+f7fSj;12-?0Mx{!nGZz|r~m)}07*qoM6N<$f@#2H A-v9sr literal 0 HcmV?d00001 diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml index a5d590e04d..7758074208 100644 --- a/java/res/values/attrs.xml +++ b/java/res/values/attrs.xml @@ -216,6 +216,7 @@ <attr name="iconShiftKeyShifted" format="reference" /> <attr name="iconDisabledShortcutKey" format="reference" /> <attr name="iconPreviewTabKey" format="reference" /> + <attr name="iconLanguageSwitchKey" format="reference" /> </declare-styleable> <declare-styleable name="Keyboard_Key"> @@ -296,6 +297,7 @@ <enum name="iconShortcutForLabel" value="9" /> <enum name="iconSpaceKeyForNumberLayout" value="10" /> <enum name="iconShiftKeyShifted" value="11" /> + <enum name="iconLanguageSwitchKey" value="14" /> </attr> <!-- The icon for disabled key --> <attr name="keyIconDisabled" format="enum"> @@ -361,6 +363,7 @@ <attr name="clobberSettingsKey" format="boolean" /> <attr name="shortcutKeyEnabled" format="boolean" /> <attr name="hasShortcutKey" format="boolean" /> + <attr name="languageSwitchKeyEnabled" format="boolean" /> <attr name="isMultiLine" format="boolean" /> <attr name="imeAction" format="enum"> <!-- This should be aligned with EditorInfo.IME_ACTION_* --> diff --git a/java/res/values/keyboard-icons-black.xml b/java/res/values/keyboard-icons-black.xml index 1c5a5f720a..44fc2b9c12 100644 --- a/java/res/values/keyboard-icons-black.xml +++ b/java/res/values/keyboard-icons-black.xml @@ -34,5 +34,7 @@ <item name="iconShiftKeyShifted">@drawable/sym_bkeyboard_shift_locked</item> <item name="iconDisabledShortcutKey">@drawable/sym_bkeyboard_voice_off</item> <item name="iconPreviewTabKey">@drawable/sym_keyboard_feedback_tab</item> + <!-- TODO: Needs dedicated black theme globe icon --> + <item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch</item> </style> </resources> diff --git a/java/res/values/keyboard-icons-ics.xml b/java/res/values/keyboard-icons-ics.xml index f68be5f1e8..5fba0253db 100644 --- a/java/res/values/keyboard-icons-ics.xml +++ b/java/res/values/keyboard-icons-ics.xml @@ -33,5 +33,6 @@ <item name="iconShiftKeyShifted">@drawable/sym_keyboard_shift_locked_holo</item> <item name="iconDisabledShortcutKey">@drawable/sym_keyboard_voice_off_holo</item> <item name="iconPreviewTabKey">@drawable/sym_keyboard_feedback_tab</item> + <item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch</item> </style> </resources> diff --git a/java/res/values/keyboard-icons-white.xml b/java/res/values/keyboard-icons-white.xml index 35197a1c01..837b1a37ac 100644 --- a/java/res/values/keyboard-icons-white.xml +++ b/java/res/values/keyboard-icons-white.xml @@ -31,5 +31,6 @@ <!-- TODO: Needs non-holo disabled shortcut icon drawable --> <item name="iconDisabledShortcutKey">@drawable/sym_keyboard_voice_off_holo</item> <item name="iconPreviewTabKey">@drawable/sym_keyboard_feedback_tab</item> + <item name="iconLanguageSwitchKey">@drawable/sym_keyboard_language_switch</item> </style> </resources> diff --git a/java/res/values/keycodes.xml b/java/res/values/keycodes.xml index 7f9e4bda48..d3d9b63244 100644 --- a/java/res/values/keycodes.xml +++ b/java/res/values/keycodes.xml @@ -32,5 +32,6 @@ <integer name="key_action_enter">-7</integer> <integer name="key_action_next">-8</integer> <integer name="key_action_previous">-9</integer> - <integer name="key_unspecified">-10</integer> + <integer name="key_language_switch">-10</integer> + <integer name="key_unspecified">-11</integer> </resources> diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml index d8a3a689ec..f2c02d014e 100644 --- a/java/res/values/strings.xml +++ b/java/res/values/strings.xml @@ -64,6 +64,13 @@ <!-- Option summary for advanced settings screen [CHAR LIMIT=65 (two lines) or 30 (fits on one line, preferable)] --> <string name="advanced_settings_summary">Options for experts</string> + <!-- Option name for including other IMEs in the language switch list [CHAR LIMIT=25] --> + <string name="include_other_imes_in_language_switch_list">Switch to other input methods</string> + <!-- Option summary for including other IMEs in the language switch list [CHAR LIMIT=65] --> + <string name="include_other_imes_in_language_switch_list_summary">Language switch key covers other input methods too</string> + <!-- Option to suppress language switch key [CHAR LIMIT=25] --> + <string name="suppress_language_switch_key">Suppress language switch key</string> + <!-- Option for the dismiss delay of the key popup [CHAR LIMIT=25] --> <string name="key_preview_popup_dismiss_delay">Key popup dismiss delay</string> <!-- Description for delay for dismissing a popup on keypress: no delay [CHAR LIMIT=15] --> diff --git a/java/res/xml/key_styles_common.xml b/java/res/xml/key_styles_common.xml index 76eacb673b..f153a7d96b 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" /> <key-style - latin:styleName="settingsKeyStyle" - latin:code="@integer/key_settings" - latin:keyIcon="iconSettingsKey" - latin:keyActionFlags="noKeyPreview|altCodeWhileTyping" + latin:styleName="languageSwitchKeyStyle" + latin:code="@integer/key_language_switch" + latin:keyIcon="iconLanguageSwitchKey" + latin:keyActionFlags="noKeyPreview|altCodeWhileTyping|enableLongPress" latin:altCode="@integer/key_space" latin:backgroundType="functional" /> <key-style diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml index f826ef006e..ebca250892 100644 --- a/java/res/xml/prefs.xml +++ b/java/res/xml/prefs.xml @@ -92,6 +92,17 @@ android:key="pref_advanced_settings" android:title="@string/advanced_settings" android:summary="@string/advanced_settings_summary"> + <CheckBoxPreference + android:key="pref_suppress_language_switch_key" + android:title="@string/suppress_language_switch_key" + android:persistent="true" + android:defaultValue="false" /> + <CheckBoxPreference + android:key="pref_include_other_imes_in_language_switch_list" + android:title="@string/include_other_imes_in_language_switch_list" + android:summary="@string/include_other_imes_in_language_switch_list_summary" + android:persistent="true" + android:defaultValue="false" /> <!-- Values for popup dismiss delay are added programatically --> <ListPreference android:key="pref_key_preview_popup_dismiss_delay" diff --git a/java/res/xml/row_qwerty4.xml b/java/res/xml/row_qwerty4.xml index df9c8fe3f0..0dd2177e82 100644 --- a/java/res/xml/row_qwerty4.xml +++ b/java/res/xml/row_qwerty4.xml @@ -57,9 +57,23 @@ latin:keyStyle="f1MoreKeysStyle" /> </default> </switch> - <Key - latin:keyStyle="spaceKeyStyle" - latin:keyWidth="50%p" /> + <switch> + <case + latin:languageSwitchKeyEnabled="true" + > + <Key + latin:keyStyle="languageSwitchKeyStyle" /> + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="40%p" /> + </case> + <!-- languageSwitchKeyEnabled="false" --> + <default> + <Key + latin:keyStyle="spaceKeyStyle" + latin:keyWidth="50%p" /> + </default> + </switch> <Key latin:keyStyle="punctuationKeyStyle" /> <Key diff --git a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java index 7e216e5c8d..9dd0a599de 100644 --- a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java @@ -49,6 +49,8 @@ public class InputMethodManagerCompatWrapper { private static final String TAG = InputMethodManagerCompatWrapper.class.getSimpleName(); private static final Method METHOD_getCurrentInputMethodSubtype = CompatUtils.getMethod(InputMethodManager.class, "getCurrentInputMethodSubtype"); + private static final Method METHOD_getLastInputMethodSubtype = + CompatUtils.getMethod(InputMethodManager.class, "getLastInputMethodSubtype"); private static final Method METHOD_getEnabledInputMethodSubtypeList = CompatUtils.getMethod(InputMethodManager.class, "getEnabledInputMethodSubtypeList", InputMethodInfo.class, boolean.class); @@ -60,6 +62,8 @@ public class InputMethodManagerCompatWrapper { String.class, InputMethodSubtypeCompatWrapper.CLASS_InputMethodSubtype); private static final Method METHOD_switchToLastInputMethod = CompatUtils.getMethod( InputMethodManager.class, "switchToLastInputMethod", IBinder.class); + private static final Method METHOD_switchToNextInputMethod = CompatUtils.getMethod( + InputMethodManager.class, "switchToNextInputMethod", IBinder.class, Boolean.TYPE); private static final InputMethodManagerCompatWrapper sInstance = new InputMethodManagerCompatWrapper(); @@ -111,6 +115,15 @@ public class InputMethodManagerCompatWrapper { return new InputMethodSubtypeCompatWrapper(o); } + public InputMethodSubtypeCompatWrapper getLastInputMethodSubtype() { + if (!SUBTYPE_SUPPORTED) { + return new InputMethodSubtypeCompatWrapper( + 0, 0, mLanguageSwitcherProxy.getInputLocale().toString(), KEYBOARD_MODE, ""); + } + Object o = CompatUtils.invoke(mImm, null, METHOD_getLastInputMethodSubtype); + return new InputMethodSubtypeCompatWrapper(o); + } + public List<InputMethodSubtypeCompatWrapper> 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<InputMethodInfoCompatWrapper> getEnabledInputMethodList() { if (mImm == null) return null; List<InputMethodInfoCompatWrapper> imis = new ArrayList<InputMethodInfoCompatWrapper>(); diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index c6cdf7986f..5660d19426 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 f5752962e0..6703b93017 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 ee882edc02..731aaf7c52 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 e1c6f26049..ac8dd1b958 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 78c371ff0c..afc4932e93 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 7c8fd12250..ca711ec7d9 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 2bcd947f15..cb22b4935f 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 3029057be5..305cef22d1 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 6d65a74c8f..69e45f6195 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 33d4b877ea..a8679e07ad 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; -- GitLab