Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions java/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@
<!-- Description for "next word suggestion" option. This displays suggestions even when there is no input, based on the previous word. -->
<string name="bigram_prediction_summary">Use the previous word in making suggestions</string>

<!-- Title for auto-switch language setting -->
<string name="auto_switch_language_title">Auto-switch language</string>
<!-- Subtitle for auto-switch language setting -->
<string name="auto_switch_language_subtitle">Automatically switch to a matching language if the text field requests it (e.g. Translate)</string>
<!-- Title for advanced language settings section -->
<string name="language_settings_advanced_options">Advanced options</string>

<!-- Title for input language selection screen -->
<string name="language_selection_title">Languages</string>

Expand Down
5 changes: 5 additions & 0 deletions java/src/org/futo/inputmethod/latin/InputAttributes.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static org.futo.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE;
import static org.futo.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE_COMPAT;

import android.os.LocaleList;
import android.text.InputType;
import android.util.Log;
import android.view.inputmethod.EditorInfo;
Expand Down Expand Up @@ -56,6 +57,8 @@ public final class InputAttributes {
final public Locale mLocaleOverride;
@Nullable
final public String mLayoutOverride;
@Nullable
final public LocaleList mHintLocales;

/**
* Whether the floating gesture preview should be disabled. If true, this should override the
Expand Down Expand Up @@ -111,6 +114,7 @@ public InputAttributes(final EditorInfo editorInfo, final boolean isFullscreenMo
mIsWebField = false;
mLocaleOverride = null;
mLayoutOverride = null;
mHintLocales = null;
return;
}
// inputClass == InputType.TYPE_CLASS_TEXT
Expand Down Expand Up @@ -191,6 +195,7 @@ public InputAttributes(final EditorInfo editorInfo, final boolean isFullscreenMo
}

mLayoutOverride = privateImeOptions.get("org.futo.inputmethod.latin.ForceLayout");
mHintLocales = editorInfo.hintLocales;
}

public boolean isTypeNull() {
Expand Down
46 changes: 46 additions & 0 deletions java/src/org/futo/inputmethod/latin/LatinIME.kt
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,50 @@ class LatinIME : InputMethodServiceCompose(), LatinIMELegacy.SuggestionStripCont
}
}

private fun updateKeyboardLanguage() {
val settings = latinIMELegacy.mSettings.current
if (!settings.mAutoSwitchLanguage) return

val hintLocales = settings.mInputAttributes.mHintLocales ?: return
if (hintLocales.isEmpty) return

// We need to read these right from the settings. LatinIME just seems to return a generic "keyboard" subtype
// with no language info when you get subtypes from InputMethodManager
val enabledSubtypes = getSettingBlocking(SubtypesSetting).map(Subtypes::convertToSubtype)
if (enabledSubtypes.isEmpty()) return

val currentSubtype = RichInputMethodManager.getInstance().currentSubtype.rawSubtype
val currentSubtypeString = Subtypes.subtypeToString(currentSubtype)
val currentLanguage = Subtypes.getLocale(currentSubtype).language
val hintedLocales = (0 until hintLocales.size()).map(hintLocales::get)

if (hintedLocales.any { it.language == currentLanguage }) {
// Some apps update hintLocales faster than keyboard view state settles.
// If the current language is already valid for hints, keep it but force one UI resync.
// Example is changing between JP/EN in translate, going from 12 key back to EN would not work correctly.
if (lastAutoSwitchResyncSubtype != currentSubtypeString) {
latinIMELegacy.onCurrentInputMethodSubtypeChanged(currentSubtype)
lastAutoSwitchResyncSubtype = currentSubtypeString
}
return
}

// checking subtypes by tag and fallback to language if none found
val targetSubtype = hintedLocales.firstNotNullOfOrNull { hintLocale ->
enabledSubtypes.find {
Subtypes.getLocale(it).toLanguageTag().equals(hintLocale.toLanguageTag(), true)
} ?: enabledSubtypes.find {
val subtypeLocale = Subtypes.getLocale(it)
subtypeLocale.language.isNotEmpty() && subtypeLocale.language == hintLocale.language
}
} ?: return

if (Subtypes.subtypeToString(targetSubtype) == currentSubtypeString) return

lastAutoSwitchResyncSubtype = ""
latinIMELegacy.onCurrentInputMethodSubtypeChanged(targetSubtype)
}

fun onSizeUpdated() {
val newSize = calculateSize() ?: return
val shouldInvalidateKeyboard = size.value?.let { oldSize ->
Expand Down Expand Up @@ -350,6 +394,7 @@ class LatinIME : InputMethodServiceCompose(), LatinIMELegacy.SuggestionStripCont
}

private var currentSubtype = ""
private var lastAutoSwitchResyncSubtype = ""

val jobs = mutableListOf<Job>()
private fun launchJob(task: suspend CoroutineScope.() -> Unit) {
Expand Down Expand Up @@ -592,6 +637,7 @@ class LatinIME : InputMethodServiceCompose(), LatinIMELegacy.SuggestionStripCont
latinIMELegacy.onStartInputView(info, restarting)
lifecycleScope.launch { uixManager.showUpdateNoticeIfNeeded() }
updateColorsIfDynamicChanged()
updateKeyboardLanguage()
}

override fun onFinishInputView(finishingInput: Boolean) {
Expand Down
4 changes: 3 additions & 1 deletion java/src/org/futo/inputmethod/latin/LatinIMELegacy.java
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,9 @@ public void onCurrentInputMethodSubtypeChanged(final InputMethodSubtype subtype)
}

void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) {

// Refresh InputAttributes even when restarting in the same field. Some apps
// (e.g Translate) update hintLocales but not inputType, leading to out of date hintLocales
loadSettings();
}

public void updateMainKeyboardViewSettings() {
Expand Down
2 changes: 2 additions & 0 deletions java/src/org/futo/inputmethod/latin/settings/Settings.java
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang

public static final int DEFAULT_ALT_SPACES_MODE = SPACES_MODE_ALL;

public static final String PREF_AUTO_SWITCH_LANGUAGE = "pref_auto_switch_language";

// Emoji
public static final String PREF_EMOJI_RECENT_KEYS = "emoji_recent_keys";
public static final String PREF_EMOJI_CATEGORY_LAST_TYPED_ID = "emoji_category_last_typed_id";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ public class SettingsValues {
public final int mBackspaceMode;
public final int mNumberRowMode;
public final int mAltSpacesMode;

public final boolean mAutoSwitchLanguage;

// From the input box
@Nonnull
public final InputAttributes mInputAttributes;
Expand Down Expand Up @@ -201,9 +202,10 @@ public SettingsValues(final Context context, final SharedPreferences prefs, fina
prefs.getInt(Settings.PREF_NUMBER_ROW_MODE, Settings.NUMBER_ROW_MODE_DEFAULT)
: Settings.NUMBER_ROW_MODE_DEFAULT;
mAltSpacesMode = prefs.getInt(Settings.PREF_ALT_SPACES_MODE, Settings.DEFAULT_ALT_SPACES_MODE);
mAutoSwitchLanguage = prefs.getBoolean(Settings.PREF_AUTO_SWITCH_LANGUAGE, false);

mShouldShowLxxSuggestionUi = Settings.SHOULD_SHOW_LXX_SUGGESTION_UI
&& prefs.getBoolean(DebugSettings.PREF_SHOULD_SHOW_LXX_SUGGESTION_UI, true);
&& prefs.getBoolean(DebugSettings.PREF_SHOULD_SHOW_LXX_SUGGESTION_UI, true);
// Compute other readable settings
mKeyLongpressTimeout = Settings.readKeyLongpressTimeout(prefs, res);
mKeypressVibrationDuration = Settings.readKeypressVibrationDuration(prefs, res);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import org.futo.inputmethod.latin.MultilingualBucketSetting
import org.futo.inputmethod.latin.R
import org.futo.inputmethod.latin.Subtypes
import org.futo.inputmethod.latin.SubtypesSetting
import org.futo.inputmethod.latin.settings.Settings
import org.futo.inputmethod.latin.uix.FileKind
import org.futo.inputmethod.latin.uix.ResourceHelper
import org.futo.inputmethod.latin.uix.getSetting
Expand All @@ -66,6 +67,7 @@ import org.futo.inputmethod.latin.uix.settings.pages.modelmanager.openModelImpor
import org.futo.inputmethod.latin.uix.settings.useDataStore
import org.futo.inputmethod.latin.uix.settings.useDataStoreValue
import org.futo.inputmethod.latin.uix.settings.userSettingNavigationItem
import org.futo.inputmethod.latin.uix.settings.userSettingToggleSharedPrefs
import org.futo.inputmethod.latin.uix.theme.Typography
import org.futo.inputmethod.latin.uix.theme.UixThemeWrapper
import org.futo.inputmethod.latin.uix.theme.presets.DynamicDarkTheme
Expand Down Expand Up @@ -507,6 +509,16 @@ val LanguageSettingsTop = listOf(
navigateTo = "addLanguage",
)
)

val LanguageSettingsToggles = listOf(
userSettingToggleSharedPrefs(
title = R.string.auto_switch_language_title,
subtitle = R.string.auto_switch_language_subtitle,
key = Settings.PREF_AUTO_SWITCH_LANGUAGE,
default = { false }
)
)

val LanguageSettingsBottom = listOf(
userSettingNavigationItem(
title = R.string.language_settings_import_resource_from_file,
Expand Down Expand Up @@ -750,5 +762,13 @@ fun LanguagesScreen(navController: NavHostController = rememberNavController())
items(LanguageSettingsBottom) {
it.component()
}

item {
ScreenTitle(stringResource(R.string.language_settings_advanced_options))
}

items(LanguageSettingsToggles) {
it.component()
}
}
}
29 changes: 29 additions & 0 deletions tests/src/org/futo/inputmethod/latin/InputAttributesTests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.futo.inputmethod.latin;

import android.os.LocaleList;
import android.view.inputmethod.EditorInfo;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;

import java.util.Locale;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class InputAttributesTests {

@Test
public void testHintLocales() {
final EditorInfo editorInfo = mock(EditorInfo.class);
final LocaleList localeList = new LocaleList(new Locale("en", "US"), new Locale("ja", "JP"));
when(editorInfo.getHintLocales()).thenReturn(localeList);

final InputAttributes inputAttributes = new InputAttributes(editorInfo, false, "");

assertEquals(localeList, inputAttributes.mHintLocales);
}
}