From 5e5f045495e3e7b05ea60b155bcf2615daf93d52 Mon Sep 17 00:00:00 2001 From: Helium314 Date: Thu, 1 Feb 2024 10:56:41 +0100 Subject: [PATCH] consider script when evaluating hint locales --- .../helium314/keyboard/latin/LatinIME.java | 4 +- .../latin/RichInputMethodManager.java | 95 +++++-------------- .../keyboard/latin/common/LocaleUtils.kt | 1 + 3 files changed, 27 insertions(+), 73 deletions(-) diff --git a/app/src/main/java/helium314/keyboard/latin/LatinIME.java b/app/src/main/java/helium314/keyboard/latin/LatinIME.java index 513ba21b..624b788f 100644 --- a/app/src/main/java/helium314/keyboard/latin/LatinIME.java +++ b/app/src/main/java/helium314/keyboard/latin/LatinIME.java @@ -914,15 +914,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } // Try switching to a subtype matching the hint language. for (final Locale hintLocale : hintLocales) { - final InputMethodSubtype newSubtype = mRichImm.findSubtypeByLocale(hintLocale); + 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 mHandler.postSwitchLanguage(newSubtype); + break; } } - @SuppressWarnings("deprecation") void onStartInputViewInternal(final EditorInfo editorInfo, final boolean restarting) { super.onStartInputView(editorInfo, restarting); diff --git a/app/src/main/java/helium314/keyboard/latin/RichInputMethodManager.java b/app/src/main/java/helium314/keyboard/latin/RichInputMethodManager.java index bda0bc81..21e92f1a 100644 --- a/app/src/main/java/helium314/keyboard/latin/RichInputMethodManager.java +++ b/app/src/main/java/helium314/keyboard/latin/RichInputMethodManager.java @@ -17,6 +17,7 @@ import android.view.inputmethod.InputMethodSubtype; import helium314.keyboard.annotations.UsedForTesting; import helium314.keyboard.compat.ConfigurationCompatKt; +import helium314.keyboard.latin.common.LocaleUtils; import helium314.keyboard.latin.settings.Settings; import helium314.keyboard.latin.utils.DeviceProtectedUtils; import helium314.keyboard.latin.utils.LanguageOnSpacebarUtils; @@ -309,82 +310,34 @@ public class RichInputMethodManager { return null; } - public InputMethodSubtype findSubtypeByLocale(final Locale locale) { - // Find the best subtype based on a straightforward matching algorithm. - final List subtypes = - getMyEnabledInputMethodSubtypeList(true /* allowsImplicitlySelectedSubtypes */); - final int count = subtypes.size(); - // search for exact match - for (int i = 0; i < count; ++i) { - final InputMethodSubtype subtype = subtypes.get(i); - final Locale subtypeLocale = SubtypeUtilsKt.locale(subtype); - if (subtypeLocale.equals(locale)) { - return subtype; - } - } - // search for language + country + variant match - for (int i = 0; i < count; ++i) { - final InputMethodSubtype subtype = subtypes.get(i); - final Locale subtypeLocale = SubtypeUtilsKt.locale(subtype); - if (subtypeLocale.getLanguage().equals(locale.getLanguage()) && - subtypeLocale.getCountry().equals(locale.getCountry()) && - subtypeLocale.getVariant().equals(locale.getVariant())) { - return subtype; - } - } - // search for language + country match - for (int i = 0; i < count; ++i) { - final InputMethodSubtype subtype = subtypes.get(i); - final Locale subtypeLocale = SubtypeUtilsKt.locale(subtype); - if (subtypeLocale.getLanguage().equals(locale.getLanguage()) && - subtypeLocale.getCountry().equals(locale.getCountry())) { - return subtype; - } - } - // search for secondary locale match - final SharedPreferences prefs = DeviceProtectedUtils.getSharedPreferences(mContext); - for (int i = 0; i < count; ++i) { - final InputMethodSubtype subtype = subtypes.get(i); - final Locale subtypeLocale = SubtypeUtilsKt.locale(subtype); - final List secondaryLocales = Settings.getSecondaryLocales(prefs, subtypeLocale); - for (final Locale secondaryLocale : secondaryLocales) { - if (secondaryLocale.equals(locale)) { - return subtype; - } - } - } - // search for language match - for (int i = 0; i < count; ++i) { - final InputMethodSubtype subtype = subtypes.get(i); - final Locale subtypeLocale = SubtypeUtilsKt.locale(subtype); - if (subtypeLocale.getLanguage().equals(locale.getLanguage())) { - return subtype; - } - } - // search for secondary language match - for (int i = 0; i < count; ++i) { - final InputMethodSubtype subtype = subtypes.get(i); - final Locale subtypeLocale = SubtypeUtilsKt.locale(subtype); - final List secondaryLocales = Settings.getSecondaryLocales(prefs, subtypeLocale); - for (final Locale secondaryLocale : secondaryLocales) { - if (secondaryLocale.getLanguage().equals(locale.getLanguage())) { - return subtype; - } - } - } + public InputMethodSubtype findSubtypeForHintLocale(final Locale locale) { + // Find the best subtype based on a locale matching + final List subtypes = getMyEnabledInputMethodSubtypeList(true); + InputMethodSubtype bestMatch = LocaleUtils.getBestMatch(locale, subtypes, SubtypeUtilsKt::locale); + if (bestMatch != null) return bestMatch; - // extra: if current script is not compatible to current subtype, search for compatible script - // this is acceptable only because this function is only used for switching to a certain locale using EditorInfo.hintLocales + // search for first secondary language & script match + final int count = subtypes.size(); + final SharedPreferences prefs = DeviceProtectedUtils.getSharedPreferences(mContext); + final String language = locale.getLanguage(); final String script = ScriptUtils.script(locale); - if (!script.equals(ScriptUtils.script(getCurrentSubtypeLocale()))) { - for (int i = 0; i < count; ++i) { - final InputMethodSubtype subtype = subtypes.get(i); - final Locale subtypeLocale = SubtypeUtilsKt.locale(subtype); - if (ScriptUtils.script(subtypeLocale).equals(script)) { - return subtype; + for (int i = 0; i < count; ++i) { + final InputMethodSubtype subtype = subtypes.get(i); + final Locale subtypeLocale = SubtypeUtilsKt.locale(subtype); + if (!ScriptUtils.script(subtypeLocale).equals(script)) + continue; // need compatible script + bestMatch = subtype; + final List secondaryLocales = Settings.getSecondaryLocales(prefs, subtypeLocale); + for (final Locale secondaryLocale : secondaryLocales) { + if (secondaryLocale.getLanguage().equals(language)) { + return bestMatch; } } } + // if wanted script is not compatible to current subtype, return a subtype with compatible script if possible + if (!script.equals(ScriptUtils.script(getCurrentSubtypeLocale()))) { + return bestMatch; + } return null; } diff --git a/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt b/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt index 695bb38c..72fae76a 100644 --- a/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/common/LocaleUtils.kt @@ -110,6 +110,7 @@ object LocaleUtils { else LOCALE_LANGUAGE_AND_COUNTRY_MATCH_VARIANT_DIFFER } + @JvmStatic fun getBestMatch(locale: Locale, collection: Collection, toLocale: (T) -> Locale): T? { var best: T? = null var bestLevel = 0