From d2c5fdda862f6dd2a1e020cf674c35fbbc63fc92 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 21 Apr 2011 19:43:20 +0900 Subject: [PATCH 1/6] Rename and reorganize key code Change-Id: I13d6fef7af1c4356a22b0e8aebc9e613b1693ece --- java/res/values/keycodes.xml | 6 +++--- java/res/xml-xlarge/kbd_key_styles.xml | 4 ++-- java/res/xml/kbd_key_styles.xml | 4 ++-- .../android/inputmethod/keyboard/Keyboard.java | 15 +++++---------- .../inputmethod/keyboard/LatinKeyboard.java | 5 ++++- .../inputmethod/keyboard/LatinKeyboardView.java | 2 +- .../com/android/inputmethod/latin/LatinIME.java | 6 +++--- 7 files changed, 20 insertions(+), 22 deletions(-) diff --git a/java/res/values/keycodes.xml b/java/res/values/keycodes.xml index d6f9bfc28..0f0a74aea 100644 --- a/java/res/values/keycodes.xml +++ b/java/res/values/keycodes.xml @@ -26,8 +26,8 @@ -1 -2 -5 - -100 - -102 + -6 + -8 @@ -45,7 +45,7 @@ @string/description_delete_key @integer/key_settings @string/description_settings_key - @integer/key_voice + @integer/key_shortcut @string/description_voice_key diff --git a/java/res/xml-xlarge/kbd_key_styles.xml b/java/res/xml-xlarge/kbd_key_styles.xml index 4fefe0056..57eaccbae 100644 --- a/java/res/xml-xlarge/kbd_key_styles.xml +++ b/java/res/xml-xlarge/kbd_key_styles.xml @@ -73,7 +73,7 @@ latin:parentStyle="functionalKeyStyle" /> @@ -127,7 +127,7 @@ latin:parentStyle="functionalKeyStyle" /> diff --git a/java/res/xml/kbd_key_styles.xml b/java/res/xml/kbd_key_styles.xml index bfc7c4ff2..4792e1f00 100644 --- a/java/res/xml/kbd_key_styles.xml +++ b/java/res/xml/kbd_key_styles.xml @@ -118,7 +118,7 @@ latin:parentStyle="functionalKeyStyle" /> @@ -191,7 +191,7 @@ latin:parentStyle="functionalKeyStyle" /> diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java index fdfe282c3..c02c22494 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -68,19 +68,14 @@ public class Keyboard { public static final int CODE_DUMMY = 0; public static final int CODE_SHIFT = -1; public static final int CODE_SWITCH_ALPHA_SYMBOL = -2; - public static final int CODE_CANCEL = -3; - public static final int CODE_DONE = -4; + public static final int CODE_CAPSLOCK = -3; + public static final int CODE_CANCEL = -4; public static final int CODE_DELETE = -5; - public static final int CODE_ALT = -6; + public static final int CODE_SETTINGS = -6; + public static final int CODE_SETTINGS_LONGPRESS = -7; + public static final int CODE_SHORTCUT = -8; // Code value representing the code is not specified. public static final int CODE_UNSPECIFIED = -99; - public static final int CODE_SETTINGS = -100; - public static final int CODE_SETTINGS_LONGPRESS = -101; - // TODO: remove this once LatinIME stops referring to this. - public static final int CODE_VOICE = -102; - public static final int CODE_CAPSLOCK = -103; - public static final int CODE_NEXT_LANGUAGE = -104; - public static final int CODE_PREV_LANGUAGE = -105; /** Horizontal gap default for all rows */ private int mDefaultHorizontalGap; diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java index 3a5dbd2de..b8bcee687 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java @@ -46,6 +46,9 @@ import java.util.Locale; public class LatinKeyboard extends Keyboard { private static final int SPACE_LED_LENGTH_PERCENT = 80; + public static final int CODE_NEXT_LANGUAGE = -100; + public static final int CODE_PREV_LANGUAGE = -101; + private final Context mContext; private final SubtypeSwitcher mSubtypeSwitcher = SubtypeSwitcher.getInstance(); @@ -102,7 +105,7 @@ public class LatinKeyboard extends Keyboard { case CODE_SPACE: spaceKeyIndex = index; break; - case CODE_VOICE: + case CODE_SHORTCUT: shortcutKeyIndex = index; break; } diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index 912074515..a64a9e609 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -236,7 +236,7 @@ public class LatinKeyboardView extends KeyboardView { if (languageDirection != 0) { getOnKeyboardActionListener().onCodeInput( languageDirection == 1 - ? Keyboard.CODE_NEXT_LANGUAGE : Keyboard.CODE_PREV_LANGUAGE, + ? LatinKeyboard.CODE_NEXT_LANGUAGE : LatinKeyboard.CODE_PREV_LANGUAGE, null, mLastX, mLastY); me.setAction(MotionEvent.ACTION_CANCEL); keyboard.keyReleased(); diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index a680b9825..0ae675b3b 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1159,16 +1159,16 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar case Keyboard.CODE_SETTINGS_LONGPRESS: onSettingsKeyLongPressed(); break; - case Keyboard.CODE_NEXT_LANGUAGE: + case LatinKeyboard.CODE_NEXT_LANGUAGE: toggleLanguage(true); break; - case Keyboard.CODE_PREV_LANGUAGE: + case LatinKeyboard.CODE_PREV_LANGUAGE: toggleLanguage(false); break; case Keyboard.CODE_CAPSLOCK: switcher.toggleCapsLock(); break; - case Keyboard.CODE_VOICE: + case Keyboard.CODE_SHORTCUT: mSubtypeSwitcher.switchToShortcutIME(); break; case Keyboard.CODE_TAB: From 89bd776cf68150202d774d62cc1c88664aea5e9f Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Wed, 20 Apr 2011 11:50:05 +0900 Subject: [PATCH 2/6] Use user-history bigrams when no input if available. This also fixes a small inconsistency upon clicking on whitespace twice in a row. Also add some unit tests for an introduced and an existing method. Change-Id: I1be2fb53c9624f4d0f5299009632cb4384fdfc15 --- .../inputmethod/latin/BinaryDictionary.java | 5 ++ .../inputmethod/latin/EditingUtils.java | 63 +++++++++++--- .../android/inputmethod/latin/LatinIME.java | 86 +++++++++++++++++-- .../android/inputmethod/latin/Suggest.java | 47 ++++++---- .../latin/UserBigramDictionary.java | 4 + .../android/inputmethod/latin/UtilsTests.java | 67 +++++++++++++++ 6 files changed, 235 insertions(+), 37 deletions(-) create mode 100644 tests/src/com/android/inputmethod/latin/UtilsTests.java diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 58e9099a9..7e63aacdf 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -197,6 +197,11 @@ public class BinaryDictionary extends Dictionary { Arrays.fill(mBigramScores, 0); int codesSize = codes.size(); + if (codesSize <= 0) { + // Do not return bigrams from BinaryDictionary when nothing was typed. + // Only use user-history bigrams (or whatever other bigram dictionaries decide). + return; + } Arrays.fill(mInputCodes, -1); int[] alternatives = codes.getCodesAt(0); System.arraycopy(alternatives, 0, mInputCodes, 0, diff --git a/java/src/com/android/inputmethod/latin/EditingUtils.java b/java/src/com/android/inputmethod/latin/EditingUtils.java index 80830c000..ea281f5b8 100644 --- a/java/src/com/android/inputmethod/latin/EditingUtils.java +++ b/java/src/com/android/inputmethod/latin/EditingUtils.java @@ -161,23 +161,62 @@ public class EditingUtils { private static final Pattern spaceRegex = Pattern.compile("\\s+"); + public static CharSequence getPreviousWord(InputConnection connection, String sentenceSeperators) { //TODO: Should fix this. This could be slow! CharSequence prev = connection.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0); - if (prev == null) { - return null; - } + return getPreviousWord(prev, sentenceSeperators); + } + + // Get the word before the whitespace preceding the non-whitespace preceding the cursor. + // Also, it won't return words that end in a separator. + // Example : + // "abc def|" -> abc + // "abc def |" -> abc + // "abc def. |" -> abc + // "abc def . |" -> def + // "abc|" -> null + // "abc |" -> null + // "abc. def|" -> null + public static CharSequence getPreviousWord(CharSequence prev, String sentenceSeperators) { + if (prev == null) return null; String[] w = spaceRegex.split(prev); - if (w.length >= 2 && w[w.length-2].length() > 0) { - char lastChar = w[w.length-2].charAt(w[w.length-2].length() -1); - if (sentenceSeperators.contains(String.valueOf(lastChar))) { - return null; - } - return w[w.length-2]; - } else { - return null; - } + + // If we can't find two words, or we found an empty word, return null. + if (w.length < 2 || w[w.length - 2].length() <= 0) return null; + + // If ends in a separator, return null + char lastChar = w[w.length - 2].charAt(w[w.length - 2].length() - 1); + if (sentenceSeperators.contains(String.valueOf(lastChar))) return null; + + return w[w.length - 2]; + } + + public static CharSequence getThisWord(InputConnection connection, String sentenceSeperators) { + final CharSequence prev = connection.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0); + return getThisWord(prev, sentenceSeperators); + } + + // Get the word immediately before the cursor, even if there is whitespace between it and + // the cursor - but not if there is punctuation. + // Example : + // "abc def|" -> def + // "abc def |" -> def + // "abc def. |" -> null + // "abc def . |" -> null + public static CharSequence getThisWord(CharSequence prev, String sentenceSeperators) { + if (prev == null) return null; + String[] w = spaceRegex.split(prev); + + // No word : return null + if (w.length < 1 || w[w.length - 1].length() <= 0) return null; + + // If ends in a separator, return null + char lastChar = w[w.length - 1].charAt(w[w.length - 1].length() - 1); + if (sentenceSeperators.contains(String.valueOf(lastChar))) return null; + + return w[w.length - 1]; } public static class SelectedWord { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 0ae675b3b..8f44ec743 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -266,6 +266,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 4; private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 5; private static final int MSG_SPACE_TYPED = 6; + private static final int MSG_SET_BIGRAM_SUGGESTIONS = 7; @Override public void handleMessage(Message msg) { @@ -281,6 +282,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar case MSG_UPDATE_SHIFT_STATE: switcher.updateShiftState(); break; + case MSG_SET_BIGRAM_SUGGESTIONS: + updateBigramSuggestions(); + break; case MSG_VOICE_RESULTS: mVoiceProxy.handleVoiceResults(preferCapitalization() || (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked())); @@ -333,6 +337,15 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar removeMessages(MSG_UPDATE_SHIFT_STATE); } + public void postSetBigramSuggestions() { + removeMessages(MSG_SET_BIGRAM_SUGGESTIONS); + sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_SUGGESTIONS), DELAY_UPDATE_SUGGESTIONS); + } + + public void cancelSetBigramSuggestions() { + removeMessages(MSG_SET_BIGRAM_SUGGESTIONS); + } + public void updateVoiceResults() { sendMessage(obtainMessage(MSG_VOICE_RESULTS)); } @@ -548,7 +561,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final KeyboardSwitcher switcher = mKeyboardSwitcher; LatinKeyboardView inputView = switcher.getInputView(); - if(DEBUG) { + if (DEBUG) { Log.d(TAG, "onStartInputView: " + inputView); } // In landscape mode, this method gets called without the input view being created. @@ -754,7 +767,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } mComposing.setLength(0); mHasValidSuggestions = false; - mHandler.postUpdateSuggestions(); + if (isCursorTouchingWord()) { + mHandler.cancelSetBigramSuggestions(); + mHandler.postUpdateSuggestions(); + } else { + setPunctuationSuggestions(); + } TextEntryState.reset(); InputConnection ic = getCurrentInputConnection(); if (ic != null) { @@ -784,14 +802,20 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar || TextEntryState.isRecorrecting()) && (newSelStart < newSelEnd - 1 || !mHasValidSuggestions)) { if (isCursorTouchingWord() || mLastSelectionStart < mLastSelectionEnd) { + mHandler.cancelSetBigramSuggestions(); mHandler.postUpdateOldSuggestions(); } else { abortRecorrection(false); - // Show the punctuation suggestions list if the current one is not - // and if not showing "Touch again to save". - if (mCandidateView != null && !isShowingPunctuationList() + // If showing the "touch again to save" hint, do not replace it. Else, + // show the bigrams if we are at the end of the text, punctuation otherwise. + if (mCandidateView != null && !mCandidateView.isShowingAddToDictionaryHint()) { - setPunctuationSuggestions(); + InputConnection ic = getCurrentInputConnection(); + if (null == ic || !TextUtils.isEmpty(ic.getTextAfterCursor(1, 0))) { + if (!isShowingPunctuationList()) setPunctuationSuggestions(); + } else { + mHandler.postSetBigramSuggestions(); + } } } } @@ -1231,7 +1255,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (mComposing.length() == 0) { mHasValidSuggestions = false; } - mHandler.postUpdateSuggestions(); + if (1 == length) { + // 1 == length means we are about to erase the last character of the word, + // so we can show bigrams. + mHandler.postSetBigramSuggestions(); + } else { + // length > 1, so we still have letters to deduce a suggestion from. + mHandler.postUpdateSuggestions(); + } } else { ic.deleteSurroundingText(1, 0); } @@ -1367,6 +1398,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Should dismiss the "Touch again to save" message when handling separator if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) { + mHandler.cancelSetBigramSuggestions(); mHandler.postUpdateSuggestions(); } @@ -1406,6 +1438,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } TextEntryState.typedCharacter((char) primaryCode, true, x, y); + if (TextEntryState.isPunctuationAfterAccepted() && primaryCode != Keyboard.CODE_ENTER) { swapPunctuationAndSpace(); } else if (isSuggestionsRequested() && primaryCode == Keyboard.CODE_SPACE) { @@ -1416,10 +1449,20 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar TextEntryState.backToAcceptedDefault(typedWord); if (!TextUtils.isEmpty(typedWord) && !typedWord.equals(mBestWord)) { InputConnectionCompatUtils.commitCorrection( - ic, mLastSelectionEnd - typedWord.length(), typedWord, mBestWord); + ic, mLastSelectionEnd - typedWord.length(), typedWord, mBestWord); if (mCandidateView != null) mCandidateView.onAutoCorrectionInverted(mBestWord); } + } + if (Keyboard.CODE_SPACE == primaryCode) { + if (!isCursorTouchingWord()) { + mHandler.cancelUpdateSuggestions(); + mHandler.cancelUpdateOldSuggestions(); + mHandler.postSetBigramSuggestions(); + } + } else { + // Set punctuation right away. onUpdateSelection will fire but tests whether it is + // already displayed or not, so it's okay. setPunctuationSuggestions(); } mKeyboardSwitcher.updateShiftState(); @@ -1654,6 +1697,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } return; } + if (!mHasValidSuggestions) { + // If we are not composing a word, then it was a suggestion inferred from + // context - no user input. We should reset the word composer. + mWord.reset(); + } mJustAccepted = true; pickSuggestion(suggestion); // Add the word to the auto dictionary if it's not a known word @@ -1692,7 +1740,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // TextEntryState.State.PICKED_SUGGESTION state. TextEntryState.typedCharacter((char) Keyboard.CODE_SPACE, true, WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); - setPunctuationSuggestions(); + // From there on onUpdateSelection() will fire so suggestions will be updated } else if (!showingAddToDictionaryHint) { // If we're not showing the "Touch again to save", then show corrections again. // In case the cursor position doesn't change, make sure we show the suggestions again. @@ -1807,6 +1855,25 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } } + private static final WordComposer sEmptyWordComposer = new WordComposer(); + private void updateBigramSuggestions() { + if (mSuggest == null || !isSuggestionsRequested()) + return; + + final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(), + mWordSeparators); + SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder( + mKeyboardSwitcher.getInputView(), sEmptyWordComposer, prevWord); + + if (builder.size() > 0) { + // Explicitly supply an empty typed word (the no-second-arg version of + // showSuggestions will retrieve the word near the cursor, we don't want that here) + showSuggestions(builder.build(), ""); + } else { + if (!isShowingPunctuationList()) setPunctuationSuggestions(); + } + } + private void setPunctuationSuggestions() { setSuggestions(mSuggestPuncList); setCandidatesViewShown(isCandidateStripVisible()); @@ -1907,6 +1974,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar ic.setComposingText(mComposing, 1); TextEntryState.backspace(); } + mHandler.cancelSetBigramSuggestions(); mHandler.postUpdateSuggestions(); } else { sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index f37206223..15743ee2d 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -265,6 +265,16 @@ public class Suggest implements Dictionary.WordCallback { return sb; } + protected void addBigramToSuggestions(CharSequence bigram) { + final int poolSize = mStringPool.size(); + final StringBuilder sb = poolSize > 0 ? + (StringBuilder) mStringPool.remove(poolSize - 1) + : new StringBuilder(getApproxMaxWordLength()); + sb.setLength(0); + sb.append(bigram); + mSuggestions.add(sb); + } + // TODO: cleanup dictionaries looking up and suggestions building with SuggestedWords.Builder public SuggestedWords.Builder getSuggestedWordBuilder(View view, WordComposer wordComposer, CharSequence prevWordForBigram) { @@ -286,7 +296,7 @@ public class Suggest implements Dictionary.WordCallback { } mTypedWord = typedWord; - if (wordComposer.size() == 1 && (mCorrectionMode == CORRECTION_FULL_BIGRAM + if (wordComposer.size() <= 1 && (mCorrectionMode == CORRECTION_FULL_BIGRAM || mCorrectionMode == CORRECTION_BASIC)) { // At first character typed, search only the bigrams Arrays.fill(mBigramScores, 0); @@ -300,21 +310,26 @@ public class Suggest implements Dictionary.WordCallback { for (final Dictionary dictionary : mBigramDictionaries.values()) { dictionary.getBigrams(wordComposer, prevWordForBigram, this); } - char currentChar = wordComposer.getTypedWord().charAt(0); - char currentCharUpper = Character.toUpperCase(currentChar); - int count = 0; - int bigramSuggestionSize = mBigramSuggestions.size(); - for (int i = 0; i < bigramSuggestionSize; i++) { - if (mBigramSuggestions.get(i).charAt(0) == currentChar - || mBigramSuggestions.get(i).charAt(0) == currentCharUpper) { - int poolSize = mStringPool.size(); - StringBuilder sb = poolSize > 0 ? - (StringBuilder) mStringPool.remove(poolSize - 1) - : new StringBuilder(getApproxMaxWordLength()); - sb.setLength(0); - sb.append(mBigramSuggestions.get(i)); - mSuggestions.add(count++, sb); - if (count > mPrefMaxSuggestions) break; + if (TextUtils.isEmpty(typedWord)) { + // Nothing entered: return all bigrams for the previous word + int insertCount = Math.min(mBigramSuggestions.size(), mPrefMaxSuggestions); + for (int i = 0; i < insertCount; ++i) { + addBigramToSuggestions(mBigramSuggestions.get(i)); + } + } else { + // Word entered: return only bigrams that match the first char of the typed word + final char currentChar = typedWord.charAt(0); + final char currentCharUpper = Character.toUpperCase(currentChar); + int count = 0; + final int bigramSuggestionSize = mBigramSuggestions.size(); + for (int i = 0; i < bigramSuggestionSize; i++) { + final CharSequence bigramSuggestion = mBigramSuggestions.get(i); + final char bigramSuggestionFirstChar = bigramSuggestion.charAt(0); + if (bigramSuggestionFirstChar == currentChar + || bigramSuggestionFirstChar == currentCharUpper) { + addBigramToSuggestions(bigramSuggestion); + if (++count > mPrefMaxSuggestions) break; + } } } } diff --git a/java/src/com/android/inputmethod/latin/UserBigramDictionary.java b/java/src/com/android/inputmethod/latin/UserBigramDictionary.java index bb6642cd9..a32a6461a 100644 --- a/java/src/com/android/inputmethod/latin/UserBigramDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserBigramDictionary.java @@ -162,6 +162,10 @@ public class UserBigramDictionary extends ExpandableDictionary { if (mIme != null && mIme.getCurrentWord().isAutoCapitalized()) { word2 = Character.toLowerCase(word2.charAt(0)) + word2.substring(1); } + // Do not insert a word as a bigram of itself + if (word1.equals(word2)) { + return 0; + } int freq = super.addBigram(word1, word2, FREQUENCY_FOR_TYPED); if (freq > FREQUENCY_MAX) freq = FREQUENCY_MAX; diff --git a/tests/src/com/android/inputmethod/latin/UtilsTests.java b/tests/src/com/android/inputmethod/latin/UtilsTests.java new file mode 100644 index 000000000..5c0b03a0a --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/UtilsTests.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2010,2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.android.inputmethod.latin; + +import android.test.AndroidTestCase; + +import com.android.inputmethod.latin.tests.R; + +public class UtilsTests extends AndroidTestCase { + + // The following is meant to be a reasonable default for + // the "word_separators" resource. + private static final String sSeparators = ".,:;!?-"; + + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + /************************** Tests ************************/ + + /** + * Test for getting previous word (for bigram suggestions) + */ + public void testGetPreviousWord() { + // If one of the following cases breaks, the bigram suggestions won't work. + assertEquals(EditingUtils.getPreviousWord("abc def", sSeparators), "abc"); + assertNull(EditingUtils.getPreviousWord("abc", sSeparators)); + assertNull(EditingUtils.getPreviousWord("abc. def", sSeparators)); + + // The following tests reflect the current behavior of the function + // EditingUtils#getPreviousWord. + // TODO: However at this time, the code does never go + // into such a path, so it should be safe to change the behavior of + // this function if needed - especially since it does not seem very + // logical. These tests are just there to catch any unintentional + // changes in the behavior of the EditingUtils#getPreviousWord method. + assertEquals(EditingUtils.getPreviousWord("abc def ", sSeparators), "abc"); + assertEquals(EditingUtils.getPreviousWord("abc def.", sSeparators), "abc"); + assertEquals(EditingUtils.getPreviousWord("abc def .", sSeparators), "def"); + assertNull(EditingUtils.getPreviousWord("abc ", sSeparators)); + } + + /** + * Test for getting the word before the cursor (for bigram) + */ + public void testGetThisWord() { + assertEquals(EditingUtils.getThisWord("abc def", sSeparators), "def"); + assertEquals(EditingUtils.getThisWord("abc def ", sSeparators), "def"); + assertNull(EditingUtils.getThisWord("abc def.", sSeparators)); + assertNull(EditingUtils.getThisWord("abc def .", sSeparators)); + } +} From b50591295d7c4ff7bb46ddf3e609d0046eb64d18 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Fri, 22 Apr 2011 13:08:35 +0900 Subject: [PATCH 3/6] Add an option for using bigram prediction. This change adds the option for bigram prediction under the option for bigram suggestion. The "prediction" option depends on the "suggestion" option. This change also reorders a tad bit the settings screen. Namely, it sticks both bigram options under a "bigram" category, and groups the options that did not have a group under a "other options", or misc, category. Finally this change also renames the internal name of the "text corrections" option category to "correction_category" instead of "prediction_category" which was misleading. Change-Id: I2d8787c8a391fd8202ed3a686c613494b7260a1e --- java/res/values/config.xml | 5 ++ java/res/values/strings.xml | 14 ++++- java/res/xml/prefs.xml | 55 ++++++++++++------- .../android/inputmethod/latin/LatinIME.java | 9 +++ .../android/inputmethod/latin/Settings.java | 21 +++++-- 5 files changed, 78 insertions(+), 26 deletions(-) diff --git a/java/res/values/config.xml b/java/res/values/config.xml index 300aaa423..77259b1dc 100644 --- a/java/res/values/config.xml +++ b/java/res/values/config.xml @@ -37,7 +37,12 @@ true true + true + + false true false true diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml index 66dc7d71c..cfad5b118 100644 --- a/java/res/values/strings.xml +++ b/java/res/values/strings.xml @@ -38,7 +38,13 @@ General - Text correction + Text correction + + + Suggestions based on previous words + + + Other options Auto-capitalization @@ -78,9 +84,13 @@ Aggressive - Bigram Suggestions + Bigram suggestions Use previous word to improve suggestion + + Bigram prediction + + Use previous word also for prediction %s : Saved diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml index cbfc3c39d..24a1d45a5 100644 --- a/java/res/xml/prefs.xml +++ b/java/res/xml/prefs.xml @@ -66,8 +66,8 @@ android:summary="@string/language_selection_summary" /> + android:title="@string/correction_category" + android:key="correction_settings"> + + + + + + + + - - - + Use the spacebar language switcher Show settings key diff --git a/java/res/xml/prefs_for_debug.xml b/java/res/xml/prefs_for_debug.xml index 2dad17148..477461df4 100644 --- a/java/res/xml/prefs_for_debug.xml +++ b/java/res/xml/prefs_for_debug.xml @@ -35,6 +35,13 @@ android:defaultValue="@string/config_default_keyboard_theme_id" /> + + mEnabledKeyboardSubtypesOfCurrentInputMethod = new ArrayList(); @@ -112,10 +115,8 @@ public class SubtypeSwitcher { mInputLocaleStr = null; mCurrentSubtype = null; mAllEnabledSubtypesOfCurrentInputMethod = null; - // TODO: Voice input should be created here mVoiceInputWrapper = null; - mConfigUseSpacebarLanguageSwitcher = service.getResources().getBoolean( - R.bool.config_use_spacebar_language_switcher); + mPrefs = prefs; final NetworkInfo info = mConnectivityManager.getActiveNetworkInfo(); mIsNetworkConnected = (info != null && info.isConnected()); @@ -133,6 +134,9 @@ public class SubtypeSwitcher { // Update parameters which are changed outside LatinIME. This parameters affect UI so they // should be updated every time onStartInputview. public void updateParametersOnStartInputView() { + mConfigUseSpacebarLanguageSwitcher = mPrefs.getBoolean(USE_SPACEBAR_LANGUAGE_SWITCH_KEY, + mService.getResources().getBoolean( + R.bool.config_use_spacebar_language_switcher)); updateEnabledSubtypes(); updateShortcutIME(); } From cb3320179d39a7983874697a0aa428b127675c9d Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Fri, 22 Apr 2011 16:16:30 +0900 Subject: [PATCH 5/6] Actually use the bigram prediction option. This change also rename methods that should have been renamed in a previous commit (namely, the *SetBigramSuggestions family -> *UpdateBigramSuggestions) Change-Id: I18cac17ba2b93fcc011ea133324f2c7f3532946c --- .../android/inputmethod/latin/LatinIME.java | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 05691b224..f9bcfc655 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -269,7 +269,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private static final int MSG_FADEOUT_LANGUAGE_ON_SPACEBAR = 4; private static final int MSG_DISMISS_LANGUAGE_ON_SPACEBAR = 5; private static final int MSG_SPACE_TYPED = 6; - private static final int MSG_SET_BIGRAM_SUGGESTIONS = 7; + private static final int MSG_SET_BIGRAM_PREDICTIONS = 7; @Override public void handleMessage(Message msg) { @@ -285,8 +285,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar case MSG_UPDATE_SHIFT_STATE: switcher.updateShiftState(); break; - case MSG_SET_BIGRAM_SUGGESTIONS: - updateBigramSuggestions(); + case MSG_SET_BIGRAM_PREDICTIONS: + updateBigramPredictions(); break; case MSG_VOICE_RESULTS: mVoiceProxy.handleVoiceResults(preferCapitalization() @@ -340,13 +340,13 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar removeMessages(MSG_UPDATE_SHIFT_STATE); } - public void postSetBigramSuggestions() { - removeMessages(MSG_SET_BIGRAM_SUGGESTIONS); - sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_SUGGESTIONS), DELAY_UPDATE_SUGGESTIONS); + public void postUpdateBigramPredictions() { + removeMessages(MSG_SET_BIGRAM_PREDICTIONS); + sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS), DELAY_UPDATE_SUGGESTIONS); } - public void cancelSetBigramSuggestions() { - removeMessages(MSG_SET_BIGRAM_SUGGESTIONS); + public void cancelUpdateBigramPredictions() { + removeMessages(MSG_SET_BIGRAM_PREDICTIONS); } public void updateVoiceResults() { @@ -771,7 +771,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mComposing.setLength(0); mHasValidSuggestions = false; if (isCursorTouchingWord()) { - mHandler.cancelSetBigramSuggestions(); + mHandler.cancelUpdateBigramPredictions(); mHandler.postUpdateSuggestions(); } else { setPunctuationSuggestions(); @@ -805,7 +805,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar || TextEntryState.isRecorrecting()) && (newSelStart < newSelEnd - 1 || !mHasValidSuggestions)) { if (isCursorTouchingWord() || mLastSelectionStart < mLastSelectionEnd) { - mHandler.cancelSetBigramSuggestions(); + mHandler.cancelUpdateBigramPredictions(); mHandler.postUpdateOldSuggestions(); } else { abortRecorrection(false); @@ -817,7 +817,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (null == ic || !TextUtils.isEmpty(ic.getTextAfterCursor(1, 0))) { if (!isShowingPunctuationList()) setPunctuationSuggestions(); } else { - mHandler.postSetBigramSuggestions(); + mHandler.postUpdateBigramPredictions(); } } } @@ -1261,7 +1261,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (1 == length) { // 1 == length means we are about to erase the last character of the word, // so we can show bigrams. - mHandler.postSetBigramSuggestions(); + mHandler.postUpdateBigramPredictions(); } else { // length > 1, so we still have letters to deduce a suggestion from. mHandler.postUpdateSuggestions(); @@ -1401,7 +1401,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Should dismiss the "Touch again to save" message when handling separator if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) { - mHandler.cancelSetBigramSuggestions(); + mHandler.cancelUpdateBigramPredictions(); mHandler.postUpdateSuggestions(); } @@ -1461,7 +1461,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (!isCursorTouchingWord()) { mHandler.cancelUpdateSuggestions(); mHandler.cancelUpdateOldSuggestions(); - mHandler.postSetBigramSuggestions(); + mHandler.postUpdateBigramPredictions(); } } else { // Set punctuation right away. onUpdateSelection will fire but tests whether it is @@ -1859,10 +1859,15 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } private static final WordComposer sEmptyWordComposer = new WordComposer(); - private void updateBigramSuggestions() { + private void updateBigramPredictions() { if (mSuggest == null || !isSuggestionsRequested()) return; + if (!mBigramPredictionEnabled) { + setPunctuationSuggestions(); + return; + } + final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(), mWordSeparators); SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder( @@ -1977,7 +1982,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar ic.setComposingText(mComposing, 1); TextEntryState.backspace(); } - mHandler.cancelSetBigramSuggestions(); + mHandler.cancelUpdateBigramPredictions(); mHandler.postUpdateSuggestions(); } else { sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); From c5c57b506e97b334a394d23ed73c9597cb55707a Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 22 Apr 2011 11:09:48 +0900 Subject: [PATCH 6/6] Move sliding language switch code to PointerTracker This change is hack and temporal. Big: 4328445 Change-Id: I0b8851e9f05390db20ddaa10f35cff1cc9f016da --- .../keyboard/KeyboardSwitcher.java | 11 --- .../inputmethod/keyboard/LatinKeyboard.java | 99 ++++++------------- .../keyboard/LatinKeyboardView.java | 26 +---- .../inputmethod/keyboard/PointerTracker.java | 64 ++++++++++-- .../keyboard/PointerTrackerQueue.java | 9 +- .../android/inputmethod/latin/LatinIME.java | 8 +- 6 files changed, 95 insertions(+), 122 deletions(-) diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index a58ad2310..f97d1283a 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -146,11 +146,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha // Update the settings key state because number of enabled IMEs could have been changed mSettingsKeyEnabledInSettings = getSettingsKeyMode(mPrefs, mInputMethodService); final KeyboardId id = getKeyboardId(attribute, isSymbols); - - final Keyboard oldKeyboard = mInputView.getKeyboard(); - if (oldKeyboard != null && oldKeyboard.mId.equals(id)) - return; - makeSymbolsKeyboardIds(id.mMode, attribute); mCurrentId = id; mInputView.setKeyPreviewEnabled(mInputMethodService.getPopupOn()); @@ -296,12 +291,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha return null; } - public void keyReleased() { - LatinKeyboard latinKeyboard = getLatinKeyboard(); - if (latinKeyboard != null) - latinKeyboard.keyReleased(); - } - public boolean isShiftedOrShiftLocked() { LatinKeyboard latinKeyboard = getLatinKeyboard(); if (latinKeyboard != null) diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java index b8bcee687..5854db656 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java @@ -56,17 +56,15 @@ public class LatinKeyboard extends Keyboard { private final Key mSpaceKey; private final Drawable mSpaceIcon; private final Drawable mSpacePreviewIcon; - private final int[] mSpaceKeyIndexArray; + private final int mSpaceKeyIndex; private final Drawable mSpaceAutoCorrectionIndicator; private final Drawable mButtonArrowLeftIcon; private final Drawable mButtonArrowRightIcon; private final int mSpacebarTextColor; private final int mSpacebarTextShadowColor; - private final int mSpacebarVerticalCorrection; private float mSpacebarTextFadeFactor = 0.0f; - private int mSpaceDragStartX; - private int mSpaceDragLastDiff; - private boolean mCurrentlyInSpace; + private final int mSpacebarLanguageSwitchThreshold; + private int mSpacebarLanguageSwitchDiff; private SlidingLocaleDrawable mSlidingLocaleIcon; private final HashMap> mSpaceDrawableCache = new HashMap>(); @@ -115,7 +113,7 @@ public class LatinKeyboard extends Keyboard { mSpaceKey = (spaceKeyIndex >= 0) ? keys.get(spaceKeyIndex) : null; mSpaceIcon = (mSpaceKey != null) ? mSpaceKey.getIcon() : null; mSpacePreviewIcon = (mSpaceKey != null) ? mSpaceKey.getPreviewIcon() : null; - mSpaceKeyIndexArray = new int[] { spaceKeyIndex }; + mSpaceKeyIndex = spaceKeyIndex; mShortcutKey = (shortcutKeyIndex >= 0) ? keys.get(shortcutKeyIndex) : null; mEnabledShortcutIcon = (mShortcutKey != null) ? mShortcutKey.getIcon() : null; @@ -133,8 +131,8 @@ public class LatinKeyboard extends Keyboard { mSpaceAutoCorrectionIndicator = res.getDrawable(R.drawable.sym_keyboard_space_led); mButtonArrowLeftIcon = res.getDrawable(R.drawable.sym_keyboard_language_arrows_left); mButtonArrowRightIcon = res.getDrawable(R.drawable.sym_keyboard_language_arrows_right); - mSpacebarVerticalCorrection = res.getDimensionPixelOffset( - R.dimen.spacebar_vertical_correction); + // The threshold is "key width" x 1.5 + mSpacebarLanguageSwitchThreshold = (getMostCommonKeyWidth() * 3) / 2; } public void setSpacebarTextFadeFactor(float fadeFactor, LatinKeyboardView view) { @@ -325,7 +323,10 @@ public class LatinKeyboard extends Keyboard { return buffer; } - private void updateLocaleDrag(int diff) { + public void updateSpacebarPreviewIcon(int diff) { + if (mSpacebarLanguageSwitchDiff == diff) + return; + mSpacebarLanguageSwitchDiff = diff; if (mSlidingLocaleIcon == null) { final int width = Math.max(mSpaceKey.mWidth, (int)(getMinWidth() * SPACEBAR_POPUP_MIN_RATIO)); @@ -333,7 +334,6 @@ public class LatinKeyboard extends Keyboard { mSlidingLocaleIcon = new SlidingLocaleDrawable(mContext, mSpacePreviewIcon, width, height); mSlidingLocaleIcon.setBounds(0, 0, width, height); - mSpaceKey.setPreviewIcon(mSlidingLocaleIcon); } mSlidingLocaleIcon.setDiff(diff); if (Math.abs(diff) == Integer.MAX_VALUE) { @@ -344,85 +344,44 @@ public class LatinKeyboard extends Keyboard { mSpaceKey.getPreviewIcon().invalidateSelf(); } - // This method is called when "popup on keypress" is off. + public boolean shouldTriggerSpacebarSlidingLanguageSwitch(int diff) { + return Math.abs(diff) > mSpacebarLanguageSwitchThreshold; + } + + /** + * Return true if spacebar needs showing preview even when "popup on keypress" is off. + * @param keyIndex index of the pressing key + * @return true if spacebar needs showing preview + */ @Override public boolean needSpacebarPreview(int keyIndex) { + // This method is called when "popup on keypress" is off. if (!mSubtypeSwitcher.useSpacebarLanguageSwitcher()) return false; // Dismiss key preview. if (keyIndex == KeyDetector.NOT_A_KEY) return true; // Key is not a spacebar. - if (keyIndex != mSpaceKeyIndexArray[0]) + if (keyIndex != mSpaceKeyIndex) return false; // The language switcher will be displayed only when the dragging distance is greater - // than average key width of this keyboard. - return Math.abs(mSpaceDragLastDiff) > getMostCommonKeyWidth(); + // than the threshold. + return shouldTriggerSpacebarSlidingLanguageSwitch(mSpacebarLanguageSwitchDiff); } public int getLanguageChangeDirection() { - if (mSpaceKey == null || SubtypeSwitcher.getInstance().getEnabledKeyboardLocaleCount() <= 1 - || Math.abs(mSpaceDragLastDiff) < getMostCommonKeyWidth() * SPACEBAR_DRAG_WIDTH) { + if (mSpaceKey == null || mSubtypeSwitcher.getEnabledKeyboardLocaleCount() <= 1 || Math.abs( + mSpacebarLanguageSwitchDiff) < getMostCommonKeyWidth() * SPACEBAR_DRAG_WIDTH) { return 0; // No change } - return mSpaceDragLastDiff > 0 ? 1 : -1; - } - - public void keyReleased() { - mCurrentlyInSpace = false; - mSpaceDragLastDiff = 0; - if (mSpaceKey != null) { - updateLocaleDrag(Integer.MAX_VALUE); - } - } - - /** - * Does the magic of locking the touch gesture into the spacebar when - * switching input languages. - */ - @Override - public boolean isInside(Key key, int pointX, int pointY) { - int x = pointX; - int y = pointY; - final int code = key.mCode; - if (code == CODE_SPACE) { - y += mSpacebarVerticalCorrection; - if (SubtypeSwitcher.getInstance().useSpacebarLanguageSwitcher() - && SubtypeSwitcher.getInstance().getEnabledKeyboardLocaleCount() > 1) { - if (mCurrentlyInSpace) { - int diff = x - mSpaceDragStartX; - if (Math.abs(diff - mSpaceDragLastDiff) > 0) { - updateLocaleDrag(diff); - } - mSpaceDragLastDiff = diff; - return true; - } else { - boolean isOnSpace = key.isOnKey(x, y); - if (isOnSpace) { - mCurrentlyInSpace = true; - mSpaceDragStartX = x; - updateLocaleDrag(0); - } - return isOnSpace; - } - } - } - - // Lock into the spacebar - if (mCurrentlyInSpace) return false; - - return key.isOnKey(x, y); + return mSpacebarLanguageSwitchDiff > 0 ? 1 : -1; } @Override public int[] getNearestKeys(int x, int y) { - if (mCurrentlyInSpace) { - return mSpaceKeyIndexArray; - } else { - // Avoid dead pixels at edges of the keyboard - return super.getNearestKeys(Math.max(0, Math.min(x, getMinWidth() - 1)), - Math.max(0, Math.min(y, getHeight() - 1))); - } + // Avoid dead pixels at edges of the keyboard + return super.getNearestKeys(Math.max(0, Math.min(x, getMinWidth() - 1)), + Math.max(0, Math.min(y, getHeight() - 1))); } private static int getTextSizeFromTheme(Theme theme, int style, int defValue) { diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index a64a9e609..efc446a0d 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -68,11 +68,6 @@ public class LatinKeyboardView extends KeyboardView { @Override public void setKeyboard(Keyboard newKeyboard) { - final LatinKeyboard oldKeyboard = getLatinKeyboard(); - if (oldKeyboard != null) { - // Reset old keyboard state before switching to new keyboard. - oldKeyboard.keyReleased(); - } super.setKeyboard(newKeyboard); // One-seventh of the keyboard width seems like a reasonable threshold mJumpThresholdSquare = newKeyboard.getMinWidth() / 7; @@ -216,8 +211,7 @@ public class LatinKeyboardView extends KeyboardView { @Override public boolean onTouchEvent(MotionEvent me) { - LatinKeyboard keyboard = getLatinKeyboard(); - if (keyboard == null) return true; + if (getLatinKeyboard() == null) return true; // If there was a sudden jump, return without processing the actual motion event. if (handleSuddenJump(me)) { @@ -226,24 +220,6 @@ public class LatinKeyboardView extends KeyboardView { return true; } - // Reset any bounding box controls in the keyboard - if (me.getAction() == MotionEvent.ACTION_DOWN) { - keyboard.keyReleased(); - } - - if (me.getAction() == MotionEvent.ACTION_UP) { - int languageDirection = keyboard.getLanguageChangeDirection(); - if (languageDirection != 0) { - getOnKeyboardActionListener().onCodeInput( - languageDirection == 1 - ? LatinKeyboard.CODE_NEXT_LANGUAGE : LatinKeyboard.CODE_PREV_LANGUAGE, - null, mLastX, mLastY); - me.setAction(MotionEvent.ACTION_CANCEL); - keyboard.keyReleased(); - return super.onTouchEvent(me); - } - } - return super.onTouchEvent(me); } diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 1b1aa492c..29867c381 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -19,6 +19,7 @@ package com.android.inputmethod.keyboard; import com.android.inputmethod.keyboard.KeyboardView.UIHandler; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.SubtypeSwitcher; import android.content.res.Resources; import android.util.Log; @@ -90,6 +91,12 @@ public class PointerTracker { // ignore modifier key if true private boolean mIgnoreModifierKey; + // TODO: Remove these hacking variables + // true if this pointer is in sliding language switch + private boolean mIsInSlidingLanguageSwitch; + private int mSpaceKeyIndex; + private final SubtypeSwitcher mSubtypeSwitcher; + // Empty {@link KeyboardActionListener} private static final KeyboardActionListener EMPTY_LISTENER = new KeyboardActionListener() { @Override @@ -129,6 +136,7 @@ public class PointerTracker { R.dimen.config_touch_noise_threshold_distance); mTouchNoiseThresholdDistanceSquared = (int)( touchNoiseThresholdDistance * touchNoiseThresholdDistance); + mSubtypeSwitcher = SubtypeSwitcher.getInstance(); } public void setOnKeyboardActionListener(KeyboardActionListener listener) { @@ -338,6 +346,7 @@ public class PointerTracker { mKeyAlreadyProcessed = false; mIsRepeatableKey = false; mIsInSlidingKeyInput = false; + mIsInSlidingLanguageSwitch = false; mIgnoreModifierKey = false; if (isValidKeyIndex(keyIndex)) { // This onPress call may have changed keyboard layout. Those cases are detected at @@ -374,6 +383,12 @@ public class PointerTracker { return; final PointerTrackerKeyState keyState = mKeyState; + // TODO: Remove this hacking code + if (mIsInSlidingLanguageSwitch) { + ((LatinKeyboard)mKeyboard).updateSpacebarPreviewIcon(x - keyState.getKeyX()); + showKeyPreview(mSpaceKeyIndex); + return; + } final int lastX = keyState.getLastX(); final int lastY = keyState.getLastY(); final int oldKeyIndex = keyState.getKeyIndex(); @@ -428,11 +443,25 @@ public class PointerTracker { dismissKeyPreview(); setReleasedKeyGraphics(oldKeyIndex); } - return; } - } else if (mKeyboard.needSpacebarPreview(keyIndex)) { - // Display spacebar slide language switcher. - showKeyPreview(keyIndex); + } + // TODO: Remove this hack code + else if (isSpaceKey(keyIndex) && !mIsInSlidingLanguageSwitch + && mKeyboard instanceof LatinKeyboard) { + final LatinKeyboard keyboard = ((LatinKeyboard)mKeyboard); + if (mSubtypeSwitcher.useSpacebarLanguageSwitcher() + && mSubtypeSwitcher.getEnabledKeyboardLocaleCount() > 1) { + final int diff = x - keyState.getKeyX(); + if (keyboard.shouldTriggerSpacebarSlidingLanguageSwitch(diff)) { + // Detect start sliding language switch. + mIsInSlidingLanguageSwitch = true; + mSpaceKeyIndex = keyIndex; + keyboard.updateSpacebarPreviewIcon(diff); + // Display spacebar slide language switcher. + showKeyPreview(keyIndex); + queue.releaseAllPointersExcept(this, eventTime, true); + } + } } } else { if (oldKey != null && isMajorEnoughMoveToBeOnNewKey(x, y, keyIndex)) { @@ -447,7 +476,6 @@ public class PointerTracker { } else { mKeyAlreadyProcessed = true; dismissKeyPreview(); - return; } } } @@ -462,7 +490,7 @@ public class PointerTracker { if (isModifier()) { // Before processing an up event of modifier key, all pointers already being // tracked should be released. - queue.releaseAllPointersExcept(this, eventTime); + queue.releaseAllPointersExcept(this, eventTime, true); } else { queue.releaseAllPointersOlderThan(this, eventTime); } @@ -474,8 +502,10 @@ public class PointerTracker { // Let this pointer tracker know that one of newer-than-this pointer trackers got an up event. // This pointer tracker needs to keep the key top graphics "pressed", but needs to get a // "virtual" up event. - public void onPhantomUpEvent(int x, int y, long eventTime) { - onUpEventInternal(x, y, eventTime, false); + public void onPhantomUpEvent(int x, int y, long eventTime, boolean updateReleasedKeyGraphics) { + if (DEBUG_EVENT) + printTouchEvent("onPhntEvent:", x, y, eventTime); + onUpEventInternal(x, y, eventTime, updateReleasedKeyGraphics); mKeyAlreadyProcessed = true; } @@ -500,6 +530,20 @@ public class PointerTracker { setReleasedKeyGraphics(keyIndex); if (mKeyAlreadyProcessed) return; + // TODO: Remove this hacking code + if (mIsInSlidingLanguageSwitch) { + setReleasedKeyGraphics(mSpaceKeyIndex); + final int languageDir = ((LatinKeyboard)mKeyboard).getLanguageChangeDirection(); + if (languageDir != 0) { + final int code = (languageDir == 1) + ? LatinKeyboard.CODE_NEXT_LANGUAGE : LatinKeyboard.CODE_PREV_LANGUAGE; + // This will change keyboard layout. + mListener.onCodeInput(code, new int[] {code}, keyX, keyY); + } + ((LatinKeyboard)mKeyboard).updateSpacebarPreviewIcon(0); + mIsInSlidingLanguageSwitch = false; + return; + } if (!mIsRepeatableKey) { detectAndSendKey(keyIndex, keyX, keyY); } @@ -515,8 +559,10 @@ public class PointerTracker { if (DEBUG_EVENT) printTouchEvent("onCancelEvt:", x, y, eventTime); - if (queue != null) + if (queue != null) { + queue.releaseAllPointersExcept(this, eventTime, true); queue.remove(this); + } onCancelEventInternal(); } diff --git a/java/src/com/android/inputmethod/keyboard/PointerTrackerQueue.java b/java/src/com/android/inputmethod/keyboard/PointerTrackerQueue.java index 0a9410042..42089d5ea 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTrackerQueue.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTrackerQueue.java @@ -35,21 +35,22 @@ public class PointerTrackerQueue { if (t.isModifier()) { oldestPos++; } else { - t.onPhantomUpEvent(t.getLastX(), t.getLastY(), eventTime); + t.onPhantomUpEvent(t.getLastX(), t.getLastY(), eventTime, false); queue.remove(oldestPos); } } } public void releaseAllPointers(long eventTime) { - releaseAllPointersExcept(null, eventTime); + releaseAllPointersExcept(null, eventTime, true); } - public void releaseAllPointersExcept(PointerTracker tracker, long eventTime) { + public void releaseAllPointersExcept(PointerTracker tracker, long eventTime, + boolean updateReleasedKeyGraphics) { for (PointerTracker t : mQueue) { if (t == tracker) continue; - t.onPhantomUpEvent(t.getLastX(), t.getLastY(), eventTime); + t.onPhantomUpEvent(t.getLastX(), t.getLastY(), eventTime, updateReleasedKeyGraphics); } mQueue.clear(); if (tracker != null) diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index f9bcfc655..28fd6aad7 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -359,11 +359,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); if (inputView != null) { final LatinKeyboard keyboard = mKeyboardSwitcher.getLatinKeyboard(); + // The language is always displayed when the delay is negative. + final boolean needsToDisplayLanguage = localeChanged + || mConfigDelayBeforeFadeoutLanguageOnSpacebar < 0; // The language is never displayed when the delay is zero. if (mConfigDelayBeforeFadeoutLanguageOnSpacebar != 0) - inputView.setSpacebarTextFadeFactor(localeChanged ? 1.0f + inputView.setSpacebarTextFadeFactor(needsToDisplayLanguage ? 1.0f : mConfigFinalFadeoutFactorOfLanguageOnSpacebar, keyboard); - // The language is always displayed when the delay is negative. + // The fadeout animation will start when the delay is positive. if (localeChanged && mConfigDelayBeforeFadeoutLanguageOnSpacebar > 0) { sendMessageDelayed(obtainMessage(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR, keyboard), mConfigDelayBeforeFadeoutLanguageOnSpacebar); @@ -2058,7 +2061,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar public void onRelease(int primaryCode, boolean withSliding) { KeyboardSwitcher switcher = mKeyboardSwitcher; // Reset any drag flags in the keyboard - switcher.keyReleased(); final boolean distinctMultiTouch = switcher.hasDistinctMultitouch(); if (distinctMultiTouch && primaryCode == Keyboard.CODE_SHIFT) { switcher.onReleaseShift(withSliding);