slightly tune when autocorrect is used

and add setting whether autocorrect should be used when not explicitly requested
This commit is contained in:
Helium314 2024-01-23 12:29:14 +01:00
parent 5348486418
commit 0e15ee9b26
11 changed files with 56 additions and 38 deletions

View file

@ -27,7 +27,7 @@ public final class InputAttributes {
private final String TAG = InputAttributes.class.getSimpleName();
final public String mTargetApplicationPackageName;
final public boolean mInputTypeNoAutoCorrect;
final public boolean mInputTypeShouldAutoCorrect;
final public boolean mIsPasswordField;
final public boolean mShouldShowSuggestions;
final public boolean mMayOverrideShowingSuggestions;
@ -42,7 +42,7 @@ public final class InputAttributes {
*/
final public boolean mDisableGestureFloatingPreviewText;
final public boolean mIsGeneralTextInput;
final private int mInputType;
final public int mInputType;
final private EditorInfo mEditorInfo;
final private String mPackageNameForPrivateImeOptions;
@ -73,7 +73,7 @@ public final class InputAttributes {
}
mShouldShowSuggestions = false;
mMayOverrideShowingSuggestions = false;
mInputTypeNoAutoCorrect = false;
mInputTypeShouldAutoCorrect = false;
mApplicationSpecifiedCompletionOn = false;
mShouldInsertSpacesAutomatically = false;
mShouldShowVoiceInputKey = false;
@ -82,6 +82,7 @@ public final class InputAttributes {
mNoLearning = false;
return;
}
// inputClass == InputType.TYPE_CLASS_TEXT
final int variation = inputType & InputType.TYPE_MASK_VARIATION;
final boolean flagNoSuggestions = 0 != (inputType & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
@ -106,14 +107,16 @@ public final class InputAttributes {
mDisableGestureFloatingPreviewText = InputAttributes.inPrivateImeOptions(
mPackageNameForPrivateImeOptions, NO_FLOATING_GESTURE_PREVIEW, editorInfo);
// If it's a browser edit field and auto correct is not ON explicitly, then
// disable auto correction, but keep suggestions on.
// If NO_SUGGESTIONS is set, don't do prediction.
// If it's not multiline and the autoCorrect flag is not set, then don't correct
mInputTypeNoAutoCorrect =
(variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT && !flagAutoCorrect)
|| flagNoSuggestions
|| (!flagAutoCorrect && !flagMultiLine);
// autocorrect if explicitly wanted, but also for most multi-line input types (like AOSP keyboard)
// originally, URI and email were always excluded from autocorrect (in Suggest.java), but this is
// and unexpected place, and if the input field explicitly requests autocorrect we should follow the flag
mInputTypeShouldAutoCorrect = flagAutoCorrect || (
flagMultiLine
&& variation != InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT
&& variation != InputType.TYPE_TEXT_VARIATION_URI
&& !InputTypeUtils.isEmailVariation(variation)
&& !flagNoSuggestions
);
mApplicationSpecifiedCompletionOn = flagAutoComplete && isFullscreenMode;
@ -274,7 +277,7 @@ public final class InputAttributes {
return String.format(
"%s: inputType=0x%08x%s%s%s%s%s targetApp=%s\n", getClass().getSimpleName(),
mInputType,
(mInputTypeNoAutoCorrect ? " noAutoCorrect" : ""),
(mInputTypeShouldAutoCorrect ? " noAutoCorrect" : ""),
(mIsPasswordField ? " password" : ""),
(mShouldShowSuggestions ? " shouldShowSuggestions" : ""),
(mApplicationSpecifiedCompletionOn ? " appSpecified" : ""),

View file

@ -724,7 +724,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mDictionaryFacilitator.resetDictionaries(this, locale,
settingsValues.mUseContactsDictionary, settingsValues.mUsePersonalizedDicts,
false, settingsValues.mAccount, "", this);
if (settingsValues.mAutoCorrectionEnabledPerUserSettings) {
if (settingsValues.mAutoCorrectEnabled) {
mInputLogic.mSuggest.setAutoCorrectionThreshold(settingsValues.mAutoCorrectionThreshold);
}
}
@ -1036,7 +1036,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mainKeyboardView.closing();
currentSettingsValues = mSettings.getCurrent();
if (currentSettingsValues.mAutoCorrectionEnabledPerUserSettings) {
if (currentSettingsValues.mAutoCorrectEnabled) {
suggest.setAutoCorrectionThreshold(currentSettingsValues.mAutoCorrectionThreshold);
}
switcher.loadKeyboard(editorInfo, currentSettingsValues, getCurrentAutoCapsState(), getCurrentRecapitalizeState());

View file

@ -11,7 +11,6 @@ import org.dslul.openboard.inputmethod.latin.utils.Log;
import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
import org.dslul.openboard.inputmethod.keyboard.Keyboard;
import org.dslul.openboard.inputmethod.keyboard.KeyboardId;
import org.dslul.openboard.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import org.dslul.openboard.inputmethod.latin.common.ComposedData;
import org.dslul.openboard.inputmethod.latin.common.Constants;
@ -201,7 +200,6 @@ public final class Suggest {
settingsValuesForSuggestion, inputStyleIfNotPrediction, first.getWord(), typedWordString);
},
isCorrectionEnabled,
keyboard.mId.mMode,
wordComposer,
suggestionResults,
firstOccurrenceOfTypedWordInSuggestions,
@ -289,7 +287,6 @@ public final class Suggest {
final List<SuggestedWordInfo> firstAndTypedWordEmptyInfos,
final Runnable putEmptyWordSuggestions,
final boolean isCorrectionEnabled,
final int keyboardIdMode,
final WordComposer wordComposer,
final SuggestionResults suggestionResults,
final int firstOccurrenceOfTypedWordInSuggestions,
@ -336,6 +333,8 @@ public final class Suggest {
// If correction is not enabled, we never auto-correct. This is for example for when
// the setting "Auto-correction" is "off": we still suggest, but we don't auto-correct.
if (!isCorrectionEnabled
// todo: can some parts be moved to isCorrectionEnabled? e.g. keyboardIdMode only depends on input type
// i guess then not mAutoCorrectionEnabledPerUserSettings should be read, but rather some isAutocorrectEnabled()
// If the word does not allow to be auto-corrected, then we don't auto-correct.
|| !allowsToBeAutoCorrected
// If we are doing prediction, then we never auto-correct of course
@ -351,10 +350,6 @@ public final class Suggest {
|| wordComposer.isMostlyCaps()
// We never auto-correct when suggestions are resumed because it would be unexpected
|| wordComposer.isResumed()
// We don't autocorrect in URL or email input, since websites and emails can be
// deliberate misspellings of actual words
|| keyboardIdMode == KeyboardId.MODE_URL
|| keyboardIdMode == KeyboardId.MODE_EMAIL
// If we don't have a main dictionary, we never want to auto-correct. The reason
// for this is, the user may have a contact whose name happens to match a valid
// word in their language, and it will unexpectedly auto-correct. For example, if

View file

@ -999,7 +999,7 @@ public final class InputLogic {
}
// isComposingWord() may have changed since we stored wasComposing
if (mWordComposer.isComposingWord()) {
if (settingsValues.mAutoCorrectionEnabledPerUserSettings) {
if (settingsValues.mAutoCorrectEnabled) {
final String separator = shouldAvoidSendingCode ? LastComposedWord.NOT_A_SEPARATOR
: StringUtils.newSingleCodePointString(codePoint);
commitCurrentAutoCorrection(settingsValues, separator, handler);
@ -2111,10 +2111,8 @@ public final class InputLogic {
private boolean textBeforeCursorMayBeUrlOrSimilar(final SettingsValues settingsValues, final Boolean forAutoSpace) {
final EditorInfo ei = getCurrentInputEditorInfo();
// URL field and no space -> may be URL
// for whatever absurd reason long message, postal address and email subject have type values that return true when filtering for URI, see https://developer.android.com/reference/android/text/InputType
// so we really need to specifically require URI as only type variation
if (ei != null && (ei.inputType & 0x000000f0) == 0x00000010 &&
// URL / mail field and no space -> may be URL
if (ei != null && (InputTypeUtils.isUriOrEmailType(ei.inputType)) &&
// we never want to commit the first part of the url, but we want to insert autospace if text might be a normal word
(forAutoSpace ? mConnection.nonWordCodePointAndNoSpaceBeforeCursor(settingsValues.mSpacingAndPunctuations) // avoid detecting URL if it could be a word
: !mConnection.spaceBeforeCursor()))
@ -2349,7 +2347,7 @@ public final class InputLogic {
mWordComposer.isComposingWord() ? 2 : 1),
keyboard,
settingsValues.mSettingsValuesForSuggestion,
settingsValues.mAutoCorrectionEnabledPerUserSettings,
settingsValues.mAutoCorrectEnabled,
inputStyle, sequenceNumber, callback);
}

View file

@ -74,6 +74,7 @@ public final class CorrectionSettingsFragment extends SubScreenFragment
private void refreshEnabledSettings() {
setPreferenceVisible(Settings.PREF_AUTO_CORRECTION_CONFIDENCE, Settings.readAutoCorrectEnabled(getSharedPreferences()));
setPreferenceVisible(Settings.PREF_MORE_AUTO_CORRECTION, Settings.readAutoCorrectEnabled(getSharedPreferences()));
setPreferenceVisible(Settings.PREF_ADD_TO_PERSONAL_DICTIONARY, getSharedPreferences().getBoolean(Settings.PREF_KEY_USE_PERSONALIZED_DICTS, true));
setPreferenceVisible(Settings.PREF_ALWAYS_SHOW_SUGGESTIONS, getSharedPreferences().getBoolean(Settings.PREF_SHOW_SUGGESTIONS, true));
turnOffLookupContactsIfNoPermission();

View file

@ -80,6 +80,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
public static final String PREF_COLOR_BACKGROUND_SUFFIX = "background";
public static final String PREF_AUTO_USER_COLOR_SUFFIX = "_auto";
public static final String PREF_AUTO_CORRECTION = "pref_key_auto_correction";
public static final String PREF_MORE_AUTO_CORRECTION = "pref_more_auto_correction";
public static final String PREF_AUTO_CORRECTION_CONFIDENCE = "pref_key_auto_correction_confidence";
public static final String PREF_SHOW_SUGGESTIONS = "show_suggestions";
public static final String PREF_ALWAYS_SHOW_SUGGESTIONS = "pref_always_show_suggestions";
@ -264,6 +265,10 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
return prefs.getBoolean(PREF_AUTO_CORRECTION, true);
}
public static boolean readMoreAutoCorrectEnabled(final SharedPreferences prefs) {
return prefs.getBoolean(PREF_MORE_AUTO_CORRECTION, true);
}
public void toggleAutoCorrect() {
mPrefs.edit().putBoolean(Settings.PREF_AUTO_CORRECTION, !readAutoCorrectEnabled(mPrefs)).apply();
}

View file

@ -11,7 +11,6 @@ import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import org.dslul.openboard.inputmethod.latin.utils.Log;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodSubtype;
@ -26,6 +25,8 @@ import org.dslul.openboard.inputmethod.latin.RichInputMethodManager;
import org.dslul.openboard.inputmethod.latin.common.Colors;
import org.dslul.openboard.inputmethod.latin.spellcheck.AndroidSpellCheckerService;
import org.dslul.openboard.inputmethod.latin.utils.AsyncResultHolder;
import org.dslul.openboard.inputmethod.latin.utils.InputTypeUtils;
import org.dslul.openboard.inputmethod.latin.utils.Log;
import org.dslul.openboard.inputmethod.latin.utils.MoreKeysUtilsKt;
import org.dslul.openboard.inputmethod.latin.utils.ScriptUtils;
import org.dslul.openboard.inputmethod.latin.utils.SubtypeSettingsKt;
@ -113,10 +114,10 @@ public class SettingsValues {
// Deduced settings
public final int mKeypressVibrationDuration;
public final float mKeypressSoundVolume;
private final boolean mAutoCorrectEnabled;
public final boolean mAutoCorrectionEnabledPerUserSettings;
public final boolean mAutoCorrectEnabled;
public final float mAutoCorrectionThreshold;
public final int mScoreLimitForAutocorrect;
public final boolean mAutoCorrectionEnabledPerUserSettings;
private final boolean mSuggestionsEnabledPerUserSettings;
private final boolean mOverrideShowingSuggestions;
public final SettingsValuesForSuggestion mSettingsValuesForSuggestion;
@ -159,7 +160,11 @@ public class SettingsValues {
mUseDoubleSpacePeriod = prefs.getBoolean(Settings.PREF_KEY_USE_DOUBLE_SPACE_PERIOD, true)
&& inputAttributes.mIsGeneralTextInput;
mBlockPotentiallyOffensive = Settings.readBlockPotentiallyOffensive(prefs, res);
mAutoCorrectEnabled = Settings.readAutoCorrectEnabled(prefs);
mUrlDetectionEnabled = prefs.getBoolean(Settings.PREF_URL_DETECTION, false);
mAutoCorrectionEnabledPerUserSettings = Settings.readAutoCorrectEnabled(prefs);
mAutoCorrectEnabled = mAutoCorrectionEnabledPerUserSettings
&& (mInputAttributes.mInputTypeShouldAutoCorrect || Settings.readMoreAutoCorrectEnabled(prefs))
&& (mUrlDetectionEnabled || !InputTypeUtils.isUriOrEmailType(mInputAttributes.mInputType));
mAutoCorrectionThreshold = mAutoCorrectEnabled
? readAutoCorrectionThreshold(res, prefs)
: AUTO_CORRECTION_DISABLED_THRESHOLD;
@ -187,8 +192,6 @@ public class SettingsValues {
mAccount = null; // remove? or can it be useful somewhere?
mGestureFloatingPreviewTextEnabled = !mInputAttributes.mDisableGestureFloatingPreviewText
&& prefs.getBoolean(Settings.PREF_GESTURE_FLOATING_PREVIEW_TEXT, true);
mAutoCorrectionEnabledPerUserSettings = mAutoCorrectEnabled;
//&& !mInputAttributes.mInputTypeNoAutoCorrect; // follow that request or not?
mOverrideShowingSuggestions = mInputAttributes.mMayOverrideShowingSuggestions && readSuggestionsOverrideEnabled(prefs);
mSuggestionsEnabledPerUserSettings = (mInputAttributes.mShouldShowSuggestions && readSuggestionsEnabled(prefs))
|| mOverrideShowingSuggestions;
@ -240,7 +243,6 @@ public class SettingsValues {
mBlockPotentiallyOffensive,
prefs.getBoolean(Settings.PREF_GESTURE_SPACE_AWARE, false)
);
mUrlDetectionEnabled = prefs.getBoolean(Settings.PREF_URL_DETECTION, false);
mSpacingAndPunctuations = new SpacingAndPunctuations(res, mUrlDetectionEnabled);
mBottomPaddingScale = prefs.getFloat(Settings.PREF_BOTTOM_PADDING_SCALE, DEFAULT_SIZE_SCALE);
}
@ -251,7 +253,7 @@ public class SettingsValues {
public boolean needsToLookupSuggestions() {
return (mInputAttributes.mShouldShowSuggestions || mOverrideShowingSuggestions)
&& (mAutoCorrectionEnabledPerUserSettings || isSuggestionsEnabledPerUserSettings());
&& (mAutoCorrectEnabled || isSuggestionsEnabledPerUserSettings());
}
public boolean isSuggestionsEnabledPerUserSettings() {

View file

@ -64,6 +64,11 @@ public final class InputTypeUtils implements InputType {
|| isWebEmailAddressVariation(variation);
}
public static boolean isUriOrEmailType(final int inputType) {
final int maskedInputType = inputType & TYPE_MASK_VARIATION;
return maskedInputType == TYPE_TEXT_VARIATION_URI || isEmailVariation(maskedInputType);
}
public static boolean isWebInputType(final int inputType) {
final int maskedInputType =
inputType & (TYPE_MASK_CLASS | TYPE_MASK_VARIATION);

View file

@ -109,11 +109,14 @@
<string name="prefs_block_potentially_offensive_title">Block offensive words</string>
<!-- Summary for option to block potentially offensive words to be shown [CHAR_LIMIT=80 (two lines) or 40 (fits on one line, preferable)] -->
<string name="prefs_block_potentially_offensive_summary">Do not suggest potentially offensive words</string>
<!-- Option to decide the auto correction threshold score -->
<!-- Option to enable auto correction [CHAR LIMIT=20]-->
<!-- Option to enable auto correction [CHAR LIMIT=20] -->
<string name="autocorrect">Auto-correction</string>
<!-- Description for auto correction [CHAR LIMIT=65 (two lines) or 30 (fits on one line, preferable)] -->
<string name="auto_correction_summary">Spacebar and punctuation automatically correct mistyped words</string>
<!-- Option to enable auto correction for many fields that do not request auto correction -->
<string name="more_autocorrect">More auto-correction</string>
<!-- Description for more_autocorrect -->
<string name="more_autocorrect_summary">Auto-correct even when not explicitly requested by the input field</string>
<!-- Option to change the confidence level of the auto correction [CHAR LIMIT=20] -->
<string name="auto_correction_confidence">Auto-correction confidence</string>
<!-- Option to disable auto correction. [CHAR LIMIT=20] -->

View file

@ -31,6 +31,13 @@
android:defaultValue="true"
android:persistent="true" />
<SwitchPreferenceCompat
android:key="pref_more_auto_correction"
android:title="@string/more_autocorrect"
android:summary="@string/more_autocorrect_summary"
android:defaultValue="true"
android:persistent="true" />
<ListPreference
android:key="pref_key_auto_correction_confidence"
android:title="@string/auto_correction_confidence"

View file

@ -271,7 +271,6 @@ class SuggestTest {
listOf(firstSuggestionForEmpty, typedWordSuggestionForEmpty),
{}, // only used to fill above if needed
true, // doesn't make sense otherwise
0, // not really relevant here
WordComposer.getComposerForTest(false),
suggestionResults,
firstOccurrenceOfTypedWordInSuggestions,