diff options
Diffstat (limited to 'java/src/com')
16 files changed, 367 insertions, 199 deletions
diff --git a/java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java b/java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java index e4b2e035c..1a606eaaf 100644 --- a/java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java +++ b/java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java @@ -83,6 +83,7 @@ public class LanguageSwitcher { String currentLanguage = sp.getString(Settings.PREF_INPUT_LANGUAGE, null); if (TextUtils.isEmpty(selectedLanguages)) { mSelectedLanguageArray = EMPTY_STIRNG_ARRAY; + mSelectedLanguages = null; loadDefaults(); if (mLocales.size() == 0) { return false; 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/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index a58ad2310..e163457d8 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()); @@ -195,6 +190,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha // we should reset the text fade factor. It is also applicable to shortcut key. keyboard.setSpacebarTextFadeFactor(0.0f, null); keyboard.updateShortcutKey(mSubtypeSwitcher.isShortcutImeReady(), null); + keyboard.setSpacebarSlidingLanguageSwitchDiff(0); return keyboard; } @@ -296,12 +292,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/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 95ecb3bc9..c36895258 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -139,6 +139,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { private final boolean mHasDistinctMultitouch; private int mOldPointerCount = 1; + private int mOldKeyIndex; // Accessibility private boolean mIsAccessibilityEnabled; @@ -202,7 +203,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { break; case MSG_REPEAT_KEY: { final PointerTracker tracker = (PointerTracker)msg.obj; - tracker.repeatKey(msg.arg1); + tracker.onRepeatKey(msg.arg1); startKeyRepeatTimer(mKeyRepeatInterval, msg.arg1, tracker); break; } @@ -1270,10 +1271,6 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { } if (mHandler.isInKeyRepeat()) { - // It will keep being in the key repeating mode while the key is being pressed. - if (action == MotionEvent.ACTION_MOVE) { - return true; - } final PointerTracker tracker = getPointerTracker(id); // Key repeating timer will be canceled if 2 or more keys are in action, and current // event (UP or DOWN) is non-modifier key. @@ -1291,12 +1288,21 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { PointerTracker tracker = getPointerTracker(0); if (pointerCount == 1 && oldPointerCount == 2) { // Multi-touch to single touch transition. - // Send a down event for the latest pointer. - tracker.onDownEvent(x, y, eventTime, null); + // Send a down event for the latest pointer if the key is different from the + // previous key. + final int newKeyIndex = tracker.getKeyIndexOn(x, y); + if (mOldKeyIndex != newKeyIndex) { + tracker.onDownEvent(x, y, eventTime, null); + if (action == MotionEvent.ACTION_UP) + tracker.onUpEvent(x, y, eventTime, null); + } } else if (pointerCount == 2 && oldPointerCount == 1) { // Single-touch to multi-touch transition. // Send an up event for the last pointer. - tracker.onUpEvent(tracker.getLastX(), tracker.getLastY(), eventTime, null); + final int lastX = tracker.getLastX(); + final int lastY = tracker.getLastY(); + mOldKeyIndex = tracker.getKeyIndexOn(lastX, lastY); + tracker.onUpEvent(lastX, lastY, eventTime, null); } else if (pointerCount == 1 && oldPointerCount == 1) { tracker.onTouchEvent(action, x, y, eventTime, null); } else { diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboard.java index 3a5dbd2de..a1d0607bf 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(); @@ -53,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 mSpacebarSlidingLanguageSwitchDiff; private SlidingLocaleDrawable mSlidingLocaleIcon; private final HashMap<Integer, SoftReference<BitmapDrawable>> mSpaceDrawableCache = new HashMap<Integer, SoftReference<BitmapDrawable>>(); @@ -102,7 +103,7 @@ public class LatinKeyboard extends Keyboard { case CODE_SPACE: spaceKeyIndex = index; break; - case CODE_VOICE: + case CODE_SHORTCUT: shortcutKeyIndex = index; break; } @@ -112,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; @@ -130,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.25 + mSpacebarLanguageSwitchThreshold = (getMostCommonKeyWidth() * 5) / 4; } public void setSpacebarTextFadeFactor(float fadeFactor, LatinKeyboardView view) { @@ -322,7 +323,14 @@ public class LatinKeyboard extends Keyboard { return buffer; } - private void updateLocaleDrag(int diff) { + public void setSpacebarSlidingLanguageSwitchDiff(int diff) { + mSpacebarSlidingLanguageSwitchDiff = diff; + } + + public void updateSpacebarPreviewIcon(int diff) { + if (mSpacebarSlidingLanguageSwitchDiff == diff) + return; + mSpacebarSlidingLanguageSwitchDiff = diff; if (mSlidingLocaleIcon == null) { final int width = Math.max(mSpaceKey.mWidth, (int)(getMinWidth() * SPACEBAR_POPUP_MIN_RATIO)); @@ -330,7 +338,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) { @@ -341,85 +348,45 @@ 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(mSpacebarSlidingLanguageSwitchDiff); } 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(mSpacebarSlidingLanguageSwitchDiff) + < 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 mSpacebarSlidingLanguageSwitchDiff > 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 912074515..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 - ? Keyboard.CODE_NEXT_LANGUAGE : Keyboard.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..e3161f610 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) { @@ -243,6 +251,10 @@ public class PointerTracker { return key != null && key.mCode == Keyboard.CODE_SHIFT; } + public int getKeyIndexOn(int x, int y) { + return mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null); + } + public boolean isSpaceKey(int keyIndex) { Key key = getKey(keyIndex); return key != null && key.mCode == Keyboard.CODE_SPACE; @@ -338,6 +350,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 @@ -346,14 +359,7 @@ public class PointerTracker { if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), false)) keyIndex = mKeyState.onDownKey(x, y, eventTime); - // Accessibility disables key repeat because users may need to pause on a key to hear - // its spoken description. - final Key key = getKey(keyIndex); - if (key != null && key.mRepeatable && !mIsAccessibilityEnabled) { - repeatKey(keyIndex); - mHandler.startKeyRepeatTimer(mDelayBeforeKeyRepeatStart, keyIndex, this); - mIsRepeatableKey = true; - } + startRepeatKey(keyIndex); startLongPressTimer(keyIndex); showKeyPreview(keyIndex); setPressedKeyGraphics(keyIndex); @@ -374,6 +380,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(); @@ -399,7 +411,8 @@ public class PointerTracker { setReleasedKeyGraphics(oldKeyIndex); callListenerOnRelease(oldKey, oldKey.mCode, true); startSlidingKeyInput(oldKey); - mHandler.cancelLongPressTimers(); + mHandler.cancelKeyTimers(); + startRepeatKey(keyIndex); if (mIsAllowedSlidingKeyInput) { // This onPress call may have changed keyboard layout. Those cases are detected // at {@link #setKeyboard}. In those cases, we should update keyIndex according @@ -428,11 +441,26 @@ 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); + if (queue != null) + queue.releaseAllPointersExcept(this, eventTime, true); + } + } } } else { if (oldKey != null && isMajorEnoughMoveToBeOnNewKey(x, y, keyIndex)) { @@ -447,7 +475,6 @@ public class PointerTracker { } else { mKeyAlreadyProcessed = true; dismissKeyPreview(); - return; } } } @@ -462,7 +489,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 +501,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 +529,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); + } + mIsInSlidingLanguageSwitch = false; + ((LatinKeyboard)mKeyboard).setSpacebarSlidingLanguageSwitchDiff(0); + return; + } if (!mIsRepeatableKey) { detectAndSendKey(keyIndex, keyX, keyY); } @@ -507,7 +550,8 @@ public class PointerTracker { public void onLongPressed(PointerTrackerQueue queue) { mKeyAlreadyProcessed = true; - queue.remove(this); + if (queue != null) + queue.remove(this); } public void onCancelEvent(int x, int y, long eventTime, PointerTrackerQueue queue) { @@ -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(); } @@ -528,7 +574,21 @@ public class PointerTracker { mIsInSlidingKeyInput = false; } - public void repeatKey(int keyIndex) { + private void startRepeatKey(int keyIndex) { + // Accessibility disables key repeat because users may need to pause on a key to hear + // its spoken description. + final Key key = getKey(keyIndex); + if (key != null && key.mRepeatable && !mIsAccessibilityEnabled) { + dismissKeyPreview(); + onRepeatKey(keyIndex); + mHandler.startKeyRepeatTimer(mDelayBeforeKeyRepeatStart, keyIndex, this); + mIsRepeatableKey = true; + } else { + mIsRepeatableKey = false; + } + } + + public void onRepeatKey(int keyIndex) { Key key = getKey(keyIndex); if (key != null) { detectAndSendKey(keyIndex, key.mX, key.mY); diff --git a/java/src/com/android/inputmethod/keyboard/PointerTrackerQueue.java b/java/src/com/android/inputmethod/keyboard/PointerTrackerQueue.java index 0a9410042..68de8df8a 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, true); 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/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/DebugSettings.java b/java/src/com/android/inputmethod/latin/DebugSettings.java index 2f1e7c2b8..fd62d61c3 100644 --- a/java/src/com/android/inputmethod/latin/DebugSettings.java +++ b/java/src/com/android/inputmethod/latin/DebugSettings.java @@ -33,6 +33,7 @@ public class DebugSettings extends PreferenceActivity private boolean mServiceNeedsRestart = false; private CheckBoxPreference mDebugMode; + private CheckBoxPreference mUseSpacebarLanguageSwitch; @Override protected void onCreate(Bundle icicle) { @@ -60,6 +61,13 @@ public class DebugSettings extends PreferenceActivity updateDebugMode(); mServiceNeedsRestart = true; } + } else if (key.equals(SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCH_KEY)) { + if (mUseSpacebarLanguageSwitch != null) { + mUseSpacebarLanguageSwitch.setChecked( + prefs.getBoolean(SubtypeSwitcher.USE_SPACEBAR_LANGUAGE_SWITCH_KEY, + getResources().getBoolean( + R.bool.config_use_spacebar_language_switcher))); + } } } 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 a680b9825..28fd6aad7 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -177,7 +177,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private boolean mJustAddedAutoSpace; private boolean mAutoCorrectEnabled; private boolean mRecorrectionEnabled; + // Suggestion: use bigrams to adjust scores of suggestions obtained from unigram dictionary private boolean mBigramSuggestionEnabled; + // Prediction: use bigrams to predict the next word when there is no input for it yet + private boolean mBigramPredictionEnabled; private boolean mAutoCorrectOn; private boolean mVibrateOn; private boolean mSoundOn; @@ -266,6 +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_PREDICTIONS = 7; @Override public void handleMessage(Message msg) { @@ -281,6 +285,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar case MSG_UPDATE_SHIFT_STATE: switcher.updateShiftState(); break; + case MSG_SET_BIGRAM_PREDICTIONS: + updateBigramPredictions(); + break; case MSG_VOICE_RESULTS: mVoiceProxy.handleVoiceResults(preferCapitalization() || (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked())); @@ -333,6 +340,15 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar removeMessages(MSG_UPDATE_SHIFT_STATE); } + public void postUpdateBigramPredictions() { + removeMessages(MSG_SET_BIGRAM_PREDICTIONS); + sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS), DELAY_UPDATE_SUGGESTIONS); + } + + public void cancelUpdateBigramPredictions() { + removeMessages(MSG_SET_BIGRAM_PREDICTIONS); + } + public void updateVoiceResults() { sendMessage(obtainMessage(MSG_VOICE_RESULTS)); } @@ -343,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); @@ -548,7 +567,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 +773,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } mComposing.setLength(0); mHasValidSuggestions = false; - mHandler.postUpdateSuggestions(); + if (isCursorTouchingWord()) { + mHandler.cancelUpdateBigramPredictions(); + mHandler.postUpdateSuggestions(); + } else { + setPunctuationSuggestions(); + } TextEntryState.reset(); InputConnection ic = getCurrentInputConnection(); if (ic != null) { @@ -784,14 +808,20 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar || TextEntryState.isRecorrecting()) && (newSelStart < newSelEnd - 1 || !mHasValidSuggestions)) { if (isCursorTouchingWord() || mLastSelectionStart < mLastSelectionEnd) { + mHandler.cancelUpdateBigramPredictions(); 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.postUpdateBigramPredictions(); + } } } } @@ -1159,16 +1189,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: @@ -1231,7 +1261,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.postUpdateBigramPredictions(); + } else { + // length > 1, so we still have letters to deduce a suggestion from. + mHandler.postUpdateSuggestions(); + } } else { ic.deleteSurroundingText(1, 0); } @@ -1367,6 +1404,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.cancelUpdateBigramPredictions(); mHandler.postUpdateSuggestions(); } @@ -1406,6 +1444,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 +1455,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.postUpdateBigramPredictions(); + } + } 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 +1703,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 +1746,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 +1861,30 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } } + private static final WordComposer sEmptyWordComposer = new WordComposer(); + private void updateBigramPredictions() { + if (mSuggest == null || !isSuggestionsRequested()) + return; + + if (!mBigramPredictionEnabled) { + setPunctuationSuggestions(); + 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 +1985,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar ic.setComposingText(mComposing, 1); TextEntryState.backspace(); } + mHandler.cancelUpdateBigramPredictions(); mHandler.postUpdateSuggestions(); } else { sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); @@ -1982,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); @@ -2132,6 +2210,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mAutoCorrectEnabled = isAutoCorrectEnabled(prefs); mBigramSuggestionEnabled = mAutoCorrectEnabled && isBigramSuggestionEnabled(prefs); + mBigramPredictionEnabled = mBigramSuggestionEnabled && isBigramPredictionEnabled(prefs); loadAndSetAutoCorrectionThreshold(prefs); mVoiceProxy.loadSettings(attribute, prefs); @@ -2216,6 +2295,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar R.bool.config_default_bigram_suggestions)); } + private boolean isBigramPredictionEnabled(SharedPreferences sp) { + return sp.getBoolean(Settings.PREF_BIGRAM_PREDICTIONS, mResources.getBoolean( + R.bool.config_default_bigram_prediction)); + } + private void initSuggestPuncList() { if (mSuggestPuncs != null || mSuggestPuncList != null) return; diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java index 6a0b7b009..42b0fadc2 100644 --- a/java/src/com/android/inputmethod/latin/Settings.java +++ b/java/src/com/android/inputmethod/latin/Settings.java @@ -62,13 +62,18 @@ public class Settings extends PreferenceActivity public static final String PREF_SELECTED_LANGUAGES = "selected_languages"; public static final String PREF_SUBTYPES = "subtype_settings"; - public static final String PREF_PREDICTION_SETTINGS_KEY = "prediction_settings"; + public static final String PREF_CORRECTION_SETTINGS_KEY = "correction_settings"; public static final String PREF_QUICK_FIXES = "quick_fixes"; public static final String PREF_SHOW_SUGGESTIONS_SETTING = "show_suggestions_setting"; public static final String PREF_AUTO_CORRECTION_THRESHOLD = "auto_correction_threshold"; - public static final String PREF_BIGRAM_SUGGESTIONS = "bigram_suggestion"; public static final String PREF_DEBUG_SETTINGS = "debug_settings"; + public static final String PREF_NGRAM_SETTINGS_KEY = "ngram_settings"; + public static final String PREF_BIGRAM_SUGGESTIONS = "bigram_suggestion"; + public static final String PREF_BIGRAM_PREDICTIONS = "bigram_prediction"; + + public static final String PREF_MISC_SETTINGS_KEY = "misc_settings"; + public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; // Dialog ids @@ -80,7 +85,10 @@ public class Settings extends PreferenceActivity private ListPreference mSettingsKeyPreference; private ListPreference mShowCorrectionSuggestionsPreference; private ListPreference mAutoCorrectionThreshold; + // Suggestion: use bigrams to adjust scores of suggestions obtained from unigram dictionary private CheckBoxPreference mBigramSuggestion; + // Prediction: use bigrams to predict the next word when there is no input for it yet + private CheckBoxPreference mBigramPrediction; private Preference mDebugSettingsPreference; private boolean mVoiceOn; @@ -96,6 +104,7 @@ public class Settings extends PreferenceActivity R.string.auto_correction_threshold_mode_index_off); final String currentSetting = mAutoCorrectionThreshold.getValue(); mBigramSuggestion.setEnabled(!currentSetting.equals(autoCorrectionOff)); + mBigramPrediction.setEnabled(!currentSetting.equals(autoCorrectionOff)); } @Override @@ -119,6 +128,7 @@ public class Settings extends PreferenceActivity mAutoCorrectionThreshold = (ListPreference) findPreference(PREF_AUTO_CORRECTION_THRESHOLD); mBigramSuggestion = (CheckBoxPreference) findPreference(PREF_BIGRAM_SUGGESTIONS); + mBigramPrediction = (CheckBoxPreference) findPreference(PREF_BIGRAM_PREDICTIONS); mDebugSettingsPreference = findPreference(PREF_DEBUG_SETTINGS); if (mDebugSettingsPreference != null) { final Intent debugSettingsIntent = new Intent(Intent.ACTION_MAIN); @@ -131,7 +141,9 @@ public class Settings extends PreferenceActivity final PreferenceGroup generalSettings = (PreferenceGroup) findPreference(PREF_GENERAL_SETTINGS_KEY); final PreferenceGroup textCorrectionGroup = - (PreferenceGroup) findPreference(PREF_PREDICTION_SETTINGS_KEY); + (PreferenceGroup) findPreference(PREF_CORRECTION_SETTINGS_KEY); + final PreferenceGroup bigramGroup = + (PreferenceGroup) findPreference(PREF_NGRAM_SETTINGS_KEY); final boolean showSettingsKeyOption = getResources().getBoolean( R.bool.config_enable_show_settings_key_option); @@ -178,6 +190,7 @@ public class Settings extends PreferenceActivity R.bool.config_enable_bigram_suggestions_option); if (!showBigramSuggestionsOption) { textCorrectionGroup.removePreference(findPreference(PREF_BIGRAM_SUGGESTIONS)); + textCorrectionGroup.removePreference(findPreference(PREF_BIGRAM_PREDICTIONS)); } final boolean showUsabilityModeStudyOption = getResources().getBoolean( @@ -192,7 +205,7 @@ public class Settings extends PreferenceActivity super.onResume(); int autoTextSize = AutoText.getSize(getListView()); if (autoTextSize < 1) { - ((PreferenceGroup) findPreference(PREF_PREDICTION_SETTINGS_KEY)) + ((PreferenceGroup) findPreference(PREF_CORRECTION_SETTINGS_KEY)) .removePreference(mQuickFixes); } if (!VoiceProxy.VOICE_INSTALLED diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index 632195533..160b677e1 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -52,6 +52,8 @@ public class SubtypeSwitcher { private static final String VOICE_MODE = "voice"; private static final String SUBTYPE_EXTRAVALUE_REQUIRE_NETWORK_CONNECTIVITY = "requireNetworkConnectivity"; + public static final String USE_SPACEBAR_LANGUAGE_SWITCH_KEY = "use_spacebar_language_switch"; + private final TextUtils.SimpleStringSplitter mLocaleSplitter = new TextUtils.SimpleStringSplitter(LOCALE_SEPARATER); @@ -61,6 +63,7 @@ public class SubtypeSwitcher { private /* final */ Resources mResources; private /* final */ ConnectivityManager mConnectivityManager; private /* final */ boolean mConfigUseSpacebarLanguageSwitcher; + private /* final */ SharedPreferences mPrefs; private final ArrayList<InputMethodSubtypeCompatWrapper> mEnabledKeyboardSubtypesOfCurrentInputMethod = new ArrayList<InputMethodSubtypeCompatWrapper>(); @@ -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(); } 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; |