mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-05-17 15:32:48 +00:00
more exhaustive search for hinLocales, if present
This commit is contained in:
parent
67d4f53e73
commit
1dc53663f0
5 changed files with 62 additions and 68 deletions
|
@ -6,20 +6,12 @@
|
||||||
|
|
||||||
package org.dslul.openboard.inputmethod.compat
|
package org.dslul.openboard.inputmethod.compat
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
object EditorInfoCompatUtils {
|
object EditorInfoCompatUtils {
|
||||||
// Note that EditorInfo.IME_FLAG_FORCE_ASCII has been introduced
|
|
||||||
// in API level 16 (Build.VERSION_CODES.JELLY_BEAN).
|
|
||||||
private val FIELD_IME_FLAG_FORCE_ASCII = CompatUtils.getField(EditorInfo::class.java, "IME_FLAG_FORCE_ASCII")
|
|
||||||
private val OBJ_IME_FLAG_FORCE_ASCII: Int? = CompatUtils.getFieldValue(null, null, FIELD_IME_FLAG_FORCE_ASCII) as? Int
|
|
||||||
private val FIELD_HINT_LOCALES = CompatUtils.getField(EditorInfo::class.java, "hintLocales")
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun hasFlagForceAscii(imeOptions: Int): Boolean {
|
|
||||||
return if (OBJ_IME_FLAG_FORCE_ASCII == null) false else imeOptions and OBJ_IME_FLAG_FORCE_ASCII != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun imeActionName(imeOptions: Int): String {
|
fun imeActionName(imeOptions: Int): String {
|
||||||
|
@ -36,32 +28,16 @@ object EditorInfoCompatUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun imeOptionsName(imeOptions: Int): String {
|
|
||||||
val action = imeActionName(imeOptions)
|
|
||||||
val flags = StringBuilder()
|
|
||||||
if (imeOptions and EditorInfo.IME_FLAG_NO_ENTER_ACTION != 0) {
|
|
||||||
flags.append("flagNoEnterAction|")
|
|
||||||
}
|
|
||||||
if (imeOptions and EditorInfo.IME_FLAG_NAVIGATE_NEXT != 0) {
|
|
||||||
flags.append("flagNavigateNext|")
|
|
||||||
}
|
|
||||||
if (imeOptions and EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS != 0) {
|
|
||||||
flags.append("flagNavigatePrevious|")
|
|
||||||
}
|
|
||||||
if (hasFlagForceAscii(imeOptions)) {
|
|
||||||
flags.append("flagForceAscii|")
|
|
||||||
}
|
|
||||||
return flags.toString() + action
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getPrimaryHintLocale(editorInfo: EditorInfo?): Locale? {
|
fun getHintLocales(editorInfo: EditorInfo?): List<Locale>? {
|
||||||
if (editorInfo == null) {
|
if (editorInfo == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val localeList = CompatUtils.getFieldValue(editorInfo, null, FIELD_HINT_LOCALES) ?: return null
|
val localeList = editorInfo.hintLocales ?: return null
|
||||||
return if (LocaleListCompatUtils.isEmpty(localeList)) {
|
val locales = ArrayList<Locale>(localeList.size())
|
||||||
null
|
for (i in 0 until localeList.size()) {
|
||||||
} else LocaleListCompatUtils[localeList, 0]
|
locales[i] = localeList.get(i)
|
||||||
|
}
|
||||||
|
return locales
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,22 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2016 The Android Open Source Project
|
|
||||||
* modified
|
|
||||||
* SPDX-License-Identifier: Apache-2.0 AND GPL-3.0-only
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.dslul.openboard.inputmethod.compat
|
|
||||||
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
object LocaleListCompatUtils {
|
|
||||||
private val CLASS_LocaleList = CompatUtils.getClass("android.os.LocaleList")
|
|
||||||
private val METHOD_get = CompatUtils.getMethod(CLASS_LocaleList, "get", Int::class.javaPrimitiveType)
|
|
||||||
private val METHOD_isEmpty = CompatUtils.getMethod(CLASS_LocaleList, "isEmpty")
|
|
||||||
fun isEmpty(localeList: Any?): Boolean {
|
|
||||||
return CompatUtils.invoke(localeList, java.lang.Boolean.FALSE, METHOD_isEmpty) as Boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun get(localeList: Any?, index: Int): Locale? {
|
|
||||||
return CompatUtils.invoke(localeList, null, METHOD_get, index) as Locale
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -290,8 +290,7 @@ public final class KeyboardLayoutSet {
|
||||||
// TODO: Consolidate with {@link InputAttributes}.
|
// TODO: Consolidate with {@link InputAttributes}.
|
||||||
@SuppressWarnings("deprecation") final boolean deprecatedForceAscii = InputAttributes.inPrivateImeOptions(
|
@SuppressWarnings("deprecation") final boolean deprecatedForceAscii = InputAttributes.inPrivateImeOptions(
|
||||||
mPackageName, FORCE_ASCII, mParams.mEditorInfo);
|
mPackageName, FORCE_ASCII, mParams.mEditorInfo);
|
||||||
final boolean forceAscii = EditorInfoCompatUtils.hasFlagForceAscii(
|
final boolean forceAscii = (mParams.mEditorInfo.imeOptions & EditorInfo.IME_FLAG_FORCE_ASCII) != 0
|
||||||
mParams.mEditorInfo.imeOptions)
|
|
||||||
|| deprecatedForceAscii;
|
|| deprecatedForceAscii;
|
||||||
final RichInputMethodSubtype keyboardSubtype = (forceAscii && !asciiCapable)
|
final RichInputMethodSubtype keyboardSubtype = (forceAscii && !asciiCapable)
|
||||||
? RichInputMethodSubtype.getNoLanguageSubtype()
|
? RichInputMethodSubtype.getNoLanguageSubtype()
|
||||||
|
|
|
@ -897,18 +897,18 @@ 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
|
final List<Locale> hintLocales = EditorInfoCompatUtils.getHintLocales(editorInfo);
|
||||||
// to switch to the primary hint language.
|
if (hintLocales == null) {
|
||||||
// TODO: Support all the locales in EditorInfo#hintLocales.
|
|
||||||
final Locale primaryHintLocale = EditorInfoCompatUtils.getPrimaryHintLocale(editorInfo);
|
|
||||||
if (primaryHintLocale == null) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final InputMethodSubtype newSubtype = mRichImm.findSubtypeByLocale(primaryHintLocale);
|
// Try switching to a subtype matching the hint language.
|
||||||
if (newSubtype == null || newSubtype.equals(mRichImm.getCurrentSubtype().getRawSubtype())) {
|
for (final Locale hintLocale : hintLocales) {
|
||||||
return;
|
final InputMethodSubtype newSubtype = mRichImm.findSubtypeByLocale(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);
|
||||||
}
|
}
|
||||||
mHandler.postSwitchLanguage(newSubtype);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
|
|
|
@ -18,9 +18,11 @@ import android.view.inputmethod.InputMethodSubtype;
|
||||||
|
|
||||||
import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
|
import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
|
||||||
import org.dslul.openboard.inputmethod.compat.InputMethodSubtypeCompatUtils;
|
import org.dslul.openboard.inputmethod.compat.InputMethodSubtypeCompatUtils;
|
||||||
|
import org.dslul.openboard.inputmethod.latin.settings.Settings;
|
||||||
import org.dslul.openboard.inputmethod.latin.settings.SubtypeSettingsKt;
|
import org.dslul.openboard.inputmethod.latin.settings.SubtypeSettingsKt;
|
||||||
import org.dslul.openboard.inputmethod.latin.utils.DeviceProtectedUtils;
|
import org.dslul.openboard.inputmethod.latin.utils.DeviceProtectedUtils;
|
||||||
import org.dslul.openboard.inputmethod.latin.utils.LanguageOnSpacebarUtils;
|
import org.dslul.openboard.inputmethod.latin.utils.LanguageOnSpacebarUtils;
|
||||||
|
import org.dslul.openboard.inputmethod.latin.utils.ScriptUtils;
|
||||||
import org.dslul.openboard.inputmethod.latin.utils.SubtypeLocaleUtils;
|
import org.dslul.openboard.inputmethod.latin.utils.SubtypeLocaleUtils;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -308,10 +310,10 @@ public class RichInputMethodManager {
|
||||||
|
|
||||||
public InputMethodSubtype findSubtypeByLocale(final Locale locale) {
|
public InputMethodSubtype findSubtypeByLocale(final Locale locale) {
|
||||||
// Find the best subtype based on a straightforward matching algorithm.
|
// Find the best subtype based on a straightforward matching algorithm.
|
||||||
// TODO: Use LocaleList#getFirstMatch() instead.
|
|
||||||
final List<InputMethodSubtype> subtypes =
|
final List<InputMethodSubtype> subtypes =
|
||||||
getMyEnabledInputMethodSubtypeList(true /* allowsImplicitlySelectedSubtypes */);
|
getMyEnabledInputMethodSubtypeList(true /* allowsImplicitlySelectedSubtypes */);
|
||||||
final int count = subtypes.size();
|
final int count = subtypes.size();
|
||||||
|
// search for exact match
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
final InputMethodSubtype subtype = subtypes.get(i);
|
final InputMethodSubtype subtype = subtypes.get(i);
|
||||||
final Locale subtypeLocale = InputMethodSubtypeCompatUtils.getLocaleObject(subtype);
|
final Locale subtypeLocale = InputMethodSubtypeCompatUtils.getLocaleObject(subtype);
|
||||||
|
@ -319,6 +321,7 @@ public class RichInputMethodManager {
|
||||||
return subtype;
|
return subtype;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// search for language + country + variant match
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
final InputMethodSubtype subtype = subtypes.get(i);
|
final InputMethodSubtype subtype = subtypes.get(i);
|
||||||
final Locale subtypeLocale = InputMethodSubtypeCompatUtils.getLocaleObject(subtype);
|
final Locale subtypeLocale = InputMethodSubtypeCompatUtils.getLocaleObject(subtype);
|
||||||
|
@ -328,6 +331,7 @@ public class RichInputMethodManager {
|
||||||
return subtype;
|
return subtype;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// search for language + country match
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
final InputMethodSubtype subtype = subtypes.get(i);
|
final InputMethodSubtype subtype = subtypes.get(i);
|
||||||
final Locale subtypeLocale = InputMethodSubtypeCompatUtils.getLocaleObject(subtype);
|
final Locale subtypeLocale = InputMethodSubtypeCompatUtils.getLocaleObject(subtype);
|
||||||
|
@ -336,6 +340,19 @@ public class RichInputMethodManager {
|
||||||
return subtype;
|
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 String subtypeLocale = subtype.getLocale();
|
||||||
|
final List<Locale> 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) {
|
for (int i = 0; i < count; ++i) {
|
||||||
final InputMethodSubtype subtype = subtypes.get(i);
|
final InputMethodSubtype subtype = subtypes.get(i);
|
||||||
final Locale subtypeLocale = InputMethodSubtypeCompatUtils.getLocaleObject(subtype);
|
final Locale subtypeLocale = InputMethodSubtypeCompatUtils.getLocaleObject(subtype);
|
||||||
|
@ -343,6 +360,30 @@ public class RichInputMethodManager {
|
||||||
return subtype;
|
return subtype;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// search for secondary language match
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
final InputMethodSubtype subtype = subtypes.get(i);
|
||||||
|
final String subtypeLocale = subtype.getLocale();
|
||||||
|
final List<Locale> secondaryLocales = Settings.getSecondaryLocales(prefs, subtypeLocale);
|
||||||
|
for (final Locale secondaryLocale : secondaryLocales) {
|
||||||
|
if (secondaryLocale.getLanguage().equals(locale.getLanguage())) {
|
||||||
|
return subtype;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
final int script = ScriptUtils.getScriptFromSpellCheckerLocale(locale);
|
||||||
|
if (script != ScriptUtils.getScriptFromSpellCheckerLocale(getCurrentSubtypeLocale())) {
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
final InputMethodSubtype subtype = subtypes.get(i);
|
||||||
|
final Locale subtypeLocale = InputMethodSubtypeCompatUtils.getLocaleObject(subtype);
|
||||||
|
if (ScriptUtils.getScriptFromSpellCheckerLocale(subtypeLocale) == script) {
|
||||||
|
return subtype;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue