aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_normal_off_lxx_dark.9.pngbin144 -> 161 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_normal_on_lxx_dark.9.pngbin137 -> 162 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_pressed_off_lxx_dark.9.pngbin143 -> 160 bytes
-rw-r--r--java/res/drawable-hdpi/btn_keyboard_key_pressed_on_lxx_dark.9.pngbin137 -> 162 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_normal_off_lxx_dark.9.pngbin127 -> 143 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_normal_on_lxx_dark.9.pngbin128 -> 138 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_pressed_off_lxx_dark.9.pngbin126 -> 127 bytes
-rw-r--r--java/res/drawable-mdpi/btn_keyboard_key_pressed_on_lxx_dark.9.pngbin128 -> 144 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_normal_off_lxx_dark.9.pngbin152 -> 282 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_normal_on_lxx_dark.9.pngbin137 -> 295 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_pressed_off_lxx_dark.9.pngbin152 -> 276 bytes
-rw-r--r--java/res/drawable-xhdpi/btn_keyboard_key_pressed_on_lxx_dark.9.pngbin137 -> 295 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_normal_off_lxx_dark.9.pngbin174 -> 171 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_normal_on_lxx_dark.9.pngbin172 -> 158 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_pressed_off_lxx_dark.9.pngbin180 -> 165 bytes
-rw-r--r--java/res/drawable-xxhdpi/btn_keyboard_key_pressed_on_lxx_dark.9.pngbin173 -> 173 bytes
-rw-r--r--java/res/values-v20/platform-theme.xml4
-rw-r--r--java/res/values/attrs.xml1
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardId.java9
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java30
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java6
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardTheme.java45
-rw-r--r--java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java2
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java11
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java10
-rw-r--r--java/src/com/android/inputmethod/latin/Dictionary.java4
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryCollection.java14
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFacilitator.java34
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java24
-rw-r--r--java/src/com/android/inputmethod/latin/InputAttributes.java29
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java111
-rw-r--r--java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java12
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputConnection.java4
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java43
-rw-r--r--java/src/com/android/inputmethod/latin/settings/SettingsValues.java37
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java45
-rw-r--r--java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java4
-rw-r--r--java/src/com/android/inputmethod/latin/utils/DistracterFilterUsingSuggestion.java155
-rw-r--r--java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java13
39 files changed, 296 insertions, 351 deletions
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_normal_off_lxx_dark.9.png b/java/res/drawable-hdpi/btn_keyboard_key_normal_off_lxx_dark.9.png
index c0fee73bc..2e6489cf5 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_normal_off_lxx_dark.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_normal_off_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_normal_on_lxx_dark.9.png b/java/res/drawable-hdpi/btn_keyboard_key_normal_on_lxx_dark.9.png
index 591292ced..0b1482281 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_normal_on_lxx_dark.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_normal_on_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png b/java/res/drawable-hdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png
index 10d91a2ea..4bf38fc35 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-hdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png b/java/res/drawable-hdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png
index 6a8c62f12..ea12c7776 100644
--- a/java/res/drawable-hdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png
+++ b/java/res/drawable-hdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_normal_off_lxx_dark.9.png b/java/res/drawable-mdpi/btn_keyboard_key_normal_off_lxx_dark.9.png
index 3ce13cc2c..9f244f2e9 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_normal_off_lxx_dark.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_normal_off_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_normal_on_lxx_dark.9.png b/java/res/drawable-mdpi/btn_keyboard_key_normal_on_lxx_dark.9.png
index 65507eea5..c5b3fbbd7 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_normal_on_lxx_dark.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_normal_on_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png b/java/res/drawable-mdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png
index 724e14212..66824cf8e 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png b/java/res/drawable-mdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png
index 264b65b52..527dfd014 100644
--- a/java/res/drawable-mdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png
+++ b/java/res/drawable-mdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_normal_off_lxx_dark.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_normal_off_lxx_dark.9.png
index 70270e290..98c085b15 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_normal_off_lxx_dark.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_normal_off_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_normal_on_lxx_dark.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_normal_on_lxx_dark.9.png
index 31f9e02ce..f0c132869 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_normal_on_lxx_dark.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_normal_on_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png
index 97ef98d4f..a2b17ba50 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xhdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png b/java/res/drawable-xhdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png
index a6e52ff82..99ff0affb 100644
--- a/java/res/drawable-xhdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png
+++ b/java/res/drawable-xhdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_normal_off_lxx_dark.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_normal_off_lxx_dark.9.png
index 814758622..4ec5864c1 100644
--- a/java/res/drawable-xxhdpi/btn_keyboard_key_normal_off_lxx_dark.9.png
+++ b/java/res/drawable-xxhdpi/btn_keyboard_key_normal_off_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_normal_on_lxx_dark.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_normal_on_lxx_dark.9.png
index 598bb68b7..6b5c0c0a4 100644
--- a/java/res/drawable-xxhdpi/btn_keyboard_key_normal_on_lxx_dark.9.png
+++ b/java/res/drawable-xxhdpi/btn_keyboard_key_normal_on_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png
index 963f34ab1..6fd8eedd3 100644
--- a/java/res/drawable-xxhdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png
+++ b/java/res/drawable-xxhdpi/btn_keyboard_key_pressed_off_lxx_dark.9.png
Binary files differ
diff --git a/java/res/drawable-xxhdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png b/java/res/drawable-xxhdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png
index b40d6f484..91322882f 100644
--- a/java/res/drawable-xxhdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png
+++ b/java/res/drawable-xxhdpi/btn_keyboard_key_pressed_on_lxx_dark.9.png
Binary files differ
diff --git a/java/res/values-v20/platform-theme.xml b/java/res/values-v20/platform-theme.xml
index 06062047b..52e7f3521 100644
--- a/java/res/values-v20/platform-theme.xml
+++ b/java/res/values-v20/platform-theme.xml
@@ -21,6 +21,6 @@
<!-- TODO: This file is temporarily placed under values-v20. -->
<!-- TODO: It might be moved under values-v21. -->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <style name="platformActivityTheme" parent="@android:style/Theme.Quantum.Light" />
- <style name="platformDialogTheme" parent="@android:style/Theme.Quantum.Light.Dialog" />
+ <style name="platformActivityTheme" parent="@android:style/Theme.Material.Light" />
+ <style name="platformDialogTheme" parent="@android:style/Theme.Material.Light.Dialog" />
</resources>
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 775a90c48..a1f478bd5 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -437,7 +437,6 @@
<attr name="navigatePrevious" format="boolean" />
<attr name="passwordInput" format="boolean" />
<attr name="clobberSettingsKey" format="boolean" />
- <attr name="supportsSwitchingToShortcutIme" format="boolean" />
<attr name="hasShortcutKey" format="boolean" />
<attr name="languageSwitchKeyEnabled" format="boolean" />
<attr name="isMultiLine" format="boolean" />
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardId.java b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
index 93a55fe6a..3c1167538 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardId.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardId.java
@@ -70,7 +70,6 @@ public final class KeyboardId {
public final int mElementId;
public final EditorInfo mEditorInfo;
public final boolean mClobberSettingsKey;
- public final boolean mSupportsSwitchingToShortcutIme;
public final boolean mLanguageSwitchKeyEnabled;
public final String mCustomActionLabel;
public final boolean mHasShortcutKey;
@@ -86,11 +85,10 @@ public final class KeyboardId {
mElementId = elementId;
mEditorInfo = params.mEditorInfo;
mClobberSettingsKey = params.mNoSettingsKey;
- mSupportsSwitchingToShortcutIme = params.mSupportsSwitchingToShortcutIme;
mLanguageSwitchKeyEnabled = params.mLanguageSwitchKeyEnabled;
mCustomActionLabel = (mEditorInfo.actionLabel != null)
? mEditorInfo.actionLabel.toString() : null;
- mHasShortcutKey = mSupportsSwitchingToShortcutIme && params.mShowsVoiceInputKey;
+ mHasShortcutKey = params.mVoiceInputKeyEnabled;
mHashCode = computeHashCode(this);
}
@@ -103,7 +101,6 @@ public final class KeyboardId {
id.mHeight,
id.passwordInput(),
id.mClobberSettingsKey,
- id.mSupportsSwitchingToShortcutIme,
id.mHasShortcutKey,
id.mLanguageSwitchKeyEnabled,
id.isMultiLine(),
@@ -124,7 +121,6 @@ public final class KeyboardId {
&& other.mHeight == mHeight
&& other.passwordInput() == passwordInput()
&& other.mClobberSettingsKey == mClobberSettingsKey
- && other.mSupportsSwitchingToShortcutIme == mSupportsSwitchingToShortcutIme
&& other.mHasShortcutKey == mHasShortcutKey
&& other.mLanguageSwitchKeyEnabled == mLanguageSwitchKeyEnabled
&& other.isMultiLine() == isMultiLine()
@@ -179,7 +175,7 @@ public final class KeyboardId {
@Override
public String toString() {
- return String.format(Locale.ROOT, "[%s %s:%s %dx%d %s %s%s%s%s%s%s%s%s%s]",
+ return String.format(Locale.ROOT, "[%s %s:%s %dx%d %s %s%s%s%s%s%s%s%s]",
elementIdToName(mElementId),
mLocale, mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET),
mWidth, mHeight,
@@ -189,7 +185,6 @@ public final class KeyboardId {
(navigatePrevious() ? " navigatePrevious" : ""),
(mClobberSettingsKey ? " clobberSettingsKey" : ""),
(passwordInput() ? " passwordInput" : ""),
- (mSupportsSwitchingToShortcutIme ? " supportsSwitchingToShortcutIme" : ""),
(mHasShortcutKey ? " hasShortcutKey" : ""),
(mLanguageSwitchKeyEnabled ? " languageSwitchKeyEnabled" : ""),
(isMultiLine() ? " isMultiLine" : "")
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
index aa646994c..3e5cfc11a 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
@@ -17,8 +17,6 @@
package com.android.inputmethod.keyboard;
import static com.android.inputmethod.latin.Constants.ImeOption.FORCE_ASCII;
-import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE;
-import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE_COMPAT;
import static com.android.inputmethod.latin.Constants.ImeOption.NO_SETTINGS_KEY;
import android.content.Context;
@@ -102,12 +100,11 @@ public final class KeyboardLayoutSet {
public static final class Params {
String mKeyboardLayoutSetName;
int mMode;
- EditorInfo mEditorInfo;
boolean mDisableTouchPositionCorrectionDataForTest;
+ // TODO: Use {@link InputAttributes} instead of these variables.
+ EditorInfo mEditorInfo;
boolean mIsPasswordField;
- boolean mSupportsSwitchingToShortcutIme;
- boolean mShowsVoiceInputKey;
- boolean mNoMicrophoneKey;
+ boolean mVoiceInputKeyEnabled;
boolean mNoSettingsKey;
boolean mLanguageSwitchKeyEnabled;
InputMethodSubtype mSubtype;
@@ -228,14 +225,9 @@ public final class KeyboardLayoutSet {
final EditorInfo editorInfo = (ei != null) ? ei : EMPTY_EDITOR_INFO;
params.mMode = getKeyboardMode(editorInfo);
+ // TODO: Consolidate those with {@link InputAttributes}.
params.mEditorInfo = editorInfo;
params.mIsPasswordField = InputTypeUtils.isPasswordInputType(editorInfo.inputType);
- @SuppressWarnings("deprecation")
- final boolean deprecatedNoMicrophone = InputAttributes.inPrivateImeOptions(
- null, NO_MICROPHONE_COMPAT, editorInfo);
- params.mNoMicrophoneKey = InputAttributes.inPrivateImeOptions(
- mPackageName, NO_MICROPHONE, editorInfo)
- || deprecatedNoMicrophone;
params.mNoSettingsKey = InputAttributes.inPrivateImeOptions(
mPackageName, NO_SETTINGS_KEY, editorInfo);
}
@@ -248,6 +240,7 @@ public final class KeyboardLayoutSet {
public Builder setSubtype(final InputMethodSubtype subtype) {
final boolean asciiCapable = InputMethodSubtypeCompatUtils.isAsciiCapable(subtype);
+ // TODO: Consolidate with {@link InputAttributes}.
@SuppressWarnings("deprecation")
final boolean deprecatedForceAscii = InputAttributes.inPrivateImeOptions(
mPackageName, FORCE_ASCII, mParams.mEditorInfo);
@@ -268,12 +261,13 @@ public final class KeyboardLayoutSet {
return this;
}
- public Builder setOptions(final boolean isShortcutImeEnabled,
- final boolean showsVoiceInputKey, final boolean languageSwitchKeyEnabled) {
- mParams.mSupportsSwitchingToShortcutIme =
- isShortcutImeEnabled && !mParams.mNoMicrophoneKey && !mParams.mIsPasswordField;
- mParams.mShowsVoiceInputKey = showsVoiceInputKey;
- mParams.mLanguageSwitchKeyEnabled = languageSwitchKeyEnabled;
+ public Builder setVoiceInputKeyEnabled(final boolean enabled) {
+ mParams.mVoiceInputKeyEnabled = enabled;
+ return this;
+ }
+
+ public Builder setLanguageSwitchKeyEnabled(final boolean enabled) {
+ mParams.mLanguageSwitchKeyEnabled = enabled;
return this;
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index ef5fabb41..6aeff189f 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -115,10 +115,8 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
final int keyboardHeight = ResourceUtils.getDefaultKeyboardHeight(res);
builder.setKeyboardGeometry(keyboardWidth, keyboardHeight);
builder.setSubtype(mSubtypeSwitcher.getCurrentSubtype());
- builder.setOptions(
- mSubtypeSwitcher.isShortcutImeEnabled(),
- settingsValues.mShowsVoiceInputKey,
- mLatinIME.shouldShowLanguageSwitchKey());
+ builder.setVoiceInputKeyEnabled(settingsValues.mShowsVoiceInputKey);
+ builder.setLanguageSwitchKeyEnabled(mLatinIME.shouldShowLanguageSwitchKey());
mKeyboardLayoutSet = builder.build();
mCurrentSettingsValues = settingsValues;
try {
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java b/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java
index 60d9a054d..0ea9c742f 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardTheme.java
@@ -21,46 +21,43 @@ import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.util.Log;
+import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.R;
import java.util.Arrays;
-import java.util.Comparator;
-public final class KeyboardTheme {
+public final class KeyboardTheme implements Comparable<KeyboardTheme> {
private static final String TAG = KeyboardTheme.class.getSimpleName();
static final String KLP_KEYBOARD_THEME_KEY = "pref_keyboard_layout_20110916";
static final String LXX_KEYBOARD_THEME_KEY = "pref_keyboard_theme_20140509";
- static final int THEME_ID_ICS = 0;
- static final int THEME_ID_KLP = 2;
- static final int THEME_ID_LXX_DARK = 3;
- static final int DEFAULT_THEME_ID = THEME_ID_KLP;
+ public static final int THEME_ID_ICS = 0;
+ public static final int THEME_ID_KLP = 2;
+ public static final int THEME_ID_LXX_DARK = 3;
+ public static final int DEFAULT_THEME_ID = THEME_ID_KLP;
private static final KeyboardTheme[] KEYBOARD_THEMES = {
new KeyboardTheme(THEME_ID_ICS, R.style.KeyboardTheme_ICS,
+ // This has never been selected because we support ICS or later.
VERSION_CODES.BASE),
new KeyboardTheme(THEME_ID_KLP, R.style.KeyboardTheme_KLP,
+ // Default theme for ICS, JB, and KLP.
VERSION_CODES.ICE_CREAM_SANDWICH),
new KeyboardTheme(THEME_ID_LXX_DARK, R.style.KeyboardTheme_LXX_Dark,
+ // Default theme for LXX.
// TODO: Update this constant once the *next* version becomes available.
VERSION_CODES.CUR_DEVELOPMENT),
};
+
static {
// Sort {@link #KEYBOARD_THEME} by descending order of {@link #mMinApiVersion}.
- Arrays.sort(KEYBOARD_THEMES, new Comparator<KeyboardTheme>() {
- @Override
- public int compare(final KeyboardTheme lhs, final KeyboardTheme rhs) {
- if (lhs.mMinApiVersion > rhs.mMinApiVersion) return -1;
- if (lhs.mMinApiVersion < rhs.mMinApiVersion) return 1;
- return 0;
- }
- });
+ Arrays.sort(KEYBOARD_THEMES);
}
public final int mThemeId;
public final int mStyleId;
- final int mMinApiVersion;
+ private final int mMinApiVersion;
// Note: The themeId should be aligned with "themeId" attribute of Keyboard style
// in values/themes-<style>.xml.
@@ -71,6 +68,13 @@ public final class KeyboardTheme {
}
@Override
+ public int compareTo(final KeyboardTheme rhs) {
+ if (mMinApiVersion > rhs.mMinApiVersion) return -1;
+ if (mMinApiVersion < rhs.mMinApiVersion) return 1;
+ return 0;
+ }
+
+ @Override
public boolean equals(final Object o) {
if (o == this) return true;
return (o instanceof KeyboardTheme) && ((KeyboardTheme)o).mThemeId == mThemeId;
@@ -81,7 +85,8 @@ public final class KeyboardTheme {
return mThemeId;
}
- private static KeyboardTheme searchKeyboardThemeById(final int themeId) {
+ @UsedForTesting
+ static KeyboardTheme searchKeyboardThemeById(final int themeId) {
// TODO: This search algorithm isn't optimal if there are many themes.
for (final KeyboardTheme theme : KEYBOARD_THEMES) {
if (theme.mThemeId == themeId) {
@@ -100,6 +105,7 @@ public final class KeyboardTheme {
return sdkVersion;
}
+ @UsedForTesting
static KeyboardTheme getDefaultKeyboardTheme(final SharedPreferences prefs,
final int sdkVersion) {
final String klpThemeIdString = prefs.getString(KLP_KEYBOARD_THEME_KEY, null);
@@ -134,6 +140,7 @@ public final class KeyboardTheme {
saveKeyboardThemeId(themeIdString, prefs, getSdkVersion());
}
+ @UsedForTesting
static String getPreferenceKey(final int sdkVersion) {
if (sdkVersion <= VERSION_CODES.KITKAT) {
return KLP_KEYBOARD_THEME_KEY;
@@ -141,8 +148,9 @@ public final class KeyboardTheme {
return LXX_KEYBOARD_THEME_KEY;
}
- static void saveKeyboardThemeId(final String themeIdString, final SharedPreferences prefs,
- final int sdkVersion) {
+ @UsedForTesting
+ static void saveKeyboardThemeId(final String themeIdString,
+ final SharedPreferences prefs, final int sdkVersion) {
final String prefKey = getPreferenceKey(sdkVersion);
prefs.edit().putString(prefKey, themeIdString).apply();
}
@@ -151,6 +159,7 @@ public final class KeyboardTheme {
return getKeyboardTheme(prefs, getSdkVersion());
}
+ @UsedForTesting
static KeyboardTheme getKeyboardTheme(final SharedPreferences prefs, final int sdkVersion) {
final String lxxThemeIdString = prefs.getString(LXX_KEYBOARD_THEME_KEY, null);
if (lxxThemeIdString == null) {
diff --git a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java
index 81d8cda7b..abed5208b 100644
--- a/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java
+++ b/java/src/com/android/inputmethod/keyboard/emoji/EmojiPalettesView.java
@@ -115,8 +115,6 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
builder.setSubtype(SubtypeSwitcher.getInstance().getEmojiSubtype());
builder.setKeyboardGeometry(ResourceUtils.getDefaultKeyboardWidth(res),
mEmojiLayoutParams.mEmojiKeyboardHeight);
- builder.setOptions(false /* shortcutImeEnabled */, false /* showsVoiceInputKey */,
- false /* languageSwitchKeyEnabled */);
final KeyboardLayoutSet layoutSet = builder.build();
final TypedArray emojiPalettesViewAttr = context.obtainStyledAttributes(attrs,
R.styleable.EmojiPalettesView, defStyle, R.style.EmojiPalettesView);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
index 2aeeed87f..e69499829 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
@@ -652,9 +652,6 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
R.styleable.Keyboard_Case_passwordInput, id.passwordInput());
final boolean clobberSettingsKeyMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_clobberSettingsKey, id.mClobberSettingsKey);
- final boolean supportsSwitchingToShortcutImeMatched = matchBoolean(caseAttr,
- R.styleable.Keyboard_Case_supportsSwitchingToShortcutIme,
- id.mSupportsSwitchingToShortcutIme);
final boolean hasShortcutKeyMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_hasShortcutKey, id.mHasShortcutKey);
final boolean languageSwitchKeyEnabledMatched = matchBoolean(caseAttr,
@@ -674,14 +671,13 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
R.styleable.Keyboard_Case_countryCode, id.mLocale.getCountry());
final boolean selected = keyboardLayoutSetMatched && keyboardLayoutSetElementMatched
&& modeMatched && navigateNextMatched && navigatePreviousMatched
- && passwordInputMatched && clobberSettingsKeyMatched
- && supportsSwitchingToShortcutImeMatched && hasShortcutKeyMatched
+ && passwordInputMatched && clobberSettingsKeyMatched && hasShortcutKeyMatched
&& languageSwitchKeyEnabledMatched && isMultiLineMatched && imeActionMatched
&& isIconDefinedMatched && localeCodeMatched && languageCodeMatched
&& countryCodeMatched;
if (DEBUG) {
- startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE,
+ startTag("<%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s>%s", TAG_CASE,
textAttr(caseAttr.getString(
R.styleable.Keyboard_Case_keyboardLayoutSet), "keyboardLayoutSet"),
textAttr(caseAttr.getString(
@@ -698,9 +694,6 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
"clobberSettingsKey"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_passwordInput,
"passwordInput"),
- booleanAttr(
- caseAttr, R.styleable.Keyboard_Case_supportsSwitchingToShortcutIme,
- "supportsSwitchingToShortcutIme"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_hasShortcutKey,
"hasShortcutKey"),
booleanAttr(caseAttr, R.styleable.Keyboard_Case_languageSwitchKeyEnabled,
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 096b946d2..7247a1f20 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -189,6 +189,7 @@ public final class BinaryDictionary extends Dictionary {
private static native void closeNative(long dict);
private static native int getFormatVersionNative(long dict);
private static native int getProbabilityNative(long dict, int[] word);
+ private static native int getMaxProbabilityOfExactMatchesNative(long dict, int[] word);
private static native int getBigramProbabilityNative(long dict, int[] word0,
boolean isBeginningOfSentence, int[] word1);
private static native void getWordPropertyNative(long dict, int[] word,
@@ -350,11 +351,18 @@ public final class BinaryDictionary extends Dictionary {
@Override
public int getFrequency(final String word) {
- if (word == null) return NOT_A_PROBABILITY;
+ if (TextUtils.isEmpty(word)) return NOT_A_PROBABILITY;
int[] codePoints = StringUtils.toCodePointArray(word);
return getProbabilityNative(mNativeDict, codePoints);
}
+ @Override
+ public int getMaxFrequencyOfExactMatches(final String word) {
+ if (TextUtils.isEmpty(word)) return NOT_A_PROBABILITY;
+ int[] codePoints = StringUtils.toCodePointArray(word);
+ return getMaxProbabilityOfExactMatchesNative(mNativeDict, codePoints);
+ }
+
@UsedForTesting
public boolean isValidNgram(final PrevWordsInfo prevWordsInfo, final String word) {
return getNgramProbability(prevWordsInfo, word) != NOT_A_PROBABILITY;
diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java
index aab16653e..bc7276b9a 100644
--- a/java/src/com/android/inputmethod/latin/Dictionary.java
+++ b/java/src/com/android/inputmethod/latin/Dictionary.java
@@ -95,6 +95,10 @@ public abstract class Dictionary {
return NOT_A_PROBABILITY;
}
+ public int getMaxFrequencyOfExactMatches(final String word) {
+ return NOT_A_PROBABILITY;
+ }
+
/**
* Compares the contents of the character array with the typed word and returns true if they
* are the same.
diff --git a/java/src/com/android/inputmethod/latin/DictionaryCollection.java b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
index 53be28139..53c78fd00 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java
@@ -89,9 +89,17 @@ public final class DictionaryCollection extends Dictionary {
int maxFreq = -1;
for (int i = mDictionaries.size() - 1; i >= 0; --i) {
final int tempFreq = mDictionaries.get(i).getFrequency(word);
- if (tempFreq >= maxFreq) {
- maxFreq = tempFreq;
- }
+ maxFreq = Math.max(tempFreq, maxFreq);
+ }
+ return maxFreq;
+ }
+
+ @Override
+ public int getMaxFrequencyOfExactMatches(final String word) {
+ int maxFreq = -1;
+ for (int i = mDictionaries.size() - 1; i >= 0; --i) {
+ final int tempFreq = mDictionaries.get(i).getMaxFrequencyOfExactMatches(word);
+ maxFreq = Math.max(tempFreq, maxFreq);
}
return maxFreq;
}
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
index 7fa3d0479..e8b0be069 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
@@ -63,7 +63,7 @@ public class DictionaryFacilitator {
private final Object mLock = new Object();
private final DistracterFilter mDistracterFilter;
- private static final String[] DICT_TYPES_ORDERED_TO_GET_SUGGESTION =
+ private static final String[] DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS =
new String[] {
Dictionary.TYPE_MAIN,
Dictionary.TYPE_USER_HISTORY,
@@ -89,8 +89,8 @@ public class DictionaryFacilitator {
new Class[] { Context.class, Locale.class, File.class };
private static final String[] SUB_DICT_TYPES =
- Arrays.copyOfRange(DICT_TYPES_ORDERED_TO_GET_SUGGESTION, 1 /* start */,
- DICT_TYPES_ORDERED_TO_GET_SUGGESTION.length);
+ Arrays.copyOfRange(DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS, 1 /* start */,
+ DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS.length);
/**
* Class contains dictionaries for a locale.
@@ -333,7 +333,7 @@ public class DictionaryFacilitator {
dictionaries = mDictionaries;
mDictionaries = new Dictionaries();
}
- for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTION) {
+ for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) {
dictionaries.closeDict(dictType);
}
mDistracterFilter.close();
@@ -469,7 +469,7 @@ public class DictionaryFacilitator {
final SuggestionResults suggestionResults =
new SuggestionResults(dictionaries.mLocale, SuggestedWords.MAX_SUGGESTIONS);
final float[] languageWeight = new float[] { Dictionary.NOT_A_LANGUAGE_WEIGHT };
- for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTION) {
+ for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) {
final Dictionary dictionary = dictionaries.getDict(dictType);
if (null == dictionary) continue;
final ArrayList<SuggestedWordInfo> dictionarySuggestions =
@@ -502,7 +502,7 @@ public class DictionaryFacilitator {
return false;
}
final String lowerCasedWord = word.toLowerCase(dictionaries.mLocale);
- for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTION) {
+ for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) {
final Dictionary dictionary = dictionaries.getDict(dictType);
// Ideally the passed map would come out of a {@link java.util.concurrent.Future} and
// would be immutable once it's finished initializing, but concretely a null test is
@@ -516,16 +516,22 @@ public class DictionaryFacilitator {
return false;
}
- public int getFrequency(final String word) {
+ private int getFrequencyInternal(final String word,
+ final boolean isGettingMaxFrequencyOfExactMatches) {
if (TextUtils.isEmpty(word)) {
return Dictionary.NOT_A_PROBABILITY;
}
- int maxFreq = -1;
+ int maxFreq = Dictionary.NOT_A_PROBABILITY;
final Dictionaries dictionaries = mDictionaries;
- for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTION) {
+ for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) {
final Dictionary dictionary = dictionaries.getDict(dictType);
if (dictionary == null) continue;
- final int tempFreq = dictionary.getFrequency(word);
+ final int tempFreq;
+ if (isGettingMaxFrequencyOfExactMatches) {
+ tempFreq = dictionary.getMaxFrequencyOfExactMatches(word);
+ } else {
+ tempFreq = dictionary.getFrequency(word);
+ }
if (tempFreq >= maxFreq) {
maxFreq = tempFreq;
}
@@ -533,6 +539,14 @@ public class DictionaryFacilitator {
return maxFreq;
}
+ public int getFrequency(final String word) {
+ return getFrequencyInternal(word, false /* isGettingMaxFrequencyOfExactMatches */);
+ }
+
+ public int getMaxFrequencyOfExactMatches(final String word) {
+ return getFrequencyInternal(word, true /* isGettingMaxFrequencyOfExactMatches */);
+ }
+
public void clearUserHistoryDictionary() {
final ExpandableBinaryDictionary userHistoryDict =
mDictionaries.getSubDict(Dictionary.TYPE_USER_HISTORY);
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index b10bae01a..8664c09e4 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -441,6 +441,30 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
return mBinaryDictionary.isValidWord(word);
}
+ @Override
+ public int getMaxFrequencyOfExactMatches(final String word) {
+ reloadDictionaryIfRequired();
+ boolean lockAcquired = false;
+ try {
+ lockAcquired = mLock.readLock().tryLock(
+ TIMEOUT_FOR_READ_OPS_IN_MILLISECONDS, TimeUnit.MILLISECONDS);
+ if (lockAcquired) {
+ if (mBinaryDictionary == null) {
+ return NOT_A_PROBABILITY;
+ }
+ return mBinaryDictionary.getMaxFrequencyOfExactMatches(word);
+ }
+ } catch (final InterruptedException e) {
+ Log.e(TAG, "Interrupted tryLock() in getMaxFrequencyOfExactMatches().", e);
+ } finally {
+ if (lockAcquired) {
+ mLock.readLock().unlock();
+ }
+ }
+ return NOT_A_PROBABILITY;
+ }
+
+
protected boolean isValidNgramLocked(final PrevWordsInfo prevWordsInfo, final String word) {
if (mBinaryDictionary == null) return false;
return mBinaryDictionary.isValidNgram(prevWordsInfo, word);
diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java
index e778a14f6..e1ae3dfe3 100644
--- a/java/src/com/android/inputmethod/latin/InputAttributes.java
+++ b/java/src/com/android/inputmethod/latin/InputAttributes.java
@@ -16,6 +16,9 @@
package com.android.inputmethod.latin;
+import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE;
+import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE_COMPAT;
+
import android.text.InputType;
import android.util.Log;
import android.view.inputmethod.EditorInfo;
@@ -35,12 +38,17 @@ public final class InputAttributes {
final public String mTargetApplicationPackageName;
final public boolean mInputTypeNoAutoCorrect;
final public boolean mIsPasswordField;
- final public boolean mIsSettingsSuggestionStripOn;
+ final public boolean mShouldShowSuggestions;
final public boolean mApplicationSpecifiedCompletionOn;
final public boolean mShouldInsertSpacesAutomatically;
final private int mInputType;
+ final private EditorInfo mEditorInfo;
+ final private String mPackageNameForPrivateImeOptions;
- public InputAttributes(final EditorInfo editorInfo, final boolean isFullscreenMode) {
+ 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;
@@ -62,7 +70,7 @@ public final class InputAttributes {
Log.w(TAG, String.format("Unexpected input class: inputType=0x%08x"
+ " imeOptions=0x%08x", inputType, editorInfo.imeOptions));
}
- mIsSettingsSuggestionStripOn = false;
+ mShouldShowSuggestions = false;
mInputTypeNoAutoCorrect = false;
mApplicationSpecifiedCompletionOn = false;
mShouldInsertSpacesAutomatically = false;
@@ -81,13 +89,13 @@ public final class InputAttributes {
// TODO: Have a helper method in InputTypeUtils
// Make sure that passwords are not displayed in {@link SuggestionStripView}.
- final boolean noSuggestionStrip = mIsPasswordField
+ final boolean shouldSuppressSuggestions = mIsPasswordField
|| InputTypeUtils.isEmailVariation(variation)
|| InputType.TYPE_TEXT_VARIATION_URI == variation
|| InputType.TYPE_TEXT_VARIATION_FILTER == variation
|| flagNoSuggestions
|| flagAutoComplete;
- mIsSettingsSuggestionStripOn = !noSuggestionStrip;
+ mShouldShowSuggestions = !shouldSuppressSuggestions;
mShouldInsertSpacesAutomatically = InputTypeUtils.isAutoSpaceFriendlyType(inputType);
@@ -111,6 +119,15 @@ public final class InputAttributes {
return editorInfo.inputType == mInputType;
}
+ public 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;
@@ -241,7 +258,7 @@ public final class InputAttributes {
mInputType,
(mInputTypeNoAutoCorrect ? " noAutoCorrect" : ""),
(mIsPasswordField ? " password" : ""),
- (mIsSettingsSuggestionStripOn ? " suggestionStrip" : ""),
+ (mShouldShowSuggestions ? " shouldShowSuggestions" : ""),
(mApplicationSpecifiedCompletionOn ? " appSpecified" : ""),
(mShouldInsertSpacesAutomatically ? " insertSpaces" : ""),
mTargetApplicationPackageName);
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index d329d2ce6..709f1334f 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -166,6 +166,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private static final int ARG1_DISMISS_GESTURE_FLOATING_PREVIEW_TEXT = 1;
private static final int ARG1_SHOW_GESTURE_FLOATING_PREVIEW_TEXT = 2;
private static final int ARG2_UNUSED = 0;
+ private static final int ARG1_FALSE = 0;
+ private static final int ARG1_TRUE = 1;
private int mDelayUpdateSuggestions;
private int mDelayUpdateShiftState;
@@ -213,7 +215,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
case MSG_RESUME_SUGGESTIONS:
latinIme.mInputLogic.restartSuggestionsOnWordTouchedByCursor(
latinIme.mSettings.getCurrent(),
- false /* includeResumedWordInSuggestions */);
+ msg.arg1 == ARG1_TRUE /* shouldIncludeResumedWordInSuggestions */);
break;
case MSG_REOPEN_DICTIONARIES:
latinIme.resetSuggest();
@@ -250,7 +252,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
sendMessage(obtainMessage(MSG_REOPEN_DICTIONARIES));
}
- public void postResumeSuggestions() {
+ public void postResumeSuggestions(final boolean shouldIncludeResumedWordInSuggestions) {
final LatinIME latinIme = getOwnerInstance();
if (latinIme == null) {
return;
@@ -260,7 +262,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return;
}
removeMessages(MSG_RESUME_SUGGESTIONS);
- sendMessageDelayed(obtainMessage(MSG_RESUME_SUGGESTIONS), mDelayUpdateSuggestions);
+ sendMessageDelayed(obtainMessage(MSG_RESUME_SUGGESTIONS,
+ shouldIncludeResumedWordInSuggestions ? ARG1_TRUE : ARG1_FALSE,
+ 0 /* ignored */),
+ mDelayUpdateSuggestions);
}
public void postResetCaches(final boolean tryResumeSuggestions, final int remainingTries) {
@@ -522,7 +527,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
void loadSettings() {
final Locale locale = mSubtypeSwitcher.getCurrentSubtypeLocale();
final EditorInfo editorInfo = getCurrentInputEditorInfo();
- final InputAttributes inputAttributes = new InputAttributes(editorInfo, isFullscreenMode());
+ final InputAttributes inputAttributes = new InputAttributes(
+ editorInfo, isFullscreenMode(), getPackageName());
mSettings.loadSettings(this, locale, inputAttributes);
final SettingsValues currentSettingsValues = mSettings.getCurrent();
AudioAndHapticFeedbackManager.getInstance().onSettingsChanged(currentSettingsValues);
@@ -602,7 +608,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mDictionaryFacilitator.resetDictionaries(this /* context */, locale,
settingsValues.mUseContactsDict, settingsValues.mUsePersonalizedDicts,
false /* forceReloadMainDictionary */, this);
- if (settingsValues.mCorrectionEnabled) {
+ if (settingsValues.mAutoCorrectionEnabled) {
mInputLogic.mSuggest.setAutoCorrectionThreshold(
settingsValues.mAutoCorrectionThreshold);
}
@@ -640,14 +646,19 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public void onConfigurationChanged(final Configuration conf) {
- // If orientation changed while predicting, commit the change
final SettingsValues settingsValues = mSettings.getCurrent();
if (settingsValues.mDisplayOrientation != conf.orientation) {
mHandler.startOrientationChanging();
- mInputLogic.mConnection.beginBatchEdit();
- mInputLogic.commitTyped(mSettings.getCurrent(), LastComposedWord.NOT_A_SEPARATOR);
- mInputLogic.mConnection.finishComposingText();
- mInputLogic.mConnection.endBatchEdit();
+ // If !isComposingWord, #commitTyped() is a no-op, but still, it's better to avoid
+ // the useless IPC of {begin,end}BatchEdit.
+ if (mInputLogic.mWordComposer.isComposingWord()) {
+ mInputLogic.mConnection.beginBatchEdit();
+ // If we had a composition in progress, we need to commit the word so that the
+ // suggestionsSpan will be added. This will allow resuming on the same suggestions
+ // after rotation is finished.
+ mInputLogic.commitTyped(mSettings.getCurrent(), LastComposedWord.NOT_A_SEPARATOR);
+ mInputLogic.mConnection.endBatchEdit();
+ }
}
PersonalizationDictionarySessionRegistrar.onConfigurationChanged(this, conf,
mDictionaryFacilitator);
@@ -741,6 +752,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
Log.i(TAG, "Starting input. Cursor position = "
+ editorInfo.initialSelStart + "," + editorInfo.initialSelEnd);
+ // TODO: Consolidate these checks with {@link InputAttributes}.
if (InputAttributes.inPrivateImeOptions(null, NO_MICROPHONE_COMPAT, editorInfo)) {
Log.w(TAG, "Deprecated private IME option specified: " + editorInfo.privateImeOptions);
Log.w(TAG, "Use " + getPackageName() + "." + NO_MICROPHONE + " instead");
@@ -802,7 +814,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// When rotating, initialSelStart and initialSelEnd sometimes are lying. Make a best
// effort to work around this bug.
mInputLogic.mConnection.tryFixLyingCursorPosition();
- mHandler.postResumeSuggestions();
+ mHandler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */);
canReachInputConnection = true;
}
@@ -814,7 +826,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mainKeyboardView.closing();
currentSettingsValues = mSettings.getCurrent();
- if (currentSettingsValues.mCorrectionEnabled) {
+ if (currentSettingsValues.mAutoCorrectionEnabled) {
suggest.setAutoCorrectionThreshold(
currentSettingsValues.mAutoCorrectionThreshold);
}
@@ -991,7 +1003,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
null /* rawSuggestions */, false /* typedWordValid */, false /* willAutoCorrect */,
false /* isObsoleteSuggestions */, false /* isPrediction */);
// When in fullscreen mode, show completions generated by the application forcibly
- setSuggestedWords(suggestedWords, true /* isSuggestionStripVisible */);
+ setSuggestedWords(suggestedWords);
}
private int getAdjustedBackingViewHeight() {
@@ -1294,30 +1306,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Nothing to do so far.
}
- private boolean isSuggestionStripVisible() {
- if (!hasSuggestionStripView()) {
- return false;
- }
- if (mSuggestionStripView.isShowingAddToDictionaryHint()) {
- return true;
- }
- final SettingsValues currentSettings = mSettings.getCurrent();
- if (null == currentSettings) {
- return false;
- }
- if (ImportantNoticeUtils.shouldShowImportantNotice(this,
- currentSettings.mInputAttributes)) {
- return true;
- }
- if (!currentSettings.isCurrentOrientationAllowingSuggestionsPerUserSettings()) {
- return false;
- }
- if (currentSettings.isApplicationSpecifiedCompletionsOn()) {
- return true;
- }
- return currentSettings.isSuggestionsRequested();
- }
-
public boolean hasSuggestionStripView() {
return null != mSuggestionStripView;
}
@@ -1335,9 +1323,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mSuggestionStripView.dismissAddToDictionaryHint();
}
- // TODO[IL]: Define a clear interface for this
- public void setSuggestedWords(final SuggestedWords suggestedWords,
- final boolean isSuggestionStripVisible) {
+ private void setSuggestedWords(final SuggestedWords suggestedWords) {
mInputLogic.setSuggestedWords(suggestedWords);
// TODO: Modify this when we support suggestions with hard keyboard
if (!hasSuggestionStripView()) {
@@ -1346,28 +1332,35 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (!onEvaluateInputViewShown()) {
return;
}
- if (!isSuggestionStripVisible) {
- mSuggestionStripView.setVisibility(isFullscreenMode() ? View.GONE : View.INVISIBLE);
+
+ final SettingsValues currentSettingsValues = mSettings.getCurrent();
+ final boolean shouldShowImportantNotice =
+ ImportantNoticeUtils.shouldShowImportantNotice(this);
+ final boolean shouldShowSuggestionsStripUnlessPassword = shouldShowImportantNotice
+ || currentSettingsValues.mShowsVoiceInputKey
+ || currentSettingsValues.isSuggestionsRequested()
+ || currentSettingsValues.isApplicationSpecifiedCompletionsOn();
+ final boolean shouldShowSuggestionsStrip = shouldShowSuggestionsStripUnlessPassword
+ && !currentSettingsValues.mInputAttributes.mIsPasswordField;
+ mSuggestionStripView.updateVisibility(shouldShowSuggestionsStrip, isFullscreenMode());
+ if (!shouldShowSuggestionsStrip) {
return;
}
- mSuggestionStripView.setVisibility(View.VISIBLE);
- final SettingsValues currentSettings = mSettings.getCurrent();
- final boolean showSuggestions;
- // May show the important notice when there are no suggestions to show,
- if (SuggestedWords.EMPTY == suggestedWords
- // or the suggestion strip is expected to show punctuation suggestions,
+ final boolean isEmptyApplicationSpecifiedCompletions =
+ currentSettingsValues.isApplicationSpecifiedCompletionsOn()
+ && suggestedWords.isEmpty();
+ final boolean noSuggestionsToShow = (SuggestedWords.EMPTY == suggestedWords)
|| suggestedWords.isPunctuationSuggestions()
- // or it's not requested to show suggestions by the input field,
- || !currentSettings.isSuggestionsRequested()
- // or the "show correction suggestions" settings is off by users preference.
- || !currentSettings.isCurrentOrientationAllowingSuggestionsPerUserSettings()) {
- showSuggestions = !mSuggestionStripView.maybeShowImportantNoticeTitle(
- currentSettings.mInputAttributes);
+ || isEmptyApplicationSpecifiedCompletions;
+ final boolean isShowingImportantNotice;
+ if (shouldShowImportantNotice && noSuggestionsToShow) {
+ isShowingImportantNotice = mSuggestionStripView.maybeShowImportantNoticeTitle();
} else {
- showSuggestions = true;
+ isShowingImportantNotice = false;
}
- if (showSuggestions) {
+
+ if (currentSettingsValues.isSuggestionsRequested() && !isShowingImportantNotice) {
mSuggestionStripView.setSuggestions(suggestedWords,
SubtypeLocaleUtils.isRtlLanguage(mSubtypeSwitcher.getCurrentSubtype()));
}
@@ -1410,7 +1403,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mInputLogic.mSuggest.getSuggestedWords(mInputLogic.mWordComposer,
mInputLogic.mWordComposer.getPrevWordsInfoForSuggestion(),
keyboard.getProximityInfo(), currentSettings.mBlockPotentiallyOffensive,
- currentSettings.mCorrectionEnabled, additionalFeaturesOptions, sessionId,
+ currentSettings.mAutoCorrectionEnabled, additionalFeaturesOptions, sessionId,
sequenceNumber, callback);
}
@@ -1430,7 +1423,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
setNeutralSuggestionStrip();
} else {
mInputLogic.mWordComposer.setAutoCorrection(autoCorrection);
- setSuggestedWords(suggestedWords, isSuggestionStripVisible());
+ setSuggestedWords(suggestedWords);
}
// Cache the auto-correction in accessibility code so we can speak it if the user
// touches a key that will insert it.
@@ -1463,7 +1456,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final SettingsValues currentSettings = mSettings.getCurrent();
final SuggestedWords neutralSuggestions = currentSettings.mBigramPredictionEnabled
? SuggestedWords.EMPTY : currentSettings.mSpacingAndPunctuations.mSuggestPuncList;
- setSuggestedWords(neutralSuggestions, isSuggestionStripVisible());
+ setSuggestedWords(neutralSuggestions);
}
// TODO: Make this private
diff --git a/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java
index 8f744bef8..7989346f4 100644
--- a/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ReadOnlyBinaryDictionary.java
@@ -102,6 +102,18 @@ public final class ReadOnlyBinaryDictionary extends Dictionary {
}
@Override
+ public int getMaxFrequencyOfExactMatches(final String word) {
+ if (mLock.readLock().tryLock()) {
+ try {
+ return mBinaryDictionary.getMaxFrequencyOfExactMatches(word);
+ } finally {
+ mLock.readLock().unlock();
+ }
+ }
+ return NOT_A_PROBABILITY;
+ }
+
+ @Override
public void close() {
mLock.writeLock().lock();
try {
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 9d72c64fc..96476b2ee 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -891,4 +891,8 @@ public final class RichInputConnection {
public boolean hasSelection() {
return mExpectedSelEnd != mExpectedSelStart;
}
+
+ public boolean isCursorPositionKnown() {
+ return INVALID_CURSOR_POSITION != mExpectedSelStart;
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index dbbe1a0c5..c90dc90ce 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -319,8 +319,16 @@ public final class InputLogic {
|| !mWordComposer.isComposingWord(); // safe to reset
final boolean hasOrHadSelection = (oldSelStart != oldSelEnd || newSelStart != newSelEnd);
final int moveAmount = newSelStart - oldSelStart;
- if (selectionChangedOrSafeToReset && (hasOrHadSelection
- || !mWordComposer.moveCursorByAndReturnIfInsideComposingWord(moveAmount))) {
+ // As an added small gift from the framework, it happens upon rotation when there
+ // is a selection that we get a wrong cursor position delivered to startInput() that
+ // does not get reflected in the oldSel{Start,End} parameters to the next call to
+ // onUpdateSelection. In this case, we may have set a composition, and when we're here
+ // we realize we shouldn't have. In theory, in this case, selectionChangedOrSafeToReset
+ // should be true, but that is if the framework had taken that wrong cursor position
+ // into account, which means we have to reset the entire composing state whenever there
+ // is or was a selection regardless of whether it changed or not.
+ if (hasOrHadSelection || (selectionChangedOrSafeToReset
+ && !mWordComposer.moveCursorByAndReturnIfInsideComposingWord(moveAmount))) {
// If we are composing a word and moving the cursor, we would want to set a
// suggestion span for recorrection to work correctly. Unfortunately, that
// would involve the keyboard committing some new text, which would move the
@@ -348,7 +356,7 @@ public final class InputLogic {
// The cursor has been moved : we now accept to perform recapitalization
mRecapitalizeStatus.enable();
// We moved the cursor. If we are touching a word, we need to resume suggestion.
- mLatinIME.mHandler.postResumeSuggestions();
+ mLatinIME.mHandler.postResumeSuggestions(false /* shouldIncludeResumedWordInSuggestions */);
// Stop the last recapitalization, if started.
mRecapitalizeStatus.stop();
return true;
@@ -770,7 +778,7 @@ public final class InputLogic {
}
// isComposingWord() may have changed since we stored wasComposing
if (mWordComposer.isComposingWord()) {
- if (settingsValues.mCorrectionEnabled) {
+ if (settingsValues.mAutoCorrectionEnabled) {
final String separator = shouldAvoidSendingCode ? LastComposedWord.NOT_A_SEPARATOR
: StringUtils.newSingleCodePointString(codePoint);
commitCurrentAutoCorrection(settingsValues, separator, handler);
@@ -990,7 +998,7 @@ public final class InputLogic {
&& !mConnection.isCursorFollowedByWordCharacter(
inputTransaction.mSettingsValues.mSpacingAndPunctuations)) {
restartSuggestionsOnWordTouchedByCursor(inputTransaction.mSettingsValues,
- true /* includeResumedWordInSuggestions */);
+ true /* shouldIncludeResumedWordInSuggestions */);
}
}
}
@@ -1173,7 +1181,7 @@ public final class InputLogic {
// If correction is not enabled, we don't add words to the user history dictionary.
// That's to avoid unintended additions in some sensitive fields, or fields that
// expect to receive non-words.
- if (!settingsValues.mCorrectionEnabled) return;
+ if (!settingsValues.mAutoCorrectionEnabled) return;
if (TextUtils.isEmpty(suggestion)) return;
final boolean wasAutoCapitalized =
@@ -1230,12 +1238,12 @@ public final class InputLogic {
* do nothing.
*
* @param settingsValues the current values of the settings.
- * @param includeResumedWordInSuggestions whether to include the word on which we resume
+ * @param shouldIncludeResumedWordInSuggestions whether to include the word on which we resume
* suggestions in the suggestion list.
*/
// TODO: make this private.
public void restartSuggestionsOnWordTouchedByCursor(final SettingsValues settingsValues,
- final boolean includeResumedWordInSuggestions) {
+ final boolean shouldIncludeResumedWordInSuggestions) {
// HACK: We may want to special-case some apps that exhibit bad behavior in case of
// recorrection. This is a temporary, stopgap measure that will be removed later.
// TODO: remove this.
@@ -1281,7 +1289,7 @@ public final class InputLogic {
if (numberOfCharsInWordBeforeCursor > expectedCursorPosition) return;
final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<>();
final String typedWord = range.mWord.toString();
- if (includeResumedWordInSuggestions) {
+ if (shouldIncludeResumedWordInSuggestions) {
suggestions.add(new SuggestedWordInfo(typedWord,
SuggestedWords.MAX_SUGGESTIONS + 1,
SuggestedWordInfo.KIND_TYPED, Dictionary.DICTIONARY_USER_TYPED,
@@ -1319,9 +1327,10 @@ public final class InputLogic {
typedWord.codePointCount(0, numberOfCharsInWordBeforeCursor));
mConnection.setComposingRegion(expectedCursorPosition - numberOfCharsInWordBeforeCursor,
expectedCursorPosition + range.getNumberOfCharsInWordAfterCursor());
- if (suggestions.isEmpty()) {
- // We come here if there weren't any suggestion spans on this word. We will try to
- // compute suggestions for it instead.
+ if (suggestions.size() <= (shouldIncludeResumedWordInSuggestions ? 1 : 0)) {
+ // If there weren't any suggestion spans on this word, suggestions#size() will be 1
+ // if shouldIncludeResumedWordInSuggestions is true, 0 otherwise. In this case, we
+ // have no useful suggestions, so we will try to compute some for it instead.
mInputLogicHandler.getSuggestedWords(Suggest.SESSION_TYPING,
SuggestedWords.NOT_A_SEQUENCE_NUMBER, new OnGetSuggestedWordsCallback() {
@Override
@@ -1329,7 +1338,7 @@ public final class InputLogic {
final SuggestedWords suggestedWordsIncludingTypedWord) {
final SuggestedWords suggestedWords;
if (suggestedWordsIncludingTypedWord.size() > 1
- && !includeResumedWordInSuggestions) {
+ && !shouldIncludeResumedWordInSuggestions) {
// We were able to compute new suggestions for this word.
// Remove the typed word, since we don't want to display it in this
// case. The #getSuggestedWordsExcludingTypedWord() method sets
@@ -1922,9 +1931,11 @@ public final class InputLogic {
final boolean tryResumeSuggestions, final int remainingTries,
// TODO: remove these arguments
final LatinIME.UIHandler handler) {
+ final boolean shouldFinishComposition = mConnection.hasSelection()
+ || !mConnection.isCursorPositionKnown();
if (!mConnection.resetCachesUponCursorMoveAndReturnSuccess(
mConnection.getExpectedSelectionStart(), mConnection.getExpectedSelectionEnd(),
- false /* shouldFinishComposition */)) {
+ shouldFinishComposition)) {
if (0 < remainingTries) {
handler.postResetCaches(tryResumeSuggestions, remainingTries - 1);
return false;
@@ -1934,7 +1945,9 @@ public final class InputLogic {
}
mConnection.tryFixLyingCursorPosition();
if (tryResumeSuggestions) {
- handler.postResumeSuggestions();
+ // This is triggered when starting input anew, so we want to include the resumed
+ // word in suggestions.
+ handler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */);
}
return true;
}
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
index 6c6e79e0f..389d9a869 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
@@ -28,6 +28,7 @@ import com.android.inputmethod.compat.AppWorkaroundsUtils;
import com.android.inputmethod.latin.InputAttributes;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.RichInputMethodManager;
+import com.android.inputmethod.latin.SubtypeSwitcher;
import com.android.inputmethod.latin.utils.AsyncResultHolder;
import com.android.inputmethod.latin.utils.ResourceUtils;
import com.android.inputmethod.latin.utils.TargetPackageInfoGetterTask;
@@ -84,7 +85,7 @@ public final class SettingsValues {
public final int mKeyPreviewPopupDismissDelay;
private final boolean mAutoCorrectEnabled;
public final float mAutoCorrectionThreshold;
- public final boolean mCorrectionEnabled;
+ public final boolean mAutoCorrectionEnabled;
public final int mSuggestionVisibility;
public final int mDisplayOrientation;
private final AsyncResultHolder<AppWorkaroundsUtils> mAppWorkarounds;
@@ -109,7 +110,8 @@ public final class SettingsValues {
// Store the input attributes
if (null == inputAttributes) {
- mInputAttributes = new InputAttributes(null, false /* isFullscreenMode */);
+ mInputAttributes = new InputAttributes(
+ null, false /* isFullscreenMode */, context.getPackageName());
} else {
mInputAttributes = inputAttributes;
}
@@ -121,7 +123,10 @@ public final class SettingsValues {
mKeyPreviewPopupOn = Settings.readKeyPreviewPopupEnabled(prefs, res);
mSlidingKeyInputPreviewEnabled = prefs.getBoolean(
DebugSettings.PREF_SLIDING_KEY_INPUT_PREVIEW, true);
- mShowsVoiceInputKey = needsToShowVoiceInputKey(prefs, res);
+ mShowsVoiceInputKey = needsToShowVoiceInputKey(prefs, res)
+ && !mInputAttributes.mIsPasswordField
+ && !mInputAttributes.hasNoMicrophoneKeyOption()
+ && SubtypeSwitcher.getInstance().isShortcutImeEnabled();
final String autoCorrectionThresholdRawValue = prefs.getString(
Settings.PREF_AUTO_CORRECTION_THRESHOLD,
res.getString(R.string.auto_correction_threshold_mode_index_modest));
@@ -150,7 +155,7 @@ public final class SettingsValues {
mGestureFloatingPreviewTextEnabled = prefs.getBoolean(
Settings.PREF_GESTURE_FLOATING_PREVIEW_TEXT, true);
mPhraseGestureEnabled = Settings.readPhraseGestureEnabled(prefs, res);
- mCorrectionEnabled = mAutoCorrectEnabled && !mInputAttributes.mInputTypeNoAutoCorrect;
+ mAutoCorrectionEnabled = mAutoCorrectEnabled && !mInputAttributes.mInputTypeNoAutoCorrect;
final String showSuggestionsSetting = prefs.getString(
Settings.PREF_SHOW_SUGGESTIONS_SETTING,
res.getString(R.string.prefs_suggestion_visibility_default_value));
@@ -189,8 +194,8 @@ public final class SettingsValues {
}
public boolean isSuggestionsRequested() {
- return mInputAttributes.mIsSettingsSuggestionStripOn
- && (mCorrectionEnabled
+ return mInputAttributes.mShouldShowSuggestions
+ && (mAutoCorrectionEnabled
|| isCurrentOrientationAllowingSuggestionsPerUserSettings());
}
@@ -318,18 +323,18 @@ public final class SettingsValues {
private static boolean needsToShowVoiceInputKey(final SharedPreferences prefs,
final Resources res) {
- if (!prefs.contains(Settings.PREF_VOICE_INPUT_KEY)) {
- // Migrate preference from {@link Settings#PREF_VOICE_MODE_OBSOLETE} to
- // {@link Settings#PREF_VOICE_INPUT_KEY}.
+ // Migrate preference from {@link Settings#PREF_VOICE_MODE_OBSOLETE} to
+ // {@link Settings#PREF_VOICE_INPUT_KEY}.
+ if (prefs.contains(Settings.PREF_VOICE_MODE_OBSOLETE)) {
final String voiceModeMain = res.getString(R.string.voice_mode_main);
final String voiceMode = prefs.getString(
Settings.PREF_VOICE_MODE_OBSOLETE, voiceModeMain);
final boolean shouldShowVoiceInputKey = voiceModeMain.equals(voiceMode);
- prefs.edit().putBoolean(Settings.PREF_VOICE_INPUT_KEY, shouldShowVoiceInputKey).apply();
- }
- // Remove the obsolete preference if exists.
- if (prefs.contains(Settings.PREF_VOICE_MODE_OBSOLETE)) {
- prefs.edit().remove(Settings.PREF_VOICE_MODE_OBSOLETE).apply();
+ prefs.edit()
+ .putBoolean(Settings.PREF_VOICE_INPUT_KEY, shouldShowVoiceInputKey)
+ // Remove the obsolete preference if exists.
+ .remove(Settings.PREF_VOICE_MODE_OBSOLETE)
+ .apply();
}
return prefs.getBoolean(Settings.PREF_VOICE_INPUT_KEY, true);
}
@@ -390,8 +395,8 @@ public final class SettingsValues {
sb.append("" + mAutoCorrectEnabled);
sb.append("\n mAutoCorrectionThreshold = ");
sb.append("" + mAutoCorrectionThreshold);
- sb.append("\n mCorrectionEnabled = ");
- sb.append("" + mCorrectionEnabled);
+ sb.append("\n mAutoCorrectionEnabled = ");
+ sb.append("" + mAutoCorrectionEnabled);
sb.append("\n mSuggestionVisibility = ");
sb.append("" + mSuggestionVisibility);
sb.append("\n mDisplayOrientation = ");
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
index 4a5a7f004..97241498a 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
@@ -42,12 +42,12 @@ import com.android.inputmethod.keyboard.MainKeyboardView;
import com.android.inputmethod.keyboard.MoreKeysPanel;
import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.InputAttributes;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SuggestedWords;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.settings.Settings;
+import com.android.inputmethod.latin.settings.SettingsValues;
import com.android.inputmethod.latin.suggestions.MoreSuggestionsView.MoreSuggestionsListener;
import com.android.inputmethod.latin.utils.ImportantNoticeUtils;
@@ -89,19 +89,17 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
private static class StripVisibilityGroup {
private final View mSuggestionStripView;
private final View mSuggestionsStrip;
- private final View mVoiceKey;
private final View mAddToDictionaryStrip;
private final View mImportantNoticeStrip;
public StripVisibilityGroup(final View suggestionStripView,
- final ViewGroup suggestionsStrip, final ImageButton voiceKey,
- final ViewGroup addToDictionaryStrip, final View importantNoticeStrip) {
+ final ViewGroup suggestionsStrip, final ViewGroup addToDictionaryStrip,
+ final View importantNoticeStrip) {
mSuggestionStripView = suggestionStripView;
mSuggestionsStrip = suggestionsStrip;
- mVoiceKey = voiceKey;
mAddToDictionaryStrip = addToDictionaryStrip;
mImportantNoticeStrip = importantNoticeStrip;
- showSuggestionsStrip(false /* voiceKeyEnabled */);
+ showSuggestionsStrip();
}
public void setLayoutDirection(final boolean isRtlLanguage) {
@@ -113,23 +111,20 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
ViewCompat.setLayoutDirection(mImportantNoticeStrip, layoutDirection);
}
- public void showSuggestionsStrip(final boolean enableVoiceKey) {
+ public void showSuggestionsStrip() {
mSuggestionsStrip.setVisibility(VISIBLE);
- mVoiceKey.setVisibility(enableVoiceKey ? VISIBLE : INVISIBLE);
mAddToDictionaryStrip.setVisibility(INVISIBLE);
mImportantNoticeStrip.setVisibility(INVISIBLE);
}
public void showAddToDictionaryStrip() {
mSuggestionsStrip.setVisibility(INVISIBLE);
- mVoiceKey.setVisibility(INVISIBLE);
mAddToDictionaryStrip.setVisibility(VISIBLE);
mImportantNoticeStrip.setVisibility(INVISIBLE);
}
- public void showImportantNoticeStrip(final boolean enableVoiceKey) {
+ public void showImportantNoticeStrip() {
mSuggestionsStrip.setVisibility(INVISIBLE);
- mVoiceKey.setVisibility(enableVoiceKey ? VISIBLE : INVISIBLE);
mAddToDictionaryStrip.setVisibility(INVISIBLE);
mImportantNoticeStrip.setVisibility(VISIBLE);
}
@@ -159,7 +154,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
mVoiceKey = (ImageButton)findViewById(R.id.suggestions_strip_voice_key);
mAddToDictionaryStrip = (ViewGroup)findViewById(R.id.add_to_dictionary_strip);
mImportantNoticeStrip = findViewById(R.id.important_notice_strip);
- mStripVisibilityGroup = new StripVisibilityGroup(this, mSuggestionsStrip, mVoiceKey,
+ mStripVisibilityGroup = new StripVisibilityGroup(this, mSuggestionsStrip,
mAddToDictionaryStrip, mImportantNoticeStrip);
for (int pos = 0; pos < SuggestedWords.MAX_SUGGESTIONS; pos++) {
@@ -207,15 +202,11 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
mMainKeyboardView = (MainKeyboardView)inputView.findViewById(R.id.keyboard_view);
}
- private boolean isVoiceKeyEnabled() {
- if (mMainKeyboardView == null) {
- return false;
- }
- final Keyboard keyboard = mMainKeyboardView.getKeyboard();
- if (keyboard == null) {
- return false;
- }
- return keyboard.mId.mHasShortcutKey;
+ public void updateVisibility(final boolean shouldBeVisible, final boolean isFullscreenMode) {
+ final int visibility = shouldBeVisible ? VISIBLE : (isFullscreenMode ? GONE : INVISIBLE);
+ setVisibility(visibility);
+ final SettingsValues currentSettingsValues = Settings.getInstance().getCurrent();
+ mVoiceKey.setVisibility(currentSettingsValues.mShowsVoiceInputKey ? VISIBLE : INVISIBLE);
}
public void setSuggestions(final SuggestedWords suggestedWords, final boolean isRtlLanguage) {
@@ -224,7 +215,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
mSuggestedWords = suggestedWords;
mSuggestionsCountInStrip = mLayoutHelper.layoutAndReturnSuggestionCountInStrip(
mSuggestedWords, mSuggestionsStrip, this);
- mStripVisibilityGroup.showSuggestionsStrip(isVoiceKeyEnabled());
+ mStripVisibilityGroup.showSuggestionsStrip();
}
public int setMoreSuggestionsHeight(final int remainingHeight) {
@@ -255,8 +246,8 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
// This method checks if we should show the important notice (checks on permanent storage if
// it has been shown once already or not, and if in the setup wizard). If applicable, it shows
// the notice. In all cases, it returns true if it was shown, false otherwise.
- public boolean maybeShowImportantNoticeTitle(final InputAttributes inputAttributes) {
- if (!ImportantNoticeUtils.shouldShowImportantNotice(getContext(), inputAttributes)) {
+ public boolean maybeShowImportantNoticeTitle() {
+ if (!ImportantNoticeUtils.shouldShowImportantNotice(getContext())) {
return false;
}
if (getWidth() <= 0) {
@@ -271,7 +262,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
dismissMoreSuggestionsPanel();
}
mLayoutHelper.layoutImportantNotice(mImportantNoticeStrip, importantNoticeTitle);
- mStripVisibilityGroup.showImportantNoticeStrip(isVoiceKeyEnabled());
+ mStripVisibilityGroup.showImportantNoticeStrip();
mImportantNoticeStrip.setOnClickListener(this);
return true;
}
@@ -279,7 +270,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
public void clear() {
mSuggestionsStrip.removeAllViews();
removeAllDebugInfoViews();
- mStripVisibilityGroup.showSuggestionsStrip(false /* enableVoiceKey */);
+ mStripVisibilityGroup.showSuggestionsStrip();
dismissMoreSuggestionsPanel();
}
@@ -481,7 +472,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
// Called by the framework when the size is known. Show the important notice if applicable.
// This may be overriden by showing suggestions later, if applicable.
if (oldw <= 0 && w > 0) {
- maybeShowImportantNoticeTitle(Settings.getInstance().getCurrent().mInputAttributes);
+ maybeShowImportantNoticeTitle();
}
}
}
diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java
index 80d4cc44f..eda81940f 100644
--- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java
+++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordContents.java
@@ -167,7 +167,9 @@ public class UserDictionaryAddWordContents {
// should not insert, because either A. the word exists with no shortcut, in which
// case the exact same thing we want to insert is already there, or B. the word
// exists with at least one shortcut, in which case it has priority on our word.
- if (hasWord(newWord, context)) return CODE_ALREADY_PRESENT;
+ if (TextUtils.isEmpty(newShortcut) && hasWord(newWord, context)) {
+ return CODE_ALREADY_PRESENT;
+ }
// Disallow duplicates. If the same word with no shortcut is defined, remove it; if
// the same word with the same shortcut is defined, remove it; but we don't mind if
diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilterUsingSuggestion.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilterUsingSuggestion.java
index b9c7f5671..8c3844ed8 100644
--- a/java/src/com/android/inputmethod/latin/utils/DistracterFilterUsingSuggestion.java
+++ b/java/src/com/android/inputmethod/latin/utils/DistracterFilterUsingSuggestion.java
@@ -16,33 +16,22 @@
package com.android.inputmethod.latin.utils;
-import java.util.HashMap;
import java.util.List;
import java.util.Locale;
-import java.util.Map;
import java.util.concurrent.TimeUnit;
import android.content.Context;
-import android.content.res.Resources;
-import android.text.InputType;
import android.util.Log;
-import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodSubtype;
-import com.android.inputmethod.keyboard.Keyboard;
-import com.android.inputmethod.keyboard.KeyboardId;
-import com.android.inputmethod.keyboard.KeyboardLayoutSet;
-import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.DictionaryFacilitator;
import com.android.inputmethod.latin.PrevWordsInfo;
-import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
-import com.android.inputmethod.latin.WordComposer;
/**
* This class is used to prevent distracters being added to personalization
* or user history dictionaries
*/
+// TODO: Rename.
public class DistracterFilterUsingSuggestion implements DistracterFilter {
private static final String TAG = DistracterFilterUsingSuggestion.class.getSimpleName();
private static final boolean DEBUG = false;
@@ -50,10 +39,7 @@ public class DistracterFilterUsingSuggestion implements DistracterFilter {
private static final long TIMEOUT_TO_WAIT_LOADING_DICTIONARIES_IN_SECONDS = 120;
private final Context mContext;
- private final Map<Locale, InputMethodSubtype> mLocaleToSubtypeMap;
- private final Map<Locale, Keyboard> mLocaleToKeyboardMap;
private final DictionaryFacilitator mDictionaryFacilitator;
- private Keyboard mKeyboard;
private final Object mLock = new Object();
/**
@@ -63,10 +49,7 @@ public class DistracterFilterUsingSuggestion implements DistracterFilter {
*/
public DistracterFilterUsingSuggestion(final Context context) {
mContext = context;
- mLocaleToSubtypeMap = new HashMap<>();
- mLocaleToKeyboardMap = new HashMap<>();
mDictionaryFacilitator = new DictionaryFacilitator();
- mKeyboard = null;
}
@Override
@@ -76,94 +59,6 @@ public class DistracterFilterUsingSuggestion implements DistracterFilter {
@Override
public void updateEnabledSubtypes(final List<InputMethodSubtype> enabledSubtypes) {
- final Map<Locale, InputMethodSubtype> newLocaleToSubtypeMap = new HashMap<>();
- if (enabledSubtypes != null) {
- for (final InputMethodSubtype subtype : enabledSubtypes) {
- final Locale locale = SubtypeLocaleUtils.getSubtypeLocale(subtype);
- if (newLocaleToSubtypeMap.containsKey(locale)) {
- // Multiple subtypes are enabled for one locale.
- // TODO: Investigate what we should do for this case.
- continue;
- }
- newLocaleToSubtypeMap.put(locale, subtype);
- }
- }
- if (mLocaleToSubtypeMap.equals(newLocaleToSubtypeMap)) {
- // Enabled subtypes have not been changed.
- return;
- }
- synchronized (mLock) {
- mLocaleToSubtypeMap.clear();
- mLocaleToSubtypeMap.putAll(newLocaleToSubtypeMap);
- mLocaleToKeyboardMap.clear();
- }
- }
-
- private boolean isDistracter(
- final SuggestionResults suggestionResults, final String consideredWord) {
- int perfectMatchProbability = Dictionary.NOT_A_PROBABILITY;
- for (final SuggestedWordInfo suggestedWordInfo : suggestionResults) {
- if (suggestedWordInfo.mWord.equals(consideredWord)) {
- perfectMatchProbability = mDictionaryFacilitator.getFrequency(consideredWord);
- continue;
- }
- // Exact match can include case errors, accent errors, digraph conversions.
- final boolean isExactMatch = suggestedWordInfo.isExactMatch();
- final boolean isExactMatchWithIntentionalOmission =
- suggestedWordInfo.isExactMatchWithIntentionalOmission();
-
- if (DEBUG) {
- final float normalizedScore = BinaryDictionaryUtils.calcNormalizedScore(
- consideredWord, suggestedWordInfo.mWord, suggestedWordInfo.mScore);
- Log.d(TAG, "consideredWord: " + consideredWord);
- Log.d(TAG, "top suggestion: " + suggestedWordInfo.mWord);
- Log.d(TAG, "suggestionScore: " + suggestedWordInfo.mScore);
- Log.d(TAG, "normalizedScore: " + normalizedScore);
- Log.d(TAG, "isExactMatch: " + isExactMatch);
- Log.d(TAG, "isExactMatchWithIntentionalOmission: "
- + isExactMatchWithIntentionalOmission);
- }
- if (perfectMatchProbability != Dictionary.NOT_A_PROBABILITY) {
- final int topNonPerfectProbability = mDictionaryFacilitator.getFrequency(
- suggestedWordInfo.mWord);
- if (DEBUG) {
- Log.d(TAG, "perfectMatchProbability: " + perfectMatchProbability);
- Log.d(TAG, "topNonPerfectProbability: " + topNonPerfectProbability);
- }
- if (perfectMatchProbability > topNonPerfectProbability) {
- return false;
- }
- }
- return isExactMatch || isExactMatchWithIntentionalOmission;
- }
- return false;
- }
-
- private void loadKeyboardForLocale(final Locale newLocale) {
- final Keyboard cachedKeyboard = mLocaleToKeyboardMap.get(newLocale);
- if (cachedKeyboard != null) {
- mKeyboard = cachedKeyboard;
- return;
- }
- final InputMethodSubtype subtype;
- synchronized (mLock) {
- subtype = mLocaleToSubtypeMap.get(newLocale);
- }
- if (subtype == null) {
- return;
- }
- final EditorInfo editorInfo = new EditorInfo();
- editorInfo.inputType = InputType.TYPE_CLASS_TEXT;
- final KeyboardLayoutSet.Builder builder = new KeyboardLayoutSet.Builder(
- mContext, editorInfo);
- final Resources res = mContext.getResources();
- final int keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res);
- final int keyboardHeight = ResourceUtils.getDefaultKeyboardHeight(res);
- builder.setKeyboardGeometry(keyboardWidth, keyboardHeight);
- builder.setSubtype(subtype);
- builder.setIsSpellChecker(false /* isSpellChecker */);
- final KeyboardLayoutSet layoutSet = builder.build();
- mKeyboard = layoutSet.getKeyboard(KeyboardId.ELEMENT_ALPHABET);
}
private void loadDictionariesForLocale(final Locale newlocale) throws InterruptedException {
@@ -191,12 +86,6 @@ public class DistracterFilterUsingSuggestion implements DistracterFilter {
}
if (!locale.equals(mDictionaryFacilitator.getLocale())) {
synchronized (mLock) {
- if (!mLocaleToSubtypeMap.containsKey(locale)) {
- Log.e(TAG, "Locale " + locale + " is not enabled.");
- // TODO: Investigate what we should do for disabled locales.
- return false;
- }
- loadKeyboardForLocale(locale);
// Reset dictionaries for the locale.
try {
loadDictionariesForLocale(locale);
@@ -207,37 +96,17 @@ public class DistracterFilterUsingSuggestion implements DistracterFilter {
}
}
}
- if (mKeyboard == null) {
- return false;
+ // The tested word is a distracter when there is a word that is exact matched to the tested
+ // word and its probability is higher than the tested word's probability.
+ final int perfectMatchFreq = mDictionaryFacilitator.getFrequency(testedWord);
+ final int exactMatchFreq = mDictionaryFacilitator.getMaxFrequencyOfExactMatches(testedWord);
+ final boolean isDistracter = perfectMatchFreq < exactMatchFreq;
+ if (DEBUG) {
+ Log.d(TAG, "testedWord: " + testedWord);
+ Log.d(TAG, "perfectMatchFreq: " + perfectMatchFreq);
+ Log.d(TAG, "exactMatchFreq: " + exactMatchFreq);
+ Log.d(TAG, "isDistracter: " + isDistracter);
}
- final WordComposer composer = new WordComposer();
- final int[] codePoints = StringUtils.toCodePointArray(testedWord);
- final int[] coordinates = mKeyboard.getCoordinates(codePoints);
- composer.setComposingWord(codePoints, coordinates, PrevWordsInfo.EMPTY_PREV_WORDS_INFO);
-
- final int trailingSingleQuotesCount = StringUtils.getTrailingSingleQuotesCount(testedWord);
- final String consideredWord = trailingSingleQuotesCount > 0 ?
- testedWord.substring(0, testedWord.length() - trailingSingleQuotesCount) :
- testedWord;
- final AsyncResultHolder<Boolean> holder = new AsyncResultHolder<>();
- ExecutorUtils.getExecutor("check distracters").execute(new Runnable() {
- @Override
- public void run() {
- final SuggestionResults suggestionResults =
- mDictionaryFacilitator.getSuggestionResults(
- composer, PrevWordsInfo.EMPTY_PREV_WORDS_INFO,
- mKeyboard.getProximityInfo(), true /* blockOffensiveWords */,
- null /* additionalFeaturesOptions */, 0 /* sessionId */,
- null /* rawSuggestions */);
- if (suggestionResults.isEmpty()) {
- holder.set(false);
- return;
- }
- holder.set(isDistracter(suggestionResults, consideredWord));
- }
- });
- // It's OK to block the distracter filtering, but the dictionary lookup should be done
- // sequentially using ExecutorUtils.
- return holder.get(false /* defaultValue */, Constants.GET_SUGGESTED_WORDS_TIMEOUT);
+ return isDistracter;
}
}
diff --git a/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java b/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java
index 7d937a9d2..8b7077879 100644
--- a/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/ImportantNoticeUtils.java
@@ -23,7 +23,6 @@ import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
import android.util.Log;
-import com.android.inputmethod.latin.InputAttributes;
import com.android.inputmethod.latin.R;
public final class ImportantNoticeUtils {
@@ -78,14 +77,7 @@ public final class ImportantNoticeUtils {
return getCurrentImportantNoticeVersion(context) > lastVersion;
}
- public static boolean shouldShowImportantNotice(final Context context,
- final InputAttributes inputAttributes) {
- if (inputAttributes == null || inputAttributes.mIsPasswordField) {
- return false;
- }
- if (isInSystemSetupWizard(context)) {
- return false;
- }
+ public static boolean shouldShowImportantNotice(final Context context) {
if (!hasNewImportantNotice(context)) {
return false;
}
@@ -93,6 +85,9 @@ public final class ImportantNoticeUtils {
if (TextUtils.isEmpty(importantNoticeTitle)) {
return false;
}
+ if (isInSystemSetupWizard(context)) {
+ return false;
+ }
return true;
}