diff options
author | 2024-12-16 21:45:41 -0500 | |
---|---|---|
committer | 2025-01-11 14:17:35 -0500 | |
commit | e9a0e66716dab4dd3184d009d8920de1961efdfa (patch) | |
tree | 02dcc096643d74645bf28459c2834c3d4a2ad7f2 /java/src/org/kelar/inputmethod/latin/InputAttributes.java | |
parent | fb3b9360d70596d7e921de8bf7d3ca99564a077e (diff) | |
download | latinime-e9a0e66716dab4dd3184d009d8920de1961efdfa.tar.gz latinime-e9a0e66716dab4dd3184d009d8920de1961efdfa.tar.xz latinime-e9a0e66716dab4dd3184d009d8920de1961efdfa.zip |
Rename to Kelar Keyboard (org.kelar.inputmethod.latin)
Diffstat (limited to 'java/src/org/kelar/inputmethod/latin/InputAttributes.java')
-rw-r--r-- | java/src/org/kelar/inputmethod/latin/InputAttributes.java | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/java/src/org/kelar/inputmethod/latin/InputAttributes.java b/java/src/org/kelar/inputmethod/latin/InputAttributes.java new file mode 100644 index 000000000..0c145e543 --- /dev/null +++ b/java/src/org/kelar/inputmethod/latin/InputAttributes.java @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.kelar.inputmethod.latin; + +import static org.kelar.inputmethod.latin.common.Constants.ImeOption.NO_FLOATING_GESTURE_PREVIEW; +import static org.kelar.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE; +import static org.kelar.inputmethod.latin.common.Constants.ImeOption.NO_MICROPHONE_COMPAT; + +import android.text.InputType; +import android.util.Log; +import android.view.inputmethod.EditorInfo; + +import org.kelar.inputmethod.latin.common.StringUtils; +import org.kelar.inputmethod.latin.utils.InputTypeUtils; +import org.kelar.inputmethod.latin.settings.SettingsValues; + +import java.util.ArrayList; +import java.util.Arrays; + +/** + * Class to hold attributes of the input field. + */ +public final class InputAttributes { + private final String TAG = InputAttributes.class.getSimpleName(); + + final public String mTargetApplicationPackageName; + final public boolean mInputTypeNoAutoCorrect; + final public boolean mIsPasswordField; + final public boolean mShouldShowSuggestions; + final public boolean mApplicationSpecifiedCompletionOn; + final public boolean mShouldInsertSpacesAutomatically; + final public boolean mShouldShowVoiceInputKey; + /** + * Whether the floating gesture preview should be disabled. If true, this should override the + * corresponding keyboard settings preference, always suppressing the floating preview text. + * {@link SettingsValues#mGestureFloatingPreviewTextEnabled} + */ + final public boolean mDisableGestureFloatingPreviewText; + final public boolean mIsGeneralTextInput; + final private int mInputType; + final private EditorInfo mEditorInfo; + final private String mPackageNameForPrivateImeOptions; + + public InputAttributes(final EditorInfo editorInfo, final boolean isFullscreenMode, + final String packageNameForPrivateImeOptions) { + mEditorInfo = editorInfo; + mPackageNameForPrivateImeOptions = packageNameForPrivateImeOptions; + mTargetApplicationPackageName = null != editorInfo ? editorInfo.packageName : null; + final int inputType = null != editorInfo ? editorInfo.inputType : 0; + final int inputClass = inputType & InputType.TYPE_MASK_CLASS; + mInputType = inputType; + mIsPasswordField = InputTypeUtils.isPasswordInputType(inputType) + || InputTypeUtils.isVisiblePasswordInputType(inputType); + if (inputClass != InputType.TYPE_CLASS_TEXT) { + // If we are not looking at a TYPE_CLASS_TEXT field, the following strange + // cases may arise, so we do a couple validity checks for them. If it's a + // TYPE_CLASS_TEXT field, these special cases cannot happen, by construction + // of the flags. + if (null == editorInfo) { + Log.w(TAG, "No editor info for this field. Bug?"); + } else if (InputType.TYPE_NULL == inputType) { + // TODO: We should honor TYPE_NULL specification. + Log.i(TAG, "InputType.TYPE_NULL is specified"); + } else if (inputClass == 0) { + // TODO: is this check still necessary? + Log.w(TAG, String.format("Unexpected input class: inputType=0x%08x" + + " imeOptions=0x%08x", inputType, editorInfo.imeOptions)); + } + mShouldShowSuggestions = false; + mInputTypeNoAutoCorrect = false; + mApplicationSpecifiedCompletionOn = false; + mShouldInsertSpacesAutomatically = false; + mShouldShowVoiceInputKey = false; + mDisableGestureFloatingPreviewText = false; + mIsGeneralTextInput = 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); + final boolean flagMultiLine = + 0 != (inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE); + final boolean flagAutoCorrect = + 0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); + final boolean flagAutoComplete = + 0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE); + + // TODO: Have a helper method in InputTypeUtils + // Make sure that passwords are not displayed in {@link SuggestionStripView}. + final boolean shouldSuppressSuggestions = mIsPasswordField + || InputTypeUtils.isEmailVariation(variation) + || InputType.TYPE_TEXT_VARIATION_URI == variation + || InputType.TYPE_TEXT_VARIATION_FILTER == variation + || flagNoSuggestions + || flagAutoComplete; + mShouldShowSuggestions = !shouldSuppressSuggestions; + + mShouldInsertSpacesAutomatically = InputTypeUtils.isAutoSpaceFriendlyType(inputType); + + final boolean noMicrophone = mIsPasswordField + || InputTypeUtils.isEmailVariation(variation) + || InputType.TYPE_TEXT_VARIATION_URI == variation + || hasNoMicrophoneKeyOption(); + mShouldShowVoiceInputKey = !noMicrophone; + + 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); + + mApplicationSpecifiedCompletionOn = flagAutoComplete && isFullscreenMode; + + // If we come here, inputClass is always TYPE_CLASS_TEXT + mIsGeneralTextInput = InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS != variation + && InputType.TYPE_TEXT_VARIATION_PASSWORD != variation + && InputType.TYPE_TEXT_VARIATION_PHONETIC != variation + && InputType.TYPE_TEXT_VARIATION_URI != variation + && InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD != variation + && InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS != variation + && InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD != variation; + } + + public boolean isTypeNull() { + return InputType.TYPE_NULL == mInputType; + } + + public boolean isSameInputType(final EditorInfo editorInfo) { + return editorInfo.inputType == mInputType; + } + + private boolean hasNoMicrophoneKeyOption() { + @SuppressWarnings("deprecation") + final boolean deprecatedNoMicrophone = InputAttributes.inPrivateImeOptions( + null, NO_MICROPHONE_COMPAT, mEditorInfo); + final boolean noMicrophone = InputAttributes.inPrivateImeOptions( + mPackageNameForPrivateImeOptions, NO_MICROPHONE, mEditorInfo); + return noMicrophone || deprecatedNoMicrophone; + } + + @SuppressWarnings("unused") + private void dumpFlags(final int inputType) { + final int inputClass = inputType & InputType.TYPE_MASK_CLASS; + final String inputClassString = toInputClassString(inputClass); + final String variationString = toVariationString( + inputClass, inputType & InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS); + final String flagsString = toFlagsString(inputType & InputType.TYPE_MASK_FLAGS); + Log.i(TAG, "Input class: " + inputClassString); + Log.i(TAG, "Variation: " + variationString); + Log.i(TAG, "Flags: " + flagsString); + } + + private static String toInputClassString(final int inputClass) { + switch (inputClass) { + case InputType.TYPE_CLASS_TEXT: + return "TYPE_CLASS_TEXT"; + case InputType.TYPE_CLASS_PHONE: + return "TYPE_CLASS_PHONE"; + case InputType.TYPE_CLASS_NUMBER: + return "TYPE_CLASS_NUMBER"; + case InputType.TYPE_CLASS_DATETIME: + return "TYPE_CLASS_DATETIME"; + default: + return String.format("unknownInputClass<0x%08x>", inputClass); + } + } + + private static String toVariationString(final int inputClass, final int variation) { + switch (inputClass) { + case InputType.TYPE_CLASS_TEXT: + return toTextVariationString(variation); + case InputType.TYPE_CLASS_NUMBER: + return toNumberVariationString(variation); + case InputType.TYPE_CLASS_DATETIME: + return toDatetimeVariationString(variation); + default: + return ""; + } + } + + private static String toTextVariationString(final int variation) { + switch (variation) { + case InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS: + return " TYPE_TEXT_VARIATION_EMAIL_ADDRESS"; + case InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT: + return "TYPE_TEXT_VARIATION_EMAIL_SUBJECT"; + case InputType.TYPE_TEXT_VARIATION_FILTER: + return "TYPE_TEXT_VARIATION_FILTER"; + case InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE: + return "TYPE_TEXT_VARIATION_LONG_MESSAGE"; + case InputType.TYPE_TEXT_VARIATION_NORMAL: + return "TYPE_TEXT_VARIATION_NORMAL"; + case InputType.TYPE_TEXT_VARIATION_PASSWORD: + return "TYPE_TEXT_VARIATION_PASSWORD"; + case InputType.TYPE_TEXT_VARIATION_PERSON_NAME: + return "TYPE_TEXT_VARIATION_PERSON_NAME"; + case InputType.TYPE_TEXT_VARIATION_PHONETIC: + return "TYPE_TEXT_VARIATION_PHONETIC"; + case InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS: + return "TYPE_TEXT_VARIATION_POSTAL_ADDRESS"; + case InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE: + return "TYPE_TEXT_VARIATION_SHORT_MESSAGE"; + case InputType.TYPE_TEXT_VARIATION_URI: + return "TYPE_TEXT_VARIATION_URI"; + case InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD: + return "TYPE_TEXT_VARIATION_VISIBLE_PASSWORD"; + case InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT: + return "TYPE_TEXT_VARIATION_WEB_EDIT_TEXT"; + case InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS: + return "TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS"; + case InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD: + return "TYPE_TEXT_VARIATION_WEB_PASSWORD"; + default: + return String.format("unknownVariation<0x%08x>", variation); + } + } + + private static String toNumberVariationString(final int variation) { + switch (variation) { + case InputType.TYPE_NUMBER_VARIATION_NORMAL: + return "TYPE_NUMBER_VARIATION_NORMAL"; + case InputType.TYPE_NUMBER_VARIATION_PASSWORD: + return "TYPE_NUMBER_VARIATION_PASSWORD"; + default: + return String.format("unknownVariation<0x%08x>", variation); + } + } + + private static String toDatetimeVariationString(final int variation) { + switch (variation) { + case InputType.TYPE_DATETIME_VARIATION_NORMAL: + return "TYPE_DATETIME_VARIATION_NORMAL"; + case InputType.TYPE_DATETIME_VARIATION_DATE: + return "TYPE_DATETIME_VARIATION_DATE"; + case InputType.TYPE_DATETIME_VARIATION_TIME: + return "TYPE_DATETIME_VARIATION_TIME"; + default: + return String.format("unknownVariation<0x%08x>", variation); + } + } + + private static String toFlagsString(final int flags) { + final ArrayList<String> flagsArray = new ArrayList<>(); + if (0 != (flags & InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS)) + flagsArray.add("TYPE_TEXT_FLAG_NO_SUGGESTIONS"); + if (0 != (flags & InputType.TYPE_TEXT_FLAG_MULTI_LINE)) + flagsArray.add("TYPE_TEXT_FLAG_MULTI_LINE"); + if (0 != (flags & InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE)) + flagsArray.add("TYPE_TEXT_FLAG_IME_MULTI_LINE"); + if (0 != (flags & InputType.TYPE_TEXT_FLAG_CAP_WORDS)) + flagsArray.add("TYPE_TEXT_FLAG_CAP_WORDS"); + if (0 != (flags & InputType.TYPE_TEXT_FLAG_CAP_SENTENCES)) + flagsArray.add("TYPE_TEXT_FLAG_CAP_SENTENCES"); + if (0 != (flags & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS)) + flagsArray.add("TYPE_TEXT_FLAG_CAP_CHARACTERS"); + if (0 != (flags & InputType.TYPE_TEXT_FLAG_AUTO_CORRECT)) + flagsArray.add("TYPE_TEXT_FLAG_AUTO_CORRECT"); + if (0 != (flags & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE)) + flagsArray.add("TYPE_TEXT_FLAG_AUTO_COMPLETE"); + return flagsArray.isEmpty() ? "" : Arrays.toString(flagsArray.toArray()); + } + + // Pretty print + @Override + public String toString() { + return String.format( + "%s: inputType=0x%08x%s%s%s%s%s targetApp=%s\n", getClass().getSimpleName(), + mInputType, + (mInputTypeNoAutoCorrect ? " noAutoCorrect" : ""), + (mIsPasswordField ? " password" : ""), + (mShouldShowSuggestions ? " shouldShowSuggestions" : ""), + (mApplicationSpecifiedCompletionOn ? " appSpecified" : ""), + (mShouldInsertSpacesAutomatically ? " insertSpaces" : ""), + mTargetApplicationPackageName); + } + + public static boolean inPrivateImeOptions(final String packageName, final String key, + final EditorInfo editorInfo) { + if (editorInfo == null) return false; + final String findingKey = (packageName != null) ? packageName + "." + key : key; + return StringUtils.containsInCommaSplittableText(findingKey, editorInfo.privateImeOptions); + } +} |