Experimental automatic language switching support.
With this CL, LatinIME switches the current subtype from its enabled subtypes based on the first locale in EditorInfo#hintLocales. This functionality is still experimental, and will be triggered only when EditorInfo#hintLocales is specified by the application. Bug: 22859862 Change-Id: Ibd0559b370d8aa0d50d1bada8ecfdac0ed8db898
This commit is contained in:
parent
16645966a9
commit
809c93214b
2 changed files with 70 additions and 1 deletions
|
@ -54,7 +54,9 @@ import android.view.inputmethod.InputMethodSubtype;
|
||||||
|
|
||||||
import com.android.inputmethod.accessibility.AccessibilityUtils;
|
import com.android.inputmethod.accessibility.AccessibilityUtils;
|
||||||
import com.android.inputmethod.annotations.UsedForTesting;
|
import com.android.inputmethod.annotations.UsedForTesting;
|
||||||
|
import com.android.inputmethod.compat.EditorInfoCompatUtils;
|
||||||
import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
|
import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
|
||||||
|
import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
|
||||||
import com.android.inputmethod.compat.ViewOutlineProviderCompatUtils;
|
import com.android.inputmethod.compat.ViewOutlineProviderCompatUtils;
|
||||||
import com.android.inputmethod.compat.ViewOutlineProviderCompatUtils.InsetsUpdater;
|
import com.android.inputmethod.compat.ViewOutlineProviderCompatUtils.InsetsUpdater;
|
||||||
import com.android.inputmethod.dictionarypack.DictionaryPackConstants;
|
import com.android.inputmethod.dictionarypack.DictionaryPackConstants;
|
||||||
|
@ -176,8 +178,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
private static final int MSG_WAIT_FOR_DICTIONARY_LOAD = 8;
|
private static final int MSG_WAIT_FOR_DICTIONARY_LOAD = 8;
|
||||||
private static final int MSG_DEALLOCATE_MEMORY = 9;
|
private static final int MSG_DEALLOCATE_MEMORY = 9;
|
||||||
private static final int MSG_RESUME_SUGGESTIONS_FOR_START_INPUT = 10;
|
private static final int MSG_RESUME_SUGGESTIONS_FOR_START_INPUT = 10;
|
||||||
|
private static final int MSG_SWITCH_LANGUAGE_AUTOMATICALLY = 11;
|
||||||
// Update this when adding new messages
|
// Update this when adding new messages
|
||||||
private static final int MSG_LAST = MSG_RESUME_SUGGESTIONS_FOR_START_INPUT;
|
private static final int MSG_LAST = MSG_SWITCH_LANGUAGE_AUTOMATICALLY;
|
||||||
|
|
||||||
private static final int ARG1_NOT_GESTURE_INPUT = 0;
|
private static final int ARG1_NOT_GESTURE_INPUT = 0;
|
||||||
private static final int ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1;
|
private static final int ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1;
|
||||||
|
@ -271,6 +274,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
case MSG_DEALLOCATE_MEMORY:
|
case MSG_DEALLOCATE_MEMORY:
|
||||||
latinIme.deallocateMemory();
|
latinIme.deallocateMemory();
|
||||||
break;
|
break;
|
||||||
|
case MSG_SWITCH_LANGUAGE_AUTOMATICALLY:
|
||||||
|
latinIme.switchLanguage((InputMethodSubtype)msg.obj);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,6 +395,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
obtainMessage(MSG_UPDATE_TAIL_BATCH_INPUT_COMPLETED, suggestedWords).sendToTarget();
|
obtainMessage(MSG_UPDATE_TAIL_BATCH_INPUT_COMPLETED, suggestedWords).sendToTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void postSwitchLanguage(final InputMethodSubtype subtype) {
|
||||||
|
obtainMessage(MSG_SWITCH_LANGUAGE_AUTOMATICALLY, subtype).sendToTarget();
|
||||||
|
}
|
||||||
|
|
||||||
// Working variables for the following methods.
|
// Working variables for the following methods.
|
||||||
private boolean mIsOrientationChanging;
|
private boolean mIsOrientationChanging;
|
||||||
private boolean mPendingSuccessiveImsCallback;
|
private boolean mPendingSuccessiveImsCallback;
|
||||||
|
@ -795,6 +805,19 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
|
|
||||||
void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) {
|
void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) {
|
||||||
super.onStartInput(editorInfo, restarting);
|
super.onStartInput(editorInfo, restarting);
|
||||||
|
|
||||||
|
// If the primary hint language does not match the current subtype language, then try
|
||||||
|
// to switch to the primary hint language.
|
||||||
|
// TODO: Support all the locales in EditorInfo#hintLocales.
|
||||||
|
final Locale primaryHintLocale = EditorInfoCompatUtils.getPrimaryHintLocale(editorInfo);
|
||||||
|
if (primaryHintLocale == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final InputMethodSubtype newSubtype = mRichImm.findSubtypeByLocale(primaryHintLocale);
|
||||||
|
if (newSubtype == null || newSubtype.equals(mRichImm.getCurrentSubtype().getRawSubtype())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mHandler.postSwitchLanguage(newSubtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
|
@ -1301,6 +1324,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
return mOptionsDialog != null && mOptionsDialog.isShowing();
|
return mOptionsDialog != null && mOptionsDialog.isShowing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void switchLanguage(final InputMethodSubtype subtype) {
|
||||||
|
final IBinder token = getWindow().getWindow().getAttributes().token;
|
||||||
|
mRichImm.setInputMethodAndSubtype(token, subtype);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Revise the language switch key behavior to make it much smarter and more reasonable.
|
// TODO: Revise the language switch key behavior to make it much smarter and more reasonable.
|
||||||
public void switchToNextSubtype() {
|
public void switchToNextSubtype() {
|
||||||
final IBinder token = getWindow().getWindow().getAttributes().token;
|
final IBinder token = getWindow().getWindow().getAttributes().token;
|
||||||
|
|
|
@ -32,6 +32,7 @@ import android.view.inputmethod.InputMethodSubtype;
|
||||||
|
|
||||||
import com.android.inputmethod.annotations.UsedForTesting;
|
import com.android.inputmethod.annotations.UsedForTesting;
|
||||||
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
|
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
|
||||||
|
import com.android.inputmethod.compat.InputMethodSubtypeCompatUtils;
|
||||||
import com.android.inputmethod.latin.settings.Settings;
|
import com.android.inputmethod.latin.settings.Settings;
|
||||||
import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
|
import com.android.inputmethod.latin.utils.AdditionalSubtypeUtils;
|
||||||
import com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils;
|
import com.android.inputmethod.latin.utils.LanguageOnSpacebarUtils;
|
||||||
|
@ -428,6 +429,46 @@ public class RichInputMethodManager {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public InputMethodSubtype findSubtypeByLocale(final Locale locale) {
|
||||||
|
// Find the best subtype based on a straightforward matching algorithm.
|
||||||
|
// TODO: Use LocaleList#getFirstMatch() instead.
|
||||||
|
final List<InputMethodSubtype> subtypes =
|
||||||
|
getMyEnabledInputMethodSubtypeList(true /* allowsImplicitlySelectedSubtypes */);
|
||||||
|
final int count = subtypes.size();
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
final InputMethodSubtype subtype = subtypes.get(i);
|
||||||
|
final Locale subtypeLocale = InputMethodSubtypeCompatUtils.getLocaleObject(subtype);
|
||||||
|
if (subtypeLocale.equals(locale)) {
|
||||||
|
return subtype;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
final InputMethodSubtype subtype = subtypes.get(i);
|
||||||
|
final Locale subtypeLocale = InputMethodSubtypeCompatUtils.getLocaleObject(subtype);
|
||||||
|
if (subtypeLocale.getLanguage().equals(locale.getLanguage()) &&
|
||||||
|
subtypeLocale.getCountry().equals(locale.getCountry()) &&
|
||||||
|
subtypeLocale.getVariant().equals(locale.getVariant())) {
|
||||||
|
return subtype;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
final InputMethodSubtype subtype = subtypes.get(i);
|
||||||
|
final Locale subtypeLocale = InputMethodSubtypeCompatUtils.getLocaleObject(subtype);
|
||||||
|
if (subtypeLocale.getLanguage().equals(locale.getLanguage()) &&
|
||||||
|
subtypeLocale.getCountry().equals(locale.getCountry())) {
|
||||||
|
return subtype;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
final InputMethodSubtype subtype = subtypes.get(i);
|
||||||
|
final Locale subtypeLocale = InputMethodSubtypeCompatUtils.getLocaleObject(subtype);
|
||||||
|
if (subtypeLocale.getLanguage().equals(locale.getLanguage())) {
|
||||||
|
return subtype;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public void setInputMethodAndSubtype(final IBinder token, final InputMethodSubtype subtype) {
|
public void setInputMethodAndSubtype(final IBinder token, final InputMethodSubtype subtype) {
|
||||||
mImmWrapper.mImm.setInputMethodAndSubtype(
|
mImmWrapper.mImm.setInputMethodAndSubtype(
|
||||||
token, getInputMethodIdOfThisIme(), subtype);
|
token, getInputMethodIdOfThisIme(), subtype);
|
||||||
|
|
Loading…
Reference in a new issue