diff options
Diffstat (limited to 'java/src')
9 files changed, 128 insertions, 53 deletions
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java index 8ca834148..86a56308a 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java @@ -105,13 +105,13 @@ public class AccessibleKeyboardViewProxy { } /** - * Receives hover events when accessibility is turned on in API > 11. In - * earlier API levels, events are manually routed from onTouchEvent. + * Receives hover events when accessibility is turned on in SDK versions ICS + * and higher. * * @param event The hover event. * @return {@code true} if the event is handled */ - public boolean onHoverEvent(MotionEvent event, PointerTracker tracker) { + public boolean dispatchHoverEvent(MotionEvent event, PointerTracker tracker) { if (mGestureDetector.onHoverEvent(event, this, tracker)) return true; diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 1010adbe0..fc47713b8 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -87,8 +87,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { private final KeyDrawParams mKeyDrawParams; // Key preview + private final int mKeyPreviewLayoutId; private final KeyPreviewDrawParams mKeyPreviewDrawParams; - private final TextView mPreviewText; private boolean mShowKeyPreviewPopup = true; private final int mDelayBeforePreview; private int mDelayAfterPreview; @@ -139,9 +139,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { keyboardView.showKey(msg.arg1, tracker); break; case MSG_DISMISS_KEY_PREVIEW: - if (keyboardView.mPreviewText != null) { - keyboardView.mPreviewText.setVisibility(View.INVISIBLE); - } + tracker.getKeyPreviewText().setVisibility(View.INVISIBLE); break; } } @@ -150,7 +148,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { removeMessages(MSG_SHOW_KEY_PREVIEW); final KeyboardView keyboardView = getOuterInstance(); if (keyboardView == null) return; - if (keyboardView.mPreviewText.getVisibility() == VISIBLE || delay == 0) { + if (tracker.getKeyPreviewText().getVisibility() == VISIBLE || delay == 0) { // Show right away, if it's already visible and finger is moving around keyboardView.showKey(keyIndex, tracker); } else { @@ -171,6 +169,10 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { sendMessageDelayed(obtainMessage(MSG_DISMISS_KEY_PREVIEW, tracker), delay); } + public void cancelDismissKeyPreview(PointerTracker tracker) { + removeMessages(MSG_DISMISS_KEY_PREVIEW, tracker); + } + public void cancelAllDismissKeyPreviews() { removeMessages(MSG_DISMISS_KEY_PREVIEW); } @@ -317,11 +319,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { mKeyDrawParams = new KeyDrawParams(a); mKeyPreviewDrawParams = new KeyPreviewDrawParams(a, mKeyDrawParams); - final int previewLayout = a.getResourceId(R.styleable.KeyboardView_keyPreviewLayout, 0); - if (previewLayout != 0) { - mPreviewText = (TextView) LayoutInflater.from(context).inflate(previewLayout, null); - } else { - mPreviewText = null; + mKeyPreviewLayoutId = a.getResourceId(R.styleable.KeyboardView_keyPreviewLayout, 0); + if (mKeyPreviewLayoutId == 0) { mShowKeyPreviewPopup = false; } mBackgroundDimAmount = a.getFloat(R.styleable.KeyboardView_backgroundDimAmount, 0.5f); @@ -730,6 +729,17 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { mDrawingHandler.cancelAllMessages(); } + // Called by {@link PointerTracker} constructor to create a TextView. + @Override + public TextView inflateKeyPreviewText() { + final Context context = getContext(); + if (mKeyPreviewLayoutId != 0) { + return (TextView)LayoutInflater.from(context).inflate(mKeyPreviewLayoutId, null); + } else { + return new TextView(context); + } + } + @Override public void showKeyPreview(int keyIndex, PointerTracker tracker) { if (mShowKeyPreviewPopup) { @@ -760,15 +770,15 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { } // TODO: Introduce minimum duration for displaying key previews - // TODO: Display up to two key previews when the user presses two keys at the same time private void showKey(final int keyIndex, PointerTracker tracker) { - final TextView previewText = mPreviewText; + final TextView previewText = tracker.getKeyPreviewText(); // If the key preview has no parent view yet, add it to the ViewGroup which can place // key preview absolutely in SoftInputWindow. if (previewText.getParent() == null) { addKeyPreview(previewText); } + mDrawingHandler.cancelDismissKeyPreview(tracker); final Key key = tracker.getKey(keyIndex); // If keyIndex is invalid or IME is already closed, we must not show key preview. // Trying to show key preview while root window is closed causes @@ -776,7 +786,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { if (key == null) return; - mDrawingHandler.cancelAllDismissKeyPreviews(); final KeyPreviewDrawParams params = mKeyPreviewDrawParams; final int keyDrawX = key.mX + key.mVisualInsetsLeft; final int keyDrawWidth = key.mWidth - key.mVisualInsetsLeft - key.mVisualInsetsRight; @@ -858,13 +867,18 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { } public void closing() { - mPreviewText.setVisibility(View.GONE); + PointerTracker.dismissAllKeyPreviews(); cancelAllMessages(); mDirtyRect.union(0, 0, getWidth(), getHeight()); requestLayout(); } + @Override + public boolean dismissPopupPanel() { + return false; + } + public void purgeKeyboardAndClosing() { mKeyboard = null; closing(); diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java index 0ad91dbb0..cb1a2b782 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java @@ -400,11 +400,10 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke mPopupPanel = popupPanel; mPopupPanelPointerTrackerId = tracker.mPointerId; - tracker.onLongPressed(); - popupPanel.showPanel(this, parentKey, tracker, mPopupWindow); + popupPanel.showPopupPanel(this, parentKey, tracker, mPopupWindow); final int translatedX = popupPanel.translateX(tracker.getLastX()); final int translatedY = popupPanel.translateY(tracker.getLastY()); - tracker.onDownEvent(translatedX, translatedY, SystemClock.uptimeMillis(), popupPanel); + tracker.onShowPopupPanel(translatedX, translatedY, SystemClock.uptimeMillis(), popupPanel); invalidateAllKeys(); return true; @@ -546,11 +545,12 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke @Override public void closing() { super.closing(); - dismissMiniKeyboard(); + dismissPopupPanel(); mPopupPanelCache.clear(); } - public boolean dismissMiniKeyboard() { + @Override + public boolean dismissPopupPanel() { if (mPopupWindow != null && mPopupWindow.isShowing()) { mPopupWindow.dismiss(); mPopupPanel = null; @@ -562,7 +562,7 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke } public boolean handleBack() { - return dismissMiniKeyboard(); + return dismissPopupPanel(); } @Override @@ -586,15 +586,22 @@ public class LatinKeyboardBaseView extends KeyboardView implements PointerTracke return super.dispatchPopulateAccessibilityEvent(event); } - public boolean onHoverEvent(MotionEvent event) { - // Since reflection doesn't support calling superclass methods, this - // method checks for the existence of onHoverEvent() in the View class - // before returning a value. + /** + * Receives hover events from the input framework. This method overrides + * View.dispatchHoverEvent(MotionEvent) on SDK version ICS or higher. On + * lower SDK versions, this method is never called. + * + * @param event The motion event to be dispatched. + * @return {@code true} if the event was handled by the view, {@code false} + * otherwise + */ + public boolean dispatchHoverEvent(MotionEvent event) { if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) { final PointerTracker tracker = getPointerTracker(0); - return AccessibleKeyboardViewProxy.getInstance().onHoverEvent(event, tracker); + return AccessibleKeyboardViewProxy.getInstance().dispatchHoverEvent(event, tracker); } + // Reflection doesn't support calling superclass methods. return false; } } diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index e66ea7b79..f64835726 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 android.content.Context; import android.content.res.Resources; import android.util.Log; +import android.widget.TextView; import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.latin.LatinImeLogger; @@ -64,9 +65,11 @@ public class PointerTracker { public interface DrawingProxy { public void invalidateKey(Key key); + public TextView inflateKeyPreviewText(); public void showKeyPreview(int keyIndex, PointerTracker tracker); public void cancelShowKeyPreview(PointerTracker tracker); public void dismissKeyPreview(PointerTracker tracker); + public boolean dismissPopupPanel(); } public interface TimerProxy { @@ -99,6 +102,7 @@ public class PointerTracker { private Keyboard mKeyboard; private List<Key> mKeys; private int mKeyQuarterWidthSquared; + private final TextView mKeyPreviewText; // The position and time at which first down event occurred. private long mDownTime; @@ -117,9 +121,12 @@ public class PointerTracker { // true if keyboard layout has been changed. private boolean mKeyboardLayoutHasBeenChanged; - // true if event is already translated to a key action (long press or mini-keyboard) + // true if event is already translated to a key action. private boolean mKeyAlreadyProcessed; + // true if this pointer has been long-pressed and is showing a popup panel. + private boolean mIsShowingPopupPanel; + // true if this pointer is repeatable key private boolean mIsRepeatableKey; @@ -211,6 +218,11 @@ public class PointerTracker { mListener = handler.getKeyboardActionListener(); mDrawingProxy = handler.getDrawingProxy(); mTimerProxy = handler.getTimerProxy(); + mKeyPreviewText = mDrawingProxy.inflateKeyPreviewText(); + } + + public TextView getKeyPreviewText() { + return mKeyPreviewText; } // Returns true if keyboard has been changed by this callback. @@ -579,6 +591,10 @@ public class PointerTracker { } final int keyIndex = onUpKey(keyX, keyY, eventTime); setReleasedKeyGraphics(keyIndex); + if (mIsShowingPopupPanel) { + mDrawingProxy.dismissPopupPanel(); + mIsShowingPopupPanel = false; + } if (mKeyAlreadyProcessed) return; if (!mIsRepeatableKey) { @@ -586,6 +602,12 @@ public class PointerTracker { } } + public void onShowPopupPanel(int x, int y, long eventTime, KeyEventHandler handler) { + onLongPressed(); + onDownEvent(x, y, eventTime, handler); + mIsShowingPopupPanel = true; + } + public void onLongPressed() { mKeyAlreadyProcessed = true; setReleasedKeyGraphics(mKeyIndex); @@ -612,6 +634,10 @@ public class PointerTracker { mDrawingProxy.cancelShowKeyPreview(this); setReleasedKeyGraphics(mKeyIndex); mIsInSlidingKeyInput = false; + if (mIsShowingPopupPanel) { + mDrawingProxy.dismissPopupPanel(); + mIsShowingPopupPanel = false; + } } private void startRepeatKey(int keyIndex) { diff --git a/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java b/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java index a90f57c62..2741ee80b 100644 --- a/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java @@ -59,19 +59,16 @@ public class PopupMiniKeyboardView extends KeyboardView implements PopupPanel { public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { mParentKeyboardView.getKeyboardActionListener() .onCodeInput(primaryCode, keyCodes, x, y); - mParentKeyboardView.dismissMiniKeyboard(); } @Override public void onTextInput(CharSequence text) { mParentKeyboardView.getKeyboardActionListener().onTextInput(text); - mParentKeyboardView.dismissMiniKeyboard(); } @Override public void onCancelInput() { mParentKeyboardView.getKeyboardActionListener().onCancelInput(); - mParentKeyboardView.dismissMiniKeyboard(); } @Override @@ -159,7 +156,7 @@ public class PopupMiniKeyboardView extends KeyboardView implements PopupPanel { } @Override - public void showPanel(LatinKeyboardBaseView parentKeyboardView, Key parentKey, + public void showPopupPanel(LatinKeyboardBaseView parentKeyboardView, Key parentKey, PointerTracker tracker, PopupWindow window) { mParentKeyboardView = parentKeyboardView; final View container = (View)getParent(); @@ -192,6 +189,11 @@ public class PopupMiniKeyboardView extends KeyboardView implements PopupPanel { } @Override + public boolean dismissPopupPanel() { + return mParentKeyboardView.dismissPopupPanel(); + } + + @Override public int translateX(int x) { return x - mOriginX; } diff --git a/java/src/com/android/inputmethod/keyboard/PopupPanel.java b/java/src/com/android/inputmethod/keyboard/PopupPanel.java index f94d1c562..dc526e74f 100644 --- a/java/src/com/android/inputmethod/keyboard/PopupPanel.java +++ b/java/src/com/android/inputmethod/keyboard/PopupPanel.java @@ -26,7 +26,7 @@ public interface PopupPanel extends PointerTracker.KeyEventHandler { * @param tracker the pointer tracker that pressesd the parent key * @param window PopupWindow to be used to show this popup panel */ - public void showPanel(LatinKeyboardBaseView parentKeyboardView, Key parentKey, + public void showPopupPanel(LatinKeyboardBaseView parentKeyboardView, Key parentKey, PointerTracker tracker, PopupWindow window); /** diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java index 00d80f566..41b577cf3 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java @@ -107,6 +107,7 @@ public class BinaryDictionaryFileDumper { if (null == afd) return null; final String fileName = copyFileTo(afd.createInputStream(), getCacheFileNameForLocale(locale, context)); + afd.close(); return Arrays.asList(AssetFileAddress.makeFromFileName(fileName)); } diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 8ae653f2f..c2452b947 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -102,6 +102,8 @@ public class Suggest implements Dictionary.WordCallback { private ArrayList<CharSequence> mSuggestions = new ArrayList<CharSequence>(); ArrayList<CharSequence> mBigramSuggestions = new ArrayList<CharSequence>(); + // TODO: maybe this should be synchronized, it's quite scary as it is. + // TODO: if it becomes synchronized, also move initPool in the thread in initAsynchronously private ArrayList<CharSequence> mStringPool = new ArrayList<CharSequence>(); private CharSequence mTypedWord; @@ -111,27 +113,39 @@ public class Suggest implements Dictionary.WordCallback { private int mCorrectionMode = CORRECTION_BASIC; - public Suggest(Context context, int dictionaryResId, Locale locale) { - init(context, DictionaryFactory.createDictionaryFromManager(context, locale, - dictionaryResId)); + public Suggest(final Context context, final int dictionaryResId, final Locale locale) { + initAsynchronously(context, dictionaryResId, locale); } /* package for test */ Suggest(Context context, File dictionary, long startOffset, long length, Flag[] flagArray) { - init(null, DictionaryFactory.createDictionaryForTest(context, dictionary, startOffset, - length, flagArray)); + initSynchronously(null, DictionaryFactory.createDictionaryForTest(context, dictionary, + startOffset, length, flagArray)); } - private void init(Context context, Dictionary mainDict) { - mMainDict = mainDict; - addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, mainDict); - addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, mainDict); + private void initWhitelistAndAutocorrectAndPool(final Context context) { mWhiteListDictionary = WhitelistDictionary.init(context); addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_WHITELIST, mWhiteListDictionary); mAutoCorrection = new AutoCorrection(); initPool(); } + private void initAsynchronously(final Context context, final int dictionaryResId, + final Locale locale) { + resetMainDict(context, dictionaryResId, locale); + + // TODO: read the whitelist and init the pool asynchronously too. + // initPool should be done asynchronously but the pool is not thread-safe at the moment. + initWhitelistAndAutocorrectAndPool(context); + } + + private void initSynchronously(Context context, Dictionary mainDict) { + mMainDict = mainDict; + addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, mainDict); + addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, mainDict); + initWhitelistAndAutocorrectAndPool(context); + } + private void addOrReplaceDictionary(Map<String, Dictionary> dictionaries, String key, Dictionary dict) { final Dictionary oldDict = (dict == null) @@ -142,12 +156,18 @@ public class Suggest implements Dictionary.WordCallback { } } - public void resetMainDict(Context context, int dictionaryResId, Locale locale) { - final Dictionary newMainDict = DictionaryFactory.createDictionaryFromManager( - context, locale, dictionaryResId); - mMainDict = newMainDict; - addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, newMainDict); - addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, newMainDict); + public void resetMainDict(final Context context, final int dictionaryResId, + final Locale locale) { + mMainDict = null; + new Thread("InitializeBinaryDictionary") { + public void run() { + final Dictionary newMainDict = DictionaryFactory.createDictionaryFromManager( + context, locale, dictionaryResId); + mMainDict = newMainDict; + addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_MAIN, newMainDict); + addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_MAIN, newMainDict); + } + }.start(); } private void initPool() { diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index 84db17504..b77cbd199 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -16,6 +16,7 @@ package com.android.inputmethod.latin; +import android.text.TextUtils; import android.view.inputmethod.CompletionInfo; import java.util.ArrayList; @@ -105,14 +106,18 @@ public class SuggestedWords { } private Builder addWord(CharSequence word, SuggestedWordInfo suggestedWordInfo) { - mWords.add(word); - mSuggestedWordInfoList.add(suggestedWordInfo); + if (!TextUtils.isEmpty(word)) { + mWords.add(word); + // It's okay if suggestedWordInfo is null since it's checked where it's used. + mSuggestedWordInfoList.add(suggestedWordInfo); + } return this; } public Builder setApplicationSpecifiedCompletions(CompletionInfo[] infos) { - for (CompletionInfo info : infos) - addWord(info.getText()); + for (CompletionInfo info : infos) { + if (null != info) addWord(info.getText()); + } return this; } |