diff options
Diffstat (limited to 'java')
23 files changed, 396 insertions, 290 deletions
diff --git a/java/res/values-sw600dp/config.xml b/java/res/values-sw600dp/config.xml index 1dd93121d..35da3009f 100644 --- a/java/res/values-sw600dp/config.xml +++ b/java/res/values-sw600dp/config.xml @@ -24,14 +24,11 @@ <bool name="config_enable_show_voice_key_option">false</bool> <bool name="config_enable_show_popup_on_keypress_option">false</bool> <bool name="config_enable_bigram_suggestions_option">false</bool> - <bool name="config_sliding_key_input_enabled">false</bool> <bool name="config_digit_more_keys_enabled">false</bool> <!-- Whether or not Popup on key press is enabled by default --> <bool name="config_default_popup_preview">false</bool> <bool name="config_default_sound_enabled">true</bool> <bool name="config_auto_correction_spacebar_led_enabled">false</bool> - <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false --> - <bool name="config_show_mini_keyboard_at_touched_point">true</bool> <!-- The language is never displayed if == 0, always displayed if < 0 --> <integer name="config_delay_before_fadeout_language_on_spacebar">1200</integer> <!-- Long pressing space will invoke IME switcher if > 0, never invoke IME switcher if == 0 --> @@ -39,4 +36,10 @@ <!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. --> <string name="config_default_keyboard_theme_id" translatable="false">5</string> <integer name="config_max_more_keys_column">5</integer> + <!-- + Configuration for LatinKeyboardView + --> + <bool name="config_sliding_key_input_enabled">false</bool> + <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false --> + <bool name="config_show_mini_keyboard_at_touched_point">true</bool> </resources> diff --git a/java/res/values-sw768dp/config.xml b/java/res/values-sw768dp/config.xml index 06553a7c9..ddeadaf0f 100644 --- a/java/res/values-sw768dp/config.xml +++ b/java/res/values-sw768dp/config.xml @@ -24,19 +24,22 @@ <bool name="config_enable_show_voice_key_option">false</bool> <bool name="config_enable_show_popup_on_keypress_option">false</bool> <bool name="config_enable_bigram_suggestions_option">false</bool> - <bool name="config_sliding_key_input_enabled">false</bool> <bool name="config_digit_more_keys_enabled">false</bool> <!-- Whether or not Popup on key press is enabled by default --> <bool name="config_default_popup_preview">false</bool> <bool name="config_default_sound_enabled">true</bool> <bool name="config_auto_correction_spacebar_led_enabled">false</bool> - <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false --> - <bool name="config_show_mini_keyboard_at_touched_point">true</bool> <!-- Long pressing space will invoke IME switcher if > 0, never invoke IME switcher if == 0 --> <integer name="config_long_press_space_key_timeout">0</integer> <!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. --> <string name="config_default_keyboard_theme_id" translatable="false">5</string> <integer name="config_max_more_keys_column">5</integer> + <!-- + Configuration for LatinKeyboardView + --> + <bool name="config_sliding_key_input_enabled">false</bool> + <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false --> + <bool name="config_show_mini_keyboard_at_touched_point">true</bool> <!-- Screen metrics for logging. 0 = "mdpi phone screen" 1 = "hdpi phone screen" diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml index 70fc7f86e..b3bd0fe59 100644 --- a/java/res/values/attrs.xml +++ b/java/res/values/attrs.xml @@ -103,6 +103,8 @@ <attr name="keyPreviewHeight" format="dimension" /> <!-- Size of the text for key press feedback popup, int the proportion of key height --> <attr name="keyPreviewTextRatio" format="float" /> + <!-- Delay after key releasing and key press feedback dismissing in millisecond --> + <attr name="keyPreviewLingerTimeout" format="integer" /> <!-- Amount to offset the touch Y coordinate by, for bias correction. --> <attr name="verticalCorrection" format="dimension" /> @@ -130,6 +132,28 @@ <attr name="spacebarTextRatio" format="fraction" /> <attr name="spacebarTextColor" format="color" /> <attr name="spacebarTextShadowColor" format="color" /> + <!-- Key detection hysteresis distance. --> + <attr name="keyHysteresisDistance" format="dimension" /> + <!-- Touch noise threshold time in millisecond --> + <attr name="touchNoiseThresholdTime" format="integer" /> + <!-- Touch noise threshold distance in millimeter --> + <attr name="touchNoiseThresholdDistance" format="dimension" /> + <!-- Sliding key input enable --> + <attr name="slidingKeyInputEnable" format="boolean" /> + <!-- Key repeat start timeout --> + <attr name="keyRepeatStartTimeout" format="integer" /> + <!-- Key repeat interval in millisecond. --> + <attr name="keyRepeatInterval" format="integer" /> + <!-- Long press timeout of letter key in millisecond. --> + <attr name="longPressKeyTimeout" format="integer" /> + <!-- Long press timeout of shift key in millisecond. --> + <attr name="longPressShiftKeyTimeout" format="integer" /> + <!-- Long press timeout of space key in millisecond. --> + <attr name="longPressSpaceKeyTimeout" format="integer" /> + <!-- Ignore special key timeout while typing in millisecond. --> + <attr name="ignoreSpecialKeyTimeout" format="integer" /> + <!-- Mini-keyboard will shown at touched point. --> + <attr name="showMiniKeyboardAtTouchedPoint" format="boolean" /> </declare-styleable> <declare-styleable name="SuggestionsView"> diff --git a/java/res/values/config.xml b/java/res/values/config.xml index 5e6804364..32041df74 100644 --- a/java/res/values/config.xml +++ b/java/res/values/config.xml @@ -27,7 +27,6 @@ <bool name="config_enable_bigram_suggestions_option">true</bool> <!-- TODO: Disable the following configuration for production. --> <bool name="config_enable_usability_study_mode_option">true</bool> - <bool name="config_sliding_key_input_enabled">true</bool> <bool name="config_digit_more_keys_enabled">true</bool> <!-- Whether or not Popup on key press is enabled by default --> <bool name="config_default_popup_preview">true</bool> @@ -39,8 +38,6 @@ <bool name="config_default_bigram_prediction">false</bool> <bool name="config_default_sound_enabled">false</bool> <bool name="config_default_vibration_enabled">true</bool> - <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false --> - <bool name="config_show_mini_keyboard_at_touched_point">false</bool> <!-- The language is never displayed if == 0, always displayed if < 0 --> <integer name="config_delay_before_fadeout_language_on_spacebar">1200</integer> <integer name="config_delay_update_suggestions">100</integer> @@ -48,26 +45,38 @@ <integer name="config_delay_update_shift_state">100</integer> <integer name="config_duration_of_fadeout_language_on_spacebar">50</integer> <integer name="config_final_fadeout_percentage_of_language_on_spacebar">50</integer> - <integer name="config_delay_before_preview">0</integer> - <integer name="config_delay_after_preview">70</integer> <integer name="config_mini_keyboard_fadein_anim_time">0</integer> <integer name="config_mini_keyboard_fadeout_anim_time">100</integer> - <integer name="config_delay_before_key_repeat_start">400</integer> - <integer name="config_key_repeat_interval">50</integer> <integer name="config_keyboard_grid_width">32</integer> <integer name="config_keyboard_grid_height">16</integer> + <integer name="config_double_spaces_turn_into_period_timeout">1100</integer> + <!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. --> + <string name="config_default_keyboard_theme_id" translatable="false">5</string> + <integer name="config_max_more_keys_column">5</integer> + <!-- + Configuration for KeyboardView + --> + <integer name="config_key_preview_linger_timeout">70</integer> + <!-- + Configuration for LatinKeyboardView + --> + <dimen name="config_key_hysteresis_distance">0.05in</dimen> + <integer name="config_touch_noise_threshold_time">40</integer> + <dimen name="config_touch_noise_threshold_distance">2.0mm</dimen> + <bool name="config_sliding_key_input_enabled">true</bool> + <integer name="config_key_repeat_start_timeout">400</integer> + <integer name="config_key_repeat_interval">50</integer> <integer name="config_long_press_key_timeout">400</integer> <!-- Long pressing shift will invoke caps-lock if > 0, never invoke caps-lock if == 0 --> <integer name="config_long_press_shift_key_timeout">1200</integer> <!-- Long pressing space will invoke IME switcher if > 0, never invoke IME switcher if == 0 --> <integer name="config_long_press_space_key_timeout">@integer/config_long_press_key_timeout</integer> - <integer name="config_touch_noise_threshold_millis">40</integer> - <integer name="config_double_spaces_turn_into_period_timeout">1100</integer> <integer name="config_ignore_special_key_timeout">700</integer> - <dimen name="config_touch_noise_threshold_distance">2.0mm</dimen> - <!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. --> - <string name="config_default_keyboard_theme_id" translatable="false">5</string> - <integer name="config_max_more_keys_column">5</integer> + <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false --> + <bool name="config_show_mini_keyboard_at_touched_point">false</bool> + <!-- + Configuration for auto correction + --> <string-array name="auto_correction_threshold_values" translatable="false"> <!-- Off, When auto correction setting is Off, this value is not used. --> <item></item> diff --git a/java/res/values/dimens.xml b/java/res/values/dimens.xml index e46ff7718..95c4e5b8b 100644 --- a/java/res/values/dimens.xml +++ b/java/res/values/dimens.xml @@ -96,6 +96,4 @@ <dimen name="more_suggestions_hint_text_size">27dip</dimen> <integer name="suggestions_count_in_strip">3</integer> <integer name="center_suggestion_percentile">36</integer> - - <dimen name="key_hysteresis_distance">0.05in</dimen> </resources> diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml index c4e39e357..69637d75a 100644 --- a/java/res/values/styles.xml +++ b/java/res/values/styles.xml @@ -59,11 +59,24 @@ <item name="keyPreviewOffset">@dimen/key_preview_offset</item> <item name="keyPreviewHeight">@dimen/key_preview_height</item> <item name="keyPreviewTextRatio">@fraction/key_preview_text_ratio</item> + <item name="keyPreviewLingerTimeout">@integer/config_key_preview_linger_timeout</item> <item name="moreKeysLayout">@layout/mini_keyboard</item> <item name="verticalCorrection">@dimen/keyboard_vertical_correction</item> <item name="shadowColor">#BB000000</item> <item name="shadowRadius">2.75</item> <item name="backgroundDimAmount">0.5</item> + <!-- Common attributes of LatinKeyboardView --> + <item name="keyHysteresisDistance">@dimen/config_key_hysteresis_distance</item> + <item name="touchNoiseThresholdTime">@integer/config_touch_noise_threshold_time</item> + <item name="touchNoiseThresholdDistance">@dimen/config_touch_noise_threshold_distance</item> + <item name="slidingKeyInputEnable">@bool/config_sliding_key_input_enabled</item> + <item name="keyRepeatStartTimeout">@integer/config_key_repeat_start_timeout</item> + <item name="keyRepeatInterval">@integer/config_key_repeat_interval</item> + <item name="longPressKeyTimeout">@integer/config_long_press_key_timeout</item> + <item name="longPressShiftKeyTimeout">@integer/config_long_press_shift_key_timeout</item> + <item name="longPressSpaceKeyTimeout">@integer/config_long_press_space_key_timeout</item> + <item name="ignoreSpecialKeyTimeout">@integer/config_ignore_special_key_timeout</item> + <item name="showMiniKeyboardAtTouchedPoint">@bool/config_show_mini_keyboard_at_touched_point</item> </style> <style name="LatinKeyboardView" diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java index cacb8a324..ae5e4e860 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSet.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java @@ -244,9 +244,10 @@ public class KeyboardSet { // TODO: Use InputMethodSubtype object as argument. public Builder setSubtype(Locale inputLocale, boolean asciiCapable, boolean touchPositionCorrectionEnabled) { + final boolean deprecatedForceAscii = Utils.inPrivateImeOptions( + mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, mEditorInfo); final boolean forceAscii = EditorInfoCompatUtils.hasFlagForceAscii(mParams.mImeOptions) - || Utils.inPrivateImeOptions( - mPackageName, LatinIME.IME_OPTION_FORCE_ASCII, mEditorInfo); + || deprecatedForceAscii; mParams.mLocale = (forceAscii && !asciiCapable) ? Locale.US : inputLocale; mParams.mTouchPositionCorrectionEnabled = touchPositionCorrectionEnabled; return this; @@ -256,10 +257,11 @@ public class KeyboardSet { boolean voiceKeyOnMain) { mParams.mSettingsKeyEnabled = settingsKeyEnabled; @SuppressWarnings("deprecation") + final boolean deprecatedNoMicrophone = Utils.inPrivateImeOptions( + null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, mEditorInfo); final boolean noMicrophone = Utils.inPrivateImeOptions( mPackageName, LatinIME.IME_OPTION_NO_MICROPHONE, mEditorInfo) - || Utils.inPrivateImeOptions( - null, LatinIME.IME_OPTION_NO_MICROPHONE_COMPAT, mEditorInfo); + || deprecatedNoMicrophone; mParams.mVoiceKeyEnabled = voiceKeyEnabled && !noMicrophone; mParams.mVoiceKeyOnMain = voiceKeyOnMain; return this; diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index 1398bae2a..5a59cc1c7 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -240,6 +240,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, private static final int ALPHABET_MANUAL_SHIFTED = 1; private static final int ALPHABET_AUTOMATIC_SHIFTED = 2; private static final int ALPHABET_SHIFT_LOCKED = 3; + private static final int ALPHABET_SHIFT_LOCK_SHIFTED = 4; // TODO: Remove this method. private void updateAlphabetKeyboardShiftState(int shiftMode) { @@ -260,6 +261,10 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, case ALPHABET_SHIFT_LOCKED: keyboard.setShiftLocked(true); break; + case ALPHABET_SHIFT_LOCK_SHIFTED: + keyboard.setShiftLocked(true); + keyboard.setShifted(true); + break; } mKeyboardView.invalidateAllKeys(); if (shiftMode != ALPHABET_SHIFT_LOCKED) { @@ -300,6 +305,13 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions, // Implements {@link KeyboardState.SwitchActions}. @Override + public void setAlphabetShiftLockShiftedKeyboard() { + setKeyboard(mKeyboardSet.getMainKeyboard()); + updateAlphabetKeyboardShiftState(ALPHABET_SHIFT_LOCK_SHIFTED); + } + + // Implements {@link KeyboardState.SwitchActions}. + @Override public void setSymbolsKeyboard() { setKeyboard(mKeyboardSet.getSymbolsKeyboard()); } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index afcf51059..6f4ef2580 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -17,7 +17,6 @@ package com.android.inputmethod.keyboard; import android.content.Context; -import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -39,7 +38,6 @@ import android.widget.RelativeLayout; import android.widget.TextView; import com.android.inputmethod.compat.FrameLayoutCompatUtils; -import com.android.inputmethod.keyboard.internal.KeyboardIconsSet; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.StaticInnerHandlerWrapper; @@ -103,7 +101,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { private final int mKeyPreviewLayoutId; protected final KeyPreviewDrawParams mKeyPreviewDrawParams; private boolean mShowKeyPreviewPopup = true; - private final int mDelayBeforePreview; private int mDelayAfterPreview; private ViewGroup mPreviewPlacer; @@ -135,8 +132,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { private final DrawingHandler mDrawingHandler = new DrawingHandler(this); public static class DrawingHandler extends StaticInnerHandlerWrapper<KeyboardView> { - private static final int MSG_SHOW_KEY_PREVIEW = 1; - private static final int MSG_DISMISS_KEY_PREVIEW = 2; + private static final int MSG_DISMISS_KEY_PREVIEW = 1; public DrawingHandler(KeyboardView outerInstance) { super(outerInstance); @@ -148,35 +144,12 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { if (keyboardView == null) return; final PointerTracker tracker = (PointerTracker) msg.obj; switch (msg.what) { - case MSG_SHOW_KEY_PREVIEW: - keyboardView.showKey(tracker); - break; case MSG_DISMISS_KEY_PREVIEW: tracker.getKeyPreviewText().setVisibility(View.INVISIBLE); break; } } - public void showKeyPreview(long delay, PointerTracker tracker) { - removeMessages(MSG_SHOW_KEY_PREVIEW); - final KeyboardView keyboardView = getOuterInstance(); - if (keyboardView == null) return; - if (tracker.getKeyPreviewText().getVisibility() == VISIBLE || delay == 0) { - // Show right away, if it's already visible and finger is moving around - keyboardView.showKey(tracker); - } else { - sendMessageDelayed(obtainMessage(MSG_SHOW_KEY_PREVIEW, tracker), delay); - } - } - - public void cancelShowKeyPreview(PointerTracker tracker) { - removeMessages(MSG_SHOW_KEY_PREVIEW, tracker); - } - - public void cancelAllShowKeyPreviews() { - removeMessages(MSG_SHOW_KEY_PREVIEW); - } - public void dismissKeyPreview(long delay, PointerTracker tracker) { sendMessageDelayed(obtainMessage(MSG_DISMISS_KEY_PREVIEW, tracker), delay); } @@ -190,7 +163,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { } public void cancelAllMessages() { - cancelAllShowKeyPreviews(); cancelAllDismissKeyPreviews(); } } @@ -295,6 +267,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { public final int mPreviewOffset; public final int mPreviewHeight; public final Typeface mKeyTextStyle; + public final int mLingerTimeout; private final float mPreviewTextRatio; private final float mKeyLetterRatio; @@ -324,6 +297,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { R.styleable.KeyboardView_keyPreviewHeight, 80); mPreviewTextRatio = getRatio(a, R.styleable.KeyboardView_keyPreviewTextRatio); mPreviewTextColor = a.getColor(R.styleable.KeyboardView_keyPreviewTextColor, 0); + mLingerTimeout = a.getInt(R.styleable.KeyboardView_keyPreviewLingerTimeout, 0); mKeyLetterRatio = keyDrawParams.mKeyLetterRatio; mKeyTextStyle = keyDrawParams.mKeyTextStyle; @@ -363,10 +337,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { mBackgroundDimAmount = a.getFloat(R.styleable.KeyboardView_backgroundDimAmount, 0.5f); a.recycle(); - final Resources res = getResources(); - - mDelayBeforePreview = res.getInteger(R.integer.config_delay_before_preview); - mDelayAfterPreview = res.getInteger(R.integer.config_delay_after_preview); + mDelayAfterPreview = mKeyPreviewDrawParams.mLingerTimeout; mPaint.setAntiAlias(true); mPaint.setTextAlign(Align.CENTER); @@ -386,8 +357,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { * @param keyboard the keyboard to display in this view */ public void setKeyboard(Keyboard keyboard) { - // Remove any pending dismissing preview - mDrawingHandler.cancelAllShowKeyPreviews(); + // Remove any pending messages. + mDrawingHandler.cancelAllMessages(); if (mKeyboard != null) { PointerTracker.dismissAllKeyPreviews(); } @@ -841,18 +812,12 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { @Override public void showKeyPreview(PointerTracker tracker) { if (mShowKeyPreviewPopup) { - mDrawingHandler.showKeyPreview(mDelayBeforePreview, tracker); + showKey(tracker); } } @Override - public void cancelShowKeyPreview(PointerTracker tracker) { - mDrawingHandler.cancelShowKeyPreview(tracker); - } - - @Override public void dismissKeyPreview(PointerTracker tracker) { - mDrawingHandler.cancelShowKeyPreview(tracker); mDrawingHandler.dismissKeyPreview(mDelayAfterPreview, tracker); } diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index f5b282df3..aee356a0c 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -18,7 +18,6 @@ package com.android.inputmethod.keyboard; import android.content.Context; import android.content.pm.PackageManager; -import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; @@ -103,6 +102,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke new WeakHashMap<Key, MoreKeysPanel>(); private final boolean mConfigShowMiniKeyboardAtTouchedPoint; + private final PointerTrackerParams mPointerTrackerParams; private final boolean mIsSpacebarTriggeringPopupByLongPress; private final SuddenJumpingTouchEventHandler mTouchScreenRegulator; @@ -114,7 +114,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke // To detect double tap. protected GestureDetector mGestureDetector; - private final KeyTimerHandler mKeyTimerHandler = new KeyTimerHandler(this); + private final KeyTimerHandler mKeyTimerHandler; private static class KeyTimerHandler extends StaticInnerHandlerWrapper<LatinKeyboardView> implements TimerProxy { @@ -126,11 +126,9 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke private final int mKeyRepeatInterval; private boolean mInKeyRepeat; - public KeyTimerHandler(LatinKeyboardView outerInstance) { + public KeyTimerHandler(LatinKeyboardView outerInstance, int keyRepeatInterval) { super(outerInstance); - // TODO: This should be the attribute of LatinKeyboardView. - final Resources res = outerInstance.getContext().getResources(); - mKeyRepeatInterval = res.getInteger(R.integer.config_key_repeat_interval); + mKeyRepeatInterval = keyRepeatInterval; } @Override @@ -253,6 +251,49 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke } } + public static class PointerTrackerParams { + public final boolean mSlidingKeyInputEnabled; + public final int mKeyRepeatStartTimeout; + public final int mLongPressKeyTimeout; + public final int mLongPressShiftKeyTimeout; + public final int mLongPressSpaceKeyTimeout; + public final int mIgnoreSpecialKeyTimeout; + public final int mTouchNoiseThresholdTime; + public final float mTouchNoiseThresholdDistance; + + public static final PointerTrackerParams DEFAULT = new PointerTrackerParams(); + + private PointerTrackerParams() { + mSlidingKeyInputEnabled = false; + mKeyRepeatStartTimeout = 0; + mLongPressKeyTimeout = 0; + mLongPressShiftKeyTimeout = 0; + mLongPressSpaceKeyTimeout = 0; + mIgnoreSpecialKeyTimeout = 0; + mTouchNoiseThresholdTime =0; + mTouchNoiseThresholdDistance = 0; + } + + public PointerTrackerParams(TypedArray latinKeyboardViewAttr) { + mSlidingKeyInputEnabled = latinKeyboardViewAttr.getBoolean( + R.styleable.LatinKeyboardView_slidingKeyInputEnable, false); + mKeyRepeatStartTimeout = latinKeyboardViewAttr.getInt( + R.styleable.LatinKeyboardView_keyRepeatStartTimeout, 0); + mLongPressKeyTimeout = latinKeyboardViewAttr.getInt( + R.styleable.LatinKeyboardView_longPressKeyTimeout, 0); + mLongPressShiftKeyTimeout = latinKeyboardViewAttr.getInt( + R.styleable.LatinKeyboardView_longPressShiftKeyTimeout, 0); + mLongPressSpaceKeyTimeout = latinKeyboardViewAttr.getInt( + R.styleable.LatinKeyboardView_longPressSpaceKeyTimeout, 0); + mIgnoreSpecialKeyTimeout = latinKeyboardViewAttr.getInt( + R.styleable.LatinKeyboardView_ignoreSpecialKeyTimeout, 0); + mTouchNoiseThresholdTime = latinKeyboardViewAttr.getInt( + R.styleable.LatinKeyboardView_touchNoiseThresholdTime, 0); + mTouchNoiseThresholdDistance = latinKeyboardViewAttr.getDimension( + R.styleable.LatinKeyboardView_touchNoiseThresholdDistance, 0); + } + } + public LatinKeyboardView(Context context, AttributeSet attrs) { this(context, attrs, R.attr.latinKeyboardViewStyle); } @@ -262,14 +303,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke mTouchScreenRegulator = new SuddenJumpingTouchEventHandler(getContext(), this); - final Resources res = getResources(); - // TODO: This should be the attribute of LatinKeyboardView. - mConfigShowMiniKeyboardAtTouchedPoint = res.getBoolean( - R.bool.config_show_mini_keyboard_at_touched_point); - // TODO: This should be the attribute of LatinKeyboardView. - final float keyHysteresisDistance = res.getDimension(R.dimen.key_hysteresis_distance); - mKeyDetector = new KeyDetector(keyHysteresisDistance); - final boolean ignoreMultitouch = true; mGestureDetector = new GestureDetector( getContext(), new DoubleTapListener(), null, ignoreMultitouch); @@ -280,11 +313,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke PointerTracker.init(mHasDistinctMultitouch, getContext()); - // TODO: This should be the attribute of LatinKeyboardView. - final int longPressSpaceKeyTimeout = - res.getInteger(R.integer.config_long_press_space_key_timeout); - mIsSpacebarTriggeringPopupByLongPress = (longPressSpaceKeyTimeout > 0); - final TypedArray a = context.obtainStyledAttributes( attrs, R.styleable.LatinKeyboardView, defStyle, R.style.LatinKeyboardView); mAutoCorrectionSpacebarLedEnabled = a.getBoolean( @@ -296,7 +324,22 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke mSpacebarTextColor = a.getColor(R.styleable.LatinKeyboardView_spacebarTextColor, 0); mSpacebarTextShadowColor = a.getColor( R.styleable.LatinKeyboardView_spacebarTextShadowColor, 0); + + mPointerTrackerParams = new PointerTrackerParams(a); + mIsSpacebarTriggeringPopupByLongPress = ( + mPointerTrackerParams.mLongPressSpaceKeyTimeout > 0); + + final float keyHysteresisDistance = a.getDimension( + R.styleable.LatinKeyboardView_keyHysteresisDistance, 0); + mKeyDetector = new KeyDetector(keyHysteresisDistance); + final int keyRepeatInterval = a.getInt( + R.styleable.LatinKeyboardView_keyRepeatInterval, 0); + mKeyTimerHandler = new KeyTimerHandler(this, keyRepeatInterval); + mConfigShowMiniKeyboardAtTouchedPoint = a.getBoolean( + R.styleable.LatinKeyboardView_showMiniKeyboardAtTouchedPoint, false); a.recycle(); + + PointerTracker.setParameters(mPointerTrackerParams); } public void startIgnoringDoubleTap() { diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 274bd0b31..a75b8f9e6 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -17,7 +17,6 @@ package com.android.inputmethod.keyboard; import android.content.Context; -import android.content.res.Resources; import android.os.SystemClock; import android.util.Log; import android.view.MotionEvent; @@ -25,7 +24,6 @@ import android.widget.TextView; import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.latin.LatinImeLogger; -import com.android.inputmethod.latin.R; import java.util.ArrayList; import java.util.List; @@ -69,7 +67,6 @@ public class PointerTracker { public void invalidateKey(Key key); public TextView inflateKeyPreviewText(); public void showKeyPreview(PointerTracker tracker); - public void cancelShowKeyPreview(PointerTracker tracker); public void dismissKeyPreview(PointerTracker tracker); } @@ -98,14 +95,8 @@ public class PointerTracker { } private static KeyboardSwitcher sKeyboardSwitcher; - private static boolean sConfigSlidingKeyInputEnabled; - // Timing constants - private static int sDelayBeforeKeyRepeatStart; - private static int sLongPressKeyTimeout; - private static int sLongPressShiftKeyTimeout; - private static int sLongPressSpaceKeyTimeout; - private static int sIgnoreSpecialKeyTimeout; - private static int sTouchNoiseThresholdMillis; + // Parameters for pointer handling. + private static LatinKeyboardView.PointerTrackerParams sParams; private static int sTouchNoiseThresholdDistanceSquared; private static final List<PointerTracker> sTrackers = new ArrayList<PointerTracker>(); @@ -169,20 +160,14 @@ public class PointerTracker { sPointerTrackerQueue = null; } - final Resources res = context.getResources(); - sConfigSlidingKeyInputEnabled = res.getBoolean(R.bool.config_sliding_key_input_enabled); - sDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start); - sLongPressKeyTimeout = res.getInteger(R.integer.config_long_press_key_timeout); - sLongPressShiftKeyTimeout = res.getInteger(R.integer.config_long_press_shift_key_timeout); - sLongPressSpaceKeyTimeout = res.getInteger(R.integer.config_long_press_space_key_timeout); - sIgnoreSpecialKeyTimeout = res.getInteger(R.integer.config_ignore_special_key_timeout); - sTouchNoiseThresholdMillis = res.getInteger(R.integer.config_touch_noise_threshold_millis); + setParameters(LatinKeyboardView.PointerTrackerParams.DEFAULT); + sKeyboardSwitcher = KeyboardSwitcher.getInstance(); + } - final float touchNoiseThresholdDistance = res.getDimension( - R.dimen.config_touch_noise_threshold_distance); + public static void setParameters(LatinKeyboardView.PointerTrackerParams params) { + sParams = params; sTouchNoiseThresholdDistanceSquared = (int)( - touchNoiseThresholdDistance * touchNoiseThresholdDistance); - sKeyboardSwitcher = KeyboardSwitcher.getInstance(); + params.mTouchNoiseThresholdDistance * params.mTouchNoiseThresholdDistance); } public static PointerTracker getPointerTracker(final int id, KeyEventHandler handler) { @@ -278,7 +263,7 @@ public class PointerTracker { mListener.onCodeInput(code, keyCodes, x, y); } if (!key.altCodeWhileTyping() && !key.isModifier()) { - mTimerProxy.startKeyTypedTimer(sIgnoreSpecialKeyTimeout); + mTimerProxy.startKeyTypedTimer(sParams.mIgnoreSpecialKeyTimeout); } } } @@ -453,7 +438,7 @@ public class PointerTracker { setKeyDetectorInner(handler.getKeyDetector()); // Naive up-to-down noise filter. final long deltaT = eventTime - mUpTime; - if (deltaT < sTouchNoiseThresholdMillis) { + if (deltaT < sParams.mTouchNoiseThresholdTime) { final int dx = x - mLastX; final int dy = y - mLastY; final int distanceSquared = (dx * dx + dy * dy); @@ -483,7 +468,7 @@ public class PointerTracker { Key key = onDownKey(x, y, eventTime); // Sliding key is allowed when 1) enabled by configuration, 2) this pointer starts sliding // from modifier key, or 3) this pointer's KeyDetector always allows sliding input. - mIsAllowedSlidingKeyInput = sConfigSlidingKeyInputEnabled + mIsAllowedSlidingKeyInput = sParams.mSlidingKeyInputEnabled || (key != null && key.isModifier()) || mKeyDetector.alwaysAllowsSlidingInput(); mKeyboardLayoutHasBeenChanged = false; @@ -620,7 +605,6 @@ public class PointerTracker { private void onUpEventInternal(int x, int y, long eventTime) { mTimerProxy.cancelKeyTimers(); - mDrawingProxy.cancelShowKeyPreview(this); mIsInSlidingKeyInput = false; final int keyX, keyY; if (isMajorEnoughMoveToBeOnNewKey(x, y, onMoveKey(x, y))) { @@ -673,7 +657,6 @@ public class PointerTracker { private void onCancelEventInternal() { mTimerProxy.cancelKeyTimers(); - mDrawingProxy.cancelShowKeyPreview(this); setReleasedKeyGraphics(mCurrentKey); mIsInSlidingKeyInput = false; if (mIsShowingMoreKeysPanel) { @@ -685,7 +668,7 @@ public class PointerTracker { private void startRepeatKey(Key key) { if (key != null && key.isRepeatable()) { onRepeatKey(key); - mTimerProxy.startKeyRepeatTimer(sDelayBeforeKeyRepeatStart, this); + mTimerProxy.startKeyRepeatTimer(sParams.mKeyRepeatStartTimeout, this); mIsRepeatableKey = true; } else { mIsRepeatableKey = false; @@ -715,12 +698,12 @@ public class PointerTracker { private void startLongPressTimer(Key key) { if (key == null) return; if (key.mCode == Keyboard.CODE_SHIFT) { - if (sLongPressShiftKeyTimeout > 0) { - mTimerProxy.startLongPressTimer(sLongPressShiftKeyTimeout, this); + if (sParams.mLongPressShiftKeyTimeout > 0) { + mTimerProxy.startLongPressTimer(sParams.mLongPressShiftKeyTimeout, this); } } else if (key.mCode == Keyboard.CODE_SPACE) { - if (sLongPressSpaceKeyTimeout > 0) { - mTimerProxy.startLongPressTimer(sLongPressSpaceKeyTimeout, this); + if (sParams.mLongPressSpaceKeyTimeout > 0) { + mTimerProxy.startLongPressTimer(sParams.mLongPressSpaceKeyTimeout, this); } } else if (key.hasUppercaseLetter() && mKeyboard.isManualTemporaryUpperCase()) { // We need not start long press timer on the key which has manual temporary upper case @@ -728,9 +711,9 @@ public class PointerTracker { return; } else if (sKeyboardSwitcher.isInMomentarySwitchState()) { // We use longer timeout for sliding finger input started from the symbols mode key. - mTimerProxy.startLongPressTimer(sLongPressKeyTimeout * 3, this); + mTimerProxy.startLongPressTimer(sParams.mLongPressKeyTimeout * 3, this); } else { - mTimerProxy.startLongPressTimer(sLongPressKeyTimeout, this); + mTimerProxy.startLongPressTimer(sParams.mLongPressKeyTimeout, this); } } diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java index 38c31adce..a89356c50 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java @@ -43,8 +43,7 @@ public class KeyboardState { public void setAlphabetManualShiftedKeyboard(); public void setAlphabetAutomaticShiftedKeyboard(); public void setAlphabetShiftLockedKeyboard(); - // TODO: Add this. - //public void setAlphabetShiftLockShiftedKeyboard(); + public void setAlphabetShiftLockShiftedKeyboard(); public void setSymbolsKeyboard(); public void setSymbolsShiftedKeyboard(); @@ -157,14 +156,10 @@ public class KeyboardState { } } - // TODO: Remove this method. - public boolean isShiftLocked() { - return mAlphabetShiftState.isShiftLocked(); - } - private static final int UNSHIFT = 0; private static final int MANUAL_SHIFT = 1; private static final int AUTOMATIC_SHIFT = 2; + private static final int SHIFT_LOCK_SHIFTED = 3; private void setShifted(int shiftMode) { if (DEBUG_ACTION) { @@ -198,6 +193,10 @@ public class KeyboardState { mSwitchActions.setAlphabetKeyboard(); } break; + case SHIFT_LOCK_SHIFTED: + mAlphabetShiftState.setShifted(true); + mSwitchActions.setAlphabetShiftLockShiftedKeyboard(); + break; } } @@ -349,7 +348,7 @@ public class KeyboardState { if (mAlphabetShiftState.isShiftLocked()) { // Shift key is pressed while caps lock state, we will treat this state as shifted // caps lock state and mark as if shift key pressed while normal state. - setShifted(MANUAL_SHIFT); + setShifted(SHIFT_LOCK_SHIFTED); mShiftKeyState.onPress(); } else if (mAlphabetShiftState.isAutomaticTemporaryUpperCase()) { // Shift key is pressed while automatic temporary upper case, we have to move to diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 3692ac179..b82400046 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -162,7 +162,7 @@ public class BinaryDictionary extends Dictionary { } if (len > 0) { callback.addWord(mOutputChars_bigrams, start, len, mBigramScores[j], - mDicTypeId, DataType.BIGRAM); + mDicTypeId, Dictionary.BIGRAM); } } } @@ -182,7 +182,7 @@ public class BinaryDictionary extends Dictionary { } if (len > 0) { callback.addWord(mOutputChars, start, len, mScores[j], mDicTypeId, - DataType.UNIGRAM); + Dictionary.UNIGRAM); } } } diff --git a/java/src/com/android/inputmethod/latin/Dictionary.java b/java/src/com/android/inputmethod/latin/Dictionary.java index c35b42877..79bf33850 100644 --- a/java/src/com/android/inputmethod/latin/Dictionary.java +++ b/java/src/com/android/inputmethod/latin/Dictionary.java @@ -33,9 +33,8 @@ public abstract class Dictionary { */ protected static final int FULL_WORD_SCORE_MULTIPLIER = 2; - public static enum DataType { - UNIGRAM, BIGRAM - } + public static final int UNIGRAM = 0; + public static final int BIGRAM = 1; /** * Interface to be implemented by classes requesting words to be fetched from the dictionary. @@ -51,11 +50,11 @@ public abstract class Dictionary { * @param score the score of occurrence. This is normalized between 1 and 255, but * can exceed those limits * @param dicTypeId of the dictionary where word was from - * @param dataType tells type of this data + * @param dataType tells type of this data, either UNIGRAM or BIGRAM * @return true if the word was added, false if no more words are required */ boolean addWord(char[] word, int wordOffset, int wordLength, int score, int dicTypeId, - DataType dataType); + int dataType); } /** @@ -64,7 +63,7 @@ public abstract class Dictionary { * @param composer the key sequence to match * @param callback the callback object to send matched words to as possible candidates * @param proximityInfo the object for key proximity. May be ignored by some implementations. - * @see WordCallback#addWord(char[], int, int, int, int, DataType) + * @see WordCallback#addWord(char[], int, int, int, int, int) */ abstract public void getWords(final WordComposer composer, final WordCallback callback, final ProximityInfo proximityInfo); diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java index 7eec8e2ca..8e8adc1c2 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java @@ -301,7 +301,7 @@ public class ExpandableDictionary extends Dictionary { finalFreq = computeSkippedWordFinalFreq(freq, snr, mInputLength); } if (!callback.addWord(word, 0, depth + 1, finalFreq, mDicTypeId, - DataType.UNIGRAM)) { + Dictionary.UNIGRAM)) { return; } } @@ -342,7 +342,7 @@ public class ExpandableDictionary extends Dictionary { snr * addedAttenuation, mInputLength); } callback.addWord(word, 0, depth + 1, finalFreq, mDicTypeId, - DataType.UNIGRAM); + Dictionary.UNIGRAM); } } if (children != null) { @@ -506,7 +506,7 @@ public class ExpandableDictionary extends Dictionary { } while (node != null); callback.addWord(mLookedUpString, index, MAX_WORD_LENGTH - index, freq, mDicTypeId, - DataType.BIGRAM); + Dictionary.BIGRAM); } } diff --git a/java/src/com/android/inputmethod/latin/LastComposedWord.java b/java/src/com/android/inputmethod/latin/LastComposedWord.java new file mode 100644 index 000000000..0c8c88f50 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/LastComposedWord.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.android.inputmethod.latin; + +import android.text.TextUtils; + +import java.util.ArrayList; + +/** + * This class encapsulates data about a word previously composed, but that has been + * committed already. This is used for resuming suggestion, and cancel auto-correction. + */ +public class LastComposedWord { + // COMMIT_TYPE_USER_TYPED_WORD is used when the word committed is the exact typed word, with + // no hinting from the IME. It happens when some external event happens (rotating the device, + // for example) or when auto-correction is off by settings or editor attributes. + public static final int COMMIT_TYPE_USER_TYPED_WORD = 0; + // COMMIT_TYPE_MANUAL_PICK is used when the user pressed a field in the suggestion strip. + public static final int COMMIT_TYPE_MANUAL_PICK = 1; + // COMMIT_TYPE_DECIDED_WORD is used when the IME commits the word it decided was best + // for the current user input. It may be different from what the user typed (true auto-correct) + // or it may be exactly what the user typed if it's in the dictionary or the IME does not have + // enough confidence in any suggestion to auto-correct (auto-correct to typed word). + public static final int COMMIT_TYPE_DECIDED_WORD = 2; + // COMMIT_TYPE_CANCEL_AUTO_CORRECT is used upon committing back the old word upon cancelling + // an auto-correction. + public static final int COMMIT_TYPE_CANCEL_AUTO_CORRECT = 3; + + public final ArrayList<int[]> mCodes; + public final int[] mXCoordinates; + public final int[] mYCoordinates; + public final String mTypedWord; + public final String mAutoCorrection; + + private boolean mActive; + + public static final LastComposedWord NOT_A_COMPOSED_WORD = + new LastComposedWord(null, null, null, "", ""); + + public LastComposedWord(final ArrayList<int[]> codes, final int[] xCoordinates, + final int[] yCoordinates, final String typedWord, final String autoCorrection) { + mCodes = codes; + mXCoordinates = xCoordinates; + mYCoordinates = yCoordinates; + mTypedWord = typedWord; + mAutoCorrection = autoCorrection; + mActive = true; + } + + public void deactivate() { + mActive = false; + } + + public boolean canCancelAutoCorrect() { + return mActive && !TextUtils.isEmpty(mAutoCorrection) + && !TextUtils.equals(mTypedWord, mAutoCorrection); + } +} diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index d59497d6a..2e7e82637 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -104,7 +104,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar */ public static final String IME_OPTION_NO_SETTINGS_KEY = "noSettingsKey"; - // TODO: Remove this private option. /** * The private IME option used to indicate that the given text field needs * ASCII code points input. @@ -200,6 +199,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private UserUnigramDictionary mUserUnigramDictionary; private boolean mIsUserDictionaryAvailable; + private LastComposedWord mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; private WordComposer mWordComposer = new WordComposer(); private int mCorrectionMode; @@ -729,6 +729,17 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar : String.format("inputType=0x%08x imeOptions=0x%08x", editorInfo.inputType, editorInfo.imeOptions))); } + if (Utils.inPrivateImeOptions(null, IME_OPTION_NO_MICROPHONE_COMPAT, editorInfo)) { + Log.w(TAG, "Deprecated private IME option specified: " + + editorInfo.privateImeOptions); + Log.w(TAG, "Use " + getPackageName() + "." + IME_OPTION_NO_MICROPHONE + " instead"); + } + if (Utils.inPrivateImeOptions(getPackageName(), IME_OPTION_FORCE_ASCII, editorInfo)) { + Log.w(TAG, "Deprecated private IME option specified: " + + editorInfo.privateImeOptions); + Log.w(TAG, "Use EditorInfo.IME_FLAG_FORCE_ASCII flag instead"); + } + LatinImeLogger.onStartInputView(editorInfo); // In landscape mode, this method gets called without the input view being created. if (inputView == null) { @@ -759,7 +770,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar inputView.closing(); mEnteredText = null; - mWordComposer.reset(); + resetComposingState(true /* alsoResetLastComposedWord */); mDeleteCount = 0; mSpaceState = SPACE_STATE_NONE; @@ -871,7 +882,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (((mWordComposer.isComposingWord()) || mVoiceProxy.isVoiceInputHighlighted()) && (selectionChanged || candidatesCleared)) { - mWordComposer.reset(); + resetComposingState(true /* alsoResetLastComposedWord */); updateSuggestions(); final InputConnection ic = getCurrentInputConnection(); if (ic != null) { @@ -880,7 +891,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mComposingStateManager.onFinishComposingText(); mVoiceProxy.setVoiceInputHighlighted(false); } else if (!mWordComposer.isComposingWord()) { - mWordComposer.reset(); + // TODO: is the following reset still needed, given that we are not composing + // a word? + resetComposingState(true /* alsoResetLastComposedWord */); updateSuggestions(); } } @@ -964,7 +977,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar .setHasMinimalSuggestion(false); // When in fullscreen mode, show completions generated by the application setSuggestions(builder.build()); - mWordComposer.deleteAutoCorrection(); + // TODO: is this the right thing to do? What should we auto-correct to in + // this case? This says to keep whatever the user typed. + mWordComposer.setAutoCorrection(mWordComposer.getTypedWord()); setSuggestionStripShown(true); } } @@ -1083,10 +1098,16 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar return super.onKeyUp(keyCode, event); } + private void resetComposingState(final boolean alsoResetLastComposedWord) { + mWordComposer.reset(); + if (alsoResetLastComposedWord) + mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; + } + public void commitTyped(final InputConnection ic) { if (!mWordComposer.isComposingWord()) return; final CharSequence typedWord = mWordComposer.getTypedWord(); - mWordComposer.onCommitWord(WordComposer.COMMIT_TYPE_USER_TYPED_WORD); + mLastComposedWord = mWordComposer.commitWord(LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD); if (typedWord.length() > 0) { if (ic != null) { ic.commitText(typedWord, 1); @@ -1253,6 +1274,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mHandler.cancelDoubleSpacesTimer(); } + boolean didAutoCorrect = false; switch (primaryCode) { case Keyboard.CODE_DELETE: mSpaceState = SPACE_STATE_NONE; @@ -1289,7 +1311,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar default: mSpaceState = SPACE_STATE_NONE; if (mSettingsValues.isWordSeparator(primaryCode)) { - handleSeparator(primaryCode, x, y, spaceState); + didAutoCorrect = handleSeparator(primaryCode, x, y, spaceState); } else { handleCharacter(primaryCode, keyCodes, x, y, spaceState); } @@ -1298,6 +1320,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } switcher.onCodeInput(primaryCode); // Reset after any single keystroke + if (!didAutoCorrect) + mLastComposedWord.deactivate(); mEnteredText = null; } @@ -1315,7 +1339,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mKeyboardSwitcher.onCodeInput(Keyboard.CODE_OUTPUT_TEXT); mSpaceState = SPACE_STATE_NONE; mEnteredText = text; - mWordComposer.reset(); + resetComposingState(true /* alsoResetLastComposedWord */); } @Override @@ -1373,7 +1397,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // resuming here. The behavior needs to be different according to text field types, // and it would be much clearer to test for them explicitly here rather than // relying on implicit values like "whether the suggestion strip is displayed". - if (mWordComposer.didAutoCorrectToAnotherWord()) { + if (mLastComposedWord.canCancelAutoCorrect()) { Utils.Stats.onAutoCorrectionCancellation(); cancelAutoCorrect(ic); return; @@ -1485,7 +1509,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // separator and it should be treated as a normal character, except in the first // position where it should not start composing a word. isComposingWord = (Keyboard.CODE_SINGLE_QUOTE != code); - mWordComposer.reset(); + // Here we don't need to reset the last composed word. It will be reset + // when we commit this one, if we ever do; if on the other hand we backspace + // it entirely and resume suggestions on the previous word, we'd like to still + // have touch coordinates for it. + resetComposingState(false /* alsoResetLastComposedWord */); clearSuggestions(); mComposingStateManager.onFinishComposingText(); } @@ -1537,7 +1565,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } } - private void handleSeparator(final int primaryCode, final int x, final int y, + // Returns true if we did an autocorrection, false otherwise. + private boolean handleSeparator(final int primaryCode, final int x, final int y, final int spaceState) { mVoiceProxy.handleSeparator(); mComposingStateManager.onFinishComposingText(); @@ -1548,6 +1577,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mHandler.postUpdateSuggestions(); } + boolean didAutoCorrect = false; // Handle separator final InputConnection ic = getCurrentInputConnection(); if (ic != null) { @@ -1562,6 +1592,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar && !mInputAttributes.mInputTypeNoAutoCorrect; if (shouldAutoCorrect && primaryCode != Keyboard.CODE_SINGLE_QUOTE) { commitCurrentAutoCorrection(primaryCode, ic); + didAutoCorrect = true; } else { commitTyped(ic); } @@ -1617,12 +1648,13 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (ic != null) { ic.endBatchEdit(); } + return didAutoCorrect; } private CharSequence getTextWithUnderline(final CharSequence text) { return mComposingStateManager.isAutoCorrectionIndicatorOn() ? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(this, text) - : mWordComposer.getTypedWord(); + : text; } private void handleClose() { @@ -1837,7 +1869,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } Utils.Stats.onAutoCorrection(typedWord, autoCorrection.toString(), separatorCodePoint); mExpectingUpdateSelection = true; - commitChosenWord(autoCorrection, WordComposer.COMMIT_TYPE_DECIDED_WORD); + commitChosenWord(autoCorrection, LastComposedWord.COMMIT_TYPE_DECIDED_WORD); // Add the word to the user unigram dictionary if it's not a known word addToUserUnigramAndBigramDictionaries(autoCorrection, UserUnigramDictionary.FREQUENCY_FOR_TYPED); @@ -1907,7 +1939,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar LatinImeLogger.logOnManualSuggestion(mWordComposer.getTypedWord().toString(), suggestion.toString(), index, suggestions.mWords); mExpectingUpdateSelection = true; - commitChosenWord(suggestion, WordComposer.COMMIT_TYPE_MANUAL_PICK); + commitChosenWord(suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK); // Add the word to the auto dictionary if it's not a known word if (index == 0) { addToUserUnigramAndBigramDictionaries(suggestion, @@ -1975,9 +2007,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } // TODO: figure out here if this is an auto-correct or if the best word is actually // what user typed. Note: currently this is done much later in - // WordComposer#didAutoCorrectToAnotherWord by string equality of the remembered + // LastComposedWord#canCancelAutoCorrect by string equality of the remembered // strings. - mWordComposer.onCommitWord(commitType); + mLastComposedWord = mWordComposer.commitWord(commitType); } private static final WordComposer sEmptyWordComposer = new WordComposer(); @@ -2141,12 +2173,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // "ic" must not be null private void cancelAutoCorrect(final InputConnection ic) { - mWordComposer.resumeSuggestionOnKeptWord(); - final String originallyTypedWord = mWordComposer.getTypedWord(); - final CharSequence autoCorrectedTo = mWordComposer.getAutoCorrectionOrNull(); + final String originallyTypedWord = mLastComposedWord.mTypedWord; + final CharSequence autoCorrectedTo = mLastComposedWord.mAutoCorrection; final int cancelLength = autoCorrectedTo.length(); final CharSequence separator = ic.getTextBeforeCursor(1, 0); if (DEBUG) { + if (mWordComposer.isComposingWord()) { + throw new RuntimeException("cancelAutoCorrect, but we are composing a word"); + } final String wordBeforeCursor = ic.getTextBeforeCursor(cancelLength + 1, 0).subSequence(0, cancelLength) .toString(); @@ -2165,8 +2199,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar ic.commitText(originallyTypedWord, 1); // Re-insert the separator ic.commitText(separator, 1); - mWordComposer.deleteAutoCorrection(); - mWordComposer.onCommitWord(WordComposer.COMMIT_TYPE_CANCEL_AUTO_CORRECT); + mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; Utils.Stats.onSeparator(separator.charAt(0), WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); mHandler.cancelUpdateBigramPredictions(); @@ -2180,7 +2213,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Note: in the interest of code simplicity, we may want to just call // restartSuggestionsOnWordBeforeCursorIfAtEndOfWord instead, but retrieving // the old WordComposer allows to reuse the actual typed coordinates. - mWordComposer.resumeSuggestionOnKeptWord(); + mWordComposer.resumeSuggestionOnLastComposedWord(mLastComposedWord); // We resume suggestion, and then we want to set the composing text to the content // of the word composer again. But since we just manually picked a word, there is // no composing text at the moment, so we have to delete the word before we set a @@ -2229,10 +2262,14 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final CharSequence textBeforeCursor = ic.getTextBeforeCursor(2, 0); // NOTE: This does not work with surrogate pairs. Hopefully when the keyboard is able to // enter surrogate pairs this code will have been removed. - if (Keyboard.CODE_SPACE != textBeforeCursor.charAt(1)) { - // We should not have come here if the text before the cursor is not a space. - throw new RuntimeException("Tried to revert a swap of punctuation but we didn't " + if (TextUtils.isEmpty(textBeforeCursor) + || (Keyboard.CODE_SPACE != textBeforeCursor.charAt(1))) { + // We may only come here if the application is changing the text while we are typing. + // This is quite a broken case, but not logically impossible, so we shouldn't crash, + // but some debugging log may be in order. + Log.d(TAG, "Tried to revert a swap of punctuation but we didn't " + "find a space just before the cursor."); + return false; } ic.beginBatchEdit(); ic.deleteSurroundingText(2, 0); diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java index 6f1adfe71..e3dadf250 100644 --- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java +++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java @@ -21,7 +21,6 @@ import android.content.SharedPreferences; import android.view.inputmethod.EditorInfo; import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.latin.Dictionary.DataType; import java.util.List; @@ -75,7 +74,7 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang public static void onStartSuggestion(CharSequence previousWords) { } - public static void onAddSuggestedWord(String word, int typeId, DataType dataType) { + public static void onAddSuggestedWord(String word, int typeId, int dataType) { } public static void onSetKeyboard(Keyboard kb) { diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java index 5af21452a..d32310096 100644 --- a/java/src/com/android/inputmethod/latin/Settings.java +++ b/java/src/com/android/inputmethod/latin/Settings.java @@ -218,7 +218,7 @@ public class Settings extends InputMethodSettingsActivity res.getString(R.string.key_preview_popup_dismiss_default_delay), }; final String popupDismissDelayDefaultValue = Integer.toString(res.getInteger( - R.integer.config_delay_after_preview)); + R.integer.config_key_preview_linger_timeout)); mKeyPreviewPopupDismissDelay.setEntries(entries); mKeyPreviewPopupDismissDelay.setEntryValues( new String[] { "0", popupDismissDelayDefaultValue }); diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java index 0ae28d3fc..e6ef3962e 100644 --- a/java/src/com/android/inputmethod/latin/SettingsValues.java +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -124,7 +124,7 @@ public class SettingsValues { mUsabilityStudyMode = getUsabilityStudyMode(prefs); mKeyPreviewPopupDismissDelayRawValue = prefs.getString( Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, - Integer.toString(res.getInteger(R.integer.config_delay_after_preview))); + Integer.toString(res.getInteger(R.integer.config_key_preview_linger_timeout))); mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true); mAutoCorrectEnabled = isAutoCorrectEnabled(res, mAutoCorrectionThresholdRawValue); mBigramSuggestionEnabled = mAutoCorrectEnabled @@ -234,7 +234,8 @@ public class SettingsValues { Resources resources) { // TODO: use mKeyPreviewPopupDismissDelayRawValue instead of reading it again here. return Integer.parseInt(sp.getString(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, - Integer.toString(resources.getInteger(R.integer.config_delay_after_preview)))); + Integer.toString(resources.getInteger( + R.integer.config_key_preview_linger_timeout)))); } private static boolean isBigramSuggestionEnabled(final SharedPreferences sp, diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 8e0d031f4..f6e177aaf 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -298,7 +298,7 @@ public class Suggest implements Dictionary.WordCallback { if (typedWord != null) { // Treating USER_TYPED as UNIGRAM suggestion for logging now. LatinImeLogger.onAddSuggestedWord(typedWord, Suggest.DIC_USER_TYPED, - Dictionary.DataType.UNIGRAM); + Dictionary.UNIGRAM); } mConsideredWord = consideredWord; @@ -417,12 +417,12 @@ public class Suggest implements Dictionary.WordCallback { @Override public boolean addWord(final char[] word, final int offset, final int length, int score, - final int dicTypeId, final Dictionary.DataType dataType) { - Dictionary.DataType dataTypeForLog = dataType; + final int dicTypeId, final int dataType) { + int dataTypeForLog = dataType; final ArrayList<CharSequence> suggestions; final int[] sortedScores; final int prefMaxSuggestions; - if(dataType == Dictionary.DataType.BIGRAM) { + if (dataType == Dictionary.BIGRAM) { suggestions = mBigramSuggestions; sortedScores = mBigramScores; prefMaxSuggestions = PREF_MAX_BIGRAMS; @@ -450,11 +450,11 @@ public class Suggest implements Dictionary.WordCallback { } } } else { - if (dataType == Dictionary.DataType.UNIGRAM) { + if (dataType == Dictionary.UNIGRAM) { // Check if the word was already added before (by bigram data) int bigramSuggestion = searchBigramSuggestion(word,offset,length); if(bigramSuggestion >= 0) { - dataTypeForLog = Dictionary.DataType.BIGRAM; + dataTypeForLog = Dictionary.BIGRAM; // turn freq from bigram into multiplier specified above double multiplier = (((double) mBigramScores[bigramSuggestion]) / MAXIMUM_BIGRAM_FREQUENCY) diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index e95dcfdc9..b96b0842a 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -33,64 +33,17 @@ public class WordComposer { public static final int NOT_A_CODE = KeyDetector.NOT_A_CODE; public static final int NOT_A_COORDINATE = -1; - // TODO: Straighten out commit behavior so that the flags here are more understandable, - // and possibly adjust their names. - // COMMIT_TYPE_USER_TYPED_WORD is used when the word committed is the exact typed word, with - // no hinting from the IME. It happens when some external event happens (rotating the device, - // for example) or when auto-correction is off by settings or editor attributes. - public static final int COMMIT_TYPE_USER_TYPED_WORD = 0; - // COMMIT_TYPE_MANUAL_PICK is used when the user pressed a field in the suggestion strip. - public static final int COMMIT_TYPE_MANUAL_PICK = 1; - // COMMIT_TYPE_DECIDED_WORD is used when the IME commits the word it decided was best - // for the current user input. It may be different from what the user typed (true auto-correct) - // or it may be exactly what the user typed if it's in the dictionary or the IME does not have - // enough confidence in any suggestion to auto-correct (auto-correct to typed word). - public static final int COMMIT_TYPE_DECIDED_WORD = 2; - // COMMIT_TYPE_CANCEL_AUTO_CORRECT is used upon committing back the old word upon cancelling - // an auto-correction. - public static final int COMMIT_TYPE_CANCEL_AUTO_CORRECT = 3; - - // Storage for all the info about the current input. - private static class CharacterStore { - /** - * The list of unicode values for each keystroke (including surrounding keys) - */ - ArrayList<int[]> mCodes; - int[] mXCoordinates; - int[] mYCoordinates; - StringBuilder mTypedWord; - CharSequence mAutoCorrection; - CharacterStore() { - final int N = BinaryDictionary.MAX_WORD_LENGTH; - mCodes = new ArrayList<int[]>(N); - mTypedWord = new StringBuilder(N); - mXCoordinates = new int[N]; - mYCoordinates = new int[N]; - mAutoCorrection = null; - } - CharacterStore(final CharacterStore that) { - mCodes = new ArrayList<int[]>(that.mCodes); - mTypedWord = new StringBuilder(that.mTypedWord); - mXCoordinates = Arrays.copyOf(that.mXCoordinates, that.mXCoordinates.length); - mYCoordinates = Arrays.copyOf(that.mYCoordinates, that.mYCoordinates.length); - } - void reset() { - // For better performance than creating a new character store. - mCodes.clear(); - mTypedWord.setLength(0); - mAutoCorrection = null; - } - } + final int N = BinaryDictionary.MAX_WORD_LENGTH; - // The currently typing word. May not be null. - private CharacterStore mCurrentWord; - // The information being kept for resuming suggestion. May be null if wiped. - private CharacterStore mCommittedWordSavedForSuggestionResuming; + private ArrayList<int[]> mCodes; + private int[] mXCoordinates; + private int[] mYCoordinates; + private StringBuilder mTypedWord; + private CharSequence mAutoCorrection; + // Cache these values for performance private int mCapsCount; - private boolean mAutoCapitalized; - // Cache this value for performance private int mTrailingSingleQuotesCount; /** @@ -99,8 +52,11 @@ public class WordComposer { private boolean mIsFirstCharCapitalized; public WordComposer() { - mCurrentWord = new CharacterStore(); - mCommittedWordSavedForSuggestionResuming = null; + mCodes = new ArrayList<int[]>(N); + mTypedWord = new StringBuilder(N); + mXCoordinates = new int[N]; + mYCoordinates = new int[N]; + mAutoCorrection = null; mTrailingSingleQuotesCount = 0; } @@ -109,8 +65,10 @@ public class WordComposer { } public void init(WordComposer source) { - mCurrentWord = new CharacterStore(source.mCurrentWord); - mCommittedWordSavedForSuggestionResuming = source.mCommittedWordSavedForSuggestionResuming; + mCodes = new ArrayList<int[]>(source.mCodes); + mTypedWord = new StringBuilder(source.mTypedWord); + mXCoordinates = Arrays.copyOf(source.mXCoordinates, source.mXCoordinates.length); + mYCoordinates = Arrays.copyOf(source.mYCoordinates, source.mYCoordinates.length); mCapsCount = source.mCapsCount; mIsFirstCharCapitalized = source.mIsFirstCharCapitalized; mAutoCapitalized = source.mAutoCapitalized; @@ -121,8 +79,9 @@ public class WordComposer { * Clear out the keys registered so far. */ public void reset() { - mCurrentWord.reset(); - mCommittedWordSavedForSuggestionResuming = null; + mCodes.clear(); + mTypedWord.setLength(0); + mAutoCorrection = null; mCapsCount = 0; mIsFirstCharCapitalized = false; mTrailingSingleQuotesCount = 0; @@ -133,7 +92,7 @@ public class WordComposer { * @return the number of keystrokes */ public final int size() { - return mCurrentWord.mTypedWord.length(); + return mTypedWord.length(); } public final boolean isComposingWord() { @@ -146,15 +105,15 @@ public class WordComposer { * @return the unicode for the pressed and surrounding keys */ public int[] getCodesAt(int index) { - return mCurrentWord.mCodes.get(index); + return mCodes.get(index); } public int[] getXCoordinates() { - return mCurrentWord.mXCoordinates; + return mXCoordinates; } public int[] getYCoordinates() { - return mCurrentWord.mYCoordinates; + return mYCoordinates; } private static boolean isFirstCharCapitalized(int index, int codePoint, boolean previous) { @@ -169,12 +128,12 @@ public class WordComposer { */ public void add(int primaryCode, int[] codes, int x, int y) { final int newIndex = size(); - mCurrentWord.mTypedWord.append((char) primaryCode); + mTypedWord.append((char) primaryCode); correctPrimaryJuxtapos(primaryCode, codes); - mCurrentWord.mCodes.add(codes); + mCodes.add(codes); if (newIndex < BinaryDictionary.MAX_WORD_LENGTH) { - mCurrentWord.mXCoordinates[newIndex] = x; - mCurrentWord.mYCoordinates[newIndex] = y; + mXCoordinates[newIndex] = x; + mYCoordinates[newIndex] = y; } mIsFirstCharCapitalized = isFirstCharCapitalized( newIndex, primaryCode, mIsFirstCharCapitalized); @@ -184,7 +143,7 @@ public class WordComposer { } else { mTrailingSingleQuotesCount = 0; } - mCurrentWord.mAutoCorrection = null; + mAutoCorrection = null; } /** @@ -218,7 +177,6 @@ public class WordComposer { int codePoint = word.charAt(i); addKeyInfo(codePoint, keyboard, keyDetector); } - mCommittedWordSavedForSuggestionResuming = null; } /** @@ -254,9 +212,9 @@ public class WordComposer { final int size = size(); if (size > 0) { final int lastPos = size - 1; - char lastChar = mCurrentWord.mTypedWord.charAt(lastPos); - mCurrentWord.mCodes.remove(lastPos); - mCurrentWord.mTypedWord.deleteCharAt(lastPos); + char lastChar = mTypedWord.charAt(lastPos); + mCodes.remove(lastPos); + mTypedWord.deleteCharAt(lastPos); if (Character.isUpperCase(lastChar)) mCapsCount--; } if (size() == 0) { @@ -265,12 +223,12 @@ public class WordComposer { if (mTrailingSingleQuotesCount > 0) { --mTrailingSingleQuotesCount; } else { - for (int i = mCurrentWord.mTypedWord.length() - 1; i >= 0; --i) { - if (Keyboard.CODE_SINGLE_QUOTE != mCurrentWord.mTypedWord.codePointAt(i)) break; + for (int i = mTypedWord.length() - 1; i >= 0; --i) { + if (Keyboard.CODE_SINGLE_QUOTE != mTypedWord.codePointAt(i)) break; ++mTrailingSingleQuotesCount; } } - mCurrentWord.mAutoCorrection = null; + mAutoCorrection = null; } /** @@ -278,7 +236,7 @@ public class WordComposer { * @return the word that was typed so far. Never returns null. */ public String getTypedWord() { - return mCurrentWord.mTypedWord.toString(); + return mTypedWord.toString(); } /** @@ -329,26 +287,18 @@ public class WordComposer { * Sets the auto-correction for this word. */ public void setAutoCorrection(final CharSequence correction) { - mCurrentWord.mAutoCorrection = correction; - } - - /** - * Remove any auto-correction that may have been set. - */ - public void deleteAutoCorrection() { - mCurrentWord.mAutoCorrection = null; + mAutoCorrection = correction; } /** * @return the auto-correction for this word, or null if none. */ public CharSequence getAutoCorrectionOrNull() { - return mCurrentWord.mAutoCorrection; + return mAutoCorrection; } - // `type' should be one of the COMMIT_TYPE_* constants above. - public void onCommitWord(final int type) { - mCommittedWordSavedForSuggestionResuming = mCurrentWord; + // `type' should be one of the LastComposedWord.COMMIT_TYPE_* constants above. + public LastComposedWord commitWord(final int type) { // Note: currently, we come here whenever we commit a word. If it's any *other* kind than // DECIDED_WORD, we should reset mAutoCorrection so that we don't attempt to cancel later. // If it's a DECIDED_WORD, it may be an actual auto-correction by the IME, or what the user @@ -356,30 +306,25 @@ public class WordComposer { // Ideally we would also null it when it was a DECIDED_WORD that was not an auto-correct. // As it happens these two cases should behave differently, because the former can be // canceled while the latter can't. Currently, we figure this out in - // #didAutoCorrectToAnotherWord with #equals(). It would be marginally cleaner to do it - // here, but it would be slower (since we would #equals() for each commit, instead of - // only on cancel), and ultimately we want to figure it out even earlier anyway. - if (type != COMMIT_TYPE_DECIDED_WORD) { - // Only ever revert an auto-correct. - mCommittedWordSavedForSuggestionResuming.mAutoCorrection = null; - } - // TODO: improve performance by swapping buffers instead of creating a new object. - mCurrentWord = new CharacterStore(); - } - - public boolean hasWordKeptForSuggestionResuming() { - return null != mCommittedWordSavedForSuggestionResuming; - } - - public void resumeSuggestionOnKeptWord() { - mCurrentWord = mCommittedWordSavedForSuggestionResuming; - mCommittedWordSavedForSuggestionResuming = null; + // LastComposedWord#didAutoCorrectToAnotherWord with #equals(). It would be marginally + // cleaner to do it here, but it would be slower (since we would #equals() for each commit, + // instead of only on cancel), and ultimately we want to figure it out even earlier anyway. + final LastComposedWord lastComposedWord = new LastComposedWord(mCodes, + mXCoordinates, mYCoordinates, mTypedWord.toString(), + (type != LastComposedWord.COMMIT_TYPE_DECIDED_WORD) || (null == mAutoCorrection) + ? null : mAutoCorrection.toString()); + mCodes.clear(); + mTypedWord.setLength(0); + mAutoCorrection = null; + return lastComposedWord; } - public boolean didAutoCorrectToAnotherWord() { - return null != mCommittedWordSavedForSuggestionResuming - && !TextUtils.isEmpty(mCommittedWordSavedForSuggestionResuming.mAutoCorrection) - && !TextUtils.equals(mCommittedWordSavedForSuggestionResuming.mTypedWord, - mCommittedWordSavedForSuggestionResuming.mAutoCorrection); + public void resumeSuggestionOnLastComposedWord(final LastComposedWord lastComposedWord) { + mCodes = lastComposedWord.mCodes; + mXCoordinates = lastComposedWord.mXCoordinates; + mYCoordinates = lastComposedWord.mYCoordinates; + mTypedWord.setLength(0); + mTypedWord.append(lastComposedWord.mTypedWord); + mAutoCorrection = lastComposedWord.mAutoCorrection; } } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 39e47f661..88ac043ed 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -31,7 +31,6 @@ import com.android.inputmethod.compat.SuggestionsInfoCompatUtils; import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.BinaryDictionary; import com.android.inputmethod.latin.Dictionary; -import com.android.inputmethod.latin.Dictionary.DataType; import com.android.inputmethod.latin.Dictionary.WordCallback; import com.android.inputmethod.latin.DictionaryCollection; import com.android.inputmethod.latin.DictionaryFactory; @@ -237,7 +236,7 @@ public class AndroidSpellCheckerService extends SpellCheckerService @Override synchronized public boolean addWord(char[] word, int wordOffset, int wordLength, int score, - int dicTypeId, DataType dataType) { + int dicTypeId, int dataType) { final int positionIndex = ArraysCompatUtils.binarySearch(mScores, 0, mLength, score); // binarySearch returns the index if the element exists, and -<insertion index> - 1 // if it doesn't. See documentation for binarySearch. |