aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/res/layout/hint_add_to_dictionary.xml36
-rw-r--r--java/res/layout/suggestions_strip.xml2
-rw-r--r--java/res/values-ne-rNP/strings.xml2
-rw-r--r--java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java80
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java3
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java2
-rw-r--r--java/src/com/android/inputmethod/latin/Constants.java4
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java25
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java100
-rw-r--r--java/src/com/android/inputmethod/latin/SuggestedWords.java2
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java31
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java11
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java23
-rw-r--r--java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java18
-rw-r--r--native/jni/src/suggest/core/dictionary/suggestions_output_utils.cpp10
-rw-r--r--native/jni/src/suggest/core/policy/scoring.h8
-rw-r--r--native/jni/src/suggest/policyimpl/typing/typing_scoring.h10
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java24
18 files changed, 231 insertions, 160 deletions
diff --git a/java/res/layout/hint_add_to_dictionary.xml b/java/res/layout/hint_add_to_dictionary.xml
deleted file mode 100644
index d42908260..000000000
--- a/java/res/layout/hint_add_to_dictionary.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-**
-** Copyright 2012, 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.
-*/
--->
-
-<!-- This is derived from suggestion_word.xml without minWidth attribute and padding -->
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:textSize="@dimen/config_suggestion_text_size"
- android:gravity="center"
- android:paddingLeft="0dp"
- android:paddingTop="0dp"
- android:paddingRight="0dp"
- android:paddingBottom="0dp"
- android:focusable="false"
- android:clickable="false"
- android:singleLine="true"
- android:ellipsize="none"
- style="?attr/suggestionWordStyle" />
diff --git a/java/res/layout/suggestions_strip.xml b/java/res/layout/suggestions_strip.xml
index 2ffac179c..85d60e681 100644
--- a/java/res/layout/suggestions_strip.xml
+++ b/java/res/layout/suggestions_strip.xml
@@ -37,7 +37,7 @@
<include
layout="@layout/suggestion_divider" />
<include
- layout="@layout/hint_add_to_dictionary"
+ layout="@layout/suggestion_word"
android:id="@+id/hint_add_to_dictionary" />
</LinearLayout>
</merge>
diff --git a/java/res/values-ne-rNP/strings.xml b/java/res/values-ne-rNP/strings.xml
index c4792dc5a..168806e77 100644
--- a/java/res/values-ne-rNP/strings.xml
+++ b/java/res/values-ne-rNP/strings.xml
@@ -76,7 +76,7 @@
<string name="gesture_floating_preview_text" msgid="4443240334739381053">"गतिशील फ्लोटिङ पूर्वावलोकन"</string>
<string name="gesture_floating_preview_text_summary" msgid="4472696213996203533">"इशारा गर्दा सुझाव दिइएको शब्द हेर्नुहोस्"</string>
<string name="gesture_space_aware" msgid="2078291600664682496">"वाक्यांश इशारा"</string>
- <string name="gesture_space_aware_summary" msgid="4371385818348528538">"इशारा सत्र दैरान space दिखिल गर्न space key मा ग्लाइडि गर्नुहोस्"</string>
+ <string name="gesture_space_aware_summary" msgid="4371385818348528538">"इशाराको बखतमा स्पेस कुञ्जीमा ग्लाईडिंग द्वारा आगत खाली ठाउँहरू"</string>
<string name="added_word" msgid="8993883354622484372">"<xliff:g id="WORD">%s</xliff:g> : बचत गरियो"</string>
<string name="spoken_use_headphones" msgid="896961781287283493">"हेडसेट प्लग इन गर्नुहोस्"</string>
<string name="spoken_current_text_is" msgid="2485723011272583845">"वर्तमान पाठ %s हो"</string>
diff --git a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java
index 5bde668e1..672759aee 100644
--- a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java
+++ b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java
@@ -73,7 +73,7 @@ import java.util.concurrent.TimeUnit;
* Because of the above reasons, this class doesn't extend {@link KeyboardView}.
*/
public final class EmojiPalettesView extends LinearLayout implements OnTabChangeListener,
- ViewPager.OnPageChangeListener, View.OnTouchListener,
+ ViewPager.OnPageChangeListener, View.OnClickListener, View.OnTouchListener,
EmojiPageKeyboardView.OnKeyEventListener {
static final String TAG = EmojiPalettesView.class.getSimpleName();
private static final boolean DEBUG_PAGER = false;
@@ -482,22 +482,31 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
final LinearLayout actionBar = (LinearLayout)findViewById(R.id.emoji_action_bar);
mEmojiLayoutParams.setActionBarProperties(actionBar);
+ // deleteKey depends only on OnTouchListener.
final ImageView deleteKey = (ImageView)findViewById(R.id.emoji_keyboard_delete);
deleteKey.setTag(Constants.CODE_DELETE);
deleteKey.setOnTouchListener(mDeleteKeyOnTouchListener);
+
+ // alphabetKey, alphabetKey2, and spaceKey depend on {@link View.OnClickListener} as well as
+ // {@link View.OnTouchListener}. {@link View.OnTouchListener} is used as the trigger of
+ // key-press, while {@link View.OnClickListener} is used as the trigger of key-release which
+ // does not occur if the event is canceled by moving off the finger from the view.
final ImageView alphabetKey = (ImageView)findViewById(R.id.emoji_keyboard_alphabet);
alphabetKey.setBackgroundResource(mEmojiFunctionalKeyBackgroundId);
- alphabetKey.setTag(Constants.CODE_SWITCH_ALPHA_SYMBOL);
+ alphabetKey.setTag(Constants.CODE_ALPHA_FROM_EMOJI);
alphabetKey.setOnTouchListener(this);
+ alphabetKey.setOnClickListener(this);
+ final ImageView alphabetKey2 = (ImageView)findViewById(R.id.emoji_keyboard_alphabet2);
+ alphabetKey2.setBackgroundResource(mEmojiFunctionalKeyBackgroundId);
+ alphabetKey2.setTag(Constants.CODE_ALPHA_FROM_EMOJI);
+ alphabetKey2.setOnTouchListener(this);
+ alphabetKey2.setOnClickListener(this);
final ImageView spaceKey = (ImageView)findViewById(R.id.emoji_keyboard_space);
spaceKey.setBackgroundResource(mKeyBackgroundId);
spaceKey.setTag(Constants.CODE_SPACE);
spaceKey.setOnTouchListener(this);
+ spaceKey.setOnClickListener(this);
mEmojiLayoutParams.setKeyProperties(spaceKey);
- final ImageView alphabetKey2 = (ImageView)findViewById(R.id.emoji_keyboard_alphabet2);
- alphabetKey2.setBackgroundResource(mEmojiFunctionalKeyBackgroundId);
- alphabetKey2.setTag(Constants.CODE_SWITCH_ALPHA_SYMBOL);
- alphabetKey2.setOnTouchListener(this);
}
@Override
@@ -507,7 +516,6 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
updateEmojiCategoryPageIdView();
}
-
@Override
public void onPageSelected(final int position) {
final Pair<Integer, Integer> newPos =
@@ -545,40 +553,62 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
}
}
- // Called from {@link EmojiPageKeyboardView} through {@link View.OnTouchListener} interface to
- // handle touch events from View-based elements such as the space bar.
+ /**
+ * Called from {@link EmojiPageKeyboardView} through {@link android.view.View.OnTouchListener}
+ * interface to handle touch events from View-based elements such as the space bar.
+ * Note that this method is used only for observing {@link MotionEvent#ACTION_DOWN} to trigger
+ * {@link KeyboardActionListener#onPressKey}. {@link KeyboardActionListener#onReleaseKey} will
+ * be covered by {@link #onClick} as long as the event is not canceled.
+ */
@Override
public boolean onTouch(final View v, final MotionEvent event) {
+ if (event.getActionMasked() != MotionEvent.ACTION_DOWN) {
+ return false;
+ }
final Object tag = v.getTag();
if (!(tag instanceof Integer)) {
return false;
}
final int code = (Integer) tag;
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- mKeyboardActionListener.onPressKey(
- code, 0 /* repeatCount */, true /* isSinglePointer */);
- break;
- case MotionEvent.ACTION_UP:
- mKeyboardActionListener.onCodeInput(code, NOT_A_COORDINATE, NOT_A_COORDINATE);
- mKeyboardActionListener.onReleaseKey(code, false /* withSliding */);
- break;
- }
+ mKeyboardActionListener.onPressKey(
+ code, 0 /* repeatCount */, true /* isSinglePointer */);
+ // It's important to return false here. Otherwise, {@link #onClick} and touch-down visual
+ // feedback stop working.
return false;
}
- // Called from {@link EmojiPageKeyboardView} through
- // {@link EmojiPageKeyboardView.OnKeyEventListener} interface to handle touch events from
- // non-View-based elements like typical Emoji characters.
+ /**
+ * Called from {@link EmojiPageKeyboardView} through {@link android.view.View.OnClickListener}
+ * interface to handle non-canceled touch-up events from View-based elements such as the space
+ * bar.
+ */
+ @Override
+ public void onClick(View v) {
+ final Object tag = v.getTag();
+ if (!(tag instanceof Integer)) {
+ return;
+ }
+ final int code = (Integer) tag;
+ mKeyboardActionListener.onCodeInput(code, NOT_A_COORDINATE, NOT_A_COORDINATE);
+ mKeyboardActionListener.onReleaseKey(code, false /* withSliding */);
+ }
+
+ /**
+ * Called from {@link EmojiPageKeyboardView} through
+ * {@link com.android.inputmethod.keyboard.internal.EmojiPageKeyboardView.OnKeyEventListener}
+ * interface to handle touch events from non-View-based elements such as Emoji buttons.
+ */
@Override
public void onPressKey(final Key key) {
final int code = key.getCode();
mKeyboardActionListener.onPressKey(code, 0 /* repeatCount */, true /* isSinglePointer */);
}
- // Called from {@link EmojiPageKeyboardView} through
- // {@link EmojiPageKeyboardView.OnKeyEventListener} interface to handle touch events from
- // non-View-based elements like typical Emoji characters.
+ /**
+ * Called from {@link EmojiPageKeyboardView} through
+ * {@link com.android.inputmethod.keyboard.internal.EmojiPageKeyboardView.OnKeyEventListener}
+ * interface to handle touch events from non-View-based elements such as Emoji buttons.
+ */
@Override
public void onReleaseKey(final Key key) {
mEmojiPalettesAdapter.addRecentKey(key);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
index dc815e57d..78809d53b 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardCodesSet.java
@@ -54,6 +54,7 @@ public final class KeyboardCodesSet {
"key_shift_enter",
"key_language_switch",
"key_emoji",
+ "key_alpha_from_emoji",
"key_unspecified",
"key_left_parenthesis",
"key_right_parenthesis",
@@ -91,6 +92,7 @@ public final class KeyboardCodesSet {
Constants.CODE_SHIFT_ENTER,
Constants.CODE_LANGUAGE_SWITCH,
Constants.CODE_EMOJI,
+ Constants.CODE_ALPHA_FROM_EMOJI,
Constants.CODE_UNSPECIFIED,
CODE_LEFT_PARENTHESIS,
CODE_RIGHT_PARENTHESIS,
@@ -119,6 +121,7 @@ public final class KeyboardCodesSet {
DEFAULT[13],
DEFAULT[14],
DEFAULT[15],
+ DEFAULT[16],
CODE_RIGHT_PARENTHESIS,
CODE_LEFT_PARENTHESIS,
CODE_GREATER_THAN_SIGN,
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index 0c80ce206..ec0b5c95f 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -645,6 +645,8 @@ public final class KeyboardState {
updateAlphabetShiftState(autoCaps, RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE);
} else if (code == Constants.CODE_EMOJI) {
setEmojiKeyboard();
+ } else if (code == Constants.CODE_ALPHA_FROM_EMOJI) {
+ setAlphabetKeyboard();
}
}
diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java
index 0477133d7..0b396b1de 100644
--- a/java/src/com/android/inputmethod/latin/Constants.java
+++ b/java/src/com/android/inputmethod/latin/Constants.java
@@ -217,8 +217,9 @@ public final class Constants {
public static final int CODE_EMOJI = -11;
public static final int CODE_SHIFT_ENTER = -12;
public static final int CODE_SYMBOL_SHIFT = -13;
+ public static final int CODE_ALPHA_FROM_EMOJI = -14;
// Code value representing the code is not specified.
- public static final int CODE_UNSPECIFIED = -14;
+ public static final int CODE_UNSPECIFIED = -15;
public static boolean isLetterCode(final int code) {
return code >= CODE_SPACE;
@@ -241,6 +242,7 @@ public final class Constants {
case CODE_UNSPECIFIED: return "unspec";
case CODE_TAB: return "tab";
case CODE_ENTER: return "enter";
+ case CODE_ALPHA_FROM_EMOJI: return "alpha";
default:
if (code < CODE_SPACE) return String.format("'\\u%02x'", code);
if (code < 0x100) return String.format("'%c'", code);
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
index fb9517220..8a8a45f35 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
@@ -44,6 +44,10 @@ import java.util.concurrent.TimeUnit;
public class DictionaryFacilitatorForSuggest {
public static final String TAG = DictionaryFacilitatorForSuggest.class.getSimpleName();
+ // HACK: This threshold is being used when adding a capitalized entry in the User History
+ // dictionary.
+ private static final int CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT = 140;
+
private final Context mContext;
public final Locale mLocale;
@@ -389,7 +393,26 @@ public class DictionaryFacilitatorForSuggest {
if (maxFreq == 0) {
return;
}
- final String secondWord = wasAutoCapitalized ? suggestion.toLowerCase(mLocale) : suggestion;
+ final String suggestionLowerCase = suggestion.toLowerCase(mLocale);
+ final String secondWord;
+ if (wasAutoCapitalized) {
+ secondWord = suggestionLowerCase;
+ } else {
+ // HACK: We'd like to avoid adding the capitalized form of common words to the User
+ // History dictionary in order to avoid suggesting them until the dictionary
+ // consolidation is done.
+ // TODO: Remove this hack when ready.
+ final int lowerCasefreqInMainDict = mMainDictionary != null ?
+ mMainDictionary.getFrequency(suggestionLowerCase) :
+ Dictionary.NOT_A_PROBABILITY;
+ if (maxFreq < lowerCasefreqInMainDict
+ && lowerCasefreqInMainDict >= CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT) {
+ // Use lower cased word as the word can be a distracter of the popular word.
+ secondWord = suggestionLowerCase;
+ } else {
+ secondWord = suggestion;
+ }
+ }
// We demote unrecognized words (frequency < 0, below) by specifying them as "invalid".
// We don't add words with 0-frequency (assuming they would be profanity etc.).
final boolean isValid = maxFreq > 0;
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index ba7503dae..e8ea5e39d 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -84,6 +84,7 @@ import com.android.inputmethod.latin.utils.IntentUtils;
import com.android.inputmethod.latin.utils.JniUtils;
import com.android.inputmethod.latin.utils.LatinImeLoggerUtils;
import com.android.inputmethod.latin.utils.LeakGuardHandlerWrapper;
+import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
import com.android.inputmethod.research.ResearchLogger;
import java.io.FileDescriptor;
@@ -192,9 +193,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (msg.arg2 == ARG2_WITH_TYPED_WORD) {
final Pair<SuggestedWords, String> p =
(Pair<SuggestedWords, String>) msg.obj;
- latinIme.showSuggestionStripWithTypedWord(p.first, p.second);
+ // [IL]: this is the only place where the second arg is not
+ // suggestedWords.mTypedWord.
+ latinIme.showSuggestionStrip(p.first, p.second);
} else {
- latinIme.showSuggestionStrip((SuggestedWords) msg.obj);
+ final SuggestedWords suggestedWords = (SuggestedWords) msg.obj;
+ latinIme.showSuggestionStrip(suggestedWords, suggestedWords.mTypedWord);
}
} else {
latinIme.showGesturePreviewAndSuggestionStrip((SuggestedWords) msg.obj,
@@ -1010,9 +1014,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
false /* isObsoleteSuggestions */,
false /* isPrediction */);
// When in fullscreen mode, show completions generated by the application
- setSuggestedWords(suggestedWords);
- setAutoCorrectionIndicator(false);
- setSuggestionStripShown(true);
+ setSuggestedWords(suggestedWords, true /* shouldShow */);
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_onDisplayCompletions(applicationSpecifiedCompletions);
}
@@ -1021,22 +1023,17 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void setSuggestionStripShownInternal(final boolean shown,
final boolean needsInputViewShown) {
// TODO: Modify this if we support suggestions with hard keyboard
- if (onEvaluateInputViewShown() && mSuggestionStripView != null) {
- final boolean inputViewShown = mKeyboardSwitcher.isShowingMainKeyboardOrEmojiPalettes();
- final boolean shouldShowSuggestions = shown
- && (needsInputViewShown ? inputViewShown : true);
- if (isFullscreenMode()) {
- mSuggestionStripView.setVisibility(
- shouldShowSuggestions ? View.VISIBLE : View.GONE);
- } else {
- mSuggestionStripView.setVisibility(
- shouldShowSuggestions ? View.VISIBLE : View.INVISIBLE);
- }
+ if (!onEvaluateInputViewShown() || null == mSuggestionStripView) {
+ return;
+ }
+ final boolean inputViewShown = mKeyboardSwitcher.isShowingMainKeyboardOrEmojiPalettes();
+ final boolean shouldShowSuggestions = shown
+ && (needsInputViewShown ? inputViewShown : true);
+ if (shouldShowSuggestions) {
+ mSuggestionStripView.setVisibility(View.VISIBLE);
+ } else {
+ mSuggestionStripView.setVisibility(isFullscreenMode() ? View.GONE : View.INVISIBLE);
}
- }
-
- private void setSuggestionStripShown(final boolean shown) {
- setSuggestionStripShownInternal(shown, /* needsInputViewShown */true);
}
private int getAdjustedBackingViewHeight() {
@@ -1276,7 +1273,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// This method must run on the UI Thread.
private void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords,
final boolean dismissGestureFloatingPreviewText) {
- showSuggestionStrip(suggestedWords);
+ showSuggestionStrip(suggestedWords, suggestedWords.mTypedWord);
final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
mainKeyboardView.showGestureFloatingPreviewText(suggestedWords);
if (dismissGestureFloatingPreviewText) {
@@ -1330,26 +1327,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
// TODO[IL]: Define a clear interface for this
- public void setSuggestedWords(final SuggestedWords words) {
- mInputLogic.mSuggestedWords = words;
+ public void setSuggestedWords(final SuggestedWords suggestedWords, final boolean shouldShow) {
+ mInputLogic.setSuggestedWords(suggestedWords);
if (mSuggestionStripView != null) {
- mSuggestionStripView.setSuggestions(words);
- mKeyboardSwitcher.onAutoCorrectionStateChanged(words.mWillAutoCorrect);
- }
- }
-
- private void setAutoCorrectionIndicator(final boolean newAutoCorrectionIndicator) {
- // Put a blue underline to a word in TextView which will be auto-corrected.
- if (mInputLogic.mIsAutoCorrectionIndicatorOn != newAutoCorrectionIndicator
- && mInputLogic.mWordComposer.isComposingWord()) {
- mInputLogic.mIsAutoCorrectionIndicatorOn = newAutoCorrectionIndicator;
- final CharSequence textWithUnderline =
- mInputLogic.getTextWithUnderline(mInputLogic.mWordComposer.getTypedWord());
- // TODO: when called from an updateSuggestionStrip() call that results from a posted
- // message, this is called outside any batch edit. Potentially, this may result in some
- // janky flickering of the screen, although the display speed makes it unlikely in
- // the practice.
- mInputLogic.mConnection.setComposingText(textWithUnderline, 1);
+ mSuggestionStripView.setSuggestions(suggestedWords,
+ SubtypeLocaleUtils.isRtlLanguage(mSubtypeSwitcher.getCurrentSubtype()));
+ mKeyboardSwitcher.onAutoCorrectionStateChanged(suggestedWords.mWillAutoCorrect);
+ setSuggestionStripShownInternal(shouldShow, true /* needsInputViewShown */);
}
}
@@ -1424,18 +1408,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
- private void showSuggestionStripWithTypedWord(final SuggestedWords sourceSuggestedWords,
+ // TODO[IL]: Define a clean interface for this
+ public void showSuggestionStrip(final SuggestedWords sourceSuggestedWords,
final String typedWord) {
- // TODO: refactor this
final SuggestedWords suggestedWords =
sourceSuggestedWords.isEmpty() ? SuggestedWords.EMPTY : sourceSuggestedWords;
- if (suggestedWords.isEmpty()) {
- // No auto-correction is available, clear the cached values.
- AccessibilityUtils.getInstance().setAutoCorrection(suggestedWords, typedWord);
- setSuggestedWords(suggestedWords);
- setAutoCorrectionIndicator(false);
- return;
- }
final String autoCorrection;
if (suggestedWords.mWillAutoCorrect) {
autoCorrection = suggestedWords.getWord(SuggestedWords.INDEX_OF_AUTO_CORRECTION);
@@ -1444,21 +1421,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// because it may differ from mWordComposer.mTypedWord.
autoCorrection = typedWord;
}
- mInputLogic.mWordComposer.setAutoCorrection(autoCorrection);
- setSuggestedWords(suggestedWords);
- setAutoCorrectionIndicator(suggestedWords.mWillAutoCorrect);
- setSuggestionStripShown(isSuggestionsStripVisible());
- // An auto-correction is available, cache it in accessibility code so
- // we can be speak it if the user touches a key that will insert it.
+ if (SuggestedWords.EMPTY != suggestedWords) {
+ mInputLogic.mWordComposer.setAutoCorrection(autoCorrection);
+ }
+ setSuggestedWords(suggestedWords, isSuggestionsStripVisible());
+ // Cache the auto-correction in accessibility code so we can speak it if the user
+ // touches a key that will insert it.
AccessibilityUtils.getInstance().setAutoCorrection(suggestedWords, typedWord);
}
- // TODO[IL]: Define a clean interface for this
- public void showSuggestionStrip(final SuggestedWords suggestedWords) {
- showSuggestionStripWithTypedWord(suggestedWords, suggestedWords.isEmpty() ? null
- : suggestedWords.getWord(SuggestedWords.INDEX_OF_TYPED_WORD));
- }
-
// Called from {@link SuggestionStripView} through the {@link SuggestionStripView#Listener}
// interface
@Override
@@ -1560,12 +1531,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public void setNeutralSuggestionStrip() {
final SettingsValues currentSettings = mSettings.getCurrent();
if (currentSettings.mBigramPredictionEnabled) {
- setSuggestedWords(SuggestedWords.EMPTY);
+ setSuggestedWords(SuggestedWords.EMPTY, isSuggestionsStripVisible());
} else {
- setSuggestedWords(currentSettings.mSpacingAndPunctuations.mSuggestPuncList);
+ setSuggestedWords(currentSettings.mSpacingAndPunctuations.mSuggestPuncList,
+ isSuggestionsStripVisible());
}
- setAutoCorrectionIndicator(false);
- setSuggestionStripShown(isSuggestionsStripVisible());
}
public void unsetIsAutoCorrectionIndicatorOnAndCallShowSuggestionStrip(
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index bb34b7ba9..982a97a5e 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -39,6 +39,7 @@ public final class SuggestedWords {
public static final SuggestedWords EMPTY = new SuggestedWords(
EMPTY_WORD_INFO_LIST, false, false, false, false, false);
+ public final String mTypedWord;
public final boolean mTypedWordValid;
// Note: this INCLUDES cases where the word will auto-correct to itself. A good definition
// of what this flag means would be "the top suggestion is strong enough to auto-correct",
@@ -74,6 +75,7 @@ public final class SuggestedWords {
mIsObsoleteSuggestions = isObsoleteSuggestions;
mIsPrediction = isPrediction;
mSequenceNumber = sequenceNumber;
+ mTypedWord = suggestedWordInfoList.isEmpty() ? null : getWord(INDEX_OF_TYPED_WORD);
}
public boolean isEmpty() {
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 43d75330d..ce3ef5374 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -349,6 +349,10 @@ public final class InputLogic {
didAutoCorrect = handleNonSpecialCharacter(settingsValues, Constants.CODE_ENTER,
x, y, spaceState, keyboardSwitcher, handler);
break;
+ case Constants.CODE_ALPHA_FROM_EMOJI:
+ // Note: Switching back from Emoji keyboard to the main keyboard is being handled in
+ // {@link KeyboardState#onCodeInput(int,int)}.
+ break;
default:
didAutoCorrect = handleNonSpecialCharacter(settingsValues,
code, x, y, spaceState, keyboardSwitcher, handler);
@@ -478,6 +482,25 @@ public final class InputLogic {
SuggestedWords.EMPTY, true /* dismissGestureFloatingPreviewText */);
}
+ // TODO: on the long term, this method should become private, but it will be difficult.
+ // Especially, how do we deal with InputMethodService.onDisplayCompletions?
+ public void setSuggestedWords(final SuggestedWords suggestedWords) {
+ mSuggestedWords = suggestedWords;
+ final boolean newAutoCorrectionIndicator = suggestedWords.mWillAutoCorrect;
+ // Put a blue underline to a word in TextView which will be auto-corrected.
+ if (mIsAutoCorrectionIndicatorOn != newAutoCorrectionIndicator
+ && mWordComposer.isComposingWord()) {
+ mIsAutoCorrectionIndicatorOn = newAutoCorrectionIndicator;
+ final CharSequence textWithUnderline =
+ getTextWithUnderline(mWordComposer.getTypedWord());
+ // TODO: when called from an updateSuggestionStrip() call that results from a posted
+ // message, this is called outside any batch edit. Potentially, this may result in some
+ // janky flickering of the screen, although the display speed makes it unlikely in
+ // the practice.
+ mConnection.setComposingText(textWithUnderline, 1);
+ }
+ }
+
/**
* Handle inputting a code point to the editor.
*
@@ -1097,7 +1120,7 @@ public final class InputLogic {
final SuggestedWords suggestedWords = holder.get(null,
Constants.GET_SUGGESTED_WORDS_TIMEOUT);
if (suggestedWords != null) {
- mLatinIME.showSuggestionStrip(suggestedWords);
+ mLatinIME.showSuggestionStrip(suggestedWords, suggestedWords.mTypedWord);
}
}
@@ -1599,8 +1622,10 @@ public final class InputLogic {
final int indexOfLastSpace = batchInputText.lastIndexOf(Constants.CODE_SPACE) + 1;
if (0 != indexOfLastSpace) {
mConnection.commitText(batchInputText.substring(0, indexOfLastSpace), 1);
- mLatinIME.showSuggestionStrip(
- suggestedWords.getSuggestedWordsForLastWordOfPhraseGesture());
+ final SuggestedWords suggestedWordsForLastWordOfPhraseGesture =
+ suggestedWords.getSuggestedWordsForLastWordOfPhraseGesture();
+ mLatinIME.showSuggestionStrip(suggestedWordsForLastWordOfPhraseGesture,
+ suggestedWordsForLastWordOfPhraseGesture.mTypedWord);
}
final String lastWord = batchInputText.substring(indexOfLastSpace);
mWordComposer.setBatchInputWord(lastWord);
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
index af04de435..3cd9d9555 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
@@ -28,6 +28,8 @@ import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.support.v4.view.GravityCompat;
+import android.support.v4.view.ViewCompat;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
@@ -39,7 +41,6 @@ import android.text.style.UnderlineSpan;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
-import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -88,6 +89,7 @@ final class SuggestionStripLayoutHelper {
private final Drawable mMoreSuggestionsHint;
private static final String MORE_SUGGESTIONS_HINT = "\u2026";
private static final String LEFTWARDS_ARROW = "\u2190";
+ private static final String RIGHTWARDS_ARROW = "\u2192";
private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD);
private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan();
@@ -471,10 +473,13 @@ final class SuggestionStripLayoutHelper {
final TextView hintView = (TextView)addToDictionaryStrip.findViewById(
R.id.hint_add_to_dictionary);
- hintView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
+ hintView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL | GravityCompat.START);
hintView.setTextColor(mColorAutoCorrect);
+ final boolean isRtlLanguage = (ViewCompat.getLayoutDirection(addToDictionaryStrip)
+ == ViewCompat.LAYOUT_DIRECTION_RTL);
+ final String hintWithArrow = (isRtlLanguage ? RIGHTWARDS_ARROW : LEFTWARDS_ARROW)
+ + hintText;
final int hintWidth = width - wordWidth;
- final String hintWithArrow = LEFTWARDS_ARROW + hintText;
final float hintScaleX = getTextScaleX(hintWithArrow, hintWidth, hintView.getPaint());
hintView.setText(hintWithArrow);
hintView.setTextScaleX(hintScaleX);
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
index 32552ebe7..0ebf5cba5 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
@@ -18,6 +18,7 @@ package com.android.inputmethod.latin.suggestions;
import android.content.Context;
import android.content.res.Resources;
+import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.LayoutInflater;
@@ -26,6 +27,7 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
+import android.view.ViewParent;
import android.widget.RelativeLayout;
import android.widget.TextView;
@@ -83,6 +85,13 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
showSuggestionsStrip();
}
+ public void setLayoutDirection(final boolean isRtlLanguage) {
+ final int layoutDirection = isRtlLanguage ? ViewCompat.LAYOUT_DIRECTION_RTL
+ : ViewCompat.LAYOUT_DIRECTION_LTR;
+ ViewCompat.setLayoutDirection(mSuggestionsStrip, layoutDirection);
+ ViewCompat.setLayoutDirection(mAddToDictionaryStrip, layoutDirection);
+ }
+
public void showSuggestionsStrip() {
mSuggestionsStrip.setVisibility(VISIBLE);
mAddToDictionaryStrip.setVisibility(INVISIBLE);
@@ -153,8 +162,9 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
mMainKeyboardView = (MainKeyboardView)inputView.findViewById(R.id.keyboard_view);
}
- public void setSuggestions(final SuggestedWords suggestedWords) {
+ public void setSuggestions(final SuggestedWords suggestedWords, final boolean isRtlLanguage) {
clear();
+ mStripVisibilityGroup.setLayoutDirection(isRtlLanguage);
mSuggestedWords = suggestedWords;
mLayoutHelper.layout(mSuggestedWords, mSuggestionsStrip, this);
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
@@ -189,10 +199,21 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick
public void clear() {
mSuggestionsStrip.removeAllViews();
+ removeAllDebugInfoViews();
mStripVisibilityGroup.showSuggestionsStrip();
dismissMoreSuggestionsPanel();
}
+ private void removeAllDebugInfoViews() {
+ // The debug info views may be placed as children views of this {@link SuggestionStripView}.
+ for (final View debugInfoView : mDebugInfoViews) {
+ final ViewParent parent = debugInfoView.getParent();
+ if (parent instanceof ViewGroup) {
+ ((ViewGroup)parent).removeView(debugInfoView);
+ }
+ }
+ }
+
private final MoreSuggestionsListener mMoreSuggestionsListener = new MoreSuggestionsListener() {
@Override
public void onSuggestionSelected(final int index, final SuggestedWordInfo wordInfo) {
diff --git a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
index fdbe81ab6..0d0288923 100644
--- a/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtils.java
@@ -28,6 +28,7 @@ import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.latin.DictionaryFactory;
import com.android.inputmethod.latin.R;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
@@ -334,4 +335,21 @@ public final class SubtypeLocaleUtils {
final Locale locale = getSubtypeLocale(subtype);
return StringUtils.capitalizeFirstCodePoint(locale.getLanguage(), locale);
}
+
+ // TODO: Get this information from the framework instead of maintaining here by ourselves.
+ // Sorted list of known Right-To-Left language codes.
+ private static final String[] SORTED_RTL_LANGUAGES = {
+ "ar", // Arabic
+ "fa", // Persian
+ "iw", // Hebrew
+ };
+ static {
+ Arrays.sort(SORTED_RTL_LANGUAGES);
+ }
+
+ public static boolean isRtlLanguage(final InputMethodSubtype subtype) {
+ final Locale locale = getSubtypeLocale(subtype);
+ final String language = locale.getLanguage();
+ return Arrays.binarySearch(SORTED_RTL_LANGUAGES, language) >= 0;
+ }
}
diff --git a/native/jni/src/suggest/core/dictionary/suggestions_output_utils.cpp b/native/jni/src/suggest/core/dictionary/suggestions_output_utils.cpp
index d219757da..b8106377c 100644
--- a/native/jni/src/suggest/core/dictionary/suggestions_output_utils.cpp
+++ b/native/jni/src/suggest/core/dictionary/suggestions_output_utils.cpp
@@ -58,12 +58,6 @@ const int SuggestionsOutputUtils::MIN_LEN_FOR_MULTI_WORD_AUTOCORRECT = 16;
++outputWordIndex;
}
- // Initial value of the loop index for terminal nodes (words)
- int doubleLetterTerminalIndex = -1;
- DoubleLetterLevel doubleLetterLevel = NOT_A_DOUBLE_LETTER;
- scoringPolicy->searchWordWithDoubleLetter(terminals, terminalSize,
- &doubleLetterTerminalIndex, &doubleLetterLevel);
-
int maxScore = S_INT_MIN;
// Force autocorrection for obvious long multi-word suggestions when the top suggestion is
// a long multiple words suggestion.
@@ -92,8 +86,8 @@ const int SuggestionsOutputUtils::MIN_LEN_FOR_MULTI_WORD_AUTOCORRECT = 16;
if (DEBUG_GEO_FULL) {
terminalDicNode->dump("OUT:");
}
- const float doubleLetterCost = scoringPolicy->getDoubleLetterDemotionDistanceCost(
- terminalIndex, doubleLetterTerminalIndex, doubleLetterLevel);
+ const float doubleLetterCost =
+ scoringPolicy->getDoubleLetterDemotionDistanceCost(terminalDicNode);
const float compoundDistance = terminalDicNode->getCompoundDistance(languageWeight)
+ doubleLetterCost;
const bool isPossiblyOffensiveWord =
diff --git a/native/jni/src/suggest/core/policy/scoring.h b/native/jni/src/suggest/core/policy/scoring.h
index 5ae3d2146..783383450 100644
--- a/native/jni/src/suggest/core/policy/scoring.h
+++ b/native/jni/src/suggest/core/policy/scoring.h
@@ -34,14 +34,10 @@ class Scoring {
int *const type, int *const freq) const = 0;
virtual void safetyNetForMostProbableString(const int terminalSize,
const int maxScore, int *const outputCodePoints, int *const frequencies) const = 0;
- // TODO: Make more generic
- virtual void searchWordWithDoubleLetter(DicNode *terminals, const int terminalSize,
- int *doubleLetterTerminalIndex, DoubleLetterLevel *doubleLetterLevel) const = 0;
virtual float getAdjustedLanguageWeight(DicTraverseSession *const traverseSession,
DicNode *const terminals, const int size) const = 0;
- virtual float getDoubleLetterDemotionDistanceCost(const int terminalIndex,
- const int doubleLetterTerminalIndex,
- const DoubleLetterLevel doubleLetterLevel) const = 0;
+ virtual float getDoubleLetterDemotionDistanceCost(
+ const DicNode *const terminalDicNode) const = 0;
virtual bool doesAutoCorrectValidWord() const = 0;
virtual bool autoCorrectsToMultiWordSuggestionIfTop() const = 0;
virtual bool sameAsTyped(const DicTraverseSession *const traverseSession,
diff --git a/native/jni/src/suggest/policyimpl/typing/typing_scoring.h b/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
index 186e3ba08..c777e7238 100644
--- a/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
+++ b/native/jni/src/suggest/policyimpl/typing/typing_scoring.h
@@ -43,11 +43,6 @@ class TypingScoring : public Scoring {
const int maxScore, int *const outputCodePoints, int *const frequencies) const {
}
- AK_FORCE_INLINE void searchWordWithDoubleLetter(DicNode *terminals,
- const int terminalSize, int *doubleLetterTerminalIndex,
- DoubleLetterLevel *doubleLetterLevel) const {
- }
-
AK_FORCE_INLINE float getAdjustedLanguageWeight(DicTraverseSession *const traverseSession,
DicNode *const terminals, const int size) const {
return 1.0f;
@@ -77,9 +72,8 @@ class TypingScoring : public Scoring {
return static_cast<int>(score * SUGGEST_INTERFACE_OUTPUT_SCALE);
}
- AK_FORCE_INLINE float getDoubleLetterDemotionDistanceCost(const int terminalIndex,
- const int doubleLetterTerminalIndex,
- const DoubleLetterLevel doubleLetterLevel) const {
+ AK_FORCE_INLINE float getDoubleLetterDemotionDistanceCost(
+ const DicNode *const terminalDicNode) const {
return 0.0f;
}
diff --git a/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java
index 939dedba1..25f57eba6 100644
--- a/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/SubtypeLocaleUtilsTests.java
@@ -101,7 +101,6 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
SubtypeLocaleUtils.NO_LANGUAGE, "azerty", null);
ZZ_PC = AdditionalSubtypeUtils.createAdditionalSubtype(
SubtypeLocaleUtils.NO_LANGUAGE, "pcqwerty", null);
-
}
public void testAllFullDisplayName() {
@@ -423,4 +422,27 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
public void testAdditionalSubtypeForSpacebarInFrench() {
testsAdditionalSubtypesForSpacebar.runInLocale(mRes, Locale.FRENCH);
}
+
+ public void testIsRtlLanguage() {
+ // Known Right-to-Left language subtypes.
+ final InputMethodSubtype ARABIC = mRichImm
+ .findSubtypeByLocaleAndKeyboardLayoutSet("ar", "arabic");
+ assertNotNull("Arabic", ARABIC);
+ final InputMethodSubtype FARSI = mRichImm
+ .findSubtypeByLocaleAndKeyboardLayoutSet("fa", "farsi");
+ assertNotNull("Farsi", FARSI);
+ final InputMethodSubtype HEBREW = mRichImm
+ .findSubtypeByLocaleAndKeyboardLayoutSet("iw", "hebrew");
+ assertNotNull("Hebrew", HEBREW);
+
+ for (final InputMethodSubtype subtype : mSubtypesList) {
+ final String subtypeName = SubtypeLocaleUtils
+ .getSubtypeDisplayNameInSystemLocale(subtype);
+ if (subtype.equals(ARABIC) || subtype.equals(FARSI) || subtype.equals(HEBREW)) {
+ assertTrue(subtypeName, SubtypeLocaleUtils.isRtlLanguage(subtype));
+ } else {
+ assertFalse(subtypeName, SubtypeLocaleUtils.isRtlLanguage(subtype));
+ }
+ }
+ }
}