From 3f2653ba60c2509bdf72c44c2ae051d2cadc5dbb Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Mon, 18 Apr 2011 17:00:58 +0900 Subject: [PATCH 1/6] Refactor key preview related code in KeyboardView Change-Id: Ib8f08cb4f5e03d0c32c32a0ea0363ce3d72fc050 --- .../inputmethod/keyboard/KeyboardView.java | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 3550dcbb0..3cef002d7 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -118,6 +118,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { private int mPopupPreviewDisplayedY; private final int mDelayBeforePreview; private final int mDelayAfterPreview; + private ViewGroup mPreviewPlacer; // Popup mini keyboard private PopupWindow mMiniKeyboardPopup; @@ -898,22 +899,35 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { } } - // 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) { - // If the preview popup has no parent view yet, add it to the screen FrameLayout. - if (mPreviewText.getParent() == null) { - final FrameLayout screenContent = (FrameLayout) getRootView() - .findViewById(android.R.id.content); - if (android.os.Build.VERSION.SDK_INT >= /* HONEYCOMB */ 11) { - screenContent.addView(mPreviewText, new FrameLayout.LayoutParams(0, 0)); + private void addKeyPreview(TextView keyPreview) { + ViewGroup placer = mPreviewPlacer; + if (placer == null) { + final FrameLayout screenContent = (FrameLayout) getRootView().findViewById( + android.R.id.content); + if (android.os.Build.VERSION.SDK_INT >= /* HONEYCOMB */11) { + placer = screenContent; } else { // Insert LinearLayout to be able to setMargin because pre-Honeycomb FrameLayout // could not handle setMargin properly. - final LinearLayout placer = new LinearLayout(getContext()); + placer = new LinearLayout(getContext()); screenContent.addView(placer); - placer.addView(mPreviewText, new LinearLayout.LayoutParams(0, 0)); } + mPreviewPlacer = placer; + } + if (placer instanceof FrameLayout) { + placer.addView(keyPreview, new FrameLayout.LayoutParams(0, 0)); + } else { + placer.addView(keyPreview, new LinearLayout.LayoutParams(0, 0)); + } + } + + // 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) { + // If the preview popup has no parent view yet, add it to the ViewGroup which can place + // key preview absolutely in SoftInputWindow. + if (mPreviewText.getParent() == null) { + addKeyPreview(mPreviewText); } final Key key = tracker.getKey(keyIndex); From 88808fcdd41c901072f3d224fa109182b26af22d Mon Sep 17 00:00:00 2001 From: satok Date: Mon, 18 Apr 2011 20:23:39 +0900 Subject: [PATCH 2/6] Show all languages supported in LatinImeGoogle in InputLanguageSelection Bug: 4311203 Change-Id: I7a94e9697758cb79743c026e7f1c023f618a9aa1 --- .../latin/InputLanguageSelection.java | 54 ++++++++++--------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/InputLanguageSelection.java b/java/src/com/android/inputmethod/latin/InputLanguageSelection.java index be5e015aa..40ab28c98 100644 --- a/java/src/com/android/inputmethod/latin/InputLanguageSelection.java +++ b/java/src/com/android/inputmethod/latin/InputLanguageSelection.java @@ -162,36 +162,42 @@ public class InputLanguageSelection extends PreferenceActivity { for (int i = 0 ; i < origSize; i++ ) { String s = locales[i]; int len = s.length(); + String language = ""; + String country = ""; if (len == 5) { - String language = s.substring(0, 2); - String country = s.substring(3, 5); - Locale l = new Locale(language, country); + language = s.substring(0, 2); + country = s.substring(3, 5); + } else if (len < 5) { + language = s; + } + Locale l = new Locale(language, country); - // Exclude languages that are not relevant to LatinIME - if (arrayContains(BLACKLIST_LANGUAGES, language)) continue; + // Exclude languages that are not relevant to LatinIME + if (arrayContains(BLACKLIST_LANGUAGES, language) || TextUtils.isEmpty(language)) { + continue; + } - if (finalSize == 0) { + if (finalSize == 0) { + preprocess[finalSize++] = + new Loc(SubtypeSwitcher.getFullDisplayName(l, true), l); + } else { + // check previous entry: + // same lang and a country -> upgrade to full name and + // insert ours with full name + // diff lang -> insert ours with lang-only name + if (preprocess[finalSize-1].mLocale.getLanguage().equals( + language)) { + preprocess[finalSize-1].setLabel(SubtypeSwitcher.getFullDisplayName( + preprocess[finalSize-1].mLocale, false)); preprocess[finalSize++] = - new Loc(SubtypeSwitcher.getFullDisplayName(l, true), l); + new Loc(SubtypeSwitcher.getFullDisplayName(l, false), l); } else { - // check previous entry: - // same lang and a country -> upgrade to full name and - // insert ours with full name - // diff lang -> insert ours with lang-only name - if (preprocess[finalSize-1].mLocale.getLanguage().equals( - language)) { - preprocess[finalSize-1].setLabel(SubtypeSwitcher.getFullDisplayName( - preprocess[finalSize-1].mLocale, false)); - preprocess[finalSize++] = - new Loc(SubtypeSwitcher.getFullDisplayName(l, false), l); + String displayName; + if (s.equals("zz_ZZ")) { + // ignore this locale } else { - String displayName; - if (s.equals("zz_ZZ")) { - // ignore this locale - } else { - displayName = SubtypeSwitcher.getFullDisplayName(l, true); - preprocess[finalSize++] = new Loc(displayName, l); - } + displayName = SubtypeSwitcher.getFullDisplayName(l, true); + preprocess[finalSize++] = new Loc(displayName, l); } } } From d2c2b4d112ee17750c1a49ff223b9410aa9e4ec6 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Mon, 18 Apr 2011 19:07:20 +0900 Subject: [PATCH 3/6] Remove mPreviousKey in PointerTracker This change also introduces PointerTracker.onLongPressed. Change-Id: I079eb52175d8fe8b88ce3f13e31493d34d00ad5e --- .../inputmethod/keyboard/KeyboardView.java | 9 +- .../inputmethod/keyboard/PointerTracker.java | 108 ++++++++++-------- .../keyboard/PointerTrackerKeyState.java | 1 + .../keyboard/PointerTrackerQueue.java | 4 +- 4 files changed, 63 insertions(+), 59 deletions(-) diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 3cef002d7..42305a15e 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -881,7 +881,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { // TODO: clean up this method. private void dismissKeyPreview() { for (PointerTracker tracker : mPointerTrackers) - tracker.releaseKey(); + tracker.setReleasedKeyGraphics(); showPreview(KeyDetector.NOT_A_KEY, null); } @@ -1034,16 +1034,13 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { if (result) { dismissKeyPreview(); mMiniKeyboardTrackerId = tracker.mPointerId; - // Mark this tracker "already processed" and remove it from the pointer queue - tracker.setAlreadyProcessed(); - mPointerQueue.remove(tracker); + tracker.onLongPressed(mPointerQueue); } return result; } private void onLongPressShiftKey(PointerTracker tracker) { - tracker.setAlreadyProcessed(); - mPointerQueue.remove(tracker); + tracker.onLongPressed(mPointerQueue); mKeyboardActionListener.onCodeInput(Keyboard.CODE_CAPSLOCK, null, 0, 0); } diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 5d137b9f6..800174c0e 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -91,9 +91,6 @@ public class PointerTracker { // ignore modifier key if true private boolean mIgnoreModifierKey; - // pressed key - private int mPreviousKey = NOT_A_KEY; - // Empty {@link KeyboardActionListener} private static final KeyboardActionListener EMPTY_LISTENER = new KeyboardActionListener() { @Override @@ -250,29 +247,24 @@ public class PointerTracker { return key != null && key.mCode == Keyboard.CODE_SPACE; } - public void releaseKey() { - updateKeyGraphics(NOT_A_KEY); + public void setReleasedKeyGraphics() { + setReleasedKeyGraphics(mKeyState.getKeyIndex()); } - private void updateKeyGraphics(int keyIndex) { - int oldKeyIndex = mPreviousKey; - mPreviousKey = keyIndex; - if (keyIndex != oldKeyIndex) { - if (isValidKeyIndex(oldKeyIndex)) { - final Key oldKey = mKeys.get(oldKeyIndex); - oldKey.onReleased(); - mProxy.invalidateKey(oldKey); - } - if (isValidKeyIndex(keyIndex)) { - final Key newKey = mKeys.get(keyIndex); - newKey.onPressed(); - mProxy.invalidateKey(newKey); - } + private void setReleasedKeyGraphics(int keyIndex) { + final Key key = getKey(keyIndex); + if (key != null) { + key.onReleased(); + mProxy.invalidateKey(key); } } - public void setAlreadyProcessed() { - mKeyAlreadyProcessed = true; + private void setPressedKeyGraphics(int keyIndex) { + final Key key = getKey(keyIndex); + if (key != null && key.mEnabled) { + key.onPressed(); + mProxy.invalidateKey(key); + } } private void checkAssertion(PointerTrackerQueue queue) { @@ -318,7 +310,7 @@ public class PointerTracker { if (DEBUG_MODE) Log.w(TAG, "onDownEvent: ignore potential noise: time=" + deltaT + " distance=" + distanceSquared); - setAlreadyProcessed(); + mKeyAlreadyProcessed = true; return; } } @@ -346,24 +338,25 @@ public class PointerTracker { mIsRepeatableKey = false; mIsInSlidingKeyInput = false; mIgnoreModifierKey = false; - final Key key = getKey(keyIndex); - if (key != null) { + if (isValidKeyIndex(keyIndex)) { // This onPress call may have changed keyboard layout. Those cases are detected at // {@link #setKeyboard}. In those cases, we should update keyIndex according to the new // keyboard layout. - if (callListenerOnPressAndCheckKeyboardLayoutChange(key, false)) + if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), false)) keyIndex = mKeyState.onDownKey(x, y, eventTime); // Accessibility disables key repeat because users may need to pause on a key to hear // its spoken description. - if (key.mRepeatable && !mIsAccessibilityEnabled) { + final Key key = getKey(keyIndex); + if (key != null && key.mRepeatable && !mIsAccessibilityEnabled) { repeatKey(keyIndex); mHandler.startKeyRepeatTimer(mDelayBeforeKeyRepeatStart, keyIndex, this); mIsRepeatableKey = true; } startLongPressTimer(keyIndex); + showKeyPreview(keyIndex); + setPressedKeyGraphics(keyIndex); } - showKeyPreviewAndUpdateKeyGraphics(keyIndex); } private void startSlidingKeyInput(Key key) { @@ -382,8 +375,9 @@ public class PointerTracker { final int lastX = keyState.getLastX(); final int lastY = keyState.getLastY(); + final int oldKeyIndex = keyState.getKeyIndex(); + final Key oldKey = getKey(oldKeyIndex); int keyIndex = keyState.onMoveKey(x, y); - final Key oldKey = getKey(keyState.getKeyIndex()); if (isValidKeyIndex(keyIndex)) { if (oldKey == null) { // The pointer has been slid in to the new key, but the finger was not on any keys. @@ -395,10 +389,13 @@ public class PointerTracker { keyIndex = keyState.onMoveKey(x, y); keyState.onMoveToNewKey(keyIndex, x, y); startLongPressTimer(keyIndex); + showKeyPreview(keyIndex); + setPressedKeyGraphics(keyIndex); } else if (!isMinorMoveBounce(x, y, keyIndex)) { // The pointer has been slid in to the new key from the previous key, we must call // onRelease() first to notify that the previous key has been released, then call // onPress() to notify that the new key is being pressed. + setReleasedKeyGraphics(oldKeyIndex); callListenerOnRelease(oldKey, oldKey.mCode, true); startSlidingKeyInput(oldKey); mHandler.cancelLongPressTimers(); @@ -410,6 +407,8 @@ public class PointerTracker { keyIndex = keyState.onMoveKey(x, y); keyState.onMoveToNewKey(keyIndex, x, y); startLongPressTimer(keyIndex); + setPressedKeyGraphics(keyIndex); + showKeyPreview(keyIndex); } else { // HACK: On some devices, quick successive touches may be translated to sudden // move by touch panel firmware. This hack detects the case and translates the @@ -424,8 +423,9 @@ public class PointerTracker { onUpEventInternal(lastX, lastY, eventTime); onDownEventInternal(x, y, eventTime); } else { - setAlreadyProcessed(); - showKeyPreviewAndUpdateKeyGraphics(NOT_A_KEY); + mKeyAlreadyProcessed = true; + showKeyPreview(NOT_A_KEY); + setReleasedKeyGraphics(oldKeyIndex); } return; } @@ -434,19 +434,19 @@ public class PointerTracker { if (oldKey != null && !isMinorMoveBounce(x, y, keyIndex)) { // The pointer has been slid out from the previous key, we must call onRelease() to // notify that the previous key has been released. + setReleasedKeyGraphics(oldKeyIndex); callListenerOnRelease(oldKey, oldKey.mCode, true); startSlidingKeyInput(oldKey); mHandler.cancelLongPressTimers(); if (mIsAllowedSlidingKeyInput) { - keyState.onMoveToNewKey(keyIndex, x ,y); + keyState.onMoveToNewKey(keyIndex, x, y); } else { - setAlreadyProcessed(); - showKeyPreviewAndUpdateKeyGraphics(NOT_A_KEY); + mKeyAlreadyProcessed = true; + showKeyPreview(NOT_A_KEY); return; } } } - showKeyPreviewAndUpdateKeyGraphics(keyState.getKeyIndex()); } public void onUpEvent(int x, int y, long eventTime, PointerTrackerQueue queue) { @@ -469,30 +469,38 @@ public class PointerTracker { public void onUpEventForRelease(int x, int y, long eventTime) { onUpEventInternal(x, y, eventTime); + mKeyAlreadyProcessed = true; } - private void onUpEventInternal(int pointX, int pointY, long eventTime) { - int x = pointX; - int y = pointY; + private void onUpEventInternal(int x, int y, long eventTime) { mHandler.cancelKeyTimers(); mHandler.cancelPopupPreview(); - showKeyPreviewAndUpdateKeyGraphics(NOT_A_KEY); mIsInSlidingKeyInput = false; + final PointerTrackerKeyState keyState = mKeyState; + final int keyX, keyY; + if (!isMinorMoveBounce(x, y, keyState.onMoveKey(x, y))) { + keyX = x; + keyY = y; + } else { + // Use previous fixed key coordinates. + keyX = keyState.getKeyX(); + keyY = keyState.getKeyY(); + } + final int keyIndex = keyState.onUpKey(keyX, keyY, eventTime); + showKeyPreview(NOT_A_KEY); + setReleasedKeyGraphics(keyIndex); if (mKeyAlreadyProcessed) return; - final PointerTrackerKeyState keyState = mKeyState; - int keyIndex = keyState.onUpKey(x, y, eventTime); - if (isMinorMoveBounce(x, y, keyIndex)) { - // Use previous fixed key index and coordinates. - keyIndex = keyState.getKeyIndex(); - x = keyState.getKeyX(); - y = keyState.getKeyY(); - } if (!mIsRepeatableKey) { - detectAndSendKey(keyIndex, x, y); + detectAndSendKey(keyIndex, keyX, keyY); } } + public void onLongPressed(PointerTrackerQueue queue) { + mKeyAlreadyProcessed = true; + queue.remove(this); + } + public void onCancelEvent(int x, int y, long eventTime, PointerTrackerQueue queue) { if (ENABLE_ASSERTION) checkAssertion(queue); if (DEBUG_EVENT) @@ -506,7 +514,8 @@ public class PointerTracker { private void onCancelEventInternal() { mHandler.cancelKeyTimers(); mHandler.cancelPopupPreview(); - showKeyPreviewAndUpdateKeyGraphics(NOT_A_KEY); + showKeyPreview(NOT_A_KEY); + setReleasedKeyGraphics(mKeyState.getKeyIndex()); mIsInSlidingKeyInput = false; } @@ -542,7 +551,7 @@ public class PointerTracker { } } - private void showKeyPreviewAndUpdateKeyGraphics(int keyIndex) { + private void showKeyPreview(int keyIndex) { final Key key = getKey(keyIndex); if (key != null && !key.mEnabled) return; @@ -555,7 +564,6 @@ public class PointerTracker { } else { mProxy.showPreview(keyIndex, this); } - updateKeyGraphics(keyIndex); } private void startLongPressTimer(int keyIndex) { diff --git a/java/src/com/android/inputmethod/keyboard/PointerTrackerKeyState.java b/java/src/com/android/inputmethod/keyboard/PointerTrackerKeyState.java index a62ed96a3..b3ed1e26f 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTrackerKeyState.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTrackerKeyState.java @@ -92,6 +92,7 @@ package com.android.inputmethod.keyboard; public int onUpKey(int x, int y, long eventTime) { mUpTime = eventTime; + mKeyIndex = KeyDetector.NOT_A_KEY; return onMoveKeyInternal(x, y); } } diff --git a/java/src/com/android/inputmethod/keyboard/PointerTrackerQueue.java b/java/src/com/android/inputmethod/keyboard/PointerTrackerQueue.java index 928f3cdc1..b1e3576c0 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTrackerQueue.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTrackerQueue.java @@ -29,14 +29,13 @@ public class PointerTrackerQueue { if (mQueue.lastIndexOf(tracker) < 0) { return; } - LinkedList queue = mQueue; + final LinkedList queue = mQueue; int oldestPos = 0; for (PointerTracker t = queue.get(oldestPos); t != tracker; t = queue.get(oldestPos)) { if (t.isModifier()) { oldestPos++; } else { t.onUpEventForRelease(t.getLastX(), t.getLastY(), eventTime); - t.setAlreadyProcessed(); queue.remove(oldestPos); } } @@ -51,7 +50,6 @@ public class PointerTrackerQueue { if (t == tracker) continue; t.onUpEventForRelease(t.getLastX(), t.getLastY(), eventTime); - t.setAlreadyProcessed(); } mQueue.clear(); if (tracker != null) From 9c192e1b709ed34bbc5a00d7e8f14d50c8adc59f Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Tue, 19 Apr 2011 18:28:57 +0900 Subject: [PATCH 4/6] Shrink tab key width on web mode layout Bug: 4315046 Change-Id: I468ddf14d1f486d2c24cef56ed211ac9228cae43 --- java/res/xml/kbd_qwerty_row4.xml | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/java/res/xml/kbd_qwerty_row4.xml b/java/res/xml/kbd_qwerty_row4.xml index 0db011672..18ff608dd 100644 --- a/java/res/xml/kbd_qwerty_row4.xml +++ b/java/res/xml/kbd_qwerty_row4.xml @@ -35,29 +35,26 @@ latin:keyEdgeFlags="left" /> + - - + latin:keyWidth="10%p" /> + latin:keyLabel="." + latin:keyHintIcon="@drawable/hint_popup" + latin:popupCharacters="@string/alternates_for_punctuation" + latin:maxPopupKeyboardColumn="7" + latin:keyStyle="functionalKeyStyle" /> - Date: Tue, 19 Apr 2011 15:18:20 +0900 Subject: [PATCH 5/6] Refactor key preview code This change removes mOldPreviewKeyIndex from KeyboardView. Bug: 4298393 Change-Id: I832eb6deab7e078609973bf0b8be09f73db204d7 --- .../keyboard/KeyboardSwitcher.java | 2 +- .../inputmethod/keyboard/KeyboardView.java | 248 +++++++++--------- .../keyboard/LatinKeyboardView.java | 6 +- .../inputmethod/keyboard/PointerTracker.java | 54 ++-- .../keyboard/PointerTrackerQueue.java | 4 +- .../android/inputmethod/latin/LatinIME.java | 2 +- 6 files changed, 162 insertions(+), 154 deletions(-) diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index dd25b3427..a58ad2310 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java @@ -153,7 +153,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha makeSymbolsKeyboardIds(id.mMode, attribute); mCurrentId = id; - mInputView.setPreviewEnabled(mInputMethodService.getPopupOn()); + mInputView.setKeyPreviewEnabled(mInputMethodService.getPopupOn()); setKeyboard(getKeyboard(id)); } diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 42305a15e..eb09a455b 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -106,27 +106,24 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { // Main keyboard private Keyboard mKeyboard; - // Key preview popup + // Key preview private boolean mInForeground; private TextView mPreviewText; private int mPreviewTextSizeLarge; private final int[] mOffsetInWindow = new int[2]; - private int mOldPreviewKeyIndex = KeyDetector.NOT_A_KEY; - private boolean mShowPreview = true; - private int mPopupPreviewOffsetX; - private int mPopupPreviewOffsetY; - private int mPopupPreviewDisplayedY; + private boolean mShowKeyPreview = true; + private int mKeyPreviewDisplayedY; private final int mDelayBeforePreview; private final int mDelayAfterPreview; private ViewGroup mPreviewPlacer; - // Popup mini keyboard - private PopupWindow mMiniKeyboardPopup; + // Mini keyboard + private PopupWindow mMiniKeyboardWindow; private KeyboardView mMiniKeyboardView; private final WeakHashMap mMiniKeyboardCache = new WeakHashMap(); private int mMiniKeyboardOriginX; private int mMiniKeyboardOriginY; - private long mMiniKeyboardPopupTime; + private long mMiniKeyboardDisplayedTime; private int[] mWindowOffset; private final float mMiniKeyboardSlideAllowance; private int mMiniKeyboardTrackerId; @@ -186,8 +183,8 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { private final UIHandler mHandler = new UIHandler(); class UIHandler extends Handler { - private static final int MSG_POPUP_PREVIEW = 1; - private static final int MSG_DISMISS_PREVIEW = 2; + private static final int MSG_SHOW_KEY_PREVIEW = 1; + private static final int MSG_DISMISS_KEY_PREVIEW = 2; private static final int MSG_REPEAT_KEY = 3; private static final int MSG_LONGPRESS_KEY = 4; private static final int MSG_LONGPRESS_SHIFT_KEY = 5; @@ -197,10 +194,10 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { @Override public void handleMessage(Message msg) { switch (msg.what) { - case MSG_POPUP_PREVIEW: + case MSG_SHOW_KEY_PREVIEW: showKey(msg.arg1, (PointerTracker)msg.obj); break; - case MSG_DISMISS_PREVIEW: + case MSG_DISMISS_KEY_PREVIEW: mPreviewText.setVisibility(View.INVISIBLE); break; case MSG_REPEAT_KEY: { @@ -211,7 +208,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { } case MSG_LONGPRESS_KEY: { final PointerTracker tracker = (PointerTracker)msg.obj; - openPopupIfRequired(msg.arg1, tracker); + openMiniKeyboardIfRequired(msg.arg1, tracker); break; } case MSG_LONGPRESS_SHIFT_KEY: { @@ -222,26 +219,35 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { } } - public void popupPreview(long delay, int keyIndex, PointerTracker tracker) { - removeMessages(MSG_POPUP_PREVIEW); + public void showKeyPreview(long delay, int keyIndex, PointerTracker tracker) { + removeMessages(MSG_SHOW_KEY_PREVIEW); if (mPreviewText.getVisibility() == VISIBLE || delay == 0) { // Show right away, if it's already visible and finger is moving around showKey(keyIndex, tracker); } else { - sendMessageDelayed(obtainMessage(MSG_POPUP_PREVIEW, keyIndex, 0, tracker), delay); + sendMessageDelayed( + obtainMessage(MSG_SHOW_KEY_PREVIEW, keyIndex, 0, tracker), delay); } } - public void cancelPopupPreview() { - removeMessages(MSG_POPUP_PREVIEW); + public void cancelShowKeyPreview(PointerTracker tracker) { + removeMessages(MSG_SHOW_KEY_PREVIEW, tracker); } - public void dismissPreview(long delay) { - sendMessageDelayed(obtainMessage(MSG_DISMISS_PREVIEW), delay); + public void cancelAllShowKeyPreviews() { + removeMessages(MSG_SHOW_KEY_PREVIEW); } - public void cancelDismissPreview() { - removeMessages(MSG_DISMISS_PREVIEW); + public void dismissKeyPreview(long delay, PointerTracker tracker) { + 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); } public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker) { @@ -283,8 +289,8 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { public void cancelAllMessages() { cancelKeyTimers(); - cancelPopupPreview(); - cancelDismissPreview(); + cancelAllShowKeyPreviews(); + cancelAllDismissKeyPreviews(); } } @@ -364,18 +370,18 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { mPreviewText = (TextView) LayoutInflater.from(context).inflate(previewLayout, null); mPreviewTextSizeLarge = (int) res.getDimension(R.dimen.key_preview_text_size_large); } else { - mShowPreview = false; + mShowKeyPreview = false; } mDelayBeforePreview = res.getInteger(R.integer.config_delay_before_preview); mDelayAfterPreview = res.getInteger(R.integer.config_delay_after_preview); mKeyLabelHorizontalPadding = (int)res.getDimension( R.dimen.key_label_horizontal_alignment_padding); - mMiniKeyboardPopup = new PopupWindow(context); - mMiniKeyboardPopup.setBackgroundDrawable(null); - mMiniKeyboardPopup.setAnimationStyle(R.style.MiniKeyboardAnimation); + mMiniKeyboardWindow = new PopupWindow(context); + mMiniKeyboardWindow.setBackgroundDrawable(null); + mMiniKeyboardWindow.setAnimationStyle(R.style.MiniKeyboardAnimation); // Allow popup window to be drawn off the screen. - mMiniKeyboardPopup.setClippingEnabled(false); + mMiniKeyboardWindow.setClippingEnabled(false); mPaint = new Paint(); mPaint.setAntiAlias(true); @@ -485,11 +491,11 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { */ public void setKeyboard(Keyboard keyboard) { if (mKeyboard != null) { - dismissKeyPreview(); + dismissAllKeyPreviews(); } // Remove any pending messages, except dismissing preview mHandler.cancelKeyTimers(); - mHandler.cancelPopupPreview(); + mHandler.cancelAllShowKeyPreviews(); mKeyboard = keyboard; LatinImeLogger.onSetKeyboard(keyboard); mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(), @@ -545,33 +551,28 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { } /** - * Enables or disables the key feedback popup. This is a popup that shows a magnified + * Enables or disables the key feedback preview. This is a preview that shows a magnified * version of the depressed key. By default the preview is enabled. - * @param previewEnabled whether or not to enable the key feedback popup - * @see #isPreviewEnabled() + * @param previewEnabled whether or not to enable the key feedback preview + * @see #isKeyPreviewEnabled() */ - public void setPreviewEnabled(boolean previewEnabled) { - mShowPreview = previewEnabled; + public void setKeyPreviewEnabled(boolean previewEnabled) { + mShowKeyPreview = previewEnabled; } /** - * Returns the enabled state of the key feedback popup. - * @return whether or not the key feedback popup is enabled - * @see #setPreviewEnabled(boolean) + * Returns the enabled state of the key feedback preview + * @return whether or not the key feedback preview is enabled + * @see #setKeyPreviewEnabled(boolean) */ - public boolean isPreviewEnabled() { - return mShowPreview; + public boolean isKeyPreviewEnabled() { + return mShowKeyPreview; } public int getColorScheme() { return mColorScheme; } - public void setPopupOffset(int x, int y) { - mPopupPreviewOffsetX = x; - mPopupPreviewOffsetY = y; - } - /** * When enabled, calls to {@link KeyboardActionListener#onCodeInput} will include key * codes for adjacent keys. When disabled, only the primary key code will be @@ -879,23 +880,25 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { } // TODO: clean up this method. - private void dismissKeyPreview() { - for (PointerTracker tracker : mPointerTrackers) + private void dismissAllKeyPreviews() { + for (PointerTracker tracker : mPointerTrackers) { tracker.setReleasedKeyGraphics(); - showPreview(KeyDetector.NOT_A_KEY, null); + dismissKeyPreview(tracker); + } } @Override - public void showPreview(int keyIndex, PointerTracker tracker) { - int oldKeyIndex = mOldPreviewKeyIndex; - mOldPreviewKeyIndex = keyIndex; - if ((mShowPreview && oldKeyIndex != keyIndex) || mKeyboard.needSpacebarPreview(keyIndex)) { - if (keyIndex == KeyDetector.NOT_A_KEY) { - mHandler.cancelPopupPreview(); - mHandler.dismissPreview(mDelayAfterPreview); - } else if (tracker != null) { - mHandler.popupPreview(mDelayBeforePreview, keyIndex, tracker); - } + public void showKeyPreview(int keyIndex, PointerTracker tracker) { + if (mShowKeyPreview || mKeyboard.needSpacebarPreview(keyIndex)) { + mHandler.showKeyPreview(mDelayBeforePreview, keyIndex, tracker); + } + } + + @Override + public void dismissKeyPreview(PointerTracker tracker) { + if (mShowKeyPreview) { + mHandler.cancelShowKeyPreview(tracker); + mHandler.dismissKeyPreview(mDelayAfterPreview, tracker); } } @@ -924,7 +927,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { // 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) { - // If the preview popup has no parent view yet, add it to the ViewGroup which can place + // If the key preview has no parent view yet, add it to the ViewGroup which can place // key preview absolutely in SoftInputWindow. if (mPreviewText.getParent() == null) { addKeyPreview(mPreviewText); @@ -932,7 +935,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { final Key key = tracker.getKey(keyIndex); // If keyIndex is invalid or IME is already closed, we must not show key preview. - // Trying to show preview PopupWindow while root window is closed causes + // Trying to show key preview while root window is closed causes // WindowManager.BadTokenException. if (key == null || !mInForeground) return; @@ -956,37 +959,35 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { previewIcon != null ? previewIcon : key.getIcon()); mPreviewText.setText(null); } - mPreviewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - int popupWidth = Math.max(mPreviewText.getMeasuredWidth(), keyDrawWidth - + mPreviewText.getPaddingLeft() + mPreviewText.getPaddingRight()); - final int popupHeight = mPreviewHeight; - final ViewGroup.LayoutParams lp = mPreviewText.getLayoutParams(); - lp.width = popupWidth; - lp.height = popupHeight; - - int popupPreviewX = keyDrawX - (popupWidth - keyDrawWidth) / 2; - int popupPreviewY = key.mY - popupHeight + mPreviewOffset; - - mHandler.cancelDismissPreview(); - getLocationInWindow(mOffsetInWindow); - mOffsetInWindow[0] += mPopupPreviewOffsetX; // Offset may be zero - mOffsetInWindow[1] += mPopupPreviewOffsetY; // Offset may be zero - // Set the preview background state mPreviewText.getBackground().setState( key.mPopupCharacters != null ? LONG_PRESSABLE_STATE_SET : EMPTY_STATE_SET); - popupPreviewX += mOffsetInWindow[0]; - popupPreviewY += mOffsetInWindow[1]; + + mPreviewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), + MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + int previewWidth = Math.max(mPreviewText.getMeasuredWidth(), keyDrawWidth + + mPreviewText.getPaddingLeft() + mPreviewText.getPaddingRight()); + final int previewHeight = mPreviewHeight; + final ViewGroup.LayoutParams lp = mPreviewText.getLayoutParams(); + lp.width = previewWidth; + lp.height = previewHeight; + + int previewX = keyDrawX - (previewWidth - keyDrawWidth) / 2; + int previewY = key.mY - previewHeight + mPreviewOffset; + + mHandler.cancelAllDismissKeyPreviews(); + getLocationInWindow(mOffsetInWindow); + previewX += mOffsetInWindow[0]; + previewY += mOffsetInWindow[1]; // Place the key preview. // TODO: Adjust position of key previews which touch screen edges if (lp instanceof ViewGroup.MarginLayoutParams) { ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams)lp; - mlp.setMargins(popupPreviewX, popupPreviewY, 0, 0); + mlp.setMargins(previewX, previewY, 0, 0); } - // Record popup preview position to display mini-keyboard later at the same position - mPopupPreviewDisplayedY = popupPreviewY; + // Record key preview position to display mini-keyboard later at the same position + mKeyPreviewDisplayedY = previewY; mPreviewText.setVisibility(VISIBLE); } @@ -1021,18 +1022,18 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { invalidate(mInvalidatedKeyRect); } - private boolean openPopupIfRequired(int keyIndex, PointerTracker tracker) { + private boolean openMiniKeyboardIfRequired(int keyIndex, PointerTracker tracker) { // Check if we have a popup layout specified first. if (mPopupLayout == 0) { return false; } - Key popupKey = tracker.getKey(keyIndex); - if (popupKey == null) + Key parentKey = tracker.getKey(keyIndex); + if (parentKey == null) return false; - boolean result = onLongPress(popupKey, tracker); + boolean result = onLongPress(parentKey, tracker); if (result) { - dismissKeyPreview(); + dismissAllKeyPreviews(); mMiniKeyboardTrackerId = tracker.mPointerId; tracker.onLongPressed(mPointerQueue); } @@ -1051,7 +1052,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { mKeyboardActionListener.onCodeInput(Keyboard.CODE_CAPSLOCK, null, 0, 0); } - private View inflateMiniKeyboardContainer(Key popupKey) { + private View inflateMiniKeyboardContainer(Key parentKey) { final View container = LayoutInflater.from(getContext()).inflate(mPopupLayout, null); if (container == null) throw new NullPointerException(); @@ -1062,19 +1063,19 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { @Override public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) { mKeyboardActionListener.onCodeInput(primaryCode, keyCodes, x, y); - dismissPopupKeyboard(); + dismissMiniKeyboard(); } @Override public void onTextInput(CharSequence text) { mKeyboardActionListener.onTextInput(text); - dismissPopupKeyboard(); + dismissMiniKeyboard(); } @Override public void onCancelInput() { mKeyboardActionListener.onCancelInput(); - dismissPopupKeyboard(); + dismissMiniKeyboard(); } @Override @@ -1096,7 +1097,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { miniKeyboardView.mGestureDetector = null; final Keyboard keyboard = new MiniKeyboardBuilder(this, mKeyboard.getPopupKeyboardResId(), - popupKey).build(); + parentKey).build(); miniKeyboardView.setKeyboard(keyboard); container.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST), @@ -1119,20 +1120,20 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { } /** - * Called when a key is long pressed. By default this will open any popup keyboard associated + * Called when a key is long pressed. By default this will open any mini keyboard associated * with this key through the attributes popupLayout and popupCharacters. - * @param popupKey the key that was long pressed + * @param parentKey the key that was long pressed * @return true if the long press is handled, false otherwise. Subclasses should call the * method on the base class if the subclass doesn't wish to handle the call. */ - protected boolean onLongPress(Key popupKey, PointerTracker tracker) { - if (popupKey.mPopupCharacters == null) + protected boolean onLongPress(Key parentKey, PointerTracker tracker) { + if (parentKey.mPopupCharacters == null) return false; - View container = mMiniKeyboardCache.get(popupKey); + View container = mMiniKeyboardCache.get(parentKey); if (container == null) { - container = inflateMiniKeyboardContainer(popupKey); - mMiniKeyboardCache.put(popupKey, container); + container = inflateMiniKeyboardContainer(parentKey); + mMiniKeyboardCache.put(parentKey, container); } mMiniKeyboardView = (KeyboardView)container.findViewById(R.id.KeyboardView); final MiniKeyboard miniKeyboard = (MiniKeyboard)mMiniKeyboardView.getKeyboard(); @@ -1142,36 +1143,35 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { getLocationInWindow(mWindowOffset); } final int pointX = (mConfigShowMiniKeyboardAtTouchedPoint) ? tracker.getLastX() - : popupKey.mX + popupKey.mWidth / 2; - final int popupX = pointX - miniKeyboard.getDefaultCoordX() + : parentKey.mX + parentKey.mWidth / 2; + final int miniKeyboardX = pointX - miniKeyboard.getDefaultCoordX() - container.getPaddingLeft() + getPaddingLeft() + mWindowOffset[0]; - final int popupY = popupKey.mY - mKeyboard.getVerticalGap() + final int miniKeyboardY = parentKey.mY - mKeyboard.getVerticalGap() - (container.getMeasuredHeight() - container.getPaddingBottom()) + getPaddingTop() + mWindowOffset[1]; - final int x = popupX; - final int y = mShowPreview && isOneRowKeys(miniKeyboard.getKeys()) - ? mPopupPreviewDisplayedY : popupY; + final int x = miniKeyboardX; + final int y = mShowKeyPreview && isOneRowKeys(miniKeyboard.getKeys()) + ? mKeyPreviewDisplayedY : miniKeyboardY; mMiniKeyboardOriginX = x + container.getPaddingLeft() - mWindowOffset[0]; mMiniKeyboardOriginY = y + container.getPaddingTop() - mWindowOffset[1]; - mMiniKeyboardView.setPopupOffset(x, y); if (miniKeyboard.setShifted( mKeyboard == null ? false : mKeyboard.isShiftedOrShiftLocked())) { mMiniKeyboardView.invalidateAllKeys(); } // Mini keyboard needs no pop-up key preview displayed. - mMiniKeyboardView.setPreviewEnabled(false); - mMiniKeyboardPopup.setContentView(container); - mMiniKeyboardPopup.setWidth(container.getMeasuredWidth()); - mMiniKeyboardPopup.setHeight(container.getMeasuredHeight()); - mMiniKeyboardPopup.showAtLocation(this, Gravity.NO_GRAVITY, x, y); + mMiniKeyboardView.setKeyPreviewEnabled(false); + mMiniKeyboardWindow.setContentView(container); + mMiniKeyboardWindow.setWidth(container.getMeasuredWidth()); + mMiniKeyboardWindow.setHeight(container.getMeasuredHeight()); + mMiniKeyboardWindow.showAtLocation(this, Gravity.NO_GRAVITY, x, y); // Inject down event on the key to mini keyboard. final long eventTime = SystemClock.uptimeMillis(); - mMiniKeyboardPopupTime = eventTime; + mMiniKeyboardDisplayedTime = eventTime; final MotionEvent downEvent = generateMiniKeyboardMotionEvent(MotionEvent.ACTION_DOWN, - pointX, popupKey.mY + popupKey.mHeight / 2, eventTime); + pointX, parentKey.mY + parentKey.mHeight / 2, eventTime); mMiniKeyboardView.onTouchEvent(downEvent); downEvent.recycle(); @@ -1180,7 +1180,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { } private MotionEvent generateMiniKeyboardMotionEvent(int action, int x, int y, long eventTime) { - return MotionEvent.obtain(mMiniKeyboardPopupTime, eventTime, action, + return MotionEvent.obtain(mMiniKeyboardDisplayedTime, eventTime, action, x - mMiniKeyboardOriginX, y - mMiniKeyboardOriginY, 0); } @@ -1191,7 +1191,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { // Create pointer trackers until we can get 'id+1'-th tracker, if needed. for (int i = pointers.size(); i <= id; i++) { final PointerTracker tracker = - new PointerTracker(i, mHandler, mKeyDetector, this, getResources()); + new PointerTracker(i, this, mHandler, mKeyDetector, this); if (mKeyboard != null) tracker.setKeyboard(mKeyboard, mKeyHysteresisDistance); if (listener != null) @@ -1237,7 +1237,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { // TODO: Reconcile gesture detection and accessibility features. if (mMiniKeyboardView == null && !mIsAccessibilityEnabled && mGestureDetector != null && mGestureDetector.onTouchEvent(me)) { - dismissKeyPreview(); + dismissAllKeyPreviews(); mHandler.cancelKeyTimers(); return true; } @@ -1334,7 +1334,7 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { mPreviewText.setVisibility(View.GONE); mHandler.cancelAllMessages(); - dismissPopupKeyboard(); + dismissMiniKeyboard(); mDirtyRect.union(0, 0, getWidth(), getHeight()); mMiniKeyboardCache.clear(); requestLayout(); @@ -1351,9 +1351,9 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { closing(); } - private void dismissPopupKeyboard() { - if (mMiniKeyboardPopup.isShowing()) { - mMiniKeyboardPopup.dismiss(); + private void dismissMiniKeyboard() { + if (mMiniKeyboardWindow.isShowing()) { + mMiniKeyboardWindow.dismiss(); mMiniKeyboardView = null; mMiniKeyboardOriginX = 0; mMiniKeyboardOriginY = 0; @@ -1362,8 +1362,8 @@ public class KeyboardView extends View implements PointerTracker.UIProxy { } public boolean handleBack() { - if (mMiniKeyboardPopup.isShowing()) { - dismissPopupKeyboard(); + if (mMiniKeyboardWindow.isShowing()) { + dismissMiniKeyboard(); return true; } return false; diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java index d6c3723fd..912074515 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -55,14 +55,14 @@ public class LatinKeyboardView extends KeyboardView { } @Override - public void setPreviewEnabled(boolean previewEnabled) { + public void setKeyPreviewEnabled(boolean previewEnabled) { LatinKeyboard latinKeyboard = getLatinKeyboard(); if (latinKeyboard != null && (latinKeyboard.isPhoneKeyboard() || latinKeyboard.isNumberKeyboard())) { // Phone and number keyboard never shows popup preview (except language switch). - super.setPreviewEnabled(false); + super.setKeyPreviewEnabled(false); } else { - super.setPreviewEnabled(previewEnabled); + super.setKeyPreviewEnabled(previewEnabled); } } diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 800174c0e..64f2f9644 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -37,7 +37,8 @@ public class PointerTracker { public interface UIProxy { public void invalidateKey(Key key); - public void showPreview(int keyIndex, PointerTracker tracker); + public void showKeyPreview(int keyIndex, PointerTracker tracker); + public void dismissKeyPreview(PointerTracker tracker); public boolean hasDistinctMultitouch(); public boolean isAccessibilityEnabled(); } @@ -49,9 +50,7 @@ public class PointerTracker { private final int mLongPressKeyTimeout; private final int mLongPressShiftKeyTimeout; - // Miscellaneous constants - private static final int NOT_A_KEY = KeyDetector.NOT_A_KEY; - + private final KeyboardView mKeyboardView; private final UIProxy mProxy; private final UIHandler mHandler; private final KeyDetector mKeyDetector; @@ -107,11 +106,12 @@ public class PointerTracker { public void onSwipeDown() {} }; - public PointerTracker(int id, UIHandler handler, KeyDetector keyDetector, - UIProxy proxy, Resources res) { + public PointerTracker(int id, KeyboardView keyboardView, UIHandler handler, + KeyDetector keyDetector, UIProxy proxy) { if (proxy == null || handler == null || keyDetector == null) throw new NullPointerException(); mPointerId = id; + mKeyboardView = keyboardView; mProxy = proxy; mHandler = handler; mKeyDetector = keyDetector; @@ -119,6 +119,7 @@ public class PointerTracker { mKeyState = new PointerTrackerKeyState(keyDetector); mIsAccessibilityEnabled = proxy.isAccessibilityEnabled(); mHasDistinctMultitouch = proxy.hasDistinctMultitouch(); + final Resources res = mKeyboardView.getResources(); mConfigSlidingKeyInputEnabled = res.getBoolean(R.bool.config_sliding_key_input_enabled); mDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start); mLongPressKeyTimeout = res.getInteger(R.integer.config_long_press_key_timeout); @@ -420,11 +421,11 @@ public class PointerTracker { if (DEBUG_MODE) Log.w(TAG, String.format("onMoveEvent: sudden move is translated to " + "up[%d,%d]/down[%d,%d] events", lastX, lastY, x, y)); - onUpEventInternal(lastX, lastY, eventTime); + onUpEventInternal(lastX, lastY, eventTime, true); onDownEventInternal(x, y, eventTime); } else { mKeyAlreadyProcessed = true; - showKeyPreview(NOT_A_KEY); + dismissKeyPreview(); setReleasedKeyGraphics(oldKeyIndex); } return; @@ -442,7 +443,7 @@ public class PointerTracker { keyState.onMoveToNewKey(keyIndex, x, y); } else { mKeyAlreadyProcessed = true; - showKeyPreview(NOT_A_KEY); + dismissKeyPreview(); return; } } @@ -464,17 +465,21 @@ public class PointerTracker { } queue.remove(this); } - onUpEventInternal(x, y, eventTime); + onUpEventInternal(x, y, eventTime, true); } - public void onUpEventForRelease(int x, int y, long eventTime) { - onUpEventInternal(x, y, eventTime); + // Let this pointer tracker know that one of newer-than-this pointer trackers got an up event. + // This pointer tracker needs to keep the key top graphics "pressed", but needs to get a + // "virtual" up event. + public void onPhantomUpEvent(int x, int y, long eventTime) { + onUpEventInternal(x, y, eventTime, false); mKeyAlreadyProcessed = true; } - private void onUpEventInternal(int x, int y, long eventTime) { + private void onUpEventInternal(int x, int y, long eventTime, + boolean updateReleasedKeyGraphics) { mHandler.cancelKeyTimers(); - mHandler.cancelPopupPreview(); + mHandler.cancelShowKeyPreview(this); mIsInSlidingKeyInput = false; final PointerTrackerKeyState keyState = mKeyState; final int keyX, keyY; @@ -487,8 +492,9 @@ public class PointerTracker { keyY = keyState.getKeyY(); } final int keyIndex = keyState.onUpKey(keyX, keyY, eventTime); - showKeyPreview(NOT_A_KEY); - setReleasedKeyGraphics(keyIndex); + dismissKeyPreview(); + if (updateReleasedKeyGraphics) + setReleasedKeyGraphics(keyIndex); if (mKeyAlreadyProcessed) return; if (!mIsRepeatableKey) { @@ -513,8 +519,8 @@ public class PointerTracker { private void onCancelEventInternal() { mHandler.cancelKeyTimers(); - mHandler.cancelPopupPreview(); - showKeyPreview(NOT_A_KEY); + mHandler.cancelShowKeyPreview(this); + dismissKeyPreview(); setReleasedKeyGraphics(mKeyState.getKeyIndex()); mIsInSlidingKeyInput = false; } @@ -559,11 +565,13 @@ public class PointerTracker { // supported. On the other hand, if multi-touch is not supported, the modifier key should // be shown as preview. If accessibility is turned on, the modifier key should be shown as // preview. - if (mHasDistinctMultitouch && isModifier() && !mIsAccessibilityEnabled) { - mProxy.showPreview(NOT_A_KEY, this); - } else { - mProxy.showPreview(keyIndex, this); - } + if (mHasDistinctMultitouch && isModifier() && !mIsAccessibilityEnabled) + return; + mProxy.showKeyPreview(keyIndex, this); + } + + private void dismissKeyPreview() { + mProxy.dismissKeyPreview(this); } private void startLongPressTimer(int keyIndex) { diff --git a/java/src/com/android/inputmethod/keyboard/PointerTrackerQueue.java b/java/src/com/android/inputmethod/keyboard/PointerTrackerQueue.java index b1e3576c0..0a9410042 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTrackerQueue.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTrackerQueue.java @@ -35,7 +35,7 @@ public class PointerTrackerQueue { if (t.isModifier()) { oldestPos++; } else { - t.onUpEventForRelease(t.getLastX(), t.getLastY(), eventTime); + t.onPhantomUpEvent(t.getLastX(), t.getLastY(), eventTime); queue.remove(oldestPos); } } @@ -49,7 +49,7 @@ public class PointerTrackerQueue { for (PointerTracker t : mQueue) { if (t == tracker) continue; - t.onUpEventForRelease(t.getLastX(), t.getLastY(), eventTime); + t.onPhantomUpEvent(t.getLastX(), t.getLastY(), eventTime); } mQueue.clear(); if (tracker != null) diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 88b3ded8e..13ef4ffe8 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -592,7 +592,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final boolean accessibilityEnabled = mAccessibilityUtils.isAccessibilityEnabled(); - inputView.setPreviewEnabled(mPopupOn); + inputView.setKeyPreviewEnabled(mPopupOn); inputView.setProximityCorrectionEnabled(true); inputView.setAccessibilityEnabled(accessibilityEnabled); // If we just entered a text field, maybe it has some old text that requires correction From 4c981d3a40ea4445a5e728cde5f2fd5119692677 Mon Sep 17 00:00:00 2001 From: satok Date: Tue, 19 Apr 2011 13:58:42 +0900 Subject: [PATCH 6/6] Demote a word with mistyped space and missing space according to the length of each word Change-Id: Ifa4338c5f43b37e6bcd0700767ef2178189de3af --- native/src/unigram_dictionary.cpp | 55 ++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/native/src/unigram_dictionary.cpp b/native/src/unigram_dictionary.cpp index 8e82f1474..3832d473a 100644 --- a/native/src/unigram_dictionary.cpp +++ b/native/src/unigram_dictionary.cpp @@ -417,6 +417,54 @@ inline static void multiplyRate(const int rate, int *freq) { } } +inline static int calcFreqForSplitTwoWords( + const int typedLetterMultiplier, const int firstWordLength, + const int secondWordLength, const int firstFreq, const int secondFreq) { + if (firstWordLength == 0 || secondWordLength == 0) { + return 0; + } + const int firstDemotionRate = 100 - 100 / (firstWordLength + 1); + int tempFirstFreq = firstFreq; + multiplyRate(firstDemotionRate, &tempFirstFreq); + + const int secondDemotionRate = 100 - 100 / (secondWordLength + 1); + int tempSecondFreq = secondFreq; + multiplyRate(secondDemotionRate, &tempSecondFreq); + + const int totalLength = firstWordLength + secondWordLength; + + // Promote pairFreq with multiplying by 2, because the word length is the same as the typed + // length. + int totalFreq = tempFirstFreq + tempSecondFreq; + + // This is a workaround to try offsetting the not-enough-demotion which will be done in + // calcNormalizedScore in Utils.java. + // In calcNormalizedScore the score will be demoted by (1 - 1 / length) + // but we demoted only (1 - 1 / (length + 1)) so we will additionally adjust freq by + // (1 - 1 / length) / (1 - 1 / (length + 1)) = (1 - 1 / (length * length)) + const int normalizedScoreNotEnoughDemotionAdjustment = 100 - 100 / (totalLength * totalLength); + multiplyRate(normalizedScoreNotEnoughDemotionAdjustment, &totalFreq); + + // At this moment, totalFreq is calculated by the following formula: + // (firstFreq * (1 - 1 / (firstWordLength + 1)) + secondFreq * (1 - 1 / (secondWordLength + 1))) + // * (1 - 1 / totalLength) / (1 - 1 / (totalLength + 1)) + + for (int i = 0; i < totalLength; ++i) { + totalFreq *= typedLetterMultiplier; + } + + // This is another workaround to offset the demotion which will be done in + // calcNormalizedScore in Utils.java. + // In calcNormalizedScore the score will be demoted by (1 - 1 / length) so we have to promote + // the same amount because we already have adjusted the synthetic freq of this "missing or + // mistyped space" suggestion candidate above in this method. + const int normalizedScoreDemotionRateOffset = (100 + 100 / totalLength); + multiplyRate(normalizedScoreDemotionRateOffset, &totalFreq); + + multiplyRate(WORDS_WITH_MISSING_SPACE_CHARACTER_DEMOTION_RATE, &totalFreq); + return totalFreq; +} + bool UnigramDictionary::getSplitTwoWordsSuggestion(const int inputLength, const int firstWordStartPos, const int firstWordLength, const int secondWordStartPos, const int secondWordLength) { @@ -448,15 +496,12 @@ bool UnigramDictionary::getSplitTwoWordsSuggestion(const int inputLength, word[i] = mWord[i - firstWordLength - 1]; } - // Promote pairFreq with multiplying by 2, because the word length is the same as the typed - // length. - int pairFreq = firstFreq + secondFreq; - for (int i = 0; i < inputLength; ++i) pairFreq *= TYPED_LETTER_MULTIPLIER; + int pairFreq = calcFreqForSplitTwoWords( + TYPED_LETTER_MULTIPLIER, firstWordLength, secondWordLength, firstFreq, secondFreq); if (DEBUG_DICT) { LOGI("Missing space: %d, %d, %d, %d, %d", firstFreq, secondFreq, pairFreq, inputLength, TYPED_LETTER_MULTIPLIER); } - multiplyRate(WORDS_WITH_MISSING_SPACE_CHARACTER_DEMOTION_RATE, &pairFreq); addWord(word, newWordLength, pairFreq); return true; }