Move hint-locale switching logic to SubtypeState

This commit is contained in:
unlair 2025-03-10 16:48:10 -04:00
parent 5868063316
commit 219336393f
No known key found for this signature in database
GPG key ID: 221ADE60BA750A31

View file

@ -153,12 +153,6 @@ public class LatinIME extends InputMethodService implements
@Nullable
private Context mDisplayContext;
// When HintLocales causes a subtype override, we store
// the overridden subtype here in order to restore it when
// we switch to another input context that has no HintLocales.
@Nullable
private InputMethodSubtype mOverriddenByHintLocale;
// Object for reacting to adding/removing a dictionary pack.
private final BroadcastReceiver mDictionaryPackInstallReceiver =
new DictionaryPackInstallBroadcastReceiver(this);
@ -529,6 +523,11 @@ public class LatinIME extends InputMethodService implements
}
final class SubtypeState {
// When HintLocales causes a subtype override, we store
// the overridden subtype here in order to restore it when
// we switch to another input context that has no HintLocales.
private InputMethodSubtype mOverriddenByLocale;
private InputMethodSubtype mLastActiveSubtype;
private boolean mCurrentSubtypeHasBeenUsed = true; // starting with true avoids immediate switch
@ -536,6 +535,70 @@ public class LatinIME extends InputMethodService implements
mCurrentSubtypeHasBeenUsed = true;
}
// TextFields can provide locale/language hints that the IME should use via 'hintLocales'.
// If a matching subtype is found, we temporarily switch to that subtype until
// we return to a context that does not provide any hints, or until the user
// explicitly changes the language/subtype in use.
public InputMethodSubtype getSubtypeForLocales(final RichInputMethodManager richImm, final Iterable<Locale> locales) {
final InputMethodSubtype overriddenByLocale = mOverriddenByLocale;
if (locales == null) {
if (overriddenByLocale != null) {
// no locales provided, so switch back to
// whatever subtype was used last time.
mOverriddenByLocale = null;
return overriddenByLocale;
}
return null;
}
final InputMethodSubtype currentSubtype = richImm.getCurrentSubtype().getRawSubtype();
final Locale currentSubtypeLocale = richImm.getCurrentSubtypeLocale();
final int minimumMatchLevel = 3; // LocaleUtils.LOCALE_LANGUAGE_MATCH_COUNTRY_DIFFER;
// Try finding a subtype matching the hint language.
for (final Locale hintLocale : locales) {
if (LocaleUtils.INSTANCE.getMatchLevel(hintLocale, currentSubtypeLocale) >= minimumMatchLevel
|| CollectionsKt.any(mSettings.getCurrent().mSecondaryLocales,
(secLocale) -> LocaleUtils.INSTANCE.getMatchLevel(hintLocale, secLocale) >= minimumMatchLevel)) {
// current locales are already a good match, and we want to avoid unnecessary layout switches.
return null;
}
final InputMethodSubtype subtypeForHintLocale = richImm.findSubtypeForHintLocale(hintLocale);
if (subtypeForHintLocale == null) {
continue;
}
if (subtypeForHintLocale.equals(currentSubtype)) {
// no need to switch, we already use the correct locale.
return null;
}
if (overriddenByLocale == null) {
// auto-switching based on hint locale, so store
// whatever subtype was in use so we can switch back
// to it later when there are no hint locales.
mOverriddenByLocale = currentSubtype;
}
return subtypeForHintLocale;
}
return null;
}
public void onSubtypeChanged(final InputMethodSubtype oldSubtype,
final InputMethodSubtype newSubtype) {
if (oldSubtype != mOverriddenByLocale) {
// Whenever the subtype is changed, clear tracking
// the subtype that is overridden by a HintLocale as
// we no longer have a subtype to automatically switch back to.
mOverriddenByLocale = null;
}
}
public void switchSubtype(final RichInputMethodManager richImm) {
final InputMethodSubtype currentSubtype = richImm.getCurrentSubtype().getRawSubtype();
final InputMethodSubtype lastActiveSubtype = mLastActiveSubtype;
@ -865,12 +928,7 @@ public class LatinIME extends InputMethodService implements
}
InputMethodSubtype oldSubtype = mRichImm.getCurrentSubtype().getRawSubtype();
if (mOverriddenByHintLocale != oldSubtype) {
// Clear tracking the subtype that is overridden by a HintLocale
// when subtypes are changed in any way other than the initial automatic change.
mOverriddenByHintLocale = null;
}
mSubtypeState.onSubtypeChanged(oldSubtype, subtype);
StatsUtils.onSubtypeChanged(oldSubtype, subtype);
mRichImm.onSubtypeChanged(subtype);
mInputLogic.onSubtypeChanged(SubtypeLocaleUtils.getCombiningRulesExtraValue(subtype),
@ -889,28 +947,10 @@ public class LatinIME extends InputMethodService implements
super.onStartInput(editorInfo, restarting);
final List<Locale> hintLocales = EditorInfoCompatUtils.getHintLocales(editorInfo);
if (hintLocales == null) {
if (mOverriddenByHintLocale != null) {
mHandler.postSwitchLanguage(mOverriddenByHintLocale);
mOverriddenByHintLocale = null;
}
return;
}
// Try switching to a subtype matching the hint language.
for (final Locale hintLocale : hintLocales) {
if (LocaleUtils.INSTANCE.getMatchLevel(hintLocale, mRichImm.getCurrentSubtypeLocale()) >= 3
|| CollectionsKt.any(mSettings.getCurrent().mSecondaryLocales, (secLocale) -> LocaleUtils.INSTANCE.getMatchLevel(hintLocale, secLocale) >= 3))
return; // current locales are already a good match, and we want to avoid unnecessary layout switches
final InputMethodSubtype newSubtype = mRichImm.findSubtypeForHintLocale(hintLocale);
if (newSubtype == null) continue;
if (newSubtype.equals(mRichImm.getCurrentSubtype().getRawSubtype()))
return; // no need to switch, we already use the correct locale
if (mOverriddenByHintLocale == null) {
mOverriddenByHintLocale = mRichImm.getCurrentSubtype().getRawSubtype();
}
mHandler.postSwitchLanguage(newSubtype);
break;
final InputMethodSubtype subtypeForLocales = mSubtypeState.getSubtypeForLocales(mRichImm, hintLocales);
if (subtypeForLocales != null) {
// found a better subtype using hint locales that we should switch to.
mHandler.postSwitchLanguage(subtypeForLocales);
}
}