From cec1495071e0cf78b5941b07768062fbafe2dccd Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 27 Aug 2010 15:26:08 +0900 Subject: [PATCH 01/58] Disable long-press on shift and symbol keys Long-press on shift and symbol keys will conflict with press-and-hold these keys and press normal key (a.k.a. multi touch support). Bug: 2910379 Change-Id: I27007b55a30a3699bf63fd8f64d58c4b23d97d9f --- java/res/xml/kbd_phone.xml | 2 -- java/res/xml/kbd_phone_black.xml | 2 -- java/res/xml/kbd_phone_symbols.xml | 2 -- java/res/xml/kbd_phone_symbols_black.xml | 2 -- java/res/xml/kbd_qwerty.xml | 10 ---------- java/res/xml/kbd_qwerty_black.xml | 10 ---------- java/res/xml/kbd_symbols.xml | 2 -- java/res/xml/kbd_symbols_black.xml | 2 -- java/res/xml/kbd_symbols_shift.xml | 2 -- java/res/xml/kbd_symbols_shift_black.xml | 2 -- .../com/android/inputmethod/latin/LatinIME.java | 3 --- .../inputmethod/latin/LatinKeyboardView.java | 14 +------------- 12 files changed, 1 insertion(+), 52 deletions(-) diff --git a/java/res/xml/kbd_phone.xml b/java/res/xml/kbd_phone.xml index d2bcdac52..73d022fcb 100755 --- a/java/res/xml/kbd_phone.xml +++ b/java/res/xml/kbd_phone.xml @@ -50,8 +50,6 @@ diff --git a/java/res/xml/kbd_phone_black.xml b/java/res/xml/kbd_phone_black.xml index b7f9096bd..3738f2b68 100755 --- a/java/res/xml/kbd_phone_black.xml +++ b/java/res/xml/kbd_phone_black.xml @@ -50,8 +50,6 @@ diff --git a/java/res/xml/kbd_phone_symbols.xml b/java/res/xml/kbd_phone_symbols.xml index 9604664fa..9196df8da 100755 --- a/java/res/xml/kbd_phone_symbols.xml +++ b/java/res/xml/kbd_phone_symbols.xml @@ -55,8 +55,6 @@ Date: Fri, 27 Aug 2010 18:27:53 +0900 Subject: [PATCH 02/58] Show key preview instantaneously This change will display the key board preview instantaneously when the key is pressed. Dismissing the key preview will be delayed slightly after the key is released, as we do now. Because in multi touch mode, we should instantaneously change keyboard layout when modifier key, such as shit and symbol, is pressed. Change-Id: I49348d563ca0f40f5a0a236bdcd0bb07eedd599b --- .../latin/LatinKeyboardBaseView.java | 32 +++---------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index 4007c2b55..e3bad80d1 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -178,7 +178,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener /** Listener for {@link OnKeyboardActionListener}. */ private OnKeyboardActionListener mKeyboardActionListener; - private static final int DELAY_BEFORE_PREVIEW = 0; private static final int DELAY_AFTER_PREVIEW = 70; private static final int DEBOUNCE_TIME = 70; @@ -245,19 +244,15 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener 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_REPEAT_KEY = 3; - private static final int MSG_LOGPRESS_KEY = 4; + private static final int MSG_DISMISS_PREVIEW = 0; + private static final int MSG_REPEAT_KEY = 1; + private static final int MSG_LOGPRESS_KEY = 2; private boolean mInKeyRepeat; @Override public void handleMessage(Message msg) { switch (msg.what) { - case MSG_POPUP_PREVIEW: - showKey(msg.arg1); - break; case MSG_DISMISS_PREVIEW: mPreviewText.setVisibility(INVISIBLE); break; @@ -271,15 +266,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } } - public void popupPreview(int keyIndex, long delay) { - removeMessages(MSG_POPUP_PREVIEW); - sendMessageDelayed(obtainMessage(MSG_POPUP_PREVIEW, keyIndex, 0), delay); - } - - public void cancelPopupPreview() { - removeMessages(MSG_POPUP_PREVIEW); - } - public void dismissPreview(long delay) { sendMessageDelayed(obtainMessage(MSG_DISMISS_PREVIEW), delay); } @@ -318,7 +304,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener public void cancelAllMessages() { cancelKeyTimers(); - cancelPopupPreview(); cancelDismissPreview(); } }; @@ -613,7 +598,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } // Remove any pending messages, except dismissing preview mHandler.cancelKeyTimers(); - mHandler.cancelPopupPreview(); mKeyboard = keyboard; LatinImeLogger.onSetKeyboard(mKeyboard); List keys = mKeyboard.getKeys(); @@ -985,17 +969,11 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener // If key changed and preview is on ... if (oldKeyIndex != mCurrentKeyIndex && mShowPreview) { if (keyIndex == NOT_A_KEY) { - mHandler.cancelPopupPreview(); if (previewPopup.isShowing()) { mHandler.dismissPreview(DELAY_AFTER_PREVIEW); } } else { - if (previewPopup.isShowing() && mPreviewText.getVisibility() == VISIBLE) { - // Show right away, if it's already visible and finger is moving around - showKey(keyIndex); - } else { - mHandler.popupPreview(keyIndex, DELAY_BEFORE_PREVIEW); - } + showKey(keyIndex); } } } @@ -1372,7 +1350,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener int keyIndex = mProximityKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); boolean wasInKeyRepeat = mHandler.isInKeyRepeat(); mHandler.cancelKeyTimers(); - mHandler.cancelPopupPreview(); if (mDebouncer.isMinorMoveBounce(touchX, touchY, keyIndex, mCurrentKey)) { mDebouncer.updateTimeDebouncing(eventTime); } else { @@ -1395,7 +1372,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener private void onCancelEvent(int touchX, int touchY, long eventTime) { mHandler.cancelKeyTimers(); - mHandler.cancelPopupPreview(); dismissPopupKeyboard(); mAbortKey = true; showPreview(NOT_A_KEY); From 00dda50efda107daec8bfcafe2639603b655f183 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 27 Aug 2010 21:04:11 +0900 Subject: [PATCH 03/58] Revert "Show key preview instantaneously" This reverts commit 09f530e248a3caf0037ca89aa79a836385a03fab. Change-Id: I3106cd22cc1eac750f05bce26df6af3026dfaf86 --- .../latin/LatinKeyboardBaseView.java | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index e3bad80d1..4007c2b55 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -178,6 +178,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener /** Listener for {@link OnKeyboardActionListener}. */ private OnKeyboardActionListener mKeyboardActionListener; + private static final int DELAY_BEFORE_PREVIEW = 0; private static final int DELAY_AFTER_PREVIEW = 70; private static final int DEBOUNCE_TIME = 70; @@ -244,15 +245,19 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener UIHandler mHandler = new UIHandler(); class UIHandler extends Handler { - private static final int MSG_DISMISS_PREVIEW = 0; - private static final int MSG_REPEAT_KEY = 1; - private static final int MSG_LOGPRESS_KEY = 2; + private static final int MSG_POPUP_PREVIEW = 1; + private static final int MSG_DISMISS_PREVIEW = 2; + private static final int MSG_REPEAT_KEY = 3; + private static final int MSG_LOGPRESS_KEY = 4; private boolean mInKeyRepeat; @Override public void handleMessage(Message msg) { switch (msg.what) { + case MSG_POPUP_PREVIEW: + showKey(msg.arg1); + break; case MSG_DISMISS_PREVIEW: mPreviewText.setVisibility(INVISIBLE); break; @@ -266,6 +271,15 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } } + public void popupPreview(int keyIndex, long delay) { + removeMessages(MSG_POPUP_PREVIEW); + sendMessageDelayed(obtainMessage(MSG_POPUP_PREVIEW, keyIndex, 0), delay); + } + + public void cancelPopupPreview() { + removeMessages(MSG_POPUP_PREVIEW); + } + public void dismissPreview(long delay) { sendMessageDelayed(obtainMessage(MSG_DISMISS_PREVIEW), delay); } @@ -304,6 +318,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener public void cancelAllMessages() { cancelKeyTimers(); + cancelPopupPreview(); cancelDismissPreview(); } }; @@ -598,6 +613,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } // Remove any pending messages, except dismissing preview mHandler.cancelKeyTimers(); + mHandler.cancelPopupPreview(); mKeyboard = keyboard; LatinImeLogger.onSetKeyboard(mKeyboard); List keys = mKeyboard.getKeys(); @@ -969,11 +985,17 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener // If key changed and preview is on ... if (oldKeyIndex != mCurrentKeyIndex && mShowPreview) { if (keyIndex == NOT_A_KEY) { + mHandler.cancelPopupPreview(); if (previewPopup.isShowing()) { mHandler.dismissPreview(DELAY_AFTER_PREVIEW); } } else { - showKey(keyIndex); + if (previewPopup.isShowing() && mPreviewText.getVisibility() == VISIBLE) { + // Show right away, if it's already visible and finger is moving around + showKey(keyIndex); + } else { + mHandler.popupPreview(keyIndex, DELAY_BEFORE_PREVIEW); + } } } } @@ -1350,6 +1372,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener int keyIndex = mProximityKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); boolean wasInKeyRepeat = mHandler.isInKeyRepeat(); mHandler.cancelKeyTimers(); + mHandler.cancelPopupPreview(); if (mDebouncer.isMinorMoveBounce(touchX, touchY, keyIndex, mCurrentKey)) { mDebouncer.updateTimeDebouncing(eventTime); } else { @@ -1372,6 +1395,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener private void onCancelEvent(int touchX, int touchY, long eventTime) { mHandler.cancelKeyTimers(); + mHandler.cancelPopupPreview(); dismissPopupKeyboard(); mAbortKey = true; showPreview(NOT_A_KEY); From 06123e56912b5dcd7aca3d0c18c7ceb1f1cde573 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 27 Aug 2010 21:23:51 +0900 Subject: [PATCH 04/58] Don't re-allocate KeyDebouncer when keyboard is switched. This change also re-orders instance variables and eliminates unnecessary ones. Bug: 2910379 Change-Id: I6b2217f75738fada32a33f59f0f7adba5e99dd6e --- .../latin/LatinKeyboardBaseView.java | 188 +++++++++--------- 1 file changed, 94 insertions(+), 94 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index 4007c2b55..95794f7cc 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -17,6 +17,7 @@ package com.android.inputmethod.latin; import android.content.Context; +import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -61,6 +62,9 @@ import java.util.Map; * @attr ref R.styleable#LatinKeyboardBaseView_popupLayout */ public class LatinKeyboardBaseView extends View implements View.OnClickListener { + private static final boolean DEBUG = false; + + public static final int NOT_A_TOUCH_COORDINATE = -1; public interface OnKeyboardActionListener { @@ -139,29 +143,54 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener void swipeUp(); } - public static final int NOT_A_TOUCH_COORDINATE = -1; + // Timing constants + private static final int DELAY_BEFORE_PREVIEW = 0; + private static final int DELAY_AFTER_PREVIEW = 70; + private static final int REPEAT_INTERVAL = 50; // ~20 keys per second + private static final int REPEAT_START_DELAY = 400; + private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout(); + private static final int MULTITAP_INTERVAL = 800; // milliseconds + private static final int KEY_DEBOUNCE_TIME = 70; - private static final boolean DEBUG = false; + // Miscellaneous constants static final int NOT_A_KEY = -1; private static final int[] KEY_DELETE = { Keyboard.KEYCODE_DELETE }; private static final int[] LONG_PRESSABLE_STATE_SET = { android.R.attr.state_long_pressable }; - private Keyboard mKeyboard; - private int mCurrentKeyIndex = NOT_A_KEY; - private int mLabelTextSize; + // XML attribute private int mKeyTextSize; private int mKeyTextColor; - private float mShadowRadius; + private Typeface mKeyTextStyle = Typeface.DEFAULT; + private int mLabelTextSize; + private int mSymbolColorScheme = 0; private int mShadowColor; + private float mShadowRadius; + private Drawable mKeyBackground; private float mBackgroundDimAmount; + private int mVerticalCorrection; + private int mPreviewOffset; + private int mPreviewHeight; + private int mPopupLayout; + // Main keyboard + private Keyboard mKeyboard; + private Key[] mKeys; + + // Key preview popup + private final static boolean PREVIEW_CENTERED = false; private TextView mPreviewText; private PopupWindow mPreviewPopup; private int mPreviewTextSizeLarge; - private int mPreviewOffset; - private int mPreviewHeight; private int[] mOffsetInWindow; + private int mOldPreviewKeyIndex = NOT_A_KEY; + private boolean mShowPreview = true; + private boolean mShowTouchPoints = true; + private int mPopupPreviewX; + private int mPopupPreviewY; + private int mWindowY; + private final StringBuilder mPreviewLabel = new StringBuilder(1); + // Popup mini keyboard private PopupWindow mPopupKeyboard; private View mMiniKeyboardContainer; private LatinKeyboardBaseView mMiniKeyboard; @@ -171,78 +200,54 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener private int mMiniKeyboardOffsetY; private Map mMiniKeyboardCache; private int[] mWindowOffset; - private Key[] mKeys; - private Typeface mKeyTextStyle = Typeface.DEFAULT; - private int mSymbolColorScheme = 0; /** Listener for {@link OnKeyboardActionListener}. */ private OnKeyboardActionListener mKeyboardActionListener; - private static final int DELAY_BEFORE_PREVIEW = 0; - private static final int DELAY_AFTER_PREVIEW = 70; - private static final int DEBOUNCE_TIME = 70; - - private int mVerticalCorrection; - private ProximityKeyDetector mProximityKeyDetector = new ProximityKeyDetector(); - - private boolean mPreviewCentered = false; - private boolean mShowPreview = true; - private boolean mShowTouchPoints = true; - private int mPopupPreviewX; - private int mPopupPreviewY; - private int mWindowY; - - private Paint mPaint; - private Rect mPadding; - + private final KeyDebouncer mDebouncer = new KeyDebouncer(); + private final float mDebounceHysteresis; private int mCurrentKey = NOT_A_KEY; private int mStartX; private int mStartY; - private KeyDebouncer mDebouncer; + private final ProximityKeyDetector mProximityKeyDetector = new ProximityKeyDetector(); - private GestureDetector mGestureDetector; - private int mPopupX; - private int mPopupY; - private int mPopupLayout; private boolean mAbortKey; - private Key mInvalidatedKey; - private Rect mClipRegion = new Rect(0, 0, 0, 0); - private SwipeTracker mSwipeTracker = new SwipeTracker(); - private int mSwipeThreshold; - private boolean mDisambiguateSwipe; - - // Variables for dealing with multiple pointers - private int mOldPointerCount = 1; - private int mOldPointerX; - private int mOldPointerY; - - private Drawable mKeyBackground; - - private static final int REPEAT_INTERVAL = 50; // ~20 keys per second - private static final int REPEAT_START_DELAY = 400; - private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout(); // For multi-tap private int mLastSentIndex; private int mTapCount; private long mLastTapTime; private boolean mInMultiTap; - private static final int MULTITAP_INTERVAL = 800; // milliseconds - private StringBuilder mPreviewLabel = new StringBuilder(1); + // Variables for dealing with multiple pointers + private int mOldPointerCount = 1; + private int mOldPointerX; + private int mOldPointerY; + + // Swipe gesture detector + private final GestureDetector mGestureDetector; + private final SwipeTracker mSwipeTracker = new SwipeTracker(); + private final int mSwipeThreshold; + private final boolean mDisambiguateSwipe; + + // Drawing /** Whether the keyboard bitmap needs to be redrawn before it's blitted. **/ private boolean mDrawPending; /** The dirty region in the keyboard bitmap */ - private Rect mDirtyRect = new Rect(); + private final Rect mDirtyRect = new Rect(); /** The keyboard bitmap for faster updates */ private Bitmap mBuffer; /** Notes if the keyboard just changed, so that we could possibly reallocate the mBuffer. */ private boolean mKeyboardChanged; + private Key mInvalidatedKey; /** The canvas for the above mutable keyboard bitmap */ private Canvas mCanvas; + private final Paint mPaint; + private final Rect mPadding; + private final Rect mClipRegion = new Rect(0, 0, 0, 0); - UIHandler mHandler = new UIHandler(); + private final UIHandler mHandler = new UIHandler(); class UIHandler extends Handler { private static final int MSG_POPUP_PREVIEW = 1; @@ -324,8 +329,8 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener }; static class KeyDebouncer { - private final Key[] mKeys; - private final int mKeyDebounceThresholdSquared; + private Key[] mKeys; + private int mKeyDebounceThresholdSquared = -1; // for move de-bouncing private int mLastCodeX; @@ -339,7 +344,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener private long mLastMoveTime; private long mCurrentKeyTime; - KeyDebouncer(Key[] keys, float hysteresisPixel) { + public void setKeyboard(Key[] keys, float hysteresisPixel) { if (keys == null || hysteresisPixel < 1.0f) throw new IllegalArgumentException(); mKeys = keys; @@ -382,6 +387,8 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } public boolean isMinorMoveBounce(int x, int y, int newKey, int curKey) { + if (mKeys == null || mKeyDebounceThresholdSquared < 0) + throw new IllegalStateException("keyboard and/or hysteresis not set"); if (newKey == curKey) { return true; } else if (curKey >= 0 && curKey < mKeys.length) { @@ -424,7 +431,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } public boolean isMinorTimeBounce() { - return mCurrentKeyTime < mLastKeyTime && mCurrentKeyTime < DEBOUNCE_TIME + return mCurrentKeyTime < mLastKeyTime && mCurrentKeyTime < KEY_DEBOUNCE_TIME && mLastKey != NOT_A_KEY; } } @@ -516,15 +523,11 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } else { mShowPreview = false; } - mPreviewPopup.setTouchable(false); + mPopupParent = this; mPopupKeyboard = new PopupWindow(context); mPopupKeyboard.setBackgroundDrawable(null); - //mPopupKeyboard.setClippingEnabled(false); - - mPopupParent = this; - //mPredicting = true; mPaint = new Paint(); mPaint.setAntiAlias(true); @@ -536,19 +539,18 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener mMiniKeyboardCache = new HashMap(); mKeyBackground.getPadding(mPadding); - mSwipeThreshold = (int) (500 * getResources().getDisplayMetrics().density); + final Resources res = getResources(); + mSwipeThreshold = (int) (500 * res.getDisplayMetrics().density); // TODO: Refer frameworks/base/core/res/res/values/config.xml - mDisambiguateSwipe = getResources().getBoolean(R.bool.config_swipeDisambiguation); + mDisambiguateSwipe = res.getBoolean(R.bool.config_swipeDisambiguation); + mDebounceHysteresis = res.getDimension(R.dimen.key_debounce_hysteresis_distance); resetMultiTap(); - initGestureDetector(); - } - private void initGestureDetector() { GestureDetector.SimpleOnGestureListener listener = new GestureDetector.SimpleOnGestureListener() { @Override - public boolean onFling(MotionEvent me1, MotionEvent me2, - float velocityX, float velocityY) { + public boolean onFling(MotionEvent me1, MotionEvent me2, float velocityX, + float velocityY) { final float absX = Math.abs(velocityX); final float absY = Math.abs(velocityY); float deltaX = me2.getX() - me1.getX(); @@ -619,6 +621,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener List keys = mKeyboard.getKeys(); mKeys = keys.toArray(new Key[keys.size()]); mProximityKeyDetector.setKeyboard(keyboard, mKeys); + mDebouncer.setKeyboard(mKeys, mDebounceHysteresis); requestLayout(); // Hint to reallocate the buffer if the size changed mKeyboardChanged = true; @@ -773,10 +776,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } if (dimensionSum < 0 || length == 0) return; mProximityKeyDetector.setProximityThreshold((int) (dimensionSum * 1.4f / length)); - - final float hysteresisPixel = getContext().getResources() - .getDimension(R.dimen.key_debounce_hysteresis_distance); - mDebouncer = new KeyDebouncer(keys, hysteresisPixel); } @Override @@ -966,24 +965,26 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } private void showPreview(int keyIndex) { - int oldKeyIndex = mCurrentKeyIndex; - final PopupWindow previewPopup = mPreviewPopup; + int oldKeyIndex = mOldPreviewKeyIndex; + mOldPreviewKeyIndex = keyIndex; - mCurrentKeyIndex = keyIndex; // Release the old key and press the new key final Key[] keys = mKeys; - if (oldKeyIndex != mCurrentKeyIndex) { + if (oldKeyIndex != keyIndex) { if (oldKeyIndex != NOT_A_KEY && keys.length > oldKeyIndex) { - keys[oldKeyIndex].onReleased(mCurrentKeyIndex == NOT_A_KEY); + // if new key index is not a key, old key was just released inside of the key. + final boolean inside = (keyIndex == NOT_A_KEY); + keys[oldKeyIndex].onReleased(inside); invalidateKey(oldKeyIndex); } - if (mCurrentKeyIndex != NOT_A_KEY && keys.length > mCurrentKeyIndex) { - keys[mCurrentKeyIndex].onPressed(); - invalidateKey(mCurrentKeyIndex); + if (keyIndex != NOT_A_KEY && keys.length > keyIndex) { + keys[keyIndex].onPressed(); + invalidateKey(keyIndex); } } // If key changed and preview is on ... - if (oldKeyIndex != mCurrentKeyIndex && mShowPreview) { + if (oldKeyIndex != keyIndex && mShowPreview) { + final PopupWindow previewPopup = mPreviewPopup; if (keyIndex == NOT_A_KEY) { mHandler.cancelPopupPreview(); if (previewPopup.isShowing()) { @@ -1030,13 +1031,13 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener lp.width = popupWidth; lp.height = popupHeight; } - if (!mPreviewCentered) { - mPopupPreviewX = key.x - mPreviewText.getPaddingLeft() + getPaddingLeft(); - mPopupPreviewY = key.y - popupHeight + mPreviewOffset; - } else { + if (PREVIEW_CENTERED) { // TODO: Fix this if centering is brought back mPopupPreviewX = 160 - mPreviewText.getMeasuredWidth() / 2; mPopupPreviewY = - mPreviewText.getMeasuredHeight(); + } else { + mPopupPreviewX = key.x - mPreviewText.getPaddingLeft() + getPaddingLeft(); + mPopupPreviewY = key.y - popupHeight + mPreviewOffset; } mHandler.cancelDismissPreview(); if (mOffsetInWindow == null) { @@ -1147,8 +1148,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener mMiniKeyboardContainer = inflater.inflate(mPopupLayout, null); mMiniKeyboard = (LatinKeyboardBaseView) mMiniKeyboardContainer.findViewById( R.id.LatinKeyboardBaseView); - View closeButton = mMiniKeyboardContainer.findViewById( - R.id.closeButton); + View closeButton = mMiniKeyboardContainer.findViewById(R.id.closeButton); if (closeButton != null) closeButton.setOnClickListener(this); mMiniKeyboard.setOnKeyboardActionListener(new OnKeyboardActionListener() { public void onKey(int primaryCode, int[] keyCodes, int x, int y) { @@ -1195,12 +1195,12 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener mWindowOffset = new int[2]; getLocationInWindow(mWindowOffset); } - mPopupX = popupKey.x + getPaddingLeft(); - mPopupY = popupKey.y + getPaddingTop(); - mPopupX = mPopupX + popupKey.width - mMiniKeyboardContainer.getMeasuredWidth(); - mPopupY = mPopupY - mMiniKeyboardContainer.getMeasuredHeight(); - final int x = mPopupX + mMiniKeyboardContainer.getPaddingRight() + mWindowOffset[0]; - final int y = mPopupY + mMiniKeyboardContainer.getPaddingBottom() + mWindowOffset[1]; + int popupX = popupKey.x + getPaddingLeft(); + int popupY = popupKey.y + getPaddingTop(); + popupX = popupX + popupKey.width - mMiniKeyboardContainer.getMeasuredWidth(); + popupY = popupY - mMiniKeyboardContainer.getMeasuredHeight(); + final int x = popupX + mMiniKeyboardContainer.getPaddingRight() + mWindowOffset[0]; + final int y = popupY + mMiniKeyboardContainer.getPaddingBottom() + mWindowOffset[1]; mMiniKeyboard.setPopupOffset(x < 0 ? 0 : x, y); mMiniKeyboard.setShifted(isShifted()); mPopupKeyboard.setContentView(mMiniKeyboardContainer); From 22708e66384e5c633e260fb9789d26f3fdb6e6cc Mon Sep 17 00:00:00 2001 From: Eric Fischer Date: Fri, 27 Aug 2010 17:18:02 -0700 Subject: [PATCH 05/58] Import revised translations. DO NOT MERGE Change-Id: I968a456446b782b1e20cad0b6d3c82a8aa9a663a --- java/res/values-cs/strings.xml | 4 ++++ java/res/values-da/strings.xml | 4 ++++ java/res/values-de/strings.xml | 4 ++++ java/res/values-el/strings.xml | 4 ++++ java/res/values-es-rUS/strings.xml | 4 ++++ java/res/values-es/strings.xml | 4 ++++ java/res/values-fr/strings.xml | 4 ++++ java/res/values-it/strings.xml | 4 ++++ java/res/values-ja/strings.xml | 4 ++++ java/res/values-ko/strings.xml | 4 ++++ java/res/values-nb/strings.xml | 4 ++++ java/res/values-nl/strings.xml | 4 ++++ java/res/values-pl/strings.xml | 4 ++++ java/res/values-pt-rPT/strings.xml | 4 ++++ java/res/values-pt/strings.xml | 4 ++++ java/res/values-ru/strings.xml | 4 ++++ java/res/values-sv/strings.xml | 4 ++++ java/res/values-tr/strings.xml | 4 ++++ java/res/values-zh-rCN/strings.xml | 4 ++++ java/res/values-zh-rTW/strings.xml | 4 ++++ 20 files changed, 80 insertions(+) diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml index 798d0807e..55f4a661d 100644 --- a/java/res/values-cs/strings.xml +++ b/java/res/values-cs/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml index 9c525a3e0..dbadd930b 100644 --- a/java/res/values-da/strings.xml +++ b/java/res/values-da/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml index 047b11420..7147adca3 100644 --- a/java/res/values-de/strings.xml +++ b/java/res/values-de/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml index ef79ea097..b53301c3f 100644 --- a/java/res/values-el/strings.xml +++ b/java/res/values-el/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml index 8cf11dfa2..9244e71f9 100644 --- a/java/res/values-es-rUS/strings.xml +++ b/java/res/values-es-rUS/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml index 6d3823918..4f9d45b3a 100644 --- a/java/res/values-es/strings.xml +++ b/java/res/values-es/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml index 544789b2d..a3e419594 100644 --- a/java/res/values-fr/strings.xml +++ b/java/res/values-fr/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml index 486a60ef8..7c42fa467 100644 --- a/java/res/values-it/strings.xml +++ b/java/res/values-it/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml index cfa5a9746..06923899d 100644 --- a/java/res/values-ja/strings.xml +++ b/java/res/values-ja/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml index 8fd4e63e8..9dfd3efa5 100644 --- a/java/res/values-ko/strings.xml +++ b/java/res/values-ko/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml index 7fbac9bdd..debc644f9 100644 --- a/java/res/values-nb/strings.xml +++ b/java/res/values-nb/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml index b4b0ab29f..542a1846a 100644 --- a/java/res/values-nl/strings.xml +++ b/java/res/values-nl/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml index 8ca1650cd..ac9d06f29 100644 --- a/java/res/values-pl/strings.xml +++ b/java/res/values-pl/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml index 5fbff0fe7..4c6a2ceb0 100644 --- a/java/res/values-pt-rPT/strings.xml +++ b/java/res/values-pt-rPT/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml index 70288efd4..14d519921 100644 --- a/java/res/values-pt/strings.xml +++ b/java/res/values-pt/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml index 1898d27eb..448c8e2ad 100644 --- a/java/res/values-ru/strings.xml +++ b/java/res/values-ru/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml index 49359e8b9..2df9c696f 100644 --- a/java/res/values-sv/strings.xml +++ b/java/res/values-sv/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml index 73ad111f3..fb48fb02b 100644 --- a/java/res/values-tr/strings.xml +++ b/java/res/values-tr/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml index 046d1d664..d38490c4d 100644 --- a/java/res/values-zh-rCN/strings.xml +++ b/java/res/values-zh-rCN/strings.xml @@ -140,4 +140,8 @@ + + + + diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml index 182f71192..6a6f37efb 100644 --- a/java/res/values-zh-rTW/strings.xml +++ b/java/res/values-zh-rTW/strings.xml @@ -140,4 +140,8 @@ + + + + From cb6221257a2f4025c91de4d65f5591e6563c54ce Mon Sep 17 00:00:00 2001 From: satok Date: Mon, 30 Aug 2010 14:56:49 +0900 Subject: [PATCH 06/58] DO NOT MERGE. Remove a preference for bigram suggestion Change-Id: I1a9142d988352abf88da5eefe1d02596c7fc2beb --- java/res/xml/prefs.xml | 9 --------- java/src/com/android/inputmethod/latin/LatinIME.java | 8 +++++--- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml index 11cc3ac42..c48b80a5d 100644 --- a/java/res/xml/prefs.xml +++ b/java/res/xml/prefs.xml @@ -105,15 +105,6 @@ android:defaultValue="@bool/enable_autocorrect" android:dependency="show_suggestions" /> - - Date: Mon, 30 Aug 2010 14:53:01 +0900 Subject: [PATCH 07/58] Remove Log functions from Gingerbread Change-Id: I0ab19726a6bfaf14b42c05903f38dfb74cbd0d37 --- java/res/values/strings.xml | 6 +- java/res/xml/prefs.xml | 6 - .../inputmethod/latin/LatinIMESettings.java | 12 +- .../inputmethod/latin/LatinIMEUtil.java | 3 - .../inputmethod/latin/LatinImeLogger.java | 857 +----------------- 5 files changed, 11 insertions(+), 873 deletions(-) diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml index c72cba7e6..ef5127e9d 100644 --- a/java/res/values/strings.xml +++ b/java/res/values/strings.xml @@ -332,9 +332,9 @@ Dictionary available - + Enable user feedback - + Help improve this input method editor by automatically sending usage statistics and crash reports to Google. Keyboard Theme @@ -357,8 +357,6 @@ 3 - Debug (Temporary) - keyboard voice diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml index c48b80a5d..c4ffeefce 100644 --- a/java/res/xml/prefs.xml +++ b/java/res/xml/prefs.xml @@ -107,10 +107,4 @@ /> - diff --git a/java/src/com/android/inputmethod/latin/LatinIMESettings.java b/java/src/com/android/inputmethod/latin/LatinIMESettings.java index 806ef00af..565c1e6e8 100644 --- a/java/src/com/android/inputmethod/latin/LatinIMESettings.java +++ b/java/src/com/android/inputmethod/latin/LatinIMESettings.java @@ -76,7 +76,7 @@ public class LatinIMESettings extends PreferenceActivity mLogger = VoiceInputLogger.getLogger(this); mDebugMode = (CheckBoxPreference) findPreference(DEBUG_MODE_KEY); - updateDebugMode(mDebugMode.isChecked()); + updateDebugMode(); } @Override @@ -111,16 +111,20 @@ public class LatinIMESettings extends PreferenceActivity showVoiceConfirmation(); } } else if (key.equals(DEBUG_MODE_KEY)) { - updateDebugMode(prefs.getBoolean(DEBUG_MODE_KEY, false)); + if (mDebugMode != null) { + mDebugMode.setChecked(prefs.getBoolean(DEBUG_MODE_KEY, false)); + updateDebugMode(); + } } mVoiceOn = !(prefs.getString(VOICE_SETTINGS_KEY, mVoiceModeOff).equals(mVoiceModeOff)); updateVoiceModeSummary(); } - private void updateDebugMode(boolean isDebugMode) { + private void updateDebugMode() { if (mDebugMode == null) { return; } + boolean isDebugMode = mDebugMode.isChecked(); String version = ""; try { PackageInfo info = getPackageManager().getPackageInfo(getPackageName(), 0); @@ -134,8 +138,8 @@ public class LatinIMESettings extends PreferenceActivity mDebugMode.setSummary(""); } else { mDebugMode.setEnabled(true); - mDebugMode.setTitle(getResources().getString(R.string.prefs_debug_mode)); mDebugMode.setSummary(version); + mDebugMode.setSummary(""); } } diff --git a/java/src/com/android/inputmethod/latin/LatinIMEUtil.java b/java/src/com/android/inputmethod/latin/LatinIMEUtil.java index 838b4fe10..93ad4072d 100644 --- a/java/src/com/android/inputmethod/latin/LatinIMEUtil.java +++ b/java/src/com/android/inputmethod/latin/LatinIMEUtil.java @@ -54,9 +54,6 @@ public class LatinIMEUtil { } public boolean tryGCOrWait(String metaData, Throwable t) { - if (LatinImeLogger.sDBG) { - Log.d(TAG, "Encountered Exception or Error. Try GC."); - } if (mGCTryCount == 0) { System.gc(); } diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java index 716f7207f..007d0ccdd 100644 --- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java +++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java @@ -20,907 +20,52 @@ import com.android.inputmethod.latin.Dictionary.DataType; import android.content.Context; import android.content.SharedPreferences; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager.NameNotFoundException; import android.inputmethodservice.Keyboard; -import android.os.AsyncTask; -import android.os.DropBoxManager; -import android.preference.PreferenceManager; -import android.text.TextUtils; -import android.text.format.DateUtils; -import android.util.Log; -import android.util.Pair; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; import java.util.List; public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChangeListener { - private static final String TAG = "LatinIMELogs"; - public static boolean sDBG = false; - private static boolean sPRINTLOGGING = false; - // SUPPRESS_EXCEPTION should be true when released to public. - private static final boolean SUPPRESS_EXCEPTION = true; - // DEFAULT_LOG_ENABLED should be false when released to public. - private static final boolean DEFAULT_LOG_ENABLED = false; - - private static final long MINIMUMSENDINTERVAL = 300 * DateUtils.SECOND_IN_MILLIS; // 300 sec - private static final long MINIMUMCOUNTINTERVAL = 20 * DateUtils.SECOND_IN_MILLIS; // 20 sec - private static final long MINIMUMSENDSIZE = 40; - private static final char SEPARATER = ';'; - private static final char NULL_CHAR = '\uFFFC'; - private static final int EXCEPTION_MAX_LENGTH = 400; - private static final int INVALID_COORDINATE = -2; - - // ID_MANUALSUGGESTION has been replaced by ID_MANUALSUGGESTION_WITH_DATATYPE - // private static final int ID_MANUALSUGGESTION = 0; - // private static final int ID_AUTOSUGGESTIONCANCELLED = 1; - // private static final int ID_AUTOSUGGESTION = 2; - private static final int ID_INPUT_COUNT = 3; - private static final int ID_DELETE_COUNT = 4; - private static final int ID_WORD_COUNT = 5; - private static final int ID_ACTUAL_CHAR_COUNT = 6; - private static final int ID_THEME_ID = 7; - private static final int ID_SETTING_AUTO_COMPLETE = 8; - private static final int ID_VERSION = 9; - private static final int ID_EXCEPTION = 10; - private static final int ID_MANUALSUGGESTIONCOUNT = 11; - private static final int ID_AUTOSUGGESTIONCANCELLEDCOUNT = 12; - private static final int ID_AUTOSUGGESTIONCOUNT = 13; - private static final int ID_LANGUAGES = 14; - private static final int ID_MANUALSUGGESTION_WITH_DATATYPE = 15; - private static final int ID_AUTOSUGGESTIONCANCELLED_WITH_COORDINATES = 16; - private static final int ID_AUTOSUGGESTION_WITH_COORDINATES = 17; - - private static final String PREF_ENABLE_LOG = "enable_logging"; - private static final String PREF_DEBUG_MODE = "debug_mode"; - private static final String PREF_AUTO_COMPLETE = "auto_complete"; - - public static boolean sLogEnabled = true; - /* package */ static LatinImeLogger sLatinImeLogger = new LatinImeLogger(); - // Store the last auto suggested word. - // This is required for a cancellation log of auto suggestion of that word. - /* package */ static String sLastAutoSuggestBefore; - /* package */ static String sLastAutoSuggestAfter; - /* package */ static String sLastAutoSuggestSeparator; - private static int[] sLastAutoSuggestXCoordinates; - private static int[] sLastAutoSuggestYCoordinates; - // This value holds MAIN, USER, AUTO, etc... - private static int sLastAutoSuggestDicTypeId; - // This value holds 0 (= unigram), 1 (= bigram) etc... - private static int sLastAutoSuggestDataType; - private static HashMap> sSuggestDicMap - = new HashMap>(); - private static String[] sPreviousWords; - private static DebugKeyEnabler sDebugKeyEnabler = new DebugKeyEnabler(); - private static int sKeyboardWidth = 0; - private static int sKeyboardHeight = 0; - - private ArrayList mLogBuffer = null; - private ArrayList mPrivacyLogBuffer = null; - /* package */ RingCharBuffer mRingCharBuffer = null; - - private Context mContext = null; - private DropBoxManager mDropBox = null; - private AddTextToDropBoxTask mAddTextToDropBoxTask; - private long mLastTimeActive; - private long mLastTimeSend; - private long mLastTimeCountEntry; - - private String mThemeId; - private String mSelectedLanguages; - private String mCurrentLanguage; - private int mDeleteCount; - private int mInputCount; - private int mWordCount; - private int[] mAutoSuggestCountPerDic = new int[Suggest.DIC_TYPE_LAST_ID + 1]; - private int[] mManualSuggestCountPerDic = new int[Suggest.DIC_TYPE_LAST_ID + 1]; - private int[] mAutoCancelledCountPerDic = new int[Suggest.DIC_TYPE_LAST_ID + 1]; - private int mActualCharCount; - - private static class LogEntry implements Comparable { - public final int mTag; - public final String[] mData; - public long mTime; - - public LogEntry (long time, int tag, String[] data) { - mTag = tag; - mTime = time; - mData = data; - } - - public int compareTo(LogEntry log2) { - if (mData.length == 0 && log2.mData.length == 0) { - return 0; - } else if (mData.length == 0) { - return 1; - } else if (log2.mData.length == 0) { - return -1; - } - return log2.mData[0].compareTo(mData[0]); - } - } - - private class AddTextToDropBoxTask extends AsyncTask { - private final DropBoxManager mDropBox; - private final long mTime; - private final String mData; - public AddTextToDropBoxTask(DropBoxManager db, long time, String data) { - mDropBox = db; - mTime = time; - mData = data; - } - @Override - protected Void doInBackground(Void... params) { - if (sPRINTLOGGING) { - Log.d(TAG, "Commit log: " + mData); - } - mDropBox.addText(TAG, mData); - return null; - } - @Override - protected void onPostExecute(Void v) { - mLastTimeSend = mTime; - } - } - - private void initInternal(Context context) { - mContext = context; - mDropBox = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE); - mLastTimeSend = System.currentTimeMillis(); - mLastTimeActive = mLastTimeSend; - mLastTimeCountEntry = mLastTimeSend; - mDeleteCount = 0; - mInputCount = 0; - mWordCount = 0; - mActualCharCount = 0; - Arrays.fill(mAutoSuggestCountPerDic, 0); - Arrays.fill(mManualSuggestCountPerDic, 0); - Arrays.fill(mAutoCancelledCountPerDic, 0); - mLogBuffer = new ArrayList(); - mPrivacyLogBuffer = new ArrayList(); - mRingCharBuffer = new RingCharBuffer(context); - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - sLogEnabled = prefs.getBoolean(PREF_ENABLE_LOG, DEFAULT_LOG_ENABLED); - mThemeId = prefs.getString(KeyboardSwitcher.PREF_KEYBOARD_LAYOUT, - KeyboardSwitcher.DEFAULT_LAYOUT_ID); - mSelectedLanguages = prefs.getString(LatinIME.PREF_SELECTED_LANGUAGES, ""); - mCurrentLanguage = prefs.getString(LatinIME.PREF_INPUT_LANGUAGE, ""); - sPRINTLOGGING = prefs.getBoolean(PREF_DEBUG_MODE, sPRINTLOGGING); - sDBG = sPRINTLOGGING; - prefs.registerOnSharedPreferenceChangeListener(this); - } - - /** - * Clear all logged data - */ - private void reset() { - mDeleteCount = 0; - mInputCount = 0; - mWordCount = 0; - mActualCharCount = 0; - Arrays.fill(mAutoSuggestCountPerDic, 0); - Arrays.fill(mManualSuggestCountPerDic, 0); - Arrays.fill(mAutoCancelledCountPerDic, 0); - mLogBuffer.clear(); - mPrivacyLogBuffer.clear(); - } - - public void destroy() { - LatinIMEUtil.cancelTask(mAddTextToDropBoxTask, false); - } - - /** - * Check if the input string is safe as an entry or not. - */ - private static boolean checkStringDataSafe(String s) { - if (sDBG) { - Log.d(TAG, "Check String safety: " + s); - } - for (int i = 0; i < s.length(); ++i) { - if (Character.isDigit(s.charAt(i))) { - return false; - } - } - return true; - } - - private void addCountEntry(long time) { - if (sPRINTLOGGING) { - Log.d(TAG, "Log counts. (4)"); - } - mLogBuffer.add(new LogEntry (time, ID_DELETE_COUNT, - new String[] {String.valueOf(mDeleteCount)})); - mLogBuffer.add(new LogEntry (time, ID_INPUT_COUNT, - new String[] {String.valueOf(mInputCount)})); - mLogBuffer.add(new LogEntry (time, ID_WORD_COUNT, - new String[] {String.valueOf(mWordCount)})); - mLogBuffer.add(new LogEntry (time, ID_ACTUAL_CHAR_COUNT, - new String[] {String.valueOf(mActualCharCount)})); - mDeleteCount = 0; - mInputCount = 0; - mWordCount = 0; - mActualCharCount = 0; - mLastTimeCountEntry = time; - } - - private void addSuggestionCountEntry(long time) { - if (sPRINTLOGGING) { - Log.d(TAG, "log suggest counts. (1)"); - } - String[] s = new String[mAutoSuggestCountPerDic.length]; - for (int i = 0; i < s.length; ++i) { - s[i] = String.valueOf(mAutoSuggestCountPerDic[i]); - } - mLogBuffer.add(new LogEntry(time, ID_AUTOSUGGESTIONCOUNT, s)); - - s = new String[mAutoCancelledCountPerDic.length]; - for (int i = 0; i < s.length; ++i) { - s[i] = String.valueOf(mAutoCancelledCountPerDic[i]); - } - mLogBuffer.add(new LogEntry(time, ID_AUTOSUGGESTIONCANCELLEDCOUNT, s)); - - s = new String[mManualSuggestCountPerDic.length]; - for (int i = 0; i < s.length; ++i) { - s[i] = String.valueOf(mManualSuggestCountPerDic[i]); - } - mLogBuffer.add(new LogEntry(time, ID_MANUALSUGGESTIONCOUNT, s)); - - Arrays.fill(mAutoSuggestCountPerDic, 0); - Arrays.fill(mManualSuggestCountPerDic, 0); - Arrays.fill(mAutoCancelledCountPerDic, 0); - } - - private void addThemeIdEntry(long time) { - if (sPRINTLOGGING) { - Log.d(TAG, "Log theme Id. (1)"); - } - // TODO: Not to convert theme ID here. Currently "2" is treated as "6" in a log server. - if (mThemeId.equals("2")) { - mThemeId = "6"; - } else if (mThemeId.equals("3")) { - mThemeId = "7"; - } - mLogBuffer.add(new LogEntry (time, ID_THEME_ID, - new String[] {mThemeId})); - } - - private void addLanguagesEntry(long time) { - if (sPRINTLOGGING) { - Log.d(TAG, "Log language settings. (1)"); - } - // CurrentLanguage and SelectedLanguages will be blank if user doesn't use multi-language - // switching. - if (TextUtils.isEmpty(mCurrentLanguage)) { - mCurrentLanguage = mContext.getResources().getConfiguration().locale.toString(); - } - mLogBuffer.add(new LogEntry (time, ID_LANGUAGES, - new String[] {mCurrentLanguage , mSelectedLanguages})); - } - - private void addSettingsEntry(long time) { - if (sPRINTLOGGING) { - Log.d(TAG, "Log settings. (1)"); - } - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); - mLogBuffer.add(new LogEntry (time, ID_SETTING_AUTO_COMPLETE, - new String[] {String.valueOf(prefs.getBoolean(PREF_AUTO_COMPLETE, - mContext.getResources().getBoolean(R.bool.enable_autocorrect)))})); - } - - private void addVersionNameEntry(long time) { - if (sPRINTLOGGING) { - Log.d(TAG, "Log Version. (1)"); - } - try { - PackageInfo info = mContext.getPackageManager().getPackageInfo( - mContext.getPackageName(), 0); - mLogBuffer.add(new LogEntry (time, ID_VERSION, - new String[] {String.valueOf(info.versionCode), info.versionName})); - } catch (NameNotFoundException e) { - Log.e(TAG, "Could not find version name."); - } - } - - private void addExceptionEntry(long time, String[] data) { - if (sPRINTLOGGING) { - Log.d(TAG, "Log Exception. (1)"); - } - mLogBuffer.add(new LogEntry(time, ID_EXCEPTION, data)); - } - - private void flushPrivacyLogSafely() { - if (sPRINTLOGGING) { - Log.d(TAG, "Log obfuscated data. (" + mPrivacyLogBuffer.size() + ")"); - } - long now = System.currentTimeMillis(); - Collections.sort(mPrivacyLogBuffer); - for (LogEntry l: mPrivacyLogBuffer) { - l.mTime = now; - mLogBuffer.add(l); - } - mPrivacyLogBuffer.clear(); - } - - /** - * Add an entry - * @param tag - * @param data - */ - private void addData(int tag, Object data) { - switch (tag) { - case ID_DELETE_COUNT: - if (((mLastTimeActive - mLastTimeCountEntry) > MINIMUMCOUNTINTERVAL) - || (mDeleteCount == 0 && mInputCount == 0)) { - addCountEntry(mLastTimeActive); - } - mDeleteCount += (Integer)data; - break; - case ID_INPUT_COUNT: - if (((mLastTimeActive - mLastTimeCountEntry) > MINIMUMCOUNTINTERVAL) - || (mDeleteCount == 0 && mInputCount == 0)) { - addCountEntry(mLastTimeActive); - } - mInputCount += (Integer)data; - break; - case ID_MANUALSUGGESTION_WITH_DATATYPE: - case ID_AUTOSUGGESTION_WITH_COORDINATES: - ++mWordCount; - String[] dataStrings = (String[]) data; - if (dataStrings.length < 2) { - if (sDBG) { - Log.e(TAG, "The length of logged string array is invalid."); - } - break; - } - mActualCharCount += dataStrings[1].length(); - if (checkStringDataSafe(dataStrings[0]) && checkStringDataSafe(dataStrings[1])) { - mPrivacyLogBuffer.add( - new LogEntry (System.currentTimeMillis(), tag, dataStrings)); - } else { - if (sDBG) { - Log.d(TAG, "Skipped to add an entry because data is unsafe."); - } - } - break; - case ID_AUTOSUGGESTIONCANCELLED_WITH_COORDINATES: - --mWordCount; - dataStrings = (String[]) data; - if (dataStrings.length < 2) { - if (sDBG) { - Log.e(TAG, "The length of logged string array is invalid."); - } - break; - } - mActualCharCount -= dataStrings[1].length(); - if (checkStringDataSafe(dataStrings[0]) && checkStringDataSafe(dataStrings[1])) { - mPrivacyLogBuffer.add( - new LogEntry (System.currentTimeMillis(), tag, dataStrings)); - } else { - if (sDBG) { - Log.d(TAG, "Skipped to add an entry because data is unsafe."); - } - } - break; - case ID_EXCEPTION: - dataStrings = (String[]) data; - if (dataStrings.length < 2) { - if (sDBG) { - Log.e(TAG, "The length of logged string array is invalid."); - } - break; - } - addExceptionEntry(System.currentTimeMillis(), dataStrings); - break; - default: - if (sDBG) { - Log.e(TAG, "Log Tag is not entried."); - } - break; - } - } - - private void commitInternal() { - // if there is no log entry in mLogBuffer, will not send logs to DropBox. - if (!mLogBuffer.isEmpty() && (mAddTextToDropBoxTask == null - || mAddTextToDropBoxTask.getStatus() == AsyncTask.Status.FINISHED)) { - if (sPRINTLOGGING) { - Log.d(TAG, "Commit (" + mLogBuffer.size() + ")"); - } - flushPrivacyLogSafely(); - long now = System.currentTimeMillis(); - addCountEntry(now); - addThemeIdEntry(now); - addLanguagesEntry(now); - addSettingsEntry(now); - addVersionNameEntry(now); - addSuggestionCountEntry(now); - String s = LogSerializer.createStringFromEntries(mLogBuffer); - reset(); - mAddTextToDropBoxTask = (AddTextToDropBoxTask) new AddTextToDropBoxTask( - mDropBox, now, s).execute(); - } - } - - private void commitInternalAndStopSelf() { - if (sDBG) { - Log.e(TAG, "Exception was thrown and let's die."); - } - commitInternal(); - LatinIME ime = ((LatinIME) mContext); - ime.hideWindow(); - ime.stopSelf(); - } - - private synchronized void sendLogToDropBox(int tag, Object s) { - long now = System.currentTimeMillis(); - if (sDBG) { - String out = ""; - if (s instanceof String[]) { - for (String str: ((String[]) s)) { - out += str + ","; - } - } else if (s instanceof Integer) { - out += (Integer) s; - } - Log.d(TAG, "SendLog: " + tag + ";" + out + " -> will be sent after " - + (- (now - mLastTimeSend - MINIMUMSENDINTERVAL) / 1000) + " sec."); - } - if (now - mLastTimeActive > MINIMUMSENDINTERVAL) { - // Send a log before adding an log entry if the last data is too old. - commitInternal(); - addData(tag, s); - } else if (now - mLastTimeSend > MINIMUMSENDINTERVAL) { - // Send a log after adding an log entry. - addData(tag, s); - commitInternal(); - } else { - addData(tag, s); - } - mLastTimeActive = now; - } public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if (PREF_ENABLE_LOG.equals(key)) { - if (sharedPreferences.getBoolean(key, DEFAULT_LOG_ENABLED)) { - sLogEnabled = (mContext != null); - } else { - sLogEnabled = false; - } - if (sDebugKeyEnabler.check()) { - sharedPreferences.edit().putBoolean(PREF_DEBUG_MODE, true).commit(); - } - } else if (KeyboardSwitcher.PREF_KEYBOARD_LAYOUT.equals(key)) { - mThemeId = sharedPreferences.getString(KeyboardSwitcher.PREF_KEYBOARD_LAYOUT, - KeyboardSwitcher.DEFAULT_LAYOUT_ID); - addThemeIdEntry(mLastTimeActive); - } else if (PREF_DEBUG_MODE.equals(key)) { - sPRINTLOGGING = sharedPreferences.getBoolean(PREF_DEBUG_MODE, sPRINTLOGGING); - sDBG = sPRINTLOGGING; - } else if (LatinIME.PREF_INPUT_LANGUAGE.equals(key)) { - mCurrentLanguage = sharedPreferences.getString(LatinIME.PREF_INPUT_LANGUAGE, ""); - addLanguagesEntry(mLastTimeActive); - } else if (LatinIME.PREF_INPUT_LANGUAGE.equals(key)) { - mSelectedLanguages = sharedPreferences.getString(LatinIME.PREF_SELECTED_LANGUAGES, ""); - } } public static void init(Context context) { - sLatinImeLogger.initInternal(context); } public static void commit() { - if (sLogEnabled) { - if (System.currentTimeMillis() - sLatinImeLogger.mLastTimeActive > MINIMUMCOUNTINTERVAL - || (sLatinImeLogger.mLogBuffer.size() - + sLatinImeLogger.mPrivacyLogBuffer.size() > MINIMUMSENDSIZE)) { - sLatinImeLogger.commitInternal(); - } - } } public static void onDestroy() { - sLatinImeLogger.commitInternal(); - sLatinImeLogger.destroy(); } - // TODO: Handle CharSequence instead of String public static void logOnManualSuggestion(String before, String after, int position , List suggestions) { - if (sLogEnabled) { - // log punctuation - if (before.length() == 0 && after.length() == 1) { - sLatinImeLogger.sendLogToDropBox(ID_MANUALSUGGESTION_WITH_DATATYPE, new String[] { - before, after, String.valueOf(position), ""}); - } else if (!sSuggestDicMap.containsKey(after)) { - if (sDBG) { - Log.e(TAG, "logOnManualSuggestion was cancelled: from unknown dic."); - } - } else { - int dicTypeId = sSuggestDicMap.get(after).first; - sLatinImeLogger.mManualSuggestCountPerDic[dicTypeId]++; - if (dicTypeId != Suggest.DIC_MAIN) { - if (sDBG) { - Log.d(TAG, "logOnManualSuggestion was cancelled: not from main dic."); - } - before = ""; - after = ""; - sPreviousWords = null; - } - // TODO: Don't send a log if this doesn't come from Main Dictionary. - { - if (before.equals(after)) { - before = ""; - after = ""; - } - - /* Example: - * When user typed "Illegal imm" and picked "immigrants", - * the suggestion list has "immigrants, immediate, immigrant". - * At this time, the log strings will be something like below: - * strings[0 = COLUMN_BEFORE_ID] = imm - * strings[1 = COLUMN_AFTER_ID] = immigrants - * strings[2 = COLUMN_PICKED_POSITION_ID] = 0 - * strings[3 = COLUMN_SUGGESTION_LENGTH_ID] = 3 - * strings[4 = COLUMN_PREVIOUS_WORDS_COUNT_ID] = 1 - * strings[5] = immigrants - * strings[6] = immediate - * strings[7] = immigrant - * strings[8] = 1 (= bigram) - * strings[9] = 0 (= unigram) - * strings[10] = 1 (= bigram) - * strings[11] = Illegal - */ - - // 0 for unigram, 1 for bigram, 2 for trigram... - int previousWordsLength = (sPreviousWords == null) ? 0 : sPreviousWords.length; - int suggestionLength = suggestions.size(); - - final int COLUMN_BEFORE_ID = 0; - final int COLUMN_AFTER_ID = 1; - final int COLUMN_PICKED_POSITION_ID = 2; - final int COLUMN_SUGGESTION_LENGTH_ID = 3; - final int COLUMN_PREVIOUS_WORDS_COUNT_ID = 4; - final int BASE_COLUMN_SIZE = 5; - - String[] strings = - new String[BASE_COLUMN_SIZE + suggestionLength * 2 + previousWordsLength]; - strings[COLUMN_BEFORE_ID] = before; - strings[COLUMN_AFTER_ID] = after; - strings[COLUMN_PICKED_POSITION_ID] = String.valueOf(position); - strings[COLUMN_SUGGESTION_LENGTH_ID] = String.valueOf(suggestionLength); - strings[COLUMN_PREVIOUS_WORDS_COUNT_ID] = String.valueOf(previousWordsLength); - - for (int i = 0; i < suggestionLength; ++i) { - String s = suggestions.get(i).toString(); - if (sSuggestDicMap.containsKey(s)) { - strings[BASE_COLUMN_SIZE + i] = s; - strings[BASE_COLUMN_SIZE + suggestionLength + i] - = sSuggestDicMap.get(s).second.toString(); - } else { - strings[BASE_COLUMN_SIZE + i] = ""; - strings[BASE_COLUMN_SIZE + suggestionLength + i] = ""; - } - } - - for (int i = 0; i < previousWordsLength; ++i) { - strings[BASE_COLUMN_SIZE + suggestionLength * 2 + i] = sPreviousWords[i]; - } - - sLatinImeLogger.sendLogToDropBox(ID_MANUALSUGGESTION_WITH_DATATYPE, strings); - } - } - sSuggestDicMap.clear(); - } - } + } public static void logOnAutoSuggestion(String before, String after) { - if (sLogEnabled) { - if (!sSuggestDicMap.containsKey(after)) { - if (sDBG) { - Log.e(TAG, "logOnAutoSuggestion was cancelled: from unknown dic."); - } - } else { - String separator = String.valueOf(sLatinImeLogger.mRingCharBuffer.getLastChar()); - sLastAutoSuggestDicTypeId = sSuggestDicMap.get(after).first; - sLastAutoSuggestDataType = sSuggestDicMap.get(after).second; - sLatinImeLogger.mAutoSuggestCountPerDic[sLastAutoSuggestDicTypeId]++; - if (sLastAutoSuggestDicTypeId != Suggest.DIC_MAIN) { - if (sDBG) { - Log.d(TAG, "logOnAutoSuggestion was cancelled: not from main dic.:" - + sLastAutoSuggestDicTypeId); - } - before = ""; - after = ""; - sPreviousWords = null; - } - // TODO: Not to send a log if this doesn't come from Main Dictionary. - { - if (before.equals(after)) { - before = ""; - after = ""; - } - - final int COLUMN_BEFORE_ID = 0; - final int COLUMN_AFTER_ID = 1; - final int COLUMN_SEPARATOR_ID = 2; - final int COLUMN_DATA_TYPE_ID = 3; - final int COLUMN_KEYBOARD_SIZE_WIDTH = 4; - final int COLUMN_KEYBOARD_SIZE_HEIGHT = 5; - final int BASE_COLUMN_SIZE = 6; - - final int userTypedWordLength = before.length(); - final int previousWordsLength = (sPreviousWords == null) ? 0 - : sPreviousWords.length; - String[] strings = new String[BASE_COLUMN_SIZE + userTypedWordLength * 2 - + previousWordsLength]; - sLastAutoSuggestXCoordinates = new int[userTypedWordLength]; - sLastAutoSuggestXCoordinates = new int[userTypedWordLength]; - - strings[COLUMN_BEFORE_ID] = before; - strings[COLUMN_AFTER_ID] = after; - strings[COLUMN_SEPARATOR_ID] = separator; - strings[COLUMN_DATA_TYPE_ID] = String.valueOf(sLastAutoSuggestDataType); - strings[COLUMN_KEYBOARD_SIZE_WIDTH] = String.valueOf(sKeyboardWidth); - strings[COLUMN_KEYBOARD_SIZE_HEIGHT] = String.valueOf(sKeyboardHeight); - - for (int i = 0; i < userTypedWordLength; ++i) { - int x = sLatinImeLogger.mRingCharBuffer.getPreviousX(before.charAt(i), - userTypedWordLength - i - 1); - int y = sLatinImeLogger.mRingCharBuffer.getPreviousY(before.charAt(i), - userTypedWordLength - i - 1); - strings[BASE_COLUMN_SIZE + i * 2] = String.valueOf(x); - strings[BASE_COLUMN_SIZE + i * 2 + 1] = String.valueOf(y); - sLastAutoSuggestXCoordinates[i] = x; - sLastAutoSuggestXCoordinates[i] = y; - } - - for (int i = 0; i < previousWordsLength; ++i) { - strings[BASE_COLUMN_SIZE + userTypedWordLength * 2 + i] = sPreviousWords[i]; - } - - sLatinImeLogger.sendLogToDropBox(ID_AUTOSUGGESTION_WITH_COORDINATES, strings); - } - synchronized (LatinImeLogger.class) { - sLastAutoSuggestBefore = before; - sLastAutoSuggestAfter = after; - sLastAutoSuggestSeparator = separator; - } - } - sSuggestDicMap.clear(); - } } public static void logOnAutoSuggestionCanceled() { - if (sLogEnabled) { - sLatinImeLogger.mAutoCancelledCountPerDic[sLastAutoSuggestDicTypeId]++; - if (sLastAutoSuggestBefore != null && sLastAutoSuggestAfter != null) { - final int COLUMN_BEFORE_ID = 0; - final int COLUMN_AFTER_ID = 1; - final int COLUMN_SEPARATOR_ID = 2; - final int COLUMN_KEYBOARD_SIZE_WIDTH = 3; - final int COLUMN_KEYBOARD_SIZE_HEIGHT = 4; - final int BASE_COLUMN_SIZE = 5; - - final int userTypedWordLength = sLastAutoSuggestBefore.length(); - - String[] strings = new String[BASE_COLUMN_SIZE + userTypedWordLength * 2]; - strings[COLUMN_BEFORE_ID] = sLastAutoSuggestBefore; - strings[COLUMN_AFTER_ID] = sLastAutoSuggestAfter; - strings[COLUMN_SEPARATOR_ID] = sLastAutoSuggestSeparator; - strings[COLUMN_KEYBOARD_SIZE_WIDTH] = String.valueOf(sKeyboardWidth); - strings[COLUMN_KEYBOARD_SIZE_HEIGHT] = String.valueOf(sKeyboardHeight); - for (int i = 0; i < userTypedWordLength; ++i) { - strings[BASE_COLUMN_SIZE + i * 2] = String.valueOf( - sLastAutoSuggestXCoordinates); - strings[BASE_COLUMN_SIZE + i * 2 + 1] = String.valueOf( - sLastAutoSuggestYCoordinates); - } - sLatinImeLogger.sendLogToDropBox( - ID_AUTOSUGGESTIONCANCELLED_WITH_COORDINATES, strings); - } - synchronized (LatinImeLogger.class) { - sLastAutoSuggestBefore = ""; - sLastAutoSuggestAfter = ""; - sLastAutoSuggestSeparator = ""; - } - } } public static void logOnDelete() { - if (sLogEnabled) { - String mLastWord = sLatinImeLogger.mRingCharBuffer.getLastString(); - if (!TextUtils.isEmpty(mLastWord) - && mLastWord.equalsIgnoreCase(sLastAutoSuggestBefore)) { - logOnAutoSuggestionCanceled(); - } - sLatinImeLogger.mRingCharBuffer.pop(); - sLatinImeLogger.sendLogToDropBox(ID_DELETE_COUNT, 1); - } } public static void logOnInputChar(char c, int x, int y) { - if (sLogEnabled) { - sLatinImeLogger.mRingCharBuffer.push(c, x, y); - sLatinImeLogger.sendLogToDropBox(ID_INPUT_COUNT, 1); - } } public static void logOnException(String metaData, Throwable e) { - if (sLogEnabled) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - PrintStream ps = new PrintStream(baos); - e.printStackTrace(ps); - String exceptionString = URLEncoder.encode(new String(baos.toByteArray(), 0, - Math.min(EXCEPTION_MAX_LENGTH, baos.size()))); - sLatinImeLogger.sendLogToDropBox( - ID_EXCEPTION, new String[] {metaData, exceptionString}); - if (sDBG) { - Log.e(TAG, "Exception: " + new String(baos.toByteArray())+ ":" + exceptionString); - } - if (SUPPRESS_EXCEPTION) { - sLatinImeLogger.commitInternalAndStopSelf(); - } else { - sLatinImeLogger.commitInternal(); - if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } else if (e instanceof Error) { - throw (Error) e; - } - } - } } public static void logOnWarning(String warning) { - if (sLogEnabled) { - sLatinImeLogger.sendLogToDropBox( - ID_EXCEPTION, new String[] {warning, ""}); - } } - // TODO: This code supports only Bigram. public static void onStartSuggestion(CharSequence previousWords) { - if (sLogEnabled) { - sSuggestDicMap.clear(); - sPreviousWords = new String[] { - (previousWords == null) ? "" : previousWords.toString()}; - } } public static void onAddSuggestedWord(String word, int typeId, DataType dataType) { - if (sLogEnabled) { - sSuggestDicMap.put(word, new Pair(typeId, dataType.ordinal())); - } } public static void onSetKeyboard(Keyboard kb) { - if (sLogEnabled) { - sKeyboardWidth = kb.getMinWidth(); - sKeyboardHeight = kb.getHeight(); - } } - private static class LogSerializer { - private static void appendWithLength(StringBuffer sb, String data) { - sb.append(data.length()); - sb.append(SEPARATER); - sb.append(data); - sb.append(SEPARATER); - } - - private static void appendLogEntry(StringBuffer sb, String time, String tag, - String[] data) { - if (data.length > 0) { - appendWithLength(sb, String.valueOf(data.length + 2)); - appendWithLength(sb, time); - appendWithLength(sb, tag); - for (String s: data) { - appendWithLength(sb, s); - } - } - } - - public static String createStringFromEntries(ArrayList logs) { - StringBuffer sb = new StringBuffer(); - for (LogEntry log: logs) { - appendLogEntry(sb, String.valueOf(log.mTime), String.valueOf(log.mTag), log.mData); - } - return sb.toString(); - } - } - - /* package */ static class RingCharBuffer { - final int BUFSIZE = 20; - private Context mContext; - private int mEnd = 0; - /* package */ int mLength = 0; - private char[] mCharBuf = new char[BUFSIZE]; - private int[] mXBuf = new int[BUFSIZE]; - private int[] mYBuf = new int[BUFSIZE]; - - public RingCharBuffer(Context context) { - mContext = context; - } - private int normalize(int in) { - int ret = in % BUFSIZE; - return ret < 0 ? ret + BUFSIZE : ret; - } - public void push(char c, int x, int y) { - mCharBuf[mEnd] = c; - mXBuf[mEnd] = x; - mYBuf[mEnd] = y; - mEnd = normalize(mEnd + 1); - if (mLength < BUFSIZE) { - ++mLength; - } - } - public char pop() { - if (mLength < 1) { - return NULL_CHAR; - } else { - mEnd = normalize(mEnd - 1); - --mLength; - return mCharBuf[mEnd]; - } - } - public char getLastChar() { - if (mLength < 1) { - return NULL_CHAR; - } else { - return mCharBuf[normalize(mEnd - 1)]; - } - } - public int getPreviousX(char c, int back) { - int index = normalize(mEnd - 2 - back); - if (mLength <= back - || Character.toLowerCase(c) != Character.toLowerCase(mCharBuf[index])) { - return INVALID_COORDINATE; - } else { - return mXBuf[index]; - } - } - public int getPreviousY(char c, int back) { - int index = normalize(mEnd - 2 - back); - if (mLength <= back - || Character.toLowerCase(c) != Character.toLowerCase(mCharBuf[index])) { - return INVALID_COORDINATE; - } else { - return mYBuf[index]; - } - } - public String getLastString() { - StringBuffer sb = new StringBuffer(); - for (int i = 0; i < mLength; ++i) { - char c = mCharBuf[normalize(mEnd - 1 - i)]; - if (!((LatinIME)mContext).isWordSeparator(c)) { - sb.append(c); - } else { - break; - } - } - return sb.reverse().toString(); - } - public void reset() { - mLength = 0; - } - } - - private static class DebugKeyEnabler { - private int mCounter = 0; - private long mLastTime = 0; - public boolean check() { - if (System.currentTimeMillis() - mLastTime > 10 * 1000) { - mCounter = 0; - mLastTime = System.currentTimeMillis(); - } else if (++mCounter >= 10) { - return true; - } - return false; - } - } } From 4fc6539bcb8a99b489b5cb72bfc977b9829f5603 Mon Sep 17 00:00:00 2001 From: satok Date: Mon, 30 Aug 2010 17:14:10 +0900 Subject: [PATCH 08/58] Remove unused assets Change-Id: I65de6335b19dec03785df51ddd544b7e4d39c036 --- .../btn_keyboard_normal_metal.9.png | Bin 7614 -> 0 bytes .../drawable-hdpi/btn_keyboard_toggle_off.png | Bin 1425 -> 0 bytes .../drawable-hdpi/btn_keyboard_toggle_on.png | Bin 1733 -> 0 bytes java/res/drawable-hdpi/btn_led_off.9.png | Bin 1279 -> 0 bytes java/res/drawable-hdpi/btn_led_on.9.png | Bin 1607 -> 0 bytes .../dialog_top_dark_bottom_medium.9.png | Bin 49933 -> 0 bytes .../res/drawable-hdpi/ic_dialog_alert_large.png | Bin 4918 -> 0 bytes .../res/drawable-hdpi/ic_dialog_voice_input.png | Bin 1931 -> 0 bytes java/res/drawable-hdpi/ic_dialog_wave_0_0.png | Bin 15673 -> 0 bytes java/res/drawable-hdpi/ic_dialog_wave_1_3.png | Bin 15823 -> 0 bytes java/res/drawable-hdpi/ic_dialog_wave_2_3.png | Bin 16009 -> 0 bytes java/res/drawable-hdpi/ic_dialog_wave_3_3.png | Bin 16022 -> 0 bytes java/res/drawable-hdpi/ic_dialog_wave_4_3.png | Bin 15910 -> 0 bytes .../keyboard_popup_panel_trans_background.9.png | Bin 1677 -> 0 bytes .../res/drawable-hdpi/sym_bkeyboard_tabprev.png | Bin 1026 -> 0 bytes .../sym_keyboard_feedback_tabprev.png | Bin 463 -> 0 bytes java/res/drawable-hdpi/sym_keyboard_tabprev.png | Bin 1033 -> 0 bytes .../btn_keyboard_normal_metal.9.png | Bin 5069 -> 0 bytes .../drawable-mdpi/btn_keyboard_toggle_off.png | Bin 693 -> 0 bytes .../drawable-mdpi/btn_keyboard_toggle_on.png | Bin 812 -> 0 bytes java/res/drawable-mdpi/btn_led_off.9.png | Bin 505 -> 0 bytes java/res/drawable-mdpi/btn_led_on.9.png | Bin 575 -> 0 bytes .../dialog_top_dark_bottom_medium.9.png | Bin 1574 -> 0 bytes .../res/drawable-mdpi/ic_dialog_alert_large.png | Bin 4089 -> 0 bytes .../res/drawable-mdpi/ic_dialog_voice_input.png | Bin 1040 -> 0 bytes java/res/drawable-mdpi/ic_dialog_wave_0_0.png | Bin 8471 -> 0 bytes java/res/drawable-mdpi/ic_dialog_wave_1_3.png | Bin 9017 -> 0 bytes java/res/drawable-mdpi/ic_dialog_wave_2_3.png | Bin 9614 -> 0 bytes java/res/drawable-mdpi/ic_dialog_wave_3_3.png | Bin 10089 -> 0 bytes java/res/drawable-mdpi/ic_dialog_wave_4_3.png | Bin 10514 -> 0 bytes .../keyboard_popup_panel_trans_background.9.png | Bin 3734 -> 0 bytes .../res/drawable-mdpi/sym_bkeyboard_tabprev.png | Bin 605 -> 0 bytes .../sym_keyboard_feedback_tabprev.png | Bin 365 -> 0 bytes java/res/drawable-mdpi/sym_keyboard_tabprev.png | Bin 612 -> 0 bytes 34 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 java/res/drawable-hdpi/btn_keyboard_normal_metal.9.png delete mode 100644 java/res/drawable-hdpi/btn_keyboard_toggle_off.png delete mode 100644 java/res/drawable-hdpi/btn_keyboard_toggle_on.png delete mode 100644 java/res/drawable-hdpi/btn_led_off.9.png delete mode 100644 java/res/drawable-hdpi/btn_led_on.9.png delete mode 100644 java/res/drawable-hdpi/dialog_top_dark_bottom_medium.9.png delete mode 100755 java/res/drawable-hdpi/ic_dialog_alert_large.png delete mode 100755 java/res/drawable-hdpi/ic_dialog_voice_input.png delete mode 100755 java/res/drawable-hdpi/ic_dialog_wave_0_0.png delete mode 100755 java/res/drawable-hdpi/ic_dialog_wave_1_3.png delete mode 100755 java/res/drawable-hdpi/ic_dialog_wave_2_3.png delete mode 100755 java/res/drawable-hdpi/ic_dialog_wave_3_3.png delete mode 100755 java/res/drawable-hdpi/ic_dialog_wave_4_3.png delete mode 100644 java/res/drawable-hdpi/keyboard_popup_panel_trans_background.9.png delete mode 100644 java/res/drawable-hdpi/sym_bkeyboard_tabprev.png delete mode 100644 java/res/drawable-hdpi/sym_keyboard_feedback_tabprev.png delete mode 100644 java/res/drawable-hdpi/sym_keyboard_tabprev.png delete mode 100644 java/res/drawable-mdpi/btn_keyboard_normal_metal.9.png delete mode 100644 java/res/drawable-mdpi/btn_keyboard_toggle_off.png delete mode 100644 java/res/drawable-mdpi/btn_keyboard_toggle_on.png delete mode 100644 java/res/drawable-mdpi/btn_led_off.9.png delete mode 100644 java/res/drawable-mdpi/btn_led_on.9.png delete mode 100644 java/res/drawable-mdpi/dialog_top_dark_bottom_medium.9.png delete mode 100644 java/res/drawable-mdpi/ic_dialog_alert_large.png delete mode 100644 java/res/drawable-mdpi/ic_dialog_voice_input.png delete mode 100644 java/res/drawable-mdpi/ic_dialog_wave_0_0.png delete mode 100644 java/res/drawable-mdpi/ic_dialog_wave_1_3.png delete mode 100644 java/res/drawable-mdpi/ic_dialog_wave_2_3.png delete mode 100644 java/res/drawable-mdpi/ic_dialog_wave_3_3.png delete mode 100644 java/res/drawable-mdpi/ic_dialog_wave_4_3.png delete mode 100644 java/res/drawable-mdpi/keyboard_popup_panel_trans_background.9.png delete mode 100644 java/res/drawable-mdpi/sym_bkeyboard_tabprev.png delete mode 100644 java/res/drawable-mdpi/sym_keyboard_feedback_tabprev.png delete mode 100644 java/res/drawable-mdpi/sym_keyboard_tabprev.png diff --git a/java/res/drawable-hdpi/btn_keyboard_normal_metal.9.png b/java/res/drawable-hdpi/btn_keyboard_normal_metal.9.png deleted file mode 100644 index b29d6d1742085f6fad8a881576f576febc78b0fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7614 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 diff --git a/java/res/drawable-hdpi/btn_keyboard_toggle_off.png b/java/res/drawable-hdpi/btn_keyboard_toggle_off.png deleted file mode 100644 index bfe78402f4b99c6f1f39e702341f2204b765893d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1425 zcmV;C1#bF@P)tFvr zYmc`v|Ksre8`kXXY^z_CJp@lRH#dLJ^<;g0eN#9buB)xB4FMeV`~5x`h4G2N zs{88dYV7jz^1N6qZk(T=uMoFJo+A<$s*`)n#7IE#c>EiZziMo3e2t~J?gl_b`KjE% z)S9l{J#z(?w}2fN3Wc`-E_1z}%jMqo_V!*nh8{CXM@2nNO--+&(dZBD?d=l{3>ay1 z3=GWm^|c|X2ZE%guCC6&*hf7fR2bmCmBOMFKgF&jbwe@Eh zeTzc^HvUqnWXk2T1(K4^1SpfF8Y)JNHF)laVJ&lz^%|bl zBsAmA1fmuYViaT2IVXnxVDL1ayjezF-y0uSte!z(zWuDyPd6Q^uTD4fKCT= zw(TW$+9L(Z)C3B4aw$;50jNOd>%g=Qm`{0$vt94H@eZIe7FJ>x>_7#g=Q0i53rIu0 zGWp5`rhECor~+UaU;AEIFk%WM%3={50)W~;2co3aZT}d|u~7#LQ1PTu%q^iG$$Oz3 z77XM()f{rKcPvczm`o<)RVWq?Oh9hvxmXBHKx%tES({{$vB0ums3Oh-qDq2(*0x1u8|oea2U4k& z+1c4K{O#CdNFa`#0yP9AR+_cWA#8?*h79qN^Mmr?wuM(Za zhI(fGTfZD09&TX&%--IfIXE~l$H&K(B?&AON!HcXW%~R3&EVjm;SiUUoX4f#kZ_q} zYn9@Pt~l5FW@TliJU%{tM1|`F=+Cf(q$xV98;JsRs80#CH%>Oz4Trc`Ran2n?*r?9 zpu#eJu+Fh{w7I!ic3_^2?!nU1lGyZMQ*81y-8BiYj+-!ygUm9;NzYpVU!Fb6VHqUM&?H~| fZhQjpUq1K?E0K1EnweR?00000NkvXXu0mjf!pNDb diff --git a/java/res/drawable-hdpi/btn_keyboard_toggle_on.png b/java/res/drawable-hdpi/btn_keyboard_toggle_on.png deleted file mode 100644 index 0a1221e97969ccd7d2c7294151920451e1c1ce72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1733 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 diff --git a/java/res/drawable-hdpi/ic_dialog_alert_large.png b/java/res/drawable-hdpi/ic_dialog_alert_large.png deleted file mode 100755 index 7e2646d654746924b7efe595bad9c94ef367559e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4918 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 LHPo)ZgL(cxaPK}a diff --git a/java/res/drawable-hdpi/ic_dialog_voice_input.png b/java/res/drawable-hdpi/ic_dialog_voice_input.png deleted file mode 100755 index 11a3cfe77321318d0e563df5cdd42eb06a49ef1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1931 zcmV;62Xy#}P)LV;{7Z2xQ&1l1q0v9f|}tZXP+ zQfVKK`B772Q>is&P3`aZx^J0W(|7NTE*&_$`}Dng&$;(}{LXn}Yieo|Iy8U&e36}< zEtV`ar^fS2u~^pw{Z=w#WjI_7K<*ZKn{Ta%xkucrWC^msfC7# zAAOgbn|o|3C7d5K8@`BPwa%(<-@X;Y!^7g`%a`KSt5;&df(0TqHB~HLyjW+tYRJNQ z_6`gTOs@c)XT^#YwYtJTc1Cv{@+FK|jj8q+%{8~njFsS`890vi0F8*OO! zfCF_F9*w{h8g--7(xpoqDC>U|@Or)LaoMRGE^xf#xO7>vg;=aTfyh)TWqoh<@7}#L zfElpOL5_6^?}n_tkLSh`S&OnFs%;?vG)@3vDj-w&r$XgY=JyH!5?66YW{c%1B*a-+ zSyhGth{^Qst>P1-IdkSzP-`|IQ`)aK;mr0MSB-Me?YfH02(A8i2Ku0(WE!beV>qXZNU?7{##<(m-Mn7%QQm;DA#@iwD4V(Lo%*1t z7X?2TzJ&X23}`$RgyAEQ!J{ewWN&d|2QRbrLEBU%M4k(QK;ZN4?(QJxfe>qu;A+6N zz*qq&5HNiLi?Pje1GfjjRDgoBaaM`{?^9iyC(AW$=g*&a`2GGtOs0!SLokJ};E-1a z2M3KTEonns*E$An0pF1rhJw>^*}7@aNv24A;ojcf9Oi)-ZqCAqsx=jGBmDgdv-v(d zJG<`DqeoG;S70tJQt0=^H$pW|#efSapz`rfgQn@43NV?*Z0F9g|0Dvi=WCjsvky=P z_$2rg9JsTiqr=P_qPVy?Rh|kP2U~SpH>4*|p0NK^#3q87!Mb3#7n1Jlc;ib zDk8!Uh!Kquf^5!BxWarvVoOnXe$I(7dgiWe*QzptL1I3gdIGODtH(r}J3BkW{8_+E6W2h* z3USTpgf~vW;=E1Rl{E-s$I{Z$D)-6-hE%(R5dlacw^m06h# zGvTJ3WlKfo3S~+}fq$`@M46?MS)LkSrp?+I(As>K^#C*VWy#HnF8+@I0|4zTW}pNS R7g7KK002ovPDHLkV1j9npK|~J diff --git a/java/res/drawable-hdpi/ic_dialog_wave_0_0.png b/java/res/drawable-hdpi/ic_dialog_wave_0_0.png deleted file mode 100755 index 33023c3f78b520a4d0c6ab9dd832855b39622a54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15673 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 PZ72m<} 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 OC`DOSnQAGMkpBTzSkj9C diff --git a/java/res/drawable-hdpi/ic_dialog_wave_3_3.png b/java/res/drawable-hdpi/ic_dialog_wave_3_3.png deleted file mode 100755 index 5fe5492ad95bfab73f6e6c424c20a14d5df54e39..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16022 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 diff --git a/java/res/drawable-hdpi/ic_dialog_wave_4_3.png b/java/res/drawable-hdpi/ic_dialog_wave_4_3.png deleted file mode 100755 index 81b803fd00c7ce17757553a2d82d15fdbc53bdc8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15910 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 AdH?_b diff --git a/java/res/drawable-hdpi/keyboard_popup_panel_trans_background.9.png b/java/res/drawable-hdpi/keyboard_popup_panel_trans_background.9.png deleted file mode 100644 index fd7366e204321ee317e1a55342d23b95f0a09202..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1677 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 diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_tabprev.png b/java/res/drawable-hdpi/sym_keyboard_feedback_tabprev.png deleted file mode 100644 index 36f6b536459f3c4b1b94132c224cbdefc102acad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 463 zcmeAS@N?(olHy`uVBq!ia0vp^#z5@C!3HFC+IWM3lw^r(L`iUdT1k0gQ7VIDN`6wR zf@f}GdTLN=VoGJ<$y6H#2F5~97srr_TW@Y((=l;`k5RmY<4@fp9;Cv-cNV#w2=;ASZvBwoF3+zbt|XW z`R>!QyBY2_ulH40$6bn0I@`d=CXoOq+Gq5wp5->#rcH5+<)syqjtQh_PB40DGI`4{ z%Oloq3cH`EH{1}&muOm(>}aQy4L z7C{bs=dAAeri||&%w3o1cYAf{EK4UR_soBRW~Q5i*(#46V!d3{r*&k`TEn0W?No(z zQ}bjlrI5BPq1tBln10}RYO z22djTH`f8(8 AasU7T diff --git a/java/res/drawable-hdpi/sym_keyboard_tabprev.png b/java/res/drawable-hdpi/sym_keyboard_tabprev.png deleted file mode 100644 index 51bff1bcd580c0d86a64e043bc0d12c008f00379..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1033 zcmV+k1or!hP)#>9oX zYO1a!GzeNZO?Pe!#R|zHEu|n`R&lAg$rq4N#0mvnbyFxBEPWsfet=RJrJ9mzRn#Qr zHIvCadTuzkj6<4CnsgE*1Apd`o0;F7=bdX+Rn^iKy!of??d`{Keh#lQW&<(kDz_jA#8Q@Wx$M+f%i0Yf;zFk^%Orj*l}g2qZsfWF zbOa?yQVj^eC?sQ6+B23O+jTOci{V;y5sMHWlzVY;@w(ILO3-XVx=R#3B8IK7|?puqh6{M|?-@(jwv zK&J{Q*8(_gx&&rmVPWCUjz!j*x0x~Iy!nwJ1(Eklix1kjXfCTjbP}M zhP(ie=j1+27OhK7Rraivm;Smz4pEKXOHA%Iq8n`RkW$hNYw zGCeprc(s!)!fv;FMn*<%AP8e9?HPut`5OZG#opfD=S~7;v)T0O>gxNJf*P`g4B~fo zc5lE}~G)90VtQ7?6J18|aHue;H*h@&3nrnPMUk-K|9FvFZ%~S;O zpsN1!%4q9Q(98mDps`r&xhRVJQ&UrO094S&f*IXj#(>NtAU`uR^UCFN?LrC{vA9*+ z{km-hNY$9PfEFu6qtVxB8PRMYeJ@hbh5yVLy8&d;J-8?4)Exupf0wljL}EkYIIcEP zXIWOk3{tuQL?12yNDav0aL}G3nX!6S4~PJi;IoE6SfJ<$oho=IS!1M=`Fbm8MXWip znM-;K0?_G!c8yUy&O-Vd{&%ae{e^QwF6*W3P=Emdg2XA`Vzt8>00000NkvXXu0mjf Drrp=U diff --git a/java/res/drawable-mdpi/btn_keyboard_normal_metal.9.png b/java/res/drawable-mdpi/btn_keyboard_normal_metal.9.png deleted file mode 100644 index f4fe0a8a02ab3721f90cf4d64f855d00de9400fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5069 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 diff --git a/java/res/drawable-mdpi/btn_keyboard_toggle_off.png b/java/res/drawable-mdpi/btn_keyboard_toggle_off.png deleted file mode 100644 index 21399a4f3618f0e6549016cd7b53e75767029de6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 693 zcmV;m0!safP)FRt&i8pU@BJ4{)I%io;3~XK@}<=MrD+L_!F;P`+!` zIp>!4TK!bWycheGlK^aHwy$+qd<4T`m*~l|Krl(`m_K zu{^q5t_O$1ac4H0i3LTB1!z8>({MOk4hDm7)9Li3SS)sa6Ut_@5(|9s`~69;*Gs$I zj>hA$cw%X_TC&+};@Ru`l0Ki0n$0F1k4NIt$Y?Z* zIR5wheNw4Z6buGQuh%CP3dMj!pAc8#=jrJw76=3$*r?HH2oeNP788VF42yX>f4kilBu-hBb2^>gnP@7< zfB_a9aOECZt=4;_J)6zQWHJd7O29>2M6tgXT`U%&RB&Y>kkQ!velMF+sTB6B&@~1e zaAhF|*O~MIC!l`x1M9j>2qDYOW+O1b{y3;E_XraU5MRGYdAVHDYPAxCYl9ClV1NY& zTv>>FQ)b695{ZbDCX)&A0jYcEU1C)0e zNG6iqZl_c#CHy?$U&G<>&w<41cDpZp;w$DPm&;Kikq|?Od4XXMA7a1&3y%DvBBP5{ zDix{I={z%W!TmVjGQ@xZ_L_V1Gg7P7Vmxedel?;z&0>v{_+o<4i9=&*5J?KH^z=N{Ec93CP z@lRbh*R5@mCTV;xS%b16B7X45m-qX_`(EA`!M1Juk0l&sG(J8)8VZHdk|d3YqS((l z(=<19U0+sJb!lN?A@@h4OeUkWx3^EmK2j zoy%sk`9nq%6B7y<-0$t}9ZRKB(83?F?SBtl*miKq?n0M!8gi`%#bObgo12SdcxQfo z-Z2wfj)_EKa$sO!EY*|5J3N9G{0ur8{C>ZKYgQ58^%clCi8KATAj|TYAP6Obro4)# zr>92;2M3>#QRIc5fhy+_4u=s42H^L(Mpn~;(J)Y})ezDYT$Zv}Uth1Tt*u?1nVHEs z6(y6&w4x}Hg6}0hVFl5k2vMxT@`(_9KF7#L6Q*dQ5mZsuzJa-lG8`$F%V~mh4y(Jn zd!)0o6K^U{VF*A2CNz5=YV!wFYugRlbB;0QFqbu~^?KCN(b3=5)`qY82gni~gZgha zxe7k~K@)90o{Q1L;j)Ico)Pzh8*7<7FK%#;ZQo&|7S3GOu$Gr|H0u6_k9u)j>_bBb zHI>MQ8`eRz-Wg*Kb6LY$&xj}1vMgMP-+)@9PhF>+N}>Z(Cv-Q*7;~7*8rFJ7l}cra z64i^TYe)!ZQLO;AeV|@-MI5~69AnI3E^Ao(+hnhNv$I53Dfd_ZqkmaH1sDLhN2LT+(uVi|0000MLu#IeH9 zP1g-$c#K+Fc1?-Q%)Me5d&70bfjzFlz870Py*XBHU2WDl|I&IxTlI5`R5HSkSGCxu zx0D<1w=`aCcmI8jjl6yR??VDk9EvR<;=kM^m*|Y1xQpDoT%|Sk=m^x?$eEk^T6eoB ziT}9g$}AJFHu+@on%AcpE(Rz{@Yp5ob<*8wTw2o5wlLrY-)hD5t1S<*u1{z_9DKz^ zY}JXZ4Dq{1k~TUUuGUeR=&@tRqa^ihs*CnaxG~qZaCT>8s^X5N^EP~W!Wq7=AtaFb z=8W1fF(JNo`3+n4H?uG`>ZKh&OJeP(&yfB3YOVJXPqW!u)hBz#ozdd{ zXrpg1|9tY|iy4R9j(h z`!BikX9do;1nW&-z3#Qzv}gOL?YNa8x^|(>DMjYY6X)yqgToC>%vX>rNANINbqtSm cEBBety?I6NQ?BI;V3aa=y85}Sb4q9e0F9c|%m4rY diff --git a/java/res/drawable-mdpi/btn_led_on.9.png b/java/res/drawable-mdpi/btn_led_on.9.png deleted file mode 100644 index fe77abb08e8a87dc6f49872d4fa1214d04b7c5ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 575 zcmeAS@N?(olHy`uVBq!ia0vp^MnLSs!3HD`yQJkZFfg%sx;TbZ+-(zy2%<+%x z$^|E#UJ9^k{c~LC7uRJ|A|NT!*pYF;F@QzYi-*TXf`8)DvnQ4u<7?_!;CRWXsA*Qf9eM=lH0#C<8gGN zqS*4pcYEJ^m8g{T3Vpqm&GBLFh6x)V^uBP}(e}-E@4my^4>{SbE>{kI-D|S)s_L1Q zrvD!Tb*)SIej>-E&nN%R5|^`UY-1h(#kyy0JtzIH`gP~s<@)=hzx#BSP88Z!0yIy+ z{^sU=$J_MR=R`f9wte1Yp?ZgT6~F(BJ?ejPd)myfI$oaEq;EC*M1P(4GbuRpwmR|| z-;A7ly~|g3-=4c=OYV}&wa3k0n}64|U-LZp+1jmMkC%rQnXIzrv(`SuwW3~qP4<_C zRxXPrEB-PuaVRt}KnM>bg%)X0aD&4fov@rD;Pr7yy;c8B=>^8IO2CA{;OXk;vd$@? F2>{eN1i1hJ diff --git a/java/res/drawable-mdpi/dialog_top_dark_bottom_medium.9.png b/java/res/drawable-mdpi/dialog_top_dark_bottom_medium.9.png deleted file mode 100644 index cf7ecaf1ea64435bad70e7513b4e1c3d5a19a21a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1574 zcmV+>2HE+EP)d zNG%_Ns2q?uJVcM2+CQbIs?baS0j@nk)l>fndT&o$5xpP|v?1c7PvX!}D9}7R{^)MH z&YLW=Yv(nNdD5;laz31$`FUn`*N%2*9LFTjMkyUo!1U2v^+6z}JoE3!c-l}`o3l6> zVCWF<=?DyurT*e!ARP@1W+*&T&39>l7yx#RC8!wm87qM@f@BdH7K4&uWB{FzG%zP6 zPcX5-(Lz2~fsquDNO~P1pT~$NwH{J=#L6ftFro;tSTa0|5X4h)TFA*)-3CV6h^XLX zC=5oH5D_Z%5h(`=Fl<8z4q9U3GN~|`WKv~PXY$d~($f6#@$on9cKava_g}>$YP>Jr zC-0l<;JSp)s<5FVY$^#G2QFNXMFL7ZAj8y{e8^;WZEbDI^Ss~VoEz7{b#a|ScMXBE z0aTBrH?fLgTh134QoSp(u&^+3dV2b^>$=M)Cnw#5g9GpI@X)`$zK%vQi_Xr@S{oZ1 z<;~4acXf5O#GuYrR#v{axVY%BuLCAsDHJ1l(2#*(4mbd&C(UN_>*eL;Z#m4~-rmF2 z)m50s@?dUm&fePEn&ePtXJ_9v8jbG-Ocy`}QttJDEX4>Xdx^u9>-G9){Dl4e{Z3vm zyz#!d4*pu`EQ1SdO9RiqNa|>YYYV_|50xvG$_hWJ)oKNKFX9p%LT4En4WX_5iPljJ z*%k)G8c$F%s+`faM2FB>Muu_=fc0CJkn01H;#wID)!LA=QYKYff-0(&kQ}1e^2*Yz z6l5t#6S}8D=G#3@=A#9mNv*Zv_gq>X=kgW(eGHedXVOM0xsl1aZhlt{~ zp{Rzf++mR+M^kLnh8)p6-6_gLY0oJ# z_+9E>Ju4zRM47Yr3=jU+4O$MCbLK%j`|OBN`Bu$l%D(qR!E zlI=jD(sBrHLJtcB3W>T5!B8Qm+xkE5kc%{4(uN#X8lbmT`SJ1bPkxf?y1CC^i4LJN zAcK3qBbBGDlwon8zCpX)zTjV0DwW)~uO&K!PI*JSa#~S&2rJmoZM9m*{G^$gnF-c% z+wsNw<~sOmp|eY#?$F1;`sD}Ez28jU6T)j4y#E1fmzS46R;$%d9v&XLH#axl-QAt< zd0sTCFk^j}r>Cdg$;rtQ>-&%S`S~yZW{pQ5lYf}J7UB!gfpC<8V6}^+NCXF(5KxtR zy@SB*yFD;9FM0)$IPzzP`Txa&d9-Q|7oAqkv$J`0M=q{I{c{qhGhTw|}|6zrRz!$ll=+V?grGVi_t4 zzeFa4xI)U{cMf^F5fJ8Q0Isqx4E2QJ9RLEu48q8H)dO;XBC4271A=c=PK@#uFm?)1 zsDVlVItq_q!*=iJNFy9Ylv<)AiY!GEgFFNV+vbc-2N0?Y0A2$?UkWef1nZ1Q!U1F4#lEz+5Ln1zRrjFM=TMGK`Dnn&cps0|(223 Y0I&?vnCT{+761SM07*qoM6N<$f~r*2p#T5? diff --git a/java/res/drawable-mdpi/ic_dialog_alert_large.png b/java/res/drawable-mdpi/ic_dialog_alert_large.png deleted file mode 100644 index 2d4a164a78de6e70dfafc70c7e5820601ac6db8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4089 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 diff --git a/java/res/drawable-mdpi/ic_dialog_voice_input.png b/java/res/drawable-mdpi/ic_dialog_voice_input.png deleted file mode 100644 index d2891413227855950e6113ec64319a4b8e49c468..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1040 zcmV+r1n>KaP)LW$6+4hB_${a~hhQisvvPBDBQ`cRG63g{G8hwSYirZW%F2WS@i3Od z{6ygF?98ueT2jUB>+9>Ohlhu*?(S~7R;;Y7XvM|F@%Hw1m5rK#1Zrw(tUck)wgOyf z%`sR2Je&om@SAPyQxMI@67K}AuC5|3c6$PVpLVp}mQb`2v@!n?C@n1==TfK^Cvjtg zm==NU?QIEiEll0<@Q_FB7lIhC#?RPEJk?eisxJI2vOgb*RfRDz?3fN5<^w>6yB} zzZVFjj=_q3)S)iN{2GDk>S`;*o}Qkjd3-J}FF%D`wy}>o{Le8;1QEhj za4^jq5U!46oSqY&b+)mOI&9+@nO$OgQmItDp`k%`5;C{9w*ly-mzI`djg5^VTqdHZ zsK`pY9v>fdTxR0%@X+k*>kA(p9r>{Y(u)mx2_IOm*4Nj|2xwT}7y!Bmu(-H5ftilw zq-k{fbbo*U1avfj$1p?b#YSw8X_`7Di9xD)Ubw2ND(zswqa?+u1+TEuWj4i@=RhlE@eL-N?(!iv^D5GlqwUr=$-PkO(2jM4OtLwDR)uAAw(A zUyJ?y{S1N?!Q~H=tjx~N@=Qk&(}Q(&bwV*td^qRF$H(IQ{G3PC7#SH+f12gW%*>4S zI0XTnJDeVI@(O3m!jl35*5h<^bo6_V(=Uj)dY%JV>3RNFfB^s~l&09uu{kUN0000< KMNUMnLSTXrr0A6Z diff --git a/java/res/drawable-mdpi/ic_dialog_wave_0_0.png b/java/res/drawable-mdpi/ic_dialog_wave_0_0.png deleted file mode 100644 index 9c3c28f37b79a696820fd971b3c660a94e9b31ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8471 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 FV1l7w^|1f| diff --git a/java/res/drawable-mdpi/ic_dialog_wave_1_3.png b/java/res/drawable-mdpi/ic_dialog_wave_1_3.png deleted file mode 100644 index d33bd0d9b534cb7107c8a770b57891349157ec59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9017 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 LNkvXXu0mjfjKUS# diff --git a/java/res/drawable-mdpi/ic_dialog_wave_4_3.png b/java/res/drawable-mdpi/ic_dialog_wave_4_3.png deleted file mode 100644 index af5a84c31a40b52848a7ebfd210d3ef2db3bd74e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10514 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 U6Do96)&Kwi07*qoM6N<$g0@KcX8-^I diff --git a/java/res/drawable-mdpi/keyboard_popup_panel_trans_background.9.png b/java/res/drawable-mdpi/keyboard_popup_panel_trans_background.9.png deleted file mode 100644 index 4ba2a4908cb81e3307c69bc1116b2b867159515a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3734 zcmV;H4r%d;P)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000BQNkl8nu5Xb+NX*+HO6ka^$0gM6}io8Xpb`H=bKpvsU(5*|ipnHrU zeT@QHn~ogbNZ3ZF%H23%S-*>y+ zPf3!{`T6SX0$3=uQUDndO-zM&x=8@dIF8=}z;HNB zs#NIa<|frK#BuzNsgzU5mU2@4L#x?rz5#&i>+1z7HXVbCsbzsGjB*7a_-if8XqW?v zY6z4WZcVvHjeyqnA>mNTXCP}I;%hiQ5BUs~n}>uDT_FUODdaPdjxS>C%Ys6DwDTFL z!Pb;kAilcx)fyIcN)^hD93EQacs{cNi5e*6df3dVARhT#^V~qzSb1921;`mEPdPZw zeFZ9<``q#WITr&^017|>C;-(5NC-jy70`3N<_IYlfC5ke3P1rU00p1`6o3Ly0P++_ z*V({v?wdK|jT{%&1t=FM5s9eeqB;SQE9H2Jm#?Nv&I(XAAhS-*S2HU}N`aO&0m>Xu zPK9*!ps$uX(k=&NDw6?7r_<>r0Cc2&%&VxxvuX8~XiAi21>IG#)Zxl@2Ky$)HO}Rd0qE?CrI6xDQnERYW7N?lYkl22{dSSr{;@m5pRA zrGXZfRy2X61*TAU^T0J(W`W{r%}e?Z*?@#)g}{MqAkhYZY)WNJtp!UpK6K|&?!GzR z*bofXtRt6vUbKJ|<{{~jzHB*U+o`hY%^bvnHNln+m>dvKJ6K>`+ilEI?J2g~kYzFI zTy0CsjRgbL5E(q)5ViW@O>9}))Qjg$yzl)p02Mihb;h4>p39|Z1$79zBcR{e@12wIfkL}V(CV@}_Zb72Y}#f((Y zfscFd+&kyH=W);6k#t?R4N_#=faRay=Lv=kMARP!B%ldsz?+o>PGAxk0m{HDP_xQK zwDTFS*LxsI(lz??z?hXWpmxILayfZC#gN5;<<>M! zTUAx{!zssyORv>x)p$I9f#EGsYF7gKq5+e@ir?=);kA3=aQK9G`fWg#foanHW9Oin z$z;xCS+=Ls=`Hcl&Z0&OpD1JCIWSe>l)*~8va{BlWCnFdNwe#H?$F^b{+!=gFc(U zXq~<$Fxq*9F{QOFegczAW)+A)1R@Z{&f2^sC#&VlljpTU9s&#iQ4muC6`Wn}00000 LNkvXXu0mjf^DvDA diff --git a/java/res/drawable-mdpi/sym_keyboard_tabprev.png b/java/res/drawable-mdpi/sym_keyboard_tabprev.png deleted file mode 100644 index eb90872fc5c188bc47ecbdba057ed6611e6735d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 612 zcmV-q0-ODbP)(Uh4*OynOZ zS_idj(?3WCqIN;J@qt2%T8sP8fxvwbh>O+{i2aHp2xc)67LjQ<=kwK4snjJ5?*Qd?C7>@FmWVYt?J4`1*jH7x-Tz60{i}evvF1T7 z8jYS?mgSDcV%vOD(=>_1g46#GM5hVf1sDL3P5q Date: Mon, 30 Aug 2010 21:09:44 +0900 Subject: [PATCH 09/58] Remove extension keyboard Bug: 2959287 Change-Id: I344ac58b4119e96daf5928c784275ee0b7095958 --- java/res/xml/kbd_extension.xml | 61 ------ .../inputmethod/latin/KeyboardSwitcher.java | 9 - .../inputmethod/latin/LatinKeyboard.java | 9 - .../inputmethod/latin/LatinKeyboardView.java | 184 +----------------- 4 files changed, 9 insertions(+), 254 deletions(-) delete mode 100755 java/res/xml/kbd_extension.xml diff --git a/java/res/xml/kbd_extension.xml b/java/res/xml/kbd_extension.xml deleted file mode 100755 index c64f666d0..000000000 --- a/java/res/xml/kbd_extension.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java index dec29b7cb..45a54b1aa 100644 --- a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java @@ -261,14 +261,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha || id.mXml == R.xml.kbd_symbols_black), mHasVoice); keyboard.setLanguageSwitcher(mLanguageSwitcher); keyboard.setBlackFlag(isBlackSym()); - if (id.mKeyboardMode == KEYBOARDMODE_NORMAL - || id.mKeyboardMode == KEYBOARDMODE_URL - || id.mKeyboardMode == KEYBOARDMODE_IM - || id.mKeyboardMode == KEYBOARDMODE_EMAIL - || id.mKeyboardMode == KEYBOARDMODE_WEB - ) { - keyboard.setExtension(R.xml.kbd_extension); - } if (id.mEnableShiftLock) { keyboard.enableShiftLock(); @@ -439,7 +431,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha mLayoutId + "," + newLayout, e); } } - mInputView.setExtentionLayoutResId(THEMES[newLayout]); mInputView.setOnKeyboardActionListener(mInputMethodService); mLayoutId = newLayout; } diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboard.java b/java/src/com/android/inputmethod/latin/LatinKeyboard.java index db4d167d4..c35a1b05a 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboard.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboard.java @@ -81,7 +81,6 @@ public class LatinKeyboard extends Keyboard { private int mPrefLetterY; private int mPrefDistance; - private int mExtensionResId; // TODO: generalize for any keyboardId private boolean mIsBlackSym; @@ -278,14 +277,6 @@ public class LatinKeyboard extends Keyboard { return mIsAlphaKeyboard; } - public void setExtension(int resId) { - mExtensionResId = resId; - } - - public int getExtension() { - return mExtensionResId; - } - public void setBlackFlag(boolean f) { mIsBlackSym = f; if (f) { diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java index cca0de18e..7a993669b 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java @@ -16,8 +16,6 @@ package com.android.inputmethod.latin; -import java.util.List; - import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; @@ -27,9 +25,9 @@ import android.os.Handler; import android.os.Message; import android.os.SystemClock; import android.util.AttributeSet; -import android.view.LayoutInflater; import android.view.MotionEvent; -import android.widget.PopupWindow; + +import java.util.List; public class LatinKeyboardView extends LatinKeyboardBaseView { @@ -41,21 +39,11 @@ public class LatinKeyboardView extends LatinKeyboardBaseView { private Keyboard mPhoneKeyboard; - /** Whether the extension of this keyboard is visible */ - private boolean mExtensionVisible; - /** The view that is shown as an extension of this keyboard view */ - private LatinKeyboardView mExtension; - /** The popup window that contains the extension of this keyboard */ - private PopupWindow mExtensionPopup; - /** Whether this view is an extension of another keyboard */ - private boolean mIsExtensionType; - private boolean mFirstEvent; /** Whether we've started dropping move events because we found a big jump */ private boolean mDroppingEvents; /** - * Whether multi-touch disambiguation needs to be disabled for any reason. There are 2 reasons - * for this to happen - (1) if a real multi-touch event has occured and (2) we've opened an - * extension keyboard. + * Whether multi-touch disambiguation needs to be disabled if a real multi-touch event has + * occured */ private boolean mDisableDisambiguation; /** The distance threshold at which we start treating the touch session as a multi-touch */ @@ -63,8 +51,6 @@ public class LatinKeyboardView extends LatinKeyboardBaseView { /** The y coordinate of the last row */ private int mLastRowY; - private int mExtensionLayoutResId = 0; - public LatinKeyboardView(Context context, AttributeSet attrs) { super(context, attrs); } @@ -77,10 +63,6 @@ public class LatinKeyboardView extends LatinKeyboardBaseView { mPhoneKeyboard = phoneKeyboard; } - public void setExtentionLayoutResId (int id) { - mExtensionLayoutResId = id; - } - @Override public void setKeyboard(Keyboard k) { super.setKeyboard(k); @@ -214,11 +196,10 @@ public class LatinKeyboardView extends LatinKeyboardBaseView { invalidate(); } - // If an extension keyboard is visible or this is an extension keyboard, don't look - // for sudden jumps. Otherwise, if there was a sudden jump, return without processing the - // actual motion event. - if (!mExtensionVisible && !mIsExtensionType - && handleSuddenJump(me)) return true; + // If there was a sudden jump, return without processing the actual motion event. + if (handleSuddenJump(me)) + return true; + // Reset any bounding box controls in the keyboard if (me.getAction() == MotionEvent.ACTION_DOWN) { keyboard.keyReleased(); @@ -236,154 +217,7 @@ public class LatinKeyboardView extends LatinKeyboardBaseView { } } - // If we don't have an extension keyboard, don't go any further. - if (keyboard.getExtension() == 0) { - return super.onTouchEvent(me); - } - // If the motion event is above the keyboard and it's not an UP event coming - // even before the first MOVE event into the extension area - if (me.getY() < 0 && (mExtensionVisible || me.getAction() != MotionEvent.ACTION_UP)) { - if (mExtensionVisible) { - int action = me.getAction(); - if (mFirstEvent) action = MotionEvent.ACTION_DOWN; - mFirstEvent = false; - MotionEvent translated = MotionEvent.obtain(me.getEventTime(), me.getEventTime(), - action, - me.getX(), me.getY() + mExtension.getHeight(), me.getMetaState()); - boolean result = mExtension.onTouchEvent(translated); - translated.recycle(); - if (me.getAction() == MotionEvent.ACTION_UP - || me.getAction() == MotionEvent.ACTION_CANCEL) { - closeExtension(); - } - return result; - } else { - if (openExtension()) { - MotionEvent cancel = MotionEvent.obtain(me.getDownTime(), me.getEventTime(), - MotionEvent.ACTION_CANCEL, me.getX() - 100, me.getY() - 100, 0); - super.onTouchEvent(cancel); - cancel.recycle(); - if (mExtension.getHeight() > 0) { - MotionEvent translated = MotionEvent.obtain(me.getEventTime(), - me.getEventTime(), - MotionEvent.ACTION_DOWN, - me.getX(), me.getY() + mExtension.getHeight(), - me.getMetaState()); - mExtension.onTouchEvent(translated); - translated.recycle(); - } else { - mFirstEvent = true; - } - // Stop processing multi-touch errors - mDisableDisambiguation = true; - } - return true; - } - } else if (mExtensionVisible) { - closeExtension(); - // Send a down event into the main keyboard first - MotionEvent down = MotionEvent.obtain(me.getEventTime(), me.getEventTime(), - MotionEvent.ACTION_DOWN, - me.getX(), me.getY(), me.getMetaState()); - super.onTouchEvent(down); - down.recycle(); - // Send the actual event - return super.onTouchEvent(me); - } else { - return super.onTouchEvent(me); - } - } - - private void setExtensionType(boolean isExtensionType) { - mIsExtensionType = isExtensionType; - } - - private boolean openExtension() { - // If the current keyboard is not visible, don't show the popup - if (!isShown()) { - return false; - } - if (((LatinKeyboard) getKeyboard()).getExtension() == 0) return false; - makePopupWindow(); - mExtensionVisible = true; - return true; - } - - private void makePopupWindow() { - if (mExtensionPopup == null) { - int[] windowLocation = new int[2]; - mExtensionPopup = new PopupWindow(getContext()); - mExtensionPopup.setBackgroundDrawable(null); - LayoutInflater li = (LayoutInflater) getContext().getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - mExtension = (LatinKeyboardView) li.inflate(mExtensionLayoutResId == 0 ? - R.layout.input_trans : mExtensionLayoutResId, null); - mExtension.setExtensionType(true); - mExtension.setOnKeyboardActionListener( - new ExtensionKeyboardListener(getOnKeyboardActionListener())); - mExtension.setPopupParent(this); - mExtension.setPopupOffset(0, -windowLocation[1]); - Keyboard keyboard; - mExtension.setKeyboard(keyboard = new LatinKeyboard(getContext(), - ((LatinKeyboard) getKeyboard()).getExtension())); - mExtensionPopup.setContentView(mExtension); - mExtensionPopup.setWidth(getWidth()); - mExtensionPopup.setHeight(keyboard.getHeight()); - mExtensionPopup.setAnimationStyle(-1); - getLocationInWindow(windowLocation); - // TODO: Fix the "- 30". - mExtension.setPopupOffset(0, -windowLocation[1] - 30); - mExtensionPopup.showAtLocation(this, 0, 0, -keyboard.getHeight() - + windowLocation[1]); - } else { - mExtension.setVisibility(VISIBLE); - } - } - - @Override - public void closing() { - super.closing(); - if (mExtensionPopup != null && mExtensionPopup.isShowing()) { - mExtensionPopup.dismiss(); - mExtensionPopup = null; - } - } - - private void closeExtension() { - mExtension.closing(); - mExtension.setVisibility(INVISIBLE); - mExtensionVisible = false; - } - - private static class ExtensionKeyboardListener implements OnKeyboardActionListener { - private OnKeyboardActionListener mTarget; - ExtensionKeyboardListener(OnKeyboardActionListener target) { - mTarget = target; - } - public void onKey(int primaryCode, int[] keyCodes, int x, int y) { - mTarget.onKey(primaryCode, keyCodes, x, y); - } - public void onPress(int primaryCode) { - mTarget.onPress(primaryCode); - } - public void onRelease(int primaryCode) { - mTarget.onRelease(primaryCode); - } - public void onText(CharSequence text) { - mTarget.onText(text); - } - public void swipeDown() { - // Don't pass through - } - public void swipeLeft() { - // Don't pass through - } - public void swipeRight() { - // Don't pass through - } - public void swipeUp() { - // Don't pass through - } + return super.onTouchEvent(me); } /**************************** INSTRUMENTATION *******************************/ From 82798ac066c8ffc497a68a313aee17cc4ad56bbd Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Mon, 30 Aug 2010 21:40:23 +0900 Subject: [PATCH 10/58] Disable long-press on symbol keys on international locale keyboards. This change is supplement of I27007b55a30a3699bf63fd8f64d58c4b23d97d9f Bug: 2910379 Change-Id: I634226a503594e76cea9ca29e32db5801a05ae09 --- java/res/xml-da/kbd_qwerty.xml | 10 ---------- java/res/xml-da/kbd_qwerty_black.xml | 10 ---------- java/res/xml-de/kbd_qwerty.xml | 10 ---------- java/res/xml-de/kbd_qwerty_black.xml | 10 ---------- java/res/xml-fr/kbd_qwerty.xml | 10 ---------- java/res/xml-fr/kbd_qwerty_black.xml | 10 ---------- java/res/xml-iw/kbd_qwerty.xml | 10 ---------- java/res/xml-iw/kbd_qwerty_black.xml | 10 ---------- java/res/xml-nb/kbd_qwerty.xml | 10 ---------- java/res/xml-nb/kbd_qwerty_black.xml | 10 ---------- java/res/xml-ru/kbd_qwerty.xml | 10 ---------- java/res/xml-ru/kbd_qwerty_black.xml | 10 ---------- java/res/xml-sr/kbd_qwerty.xml | 10 ---------- java/res/xml-sr/kbd_qwerty_black.xml | 10 ---------- java/res/xml-sv/kbd_qwerty.xml | 10 ---------- java/res/xml-sv/kbd_qwerty_black.xml | 10 ---------- 16 files changed, 160 deletions(-) diff --git a/java/res/xml-da/kbd_qwerty.xml b/java/res/xml-da/kbd_qwerty.xml index 472f8be55..0457395cd 100644 --- a/java/res/xml-da/kbd_qwerty.xml +++ b/java/res/xml-da/kbd_qwerty.xml @@ -117,8 +117,6 @@ @@ -114,8 +112,6 @@ @@ -170,8 +162,6 @@ diff --git a/java/res/xml-de/kbd_qwerty_black.xml b/java/res/xml-de/kbd_qwerty_black.xml index 366f87134..18fdc7d01 100755 --- a/java/res/xml-de/kbd_qwerty_black.xml +++ b/java/res/xml-de/kbd_qwerty_black.xml @@ -97,8 +97,6 @@ @@ -114,8 +112,6 @@ @@ -170,8 +162,6 @@ diff --git a/java/res/xml-fr/kbd_qwerty.xml b/java/res/xml-fr/kbd_qwerty.xml index 77076fd2f..7df32d914 100644 --- a/java/res/xml-fr/kbd_qwerty.xml +++ b/java/res/xml-fr/kbd_qwerty.xml @@ -99,8 +99,6 @@ @@ -116,8 +114,6 @@ @@ -172,8 +164,6 @@ diff --git a/java/res/xml-fr/kbd_qwerty_black.xml b/java/res/xml-fr/kbd_qwerty_black.xml index 1b799a51d..78b1da986 100644 --- a/java/res/xml-fr/kbd_qwerty_black.xml +++ b/java/res/xml-fr/kbd_qwerty_black.xml @@ -99,8 +99,6 @@ @@ -116,8 +114,6 @@ @@ -172,8 +164,6 @@ diff --git a/java/res/xml-iw/kbd_qwerty.xml b/java/res/xml-iw/kbd_qwerty.xml index b893f1a62..0ce5d367f 100755 --- a/java/res/xml-iw/kbd_qwerty.xml +++ b/java/res/xml-iw/kbd_qwerty.xml @@ -71,8 +71,6 @@ @@ -88,8 +86,6 @@ @@ -144,8 +136,6 @@ diff --git a/java/res/xml-iw/kbd_qwerty_black.xml b/java/res/xml-iw/kbd_qwerty_black.xml index 0dcf513e3..2bf0c2a0c 100755 --- a/java/res/xml-iw/kbd_qwerty_black.xml +++ b/java/res/xml-iw/kbd_qwerty_black.xml @@ -71,8 +71,6 @@ @@ -88,8 +86,6 @@ @@ -144,8 +136,6 @@ diff --git a/java/res/xml-nb/kbd_qwerty.xml b/java/res/xml-nb/kbd_qwerty.xml index d2f0258c1..a9e6adc9e 100644 --- a/java/res/xml-nb/kbd_qwerty.xml +++ b/java/res/xml-nb/kbd_qwerty.xml @@ -115,8 +115,6 @@ @@ -100,8 +98,6 @@ @@ -156,8 +148,6 @@ diff --git a/java/res/xml-ru/kbd_qwerty_black.xml b/java/res/xml-ru/kbd_qwerty_black.xml index 4923be01a..a9c88b7d2 100755 --- a/java/res/xml-ru/kbd_qwerty_black.xml +++ b/java/res/xml-ru/kbd_qwerty_black.xml @@ -83,8 +83,6 @@ @@ -100,8 +98,6 @@ @@ -156,8 +148,6 @@ diff --git a/java/res/xml-sr/kbd_qwerty.xml b/java/res/xml-sr/kbd_qwerty.xml index e4884a8a6..117db4c54 100644 --- a/java/res/xml-sr/kbd_qwerty.xml +++ b/java/res/xml-sr/kbd_qwerty.xml @@ -79,8 +79,6 @@ @@ -96,8 +94,6 @@ @@ -152,8 +144,6 @@ diff --git a/java/res/xml-sr/kbd_qwerty_black.xml b/java/res/xml-sr/kbd_qwerty_black.xml index 30d094a88..91b118f27 100644 --- a/java/res/xml-sr/kbd_qwerty_black.xml +++ b/java/res/xml-sr/kbd_qwerty_black.xml @@ -79,8 +79,6 @@ @@ -96,8 +94,6 @@ @@ -152,8 +144,6 @@ diff --git a/java/res/xml-sv/kbd_qwerty.xml b/java/res/xml-sv/kbd_qwerty.xml index d4ffa4d52..1ffa9dd1c 100644 --- a/java/res/xml-sv/kbd_qwerty.xml +++ b/java/res/xml-sv/kbd_qwerty.xml @@ -119,8 +119,6 @@ Date: Mon, 30 Aug 2010 20:18:55 +0900 Subject: [PATCH 11/58] Remove mAbortKey flag completely These three conditions assign true to the mAbortKey flag. 1. setKeyboard() sets the new keyboard layout. 2. long press shows the pop-up mini keyboard. 3. ACTION_CANCEL event is occurred. In the case 1, in LatinIME so far, only "symbol key" and "language switch" cause keyboard layout change. In both cases, the event is occurred in onUpEvent(), so we do not need to worry about aborting event. In the case 2, long press is used only to pop-up mini-keyboard and at that time mMiniKeyboardOnScreen could be used as a flag. In the case 3, though I'm not sure when this case occurs, in onCancelEvent() all the things that should be canceled are canceled in onCancelEvent(). Bug: 2910379 Change-Id: I12377c5f3e808f1c017ce980e12b1513895047bc --- .../latin/LatinKeyboardBaseView.java | 25 +++---------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index 95794f7cc..d9fa9f2a2 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -212,8 +212,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener private final ProximityKeyDetector mProximityKeyDetector = new ProximityKeyDetector(); - private boolean mAbortKey; - // For multi-tap private int mLastSentIndex; private int mTapCount; @@ -628,10 +626,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener invalidateAllKeys(); computeProximityThreshold(keyboard); mMiniKeyboardCache.clear(); - // Not really necessary to do every time, but will free up views - // Switching to a different keyboard should abort any pending keys so that the key up - // doesn't get delivered to the old or new keyboard - mAbortKey = true; // Until the next ACTION_DOWN } /** @@ -1124,7 +1118,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener Key popupKey = mKeys[keyIndex]; boolean result = onLongPress(popupKey); if (result) { - mAbortKey = true; showPreview(NOT_A_KEY); } return result; @@ -1239,13 +1232,8 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener // Track the last few movements to look for spurious swipes. mSwipeTracker.addMovement(me); - // Ignore all motion events until a DOWN. - if (mAbortKey - && action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_CANCEL) { - return true; - } - - if (mGestureDetector.onTouchEvent(me)) { + // We must disable gesture detector while mini-keyboard is on the screen. + if (!mMiniKeyboardOnScreen && mGestureDetector.onTouchEvent(me)) { showPreview(NOT_A_KEY); mHandler.cancelKeyTimers(); return true; @@ -1315,7 +1303,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener private void onDownEvent(int touchX, int touchY, long eventTime) { int keyIndex = mProximityKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); - mAbortKey = false; mCurrentKey = keyIndex; mStartX = touchX; mStartY = touchY; @@ -1326,11 +1313,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener if (keyIndex >= 0 && mKeys[keyIndex].repeatable) { repeatKey(keyIndex); mHandler.startKeyRepeatTimer(REPEAT_START_DELAY, keyIndex); - // Delivering the key could have caused an abort - if (mAbortKey) { - mHandler.cancelKeyRepeatTimer(); - return; - } } if (keyIndex != NOT_A_KEY) { mHandler.startLongPressTimer(keyIndex, LONGPRESS_TIMEOUT); @@ -1387,7 +1369,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } showPreview(NOT_A_KEY); // If we're not on a repeating key (which sends on a DOWN event) - if (!wasInKeyRepeat && !mMiniKeyboardOnScreen && !mAbortKey) { + if (!wasInKeyRepeat && !mMiniKeyboardOnScreen) { detectAndSendKey(mCurrentKey, touchX, touchY, eventTime); } invalidateKey(keyIndex); @@ -1397,7 +1379,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener mHandler.cancelKeyTimers(); mHandler.cancelPopupPreview(); dismissPopupKeyboard(); - mAbortKey = true; showPreview(NOT_A_KEY); invalidateKey(mCurrentKey); } From 7b9ed1aa7601e263a46cf6b852df75a3866277d4 Mon Sep 17 00:00:00 2001 From: Maryam Garrett Date: Thu, 26 Aug 2010 16:31:54 -0400 Subject: [PATCH 12/58] Logging for the VoiceSearch alternates Log which voice-based alternates were selected, and what word in the recognition results were replaced. Change-Id: I1527dc794902a18a226ca45e186ecf84841094c8 Conflicts: java/src/com/android/inputmethod/latin/LatinIME.java --- .../com/android/inputmethod/latin/LatinIME.java | 8 ++++---- .../android/inputmethod/voice/VoiceInput.java | 16 ++++++++++------ .../inputmethod/voice/VoiceInputLogger.java | 15 +++++++-------- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 37ae43d38..e0a861a68 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1727,13 +1727,13 @@ public class LatinIME extends InputMethodService } public void pickSuggestionManually(int index, CharSequence suggestion) { - if (mAfterVoiceInput && mShowingVoiceSuggestions) mVoiceInput.logNBestChoose(index); List suggestions = mCandidateView.getSuggestions(); - - if (mAfterVoiceInput && !mShowingVoiceSuggestions) { + if (mAfterVoiceInput && mShowingVoiceSuggestions) { mVoiceInput.flushAllTextModificationCounters(); // send this intent AFTER logging any prior aggregated edits. - mVoiceInput.logTextModifiedByChooseSuggestion(suggestion.length()); + mVoiceInput.logTextModifiedByChooseSuggestion(suggestion.toString(), index, + mWordSeparators, + getCurrentInputConnection()); } final boolean correcting = TextEntryState.isCorrecting(); diff --git a/java/src/com/android/inputmethod/voice/VoiceInput.java b/java/src/com/android/inputmethod/voice/VoiceInput.java index f24c180d0..4c54dd3c5 100644 --- a/java/src/com/android/inputmethod/voice/VoiceInput.java +++ b/java/src/com/android/inputmethod/voice/VoiceInput.java @@ -16,6 +16,7 @@ package com.android.inputmethod.voice; +import com.android.inputmethod.latin.EditingUtil; import com.android.inputmethod.latin.R; import android.content.ContentResolver; @@ -30,6 +31,7 @@ import android.speech.RecognitionListener; import android.speech.SpeechRecognizer; import android.speech.RecognizerIntent; import android.util.Log; +import android.view.inputmethod.InputConnection; import android.view.View; import android.view.View.OnClickListener; @@ -423,8 +425,14 @@ public class VoiceInput implements OnClickListener { mLogger.textModifiedByTypingDeletion(length); } - public void logTextModifiedByChooseSuggestion(int length) { - mLogger.textModifiedByChooseSuggestion(length); + public void logTextModifiedByChooseSuggestion(String suggestion, int index, + String wordSeparators, InputConnection ic) { + EditingUtil.Range range = new EditingUtil.Range(); + String wordToBeReplaced = EditingUtil.getWordAtCursor(ic, wordSeparators, range); + // If we enable phrase-based alternatives, only send up the first word + // in suggestion and wordToBeReplaced. + mLogger.textModifiedByChooseSuggestion(suggestion.length(), wordToBeReplaced.length(), + index, wordToBeReplaced, suggestion); } public void logKeyboardWarningDialogShown() { @@ -455,10 +463,6 @@ public class VoiceInput implements OnClickListener { mLogger.voiceInputDelivered(length); } - public void logNBestChoose(int index) { - mLogger.nBestChoose(index); - } - public void logInputEnded() { mLogger.inputEnded(); } diff --git a/java/src/com/android/inputmethod/voice/VoiceInputLogger.java b/java/src/com/android/inputmethod/voice/VoiceInputLogger.java index 9d3a92037..4d50f5ee8 100644 --- a/java/src/com/android/inputmethod/voice/VoiceInputLogger.java +++ b/java/src/com/android/inputmethod/voice/VoiceInputLogger.java @@ -178,20 +178,19 @@ public class VoiceInputLogger { mContext.sendBroadcast(i); } - public void textModifiedByChooseSuggestion(int length) { + public void textModifiedByChooseSuggestion(int suggestionLength, int replacedPhraseLength, + int index, String before, String after) { Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.TEXT_MODIFIED); - i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_LENGTH, length); + i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_LENGTH, suggestionLength); + i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_REPLACED_LENGTH, replacedPhraseLength); i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_TYPE, LoggingEvents.VoiceIme.TEXT_MODIFIED_TYPE_CHOOSE_SUGGESTION); + i.putExtra(LoggingEvents.VoiceIme.EXTRA_N_BEST_CHOOSE_INDEX, index); + i.putExtra(LoggingEvents.VoiceIme.EXTRA_BEFORE_N_BEST_CHOOSE, before); + i.putExtra(LoggingEvents.VoiceIme.EXTRA_AFTER_N_BEST_CHOOSE, after); mContext.sendBroadcast(i); } - public void nBestChoose(int index) { - Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.N_BEST_CHOOSE); - i.putExtra(LoggingEvents.VoiceIme.EXTRA_N_BEST_CHOOSE_INDEX, index); - mContext.sendBroadcast(i); - } - public void inputEnded() { mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.INPUT_ENDED)); } From c788e3c3c9c87d24bbeb2ad06b60b863fc761313 Mon Sep 17 00:00:00 2001 From: Eric Fischer Date: Mon, 30 Aug 2010 13:40:34 -0700 Subject: [PATCH 13/58] Import revised translations Change-Id: I4de68ff4db492e7efbaafaf01c7d1b97110a948a --- java/res/values-cs/strings.xml | 4 +++- java/res/values-da/strings.xml | 4 +++- java/res/values-de/strings.xml | 4 +++- java/res/values-el/strings.xml | 4 +++- java/res/values-es-rUS/strings.xml | 4 +++- java/res/values-es/strings.xml | 4 +++- java/res/values-fr/strings.xml | 4 +++- java/res/values-it/strings.xml | 4 +++- java/res/values-ja/strings.xml | 4 +++- java/res/values-ko/strings.xml | 4 +++- java/res/values-nb/strings.xml | 4 +++- java/res/values-nl/strings.xml | 4 +++- java/res/values-pl/strings.xml | 4 +++- java/res/values-pt-rPT/strings.xml | 4 +++- java/res/values-pt/strings.xml | 4 +++- java/res/values-rm/strings.xml | 4 +++- java/res/values-ru/strings.xml | 4 +++- java/res/values-sv/strings.xml | 4 +++- java/res/values-tr/strings.xml | 4 +++- java/res/values-zh-rCN/strings.xml | 4 +++- java/res/values-zh-rTW/strings.xml | 4 +++- 21 files changed, 63 insertions(+), 21 deletions(-) diff --git a/java/res/values-cs/strings.xml b/java/res/values-cs/strings.xml index 798d0807e..1269658dd 100644 --- a/java/res/values-cs/strings.xml +++ b/java/res/values-cs/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml index 9c525a3e0..ff9dec5f5 100644 --- a/java/res/values-da/strings.xml +++ b/java/res/values-da/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-de/strings.xml b/java/res/values-de/strings.xml index 047b11420..d00a7d1d0 100644 --- a/java/res/values-de/strings.xml +++ b/java/res/values-de/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-el/strings.xml b/java/res/values-el/strings.xml index ef79ea097..7f5c1f761 100644 --- a/java/res/values-el/strings.xml +++ b/java/res/values-el/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-es-rUS/strings.xml b/java/res/values-es-rUS/strings.xml index 8cf11dfa2..068555a9d 100644 --- a/java/res/values-es-rUS/strings.xml +++ b/java/res/values-es-rUS/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-es/strings.xml b/java/res/values-es/strings.xml index 6d3823918..0fdb509fb 100644 --- a/java/res/values-es/strings.xml +++ b/java/res/values-es/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-fr/strings.xml b/java/res/values-fr/strings.xml index 544789b2d..56643bc88 100644 --- a/java/res/values-fr/strings.xml +++ b/java/res/values-fr/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-it/strings.xml b/java/res/values-it/strings.xml index 486a60ef8..c1d44bc22 100644 --- a/java/res/values-it/strings.xml +++ b/java/res/values-it/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-ja/strings.xml b/java/res/values-ja/strings.xml index cfa5a9746..c5757597b 100644 --- a/java/res/values-ja/strings.xml +++ b/java/res/values-ja/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-ko/strings.xml b/java/res/values-ko/strings.xml index 8fd4e63e8..b61285253 100644 --- a/java/res/values-ko/strings.xml +++ b/java/res/values-ko/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml index 7fbac9bdd..53eeab9f1 100644 --- a/java/res/values-nb/strings.xml +++ b/java/res/values-nb/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml index b4b0ab29f..8e33a3463 100644 --- a/java/res/values-nl/strings.xml +++ b/java/res/values-nl/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-pl/strings.xml b/java/res/values-pl/strings.xml index 8ca1650cd..a4b5210b9 100644 --- a/java/res/values-pl/strings.xml +++ b/java/res/values-pl/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-pt-rPT/strings.xml b/java/res/values-pt-rPT/strings.xml index 5fbff0fe7..2fd97f0d9 100644 --- a/java/res/values-pt-rPT/strings.xml +++ b/java/res/values-pt-rPT/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-pt/strings.xml b/java/res/values-pt/strings.xml index 70288efd4..88f2ce151 100644 --- a/java/res/values-pt/strings.xml +++ b/java/res/values-pt/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-rm/strings.xml b/java/res/values-rm/strings.xml index c32a2efa9..f30b41fa2 100644 --- a/java/res/values-rm/strings.xml +++ b/java/res/values-rm/strings.xml @@ -140,6 +140,8 @@ - + + + diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml index 1898d27eb..dabbf036d 100644 --- a/java/res/values-ru/strings.xml +++ b/java/res/values-ru/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml index 49359e8b9..397672884 100644 --- a/java/res/values-sv/strings.xml +++ b/java/res/values-sv/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-tr/strings.xml b/java/res/values-tr/strings.xml index 73ad111f3..1dc55a777 100644 --- a/java/res/values-tr/strings.xml +++ b/java/res/values-tr/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-zh-rCN/strings.xml b/java/res/values-zh-rCN/strings.xml index 046d1d664..fd37c2bd6 100644 --- a/java/res/values-zh-rCN/strings.xml +++ b/java/res/values-zh-rCN/strings.xml @@ -138,6 +138,8 @@ - + + + diff --git a/java/res/values-zh-rTW/strings.xml b/java/res/values-zh-rTW/strings.xml index 182f71192..0ef399e85 100644 --- a/java/res/values-zh-rTW/strings.xml +++ b/java/res/values-zh-rTW/strings.xml @@ -138,6 +138,8 @@ - + + + From 673aed42c3b291fc9f81ead58ca35a5d150f4dce Mon Sep 17 00:00:00 2001 From: satok Date: Mon, 30 Aug 2010 18:38:36 +0900 Subject: [PATCH 14/58] Add settings button - delete unused keyboard layout Change-Id: Iab39446653460797f1ca876a7d9a23190c3a8df6 --- .../sym_keyboard_feedback_settings.png | Bin 0 -> 729 bytes .../drawable-hdpi/sym_keyboard_settings.png | Bin 0 -> 1459 bytes .../sym_keyboard_feedback_settings.png | Bin 0 -> 729 bytes java/res/drawable/sym_keyboard_settings.png | Bin 0 -> 1459 bytes java/res/values/keycodes.xml | 1 + java/res/xml/kbd_alpha.xml | 106 ------------------ java/res/xml/kbd_alpha_black.xml | 106 ------------------ java/res/xml/kbd_qwerty.xml | 58 +++++----- java/res/xml/kbd_qwerty_black.xml | 62 +++++----- java/res/xml/kbd_symbols.xml | 9 +- java/res/xml/kbd_symbols_black.xml | 9 +- java/res/xml/kbd_symbols_shift.xml | 9 +- java/res/xml/kbd_symbols_shift_black.xml | 9 +- .../inputmethod/latin/KeyboardSwitcher.java | 17 +-- 14 files changed, 93 insertions(+), 293 deletions(-) create mode 100644 java/res/drawable-hdpi/sym_keyboard_feedback_settings.png create mode 100644 java/res/drawable-hdpi/sym_keyboard_settings.png create mode 100644 java/res/drawable/sym_keyboard_feedback_settings.png create mode 100644 java/res/drawable/sym_keyboard_settings.png delete mode 100644 java/res/xml/kbd_alpha.xml delete mode 100644 java/res/xml/kbd_alpha_black.xml diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_settings.png b/java/res/drawable-hdpi/sym_keyboard_feedback_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..08ba18f28db90ae647f03e5ee4111cc29a2ebb27 GIT binary patch literal 729 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 + -100 -103 diff --git a/java/res/xml/kbd_alpha.xml b/java/res/xml/kbd_alpha.xml deleted file mode 100644 index 4e8af3399..000000000 --- a/java/res/xml/kbd_alpha.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/java/res/xml/kbd_alpha_black.xml b/java/res/xml/kbd_alpha_black.xml deleted file mode 100644 index 108e466b8..000000000 --- a/java/res/xml/kbd_alpha_black.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/java/res/xml/kbd_qwerty.xml b/java/res/xml/kbd_qwerty.xml index b0450c6cd..59c61e4c8 100755 --- a/java/res/xml/kbd_qwerty.xml +++ b/java/res/xml/kbd_qwerty.xml @@ -111,74 +111,81 @@ + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="10%p" android:keyEdgeFlags="left"/> + @@ -187,12 +194,11 @@ android:keyWidth="20%p" android:isRepeatable="true"/> - + android:keyWidth="15%p"/> + + android:keyWidth="15%p" android:keyEdgeFlags="right"/> - - diff --git a/java/res/xml/kbd_qwerty_black.xml b/java/res/xml/kbd_qwerty_black.xml index afea2f379..076359c95 100755 --- a/java/res/xml/kbd_qwerty_black.xml +++ b/java/res/xml/kbd_qwerty_black.xml @@ -110,75 +110,82 @@ - + + - + + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - + + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="10%p" android:keyEdgeFlags="left"/> + @@ -187,11 +194,12 @@ android:keyWidth="20%p" android:isRepeatable="true"/> - + android:keyWidth="15%p"/> + + android:keyWidth="15%p" android:keyEdgeFlags="right"/> diff --git a/java/res/xml/kbd_symbols.xml b/java/res/xml/kbd_symbols.xml index 77eb7d059..3f6b8ac85 100755 --- a/java/res/xml/kbd_symbols.xml +++ b/java/res/xml/kbd_symbols.xml @@ -123,16 +123,19 @@ + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - diff --git a/java/res/xml/kbd_symbols_black.xml b/java/res/xml/kbd_symbols_black.xml index 5f8dfbeaa..7eae55481 100755 --- a/java/res/xml/kbd_symbols_black.xml +++ b/java/res/xml/kbd_symbols_black.xml @@ -123,16 +123,19 @@ + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - diff --git a/java/res/xml/kbd_symbols_shift.xml b/java/res/xml/kbd_symbols_shift.xml index 467ca529f..0ec4c713c 100755 --- a/java/res/xml/kbd_symbols_shift.xml +++ b/java/res/xml/kbd_symbols_shift.xml @@ -89,16 +89,19 @@ - + diff --git a/java/res/xml/kbd_symbols_shift_black.xml b/java/res/xml/kbd_symbols_shift_black.xml index 511ad4981..250e0854c 100755 --- a/java/res/xml/kbd_symbols_shift_black.xml +++ b/java/res/xml/kbd_symbols_shift_black.xml @@ -89,16 +89,19 @@ - + diff --git a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java index 45a54b1aa..a50c5aa41 100644 --- a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java @@ -37,11 +37,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha public static final int MODE_EMAIL = 5; public static final int MODE_IM = 6; public static final int MODE_WEB = 7; - - public static final int MODE_TEXT_QWERTY = 0; - public static final int MODE_TEXT_ALPHA = 1; - public static final int MODE_TEXT_COUNT = 2; - + public static final int KEYBOARDMODE_NORMAL = R.id.mode_normal; public static final int KEYBOARDMODE_URL = R.id.mode_url; public static final int KEYBOARDMODE_EMAIL = R.id.mode_email; @@ -59,7 +55,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha private static final int CHAR_THEME_COLOR_BLACK = 1; // Tables which contains resource ids for each character theme color - private static final int[] KBD_ALPHA = new int[] {R.xml.kbd_alpha, R.xml.kbd_alpha_black}; private static final int[] KBD_PHONE = new int[] {R.xml.kbd_phone, R.xml.kbd_phone_black}; private static final int[] KBD_PHONE_SYMBOLS = new int[] { R.xml.kbd_phone_symbols, R.xml.kbd_phone_symbols_black}; @@ -92,7 +87,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha private int mMode = MODE_NONE; /** One of the MODE_XXX values */ private int mImeOptions; - private int mTextMode = MODE_TEXT_QWERTY; private boolean mIsSymbols; private boolean mHasVoice; private boolean mVoiceOnPrimary; @@ -291,11 +285,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha "getKeyboardId:" + mode + "," + imeOptions + "," + isSymbols); /* fall through */ case MODE_TEXT: - if (mTextMode == MODE_TEXT_ALPHA) { - return new KeyboardId( - KBD_ALPHA[charColorId], KEYBOARDMODE_NORMAL, true, hasVoice); - } - // Normally mTextMode should be MODE_TEXT_QWERTY. return new KeyboardId(keyboardRowsResId, KEYBOARDMODE_NORMAL, true, hasVoice); case MODE_SYMBOLS: return new KeyboardId(KBD_SYMBOLS[charColorId], hasVoice); @@ -320,10 +309,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha boolean isTextMode() { return mMode == MODE_TEXT; } - - int getTextModeCount() { - return MODE_TEXT_COUNT; - } boolean isAlphabetMode() { if (mCurrentId == null) { From 0ca1bf71589007fa8f873cbad2ae80c68918ac60 Mon Sep 17 00:00:00 2001 From: satok Date: Tue, 31 Aug 2010 14:11:26 +0900 Subject: [PATCH 15/58] Add missing resources for LatinIME Change-Id: I470387ab9f9d867c1ac839b75fe18c1ce711083d --- .../res/drawable-hdpi/sym_bkeyboard_settings.png | Bin 0 -> 729 bytes .../res/drawable-mdpi/sym_bkeyboard_settings.png | Bin 0 -> 729 bytes .../sym_keyboard_feedback_settings.png | Bin 0 -> 729 bytes java/res/drawable-mdpi/sym_keyboard_settings.png | Bin 0 -> 1459 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 java/res/drawable-hdpi/sym_bkeyboard_settings.png create mode 100644 java/res/drawable-mdpi/sym_bkeyboard_settings.png create mode 100644 java/res/drawable-mdpi/sym_keyboard_feedback_settings.png create mode 100644 java/res/drawable-mdpi/sym_keyboard_settings.png diff --git a/java/res/drawable-hdpi/sym_bkeyboard_settings.png b/java/res/drawable-hdpi/sym_bkeyboard_settings.png new file mode 100644 index 0000000000000000000000000000000000000000..08ba18f28db90ae647f03e5ee4111cc29a2ebb27 GIT binary patch literal 729 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 Date: Tue, 31 Aug 2010 17:01:21 +0900 Subject: [PATCH 16/58] Refactor key preview methods Extract key press and release handling out of previewKey() to KeyDebouncer class. And pass Key object as argument of previewKey() instead of key index. Bug: 2910379 Change-Id: Ifec39cfc4845bd92da2f62eba2b26ac6a5cbb341 --- .../latin/LatinKeyboardBaseView.java | 123 +++++++++++------- 1 file changed, 75 insertions(+), 48 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index d9fa9f2a2..f79b64629 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -204,7 +204,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener /** Listener for {@link OnKeyboardActionListener}. */ private OnKeyboardActionListener mKeyboardActionListener; - private final KeyDebouncer mDebouncer = new KeyDebouncer(); + private final KeyDebouncer mDebouncer; private final float mDebounceHysteresis; private int mCurrentKey = NOT_A_KEY; private int mStartX; @@ -251,7 +251,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener private static final int MSG_POPUP_PREVIEW = 1; private static final int MSG_DISMISS_PREVIEW = 2; private static final int MSG_REPEAT_KEY = 3; - private static final int MSG_LOGPRESS_KEY = 4; + private static final int MSG_LONGPRESS_KEY = 4; private boolean mInKeyRepeat; @@ -259,7 +259,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener public void handleMessage(Message msg) { switch (msg.what) { case MSG_POPUP_PREVIEW: - showKey(msg.arg1); + showKey((Key)msg.obj); break; case MSG_DISMISS_PREVIEW: mPreviewText.setVisibility(INVISIBLE); @@ -268,15 +268,15 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener repeatKey(msg.arg1); startKeyRepeatTimer(REPEAT_INTERVAL, msg.arg1); break; - case MSG_LOGPRESS_KEY: + case MSG_LONGPRESS_KEY: openPopupIfRequired(msg.arg1); break; } } - public void popupPreview(int keyIndex, long delay) { + public void popupPreview(Key key, long delay) { removeMessages(MSG_POPUP_PREVIEW); - sendMessageDelayed(obtainMessage(MSG_POPUP_PREVIEW, keyIndex, 0), delay); + sendMessageDelayed(obtainMessage(MSG_POPUP_PREVIEW, key), delay); } public void cancelPopupPreview() { @@ -306,12 +306,12 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } public void startLongPressTimer(int keyIndex, long delay) { - removeMessages(MSG_LOGPRESS_KEY); - sendMessageDelayed(obtainMessage(MSG_LOGPRESS_KEY, keyIndex, 0), delay); + removeMessages(MSG_LONGPRESS_KEY); + sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, keyIndex, 0), delay); } public void cancelLongPressTimer() { - removeMessages(MSG_LOGPRESS_KEY); + removeMessages(MSG_LONGPRESS_KEY); } public void cancelKeyTimers() { @@ -326,7 +326,12 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } }; - static class KeyDebouncer { + public static class KeyDebouncer { + public interface UIProxy { + public void invalidateKey(Key key); + } + private final UIProxy mProxy; + private Key[] mKeys; private int mKeyDebounceThresholdSquared = -1; @@ -342,6 +347,15 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener private long mLastMoveTime; private long mCurrentKeyTime; + // pressed key + private int mPreviousKey; + + public KeyDebouncer(UIProxy proxy) { + if (proxy == null) + throw new NullPointerException(); + mProxy = proxy; + } + public void setKeyboard(Key[] keys, float hysteresisPixel) { if (keys == null || hysteresisPixel < 1.0f) throw new IllegalArgumentException(); @@ -349,6 +363,23 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener mKeyDebounceThresholdSquared = (int)(hysteresisPixel * hysteresisPixel); } + public void updateKey(int keyIndex) { + int oldKeyIndex = mPreviousKey; + mPreviousKey = keyIndex; + if (keyIndex != oldKeyIndex) { + if (oldKeyIndex != NOT_A_KEY && oldKeyIndex < mKeys.length) { + // if new key index is not a key, old key was just released inside of the key. + final boolean inside = (keyIndex == NOT_A_KEY); + mKeys[oldKeyIndex].onReleased(inside); + mProxy.invalidateKey(mKeys[oldKeyIndex]); + } + if (keyIndex != NOT_A_KEY && keyIndex < mKeys.length) { + mKeys[keyIndex].onPressed(); + mProxy.invalidateKey(mKeys[keyIndex]); + } + } + } + public int getLastCodeX() { return mLastCodeX; } @@ -586,6 +617,14 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener final boolean ignoreMultitouch = true; mGestureDetector = new GestureDetector(getContext(), listener, null, ignoreMultitouch); mGestureDetector.setIsLongpressEnabled(false); + + // TODO: This anonymous interface is temporary until KeyDebouncer becomes top-level class. + // In the future LatinKeyboardBaseView class will implement UIProxy. + mDebouncer = new KeyDebouncer(new KeyDebouncer.UIProxy() { + public void invalidateKey(Key key) { + LatinKeyboardBaseView.this.invalidateKey(key); + } + }); } public void setOnKeyboardActionListener(OnKeyboardActionListener listener) { @@ -609,7 +648,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener */ public void setKeyboard(Keyboard keyboard) { if (mKeyboard != null) { - showPreview(NOT_A_KEY); + showKeyPreviewAndUpdateKey(NOT_A_KEY); } // Remove any pending messages, except dismissing preview mHandler.cancelKeyTimers(); @@ -952,30 +991,21 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener // Multi-tap mPreviewLabel.setLength(0); mPreviewLabel.append((char) key.codes[mTapCount < 0 ? 0 : mTapCount]); - return adjustCase(mPreviewLabel); + return mPreviewLabel; } else { - return adjustCase(key.label); + return key.label; } } + // TODO: clean up this when KeyDebouncer class becomes top-level class. + private void showKeyPreviewAndUpdateKey(int keyIndex) { + mDebouncer.updateKey(keyIndex); + showPreview(keyIndex); + } + private void showPreview(int keyIndex) { int oldKeyIndex = mOldPreviewKeyIndex; mOldPreviewKeyIndex = keyIndex; - - // Release the old key and press the new key - final Key[] keys = mKeys; - if (oldKeyIndex != keyIndex) { - if (oldKeyIndex != NOT_A_KEY && keys.length > oldKeyIndex) { - // if new key index is not a key, old key was just released inside of the key. - final boolean inside = (keyIndex == NOT_A_KEY); - keys[oldKeyIndex].onReleased(inside); - invalidateKey(oldKeyIndex); - } - if (keyIndex != NOT_A_KEY && keys.length > keyIndex) { - keys[keyIndex].onPressed(); - invalidateKey(keyIndex); - } - } // If key changed and preview is on ... if (oldKeyIndex != keyIndex && mShowPreview) { final PopupWindow previewPopup = mPreviewPopup; @@ -987,26 +1017,23 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } else { if (previewPopup.isShowing() && mPreviewText.getVisibility() == VISIBLE) { // Show right away, if it's already visible and finger is moving around - showKey(keyIndex); + showKey(mKeys[keyIndex]); } else { - mHandler.popupPreview(keyIndex, DELAY_BEFORE_PREVIEW); + mHandler.popupPreview(mKeys[keyIndex], DELAY_BEFORE_PREVIEW); } } } } - private void showKey(final int keyIndex) { + private void showKey(final Key key) { final PopupWindow previewPopup = mPreviewPopup; - final Key[] keys = mKeys; - if (keyIndex < 0 || keyIndex >= mKeys.length) return; - Key key = keys[keyIndex]; if (key.icon != null) { mPreviewText.setCompoundDrawables(null, null, null, key.iconPreview != null ? key.iconPreview : key.icon); mPreviewText.setText(null); } else { mPreviewText.setCompoundDrawables(null, null, null, null); - mPreviewText.setText(getPreviewText(key)); + mPreviewText.setText(adjustCase(getPreviewText(key))); if (key.label.length() > 1 && key.codes.length < 2) { mPreviewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mKeyTextSize); mPreviewText.setTypeface(Typeface.DEFAULT_BOLD); @@ -1092,12 +1119,9 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener * @param keyIndex the index of the key in the attached {@link Keyboard}. * @see #invalidateAllKeys */ - public void invalidateKey(int keyIndex) { - if (mKeys == null) return; - if (keyIndex < 0 || keyIndex >= mKeys.length) { + public void invalidateKey(Key key) { + if (key == null) return; - } - final Key key = mKeys[keyIndex]; mInvalidatedKey = key; mDirtyRect.union(key.x + getPaddingLeft(), key.y + getPaddingTop(), key.x + key.width + getPaddingLeft(), key.y + key.height + getPaddingTop()); @@ -1118,7 +1142,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener Key popupKey = mKeys[keyIndex]; boolean result = onLongPress(popupKey); if (result) { - showPreview(NOT_A_KEY); + showKeyPreviewAndUpdateKey(NOT_A_KEY); } return result; } @@ -1234,7 +1258,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener // We must disable gesture detector while mini-keyboard is on the screen. if (!mMiniKeyboardOnScreen && mGestureDetector.onTouchEvent(me)) { - showPreview(NOT_A_KEY); + showKeyPreviewAndUpdateKey(NOT_A_KEY); mHandler.cancelKeyTimers(); return true; } @@ -1317,7 +1341,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener if (keyIndex != NOT_A_KEY) { mHandler.startLongPressTimer(keyIndex, LONGPRESS_TIMEOUT); } - showPreview(keyIndex); + showKeyPreviewAndUpdateKey(keyIndex); mDebouncer.updateMoveDebouncing(touchX, touchY); } @@ -1346,7 +1370,8 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener * eventually, the last key should be sent as the result. In such case mCurrentKey * should not be showed as popup preview. */ - showPreview(mDebouncer.isMinorTimeBounce() ? mDebouncer.getLastKey() : mCurrentKey); + showKeyPreviewAndUpdateKey( + mDebouncer.isMinorTimeBounce() ? mDebouncer.getLastKey() : mCurrentKey); mDebouncer.updateMoveDebouncing(touchX, touchY); } @@ -1367,20 +1392,22 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener touchX = mDebouncer.getLastCodeX(); touchY = mDebouncer.getLastCodeY(); } - showPreview(NOT_A_KEY); + showKeyPreviewAndUpdateKey(NOT_A_KEY); // If we're not on a repeating key (which sends on a DOWN event) if (!wasInKeyRepeat && !mMiniKeyboardOnScreen) { detectAndSendKey(mCurrentKey, touchX, touchY, eventTime); } - invalidateKey(keyIndex); + if (keyIndex != NOT_A_KEY) + invalidateKey(mKeys[keyIndex]); } private void onCancelEvent(int touchX, int touchY, long eventTime) { mHandler.cancelKeyTimers(); mHandler.cancelPopupPreview(); dismissPopupKeyboard(); - showPreview(NOT_A_KEY); - invalidateKey(mCurrentKey); + showKeyPreviewAndUpdateKey(NOT_A_KEY); + if (mCurrentKey != NOT_A_KEY) + invalidateKey(mKeys[mCurrentKey]); } private void repeatKey(int keyIndex) { From b57b47856930ca4b7a5391f92947ab2ce9de9c59 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Tue, 31 Aug 2010 20:21:45 +0900 Subject: [PATCH 17/58] Refactor KeyDebounce class This change moves the following methods into KeyDebounce class. - MotionEvent handling methods (onDownEvent etc.). - Keyboard action event generator method (detectAndSendKey). - Multi-tap key support methods (resetMultiTap etc.). - Key preview text generator method (getPreviewText). The change that makes KeyDebounce a top-level class will follow. Bug: 2910379 Change-Id: I1526c0461e247d97f0c4b3bd580330f137c787be --- .../latin/LatinKeyboardBaseView.java | 562 ++++++++++-------- 1 file changed, 304 insertions(+), 258 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index f79b64629..efce0d193 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -188,7 +188,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener private int mPopupPreviewX; private int mPopupPreviewY; private int mWindowY; - private final StringBuilder mPreviewLabel = new StringBuilder(1); // Popup mini keyboard private PopupWindow mPopupKeyboard; @@ -206,18 +205,9 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener private final KeyDebouncer mDebouncer; private final float mDebounceHysteresis; - private int mCurrentKey = NOT_A_KEY; - private int mStartX; - private int mStartY; private final ProximityKeyDetector mProximityKeyDetector = new ProximityKeyDetector(); - // For multi-tap - private int mLastSentIndex; - private int mTapCount; - private long mLastTapTime; - private boolean mInMultiTap; - // Variables for dealing with multiple pointers private int mOldPointerCount = 1; private int mOldPointerX; @@ -259,24 +249,32 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener public void handleMessage(Message msg) { switch (msg.what) { case MSG_POPUP_PREVIEW: - showKey((Key)msg.obj); + showKey(msg.arg1, (KeyDebouncer)msg.obj); break; case MSG_DISMISS_PREVIEW: mPreviewText.setVisibility(INVISIBLE); break; - case MSG_REPEAT_KEY: - repeatKey(msg.arg1); - startKeyRepeatTimer(REPEAT_INTERVAL, msg.arg1); + case MSG_REPEAT_KEY: { + final KeyDebouncer debouncer = (KeyDebouncer)msg.obj; + debouncer.repeatKey(msg.arg1); + startKeyRepeatTimer(REPEAT_INTERVAL, msg.arg1, debouncer); break; + } case MSG_LONGPRESS_KEY: openPopupIfRequired(msg.arg1); break; } } - public void popupPreview(Key key, long delay) { + public void popupPreview(long delay, int keyIndex, KeyDebouncer debouncer) { removeMessages(MSG_POPUP_PREVIEW); - sendMessageDelayed(obtainMessage(MSG_POPUP_PREVIEW, key), delay); + if (mPreviewPopup.isShowing() && mPreviewText.getVisibility() == VISIBLE) { + // Show right away, if it's already visible and finger is moving around + showKey(keyIndex, debouncer); + } else { + sendMessageDelayed(obtainMessage(MSG_POPUP_PREVIEW, keyIndex, 0, debouncer), + delay); + } } public void cancelPopupPreview() { @@ -284,16 +282,18 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } public void dismissPreview(long delay) { - sendMessageDelayed(obtainMessage(MSG_DISMISS_PREVIEW), delay); + if (mPreviewPopup.isShowing()) { + sendMessageDelayed(obtainMessage(MSG_DISMISS_PREVIEW), delay); + } } public void cancelDismissPreview() { removeMessages(MSG_DISMISS_PREVIEW); } - public void startKeyRepeatTimer(long delay, int keyIndex) { + public void startKeyRepeatTimer(long delay, int keyIndex, KeyDebouncer debouncer) { mInKeyRepeat = true; - sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, keyIndex, 0), delay); + sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, keyIndex, 0, debouncer), delay); } public void cancelKeyRepeatTimer() { @@ -326,15 +326,28 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } }; + // TODO:nn Rename this class to PointerTracker when this becomes a top-level class. public static class KeyDebouncer { public interface UIProxy { public void invalidateKey(Key key); + public void showPreview(int keyIndex, KeyDebouncer debouncer); + // TODO: These methods might be temporary. + public void dismissPopupKeyboard(); + public boolean isMiniKeyboardOnScreen(); } + private final UIProxy mProxy; + private final UIHandler mHandler; + private final ProximityKeyDetector mKeyDetector; + private OnKeyboardActionListener mListener; private Key[] mKeys; private int mKeyDebounceThresholdSquared = -1; + private int mCurrentKey = NOT_A_KEY; + private int mStartX; + private int mStartY; + // for move de-bouncing private int mLastCodeX; private int mLastCodeY; @@ -347,13 +360,27 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener private long mLastMoveTime; private long mCurrentKeyTime; + // For multi-tap + private int mLastSentIndex; + private int mTapCount; + private long mLastTapTime; + private boolean mInMultiTap; + private final StringBuilder mPreviewLabel = new StringBuilder(1); + // pressed key private int mPreviousKey; - public KeyDebouncer(UIProxy proxy) { - if (proxy == null) + public KeyDebouncer(UIHandler handler, ProximityKeyDetector keyDetector, UIProxy proxy) { + if (proxy == null || handler == null || keyDetector == null) throw new NullPointerException(); mProxy = proxy; + mHandler = handler; + mKeyDetector = keyDetector; + resetMultiTap(); + } + + public void setOnKeyboardActionListener(OnKeyboardActionListener listener) { + mListener = listener; } public void setKeyboard(Key[] keys, float hysteresisPixel) { @@ -363,6 +390,10 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener mKeyDebounceThresholdSquared = (int)(hysteresisPixel * hysteresisPixel); } + public Key getKey(int keyIndex) { + return (keyIndex >= 0 && keyIndex < mKeys.length) ? mKeys[keyIndex] : null; + } + public void updateKey(int keyIndex) { int oldKeyIndex = mPreviousKey; mPreviousKey = keyIndex; @@ -380,42 +411,148 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } } - public int getLastCodeX() { - return mLastCodeX; + public void onModifiedTouchEvent(int action, int touchX, int touchY, long eventTime) { + switch (action) { + case MotionEvent.ACTION_DOWN: + onDownEvent(touchX, touchY, eventTime); + break; + case MotionEvent.ACTION_MOVE: + onMoveEvent(touchX, touchY, eventTime); + break; + case MotionEvent.ACTION_UP: + onUpEvent(touchX, touchY, eventTime); + break; + case MotionEvent.ACTION_CANCEL: + onCancelEvent(touchX, touchY, eventTime); + break; + } } - public int getLastCodeY() { - return mLastCodeY; + public void onDownEvent(int touchX, int touchY, long eventTime) { + int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); + mCurrentKey = keyIndex; + mStartX = touchX; + mStartY = touchY; + startMoveDebouncing(touchX, touchY); + startTimeDebouncing(eventTime); + checkMultiTap(eventTime, keyIndex); + if (mListener != null) + mListener.onPress(keyIndex != NOT_A_KEY ? mKeys[keyIndex].codes[0] : 0); + if (keyIndex >= 0 && mKeys[keyIndex].repeatable) { + repeatKey(keyIndex); + mHandler.startKeyRepeatTimer(REPEAT_START_DELAY, keyIndex, this); + } + if (keyIndex != NOT_A_KEY) { + mHandler.startLongPressTimer(keyIndex, LONGPRESS_TIMEOUT); + } + showKeyPreviewAndUpdateKey(keyIndex); + updateMoveDebouncing(touchX, touchY); } - public int getLastX() { + public void onMoveEvent(int touchX, int touchY, long eventTime) { + int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); + if (keyIndex != NOT_A_KEY) { + if (mCurrentKey == NOT_A_KEY) { + updateTimeDebouncing(eventTime); + mCurrentKey = keyIndex; + mHandler.startLongPressTimer(keyIndex, LONGPRESS_TIMEOUT); + } else if (isMinorMoveBounce(touchX, touchY, keyIndex, mCurrentKey)) { + updateTimeDebouncing(eventTime); + } else { + resetMultiTap(); + resetTimeDebouncing(eventTime, mCurrentKey); + resetMoveDebouncing(); + mCurrentKey = keyIndex; + mHandler.startLongPressTimer(keyIndex, LONGPRESS_TIMEOUT); + } + } else { + mHandler.cancelLongPressTimer(); + } + /* + * While time debouncing is in effect, mCurrentKey holds the new key and mDebouncer + * holds the last key. At ACTION_UP event if time debouncing will be in effect + * eventually, the last key should be sent as the result. In such case mCurrentKey + * should not be showed as popup preview. + */ + showKeyPreviewAndUpdateKey(isMinorTimeBounce() ? mLastKey : mCurrentKey); + updateMoveDebouncing(touchX, touchY); + } + + public void onUpEvent(int touchX, int touchY, long eventTime) { + int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); + boolean wasInKeyRepeat = mHandler.isInKeyRepeat(); + mHandler.cancelKeyTimers(); + mHandler.cancelPopupPreview(); + if (isMinorMoveBounce(touchX, touchY, keyIndex, mCurrentKey)) { + updateTimeDebouncing(eventTime); + } else { + resetMultiTap(); + resetTimeDebouncing(eventTime, mCurrentKey); + mCurrentKey = keyIndex; + } + if (isMinorTimeBounce()) { + mCurrentKey = mLastKey; + touchX = mLastCodeX; + touchY = mLastCodeY; + } + showKeyPreviewAndUpdateKey(NOT_A_KEY); + // If we're not on a repeating key (which sends on a DOWN event) + if (!wasInKeyRepeat && !mProxy.isMiniKeyboardOnScreen()) { + detectAndSendKey(mCurrentKey, touchX, touchY, eventTime); + } + if (keyIndex != NOT_A_KEY) + mProxy.invalidateKey(mKeys[keyIndex]); + } + + public void onCancelEvent(int touchX, int touchY, long eventTime) { + mHandler.cancelKeyTimers(); + mHandler.cancelPopupPreview(); + mProxy.dismissPopupKeyboard(); + showKeyPreviewAndUpdateKey(NOT_A_KEY); + if (mCurrentKey != NOT_A_KEY) + mProxy.invalidateKey(mKeys[mCurrentKey]); + } + + public void repeatKey(int keyIndex) { + Key key = mKeys[keyIndex]; + // While key is repeating, because there is no need to handle multi-tap key, we can pass + // -1 as eventTime argument. + detectAndSendKey(keyIndex, key.x, key.y, -1); + } + + // These package scope methods are only for debugging purpose. + /* package */ int getStartX() { + return mStartX; + } + + /* package */ int getStartY() { + return mStartY; + } + + /* package */ int getLastX() { return mLastX; } - public int getLastY() { + /* package */ int getLastY() { return mLastY; } - public int getLastKey() { - return mLastKey; - } - - public void startMoveDebouncing(int x, int y) { + private void startMoveDebouncing(int x, int y) { mLastCodeX = x; mLastCodeY = y; } - public void updateMoveDebouncing(int x, int y) { + private void updateMoveDebouncing(int x, int y) { mLastX = x; mLastY = y; } - public void resetMoveDebouncing() { + private void resetMoveDebouncing() { mLastCodeX = mLastX; mLastCodeY = mLastY; } - public boolean isMinorMoveBounce(int x, int y, int newKey, int curKey) { + private boolean isMinorMoveBounce(int x, int y, int newKey, int curKey) { if (mKeys == null || mKeyDebounceThresholdSquared < 0) throw new IllegalStateException("keyboard and/or hysteresis not set"); if (newKey == curKey) { @@ -440,29 +577,115 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener return dx * dx + dy * dy; } - public void startTimeDebouncing(long eventTime) { + private void startTimeDebouncing(long eventTime) { mLastKey = NOT_A_KEY; mLastKeyTime = 0; mCurrentKeyTime = 0; mLastMoveTime = eventTime; } - public void updateTimeDebouncing(long eventTime) { + private void updateTimeDebouncing(long eventTime) { mCurrentKeyTime += eventTime - mLastMoveTime; mLastMoveTime = eventTime; } - public void resetTimeDebouncing(long eventTime, int currentKey) { + private void resetTimeDebouncing(long eventTime, int currentKey) { mLastKey = currentKey; mLastKeyTime = mCurrentKeyTime + eventTime - mLastMoveTime; mCurrentKeyTime = 0; mLastMoveTime = eventTime; } - public boolean isMinorTimeBounce() { + private boolean isMinorTimeBounce() { return mCurrentKeyTime < mLastKeyTime && mCurrentKeyTime < KEY_DEBOUNCE_TIME && mLastKey != NOT_A_KEY; } + + private void showKeyPreviewAndUpdateKey(int keyIndex) { + updateKey(keyIndex); + mProxy.showPreview(keyIndex, this); + } + + private void detectAndSendKey(int index, int x, int y, long eventTime) { + if (index != NOT_A_KEY && index < mKeys.length) { + final Key key = mKeys[index]; + OnKeyboardActionListener listener = mListener; + if (key.text != null) { + if (listener != null) { + listener.onText(key.text); + listener.onRelease(NOT_A_KEY); + } + } else { + int code = key.codes[0]; + //TextEntryState.keyPressedAt(key, x, y); + int[] codes = mKeyDetector.newCodeArray(); + mKeyDetector.getKeyIndexAndNearbyCodes(x, y, codes); + // Multi-tap + if (mInMultiTap) { + if (mTapCount != -1) { + mListener.onKey(Keyboard.KEYCODE_DELETE, KEY_DELETE, x, y); + } else { + mTapCount = 0; + } + code = key.codes[mTapCount]; + } + /* + * Swap the first and second values in the codes array if the primary code is not + * the first value but the second value in the array. This happens when key + * debouncing is in effect. + */ + if (codes.length >= 2 && codes[0] != code && codes[1] == code) { + codes[1] = codes[0]; + codes[0] = code; + } + if (listener != null) { + listener.onKey(code, codes, x, y); + listener.onRelease(code); + } + } + mLastSentIndex = index; + mLastTapTime = eventTime; + } + } + + /** + * Handle multi-tap keys by producing the key label for the current multi-tap state. + */ + public CharSequence getPreviewText(Key key) { + if (mInMultiTap) { + // Multi-tap + mPreviewLabel.setLength(0); + mPreviewLabel.append((char) key.codes[mTapCount < 0 ? 0 : mTapCount]); + return mPreviewLabel; + } else { + return key.label; + } + } + + private void resetMultiTap() { + mLastSentIndex = NOT_A_KEY; + mTapCount = 0; + mLastTapTime = -1; + mInMultiTap = false; + } + + private void checkMultiTap(long eventTime, int keyIndex) { + if (keyIndex == NOT_A_KEY) return; + Key key = mKeys[keyIndex]; + if (key.codes.length > 1) { + mInMultiTap = true; + if (eventTime < mLastTapTime + MULTITAP_INTERVAL && keyIndex == mLastSentIndex) { + mTapCount = (mTapCount + 1) % key.codes.length; + return; + } else { + mTapCount = -1; + return; + } + } + if (eventTime > mLastTapTime + MULTITAP_INTERVAL || keyIndex != mLastSentIndex) { + resetMultiTap(); + } + } } public LatinKeyboardBaseView(Context context, AttributeSet attrs) { @@ -573,7 +796,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener // TODO: Refer frameworks/base/core/res/res/values/config.xml mDisambiguateSwipe = res.getBoolean(R.bool.config_swipeDisambiguation); mDebounceHysteresis = res.getDimension(R.dimen.key_debounce_hysteresis_distance); - resetMultiTap(); GestureDetector.SimpleOnGestureListener listener = new GestureDetector.SimpleOnGestureListener() { @@ -620,15 +842,28 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener // TODO: This anonymous interface is temporary until KeyDebouncer becomes top-level class. // In the future LatinKeyboardBaseView class will implement UIProxy. - mDebouncer = new KeyDebouncer(new KeyDebouncer.UIProxy() { + mDebouncer = new KeyDebouncer(mHandler, mProximityKeyDetector, new KeyDebouncer.UIProxy() { public void invalidateKey(Key key) { LatinKeyboardBaseView.this.invalidateKey(key); } + + public void showPreview(int keyIndex, KeyDebouncer debouncer) { + LatinKeyboardBaseView.this.showPreview(keyIndex, debouncer); + } + + public void dismissPopupKeyboard() { + LatinKeyboardBaseView.this.dismissPopupKeyboard(); + } + + public boolean isMiniKeyboardOnScreen() { + return LatinKeyboardBaseView.this.mMiniKeyboardOnScreen; + } }); } public void setOnKeyboardActionListener(OnKeyboardActionListener listener) { mKeyboardActionListener = listener; + mDebouncer.setOnKeyboardActionListener(listener); } /** @@ -648,7 +883,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener */ public void setKeyboard(Keyboard keyboard) { if (mKeyboard != null) { - showKeyPreviewAndUpdateKey(NOT_A_KEY); + dismissKeyPreview(); } // Remove any pending messages, except dismissing preview mHandler.cancelKeyTimers(); @@ -928,16 +1163,19 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener if (DEBUG) { if (mShowTouchPoints) { - int lastX = mDebouncer.getLastX(); - int lastY = mDebouncer.getLastY(); + KeyDebouncer debouncer = mDebouncer; + int startX = debouncer.getStartX(); + int startY = debouncer.getStartY(); + int lastX = debouncer.getLastX(); + int lastY = debouncer.getLastY(); paint.setAlpha(128); paint.setColor(0xFFFF0000); - canvas.drawCircle(mStartX, mStartY, 3, paint); - canvas.drawLine(mStartX, mStartY, lastX, lastY, paint); + canvas.drawCircle(startX, startY, 3, paint); + canvas.drawLine(startX, startY, lastX, lastY, paint); paint.setColor(0xFF0000FF); canvas.drawCircle(lastX, lastY, 3, paint); paint.setColor(0xFF00FF00); - canvas.drawCircle((mStartX + lastX) / 2, (mStartY + lastY) / 2, 2, paint); + canvas.drawCircle((startX + lastX) / 2, (startY + lastY) / 2, 2, paint); } } @@ -945,87 +1183,30 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener mDirtyRect.setEmpty(); } - - private void detectAndSendKey(int index, int x, int y, long eventTime) { - if (index != NOT_A_KEY && index < mKeys.length) { - final Key key = mKeys[index]; - if (key.text != null) { - mKeyboardActionListener.onText(key.text); - mKeyboardActionListener.onRelease(NOT_A_KEY); - } else { - int code = key.codes[0]; - //TextEntryState.keyPressedAt(key, x, y); - int[] codes = mProximityKeyDetector.newCodeArray(); - mProximityKeyDetector.getKeyIndexAndNearbyCodes(x, y, codes); - // Multi-tap - if (mInMultiTap) { - if (mTapCount != -1) { - mKeyboardActionListener.onKey(Keyboard.KEYCODE_DELETE, KEY_DELETE, x, y); - } else { - mTapCount = 0; - } - code = key.codes[mTapCount]; - } - /* - * Swap the first and second values in the codes array if the primary code is not - * the first value but the second value in the array. This happens when key - * debouncing is in effect. - */ - if (codes.length >= 2 && codes[0] != code && codes[1] == code) { - codes[1] = codes[0]; - codes[0] = code; - } - mKeyboardActionListener.onKey(code, codes, x, y); - mKeyboardActionListener.onRelease(code); - } - mLastSentIndex = index; - mLastTapTime = eventTime; - } - } - - /** - * Handle multi-tap keys by producing the key label for the current multi-tap state. - */ - private CharSequence getPreviewText(Key key) { - if (mInMultiTap) { - // Multi-tap - mPreviewLabel.setLength(0); - mPreviewLabel.append((char) key.codes[mTapCount < 0 ? 0 : mTapCount]); - return mPreviewLabel; - } else { - return key.label; - } - } - // TODO: clean up this when KeyDebouncer class becomes top-level class. - private void showKeyPreviewAndUpdateKey(int keyIndex) { - mDebouncer.updateKey(keyIndex); - showPreview(keyIndex); + private void dismissKeyPreview() { + mDebouncer.updateKey(NOT_A_KEY); + showPreview(NOT_A_KEY, mDebouncer); } - private void showPreview(int keyIndex) { + private void showPreview(int keyIndex, KeyDebouncer debouncer) { int oldKeyIndex = mOldPreviewKeyIndex; mOldPreviewKeyIndex = keyIndex; // If key changed and preview is on ... if (oldKeyIndex != keyIndex && mShowPreview) { - final PopupWindow previewPopup = mPreviewPopup; if (keyIndex == NOT_A_KEY) { mHandler.cancelPopupPreview(); - if (previewPopup.isShowing()) { - mHandler.dismissPreview(DELAY_AFTER_PREVIEW); - } + mHandler.dismissPreview(DELAY_AFTER_PREVIEW); } else { - if (previewPopup.isShowing() && mPreviewText.getVisibility() == VISIBLE) { - // Show right away, if it's already visible and finger is moving around - showKey(mKeys[keyIndex]); - } else { - mHandler.popupPreview(mKeys[keyIndex], DELAY_BEFORE_PREVIEW); - } + mHandler.popupPreview(DELAY_BEFORE_PREVIEW, keyIndex, debouncer); } } } - private void showKey(final Key key) { + private void showKey(final int keyIndex, KeyDebouncer debouncer) { + Key key = debouncer.getKey(keyIndex); + if (key == null) + return; final PopupWindow previewPopup = mPreviewPopup; if (key.icon != null) { mPreviewText.setCompoundDrawables(null, null, null, @@ -1033,7 +1214,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener mPreviewText.setText(null); } else { mPreviewText.setCompoundDrawables(null, null, null, null); - mPreviewText.setText(adjustCase(getPreviewText(key))); + mPreviewText.setText(adjustCase(debouncer.getPreviewText(key))); if (key.label.length() > 1 && key.codes.length < 2) { mPreviewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mKeyTextSize); mPreviewText.setTypeface(Typeface.DEFAULT_BOLD); @@ -1104,7 +1285,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener * Requests a redraw of the entire keyboard. Calling {@link #invalidate} is not sufficient * because the keyboard renders the keys to an off-screen buffer and an invalidate() only * draws the cached buffer. - * @see #invalidateKey(int) + * @see #invalidateKey(Key) */ public void invalidateAllKeys() { mDirtyRect.union(0, 0, getWidth(), getHeight()); @@ -1116,7 +1297,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener * Invalidates a key so that it will be redrawn on the next repaint. Use this method if only * one key is changing it's content. Any changes that affect the position or size of the key * may not be honored. - * @param keyIndex the index of the key in the attached {@link Keyboard}. + * @param key key in the attached {@link Keyboard}. * @see #invalidateAllKeys */ public void invalidateKey(Key key) { @@ -1142,7 +1323,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener Key popupKey = mKeys[keyIndex]; boolean result = onLongPress(popupKey); if (result) { - showKeyPreviewAndUpdateKey(NOT_A_KEY); + dismissKeyPreview(); } return result; } @@ -1258,7 +1439,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener // We must disable gesture detector while mini-keyboard is on the screen. if (!mMiniKeyboardOnScreen && mGestureDetector.onTouchEvent(me)) { - showKeyPreviewAndUpdateKey(NOT_A_KEY); + dismissKeyPreview(); mHandler.cancelKeyTimers(); return true; } @@ -1285,20 +1466,20 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener if (pointerCount != mOldPointerCount) { if (pointerCount == 1) { // Send a down event for the latest pointer - onDownEvent(touchX, touchY, eventTime); + mDebouncer.onDownEvent(touchX, touchY, eventTime); // If it's an up action, then deliver the up as well. if (action == MotionEvent.ACTION_UP) { - onUpEvent(touchX, touchY, eventTime); + mDebouncer.onUpEvent(touchX, touchY, eventTime); } } else { // Send an up event for the last pointer - onUpEvent(mOldPointerX, mOldPointerY, eventTime); + mDebouncer.onUpEvent(mOldPointerX, mOldPointerY, eventTime); } mOldPointerCount = pointerCount; return true; } else { if (pointerCount == 1) { - onModifiedTouchEvent(action, touchX, touchY, eventTime); + mDebouncer.onModifiedTouchEvent(action, touchX, touchY, eventTime); mOldPointerX = touchX; mOldPointerY = touchY; return true; @@ -1308,115 +1489,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener return false; } - private void onModifiedTouchEvent(int action, int touchX, int touchY, long eventTime) { - switch (action) { - case MotionEvent.ACTION_DOWN: - onDownEvent(touchX, touchY, eventTime); - break; - case MotionEvent.ACTION_MOVE: - onMoveEvent(touchX, touchY, eventTime); - break; - case MotionEvent.ACTION_UP: - onUpEvent(touchX, touchY, eventTime); - break; - case MotionEvent.ACTION_CANCEL: - onCancelEvent(touchX, touchY, eventTime); - break; - } - } - - private void onDownEvent(int touchX, int touchY, long eventTime) { - int keyIndex = mProximityKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); - mCurrentKey = keyIndex; - mStartX = touchX; - mStartY = touchY; - mDebouncer.startMoveDebouncing(touchX, touchY); - mDebouncer.startTimeDebouncing(eventTime); - checkMultiTap(eventTime, keyIndex); - mKeyboardActionListener.onPress(keyIndex != NOT_A_KEY ? mKeys[keyIndex].codes[0] : 0); - if (keyIndex >= 0 && mKeys[keyIndex].repeatable) { - repeatKey(keyIndex); - mHandler.startKeyRepeatTimer(REPEAT_START_DELAY, keyIndex); - } - if (keyIndex != NOT_A_KEY) { - mHandler.startLongPressTimer(keyIndex, LONGPRESS_TIMEOUT); - } - showKeyPreviewAndUpdateKey(keyIndex); - mDebouncer.updateMoveDebouncing(touchX, touchY); - } - - private void onMoveEvent(int touchX, int touchY, long eventTime) { - int keyIndex = mProximityKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); - if (keyIndex != NOT_A_KEY) { - if (mCurrentKey == NOT_A_KEY) { - mDebouncer.updateTimeDebouncing(eventTime); - mCurrentKey = keyIndex; - mHandler.startLongPressTimer(keyIndex, LONGPRESS_TIMEOUT); - } else if (mDebouncer.isMinorMoveBounce(touchX, touchY, keyIndex, mCurrentKey)) { - mDebouncer.updateTimeDebouncing(eventTime); - } else { - resetMultiTap(); - mDebouncer.resetTimeDebouncing(eventTime, mCurrentKey); - mDebouncer.resetMoveDebouncing(); - mCurrentKey = keyIndex; - mHandler.startLongPressTimer(keyIndex, LONGPRESS_TIMEOUT); - } - } else { - mHandler.cancelLongPressTimer(); - } - /* - * While time debouncing is in effect, mCurrentKey holds the new key and mDebouncer - * holds the last key. At ACTION_UP event if time debouncing will be in effect - * eventually, the last key should be sent as the result. In such case mCurrentKey - * should not be showed as popup preview. - */ - showKeyPreviewAndUpdateKey( - mDebouncer.isMinorTimeBounce() ? mDebouncer.getLastKey() : mCurrentKey); - mDebouncer.updateMoveDebouncing(touchX, touchY); - } - - private void onUpEvent(int touchX, int touchY, long eventTime) { - int keyIndex = mProximityKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); - boolean wasInKeyRepeat = mHandler.isInKeyRepeat(); - mHandler.cancelKeyTimers(); - mHandler.cancelPopupPreview(); - if (mDebouncer.isMinorMoveBounce(touchX, touchY, keyIndex, mCurrentKey)) { - mDebouncer.updateTimeDebouncing(eventTime); - } else { - resetMultiTap(); - mDebouncer.resetTimeDebouncing(eventTime, mCurrentKey); - mCurrentKey = keyIndex; - } - if (mDebouncer.isMinorTimeBounce()) { - mCurrentKey = mDebouncer.getLastKey(); - touchX = mDebouncer.getLastCodeX(); - touchY = mDebouncer.getLastCodeY(); - } - showKeyPreviewAndUpdateKey(NOT_A_KEY); - // If we're not on a repeating key (which sends on a DOWN event) - if (!wasInKeyRepeat && !mMiniKeyboardOnScreen) { - detectAndSendKey(mCurrentKey, touchX, touchY, eventTime); - } - if (keyIndex != NOT_A_KEY) - invalidateKey(mKeys[keyIndex]); - } - - private void onCancelEvent(int touchX, int touchY, long eventTime) { - mHandler.cancelKeyTimers(); - mHandler.cancelPopupPreview(); - dismissPopupKeyboard(); - showKeyPreviewAndUpdateKey(NOT_A_KEY); - if (mCurrentKey != NOT_A_KEY) - invalidateKey(mKeys[mCurrentKey]); - } - - private void repeatKey(int keyIndex) { - Key key = mKeys[keyIndex]; - // While key is repeating, because there is no need to handle multi-tap key, we can pass - // -1 as eventTime argument. - detectAndSendKey(keyIndex, key.x, key.y, -1); - } - protected void swipeRight() { mKeyboardActionListener.swipeRight(); } @@ -1466,30 +1538,4 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } return false; } - - private void resetMultiTap() { - mLastSentIndex = NOT_A_KEY; - mTapCount = 0; - mLastTapTime = -1; - mInMultiTap = false; - } - - private void checkMultiTap(long eventTime, int keyIndex) { - if (keyIndex == NOT_A_KEY) return; - Key key = mKeys[keyIndex]; - if (key.codes.length > 1) { - mInMultiTap = true; - if (eventTime < mLastTapTime + MULTITAP_INTERVAL - && keyIndex == mLastSentIndex) { - mTapCount = (mTapCount + 1) % key.codes.length; - return; - } else { - mTapCount = -1; - return; - } - } - if (eventTime > mLastTapTime + MULTITAP_INTERVAL || keyIndex != mLastSentIndex) { - resetMultiTap(); - } - } } From ca4e42785f598af9f24a9e3e2ae644ffa83c77ed Mon Sep 17 00:00:00 2001 From: Amith Yamasani Date: Tue, 31 Aug 2010 11:05:32 -0700 Subject: [PATCH 18/58] Fix UnsatisfiedLinkError for Latin IME. Don't use old NDK version in a platform build. Also added a clean step, since it's only a Makefile change. Change-Id: Ide1684a5f34e99496e969edb8443dc4545b57306 --- CleanSpec.mk | 1 + native/Android.mk | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CleanSpec.mk b/CleanSpec.mk index 7cdf69a6a..44ff0a29d 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -47,6 +47,7 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/LatinIME*) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/LatinIME.apk) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjni_latinime_intermediates) # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST # ************************************************ diff --git a/native/Android.mk b/native/Android.mk index b2944699c..e9ceceb71 100644 --- a/native/Android.mk +++ b/native/Android.mk @@ -8,8 +8,8 @@ LOCAL_SRC_FILES := \ src/dictionary.cpp \ src/char_utils.cpp -LOCAL_NDK_VERSION := 4 -LOCAL_SDK_VERSION := 8 +#LOCAL_NDK_VERSION := 4 +#LOCAL_SDK_VERSION := 8 LOCAL_MODULE := libjni_latinime From b24cc640c1485590b1e9912397ea9acd68b43d99 Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Wed, 1 Sep 2010 09:11:38 +0900 Subject: [PATCH 19/58] Fix ArrayIndexOutOfBoundsException. bug: 2964045 Change-Id: I97d95181e1a6838ace9c135aa92e7f20034e821f --- .../android/inputmethod/latin/LatinKeyboardBaseView.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index efce0d193..280801a55 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -500,8 +500,9 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener if (!wasInKeyRepeat && !mProxy.isMiniKeyboardOnScreen()) { detectAndSendKey(mCurrentKey, touchX, touchY, eventTime); } - if (keyIndex != NOT_A_KEY) + if (keyIndex != NOT_A_KEY && keyIndex < mKeys.length) { mProxy.invalidateKey(mKeys[keyIndex]); + } } public void onCancelEvent(int touchX, int touchY, long eventTime) { @@ -509,8 +510,9 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener mHandler.cancelPopupPreview(); mProxy.dismissPopupKeyboard(); showKeyPreviewAndUpdateKey(NOT_A_KEY); - if (mCurrentKey != NOT_A_KEY) + if (mCurrentKey != NOT_A_KEY && mCurrentKey < mKeys.length) { mProxy.invalidateKey(mKeys[mCurrentKey]); + } } public void repeatKey(int keyIndex) { @@ -670,7 +672,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } private void checkMultiTap(long eventTime, int keyIndex) { - if (keyIndex == NOT_A_KEY) return; + if (keyIndex == NOT_A_KEY || keyIndex >= mKeys.length) return; Key key = mKeys[keyIndex]; if (key.codes.length > 1) { mInMultiTap = true; From 543dbdfdbda259aa56be9670480c7d802beba332 Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Tue, 31 Aug 2010 18:00:09 +0900 Subject: [PATCH 20/58] Always present suggestion strip whenever in appropriate mode. Some cleanups too. bug: 2959293 Change-Id: Idf07fc25c5700b69b93ab4b09ce34941f0d9c157 --- .../android/inputmethod/latin/LatinIME.java | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index f26cbc059..74ed90ff6 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -647,16 +647,14 @@ public class LatinIME extends InputMethodService (attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE) == 0) { mInputTypeNoAutoCorrect = true; } - if ((attribute.inputType&EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { + if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { mPredictionOn = false; - mCompletionOn = true && isFullscreenMode(); + mCompletionOn = isFullscreenMode(); } - updateShiftKeyState(attribute); break; default: mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_TEXT, attribute.imeOptions, enableVoiceButton); - updateShiftKeyState(attribute); } inputView.closing(); mComposing.setLength(0); @@ -666,8 +664,9 @@ public class LatinIME extends InputMethodService loadSettings(); updateShiftKeyState(attribute); - setCandidatesViewShown(false); - setSuggestions(null, false, false, false); + setCandidatesViewShownInternal(isCandidateStripVisible() || mCompletionOn, + false /* needsInputViewShown */ ); + updateSuggestions(); // If the dictionary is not big enough, don't auto correct mHasDictionary = mSuggest.hasMainDictionary(); @@ -831,18 +830,21 @@ public class LatinIME extends InputMethodService // When in fullscreen mode, show completions generated by the application setSuggestions(stringList, true, true, true); mBestWord = null; - setCandidatesViewShown(isCandidateStripVisible() || mCompletionOn); + setCandidatesViewShown(true); + } + } + + private void setCandidatesViewShownInternal(boolean shown, boolean needsInputViewShown) { + // TODO: Remove this if we support candidates with hard keyboard + if (onEvaluateInputViewShown()) { + super.setCandidatesViewShown(shown && mKeyboardSwitcher.getInputView() != null + && (needsInputViewShown ? mKeyboardSwitcher.getInputView().isShown() : true)); } } @Override public void setCandidatesViewShown(boolean shown) { - // TODO: Remove this if we support candidates with hard keyboard - if (onEvaluateInputViewShown()) { - // Show the candidates view only if input view is showing - super.setCandidatesViewShown(shown && mKeyboardSwitcher.getInputView() != null - && mKeyboardSwitcher.getInputView().isShown()); - } + setCandidatesViewShownInternal(shown, true /* needsInputViewShown */ ); } @Override @@ -1430,8 +1432,7 @@ public class LatinIME extends InputMethodService } private boolean isPredictionOn() { - boolean predictionOn = mPredictionOn; - return predictionOn; + return mPredictionOn; } private boolean isCandidateStripVisible() { From eee0a637b4bb7a3bd9857194939e143e5c0d55fb Mon Sep 17 00:00:00 2001 From: satok Date: Wed, 1 Sep 2010 11:48:35 +0900 Subject: [PATCH 21/58] Add new assets for LatinIME Change-Id: I62b544d6ed2d3ef7a5e37cdcedef7a60d09a1cb2 --- .../btn_keyboard_key_dark_normal.9.png | Bin 0 -> 520 bytes .../btn_keyboard_key_dark_normal_off.9.png | Bin 0 -> 774 bytes .../btn_keyboard_key_dark_normal_on.9.png | Bin 0 -> 1130 bytes .../btn_keyboard_key_dark_pressed.9.png | Bin 0 -> 795 bytes .../btn_keyboard_key_dark_pressed_off.9.png | Bin 0 -> 1029 bytes .../btn_keyboard_key_dark_pressed_on.9.png | Bin 0 -> 1332 bytes .../btn_keyboard_key_light_normal.9.png | Bin 0 -> 497 bytes .../btn_keyboard_key_light_popup_normal.9.png | Bin 0 -> 642 bytes ...tn_keyboard_key_light_popup_selected.9.png | Bin 0 -> 1514 bytes .../btn_keyboard_key_light_pressed.9.png | Bin 0 -> 812 bytes java/res/drawable-hdpi/cancel.png | Bin 1811 -> 3992 bytes .../keyboard_dark_background.9.png | Bin 0 -> 228 bytes .../keyboard_key_feedback_background.9.png | Bin 1372 -> 1184 bytes ...eyboard_key_feedback_more_background.9.png | Bin 1637 -> 1544 bytes .../keyboard_suggest_strip.9.png | Bin 1577 -> 215 bytes .../keyboard_suggest_strip_divider.png | Bin 2852 -> 945 bytes java/res/drawable-hdpi/mic_slash.png | Bin 5615 -> 6995 bytes java/res/drawable-hdpi/ok_cancel.png | Bin 442 -> 774 bytes java/res/drawable-hdpi/speak_now_level0.png | Bin 1512 -> 6017 bytes java/res/drawable-hdpi/speak_now_level1.png | Bin 2215 -> 6267 bytes java/res/drawable-hdpi/speak_now_level2.png | Bin 3130 -> 6359 bytes java/res/drawable-hdpi/speak_now_level3.png | Bin 3647 -> 6506 bytes java/res/drawable-hdpi/speak_now_level4.png | Bin 3626 -> 6542 bytes java/res/drawable-hdpi/speak_now_level5.png | Bin 3670 -> 6463 bytes java/res/drawable-hdpi/speak_now_level6.png | Bin 4006 -> 6782 bytes .../res/drawable-hdpi/sym_keyboard_delete.png | Bin 2282 -> 1465 bytes .../sym_keyboard_feedback_123_mic.png | Bin 1046 -> 3541 bytes .../sym_keyboard_feedback_delete.png | Bin 1278 -> 1453 bytes .../sym_keyboard_feedback_mic.png | Bin 681 -> 2494 bytes .../sym_keyboard_feedback_numalt.png | Bin 1336 -> 3797 bytes .../sym_keyboard_feedback_return.png | Bin 838 -> 2018 bytes .../sym_keyboard_feedback_search.png | Bin 1209 -> 2335 bytes .../sym_keyboard_feedback_shift.png | Bin 885 -> 1987 bytes .../sym_keyboard_feedback_shift_locked.png | Bin 700 -> 1764 bytes .../sym_keyboard_feedback_space.png | Bin 287 -> 1336 bytes .../sym_keyboard_feedback_tab.png | Bin 462 -> 1707 bytes java/res/drawable-hdpi/sym_keyboard_mic.png | Bin 1440 -> 886 bytes .../res/drawable-hdpi/sym_keyboard_return.png | Bin 1123 -> 1719 bytes .../res/drawable-hdpi/sym_keyboard_search.png | Bin 1623 -> 1260 bytes java/res/drawable-hdpi/sym_keyboard_shift.png | Bin 1495 -> 1814 bytes .../sym_keyboard_shift_locked.png | Bin 1119 -> 1523 bytes java/res/drawable-hdpi/sym_keyboard_space.png | Bin 371 -> 326 bytes .../sym_keyboard_space_led.9.png | Bin 0 -> 1291 bytes java/res/drawable-hdpi/sym_keyboard_tab.png | Bin 1027 -> 1434 bytes .../btn_keyboard_key_dark_normal.9.png | Bin 0 -> 520 bytes .../btn_keyboard_key_dark_normal_off.9.png | Bin 0 -> 774 bytes .../btn_keyboard_key_dark_normal_on.9.png | Bin 0 -> 1130 bytes .../btn_keyboard_key_dark_pressed.9.png | Bin 0 -> 795 bytes .../btn_keyboard_key_dark_pressed_off.9.png | Bin 0 -> 1029 bytes .../btn_keyboard_key_dark_pressed_on.9.png | Bin 0 -> 1332 bytes .../btn_keyboard_key_light_normal.9.png | Bin 0 -> 497 bytes .../btn_keyboard_key_light_popup_normal.9.png | Bin 0 -> 642 bytes ...tn_keyboard_key_light_popup_selected.9.png | Bin 0 -> 1514 bytes .../btn_keyboard_key_light_pressed.9.png | Bin 0 -> 812 bytes .../keyboard_dark_background.9.png | Bin 0 -> 228 bytes .../sym_keyboard_space_led.9.png | Bin 0 -> 1291 bytes java/res/layout/keyboard_key_preview.xml | 2 +- 57 files changed, 1 insertion(+), 1 deletion(-) create mode 100755 java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png create mode 100755 java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off.9.png create mode 100755 java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on.9.png create mode 100755 java/res/drawable-hdpi/btn_keyboard_key_dark_pressed.9.png create mode 100755 java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off.9.png create mode 100755 java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.png create mode 100755 java/res/drawable-hdpi/btn_keyboard_key_light_normal.9.png create mode 100755 java/res/drawable-hdpi/btn_keyboard_key_light_popup_normal.9.png create mode 100644 java/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.png create mode 100755 java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png create mode 100755 java/res/drawable-hdpi/keyboard_dark_background.9.png mode change 100644 => 100755 java/res/drawable-hdpi/keyboard_key_feedback_background.9.png mode change 100644 => 100755 java/res/drawable-hdpi/keyboard_key_feedback_more_background.9.png mode change 100644 => 100755 java/res/drawable-hdpi/keyboard_suggest_strip_divider.png mode change 100644 => 100755 java/res/drawable-hdpi/mic_slash.png mode change 100644 => 100755 java/res/drawable-hdpi/sym_keyboard_feedback_mic.png mode change 100755 => 100644 java/res/drawable-hdpi/sym_keyboard_feedback_numalt.png mode change 100755 => 100644 java/res/drawable-hdpi/sym_keyboard_feedback_return.png mode change 100644 => 100755 java/res/drawable-hdpi/sym_keyboard_feedback_tab.png mode change 100644 => 100755 java/res/drawable-hdpi/sym_keyboard_mic.png create mode 100644 java/res/drawable-hdpi/sym_keyboard_space_led.9.png mode change 100644 => 100755 java/res/drawable-hdpi/sym_keyboard_tab.png create mode 100755 java/res/drawable-mdpi/btn_keyboard_key_dark_normal.9.png create mode 100755 java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off.9.png create mode 100755 java/res/drawable-mdpi/btn_keyboard_key_dark_normal_on.9.png create mode 100755 java/res/drawable-mdpi/btn_keyboard_key_dark_pressed.9.png create mode 100755 java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off.9.png create mode 100755 java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.png create mode 100755 java/res/drawable-mdpi/btn_keyboard_key_light_normal.9.png create mode 100755 java/res/drawable-mdpi/btn_keyboard_key_light_popup_normal.9.png create mode 100644 java/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.png create mode 100755 java/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.png create mode 100755 java/res/drawable-mdpi/keyboard_dark_background.9.png create mode 100644 java/res/drawable-mdpi/sym_keyboard_space_led.9.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png new file mode 100755 index 0000000000000000000000000000000000000000..48ebb6183b270bf86619f8b7b9ad0f7fcb185286 GIT binary patch literal 520 zcmV+j0{8uiP)kP^2V-*_9AdaKub@XFawYqSu6c_6w|6z3ACIY%(O6 z2oqr<^C89`gkeaZ`#l9g00}sbWBNIrD2k%__WN}>kd%^&qUi2WJ=U_wb=~g%eLM~x zO)^qf75$#iRM#~m5yx@pW4F6sT6vyR*=D2vB2qL>LrwbwD~x03Ahd(q3ynmFwyh9# zDSUS`(ho+A9-9uI(78KQ<0WVC8JrO&0!DnE8y zluP{#N=9yJWZ)0w6&X~q>yR1lwfZ)P+O;<2exWDBM9dhC{5GhqcM?{2LJ5>FC`1?|0?ia1Q-C}TJxZIhamj`0000< KMNUMnLSTaTDdBMd literal 0 HcmV?d00001 diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off.9.png new file mode 100755 index 0000000000000000000000000000000000000000..38b8b48aae600c82c23365a54a11e7797970f740 GIT binary patch literal 774 zcmV+h1Nr=kP)KoFh8#46Q__yHpN z(__@b)MK@WX-}e7p;au1A81TWXBJa5i8c{j$G8h3WR=X@_vX!HU3HK%+)Lj;lXas@ z)~?2Ii2Qq@x%fmRz?z#46gWW zHamJhZO6>tycZj{WH)zgIB2J|@_uF5=wLa_A8S|FVkJ9Blol1Xdc6+4UQdAXz)+pA zvBM~r%Lg6CpR6J?BGI*|hO}BO7@*x!@)HP>Q?tIg^sC01zFi5aq49qWjN z;3#+etq9v>_lAvu|4b&4TrPUDU!g^b+iS6GQQ~fnv29T<#>h2tBu*!wa^&W7MB@nP zobK19M_q;zI|d}V8+4}mS=NZUF)v8U)II&oPx*}2P9xS=suqiRgPRaN0hX3IJIym*O-69ia$2a(7kvAPB=SM2rC>`+E*F3Wb6= zxds3%8KE&AkHw+1gDF3d8y)Iz7yKxR(Ei^5|{e1PU*!m4>3uqj^u?c)sH}IJdO)ZPywOhX{#{YzK+~Aq)^n3UypE z&XuN1nb5+<$1(L#(MUZ?SW&dO+}XyXmBR!OrIhJKfyi7)5DKRvQSlsjRR=D02E*qR zfe6DG;gCDC5hG5$BeU$^z1fsIwqP8?dMZUo8dlFZ#d#F@AeA*b`?Y}QctGA%^ zmBhWMBNhZG-@X%P1V$giXv3>YEMI($+jl$yQ6-j=DVLUAG*?`_dG#J2*DsQLxujc> zg|RsqDH4cC!>LSISyQqrk+sXK74-KMI^8yUJAaPK+xcCqXhxD)YJOa- zhi3O{HIeIreD3`D2pb}E`}AubAma-agCj8{$q$Q$30`h`kgO+jIa2XNm2aP%CiX&l zY6C~1h{WrEsbjNU$8di#oJN#8e4pp6A~N|TO^}#V>?qi^lu2-c1RP<oDxLzJIVl2TIDj5AAXAjqPYyBL`TJg9E51Cdt~54 zeE$3f%gqivH^O$Of%fJNZ2Vs%p?4ANN5o2;Qx`iMV!~IDY}*&LOALhQZr?%c zW7UM_A(cpe*GF%6n?S?{1eYnswX`K-NBZ$Gl^w>7xuy#C(C-bBS_>krwUnu~B6g`v zADQ5-2*2qXLStmG3`rY-IEY+&tSm9(ShTaHL>VU@1`vT!1R@%{IvSlnd_AIP*mo+7 zOaPj5>yE`p;TriFRe>!U`QfU-CXIY&z&pN1gpGiX#Yi@pW1)pEHVw$xy+JoiP&PAi zc7e=_)mG(_dBd;mA-Hs{(zQz0`i&E!p0}Q{g^_6*IaD9&6SyVx!-Zqc;WJ)q9bALj z8MS_^>euRI_&o{HS{$(Sc2JoROO05rkUW&(su_UR7bu! z66i^ZAQ2>jRF|RNuv)EPyWPTaxdbVTlNp}tZQiCKAyn1dPNx&>b~`v8kJZ!fe!qwL zd=9VIOPyy~rYb>%2Em#niK$pvaF)6m~73U|a-Lls-!PNC%j(=^E6a-^#u{T=Ks z&NS(Wevi`G(6VXhFGzl~SSQvujHv0`aT{OvrTaETi0Zzbw()HWFYgOt(;&`Ul(uYB z-kE;?_U^YyM?Siav=JnRRt&8eTEE!F^M$8Pj@TB%UajoC3N86=ST(&xvCUe7!$|hh z&-I^q2dU6fKiH*q?;8>h;;?v=zC!JxM6NhpNEq*aU@r<2NW1}p4&N;M5JQqw^LNsPVh88(NM`sWe zj5&>%4w$BCA#bbhk<6!ODsqLKm`o-x9*2!%C*Os7-0 zUa#h7*xj%yi^T%g>otrOX*($NzC?V^2_I6PVEgx-Gw Z3;KUEXEd(t-2~(lL|T3Y~L$&b>2j zuSC%_JM00hs0Ip~M}~H!r9@I9DUsDJs~@<%y`}s6d%C*1BHLb0X4uz{g_edaOLhI& z^Yb&c+imLi`>WG$r_-UMqa*tL{Z;$3*-UjN5j7F?OeUi`+TPwCeSd#btJPZixI>X* zu}H(=P!VAgI+-YmFbVD;0*t=a8jXfD9*@;YyoiKNMyg@knWa9RPX2CZj+KLh2tdwe z06GURm5EakC@~+~a>d|6gchLZM4YMw-F|+4=<)H9-rwJ8GMP}RRHD1PJ32c%Q+Vb> zT53C2iA;#t3&5-fZ^N+G=jSK&dObQhIic(8YszM`^zrdQ4-XI2Xf){Z^3tJ{ks|WS zGYND_FeoB8&(qTrRjXAxJw08d+e)QEhlhvs`ua-ca#@j-b_0&J6p_D&5hu9v@IHXb z^8zf0An6PS13ErFR&j#yjTMph(MbdyBh%?r0fwF2Fcb=fB`mC%8-`eyC?KKF-g-P7 z92{)6M3IVk^`II+;(W+dZmM8nK0iNqjBTul37H@|taWj5p_Uw@(P)ua5F1}#Un}oX_PVx;dx_$ewJb@-7C-vF{(U@Dear331FsX)RWQx5h;H9XF~EP>mq#w)`H+1f8i^6;>jj&(r?? zzN6fO+=?^b-rf{wkYOUSQYa20Y-XZlqSAzhhPZEPCOIv~Wj{pMz*zbvBJVhcF00000NkvXXu0mjf)ja5# literal 0 HcmV?d00001 diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.png new file mode 100755 index 0000000000000000000000000000000000000000..b7dccfe3c5e0a32b3c99c683d613d7de2f89cc87 GIT binary patch literal 1332 zcmV-41cjbtHNmUTDYEVp~Q~gXP8LFQ1pldq~P%#1c6V_QEKIo0%4JnI*Ar< zTV_!f;Ym{B8w?=fxB?9qWA|YQ))0j>UdWn+vWyfoHXUba$N<4uv<69A<*L@;*$2A{ zcTy0_4xS%B#YN{&1bz>{Lo^f( z{WTm6gSUA3@&N6xCBE8j!t+`<`};LsJpYZ{{3krv{08Jz1QT-DD~LiCv1i^uaJK=k z0^+cnIP50uS`ruMzvJ8Q8U(RMfvmr?`M|{|4_&-?_7p+bCM#|#a2_AA$IN9B`*>k- z!tuc{q$mhq;q$F?eDP}M=%Pd)TLM0owzGu&$Kj@_Q)r(lf8T!=-)2nVk6bHO#C zt7gB|5}C2YpS^$g0i2|?ru?GpRKJ>tgO$4H-B*^FHaAW0uKI$Uv5Io0S)`O6#jzJq z_aEW>{2qpbw9f~WsX7;u62lXnIm78O>SUY0JdlVx2@5C-_4^|PgP$o&Iq3cyDe)l* z?)M_ReG}lH_dj6Jze6cGRKGFxC9Am~197FsVrc$Y9LGVobC2rDuQ=`ef%T17XgDME zdY@4t{2u;ri$DgHdZ7xTi06IoU@rqi1uUV+KnFd~ucDCSy4EVBR(QbbGjh!>`G z7;uq{CN3(>3Ygbeh%F(6OkJZaFGgUC)r!UCy53sl#|z8xa(}vp<$+*w_LEoJdghHw z&DP*%-xQRyN3Z0*VcysUm+`YEz3j_&A!cMfSuofucdt1TPG0+{7+E&RTy~(Ev}@;D3#}uo2vWON?OL^K&FNZp!C5tnC{ zualoua4RoY%j{s6iE9^`)2kuL*HYJ!6>m4cAg;1&-RMPQ9V6H7dSu?)GG(|{p03)p zYLI2bh}kD)-w4avH&sd4y1m0J+amwA&5|2N4TbIaOwP>QR>d$epVc@Q%#VoqQ( zg@LIG#Efr46t;*x`^gk&tW$RSwI|VZ-f(6^6>=^6%LdAvyvjX|Hi&^K>{>>=E!gZ5 zGBH!7YZ*(J=fWT?nD;dDcEI6qII(YQ)-9PuXDVYAV~Mr3H8h(|xNbTkQtzCdohi`_ zV?gYkLdyU#Zp|RARtud@C;c1iYFM>)yN%u5U3i|Ca-(H{B;C#TeH%$@+V1< qYuaj%l?9o0XKAGb=Y8;>00RK)ea#N;9MrY|0000~($Fc5_Y@QRv4&~qV5 zPDRNfxCT8}fR3<6{CHz0k=W%=TM&)Ob3_xx;(eKC&zMYz-ZRwMH*nr{qq8|&y2t+Y@B2nq z9LK*n#M*?qu4xzsmJty`P!I&i*1FvqlJeWo>xrC(j)au`UE|lHauCZ8D-#KB(J*SC zy0pf_h&(1dE`A`}y2KVW=ZLIn0|-D)0=aI9av5vQCvXKpL~Mu%7CZ6?K>oeh)$G8? z@wuH^)g|^yWt&QQtE{!R1p|Z|$aNDU=Mv?m&HBv#nbyLt1#7`tuoio3sjFDanZu~r zizUd0HnDkb;o1waq3trY7Jg?(LPSFRkc5ae0&Brq009U<00IyjGP`cK>-(Ohlr)Yb zE3uyEnQNtKblIF)RTZ^uYr0HzgC?tQT?o@?ki^u|P+ICaa0! z;v$N*TJ51ysXTd}S9Kg-I;PVp42Q$lZnyi~YPDYQs{oPEZ`!(!GH_Kcmz$+h$Hx5xlRZjUj#t_GMSHt;7M(BsH zPN&oE^?HxRV)2|~2?aqg@_oNeTn*=WN~~+n5I2ZB#4X|)=3ZbfR#Pe^a$xrn?}#@< z4~$(_W%`A(Kz>^C)h_I)oP@+C6GOxYVzkIg)*J7_(ig9Rr#C)^r9VD_HQxA5tH3EX c^8FTI04_5jMM>=0SO5S307*qoM6N<$f(eWq^Z)<= literal 0 HcmV?d00001 diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.png new file mode 100644 index 0000000000000000000000000000000000000000..fe6c517f9115113b4811ebbb3a555d43f1761d63 GIT binary patch literal 1514 zcmeAS@N?(olHy`uVBq!ia0vp^MnLSs!3HD`yQJj;DajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_cg49sbnArU1JzCKpT`MG+DAT@dwxdlMo3=B5*6$OdO*{LN8 zNvY|XdA3ULckfqH$V{%1*XSQL?vFu&J;D8jzb> zlBiITo0C^;Rbi_HHrEQs1_|pcDS(xfWZNo192Makpx~Tel&WB=XP}#GU}m6TW~gUq zY+`P1uA^XNU}&IkV5Dzoq-$tyWo%?+V4wg6Nh+i#(Mch>H3D2mX;thjEr=FDs+o0^GXscbn}XpVJ5hw7AF^F7L;V>=P7_pOiaoz zEwNPsx)kDt+yY-;xWReF(0~F4nSMoLfxe-hfqrf-$X{U9#U(+h2xnkbT^v$bkg6Y) zTAW{6lnjiIG-a4(VA$ce2&53`8Y};zOkkuW=D6f1m*%GCm3X??DgkBmQZiGl++57v z3=Pdq49txT%q$EIEzKQGot;e$TwTrGOw27@U}j*`>tbR7)amNv=m-pXLl-wES0h(P zS7Qqo7b9agXID3vUeCPZlEl2^RG7V)KzpHj9r5b5axO|uEXgkl$xAZ!`CVki~X)Q=>r|34@w+Ji3KJEOo1RKJm~{D@XV8%2h1@=z^oD1tz^o;z$E4A;uunK>rM22 z@52rvb)Lb3S_iE}?=ETb>(gsm^x(;ZXY&Xf`(F?sTAd&h}c zQbL!HR4a1KjRiut>v#_{oZj@u z<{?u`)peL=HSeW zizeE9vhVL$zbRGqvz(_}u^Sr!|&i>hKq*VMzbM1q) zeeSW{YA#0Bz8xltliW`zgH)=tv`i2Xa&juN+HBp&ye;?l?RQms=Y^yc+AF`SaqSb- zh&iF$E&2b&Ye~Bq9gONd-&SSMs&5Q^94b>MVtgrSV=ue)RBMY}Ya15&ctkp>zL(|` zk3X_-+Wbig>fgA!XZPGn4qfj&dG_9yI|?S4vYwE1{ZhJiWw6D&e+Srpe>n8@fp6HS z6TFs6;ZJ0C*}lBEFVdQ&MBb@0P9mI A0{{R3 literal 0 HcmV?d00001 diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png new file mode 100755 index 0000000000000000000000000000000000000000..d09bd3db3ce5421d83cb2b1f29bbba78847a6915 GIT binary patch literal 812 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 delta 1759 zcmX|>c~p~U7RKMO4YH_3pp_kp9fq|~2?HWqYZU~Mk_dxLLD>yEh5$i6q)n+*0z%nj zBp4JS0RkEl1Tml`u?S%eTZlEXWI|Yt>{~yMJ$=u)=l$bd?sM;X?ypq8@NoV)NTJ#N z8&_1y#Qdb!ITS{Rv%-mth%eE?l{BLi!z@jW z2No*l?ZV@O6`1H0`RA5VBfBpDQ#bVOpSC5jyiG_vAEd7-DaBk|Xqo`w}d|#?# z@&EbxlmB8p3TQ$AAekZU?d>^3%!Y=By*p`x+*JUAZ#>KyPmqsME|CG5&mzaRRwaIx zvH+yI^~(U4zXD`wg1_S^9f0V-{)W1`cntt5$?_mG2R^Ls&R74Ba z;O&eu0IqNhT4PlJ(69hN&H@6!AQAyKu>Mtlz0K0>_yRlIbKDn=4%4?oA`@NVZ0BM* zMBQpSeOSTW$H!-avAw=jJ~I<0eb=RIISg&wlld{L_&oRx6BlQPUti1>WXz9QZ%a2; zros~w2ayND9-Ek(pKNb$XWT8y(|5ir>Lc-IYr4^pqP}BF{~|31clGMkA-|@b3kbyk z11gb7GzitGsH&=Ro|i5PPVv>BPmuBrBN4Ea%GTD2OVsysJhQKCYzh+g2?Y5h@!*N1 zwfS)`Z5tFFuF<%3q#+h-XUGY$_FQq^gu{Z^&M&XGZcXZ?Z0tM`(W}okKN$p z5T4TGP_5@XAR}jye@wnW`GmX>E+{EY-|H0V-w8&Ed`1j^9%)-IYqnuS$iQGQp}hJp zQTsKGXn#ugNE4Y+E8b{sZjRy)LyyR0qvRee7Td%zj=Wh~Iim)|u98ry<`bWblG88H zm05MQwZC7Y#CF?LJcg4Aby@zrN6MkAI77<1&oZI!K8*J4bQM` z(JL(r*qXOC_VeBD|4Qr2c6&WQQaGb~)|Hm|dL$?$xlb_BsEmi4N!*1w9CUD!rP=`MB4qARDJ^i@?=T@CacuA4m0AyO5mh)dr5 ztz8Yeu-pF7=+Xk8d3@U>`e92;N^gjQVgQJ;a~40jBN2Tq#LW%Yz6#D&T5p*$P8BRI zdEYQoFT5ReU;IDE)Io-^h&f^{D`x>tJ)DbFTI(%`?Cjh7nlYn2+v~xA-)wt2Lj8ipJsAe?m=D z9116o&o5P3$t7TDpeFJrX-)VtyYk&63u4u;jchULGcz-tQ}E2cQnDHfh_{s7i*;t@ zK)kU+RCBC=M@X_{9fODPT};Bzg_Bwfc>MBP*JVUhZ0v>Mv$(^!+<2}^;eRd-vB7RU>g+7RfI!npyx0IM>u~;1ZY@F+d$Pm6D{1&7W zN$-7A>Y!j0$jT6?sHl{}T`y;|zkPyVkJawDM*N;yS9j9Z*0xi<&dFOUl``_KW3gpI zq0k_`nZ^*`c-i@Dj0bWERlmOjH@CC3k$WXN+PvOlbR|#k^j)NvqpfY2EQAtOEd-E8 zo|?Ak<_hjTiB+2lH!%=uS(JdEzh^o^d(U81O+xb9rztDsn1t=NFMSoo#COHTn*1ep zu6ES+-0bIsxJmr3`KLss%Y<6?{o?7@1e0@E?zIHF#1rjR$AR6~h$i(f{2BtS@oV!< zH^meek__5V;+H`-{f-7v^V;zLK~P6|J2}Xx8LfX(j4H~?tZ6|kWcCq#Mo|sqn2Xk6 zus^AGK0la(w$kJ#}S2qWJ*Ge-r%RuLEFr{B((K7N`Kgd%uC?2NOYo pN&t-T{-_=C?a+enZ%Vx~5rC7XI_6@mrVHTZe&)hA4Q|0%e*zS?ZZiM? diff --git a/java/res/drawable-hdpi/keyboard_dark_background.9.png b/java/res/drawable-hdpi/keyboard_dark_background.9.png new file mode 100755 index 0000000000000000000000000000000000000000..2d5c02080db6fa71f6fc40c02835c8f1b61ce6da GIT binary patch literal 228 zcmeAS@N?(olHy`uVBq!ia0vp^3P3Ew!3HE54((L}l9DB^5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>JirPF~978H@y_sgs$DqjJ!k(0v{`4<@##7dm)-~c0!lv56 zl0qL+KQMQ4?Ca{N+9ja2M08Dn7w1~jH3G(quW_~V*A{ahlbBc>#}wdY$WZ*Cm($Ec zHX-L)7=vwfx%C4Ez5=!bXVSm$vwtzYb(iT=G)P3Z;e3lbL(9c(!=>w9{f)3^;$bkb VF_7Zg{_h#c^`5SNF6*2UngERVOkMy0 literal 0 HcmV?d00001 diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_background.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_background.9.png old mode 100644 new mode 100755 index 6ba42db8237727d5d67b629bd60384fc014df3ab..1dd1d0f20bb1b55d5318b929a217943c47585ea7 GIT binary patch delta 1165 zcmV;81akY_3ZMy)BYyxHbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU$ zLPUqLDiQ~ z_!X9<>xH(rx4i~2olbB3T@-Y}0-QU6qvCBH>qCCI$tNr242Q!#up=;u>Jyjk2yAa% zKNAZuZ+CWf-t6w~F2>{WR64%IffD%1$;qq3!^8K-$H!wh_0D=JUlA%?!

muSoKmK-17OH;{4Xiv_f{odG$P+ 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 UZc;1IMF0Q*07*qoM6N<$g2Mm3N&o-= delta 2166 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 BQ!D@g delta 3610 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 delta 3588 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 KMNUMnLSTX=$H=b$ diff --git a/java/res/drawable-hdpi/speak_now_level5.png b/java/res/drawable-hdpi/speak_now_level5.png index 7d4fd5f20848b753e27d67bd4db7852265cf7432..8cd5ae7ad212767b82152585cdbb4f552c3cb40a 100755 GIT binary patch delta 6448 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 delta 3633 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 D+=$;} diff --git a/java/res/drawable-hdpi/speak_now_level6.png b/java/res/drawable-hdpi/speak_now_level6.png index e06990faaaa7490ee52b428d70fd7a09cdaa63be..9f4481eb4fabb88514141d4251122e1add120bdd 100755 GIT binary patch delta 6769 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

RBkjYhT^^xN4XrGngaOHx9H})N0$+@#FjC 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 diff --git a/java/res/drawable-hdpi/sym_keyboard_delete.png b/java/res/drawable-hdpi/sym_keyboard_delete.png index 59d78bec06339da04b7ee3ae908a2be0994e296f..ee29af02e6ba3dcc9e6497a5c967cba275ace802 100755 GIT binary patch literal 1465 zcmeAS@N?(olHy`uVBq!ia0vp^W8U}fi7AzZCsS=07?{&CLn2Bde0{8v^Ko2Tt~skz|cV7z)0WFNY~KZ%Gk)tz(4^Clz_GsrKDK}xwt{?0`hE?GD=Dctn~HE z%ggo3jrH=2()A53EiFN27#ZmTRp=I1=9MH?=;jqG!%T2VElw`VEGWs$&r<-In3$Ab zT4JjNbScCOxdpzyaD(%Tp#cR9GX09g0)0b01O41wkiWpHi%Wu15zfG>x;Uh=AXPso zwK%`DC>aHCFybnZQU%%yG$2F3nBNEAe!(RRYTBrDUd9nVXt8 znmd{sySW;fnOPVbI=Z>JSQr}`m|9x8n!B1i!_2^@*TC7$*wo0($kEZz+0f9%&B@is z)zQ`1!o|hN*v;A14W`#Kuec;JFF6%vZzj-Qs9r<7daay`QWHz^i$e1Ab6_bTAS1sd zzc?emK*2fKRKYhfIWrH$2SpFWw=StgnPsUdZbkXI3gGay%EV&7xfvmUL-eMQ6K48A z$LNC+2U22z2?0|ehzU>nKn^_fq~-y0Oc5|^Fz)YO#=yY%($mE;q~cc6pa1{u4;Qfb z@EjKDsmi&MyjV{9>x~u1-E7TXZ4B)1t?EfS(BwN|;>5xel`MM=?PrO!y9O;$;as4a zX}92ydd;uQsc$lck{ynJV%Qkv>guXBAxvt6PkW!{MShk~ZEbCJ>i+X=zC1qO|K4FA zubK6Ujom8c0jHB46c~;~O;+=L^@D@OVdH=2d&v$99z1v;Q1tTBQse&<4+MOhVIc7O z++6GOOV`)O@Bib@?0hxZYu~J?Oe>OKaAD+ziu`#eB;YahGM|EdsnR2rg7y7SDU7!)l#l_XN zxAgV3tq-3VN(e9}*#=DJdeRBx%&1ZgQ2udhs`m4?smB*ou{1_h-`bKHdwALHrnQSJ ze|>qWeE3vyz~4O%YwlgR5WwiQjQOEq&@00tw&EX+pX6T}&S-we*JW#Fm0)F+;B}bs o^1}@)QcX1bP-BpT(V>BnVam}TtQIR>IzWY~r>mdKI;Vst0D~AAU;qFB delta 2234 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 u)7aInyt|mAAg9Gf65 zgjsTqAT!TySs1hUBz+sW0=}!!Y&DSMuC<_aDTP)-V&fbrq2H={pk4p*rWVu zD*~7OW?pAh$x#UqkJ@)z0yB?{eGIH4V?o@Q@#N~cDBMzvN&k#ZWGkI$>20IyxvP;TbZ!B02w1tPA)G8MX-!FiduF`KSV%E|OYL56 zE+LkemVfUa1J19yL=@>iCD@REL1Ovbx5LvXem=IgP*_T?ZA?lqHqj<>uUKfYxYjr( zs`1T2-%^ZQe)+^`mlVipN(8fssEyXytgC&VQJiH6t8>E592!7uMbd6Yr7J!IuGu_g z0d04s#WA%MF$P@W7`Qk`p3w$p>(UAaTwz)DiGOzQu6ABEUJ1oWZLRmvaD`>|&jwb9 zOM_u|PezAUdD7LA#@@Q{j4>M;?%-eRP(h%mi;Tw4*@rEXCX;_m`08Se`s=UTa^2)9|@Ggc8Hmba_eC;XRPvgZE^H;;UV zX8vn{+>|Xj=L7%u-`x(TZ8^aTnZ!BM0`$o3Vr2Xlj+P|6H_V+Po~;1Ffc1+hD4M^`1)8S=jZArg4F0$^BXQ!4Z zB&DWj=GiK}-@RW+Av48RDcsc8z_-9TH6zobswg$M$}c3jDm&RSMakYy!KT6rXh3di zNuokUZcbjYRfVk**jy_h8zii+qySb@l5ML5aa4qFfP!;=QL2Keo`G(%fti7VnW3Jc zv5C34xsHO7fuVuEfswwUk*=Y+m9dePfq?=PC;@FNN=dT{a&d#&1?1T(Wt5Z@Sn2DR zmzV368|&p4rRy77T3Uk4Ff!5ws?aU2%qvN((9J7WhMC}!TAW;zSx}OhpQivaF)=B> zw8T~k=u(Imatq+b<`qMO2^e7d6^RAATTy%67E zfcc9_(bL5-q~g|_S%w}=ff5b2*4++^6nGX1^gPhuh*4VdP)eqyWCELXlR#8fW>I10 zR>MQS1!mg|IOfRA+T^&zQL9kU$LW-!^4{z9ixg))*R1*__n+Oqd`{8%{_lV8|Gy{e z&T(;LN8E7@jkY8V#KT(|&d{!u`{D45Z)FyJvzuO<>ar}*&8^~*iV|fxs3^bk|6;SM zTs|ib7AEnfK`&*`mCu^rYjmY=kz@O!n^{|TO*;9+Hk0AH%dDef3TDj*AEfS#`KO|L zK_^Yn^`pXEKl@4b3j%WlleA^{;={G3>R)1=b>zvOtdA8o$7lLH>-^Fnwo#QM+eC`D zp4o+UvR+z4#OJEL>N{iJwSGCcI9LdCYR^?W6+b=uJmn`&O-1p){SJtzQ zRa+mH?e4!4B5e{T_w|>72v@A;)pir{gI%JwZ?FEnFZG5w!E=r0@l`WLH}=)?O*=Bn zd}8^sZ^E5NWP_7>rO%!^y7~V5@1osD%`NVyIjvc`P;~Oil~uL8o*u|^Gyo0d%=p7)z@T#f$I^F?u7V0<22WQ%mvv4FO#l=i5w!pS delta 1222 zcmV;%1UdVy3;qd^NPh&NNkl3$PrM%9dsE$4Jry z(g-|Gkorlzq;I5dd{>LwPA=T$BRVMpB1!*=^PWs^MCi7s5)smTfC(R{|#piwLH#W=BQderbN{3;Y)b-62 z)zU}$LV86yDm`DRfCbkprYJnKZEyq;#fhkH%YuUt6Waq*><%JW0(++qVC+0b+0@M= zT~nTw`w5nb03C>%tDh^Djg=7Z>~&ZHUfETo4#gA$34fN4_!Y(X4(z+6&8og3Jq_}T zWn(XuBBqJbMEd%#nj(9*>7?bPI?^IMe@!~+V2UPQ(VGWNGeGO~f>euxtX;ZPD@R+qiiQc^wQRWcxYOIpVhuEbm; zsEz;u$>J3&H372_PnO`Qlnk({+@3rv>?1znoK}u9e8_Di-LnbEf5W3MBkhx%plfF+ zt|CvAnK=x|d>78cl9WyzT@0QhU5!}PZcLF^YJWbdU4i0+%@mg&HG&LQ1&&BjO`Tli zB`Z)jVgOfZ3Kr9((^w~vFO0gJ(E`#|oF&iU&K6am_}X(FXU#2`fJi35_(3ni zCV#)d#0=h2I%|NVh#Gn=VT#)|aF9Gc^9lzy! zcyG!TD@3kB?(hyANnV;z!pv_tnBoOZD1Y!}k45p~2BpKBa45NHLN#m5uV3RWP2pU5 zMSfv9&VX`|3@$L!4Jq6hCdhIB>)bpV0B2;Q<^a}JIB z4JP1bXyVyuKp2BZ76QgwduxLJ{2q^JqviwqtZ*3iW54ENiPEm#VNQF zQ!qINSA#&>86c?lq&0G0(KN*^XFr1DuIet$^ZZW diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_mic.png b/java/res/drawable-hdpi/sym_keyboard_feedback_mic.png old mode 100644 new mode 100755 index cb86a5598a7a9213a0755ea1670f6e27d25e9528..f82c33ae301f555db4c640eb2733e2126e83b493 GIT binary patch literal 2494 zcmaJ@c{o)49zO_?B}NpfX&MuiS<^5Kh8asWbj?&GF=mc2GK-nf%v4HtAzMU@nzv0v zdV5Ni^wv$dp6qR&l$KXzFE>j?_vlUU{o{7e^PKZrp3mp=U4Oslq;B`|)YmoF1pq+b z+l%T4jacZVF4ls+O;>MhhlUkWn!l7G43o-OVi2HkgrOkZo6q8cejtmZh-v|y06+u5 zWBN<|>Dx$bAs@|}$DrkW5yS=nCl|Sh#oh->;h`XxCmTV<8JPsML%Z`qvi`>C* zp4R~}$T;A`WFOeacHkgfoZ(J#5+uL}r7XCdA1RQKgQD4+imEs^?x zfBXACg(Xad2*mh-5@EEM4HYhI?Yt=w$z2Sxq(U)MD2!al;`VT%R454-is0@HJ2;)i z<_YH4-|=)h$y*?ivIK0$3raS!@q}2;{Dne>M!+va5=y9 z#h&&{E(UT2Ghf*MD)hn@)IIalpKS{*el|WRfVy1_wKW1|jRpWMyf>A?l=lwrKIp~S zvHbK3Pua(jK_@-gp0jxYs~wIz?q(j#In|MbilkVZs}he`Yu-spKz&Z`A|)I}8B8|C zqGnwERv^3gbVkH*s>=IwYMnhiExCQ0qKg~a$wca&TZE~>H>2e7sIg*6yK=(ut>cT= zGW3gx>mS=BM&oUYmw*T;i3aZGuIitdFE00R@)1oeky!0I8P^9C$U`Y1A!qy%+0(sW)GsmDC#7lUro`$1 z>#9Eap-|6swnRo=))QK)xmHzIzrELEs8A?s93wRSC9kMAMW;0WQ0s>hWDi`-_X~Zs zW=+(Rf$Oaov8HBA(=)L8cJUjt_ngXGHqI9a=5)In9kU)ErpzUbyb1~oJP7-}&9S1Q z!hCw9X+U>6Avw96hUiQzEiIK#S1c+F4h}wvx3p6O-)Vs7TmH;28M<&u9*SvzMd8ZPz2T+HViHESCgKo zhbn%1+~w)BduVaZSKDKM433V@=?}Vf63QPAS~M$qYZX_0snmOp2~TRfo~K3<>cgC0r4vYb8k}zZS2e+O!YLV zr%hTzCCvpK?F1%MarOkl1nk<=uUYCxW%Q;Sm69jaRu8i)JfzPRaA zPf}yt)XdC`6~}!^`!S`*QsYgke(lj!kD@u3qprC2e0D4|+-qiLcGAEl*>s(a&3g^} zgqvr_P&n-bjYczH|KuzqEG%qbO?su(!KNW(@_}d5)9WllJM6WhQMI<(hO=6wEk#)c z%`t}#IW3N93k(XfgAQy(-1}RG<()wc#srMn9s;``AT73K_#O&9^4rdE%J@B+^3=yxD8QDsu zvU&tWHWOhHcq6VZaMGE1vHN{t*Lq7!OATa#snQAv2nykrZ nHaoN*ZT=^84Yes|cEzdzE{Wbow7oEw`9CUenh&+oEhO$gh$jaX delta 620 zcmV-y0+ao|6R8D|NPhxLNklv4lH42E9+*WG|lP&z>wfe}1HHYlBd5$Fc# z26O}H1jz=;2E^`}p3f%(wnRy;(w#03Y)c=OWJykkVMuP7?vfiP2EYIq00Y>T?y(D` zY3h3<6z7V2#b@6j^f{y#z%Zb6t@xmqw)mvDQJj&>Cj?L$MSq70*3acN0w`t_cUe*a zNU=7kd_WkJ5dqV*PrN8TV&zjrAsMLr=qqm&QHWv(IumU|N$^XqXGaeej0bdqGqA;o$Z`vjRP=l zN7h>On9&|+$?Ot;e^mcp0aonWJwXYe@(9^^T&py5Mt?3nAyInPt;w6ao^2jHZ*>XD ziJcN_0LUlox(#SjWuCzB8=Y2buTQ)+JGw}~T*kCu&e7}D?*|ruu=x-$w)wLQ4g=zp z;4;zRkV$$&V|=1TD*n@&-};J4MgZx?!sQySnC$4H9re}ZM*>LRzRhRvoW$|+2?5yD z0$FS7OJydxE5QJ+xvjE*D&x4xOnKM><>EWCBu%g(v_hT(&8A^gMIb2JgucLZOCLBR z=l5s>Mw(C_n6SBdf4=!i%wd!PFaQR?02lxR_|E_?0t^5m_{c7vlRPj00000!!Gs+Ne^=FqU&7Q!5wDLEE;973fiiHAt# zOtBOuWON{;2&sf;4*lkNp8Ed&`1ZYCug~Yc@6YRfy|3%Ouj{_=>yzl@cu-PIQ49b8 zNZKB!uye2NO`inN0{_ipg77QAWr$S-6dK**v z3B+RmH#8{d7n;s+A^peS|4K}EJ3}QwT}X7wX&ONgIA665Q&c3HM#3{FG&c$*@aHNz z`BNAax<7>qLc1D*uy{g1@W%LWJQjZ+8VBpLEB({>RM9>r-MkrjGwy1|L7Y0R(B&6f~W$^)+Aa$D2a%n zQG!5!PZ=5TdtYF`<@;Bc_FdzGqjO#OYrl{XI|rZ$ukI&_J`urmq$b;E zf_)D;f#oEMQr$f;D#|r36=eTdZZqaW6=yx0&S{wZy87b> z#3Hw{LF?g}w8)W|&oNCuUeg=t-KsxlBGp6v0s@>M9eZ;9GOVx8|^(vsuqk zlOXy#5Ix<5xv53$%8&Mr6#N($X z`uh6a!^07!b~oWJdu8)!4_DX6o+RCqCZ=SF)p)@n zc>nu*Q_=KQ%dA@RwOF@Rae4U-0*I_W&9aB@&okm7RKRm05Pra@+#U(Myc=b;wY9|A;hI9Lm^->ju{j4!XF|pvCpIN38F%L{`Vomym$I_h-wb!WGVA0{ z3achxK?ny`cW1A@#J#Gi&h88TvAz~llsnMhzaYUc)*s)^X0x9#R;LH<{D`;M)w4L04hGG%ofIS&}ej9xmVM=ibe11*RLy_2wcrXk2D}xGIby^E>7r3bo4sp zri()I{eD31%*y<`HpNm;>XoJ&xfc|T@U8J9m5$m-WQ58KsHcI#?Cdr4IT{XP5wY;` zjGJQAmg#TuonMYmzJI^Q(&cRuUeJ){-?b^P6_t`&AJq`0_tWB|E5tby@4E0GYAs&WWy|G<7LIpIMMv z)Lt}6{zT_w8(JWaCJEq?oA_FZU4%noes!k?O4FzWM#!H%L-Cy)`H1&rb9$F9T?*ZE zGs3mw9DU|ZopD}w5>SQj3;VP`>B0rOkIN6~9~v(TAKXj?QZI+`Rtha+EOM2<6$%rH zVx7tyzK^baE)dAq@eGV&-I*UKg zM{6MQ$msr?s3F z$r~j%;8K0slNByfJ$L7izqn~%tEQ%QteJTv=}n#b>;Oxv$ybUSRp#*!F3B&^(9-g& z>d=8eX16DH5+BVICtA+|RV|SI-nRw9dKjZ&1B@%aSvd&MvP`^I)8CM0jY~;|T&=FI zK3kLG=;(N&x23o7RW0R@>tnY~F%Z;!kxoW<{DA_^O5+vg%A$&2#qq|dGgay4FXf0k zBoAnxUy~7YKWTM~Z^Ch?D274FNIp~_NL4_0KZOq8gr_(Q#;w`9BFo0?ZW z0i3M9lEZ0FxC*ARhMg@!e}zXxJQ^Pv7#KM1UHI(z^XHGImU9istsSvkf)udnDUTPv z*GX_2Hlazfq_ptIU>MSm%*4uQQhQVz)+YPmsVwyZ~66`AO1 zd1Jeb=&LLX2QD{ z2B}`!%)qKl%~$Mm=Q>c!W~joF51&6*Jl6cKG}>!1AA(XL()zT8Fwv{#KTbkV)}LQUfp2|w+qHz>tIFDkTAa5M_3o-QM9hnUyyfTS<_IG< z+_Y+1jJOG^-mb+iJ7Pmq@O`mvxp{dfnlW~oqyy;PZ3oZAUfz}?7I`(b=~~n6iVDi+ z$U8nWYu55%*T%P}fH`9FbWP8O2{#7NE^={QK>A1Exum2dtfy!GHmsF`%!Kb~Z45{# zuCf{7%Zma9Vx@%@t{i1jsq@jxe5c2i_>nZLV&VMRVr*V3Gb&21%8~N6{)|PLi3xS| zfZ3;o<~@y_^>J$VO~U8Bk^J~QhPBm!rZMZQ&Z24d2AN3_c?Wo@v9SQ4x1Dcz+<6sY=#X!xwtf|(B(Q67y!&^lw)rF?I zdwQVfzI){)1oRc-?FMP;fmQv6bAp}ku*D+4(d5fySKdp;BK>{ zCCQ*Ha4}gvX6wp|?97_0-OjbuRkOs|K@yNc)Sbx?oP||62m>X5i}SMuqN{vmGUmW| z?bU5uJmmWXcSf*b#7{Y&P|uLPu=&wZ#|}D;*4Qqa;O?_+le~EDL~lBq-t+8PU3ad8 zX#IfFSAu-4$Kbzs>nwHIO zW2k351_lQOF&#TxU0p5PWinHvV?~C9#btCjIO$f28@R6{PM~pLGmzpVyIt)vJ*{l< zA7zbu`rZ3a9({GVz%227=~I^}tBXFG$f2CTO2D_L2F58sT^*f3kw{t;lez0&h3H2i z_}l=nb;=zHwXS92rks25@`^+o2Z!f&27#vrgrRXINxp4)B&BfAz`&WpesYj|?5ca0 z)P6My`#;}Q5)R6#w0Xc6M5bE&`^izEqkeD^?SZ#5(UOu?JHI;IzcMj8I$!RD&%B(N zX-86L?%Rwy>zZy$4nf8SidcZqWxnT*0Hb&eF8Ac_9b$0W=Qfaf9oaPD|;Eqh7Bv}d3kvUjonY4Jb805m3`^1 zho7I{hw~xs=5Oo%JX!7EyJb=K8nD$}>pN8K-SYetk~cJTCPPrG7w|Icwb{oXh4?@p z`15W-{7+4$C>b}}e4wu`e|ZylcRQ<2aG^j$B&wIaCe{qtaR+vPMVC0{clvd0!9y*q zzhHC%D!!Y_3>!!)J(+(~P(KdKssG{InM}AkZWYBc-KLlcE+HX7w=E2cliQ@2k9x4w^OfCJ=#Ffb-3frK0me2{vg}AYe>|&e{xX>S zVvLPumJT$z!NA2W@lmSkw+}m9lRA_iEmbAdmE64zyxx>35xMyR^`AO)qeR{Ht4c*p nwr*6Z=?|&tBecH?0h<79DQEu3Gg8RLkEX4SqjkBJ_u2mgM%%t= delta 1280 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 delta 814 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 MNRyFI7H1Xx11A*-*8l(j delta 825 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 delta 223 zcmdnNHJ@pMM?J$qPZ!6Kid%1PZ{%w-5Md3-np05r{D1lWQ<2xwC3}uuc(EXC_UB3B zPV7ben!fFml#*U7Epv8fWhMwNJH9Do~zBAv3ZuZ(z~70KBsLz zXR7NgZEG4)_ws5?>c8WeW?^z>X2Ku*##`_ubR y%|7+`^VGdJ^_|12H$RDIkN|=i{MSMo7#W%tnZH~0Md&yK5O})!xvXPzz<^eQ;pm|~-p}fQZifodF1V}bb772($l^PVZ zf>s8IXcZi%q9Rd*imi`;z}SiiRuLJ%RvC(&Sb?IpYBvb9KT3CI_ulW$Ip_QCch8;O z9T^cif1cMo91b^MvQ8L{jZEwn;$5*X**rf684%| zAyxKg?Qk#-=R(rN%2ByY%26U(D&)XWOy#!JuFWiZNSBdaq`wFzq&%>?ObbSmiB(lk&e`+ulbJA*c& z(eOX@{->}pHd_zVqG2PFX;5MZm*V3{rRN9?FoYt8SOm$K?qZ}GK@p=G(F1}Qe?SH) zH9AK;iI>SZ5}gr+bV^tvZeeY+NYPmx$}0^xVkGA&5>eoDo1Nm?tp@?o0fnHw(tWbCTM zVU*)!8{J55KUUc}jH-f{F4%tjdk~7U%RJ+L}Ttfe1UCvOVcZ7^VYQb zm)BUJn%QvU7b$)C{m;`o?%5|M%J%0jGuw#;#c7fNR^xsAPQG_##0e)GQs7PM%H>(N zm#gv*|Nb;|F$iwn97-yYp6fYf)wU`6Gu*r_d-iUtutgnGfqTVOiwLfWv7We+U@f`v z=rG@sx4>*~ykAT(!&R=f+FYdXWV5xTW9Ue$qAr-w|4btwcou4X-0{_kr{mV+y%kr+ z%(lUhANHp5d)-|gS9J^}(iRsT8F=+U-IxAzm@WV=ssgcb`4#uRjJp9O_zC_fvBo_uXA*lu+_(=aoex15G25_wv_1zs$nSbrme!wal4- XYg_|MN687}j^Bqw6d^prPu}r2=-HSz delta 400 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 diff --git a/java/res/drawable-hdpi/sym_keyboard_search.png b/java/res/drawable-hdpi/sym_keyboard_search.png index e72cde3bb6b1265464a78f0deacaf2143bb526c2..1aa22d7e23ec73cffa924d72cee411c9fa0cbd30 100755 GIT binary patch delta 1204 zcmV;l1WWtZ4D1PzNPh&5NklATlHp`^F3({78w;15|W@)D$k{- zr=OHcr3$%RuHf_e0Xm&dySTWxFfuaIS6p2D4932LDH_lfuWdd@>V(J8EAeGzWyN~E z{+ro>tbjB%HGkD7B_*AQd6C{&|Av8qNWd#+Iy*a?%`VE!%*=FFR#pz!i19Qqo-<{O zoqZ4hnlLmp^du!E;?`XA>9?()wv!3|&}dW#t2Vp0Z*y1oqoS%#hSZ zd3pJL=zmwR2`sFzu<#c1Zqq&DEHGj>xv#J94YkwL)6)TciJk!FE~OGCCMN#f4_dAE z3mm{Y%!V%7nI9b;eNP(-g<=mm6ItVm0TPKsOdG%`<_KMKRZMU{^t2HK;_4prG_W;@ zz9rg#{T2ovfo|CG7l}kd+E@ia+iU_e0c+6FhJQ>ZQxL-Is)%A^W8-LJZf;KRDemYl zu=%R0s&2Zc!o$PGa44Suh9Yx;Fk@zoNli^XO8dsg$4B5}fo&3eXmWCLoMyDKv9S-( zchK3)2(k~42s(d#eSHn6)n(`pX8VAamz0#;WwM9b+S>pa%Zfk3M348bke4PSa-pmTx-kcqzaz;-|kvQ8J7g=3h{m53xwtu#^ zzMw}4E1~GF5{YkbZ*Q^%4v!E5PPo;82_1pMYXsbu0_GGrYZbPq3r%l`5uXfaWMo|L z=;&y+ya-8l6|$|GjN6q&ts#|TNb6T~iICZm=Qr(lz zf5yf@*mT1FQW*>eY88pw2m{@ioo>@VhMM^bdkDT@_=m8L;tQFIb5&aFRD9MMU5rgk zvUAG$+RI0hCTbEVxp2srd(J)I{oTj8zjG7LXf(Q=#^UaFN`H$BmI*Y~qT zB6%6~2_O+5VI=sRfV$q^-e1s`ZHvCpC;4`F1~44ab9s4r9~cYv*6Gd`b6Kh%-V4Q!w&j^Buz|A++;^wsZ@3ls1WKHXQn;sLP64d zdV0E8AAjf*ebYNQM*_noa>m!!H%p_@sQC_UK?w~Fy$ZUs=0KSM7XfYF*xA|H<^7;f z@O=f}VeN9X)L&adEK(%z^78TwZ*OlOzH)qge0XDHV-+5EK^{av3mrk74sEf`$jHd= zybgVql$5-HkH^7b-EFk>jEjqlWh@Pd<;if zx4F5w&Q?Z8M@Q1W@ZhY-ZO8`0zqeE>J;&FF7)VsvzLhW4M{k?bBvIvC`VN~PLj&mdsyGN_NIGsxY74-wg1tg5Q| zjP-#&q5egBheOXXp8UoEEox^wwZ6W-0TJyT(8YlG^Q=SAR!litOlD^0yZ7$h+hl$8 z_xE?AZ(=A81;!_);Ry)|SK)Bo7UWsT)PM7dJ>X#-L?Hd?8Tn#TR#w*gLNW}qrHYM> zeUofFoWT`28qwIgy1LJWOdXj-OH0f5$SS}F_fHB*Mo36VPHSsx6U#REQd3j&BiOtS z5-H%B4ozFcGy^FE0|P&q%Cq+O_cf46{sFB01`0mkhhi=-16HOgDk}OEd|sjD9DiaB z1F=V<=}DX}4flrekOc-nD_G9AJ3BkSg|qPz_&!gwCvxP~07th_2re0xk_@=tinV|s z*sNAoR@Ol@Z8W7{T3WhIne{UiMMaJR#?Bm`VbL(kmlX=d*R!*;Q^G`&&)HCiHpJpF z&3SEjc=)C{@Hsg-?+GKVwZJ%Qe}DKhLn`A!cGRp|uMzTZ91P@{O0vg(&jumlcgE+Qi0 zdEBoj9T*SJgZ58yV`JlWy?iW02MHs UD%|&*82|tP07*qoM6N<$g21%|V*mgE diff --git a/java/res/drawable-hdpi/sym_keyboard_shift.png b/java/res/drawable-hdpi/sym_keyboard_shift.png index 8149081786d9a6b6e2dd4e636d64c3bab9f37be4..1a64dcce613d3c3e13d7f503ff62a3f1871ff621 100755 GIT binary patch literal 1814 zcmaJ?do)ye93Srzi6fN{gl0kt<{z3dC5uYl+d3j+U-Mi40o00{{R_yjT@mPG+XDwV3yAd#F?@1W-~WKg(rE{qlR7P*3zb78K?1<+&w z&B6ZbpqIAL>Cu?WV~aY=gAYm2X_uj69Xwq>hu)SGzD(~RMaR(hVLpMe>(u#am3!}` z(`WcreT}WSN5`_Mwo}6lJu_d^n%+RT%plo0{qUwSp$V=2%Re8de+R6dvQP=wn+v)! zGRAhEsp3}Fgt@sMjTyW%+}-!V)@}drRK7g*Re5sS{Iz}Dk{}lK1nZC^L9gicy0#kq z@{p~``Z#k2#LC;zo*ryjs=OQEj_6EZ?X4U4^R!Z`W2xFS-O!^Qrj_A+A(Yu*=5w`_ z`g~LYUV8MJuYB5hWG1rgockp~OG=NudRMXfP5iUt>Yl99Ld8qkn-+;-hA@0=AT;K{ zfhy~)-z~VpJINjG_|#+_zZ0szq;8VNrlvIe#({x>hWh$?oo^C%x_9>H0{gvhV?T?| zeHdBo>Fz$0Z8|tOSgUVfFjAMA_q3v-qToh(e(HGcuPwS6&h#dR@>XW)-%MN?)!7-b zqW}(O(ZGl>%6;}V5Nm92pkI<%b)lxezrS*8l1MaY66V!5ectK%t+yT9(OBEl?)#>E z`{1DWl>p1EHJNvnAwv`af{dHR%r@sV+l*e#o=Ls=`1IUKbGN>-^|nS_198-@oSYnQ zi#)$C67H+j1%^)?qu*TXs)!i*$!^x#(n!Bx&Hn0MCmSnwm`^k}H`fw_Cc4^9m+21Q zUhh@r#M{kQg!E;%QB+cP#^@gSrP7l^nPkqiGA=ZKdv^0vGNLf7rZfcvC99ZK|uQ%c0#SloROrn?-)O(~EiF$EmZqQ|+gR_9b0T zyIZFysyfV9cNZ2Gj+AV~=~W^0(Ft%60pV8->bW*xCKoi)={Z%`-Q7*QV(VqNy2v)6 zt#-)&=Xryo_qr^{UUKRBBF;G*?24-2yDnOk4Ak!PFvaMtvPqM9u>?~gPDp9;5y-rpO`pKP_- za@)LT`ua&?+{1&yRMyyfOTQYGXz=SU452$q`bX6hySXRYp*9!iMD&k$VN$OxOiLe= X>7HL)qT1M?`BV9_{F&Fbg{S`mR)yz( delta 1441 zcmV;S1z!4=4%Z8iNPh)+Nkl-oyX8F#OGW0V{?=soxQzWe)q-}%lt_q*YEo_{}a97S>Bm`aLRidc$R zirAh+CAJ~Qar>P>R2&5J%NG6JlZZ)Csswq37Bn4H4H^awfCl$NPIgzs*^8&NLP+XV zMMZ^uVPWBGtJQiDuFaqtx-XCH25cKhN&N++&RQ&%TPrIoe}J8znVI<&Y!1+u_DW6^ zUO9*nSPg-9xPM%(ab6&!qoe&`zXE!O+>=XsVgyo6psyeaBom25!aY4bKQnT@y}e(- z{mY1okq5XGGfC+S4 zK_hr1F)}jJ3$|-SqKLU>I2;bX4+1s}D4C$jq$5V45P#go`uh40(De|!+wJ~M5G)L! z=koIMN|u+G|HS(~pU+!fUj7!?Eua} z(7f&K>~{NYu)jk2jyrT>1OmaH2XN&G62S%n0bf;B)!VcZc%KtY!oMrq*x2|HTiN;f z`A2%a{(m~yU;e)|kO*QdtmkBBXWv9{2r>%N+}!*L*sW~u#Mz6lcXV`o&H~KD#Kc3e zT?NhFEe*&`jD>XsadmQXa*P4&?(V)1HXEo3NyJGBEPC39hljsoeFp~zzd;*TE1+pR zk&}}cM-Rn^7Yqyxe9M51kB|Qdwl_deGhn+Uaep>3*QTbXeqm#Db#=7~CnizE*lgoN zZJnK+Uob$lPn^PXNn|Z~79-`-($XAr<))^lkI9t{+tYwt#PA^}L0@ZWX}O0W5X|c8 z>JyvIc9%+}^Hh15X^$aEg&-|x2yhmy7`87gC@6UEDF}||_xm?%YHI4hegRZ3OapQd zQ-9DyF4Wc4)dz#YXA}WLrKP1`g8f}k4BIzBofHVHL_jTAp)-`MF~8lQ_So-kSy|Zw zNZb(|cWrIW<8(T!!Jf+^s~p5$6t*QLCAYm^?_*wsz|22}KCjZs;TXo^;$jCcQZSL{ z=jY!LMoKw|=^PG+6=w30SYR6)8&AkRjej)8>B7RoQeJ}0&CNX&u9_IUlHZ^k8X9t- z*83jFWr8bepdNhT`}lt-6w+j5WSpz6uD;G}G}9~qC?P3pgkz44js31vD*Y;zDk?aN z;88UiO&9`FpufN0R#{p3(}ACPkVF75z9_n=^igihGkARpHvOB77|b3=!6u9Dn}30P zrf|^O+S&)Rv$HtnI?l!RXVOu^253|+Vo`cXC{9&?<3(VGp9)uzYCt5li6kM||2S}2l|r?5TMp4>rUmSe@zzzs8`bfETW$?l2@ zsEgH-a>(=ciexADA1Nv-`V{tD73eMei`Pl>wPim7(GL^z8mJc+h^~)5F@Fg8dU`j* z=Nahw=o5n?_ug^%q8WoKJuGQpM_V>G7Q{ zUPGwrLq?-<6Wh}p!+{AW_9sUYzCo+##ZpH{3A=r0*djvsHV_tDFN(n|2Qg0I=3+YW vg8juOoY+y5)DKuv#8Sjk#2WS_{|GPunb@fot7JZ-00000NkvXXu0mjf^n0)f diff --git a/java/res/drawable-hdpi/sym_keyboard_shift_locked.png b/java/res/drawable-hdpi/sym_keyboard_shift_locked.png index 31ca277181eaae1e148a0f67a0e56cc39f347069..807e977515b80b2e3e6b9986bfc86e9290390191 100755 GIT binary patch literal 1523 zcmeAS@N?(olHy`uVBq!ia0vp^W8U}fi7AzZCsS=07?_nZLn2Bde0{8v^Ko2Tt~skz|cV7z)0WFNY~KZ%Gk)tz(4^Clz_GsrKDK}xwt{?0`hE?GD=Dctn~HE z%ggo3jrH=2()A53EiFN27#ZmTRp=I1=9MH?=;jqG!%T2VElw`VEGWs$&r<-In3$Ab zT4JjNbScCOxdm`z^NOLt1Pn0!io^naLp=kKmtYEgeeo;J&4sHjE(uCSxEHIz#UYgi zsro^w#rdU0$-sz9QwCX8VC7ttnpl!w6q28x0}I7~jQo=P;*9(P1?ON>1>eNv%sdbu ztlrnx$}_LHBrz{J)zigR321^|W@d_&tD}*Hv8$n}qobjbp`nYLldF-dqpPuni;I!5 zo3pDMOs`9Ra%paAUI|QZ3PP_LPQ9R{kXrz>*(J3ovn(~mttdZN0qkX~Ox$iU#%Uf@ zZwhX=nBdf_4|I$^C}NQ!8YToxJs>7L*#bH6grAxROzlO$WIbcu_ecf?rgTpi$B>F! zZ)WY!7EY8oR^4l#WIg4GrfJZs3@?_20Rl}*p#|qJId&ZkF2T@SokHV+vgN6ly_zQy?@=o>r212{l5!ED}?L5i8{?q1d7FPG%e3gxL|Z< z_2(^7YwHa4KF;`BR9BgHV1dD$Cr`Aep4um=aE&`A=oY&)&n~X~f=f$-GSBk}p69;P z_JvzbqJ(uHv%RKR_xv*)N!Hui-+TQ}Xmp(ZFnUgk-TeO_#HCn!-g31ba&O$NYk82N z+3ADTp1Eh!?w9VqD_qRCu~u(-_4$93gg?pp+-uGL@YqM~^R~Nr^0N(()V(<`b29pi z^c%H58gu>jTekGDZ?rF-p}uop>KMKJT@Mc*8C#BQ&>nzg@&)o}Vx8TVtG`HmfZEhe`4{C>w{i)NfJw3yeE zEvoY_?#iuc*%xK(`DYYgV@^6yr>Uj?=*5DomY?kUH@|ybV)eGb;!o0nmCiR0|D95_ zWbXqD>9cVa!f~&xr+?YeZPi-;<*Mw?2W#Fhh~C>+Rc{(|vs(C;lF+-|bu$-(BTa0D zzR&M_=DIfD%57|({rBkmpRjJKXY8pq_6^G6ecLO0H!k7o`I5e5XH~_SSNm07x(6N< j@i{1xqj%sRrvXFPe80Uj&ulyeDuz8>{an^LB{Ts5aXC$T delta 1062 zcmV+>1ljxZ3*QKkNPh$YNklF-=WOCZE@P>s6*9 zi8C=1gPjA1NoL;XoHsY`-S@&V#u|tKaXxyt=yj%H?uhfbT6po}Md% za>5Ek%Bn9ib-Jys&9}C;7KZyQ6bgNUd%ZwMrRF5*Rl*pFD(LHE_6~V;B#7lVY1|Fy1I#;*GNSuzux=}nUfm|+^9~~Wi2IV?| zRyh;dVHneq$W9cE;#nD_0fU2s51~9xC`~|Z-5DcMDDEPP&15nHlYn?U9_#Dty9@Q& zfo3T)bC7!=ixB7Xsx46LuOe|NjxeyD$z);sRdjen5{6Yw00Ly@ckgu~&l7K_CT z?VQ|i8K{M^-D&-l-EO~);@AN&H#hel+PVU?ms6Xj*gBS;+awjVm6dnm zwt$hFpESY0?uek zo*UNm_>CqM8)OUD#{LK}0G)y&dA>a%(*OVf07*qoM6N<$f*Gm!e*gdg diff --git a/java/res/drawable-hdpi/sym_keyboard_space.png b/java/res/drawable-hdpi/sym_keyboard_space.png index 3e98b3014a42d082a1af04467894cb2a01e542f4..fcd20de7decfe526f90183de2a944de4ae34ef4b 100755 GIT binary patch delta 262 zcmey&bc|_&M?J#}PZ!6Kid%1PIdU~Qh#V`N&$9EfUx2v4t5tJ1_)S=w^Sw&g@5BPj zX-kj%Z{E%!`KxY4bGKlq@1YJ4q1o%c?(cao_040lJ+DE+fd)oqHXaFF471QM=Ih+E z=lbRqZ?wD}^IStqY2D##^=X$&ELLV+-F-k-nPd6Xy=E(4|4Q3`ddAoL65sEyYkq&Z zbP0l+XkKKkIvE delta 308 zcmX@c^qFabM?Iscr;B4q#jQ894ssn<;AzXw{P=9?h0Ah@>vx;q4u12(munYC;*O?V z@r$`n|0}XY8PrMn@~skZDtG&O*OS$tfsrSHfmz}J0~=1}8y2Z;by`c6et0aq>8_j7 zw>N*ohnqhXS@fA6ALOaOdB*P4B-&m z_^SD0;=aGtjo*0Jm2}>Tv4 zq}24xJX@vryZ0+8WTx0Eg`4^s_!c;)W@LI)6{QAO`Gq7`WhYyvDB0U7*i={n4aiL` zNmQuF&B-gas<2f8n`;GRgM{^!6u?SKvTcwn`Gtf;oFf&jvGt@IQ zHZeCh*HJJsFf`CNFw!?P(ls=ndS0-B(gnVDkcYHDiXVq|XS=xFF_Xz1eRv4~Pj*wm=R%;iu*SQ+p9GSr?1m^k-mTtoL+r45_$v zX6kOg!v-P_>o2?bMlYDMFhqxgvxTLGDL&xXxtyAadImMKG`ocyA0;M8ELdc7ORaaK zY%%loNu5EqH8nJ2S6=Bh9s(N=7p^n}T3wisudN`(4Jsj0hqgo?e-rI?)L z{-yFox3c#1uCCHP=lz==8a_Lsb5$xW$d2v9o%?sMiHEIB-u?W{leJ3OZKpr~-aNN# zabRe2f|rHhm8lFn?zhZNw6V0g_3Gh8=}%sJ(%)BHi@G3|Ict?guUiDe!wox_u6$wL zBINn*-yucAt>=4w{5lx-Kd+#4(-D``$$ftUlrJ6B*v-BE*|l90U8@aV?-!Mtpw{wM zOeepr;b-Gz!HYo$o;>87lo)o8KgnnB5AEhzopr E04}7?xBvhE literal 0 HcmV?d00001 diff --git a/java/res/drawable-hdpi/sym_keyboard_tab.png b/java/res/drawable-hdpi/sym_keyboard_tab.png old mode 100644 new mode 100755 index 1d4d92bd16c5768e15bcb70000d7a8f7e0f0c16f..51d17d98962e2064b99da6fb8a253c9fffbc451d GIT binary patch literal 1434 zcmeAS@N?(olHy`uVBq!ia0vp^DnM+^!3HG%UtYBvNJ*BsMwA5Srr5%(GQ`zk9!uLS~AsQn;zFfp39xYDT62(s|s5su(?)1Hb_`sNdc^+B->UA;;0DU00rm#qErP_Jp*lEl2^R8JRMC7=m(LT&-jW|!2W%(B!Jx1#)91+bT`GI6`b5~q1k zy(zfe;)qkPKF~4xpom3^XqXT%^?;c0WDDfL6MkwQFtrx}lXaw#M+E}|6Q8GxV@SoV zq(A@v+aFF~^5JRb>9NYV;&}L+qmDw;#EFFg7HlCb8v_mtcrjEZY~XS6V31X0Sn|a2 zALFBThd+f2E>B=GNYStP|L?EJ1YL6pp{)!;v+GT6^ZzaCU^>8i#&D0rFKdB%Hnl7D z%(6~F+w<<;5|WUR;5?=4aC~F%(vl?%5e%E(_0M-OsQvZD)M1~d$#sLqGe=t+4={TC zXMf4MDL3Gb)57K)hqiz1O{>G#-~0CIlNb9`V}~<#5BQiElbpKO@j3D7hKFAl$q+pV z6l;p?(A~mz#_`0$r_Y{E<5|1?#s^D|oia>YnOPP(p7CGOT+$i1Wa-kSn+hKvTWOqr zE+#r4;6nfPnk52B+qP{h`{SR?z@_W#d^j#fu_ea9sP5+{*9q4`nKib2dwYAjkB{fy z`R(n`ZP&_{yuG#6+Rx9gxX|pL!$Fo@w@Fjm8V=q&d+?y+hEqRSSw25Idwb5znKwCC z6*YXz`|d_XLjZDD}oHODF2R?c6! zVns#pW?$cx&HI>SKbCHZH+!{!kwJdK4SDvO8V(LQhG+@43m+G{GrvmdKI;Vst08T&6XK_h?wn4iYAz>dgF?8+6O7G?)wE|O_rb+AL4C5xQSPJyz z<>mXOQb~))zYU*hq5V)R5BwlkMHPMxYdW=97&SZh_hkwBO04PjRCr?gJ#zUb{|Jc}A ziux&%&Jd+;SCM*2_N_9UYBqY;1(0(dc}&TK!65*C;~^0VxE6 z9bcwjuG2fx2^z!#*?V2TuPAHk2Y%HZ5T)T}IRKbjtE;PzPy)ar ziG;mP8Md*$zMh5Y&ASN%GxTMAeEcP@5<&E~Xq4f)wlXs_^AYR;ry;+HhNh>d@1;_y zsPl#G?d{y~@bKK;-rjfYOO|Cz1juGUG*eZueSb=7(g{E;%1VY|+;%?9X0sn6k;rq1 zvR&#w)Cy385?GypMDq|vr5p?f3;ctXm6f+6BO@>1Bf7spX{1LKh=*zrlxSjYx-A?I z7irmHEiEm*nwXf#5X?6!wjt{K+)D?#q6|PK$T8;P;^KTVnOq~6?^BVLL}1(ivf2I$ zTz|Hk$z&b_%pcXBo~vx()-Iq5=w;2h9>QnnLI`!?aohkxfS&~Md&P+Ny;w2Y+%~u) z*3|sKuADD-_hp>|#I$Crs@lv)l(8G^7{&{rW@*wi?WieURW+$ZnLJcGU4|fsx~^l2 z@DW&`_V>Jx^b|UnI_?Cm!p)Q`dqI1V*VuU?nVO_{-gLyfB^u`1hNu1HC=cB0000kP^2V-*_9AdaKub@XFawYqSu6c_6w|6z3ACIY%(O6 z2oqr<^C89`gkeaZ`#l9g00}sbWBNIrD2k%__WN}>kd%^&qUi2WJ=U_wb=~g%eLM~x zO)^qf75$#iRM#~m5yx@pW4F6sT6vyR*=D2vB2qL>LrwbwD~x03Ahd(q3ynmFwyh9# zDSUS`(ho+A9-9uI(78KQ<0WVC8JrO&0!DnE8y zluP{#N=9yJWZ)0w6&X~q>yR1lwfZ)P+O;<2exWDBM9dhC{5GhqcM?{2LJ5>FC`1?|0?ia1Q-C}TJxZIhamj`0000< KMNUMnLSTaTDdBMd literal 0 HcmV?d00001 diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_normal_off.9.png new file mode 100755 index 0000000000000000000000000000000000000000..38b8b48aae600c82c23365a54a11e7797970f740 GIT binary patch literal 774 zcmV+h1Nr=kP)KoFh8#46Q__yHpN z(__@b)MK@WX-}e7p;au1A81TWXBJa5i8c{j$G8h3WR=X@_vX!HU3HK%+)Lj;lXas@ z)~?2Ii2Qq@x%fmRz?z#46gWW zHamJhZO6>tycZj{WH)zgIB2J|@_uF5=wLa_A8S|FVkJ9Blol1Xdc6+4UQdAXz)+pA zvBM~r%Lg6CpR6J?BGI*|hO}BO7@*x!@)HP>Q?tIg^sC01zFi5aq49qWjN z;3#+etq9v>_lAvu|4b&4TrPUDU!g^b+iS6GQQ~fnv29T<#>h2tBu*!wa^&W7MB@nP zobK19M_q;zI|d}V8+4}mS=NZUF)v8U)II&oPx*}2P9xS=suqiRgPRaN0hX3IJIym*O-69ia$2a(7kvAPB=SM2rC>`+E*F3Wb6= zxds3%8KE&AkHw+1gDF3d8y)Iz7yKxR(Ei^5|{e1PU*!m4>3uqj^u?c)sH}IJdO)ZPywOhX{#{YzK+~Aq)^n3UypE z&XuN1nb5+<$1(L#(MUZ?SW&dO+}XyXmBR!OrIhJKfyi7)5DKRvQSlsjRR=D02E*qR zfe6DG;gCDC5hG5$BeU$^z1fsIwqP8?dMZUo8dlFZ#d#F@AeA*b`?Y}QctGA%^ zmBhWMBNhZG-@X%P1V$giXv3>YEMI($+jl$yQ6-j=DVLUAG*?`_dG#J2*DsQLxujc> zg|RsqDH4cC!>LSISyQqrk+sXK74-KMI^8yUJAaPK+xcCqXhxD)YJOa- zhi3O{HIeIreD3`D2pb}E`}AubAma-agCj8{$q$Q$30`h`kgO+jIa2XNm2aP%CiX&l zY6C~1h{WrEsbjNU$8di#oJN#8e4pp6A~N|TO^}#V>?qi^lu2-c1RP<oDxLzJIVl2TIDj5AAXAjqPYyBL`TJg9E51Cdt~54 zeE$3f%gqivH^O$Of%fJNZ2Vs%p?4ANN5o2;Qx`iMV!~IDY}*&LOALhQZr?%c zW7UM_A(cpe*GF%6n?S?{1eYnswX`K-NBZ$Gl^w>7xuy#C(C-bBS_>krwUnu~B6g`v zADQ5-2*2qXLStmG3`rY-IEY+&tSm9(ShTaHL>VU@1`vT!1R@%{IvSlnd_AIP*mo+7 zOaPj5>yE`p;TriFRe>!U`QfU-CXIY&z&pN1gpGiX#Yi@pW1)pEHVw$xy+JoiP&PAi zc7e=_)mG(_dBd;mA-Hs{(zQz0`i&E!p0}Q{g^_6*IaD9&6SyVx!-Zqc;WJ)q9bALj z8MS_^>euRI_&o{HS{$(Sc2JoROO05rkUW&(su_UR7bu! z66i^ZAQ2>jRF|RNuv)EPyWPTaxdbVTlNp}tZQiCKAyn1dPNx&>b~`v8kJZ!fe!qwL zd=9VIOPyy~rYb>%2Em#niK$pvaF)6m~73U|a-Lls-!PNC%j(=^E6a-^#u{T=Ks z&NS(Wevi`G(6VXhFGzl~SSQvujHv0`aT{OvrTaETi0Zzbw()HWFYgOt(;&`Ul(uYB z-kE;?_U^YyM?Siav=JnRRt&8eTEE!F^M$8Pj@TB%UajoC3N86=ST(&xvCUe7!$|hh z&-I^q2dU6fKiH*q?;8>h;;?v=zC!JxM6NhpNEq*aU@r<2NW1}p4&N;M5JQqw^LNsPVh88(NM`sWe zj5&>%4w$BCA#bbhk<6!ODsqLKm`o-x9*2!%C*Os7-0 zUa#h7*xj%yi^T%g>otrOX*($NzC?V^2_I6PVEgx-Gw Z3;KUEXEd(t-2~(lL|T3Y~L$&b>2j zuSC%_JM00hs0Ip~M}~H!r9@I9DUsDJs~@<%y`}s6d%C*1BHLb0X4uz{g_edaOLhI& z^Yb&c+imLi`>WG$r_-UMqa*tL{Z;$3*-UjN5j7F?OeUi`+TPwCeSd#btJPZixI>X* zu}H(=P!VAgI+-YmFbVD;0*t=a8jXfD9*@;YyoiKNMyg@knWa9RPX2CZj+KLh2tdwe z06GURm5EakC@~+~a>d|6gchLZM4YMw-F|+4=<)H9-rwJ8GMP}RRHD1PJ32c%Q+Vb> zT53C2iA;#t3&5-fZ^N+G=jSK&dObQhIic(8YszM`^zrdQ4-XI2Xf){Z^3tJ{ks|WS zGYND_FeoB8&(qTrRjXAxJw08d+e)QEhlhvs`ua-ca#@j-b_0&J6p_D&5hu9v@IHXb z^8zf0An6PS13ErFR&j#yjTMph(MbdyBh%?r0fwF2Fcb=fB`mC%8-`eyC?KKF-g-P7 z92{)6M3IVk^`II+;(W+dZmM8nK0iNqjBTul37H@|taWj5p_Uw@(P)ua5F1}#Un}oX_PVx;dx_$ewJb@-7C-vF{(U@Dear331FsX)RWQx5h;H9XF~EP>mq#w)`H+1f8i^6;>jj&(r?? zzN6fO+=?^b-rf{wkYOUSQYa20Y-XZlqSAzhhPZEPCOIv~Wj{pMz*zbvBJVhcF00000NkvXXu0mjf)ja5# literal 0 HcmV?d00001 diff --git a/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.png b/java/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.png new file mode 100755 index 0000000000000000000000000000000000000000..b7dccfe3c5e0a32b3c99c683d613d7de2f89cc87 GIT binary patch literal 1332 zcmV-41cjbtHNmUTDYEVp~Q~gXP8LFQ1pldq~P%#1c6V_QEKIo0%4JnI*Ar< zTV_!f;Ym{B8w?=fxB?9qWA|YQ))0j>UdWn+vWyfoHXUba$N<4uv<69A<*L@;*$2A{ zcTy0_4xS%B#YN{&1bz>{Lo^f( z{WTm6gSUA3@&N6xCBE8j!t+`<`};LsJpYZ{{3krv{08Jz1QT-DD~LiCv1i^uaJK=k z0^+cnIP50uS`ruMzvJ8Q8U(RMfvmr?`M|{|4_&-?_7p+bCM#|#a2_AA$IN9B`*>k- z!tuc{q$mhq;q$F?eDP}M=%Pd)TLM0owzGu&$Kj@_Q)r(lf8T!=-)2nVk6bHO#C zt7gB|5}C2YpS^$g0i2|?ru?GpRKJ>tgO$4H-B*^FHaAW0uKI$Uv5Io0S)`O6#jzJq z_aEW>{2qpbw9f~WsX7;u62lXnIm78O>SUY0JdlVx2@5C-_4^|PgP$o&Iq3cyDe)l* z?)M_ReG}lH_dj6Jze6cGRKGFxC9Am~197FsVrc$Y9LGVobC2rDuQ=`ef%T17XgDME zdY@4t{2u;ri$DgHdZ7xTi06IoU@rqi1uUV+KnFd~ucDCSy4EVBR(QbbGjh!>`G z7;uq{CN3(>3Ygbeh%F(6OkJZaFGgUC)r!UCy53sl#|z8xa(}vp<$+*w_LEoJdghHw z&DP*%-xQRyN3Z0*VcysUm+`YEz3j_&A!cMfSuofucdt1TPG0+{7+E&RTy~(Ev}@;D3#}uo2vWON?OL^K&FNZp!C5tnC{ zualoua4RoY%j{s6iE9^`)2kuL*HYJ!6>m4cAg;1&-RMPQ9V6H7dSu?)GG(|{p03)p zYLI2bh}kD)-w4avH&sd4y1m0J+amwA&5|2N4TbIaOwP>QR>d$epVc@Q%#VoqQ( zg@LIG#Efr46t;*x`^gk&tW$RSwI|VZ-f(6^6>=^6%LdAvyvjX|Hi&^K>{>>=E!gZ5 zGBH!7YZ*(J=fWT?nD;dDcEI6qII(YQ)-9PuXDVYAV~Mr3H8h(|xNbTkQtzCdohi`_ zV?gYkLdyU#Zp|RARtud@C;c1iYFM>)yN%u5U3i|Ca-(H{B;C#TeH%$@+V1< qYuaj%l?9o0XKAGb=Y8;>00RK)ea#N;9MrY|0000~($Fc5_Y@QRv4&~qV5 zPDRNfxCT8}fR3<6{CHz0k=W%=TM&)Ob3_xx;(eKC&zMYz-ZRwMH*nr{qq8|&y2t+Y@B2nq z9LK*n#M*?qu4xzsmJty`P!I&i*1FvqlJeWo>xrC(j)au`UE|lHauCZ8D-#KB(J*SC zy0pf_h&(1dE`A`}y2KVW=ZLIn0|-D)0=aI9av5vQCvXKpL~Mu%7CZ6?K>oeh)$G8? z@wuH^)g|^yWt&QQtE{!R1p|Z|$aNDU=Mv?m&HBv#nbyLt1#7`tuoio3sjFDanZu~r zizUd0HnDkb;o1waq3trY7Jg?(LPSFRkc5ae0&Brq009U<00IyjGP`cK>-(Ohlr)Yb zE3uyEnQNtKblIF)RTZ^uYr0HzgC?tQT?o@?ki^u|P+ICaa0! z;v$N*TJ51ysXTd}S9Kg-I;PVp42Q$lZnyi~YPDYQs{oPEZ`!(!GH_Kcmz$+h$Hx5xlRZjUj#t_GMSHt;7M(BsH zPN&oE^?HxRV)2|~2?aqg@_oNeTn*=WN~~+n5I2ZB#4X|)=3ZbfR#Pe^a$xrn?}#@< z4~$(_W%`A(Kz>^C)h_I)oP@+C6GOxYVzkIg)*J7_(ig9Rr#C)^r9VD_HQxA5tH3EX c^8FTI04_5jMM>=0SO5S307*qoM6N<$f(eWq^Z)<= literal 0 HcmV?d00001 diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.png new file mode 100644 index 0000000000000000000000000000000000000000..fe6c517f9115113b4811ebbb3a555d43f1761d63 GIT binary patch literal 1514 zcmeAS@N?(olHy`uVBq!ia0vp^MnLSs!3HD`yQJj;DajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_cg49sbnArU1JzCKpT`MG+DAT@dwxdlMo3=B5*6$OdO*{LN8 zNvY|XdA3ULckfqH$V{%1*XSQL?vFu&J;D8jzb> zlBiITo0C^;Rbi_HHrEQs1_|pcDS(xfWZNo192Makpx~Tel&WB=XP}#GU}m6TW~gUq zY+`P1uA^XNU}&IkV5Dzoq-$tyWo%?+V4wg6Nh+i#(Mch>H3D2mX;thjEr=FDs+o0^GXscbn}XpVJ5hw7AF^F7L;V>=P7_pOiaoz zEwNPsx)kDt+yY-;xWReF(0~F4nSMoLfxe-hfqrf-$X{U9#U(+h2xnkbT^v$bkg6Y) zTAW{6lnjiIG-a4(VA$ce2&53`8Y};zOkkuW=D6f1m*%GCm3X??DgkBmQZiGl++57v z3=Pdq49txT%q$EIEzKQGot;e$TwTrGOw27@U}j*`>tbR7)amNv=m-pXLl-wES0h(P zS7Qqo7b9agXID3vUeCPZlEl2^RG7V)KzpHj9r5b5axO|uEXgkl$xAZ!`CVki~X)Q=>r|34@w+Ji3KJEOo1RKJm~{D@XV8%2h1@=z^oD1tz^o;z$E4A;uunK>rM22 z@52rvb)Lb3S_iE}?=ETb>(gsm^x(;ZXY&Xf`(F?sTAd&h}c zQbL!HR4a1KjRiut>v#_{oZj@u z<{?u`)peL=HSeW zizeE9vhVL$zbRGqvz(_}u^Sr!|&i>hKq*VMzbM1q) zeeSW{YA#0Bz8xltliW`zgH)=tv`i2Xa&juN+HBp&ye;?l?RQms=Y^yc+AF`SaqSb- zh&iF$E&2b&Ye~Bq9gONd-&SSMs&5Q^94b>MVtgrSV=ue)RBMY}Ya15&ctkp>zL(|` zk3X_-+Wbig>fgA!XZPGn4qfj&dG_9yI|?S4vYwE1{ZhJiWw6D&e+Srpe>n8@fp6HS z6TFs6;ZJ0C*}lBEFVdQ&MBb@0P9mI A0{{R3 literal 0 HcmV?d00001 diff --git a/java/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.png b/java/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.png new file mode 100755 index 0000000000000000000000000000000000000000..d09bd3db3ce5421d83cb2b1f29bbba78847a6915 GIT binary patch literal 812 zcmV+{1JnG8P)j+?{MP&={YzZox z!v{xN2hxFbAo(qj2bRkvtk-K;EEeDSGm1pFl7>7_bl&#+J#01`*zI=t>Gya%!gM+n z3Ws5s^eRDo-%mP?UoIDz&1PSxrz|p=OoZ~E&nFY4Y#0u~L3+Jjazq`quJwAo62P!9n656!B3Zf^gUBb#Cbj)`&yr^p zBXzP!5xLF;d#-EM4J6OC++88c0bVqFl$n0p86&1ZRe{KBc=uyO^#ZI*)>6suT&ppz zrE@Ra7SYZ18aLNc$<|I$ica3j08#1Hz9~whU8|`eZl~X@?^VuzO=iJPStN2L*gXzY z_w|TMzT58+-4wcx8+7ehSp8Qswxlu+9KFd zHgzg@G6tdAC^{J}&|}p&Hj8RFgbZX9BSg-#gs9fB41&4@K_EbkV+0$y6ZcE3*^&#v z$_C+ZkHg^*`u#qPMxzva3gmP;B^O<< z*93%0o2n{2BP-w$LB``ToX_X8U}fi7AzZCsS>JirPF~978H@y_sgs$DqjJ!k(0v{`4<@##7dm)-~c0!lv56 zl0qL+KQMQ4?Ca{N+9ja2M08Dn7w1~jH3G(quW_~V*A{ahlbBc>#}wdY$WZ*Cm($Ec zHX-L)7=vwfx%C4Ez5=!bXVSm$vwtzYb(iT=G)P3Z;e3lbL(9c(!=>w9{f)3^;$bkb VF_7Zg{_h#c^`5SNF6*2UngERVOkMy0 literal 0 HcmV?d00001 diff --git a/java/res/drawable-mdpi/sym_keyboard_space_led.9.png b/java/res/drawable-mdpi/sym_keyboard_space_led.9.png new file mode 100644 index 0000000000000000000000000000000000000000..71da57319421de5694f096ad10c42e319d7c4828 GIT binary patch literal 1291 zcmeAS@N?(olHy`uVBq!ia0vp^8bHj)!3HE_x#Qe`lw^r(L`iUdT1k0gQ7VIDN`6wR zf@f}GdTLN=VoGJ<$y6H#24v4 zq}24xJX@vryZ0+8WTx0Eg`4^s_!c;)W@LI)6{QAO`Gq7`WhYyvDB0U7*i={n4aiL` zNmQuF&B-gas<2f8n`;GRgM{^!6u?SKvTcwn`Gtf;oFf&jvGt@IQ zHZeCh*HJJsFf`CNFw!?P(ls=ndS0-B(gnVDkcYHDiXVq|XS=xFF_Xz1eRv4~Pj*wm=R%;iu*SQ+p9GSr?1m^k-mTtoL+r45_$v zX6kOg!v-P_>o2?bMlYDMFhqxgvxTLGDL&xXxtyAadImMKG`ocyA0;M8ELdc7ORaaK zY%%loNu5EqH8nJ2S6=Bh9s(N=7p^n}T3wisudN`(4Jsj0hqgo?e-rI?)L z{-yFox3c#1uCCHP=lz==8a_Lsb5$xW$d2v9o%?sMiHEIB-u?W{leJ3OZKpr~-aNN# zabRe2f|rHhm8lFn?zhZNw6V0g_3Gh8=}%sJ(%)BHi@G3|Ict?guUiDe!wox_u6$wL zBINn*-yucAt>=4w{5lx-Kd+#4(-D``$$ftUlrJ6B*v-BE*|l90U8@aV?-!Mtpw{wM zOeepr;b-Gz!HYo$o;>87lo)o8KgnnB5AEhzopr E04}7?xBvhE literal 0 HcmV?d00001 diff --git a/java/res/layout/keyboard_key_preview.xml b/java/res/layout/keyboard_key_preview.xml index 64eaa6579..de03506ad 100644 --- a/java/res/layout/keyboard_key_preview.xml +++ b/java/res/layout/keyboard_key_preview.xml @@ -22,7 +22,7 @@ android:layout_width="wrap_content" android:layout_height="80sp" android:textSize="40sp" - android:textColor="?android:attr/textColorPrimaryInverse" + android:textColor="@color/latinkeyboard_key_color_white" android:minWidth="32dip" android:gravity="center" android:background="@drawable/keyboard_key_feedback" From 6a1514a0deac7f3d8ec33430403b2caea05bc8b9 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Wed, 1 Sep 2010 00:27:04 +0900 Subject: [PATCH 22/58] Make KeyDebounce class a top-level class and rename it to PointerTracker Bug: 2910379 Change-Id: I9503b2211b272a4a2903d0732985e5ab8ee39440 --- .../latin/LatinKeyboardBaseView.java | 461 ++---------------- .../inputmethod/latin/PointerTracker.java | 400 +++++++++++++++ 2 files changed, 440 insertions(+), 421 deletions(-) create mode 100644 java/src/com/android/inputmethod/latin/PointerTracker.java diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index 280801a55..0833a4043 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -61,7 +61,8 @@ import java.util.Map; * @attr ref R.styleable#LatinKeyboardBaseView_verticalCorrection * @attr ref R.styleable#LatinKeyboardBaseView_popupLayout */ -public class LatinKeyboardBaseView extends View implements View.OnClickListener { +public class LatinKeyboardBaseView extends View implements View.OnClickListener, + PointerTracker.UIProxy { private static final boolean DEBUG = false; public static final int NOT_A_TOUCH_COORDINATE = -1; @@ -146,15 +147,10 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener // Timing constants private static final int DELAY_BEFORE_PREVIEW = 0; private static final int DELAY_AFTER_PREVIEW = 70; - private static final int REPEAT_INTERVAL = 50; // ~20 keys per second - private static final int REPEAT_START_DELAY = 400; - private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout(); - private static final int MULTITAP_INTERVAL = 800; // milliseconds - private static final int KEY_DEBOUNCE_TIME = 70; + private static final int REPEAT_INTERVAL = PointerTracker.REPEAT_INTERVAL; // Miscellaneous constants - static final int NOT_A_KEY = -1; - private static final int[] KEY_DELETE = { Keyboard.KEYCODE_DELETE }; + /* package */ static final int NOT_A_KEY = -1; private static final int[] LONG_PRESSABLE_STATE_SET = { android.R.attr.state_long_pressable }; // XML attribute @@ -203,7 +199,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener /** Listener for {@link OnKeyboardActionListener}. */ private OnKeyboardActionListener mKeyboardActionListener; - private final KeyDebouncer mDebouncer; + private final PointerTracker mPointerTracker; private final float mDebounceHysteresis; private final ProximityKeyDetector mProximityKeyDetector = new ProximityKeyDetector(); @@ -249,15 +245,15 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener public void handleMessage(Message msg) { switch (msg.what) { case MSG_POPUP_PREVIEW: - showKey(msg.arg1, (KeyDebouncer)msg.obj); + showKey(msg.arg1, (PointerTracker)msg.obj); break; case MSG_DISMISS_PREVIEW: mPreviewText.setVisibility(INVISIBLE); break; case MSG_REPEAT_KEY: { - final KeyDebouncer debouncer = (KeyDebouncer)msg.obj; - debouncer.repeatKey(msg.arg1); - startKeyRepeatTimer(REPEAT_INTERVAL, msg.arg1, debouncer); + final PointerTracker tracker = (PointerTracker)msg.obj; + tracker.repeatKey(msg.arg1); + startKeyRepeatTimer(REPEAT_INTERVAL, msg.arg1, tracker); break; } case MSG_LONGPRESS_KEY: @@ -266,13 +262,13 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } } - public void popupPreview(long delay, int keyIndex, KeyDebouncer debouncer) { + public void popupPreview(long delay, int keyIndex, PointerTracker tracker) { removeMessages(MSG_POPUP_PREVIEW); if (mPreviewPopup.isShowing() && mPreviewText.getVisibility() == VISIBLE) { // Show right away, if it's already visible and finger is moving around - showKey(keyIndex, debouncer); + showKey(keyIndex, tracker); } else { - sendMessageDelayed(obtainMessage(MSG_POPUP_PREVIEW, keyIndex, 0, debouncer), + sendMessageDelayed(obtainMessage(MSG_POPUP_PREVIEW, keyIndex, 0, tracker), delay); } } @@ -291,9 +287,9 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener removeMessages(MSG_DISMISS_PREVIEW); } - public void startKeyRepeatTimer(long delay, int keyIndex, KeyDebouncer debouncer) { + public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker) { mInKeyRepeat = true; - sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, keyIndex, 0, debouncer), delay); + sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, keyIndex, 0, tracker), delay); } public void cancelKeyRepeatTimer() { @@ -326,370 +322,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } }; - // TODO:nn Rename this class to PointerTracker when this becomes a top-level class. - public static class KeyDebouncer { - public interface UIProxy { - public void invalidateKey(Key key); - public void showPreview(int keyIndex, KeyDebouncer debouncer); - // TODO: These methods might be temporary. - public void dismissPopupKeyboard(); - public boolean isMiniKeyboardOnScreen(); - } - - private final UIProxy mProxy; - private final UIHandler mHandler; - private final ProximityKeyDetector mKeyDetector; - private OnKeyboardActionListener mListener; - - private Key[] mKeys; - private int mKeyDebounceThresholdSquared = -1; - - private int mCurrentKey = NOT_A_KEY; - private int mStartX; - private int mStartY; - - // for move de-bouncing - private int mLastCodeX; - private int mLastCodeY; - private int mLastX; - private int mLastY; - - // for time de-bouncing - private int mLastKey; - private long mLastKeyTime; - private long mLastMoveTime; - private long mCurrentKeyTime; - - // For multi-tap - private int mLastSentIndex; - private int mTapCount; - private long mLastTapTime; - private boolean mInMultiTap; - private final StringBuilder mPreviewLabel = new StringBuilder(1); - - // pressed key - private int mPreviousKey; - - public KeyDebouncer(UIHandler handler, ProximityKeyDetector keyDetector, UIProxy proxy) { - if (proxy == null || handler == null || keyDetector == null) - throw new NullPointerException(); - mProxy = proxy; - mHandler = handler; - mKeyDetector = keyDetector; - resetMultiTap(); - } - - public void setOnKeyboardActionListener(OnKeyboardActionListener listener) { - mListener = listener; - } - - public void setKeyboard(Key[] keys, float hysteresisPixel) { - if (keys == null || hysteresisPixel < 1.0f) - throw new IllegalArgumentException(); - mKeys = keys; - mKeyDebounceThresholdSquared = (int)(hysteresisPixel * hysteresisPixel); - } - - public Key getKey(int keyIndex) { - return (keyIndex >= 0 && keyIndex < mKeys.length) ? mKeys[keyIndex] : null; - } - - public void updateKey(int keyIndex) { - int oldKeyIndex = mPreviousKey; - mPreviousKey = keyIndex; - if (keyIndex != oldKeyIndex) { - if (oldKeyIndex != NOT_A_KEY && oldKeyIndex < mKeys.length) { - // if new key index is not a key, old key was just released inside of the key. - final boolean inside = (keyIndex == NOT_A_KEY); - mKeys[oldKeyIndex].onReleased(inside); - mProxy.invalidateKey(mKeys[oldKeyIndex]); - } - if (keyIndex != NOT_A_KEY && keyIndex < mKeys.length) { - mKeys[keyIndex].onPressed(); - mProxy.invalidateKey(mKeys[keyIndex]); - } - } - } - - public void onModifiedTouchEvent(int action, int touchX, int touchY, long eventTime) { - switch (action) { - case MotionEvent.ACTION_DOWN: - onDownEvent(touchX, touchY, eventTime); - break; - case MotionEvent.ACTION_MOVE: - onMoveEvent(touchX, touchY, eventTime); - break; - case MotionEvent.ACTION_UP: - onUpEvent(touchX, touchY, eventTime); - break; - case MotionEvent.ACTION_CANCEL: - onCancelEvent(touchX, touchY, eventTime); - break; - } - } - - public void onDownEvent(int touchX, int touchY, long eventTime) { - int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); - mCurrentKey = keyIndex; - mStartX = touchX; - mStartY = touchY; - startMoveDebouncing(touchX, touchY); - startTimeDebouncing(eventTime); - checkMultiTap(eventTime, keyIndex); - if (mListener != null) - mListener.onPress(keyIndex != NOT_A_KEY ? mKeys[keyIndex].codes[0] : 0); - if (keyIndex >= 0 && mKeys[keyIndex].repeatable) { - repeatKey(keyIndex); - mHandler.startKeyRepeatTimer(REPEAT_START_DELAY, keyIndex, this); - } - if (keyIndex != NOT_A_KEY) { - mHandler.startLongPressTimer(keyIndex, LONGPRESS_TIMEOUT); - } - showKeyPreviewAndUpdateKey(keyIndex); - updateMoveDebouncing(touchX, touchY); - } - - public void onMoveEvent(int touchX, int touchY, long eventTime) { - int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); - if (keyIndex != NOT_A_KEY) { - if (mCurrentKey == NOT_A_KEY) { - updateTimeDebouncing(eventTime); - mCurrentKey = keyIndex; - mHandler.startLongPressTimer(keyIndex, LONGPRESS_TIMEOUT); - } else if (isMinorMoveBounce(touchX, touchY, keyIndex, mCurrentKey)) { - updateTimeDebouncing(eventTime); - } else { - resetMultiTap(); - resetTimeDebouncing(eventTime, mCurrentKey); - resetMoveDebouncing(); - mCurrentKey = keyIndex; - mHandler.startLongPressTimer(keyIndex, LONGPRESS_TIMEOUT); - } - } else { - mHandler.cancelLongPressTimer(); - } - /* - * While time debouncing is in effect, mCurrentKey holds the new key and mDebouncer - * holds the last key. At ACTION_UP event if time debouncing will be in effect - * eventually, the last key should be sent as the result. In such case mCurrentKey - * should not be showed as popup preview. - */ - showKeyPreviewAndUpdateKey(isMinorTimeBounce() ? mLastKey : mCurrentKey); - updateMoveDebouncing(touchX, touchY); - } - - public void onUpEvent(int touchX, int touchY, long eventTime) { - int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); - boolean wasInKeyRepeat = mHandler.isInKeyRepeat(); - mHandler.cancelKeyTimers(); - mHandler.cancelPopupPreview(); - if (isMinorMoveBounce(touchX, touchY, keyIndex, mCurrentKey)) { - updateTimeDebouncing(eventTime); - } else { - resetMultiTap(); - resetTimeDebouncing(eventTime, mCurrentKey); - mCurrentKey = keyIndex; - } - if (isMinorTimeBounce()) { - mCurrentKey = mLastKey; - touchX = mLastCodeX; - touchY = mLastCodeY; - } - showKeyPreviewAndUpdateKey(NOT_A_KEY); - // If we're not on a repeating key (which sends on a DOWN event) - if (!wasInKeyRepeat && !mProxy.isMiniKeyboardOnScreen()) { - detectAndSendKey(mCurrentKey, touchX, touchY, eventTime); - } - if (keyIndex != NOT_A_KEY && keyIndex < mKeys.length) { - mProxy.invalidateKey(mKeys[keyIndex]); - } - } - - public void onCancelEvent(int touchX, int touchY, long eventTime) { - mHandler.cancelKeyTimers(); - mHandler.cancelPopupPreview(); - mProxy.dismissPopupKeyboard(); - showKeyPreviewAndUpdateKey(NOT_A_KEY); - if (mCurrentKey != NOT_A_KEY && mCurrentKey < mKeys.length) { - mProxy.invalidateKey(mKeys[mCurrentKey]); - } - } - - public void repeatKey(int keyIndex) { - Key key = mKeys[keyIndex]; - // While key is repeating, because there is no need to handle multi-tap key, we can pass - // -1 as eventTime argument. - detectAndSendKey(keyIndex, key.x, key.y, -1); - } - - // These package scope methods are only for debugging purpose. - /* package */ int getStartX() { - return mStartX; - } - - /* package */ int getStartY() { - return mStartY; - } - - /* package */ int getLastX() { - return mLastX; - } - - /* package */ int getLastY() { - return mLastY; - } - - private void startMoveDebouncing(int x, int y) { - mLastCodeX = x; - mLastCodeY = y; - } - - private void updateMoveDebouncing(int x, int y) { - mLastX = x; - mLastY = y; - } - - private void resetMoveDebouncing() { - mLastCodeX = mLastX; - mLastCodeY = mLastY; - } - - private boolean isMinorMoveBounce(int x, int y, int newKey, int curKey) { - if (mKeys == null || mKeyDebounceThresholdSquared < 0) - throw new IllegalStateException("keyboard and/or hysteresis not set"); - if (newKey == curKey) { - return true; - } else if (curKey >= 0 && curKey < mKeys.length) { - return getSquareDistanceToKeyEdge(x, y, mKeys[curKey]) - < mKeyDebounceThresholdSquared; - } else { - return false; - } - } - - private static int getSquareDistanceToKeyEdge(int x, int y, Key key) { - final int left = key.x; - final int right = key.x + key.width; - final int top = key.y; - final int bottom = key.y + key.height; - final int edgeX = x < left ? left : (x > right ? right : x); - final int edgeY = y < top ? top : (y > bottom ? bottom : y); - final int dx = x - edgeX; - final int dy = y - edgeY; - return dx * dx + dy * dy; - } - - private void startTimeDebouncing(long eventTime) { - mLastKey = NOT_A_KEY; - mLastKeyTime = 0; - mCurrentKeyTime = 0; - mLastMoveTime = eventTime; - } - - private void updateTimeDebouncing(long eventTime) { - mCurrentKeyTime += eventTime - mLastMoveTime; - mLastMoveTime = eventTime; - } - - private void resetTimeDebouncing(long eventTime, int currentKey) { - mLastKey = currentKey; - mLastKeyTime = mCurrentKeyTime + eventTime - mLastMoveTime; - mCurrentKeyTime = 0; - mLastMoveTime = eventTime; - } - - private boolean isMinorTimeBounce() { - return mCurrentKeyTime < mLastKeyTime && mCurrentKeyTime < KEY_DEBOUNCE_TIME - && mLastKey != NOT_A_KEY; - } - - private void showKeyPreviewAndUpdateKey(int keyIndex) { - updateKey(keyIndex); - mProxy.showPreview(keyIndex, this); - } - - private void detectAndSendKey(int index, int x, int y, long eventTime) { - if (index != NOT_A_KEY && index < mKeys.length) { - final Key key = mKeys[index]; - OnKeyboardActionListener listener = mListener; - if (key.text != null) { - if (listener != null) { - listener.onText(key.text); - listener.onRelease(NOT_A_KEY); - } - } else { - int code = key.codes[0]; - //TextEntryState.keyPressedAt(key, x, y); - int[] codes = mKeyDetector.newCodeArray(); - mKeyDetector.getKeyIndexAndNearbyCodes(x, y, codes); - // Multi-tap - if (mInMultiTap) { - if (mTapCount != -1) { - mListener.onKey(Keyboard.KEYCODE_DELETE, KEY_DELETE, x, y); - } else { - mTapCount = 0; - } - code = key.codes[mTapCount]; - } - /* - * Swap the first and second values in the codes array if the primary code is not - * the first value but the second value in the array. This happens when key - * debouncing is in effect. - */ - if (codes.length >= 2 && codes[0] != code && codes[1] == code) { - codes[1] = codes[0]; - codes[0] = code; - } - if (listener != null) { - listener.onKey(code, codes, x, y); - listener.onRelease(code); - } - } - mLastSentIndex = index; - mLastTapTime = eventTime; - } - } - - /** - * Handle multi-tap keys by producing the key label for the current multi-tap state. - */ - public CharSequence getPreviewText(Key key) { - if (mInMultiTap) { - // Multi-tap - mPreviewLabel.setLength(0); - mPreviewLabel.append((char) key.codes[mTapCount < 0 ? 0 : mTapCount]); - return mPreviewLabel; - } else { - return key.label; - } - } - - private void resetMultiTap() { - mLastSentIndex = NOT_A_KEY; - mTapCount = 0; - mLastTapTime = -1; - mInMultiTap = false; - } - - private void checkMultiTap(long eventTime, int keyIndex) { - if (keyIndex == NOT_A_KEY || keyIndex >= mKeys.length) return; - Key key = mKeys[keyIndex]; - if (key.codes.length > 1) { - mInMultiTap = true; - if (eventTime < mLastTapTime + MULTITAP_INTERVAL && keyIndex == mLastSentIndex) { - mTapCount = (mTapCount + 1) % key.codes.length; - return; - } else { - mTapCount = -1; - return; - } - } - if (eventTime > mLastTapTime + MULTITAP_INTERVAL || keyIndex != mLastSentIndex) { - resetMultiTap(); - } - } - } - public LatinKeyboardBaseView(Context context, AttributeSet attrs) { this(context, attrs, R.attr.keyboardViewStyle); } @@ -842,30 +474,12 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener mGestureDetector = new GestureDetector(getContext(), listener, null, ignoreMultitouch); mGestureDetector.setIsLongpressEnabled(false); - // TODO: This anonymous interface is temporary until KeyDebouncer becomes top-level class. - // In the future LatinKeyboardBaseView class will implement UIProxy. - mDebouncer = new KeyDebouncer(mHandler, mProximityKeyDetector, new KeyDebouncer.UIProxy() { - public void invalidateKey(Key key) { - LatinKeyboardBaseView.this.invalidateKey(key); - } - - public void showPreview(int keyIndex, KeyDebouncer debouncer) { - LatinKeyboardBaseView.this.showPreview(keyIndex, debouncer); - } - - public void dismissPopupKeyboard() { - LatinKeyboardBaseView.this.dismissPopupKeyboard(); - } - - public boolean isMiniKeyboardOnScreen() { - return LatinKeyboardBaseView.this.mMiniKeyboardOnScreen; - } - }); + mPointerTracker = new PointerTracker(mHandler, mProximityKeyDetector, this); } public void setOnKeyboardActionListener(OnKeyboardActionListener listener) { mKeyboardActionListener = listener; - mDebouncer.setOnKeyboardActionListener(listener); + mPointerTracker.setOnKeyboardActionListener(listener); } /** @@ -895,7 +509,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener List keys = mKeyboard.getKeys(); mKeys = keys.toArray(new Key[keys.size()]); mProximityKeyDetector.setKeyboard(keyboard, mKeys); - mDebouncer.setKeyboard(mKeys, mDebounceHysteresis); + mPointerTracker.setKeyboard(mKeys, mDebounceHysteresis); requestLayout(); // Hint to reallocate the buffer if the size changed mKeyboardChanged = true; @@ -1165,11 +779,11 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener if (DEBUG) { if (mShowTouchPoints) { - KeyDebouncer debouncer = mDebouncer; - int startX = debouncer.getStartX(); - int startY = debouncer.getStartY(); - int lastX = debouncer.getLastX(); - int lastY = debouncer.getLastY(); + PointerTracker tracker = mPointerTracker; + int startX = tracker.getStartX(); + int startY = tracker.getStartY(); + int lastX = tracker.getLastX(); + int lastY = tracker.getLastY(); paint.setAlpha(128); paint.setColor(0xFFFF0000); canvas.drawCircle(startX, startY, 3, paint); @@ -1185,13 +799,13 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener mDirtyRect.setEmpty(); } - // TODO: clean up this when KeyDebouncer class becomes top-level class. + // TODO: clean up this method. private void dismissKeyPreview() { - mDebouncer.updateKey(NOT_A_KEY); - showPreview(NOT_A_KEY, mDebouncer); + mPointerTracker.updateKey(NOT_A_KEY); + showPreview(NOT_A_KEY, mPointerTracker); } - private void showPreview(int keyIndex, KeyDebouncer debouncer) { + public void showPreview(int keyIndex, PointerTracker tracker) { int oldKeyIndex = mOldPreviewKeyIndex; mOldPreviewKeyIndex = keyIndex; // If key changed and preview is on ... @@ -1200,13 +814,13 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener mHandler.cancelPopupPreview(); mHandler.dismissPreview(DELAY_AFTER_PREVIEW); } else { - mHandler.popupPreview(DELAY_BEFORE_PREVIEW, keyIndex, debouncer); + mHandler.popupPreview(DELAY_BEFORE_PREVIEW, keyIndex, tracker); } } } - private void showKey(final int keyIndex, KeyDebouncer debouncer) { - Key key = debouncer.getKey(keyIndex); + private void showKey(final int keyIndex, PointerTracker tracker) { + Key key = tracker.getKey(keyIndex); if (key == null) return; final PopupWindow previewPopup = mPreviewPopup; @@ -1216,7 +830,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener mPreviewText.setText(null); } else { mPreviewText.setCompoundDrawables(null, null, null, null); - mPreviewText.setText(adjustCase(debouncer.getPreviewText(key))); + mPreviewText.setText(adjustCase(tracker.getPreviewText(key))); if (key.label.length() > 1 && key.codes.length < 2) { mPreviewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mKeyTextSize); mPreviewText.setTypeface(Typeface.DEFAULT_BOLD); @@ -1415,6 +1029,11 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener return false; } + // TODO: Should cleanup after refactoring mini-keyboard. + public boolean isMiniKeyboardOnScreen() { + return mMiniKeyboardOnScreen; + } + private int getTouchX(float x) { return (int)x - getPaddingLeft(); } @@ -1468,20 +1087,20 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener if (pointerCount != mOldPointerCount) { if (pointerCount == 1) { // Send a down event for the latest pointer - mDebouncer.onDownEvent(touchX, touchY, eventTime); + mPointerTracker.onDownEvent(touchX, touchY, eventTime); // If it's an up action, then deliver the up as well. if (action == MotionEvent.ACTION_UP) { - mDebouncer.onUpEvent(touchX, touchY, eventTime); + mPointerTracker.onUpEvent(touchX, touchY, eventTime); } } else { // Send an up event for the last pointer - mDebouncer.onUpEvent(mOldPointerX, mOldPointerY, eventTime); + mPointerTracker.onUpEvent(mOldPointerX, mOldPointerY, eventTime); } mOldPointerCount = pointerCount; return true; } else { if (pointerCount == 1) { - mDebouncer.onModifiedTouchEvent(action, touchX, touchY, eventTime); + mPointerTracker.onModifiedTouchEvent(action, touchX, touchY, eventTime); mOldPointerX = touchX; mOldPointerY = touchY; return true; @@ -1525,7 +1144,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener closing(); } - private void dismissPopupKeyboard() { + public void dismissPopupKeyboard() { if (mPopupKeyboard.isShowing()) { mPopupKeyboard.dismiss(); mMiniKeyboardOnScreen = false; diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java new file mode 100644 index 000000000..0c35ea966 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/PointerTracker.java @@ -0,0 +1,400 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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 com.android.inputmethod.latin.LatinKeyboardBaseView.OnKeyboardActionListener; +import com.android.inputmethod.latin.LatinKeyboardBaseView.UIHandler; + +import android.inputmethodservice.Keyboard; +import android.inputmethodservice.Keyboard.Key; +import android.view.MotionEvent; +import android.view.ViewConfiguration; + +public class PointerTracker { + public interface UIProxy { + public void invalidateKey(Key key); + public void showPreview(int keyIndex, PointerTracker tracker); + // TODO: These methods might be temporary. + public void dismissPopupKeyboard(); + public boolean isMiniKeyboardOnScreen(); + } + + // Timing constants + private static final int REPEAT_START_DELAY = 400; + /* package */ static final int REPEAT_INTERVAL = 50; // ~20 keys per second + private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout(); + private static final int MULTITAP_INTERVAL = 800; // milliseconds + private static final int KEY_DEBOUNCE_TIME = 70; + + // Miscellaneous constants + private static final int NOT_A_KEY = LatinKeyboardBaseView.NOT_A_KEY; + private static final int[] KEY_DELETE = { Keyboard.KEYCODE_DELETE }; + + private final UIProxy mProxy; + private final UIHandler mHandler; + private final ProximityKeyDetector mKeyDetector; + private OnKeyboardActionListener mListener; + + private Key[] mKeys; + private int mKeyDebounceThresholdSquared = -1; + + private int mCurrentKey = NOT_A_KEY; + private int mStartX; + private int mStartY; + + // for move de-bouncing + private int mLastCodeX; + private int mLastCodeY; + private int mLastX; + private int mLastY; + + // for time de-bouncing + private int mLastKey; + private long mLastKeyTime; + private long mLastMoveTime; + private long mCurrentKeyTime; + + // For multi-tap + private int mLastSentIndex; + private int mTapCount; + private long mLastTapTime; + private boolean mInMultiTap; + private final StringBuilder mPreviewLabel = new StringBuilder(1); + + // pressed key + private int mPreviousKey; + + public PointerTracker(UIHandler handler, ProximityKeyDetector keyDetector, UIProxy proxy) { + if (proxy == null || handler == null || keyDetector == null) + throw new NullPointerException(); + mProxy = proxy; + mHandler = handler; + mKeyDetector = keyDetector; + resetMultiTap(); + } + + public void setOnKeyboardActionListener(OnKeyboardActionListener listener) { + mListener = listener; + } + + public void setKeyboard(Key[] keys, float hysteresisPixel) { + if (keys == null || hysteresisPixel < 1.0f) + throw new IllegalArgumentException(); + mKeys = keys; + mKeyDebounceThresholdSquared = (int)(hysteresisPixel * hysteresisPixel); + } + + public Key getKey(int keyIndex) { + return (keyIndex >= 0 && keyIndex < mKeys.length) ? mKeys[keyIndex] : null; + } + + public void updateKey(int keyIndex) { + int oldKeyIndex = mPreviousKey; + mPreviousKey = keyIndex; + if (keyIndex != oldKeyIndex) { + if (oldKeyIndex != NOT_A_KEY && oldKeyIndex < mKeys.length) { + // if new key index is not a key, old key was just released inside of the key. + final boolean inside = (keyIndex == NOT_A_KEY); + mKeys[oldKeyIndex].onReleased(inside); + mProxy.invalidateKey(mKeys[oldKeyIndex]); + } + if (keyIndex != NOT_A_KEY && keyIndex < mKeys.length) { + mKeys[keyIndex].onPressed(); + mProxy.invalidateKey(mKeys[keyIndex]); + } + } + } + + public void onModifiedTouchEvent(int action, int touchX, int touchY, long eventTime) { + switch (action) { + case MotionEvent.ACTION_DOWN: + onDownEvent(touchX, touchY, eventTime); + break; + case MotionEvent.ACTION_MOVE: + onMoveEvent(touchX, touchY, eventTime); + break; + case MotionEvent.ACTION_UP: + onUpEvent(touchX, touchY, eventTime); + break; + case MotionEvent.ACTION_CANCEL: + onCancelEvent(touchX, touchY, eventTime); + break; + } + } + + public void onDownEvent(int touchX, int touchY, long eventTime) { + int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); + mCurrentKey = keyIndex; + mStartX = touchX; + mStartY = touchY; + startMoveDebouncing(touchX, touchY); + startTimeDebouncing(eventTime); + checkMultiTap(eventTime, keyIndex); + if (mListener != null) { + int primaryCode = (keyIndex != NOT_A_KEY) ? mKeys[keyIndex].codes[0] : 0; + mListener.onPress(primaryCode); + } + if (keyIndex >= 0 && mKeys[keyIndex].repeatable) { + repeatKey(keyIndex); + mHandler.startKeyRepeatTimer(REPEAT_START_DELAY, keyIndex, this); + } + if (keyIndex != NOT_A_KEY) { + mHandler.startLongPressTimer(keyIndex, LONGPRESS_TIMEOUT); + } + showKeyPreviewAndUpdateKey(keyIndex); + updateMoveDebouncing(touchX, touchY); + } + + public void onMoveEvent(int touchX, int touchY, long eventTime) { + int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); + if (keyIndex != NOT_A_KEY) { + if (mCurrentKey == NOT_A_KEY) { + updateTimeDebouncing(eventTime); + mCurrentKey = keyIndex; + mHandler.startLongPressTimer(keyIndex, LONGPRESS_TIMEOUT); + } else if (isMinorMoveBounce(touchX, touchY, keyIndex, mCurrentKey)) { + updateTimeDebouncing(eventTime); + } else { + resetMultiTap(); + resetTimeDebouncing(eventTime, mCurrentKey); + resetMoveDebouncing(); + mCurrentKey = keyIndex; + mHandler.startLongPressTimer(keyIndex, LONGPRESS_TIMEOUT); + } + } else { + mHandler.cancelLongPressTimer(); + } + /* + * While time debouncing is in effect, mCurrentKey holds the new key and this tracker + * holds the last key. At ACTION_UP event if time debouncing will be in effect + * eventually, the last key should be sent as the result. In such case mCurrentKey + * should not be showed as popup preview. + */ + showKeyPreviewAndUpdateKey(isMinorTimeBounce() ? mLastKey : mCurrentKey); + updateMoveDebouncing(touchX, touchY); + } + + public void onUpEvent(int touchX, int touchY, long eventTime) { + int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); + boolean wasInKeyRepeat = mHandler.isInKeyRepeat(); + mHandler.cancelKeyTimers(); + mHandler.cancelPopupPreview(); + if (isMinorMoveBounce(touchX, touchY, keyIndex, mCurrentKey)) { + updateTimeDebouncing(eventTime); + } else { + resetMultiTap(); + resetTimeDebouncing(eventTime, mCurrentKey); + mCurrentKey = keyIndex; + } + if (isMinorTimeBounce()) { + mCurrentKey = mLastKey; + touchX = mLastCodeX; + touchY = mLastCodeY; + } + showKeyPreviewAndUpdateKey(NOT_A_KEY); + // If we're not on a repeating key (which sends on a DOWN event) + if (!wasInKeyRepeat && !mProxy.isMiniKeyboardOnScreen()) { + detectAndSendKey(mCurrentKey, touchX, touchY, eventTime); + } + if (keyIndex != NOT_A_KEY && keyIndex < mKeys.length) + mProxy.invalidateKey(mKeys[keyIndex]); + } + + public void onCancelEvent(int touchX, int touchY, long eventTime) { + mHandler.cancelKeyTimers(); + mHandler.cancelPopupPreview(); + mProxy.dismissPopupKeyboard(); + showKeyPreviewAndUpdateKey(NOT_A_KEY); + int keyIndex = mCurrentKey; + if (keyIndex != NOT_A_KEY && keyIndex < mKeys.length) + mProxy.invalidateKey(mKeys[keyIndex]); + } + + public void repeatKey(int keyIndex) { + Key key = mKeys[keyIndex]; + // While key is repeating, because there is no need to handle multi-tap key, we can pass + // -1 as eventTime argument. + detectAndSendKey(keyIndex, key.x, key.y, -1); + } + + // These package scope methods are only for debugging purpose. + /* package */ int getStartX() { + return mStartX; + } + + /* package */ int getStartY() { + return mStartY; + } + + /* package */ int getLastX() { + return mLastX; + } + + /* package */ int getLastY() { + return mLastY; + } + + private void startMoveDebouncing(int x, int y) { + mLastCodeX = x; + mLastCodeY = y; + } + + private void updateMoveDebouncing(int x, int y) { + mLastX = x; + mLastY = y; + } + + private void resetMoveDebouncing() { + mLastCodeX = mLastX; + mLastCodeY = mLastY; + } + + private boolean isMinorMoveBounce(int x, int y, int newKey, int curKey) { + if (mKeys == null || mKeyDebounceThresholdSquared < 0) + throw new IllegalStateException("keyboard and/or hysteresis not set"); + if (newKey == curKey) { + return true; + } else if (curKey >= 0 && curKey < mKeys.length) { + return getSquareDistanceToKeyEdge(x, y, mKeys[curKey]) + < mKeyDebounceThresholdSquared; + } else { + return false; + } + } + + private static int getSquareDistanceToKeyEdge(int x, int y, Key key) { + final int left = key.x; + final int right = key.x + key.width; + final int top = key.y; + final int bottom = key.y + key.height; + final int edgeX = x < left ? left : (x > right ? right : x); + final int edgeY = y < top ? top : (y > bottom ? bottom : y); + final int dx = x - edgeX; + final int dy = y - edgeY; + return dx * dx + dy * dy; + } + + private void startTimeDebouncing(long eventTime) { + mLastKey = NOT_A_KEY; + mLastKeyTime = 0; + mCurrentKeyTime = 0; + mLastMoveTime = eventTime; + } + + private void updateTimeDebouncing(long eventTime) { + mCurrentKeyTime += eventTime - mLastMoveTime; + mLastMoveTime = eventTime; + } + + private void resetTimeDebouncing(long eventTime, int currentKey) { + mLastKey = currentKey; + mLastKeyTime = mCurrentKeyTime + eventTime - mLastMoveTime; + mCurrentKeyTime = 0; + mLastMoveTime = eventTime; + } + + private boolean isMinorTimeBounce() { + return mCurrentKeyTime < mLastKeyTime && mCurrentKeyTime < KEY_DEBOUNCE_TIME + && mLastKey != NOT_A_KEY; + } + + private void showKeyPreviewAndUpdateKey(int keyIndex) { + updateKey(keyIndex); + mProxy.showPreview(keyIndex, this); + } + + private void detectAndSendKey(int index, int x, int y, long eventTime) { + if (index != NOT_A_KEY && index < mKeys.length) { + final Key key = mKeys[index]; + OnKeyboardActionListener listener = mListener; + if (key.text != null) { + if (listener != null) { + listener.onText(key.text); + listener.onRelease(NOT_A_KEY); + } + } else { + int code = key.codes[0]; + //TextEntryState.keyPressedAt(key, x, y); + int[] codes = mKeyDetector.newCodeArray(); + mKeyDetector.getKeyIndexAndNearbyCodes(x, y, codes); + // Multi-tap + if (mInMultiTap) { + if (mTapCount != -1) { + mListener.onKey(Keyboard.KEYCODE_DELETE, KEY_DELETE, x, y); + } else { + mTapCount = 0; + } + code = key.codes[mTapCount]; + } + /* + * Swap the first and second values in the codes array if the primary code is not + * the first value but the second value in the array. This happens when key + * debouncing is in effect. + */ + if (codes.length >= 2 && codes[0] != code && codes[1] == code) { + codes[1] = codes[0]; + codes[0] = code; + } + if (listener != null) { + listener.onKey(code, codes, x, y); + listener.onRelease(code); + } + } + mLastSentIndex = index; + mLastTapTime = eventTime; + } + } + + /** + * Handle multi-tap keys by producing the key label for the current multi-tap state. + */ + public CharSequence getPreviewText(Key key) { + if (mInMultiTap) { + // Multi-tap + mPreviewLabel.setLength(0); + mPreviewLabel.append((char) key.codes[mTapCount < 0 ? 0 : mTapCount]); + return mPreviewLabel; + } else { + return key.label; + } + } + + private void resetMultiTap() { + mLastSentIndex = NOT_A_KEY; + mTapCount = 0; + mLastTapTime = -1; + mInMultiTap = false; + } + + private void checkMultiTap(long eventTime, int keyIndex) { + if (keyIndex == NOT_A_KEY) return; + Key key = mKeys[keyIndex]; + if (key.codes.length > 1) { + mInMultiTap = true; + if (eventTime < mLastTapTime + MULTITAP_INTERVAL && keyIndex == mLastSentIndex) { + mTapCount = (mTapCount + 1) % key.codes.length; + return; + } else { + mTapCount = -1; + return; + } + } + if (eventTime > mLastTapTime + MULTITAP_INTERVAL || keyIndex != mLastSentIndex) { + resetMultiTap(); + } + } +} \ No newline at end of file From d0ef2ae291dbcc9a590b5c015d19d0ece391aefb Mon Sep 17 00:00:00 2001 From: satok Date: Wed, 1 Sep 2010 13:32:51 +0900 Subject: [PATCH 23/58] Add new assets - drawable-hdpi/keyboard_popup_panel_background.9.png - drawable-hdpi/voice_ime_background.9.png Change-Id: Iac75c8d488454534a921c59267f2523e47bb5e11 --- .../keyboard_popup_panel_background.9.png | Bin 1443 -> 4021 bytes .../drawable-hdpi/voice_ime_background.9.png | Bin 2349 -> 1271 bytes 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 java/res/drawable-hdpi/keyboard_popup_panel_background.9.png mode change 100755 => 100644 java/res/drawable-hdpi/voice_ime_background.9.png diff --git a/java/res/drawable-hdpi/keyboard_popup_panel_background.9.png b/java/res/drawable-hdpi/keyboard_popup_panel_background.9.png old mode 100644 new mode 100755 index 8e2461b3f184a8d3b91bbfdb951d75624507e4ff..f94bc38ed9bcebb3241bc0256f93c6570ecbdc5d GIT binary patch literal 4021 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 UoUASA>$?aT=$L9(LF~f+2WK~&0ssI2 delta 1425 zcmV;C1#bGaAEOJ9B!3xnMObuGZ)S9NVRB^vL1b@YWgtmyVP|DhWnpA_ami&o000F= zNklwIDa$a^Ouh7@r*paKmPYI zV|)&E9EZeBlv4hoXdFMAkQUR=MM=zM+`<*~b2r-m6m3aqU#Cr5x6~Z~EWgLNI>zzY z_B^%%F%mcz7=)w>85oTrGzdx+f}eA%t|~c9gyseXk1B{HhOU#t29M%-V~7X>Xhd|G zCdcaP>S8XJdw-(q`U7_8Jr*M*0b(pZu=v}utXEf8SI^eg)^-3m70w6^q5c*k(Ei_G-&^zRT_xqn}+HE{QUgq_4V~j;n*~@9+O!9KdXycxYU_4Tpz^jqSd^z9+n` zZkx5Bm4AX3u=>}a>zM9~ohK(JsTto+PfwfUmSH?_p^0{De#yN1PaNg2-~ z&Z@+=ZPEU_Om_e@5jQR|!@8;tBDE6WxCRCW`he^FE-6F7Q7}Ptg&0KHZEcNl9=moK zxWG%uFd%St?G{lVaDii7&>fJj5L>Q=-Sr7|Tz^-BliE&N>8jlbO4aLvZnrraLA52V zMcblU0Ea?w2oAv^I0T16a0m{;AvgqwLU0HU!67&lfaA-GlT<2uO`8T2HI0T16a0m{;AvgqwLU0HU!67&VheB`&4#6Qf6oNx=2oAv^ zIDZs^LvUYS6v3h6Iw$@mK7vEXA-Gh5!~e`_0~|t&2+rv?Sen+vaB*=_y{+Rs>8)+s zz7RWjO4ziBw?%;CZM?j^G$r#mQNZ~oQLk33uf;*5qob(-H!{-9G;W&aJK~c#zSS|V zkxc#U>}*54I5{~<1_uWd4~@5BYHF&nU4N-m{v_UX-M;X&0AQZX^BWr*MfMkYBMz9K zpC@BuV?1|m;(+CHx%y}4Z2)e2v$?tXoHWyQ2affg%+qel)O52pF*=Nz5QIKgZE83`^xW8}yhO z7|Uv;-3lT;uB%BWwum=@ykClI8WX3~)xx3d-Bv9s9;<+<#(i;V&q_w=wHZI@( zL2V23dq=Om9ZN6YyH&w>X|~Q%(Oy}W?!R*+Z}#4}u|qHYrfucC76#U{o@V>^{BH}m z{*`aTUnh=o`R7&@oHs6PXSiXPwP*CxG@7qX* z2Z^l$ZsFnKbCdpghlVC`GYH<{zjY>H}d>WF(~X{n82o<%CMn; z@xUQg2Avor)(tJimRmqUZgGZ72@jbXTDcj-^guc`Sk9RORt}VbYDBPD#2MsTCmS(D z>|g+D0_lLVnz$LFk9$gj>;T&SK)&^-<<8r0cWE*^s2qM6P{5dwd+=?E6;Rd09yjHK ztPBTP8>Tef&fCr^&Y&dOe;ggP zYcc?Rk+8eD`n&2jP{;ypgjvT8^)ybHflmp!R@!(K%xKmV+5{Sc7`MkiS4o$+4)Cf`oWC6qK02VbstvP&%TmcLSvvy#T z26_J=Fa-nommVzPVR#+2gTcY3G?pExG=dpS0P_JP4}o$G3JaLM8r)-dEM3mfpmECn zpsj_)k0-Va4<6n%H@i~0x46=>qOPc@s;sv5@1j+!)aS7?giTJpdH(O;zxvPrelB<4 wyEwo5!8)aufa)-YAoKs?)vN#f)n{a5*d_c!d+roAQ3fFJboFyt=akR{03blT+W-In literal 2349 zcmZ8jdpuNWAAe>T*=AHLxs}+YLg?lenh}~I@g~*AluIU+%b1}FEi>v}k}b1JmU0PY zTbH$Nb5NR4F44S-ncNL6iAZiShJ6nEe%{MJzw?~u{I1{c_c`ap{= zV(S6`rVFmS z)*gNAk#R$*wBa|~kC~?mFVtEcpNFk?l<6iJsymJr?LLrtZ3NHFl|=UC%o!2gPh?T* z7gL7?f=?c$BZATq({btI)4H?ynu`T2X>~D%^Wd?{JCC-4mX7IHhx+c)!a9O6oUKkg z8Q!@}5sx+2r6!sA6gNzFtb0G$@XJC+HhC3)>FJ9l!x;!rzC7hs~H@DP0Id+wja2)%eX;ALpfmT&50# z7uc}h)@W*_6J<(kH_GNQ@J>{qP zc+&$$Mn-kj)tTGnLBv;qibn~N-d^-@#rR+<79HL%17u9P ze%;rVXy5&@lJQg@J~lvTNp{Dg?_fON#rjdyK*CUfs*4}4+R#}LjO2Tqcs3e_;d@4HJl&(bm4VR;=)d)2 zEspa(wlkPguEYa{W7j_=W<8C$qhkmN1`GvV8B)4og(Fr}*r~nfVisF6Phpwwr3iIwBbnw^3chEWHuqt5B zE{KS3NP0~o4{&$U-4#y0$CBRE8^c|-UutliDI5xxPrWZ$K)IZmQ=3fkBDySC*ZJ+|msbvBPVJNFi)NxM;RY3(58B=j8z(x5#>xAVsa~;ed z6<`gxwnG_3#~T6n03Gdd4ccR&fjm$|4LS{g^TSQ(|GEFX#t$uSR9mr@6*#b*ayv35`+`NF;>2u;79vCQ5fofi_@{06P)L}^&mEl~5 z!;loA;lJF6O2V^VDnum))$=z#Qw{K*k{RsIMUmVRm=Dj?!b&tcSGrr=qm<$bJ6fWv zSDO+bWT!pI4R(cW6aLF*CzPcuY83u0st4vVofQ+z13>jwW#g2?*v4i(Y{* zWO)xv4PE>G^lVXr;)BM=o*MTEXj!0&Ma3i=-XwN_+DJyueg}_QSbqvyvk7YIOJpvz zRna4Tc%aI9ap^M-_&e61Dzq^~#5HI7uUoXT9nq$-ZMq5Y z!}S8$HjUk57*1rdC=(vRw=AgPcbt_@n0+jZuLt|Fq>kF@FIYhNnJ4}e2QtK14rI`h zU1N}xbTUHlNDF)*dc>(}Xaw{UPq}^cM`)*%bDX3ZdA&Q6XqJ%+X4|%H^Y-!CYC>;U z#N+X4TYzPah!^0;PD^K(oV$Z$iG|HgO|=hfV${<;*wRkMB7Mlp4unQ)lh^Qw0%1|f zeg{jTUiBxm~+3K78RQC3kI=qe9B%{G1GkJ!~26N#Fd3*u{s9Atoi zHC>!LA=V`RWTY8UzU|}{ldg)GwVE&M*mGuv9#vhcXCi45{oTgK8*bm*Zgm`#wEy@b z)NERY+4;{VxkcySO5S3 From a521b31d96ff51672a3bc399a27a8f02dca840fa Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Wed, 1 Sep 2010 14:25:19 +0900 Subject: [PATCH 24/58] Introduce multiple PointerTracker Bug: 2910379 Change-Id: Iefafa2d30ad16f898a00664e4bf3e3e88dcd2cb2 --- .../latin/LatinKeyboardBaseView.java | 80 +++++++++++++------ .../inputmethod/latin/PointerTracker.java | 2 +- 2 files changed, 55 insertions(+), 27 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index 0833a4043..3efb16b09 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -39,11 +39,11 @@ import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; -import android.view.ViewConfiguration; import android.view.ViewGroup.LayoutParams; import android.widget.PopupWindow; import android.widget.TextView; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -199,7 +199,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, /** Listener for {@link OnKeyboardActionListener}. */ private OnKeyboardActionListener mKeyboardActionListener; - private final PointerTracker mPointerTracker; + private final ArrayList mPointerTrackers = new ArrayList(); private final float mDebounceHysteresis; private final ProximityKeyDetector mProximityKeyDetector = new ProximityKeyDetector(); @@ -473,13 +473,14 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, final boolean ignoreMultitouch = true; mGestureDetector = new GestureDetector(getContext(), listener, null, ignoreMultitouch); mGestureDetector.setIsLongpressEnabled(false); - - mPointerTracker = new PointerTracker(mHandler, mProximityKeyDetector, this); } public void setOnKeyboardActionListener(OnKeyboardActionListener listener) { mKeyboardActionListener = listener; - mPointerTracker.setOnKeyboardActionListener(listener); + for (PointerTracker tracker : mPointerTrackers) { + if (tracker != null) + tracker.setOnKeyboardActionListener(listener); + } } /** @@ -509,7 +510,10 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, List keys = mKeyboard.getKeys(); mKeys = keys.toArray(new Key[keys.size()]); mProximityKeyDetector.setKeyboard(keyboard, mKeys); - mPointerTracker.setKeyboard(mKeys, mDebounceHysteresis); + for (PointerTracker tracker : mPointerTrackers) { + if (tracker != null) + tracker.setKeyboard(mKeys, mDebounceHysteresis); + } requestLayout(); // Hint to reallocate the buffer if the size changed mKeyboardChanged = true; @@ -779,19 +783,21 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, if (DEBUG) { if (mShowTouchPoints) { - PointerTracker tracker = mPointerTracker; - int startX = tracker.getStartX(); - int startY = tracker.getStartY(); - int lastX = tracker.getLastX(); - int lastY = tracker.getLastY(); - paint.setAlpha(128); - paint.setColor(0xFFFF0000); - canvas.drawCircle(startX, startY, 3, paint); - canvas.drawLine(startX, startY, lastX, lastY, paint); - paint.setColor(0xFF0000FF); - canvas.drawCircle(lastX, lastY, 3, paint); - paint.setColor(0xFF00FF00); - canvas.drawCircle((startX + lastX) / 2, (startY + lastY) / 2, 2, paint); + for (PointerTracker tracker : mPointerTrackers) { + if (tracker == null) continue; + int startX = tracker.getStartX(); + int startY = tracker.getStartY(); + int lastX = tracker.getLastX(); + int lastY = tracker.getLastY(); + paint.setAlpha(128); + paint.setColor(0xFFFF0000); + canvas.drawCircle(startX, startY, 3, paint); + canvas.drawLine(startX, startY, lastX, lastY, paint); + paint.setColor(0xFF0000FF); + canvas.drawCircle(lastX, lastY, 3, paint); + paint.setColor(0xFF00FF00); + canvas.drawCircle((startX + lastX) / 2, (startY + lastY) / 2, 2, paint); + } } } @@ -801,8 +807,9 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, // TODO: clean up this method. private void dismissKeyPreview() { - mPointerTracker.updateKey(NOT_A_KEY); - showPreview(NOT_A_KEY, mPointerTracker); + for (PointerTracker tracker : mPointerTrackers) + tracker.updateKey(NOT_A_KEY); + showPreview(NOT_A_KEY, null); } public void showPreview(int keyIndex, PointerTracker tracker) { @@ -813,7 +820,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, if (keyIndex == NOT_A_KEY) { mHandler.cancelPopupPreview(); mHandler.dismissPreview(DELAY_AFTER_PREVIEW); - } else { + } else if (tracker != null) { mHandler.popupPreview(DELAY_BEFORE_PREVIEW, keyIndex, tracker); } } @@ -1042,6 +1049,25 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, return (int)y + mVerticalCorrection - getPaddingTop(); } + private PointerTracker getPointerTracker(final int id) { + final ArrayList pointers = mPointerTrackers; + final Key[] keys = mKeys; + final OnKeyboardActionListener listener = mKeyboardActionListener; + + // 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(mHandler, mProximityKeyDetector, this); + if (keys != null) + tracker.setKeyboard(keys, mDebounceHysteresis); + if (listener != null) + tracker.setOnKeyboardActionListener(listener); + pointers.add(tracker); + } + + return pointers.get(id); + } + @Override public boolean onTouchEvent(MotionEvent me) { // Convert multi-pointer up/down events to single up/down events to @@ -1082,25 +1108,27 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, // Up event will pass through. } + // TODO: Should remove this implicit reference to id=0 pointer tracker in the future. + PointerTracker tracker = getPointerTracker(0); int touchX = getTouchX(me.getX()); int touchY = getTouchY(me.getY()); if (pointerCount != mOldPointerCount) { if (pointerCount == 1) { // Send a down event for the latest pointer - mPointerTracker.onDownEvent(touchX, touchY, eventTime); + tracker.onDownEvent(touchX, touchY, eventTime); // If it's an up action, then deliver the up as well. if (action == MotionEvent.ACTION_UP) { - mPointerTracker.onUpEvent(touchX, touchY, eventTime); + tracker.onUpEvent(touchX, touchY, eventTime); } } else { // Send an up event for the last pointer - mPointerTracker.onUpEvent(mOldPointerX, mOldPointerY, eventTime); + tracker.onUpEvent(mOldPointerX, mOldPointerY, eventTime); } mOldPointerCount = pointerCount; return true; } else { if (pointerCount == 1) { - mPointerTracker.onModifiedTouchEvent(action, touchX, touchY, eventTime); + tracker.onModifiedTouchEvent(action, touchX, touchY, eventTime); mOldPointerX = touchX; mOldPointerY = touchY; return true; diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java index 0c35ea966..185fca40c 100644 --- a/java/src/com/android/inputmethod/latin/PointerTracker.java +++ b/java/src/com/android/inputmethod/latin/PointerTracker.java @@ -76,7 +76,7 @@ public class PointerTracker { private final StringBuilder mPreviewLabel = new StringBuilder(1); // pressed key - private int mPreviousKey; + private int mPreviousKey = NOT_A_KEY; public PointerTracker(UIHandler handler, ProximityKeyDetector keyDetector, UIProxy proxy) { if (proxy == null || handler == null || keyDetector == null) From 31adfa78e2edae188edb05e869f9f68798857582 Mon Sep 17 00:00:00 2001 From: satok Date: Wed, 1 Sep 2010 15:45:20 +0900 Subject: [PATCH 25/58] Add a new theme for Gingerbread bug: 2959293 Change-Id: I8aef19a7485ffd5639a177aee21103b3a1e04cf2 --- .../drawable/btn_keyboard_key_gingerbread.xml | 36 ++++++++++++++ java/res/layout/input_gingerbread.xml | 33 +++++++++++++ java/res/layout/input_gingerbread_popup.xml | 48 +++++++++++++++++++ java/res/values/colors.xml | 6 +-- java/res/values/strings.xml | 8 +++- java/res/xml/prefs.xml | 2 +- .../inputmethod/latin/KeyboardSwitcher.java | 6 +-- 7 files changed, 130 insertions(+), 9 deletions(-) create mode 100644 java/res/drawable/btn_keyboard_key_gingerbread.xml create mode 100755 java/res/layout/input_gingerbread.xml create mode 100755 java/res/layout/input_gingerbread_popup.xml diff --git a/java/res/drawable/btn_keyboard_key_gingerbread.xml b/java/res/drawable/btn_keyboard_key_gingerbread.xml new file mode 100644 index 000000000..24a547974 --- /dev/null +++ b/java/res/drawable/btn_keyboard_key_gingerbread.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + diff --git a/java/res/layout/input_gingerbread.xml b/java/res/layout/input_gingerbread.xml new file mode 100755 index 000000000..8f59cae21 --- /dev/null +++ b/java/res/layout/input_gingerbread.xml @@ -0,0 +1,33 @@ + + + + diff --git a/java/res/layout/input_gingerbread_popup.xml b/java/res/layout/input_gingerbread_popup.xml new file mode 100755 index 000000000..0f0f080b5 --- /dev/null +++ b/java/res/layout/input_gingerbread_popup.xml @@ -0,0 +1,48 @@ + + + + + + + diff --git a/java/res/values/colors.xml b/java/res/values/colors.xml index 343a9405d..5ca96241e 100644 --- a/java/res/values/colors.xml +++ b/java/res/values/colors.xml @@ -18,9 +18,9 @@ */ --> - #FF000000 - #FFE35900 - #ff808080 + #FFFFFFFF + #FFF07020 + #ffB05010 #00000000 #80000000 #80FFFFFF diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml index ef5127e9d..09521146f 100644 --- a/java/res/values/strings.xml +++ b/java/res/values/strings.xml @@ -337,17 +337,20 @@ Help improve this input method editor by automatically sending usage statistics and crash reports to Google. + Keyboard Theme Basic Basic (High Contrast) - Default (bold) - Default (normal) + Stone (bold) + Stone (normal) + Gingerbread @string/layout_basic @string/layout_high_contrast @string/layout_stone_normal @string/layout_stone_bold + @string/layout_gingerbread @@ -355,6 +358,7 @@ 1 2 3 + 4 keyboard diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml index c4ffeefce..a3c956e71 100644 --- a/java/res/xml/prefs.xml +++ b/java/res/xml/prefs.xml @@ -67,7 +67,7 @@ android:persistent="true" android:entryValues="@array/keyboard_layout_modes_values" android:entries="@array/keyboard_layout_modes" - android:defaultValue="3" + android:defaultValue="4" /> Date: Wed, 1 Sep 2010 16:26:08 +0900 Subject: [PATCH 26/58] Remove duplicated assets Change-Id: I4f8abf917ff9dfa3c5d31e441476e032fb4ce3a9 --- .../drawable/sym_keyboard_feedback_settings.png | Bin 729 -> 0 bytes java/res/drawable/sym_keyboard_settings.png | Bin 1459 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 java/res/drawable/sym_keyboard_feedback_settings.png delete mode 100644 java/res/drawable/sym_keyboard_settings.png diff --git a/java/res/drawable/sym_keyboard_feedback_settings.png b/java/res/drawable/sym_keyboard_feedback_settings.png deleted file mode 100644 index 08ba18f28db90ae647f03e5ee4111cc29a2ebb27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 729 zcmV;~0w(>5P)9K*yjX)QcaWw?E#+Y%5}#Bmpr4T2-D4MYt#Q!N3GcfV#1t)-0^kJt!t^qQ6x@ zQ=l5C4BEoJy100r(L5Jp_oe<=vp|!KlPI8HML|`|*e4y7AD~0a0%F&F()ek{1}2*U z61#pTjL&K2>=NTI@ict{2`3JN)(wV>pg|%nEP@^lb2mV<7#u91Ao{|y;dF$Pb~2(_ zL|BP9tqaUuR-h@uNKt`_;*PTjDo(UZ`hOf9*<>%p0oo=E3`>ipFxRMK#OaPmQG z{ zUbE#5Yy)@$(3J<-#}){CYaF12W#_UZhVZVF!5X%VnO=TXkA%Ghx0dAzBZthJ;GpHT zp86@Sqm~>~!V=S=0SV%3da~G<&;e1G{2Woy-`g!lTm?fojD8lh%sT)L`Mu;vu>{mx ztTNhe=z^AH9K9dabXnf-B|m9#POffDC8v?kpcwj8qcB+RMA43NL-+?jHn<IWgOrAn0jihbLydm zce*tpgHci7rGaL?}ck zBq6!WMRy0^7=ZhLNWcWF18czj@@x}u$@6t@fT+>wbpMG^A`k;a3rs?02{;6p{RsgM zaQb7v32|XPaKvmjKU!T~eJVRUJHu+VCQVFCT*=GJYciQk@pE%?ZGS?pLB__$uC}za z{Ni%CuHd@`(Uvn1p+FJ_qyQ&@CxGmMfr0P5J7jTj@$dHb_OAv92fz3FNoHo|oA~B& zeg`}WBy&z$(FcFgYmkW$GPa6}igS=Gj-Q;IoZdMoCMM=^Sy|cnf`Wp=ozFKnH#efA zqm48(Ht{yb>YL#{L5lQl}V|!I+HUYc47( zdR~h)=66?BRej=cIA)=x$TN}<#XcG+_lH!*;3naS65fJ zn7{^{0M1^8sEuEOP@5R{jA-eY0Z=#tXJ3kwT>A@tv;j{%Pe zAuI3{7wqrv{{~LIsr2pe@bKl1j*hOTrluB*KLb3d72=QCY_>A`0yU$g9Xe@3Lc)2O zjHw_8V1yOOJ;OW)x#`04^0GrsTTBi)5_G_ zgkXQCVk4B8XpzLZj)?j#5DP@!4e5)*EEY?=(ij8e_53@#ND{y`M)c%jf;zmMW{2B4~>tHU&DP1NUivfLtS&!*4BQC z#TY>`4Gj(Fj7H-@r8#9SmtdE$B|XWqp|x`f=hHwIch826J7o>~7Q#%=q{#Qh#l=-> zC4|DYq;5v5nSMJLG3TgFaswirAQw%S1W2`?B?*=vrUuqJEwkQ)hzlIm^2G$;>Bh#! zkF|0PHN_Gml{;UGEL)X)YN)TT?`y4+K|#O$xm5i`ttQ_fS~?2*eikU-tgf!E&CJYP zrzQ}>dbF%jFyo0Zh}L&d@^nf{$_3og&)5>XwZ_N$dLfno?>-A#Va_dn7{AwKw%r$1 zR#v_jNcF)8!(SYkzLpeBPi+*_<&u<^bM93*hmgsYuGA3hQBb&$%3`y{%6z9}*e{8h zvV=^S+JD(zG?gUwE@a!O)}E;Skw_C(C{10G@ApTI&|d#z>3k2!)m&0il3H3?dL}I` z?KmoSRBUYQVbss Date: Wed, 1 Sep 2010 16:36:30 +0900 Subject: [PATCH 27/58] Remove old unused delete key assets Change-Id: Id50b0f3069b37e6751a4cfbd374c22c13fb0f505 --- .../res/drawable-en-hdpi/sym_keyboard_delete.png | Bin 2315 -> 0 bytes .../res/drawable-en-mdpi/sym_keyboard_delete.png | Bin 1366 -> 0 bytes .../sym_keyboard_feedback_delete.png | Bin 524 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100755 java/res/drawable-en-hdpi/sym_keyboard_delete.png delete mode 100644 java/res/drawable-en-mdpi/sym_keyboard_delete.png delete mode 100644 java/res/drawable-en-mdpi/sym_keyboard_feedback_delete.png diff --git a/java/res/drawable-en-hdpi/sym_keyboard_delete.png b/java/res/drawable-en-hdpi/sym_keyboard_delete.png deleted file mode 100755 index 569369e79927ae1eb3ca3728fc567c1f5586070b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2315 zcmV+m3H0`fP)TNc zm^N)%WLsOC0vpT9$~4*8*~M3{UM+*$2Oy0ER=IZV+K`x-n76U7!C(+OIXUTETwJsb z4Go1WR;)OWzx}g*l z6y%K^J9Yu|83!^1>pgq+d}TCK%FD}7!}HM~V?ski<5)Y6jqjj$*)(UVjfCUe+S;mQ z4Lf)4yb>H7JS;3M%pWEgo|BU^V#<^$YoHIVhN7jVWf1GTZQHiYJ9qB<gLkk-adr&p|PExhumznF=+FAu=*D z8mgg09=sZfY0{1ytG-;i?{yHVR7C$OXp*Y;Xe?J?lEPDhB{RK?KsaMaK zK|iw@qK_uB-G|ij-HQDUL3H_&Q7!^LvnI*7%(FGB?oZSIpn0RRx_RSiE@gF9foy@3ZX3$OCq+Ge18c z$sin~36Q~-B9D9b?p=oGV?n(5$b&CUO-<-Nyoq7$8hN0;w-go@;-tDkZR8LsbfEvr z%gei4R8({i+Utn^afMrM-MaP1>C>lwVzDCbAh4#kxw*N7$fFwwMU#<{u@iRD1s%FX zBGD@pigw5-s;H0NDmD|Q0F;_M%c-;I-i0&#PAs z(Z*b$Ti*j+bhRP*lLyVY=8$pz8RX2m{$LUtMl zIAT;PRSpnBtMLUFAgFu_%Z4&@dJ2aXz<5w`*P$3+Vp+0e$pHvly; zH#heiaK<6{;PU0m>hFMb!u>lfO zCE2*hRvTlWMwkJW7aJS<9b9UNlDh?ymJ+$hxkDOe^lV%O(K{oB4l_OrZP&e|q(mu* zC&jiVnood&ls}b$%FfQt1yEbyvJ?bU{7O)PYLFVZuAu{+W*lS3jvX-{RV(|f`l2e z7uyXpW8f}$Y~8x`Q;7a`_`3@iE?k7RSdc)FkU4Yatgfr8tH)!24_tkg$G22SyTW$fH+K5VfnIJ%(aDxjEzIfQ>$L=FE@0(VsngHW%7I3<(KI zsjaPj$l4M7h7B8*Q~F~UU?xx?^UQ#XwFHU-CZS1&LY#Pp2M5V!NmW%ZED#+CN# zah#demXb=$Jap(#8e5_I`uayvQBiBi4hFNR{uwrg{rn+g{#Za1dVc3JGc)lRA&S&i zW-nD_UsFbbyb0>_8yl>;y86M)nKKiieIf&A0ayL{|69C{xa6O6amnEpE5y6KKAKn-Ph5Vzk7aQ{e5{vIIV0^rYs~nY; zm34^?URYRoQ!baki<6@r@TAFlQ0+x38%Q#N+D4He5I>M0atYovhKE3~E!4-yC#kQ% z`V!q6xPwdlsPHXB^-`e!$f;AO212yI1;V5&`}glxgE~DHr0OC;Z4}hzo*R2v+~M%f z8GJTv@oT4*iKd)ZJQ@I9d6|hOuiRwZL>!M z&vUMbpH|%{&{g!~mz!suQnk_1Im`ES{dKO$pA|ZD;n0itGmMdvQ5|cO*QE^n lmudjm0I&gIHkJPb7yynfmsOamWq<$x002ovPDHLkV1iL0O0WO` diff --git a/java/res/drawable-en-mdpi/sym_keyboard_delete.png b/java/res/drawable-en-mdpi/sym_keyboard_delete.png deleted file mode 100644 index f1f7c58cf5ca0a65a98cb5cde80164e4e3848bc0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1366 zcmV-c1*!UpP)&&$;i2Zns-FOidvivZmUv zQxrwd4;!vvnOy2(2wr{i=Dhpl=JwSEIvG_EgUJ955C_DwOfNPACcw$M1R$2@SOE)< zQ}C~y;f%^d{KB}Bl9I=Zii*x#ES6ZMQt51JYWf!XKX~yYU0q!-n@pxS>Pt>ezF$*Q z^9@ZN9UVQtxVX61($cbo$E{Ed^0+P#(A2=m_V)Jo++J;adwa8?q2X=xJp&ZGeHwJ< zfage_nVI<%@@X{b9tE(H<>-8VOQ}*WO=Ic2!Kt784U=U0YkbJ2*J_RYF3-(aOror=Wh2`m(dL^;!W8zg%O?k8^~!5gROd1-0M$cqb8Q&T^bmX>}E(ZHVf%z=TFeaC^jJk~1D ziS)=MjYhLeLQYOjT3cJ&xw5jd;`R0QA15a#e}bAkBBZ9KCf3*2pG5!D>;ccBDJdzs z#>U38eSLk!czhtJ6GF(cG^F*rat7IKHp{}o!gmD)1((Q1pwLg2ruZGhPlEm9kkOJ-f0}q5u>P|yX?VxTz>4K8YJ(Aj^ojZ ziHRDuTAjpc9Co95E|*K8QmGvA@$sg@!onNuMZ4di_E*Dz$AFjS=jUhL2iz#=X|ujT zt=h*k#2rt}&COlU%gf6*8jW{aTU)=-YPA;HB{8rhNgBJ|PGd#rc2Qg%@Pd-`^diuO z9k5Z+#W?NG&Q20a&IM4!ai#!uz_j<{nTs&yd)f_*F=k|BT%!~Rh-b1mwM(k1s&4f3 z^xTB}CQt#qQBhIRGB7YO0{JpImn0ZY%&Uu9;Nxho`tqPgUYG9RJ(+o<{J zkBA>4IWm!t;>^&{(4g#@>FH^MER#OkBMT>}J+x3=U42zH0N31G&^2~+bbKl6q7CYB z)1K1#wcg&|&$_$2KZpDlK!#r{FE4NF@9+O4lC=N3+Itn(J;aEs#y^OWh>k98M2bv| z0?G;zqeR3A($uidPPa^d#EA7?q01aa#(%DK$kz_KYTh9^KR^HdgD$T8U1!^qx_*vq z&u0*SnLhMyTtBeBJ)HZHi+3UMEm3&@e^9vj3s&;?C94Yd@$dELf%L!pJLb?C^p^kw Y0Fy#=sqh&+d;kCd07*qoM6N<$f~8NZ4*&oF diff --git a/java/res/drawable-en-mdpi/sym_keyboard_feedback_delete.png b/java/res/drawable-en-mdpi/sym_keyboard_feedback_delete.png deleted file mode 100644 index 3c9083972d92e50a87efcaafe02814b36dcd7238..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 524 zcmV+n0`vWeP)tf>{p;YxrPXYgUdH2pXo2F^ErFhwGEE1ta z=>HL7jFo^%K@X@cV+2~Izs0uF_PxCa`2p|+I04>Z@mJWx&W17a*+0a_I0p#vuf#*E zwDs6ln8uJbTI?@v-wXASRDq@-7wJTlAq(##J(y8KBAv?nWo<$udB1?{hgHiSQjwvt zMSL$^_C5*;e|*625mWOCY79CL$tr{XhV-8lZ#A0vUR5U10cy(_T9vJ)Ut4i3-G}}f zA?CQ(6i?d6{{HajBUYO zxr)%S9NYQK{CdtqsxqU4GV*X86#|v!Ia-;Ur;(|u>M_ABa~~9nB{R1@aEE!?l;w!n zd(oA&{lqL-pgN%{aYdP%M^R`~7E6i~0zQ>GODKd?u8gk?p6X%&NCUXz7xl2qi*^&~L|GfB^ve-=TlpZrCjV O0000 Date: Wed, 1 Sep 2010 17:34:30 +0900 Subject: [PATCH 28/58] Fix new theme assets and resources - Add a layout for popup for new theme - Change the color of language bar - Fix a drawable for settings feedback Change-Id: I7c0c9e238c8223554a62f7b0c8092d074cf9743f --- .../sym_keyboard_feedback_settings.png | Bin 729 -> 2601 bytes java/res/layout/keyboard_popup_keyboard.xml | 1 + java/res/values/colors.xml | 6 +++--- .../inputmethod/latin/LatinKeyboard.java | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) mode change 100644 => 100755 java/res/drawable-hdpi/sym_keyboard_feedback_settings.png diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_settings.png b/java/res/drawable-hdpi/sym_keyboard_feedback_settings.png old mode 100644 new mode 100755 index 08ba18f28db90ae647f03e5ee4111cc29a2ebb27..7dee8984f5f4e616aa23d96cba581e63ff599d58 GIT binary patch literal 2601 zcmbVOX;c&E8XiOjGGdAd3VQ1ENx;;6f2aL=jv&D0uG=Pk-F^oSAQ#=Y8Jw`_5!XEDUzE zpJ@*OfMaNgK!S}B_6Tfo*t@Re*9dHwfeNK)B%(wOG93)?6i6%#hN@*NURT`P-(b?{)*oSpi03de8mt$ zVl5wzQ-!S3!I7&LM#)zt$o&+Ac>$omk%JMaVN?bh)rlHC$H*nTekCks&IXLiMGvI5a8;g1|8$VAgaB zB}XC&8dX z`lu8wOqRfUBuOX7>Y?-;SH^Pp&xS^Um^YkooeC?8EKz{Slhm*V4Ha++*cXyQrQigK zSab%H#il}3h{>i<{8&5&pU;4VLY9cmVhhGOKBmhOu_!c1MC0)&d-QxGL0M_x2wYJj_FeWQJ2Hl!7>!lMIlJycn3tpAt<7cL$n}2k`9Vx za+PLuJzAdk(F$OlDj8OYbch;!mtT(RBlbliCQry@Fd+U|+!V-9NQLMO5nI5d2Qdg^ zx{CiNXJpJ7@@RAXPqU0~VI4R+{m}Z@;=|#AHQ0&KVMhbkz>5O_Tui8d7iGNB_ix7# z#o}q2ww0|j238nc)zPz-8LI2!|M*21DM{bqLJj$eXd5JTnEG9MF7Y#}8JaqoRx@Q$ zbYwJ-Vwt)q*P&^O*_~dJL}grU8}Lrr-Ry1Xq`cg1xZQMzSZSU0!$6h3f8^1Z&v*BC z9Bx#WanT*ZgFpn}155+#0UOhVb9uTQR<17#fyY!+H+R3}XvZhKnV!1>NV&Kz@gZhZ zo&Dxf_-)7h>7j;D-~6>LjLBvC1kH(?F@XoE)xURjb(LEzmTgCl9Fgu>I9*1c`OU!u z<M`qoV38v(eWEMSJyuGEg*WPqT=Sz&``44yB?GM(&2VEE5E9$Ds2eI zJmDz6(v_Nd+J9Eip`4r?uRMnsEFgZ-wR!t6nRKo)+4f{_Z*O?J(~zynsrwZ%?L2nX zAe$e4!EU*B?V886v-$aVzAbeem}m;FyKrGmZg=34B}=%jE9Cp?wrX9%V(maK_qB8B zvu6`cAiKD@7^ghmnY3Y*+OU>ZmU|Hf_ zH2J;_SO`w5jsO1VCbL<5^>z3buiOBB{IX8|@;rUu}An z9UQxydFa4_1O3K(jm^zx&C)_5Q23aa8oQP95~yKPbGQA`)6)Z4TesMWt5CTe#VY@R5QNLum}eOAuBQpddH1eKSUr<(KHc2#{E zZZ%O2RGq78BH2b|W;wOCwXG37e~{8^TB}sv!&8kFRiNt6&xbdD4&(M6u#Au%7+RaW z+-&}H*gQ?1-`sxWPC)T=;$;ma^nks@q`7lbi%y?D?P4F+TrbV<3~)k@{VQ(EslUpt zoCY0o3e15^lY6Su+cy)U<_v$CPGt^dMveFxB-wtD~#A3C1tIekaWW$WSf zbXweHF^I4=f10K1*RLN`?Cc4fuR2~-^fqWAZPU|r_cFMf>B;50!hZbZY=$_e4D^$i zdNyjm%6oCF(p=eo;e5$YWf|nzKkV8yoSkZH+7oHVZE=lmOKwc}i@9f)^j!MI%$UrR zYoBFy9xZ8det7ifTK1h+R{^X0F&*>Wo-}g5-gI7cNADis+ zx;*7ZN}|+d@JeO#sTb*<4#%f>d`I&z%nGgzZdG3QdP=`7>AEwbve<-m=>j(H12Wd7*STc~iMpfG58`rj7=LLdMD delta 704 zcmV;x0zdt!6xjtKiBL{Q4GJ0x0000DNk~Le0000a0000p2nGNE0RPjfyOAL$e*$|+ zL_t(|+U%JBN5erF$M-2B#uzcih=}N?F-DY#5hEfZ`Y9s%DM~~{MD$PebHBtAV=1Cv z#wbgaWt3)=7*W=9dCGO&J@y2jqYpkOTTl zK%VFQ2*f9b{{YkhN`ca#IA{;Fe*|g=U4YI&$DkwBiyxr3KiAxCmoa@phL?7V%L4r_-V!lCYu2gyM88&&uQlD65}uNG<^dJCk}(we+`C%p0oo=E3`>ipFxRMK#OaPmH%$K!vKo8$=!!T9+b`DU*Fu7amA2A?K zq<)WK%mZE6==WVzj{1i1pAtH=&8agSr(Uz=4QvB=1JIQR*~bm@jZcHVo zk diff --git a/java/res/values/colors.xml b/java/res/values/colors.xml index 5ca96241e..245648df2 100644 --- a/java/res/values/colors.xml +++ b/java/res/values/colors.xml @@ -20,13 +20,13 @@ #FFFFFFFF #FFF07020 - #ffB05010 + #ffD06015 #00000000 #80000000 #80FFFFFF - #FF808080 + #FFC0C0C0 #A0000000 - #FF000000 + #FFFFFFFF #FFFFFFFF #FF000000 diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboard.java b/java/src/com/android/inputmethod/latin/LatinKeyboard.java index c35a1b05a..15e22f318 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboard.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboard.java @@ -732,7 +732,7 @@ public class LatinKeyboard extends Keyboard { public void draw(Canvas canvas) { canvas.save(); if (mHitThreshold) { - mTextPaint.setColor(mRes.getColor(R.color.latinkeyboard_text_color)); + mTextPaint.setColor(mRes.getColor(R.color.latinkeyboard_feedback_language_text)); canvas.clipRect(0, 0, mWidth, mHeight); if (mCurrentLanguage == null) { mCurrentLanguage = getInputLanguage(mWidth, mTextPaint); From 40ac45ebdcd71940394dda00371d4847f7db0f26 Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Wed, 1 Sep 2010 17:54:12 +0900 Subject: [PATCH 29/58] Get rid of arrows in candidate view bug: 2959293 Change-Id: Ia5dcb29397f608846f865fabb3c696866b3687aa --- .../ic_suggest_strip_scroll_left_arrow.png | Bin 619 -> 0 bytes .../ic_suggest_strip_scroll_right_arrow.png | Bin 619 -> 0 bytes .../keyboard_suggest_strip_divider.png | Bin 172 -> 0 bytes .../keyboard_suggest_strip_divider.png | Bin 166 -> 0 bytes .../ic_suggest_strip_scroll_left_arrow.png | Bin 445 -> 0 bytes .../ic_suggest_strip_scroll_right_arrow.png | Bin 440 -> 0 bytes java/res/layout/candidates.xml | 47 +--------- .../latin/CandidateViewContainer.java | 83 ------------------ .../android/inputmethod/latin/LatinIME.java | 6 +- 9 files changed, 5 insertions(+), 131 deletions(-) delete mode 100755 java/res/drawable-hdpi/ic_suggest_strip_scroll_left_arrow.png delete mode 100755 java/res/drawable-hdpi/ic_suggest_strip_scroll_right_arrow.png delete mode 100755 java/res/drawable-land-hdpi/keyboard_suggest_strip_divider.png delete mode 100644 java/res/drawable-land-mdpi/keyboard_suggest_strip_divider.png delete mode 100644 java/res/drawable-mdpi/ic_suggest_strip_scroll_left_arrow.png delete mode 100644 java/res/drawable-mdpi/ic_suggest_strip_scroll_right_arrow.png delete mode 100644 java/src/com/android/inputmethod/latin/CandidateViewContainer.java diff --git a/java/res/drawable-hdpi/ic_suggest_strip_scroll_left_arrow.png b/java/res/drawable-hdpi/ic_suggest_strip_scroll_left_arrow.png deleted file mode 100755 index e375f262f875012c5893a2e2e08fa6d5ab8c9a16..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 619 zcmV-x0+juUP)-Eax-EMbt z0L1qo{s{3%AP^unn~mT*84ib=cTpmdIEUDa$z+Oz!{LcI{Fkq4vC<6U@wgWPcc}W* z<#G|X+fDG9!2bzAu2u!I6cCHWqPX!Mf?LcIi^U=fE8+@Z-aD?iphJXCrz1h2Y&M&T z&*vlPmT#id)w588%msu(Avdbs(d+f{0`_{niRd&$sh+i{8h|c)eXrGO`N3dNX}8-Z z8C#Ta% zj7HoN0|&FYMb!rmhvSv)aMseApJ;_b;T`L7 z49hNp!QjsyFyFLFNs>-x$0+}w%mEz00UW>q{{i?EU;y5403`qfvlajV002ovPDHLk FV1i%mBQ*d3 diff --git a/java/res/drawable-hdpi/ic_suggest_strip_scroll_right_arrow.png b/java/res/drawable-hdpi/ic_suggest_strip_scroll_right_arrow.png deleted file mode 100755 index d38ae7562d1c2ba5a9f7a61aad1079c71410a86d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 619 zcmV-x0+juUP)r5~hWXWWbvN;1}RH;-{TZ=4767zUGES*lXForD4 zPk`K&%Vov3U4)f02(x%RZUnB|m>U9;wGBX-&~GRdVyRS$dA;5&=7yzGsl7LVi&CJ_ zU*UGUSt5~O(P&gbHg~G3J{60_@Lol>f;fyUi^XDwW!L~J?im#dg|lA)R;v{=zZi3n z8R+x*jBFG|p)K6c=kq=5nUS|;KtUi{H3{>Y@c(EI8L&(yL-Wq%a(OzPP6N2@V<&)w zc@|uZXTq<^D#{`d2u!eut4^nLZ`F}^S!9No?IK}VL-D#;EG{7a_MOgFfUfICSnJ{U z`zdr}a0^Rry4~)4lg>tfSsdOP-jm!uK;ld8k>o7rrZ!!8-` z^E}v?0ea3H#m#A&HaO&wDT(i70T2KI5C8%A3&5uU0|4hj%<6-iXMg|z002ovPDHLk FV1le=5-R`z diff --git a/java/res/drawable-land-hdpi/keyboard_suggest_strip_divider.png b/java/res/drawable-land-hdpi/keyboard_suggest_strip_divider.png deleted file mode 100755 index 1a03c52e64df4681aacb8bf1c15cb741eaf0b568..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 172 zcmeAS@N?(olHy`uVBq!ia0vp^Oh9bO0U{@7=E?#o$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1Gex5FlAr-fhcGUd*v_5|SjDP?CpFePbVNnA^ZxREu3D-iF zP`=d)lh_{lI%*tL_gKO!(PVMfCBvaeQZN6}7hSvCk_Q_&IUGc$urFj_;$fK5SXEbR SE_V%RGJ~h9pUXO@geCwk*Ei?@ diff --git a/java/res/drawable-land-mdpi/keyboard_suggest_strip_divider.png b/java/res/drawable-land-mdpi/keyboard_suggest_strip_divider.png deleted file mode 100644 index e54c5b099431be9853118c033e6fee440e44aa61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^OhBy00U{G$-VFv)k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5XJUm?-Ln?0d^f~e|7_hKJfBb*`XD@STZt$Zdp^0}R7z7QC zJ33Z1S*_<)pAj9ID(Y6%nD%G&tkd;!!sj`ry)J!Ta$v{V2qqqeESB;(&)M-UKr&M1Kt@J}K}1A^fsv7sfti_^fuIY5gM$r#&fU+>&Mu&!puoV-&(FZg z$;t5d?_UO>q4>ifFfgzH}(jsKZuKqGXTTp0lFGSVrr&IlO_oOU84XD nqYGpiFj^vw8Zh_`00=Mu3SEkNqBo^b00000NkvXXu0mjfuG6_P diff --git a/java/res/drawable-mdpi/ic_suggest_strip_scroll_right_arrow.png b/java/res/drawable-mdpi/ic_suggest_strip_scroll_right_arrow.png deleted file mode 100644 index 639a28711cd019a6feeaf2f84b50381e5a834ae3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 440 zcmV;p0Z0CcP)To!~BSFK1Q36W9GXqT1)Jbap0yvJNF$}ZdIBscK*0?aB(P(I@szS5b1W^>{1UN4Q zpePD>o`+7S1HE1kBuN^(uDckGMzucyP9GT32FS7u{eB-II)N??!_e;n(lmwret)i& zN+pAk)@tN>F&qxxZURuW+wIPYAeyG3+wDTT-G+L-{$bnp8NyyW0Vax3co_(3wOX)V zuj4`hti%zhR;w#w?;r?*=;jPATR>M(OosTKB*}~CdC}b=o**pCW@1vmHk-}sWHO2K z&$HLO#kUHAkcr9h-+kZz{B4nb0EqW74oXp!)polbOsCW6<}Tyn - - - - - - - - - - - - - - + diff --git a/java/src/com/android/inputmethod/latin/CandidateViewContainer.java b/java/src/com/android/inputmethod/latin/CandidateViewContainer.java deleted file mode 100644 index e0cb8c3b0..000000000 --- a/java/src/com/android/inputmethod/latin/CandidateViewContainer.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2008 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.content.Context; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.view.View.OnTouchListener; -import android.widget.LinearLayout; - -public class CandidateViewContainer extends LinearLayout implements OnTouchListener { - - private View mButtonLeft; - private View mButtonRight; - private View mButtonLeftLayout; - private View mButtonRightLayout; - private CandidateView mCandidates; - - public CandidateViewContainer(Context screen, AttributeSet attrs) { - super(screen, attrs); - } - - public void initViews() { - if (mCandidates == null) { - mButtonLeftLayout = findViewById(R.id.candidate_left_parent); - mButtonLeft = findViewById(R.id.candidate_left); - if (mButtonLeft != null) { - mButtonLeft.setOnTouchListener(this); - } - mButtonRightLayout = findViewById(R.id.candidate_right_parent); - mButtonRight = findViewById(R.id.candidate_right); - if (mButtonRight != null) { - mButtonRight.setOnTouchListener(this); - } - mCandidates = (CandidateView) findViewById(R.id.candidates); - } - } - - @Override - public void requestLayout() { - if (mCandidates != null) { - int availableWidth = mCandidates.getWidth(); - int neededWidth = mCandidates.computeHorizontalScrollRange(); - int x = mCandidates.getScrollX(); - boolean leftVisible = x > 0; - boolean rightVisible = x + availableWidth < neededWidth; - if (mButtonLeftLayout != null) { - mButtonLeftLayout.setVisibility(leftVisible ? VISIBLE : GONE); - } - if (mButtonRightLayout != null) { - mButtonRightLayout.setVisibility(rightVisible ? VISIBLE : GONE); - } - } - super.requestLayout(); - } - - public boolean onTouch(View v, MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_DOWN) { - if (v == mButtonRight) { - mCandidates.scrollNext(); - } else if (v == mButtonLeft) { - mCandidates.scrollPrev(); - } - } - return false; - } - -} diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 74ed90ff6..0896f6c2c 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -61,6 +61,7 @@ import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; +import android.widget.LinearLayout; import java.io.FileDescriptor; import java.io.IOException; @@ -153,7 +154,7 @@ public class LatinIME extends InputMethodService private static final int POS_METHOD = 1; //private LatinKeyboardView mInputView; - private CandidateViewContainer mCandidateViewContainer; + private LinearLayout mCandidateViewContainer; private CandidateView mCandidateView; private Suggest mSuggest; private CompletionInfo[] mCompletions; @@ -538,9 +539,8 @@ public class LatinIME extends InputMethodService @Override public View onCreateCandidatesView() { mKeyboardSwitcher.makeKeyboards(true); - mCandidateViewContainer = (CandidateViewContainer) getLayoutInflater().inflate( + mCandidateViewContainer = (LinearLayout) getLayoutInflater().inflate( R.layout.candidates, null); - mCandidateViewContainer.initViews(); mCandidateView = (CandidateView) mCandidateViewContainer.findViewById(R.id.candidates); mCandidateView.setService(this); setCandidatesViewShown(true); From 681b102a492b7d5301c1ca87985b4c391eb5eb14 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Wed, 1 Sep 2010 16:36:24 +0900 Subject: [PATCH 30/58] Track all pointers events Bug: 2910379 Change-Id: I179ae4359afb57c351d5fcc5f5453c30d3ef0c01 --- .../android/inputmethod/latin/LatinIME.java | 21 +++---- .../latin/LatinKeyboardBaseView.java | 62 ++++++++----------- .../inputmethod/latin/PointerTracker.java | 18 ------ 3 files changed, 33 insertions(+), 68 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 0896f6c2c..9312ce2c8 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -965,6 +965,7 @@ public class LatinIME extends InputMethodService private void postUpdateShiftKeyState() { mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE); + // TODO: Should remove this 300ms delay? mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_UPDATE_SHIFT_STATE), 300); } @@ -1090,7 +1091,7 @@ public class LatinIME extends InputMethodService LatinImeLogger.logOnDelete(); break; case Keyboard.KEYCODE_SHIFT: - handleShift(); + // Shift key is handled in onPress(). break; case Keyboard.KEYCODE_CANCEL: if (mOptionsDialog == null || !mOptionsDialog.isShowing()) { @@ -1107,6 +1108,7 @@ public class LatinIME extends InputMethodService toggleLanguage(false, false); break; case Keyboard.KEYCODE_MODE_CHANGE: + // TODO: Mode change (symbol key) should be handled in onPress(). changeKeyboardMode(); break; case LatinKeyboardView.KEYCODE_VOICE: @@ -1248,19 +1250,6 @@ public class LatinIME extends InputMethodService } } - private void handleCapsLock() { - mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE); - KeyboardSwitcher switcher = mKeyboardSwitcher; - if (switcher.isAlphabetMode()) { - mCapsLock = !mCapsLock; - if (mCapsLock) { - switcher.setShiftLocked(true); - } else { - switcher.setShifted(false); - } - } - } - private void abortCorrection(boolean force) { if (force || TextEntryState.isCorrecting()) { getCurrentInputConnection().finishComposingText(); @@ -2157,6 +2146,10 @@ public class LatinIME extends InputMethodService public void onPress(int primaryCode) { vibrate(); playKeyClick(primaryCode); + if (primaryCode == Keyboard.KEYCODE_SHIFT) { + handleShift(); + } + // TODO: We should handle KEYCODE_MODE_CHANGE (symbol) here as well. } public void onRelease(int primaryCode) { diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index 3efb16b09..d1a5cd8e4 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -204,11 +204,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, private final ProximityKeyDetector mProximityKeyDetector = new ProximityKeyDetector(); - // Variables for dealing with multiple pointers - private int mOldPointerCount = 1; - private int mOldPointerX; - private int mOldPointerY; - // Swipe gesture detector private final GestureDetector mGestureDetector; private final SwipeTracker mSwipeTracker = new SwipeTracker(); @@ -1070,17 +1065,10 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, @Override public boolean onTouchEvent(MotionEvent me) { - // Convert multi-pointer up/down events to single up/down events to - // deal with the typical multi-pointer behavior of two-thumb typing final int pointerCount = me.getPointerCount(); - final int action = me.getAction(); + final int action = me.getActionMasked(); final long eventTime = me.getEventTime(); - if (pointerCount > 1 && mOldPointerCount > 1) { - // Don't do anything when 2 or more pointers are down and moving. - return true; - } - // Track the last few movements to look for spurious swipes. mSwipeTracker.addMovement(me); @@ -1108,34 +1096,36 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, // Up event will pass through. } - // TODO: Should remove this implicit reference to id=0 pointer tracker in the future. - PointerTracker tracker = getPointerTracker(0); - int touchX = getTouchX(me.getX()); - int touchY = getTouchY(me.getY()); - if (pointerCount != mOldPointerCount) { - if (pointerCount == 1) { - // Send a down event for the latest pointer - tracker.onDownEvent(touchX, touchY, eventTime); - // If it's an up action, then deliver the up as well. - if (action == MotionEvent.ACTION_UP) { - tracker.onUpEvent(touchX, touchY, eventTime); - } - } else { - // Send an up event for the last pointer - tracker.onUpEvent(mOldPointerX, mOldPointerY, eventTime); + if (action == MotionEvent.ACTION_MOVE) { + for (int index = 0; index < pointerCount; index++) { + int touchX = getTouchX(me.getX(index)); + int touchY = getTouchY(me.getY(index)); + int id = me.getPointerId(index); + PointerTracker tracker = getPointerTracker(id); + tracker.onMoveEvent(touchX, touchY, eventTime); } - mOldPointerCount = pointerCount; - return true; } else { - if (pointerCount == 1) { - tracker.onModifiedTouchEvent(action, touchX, touchY, eventTime); - mOldPointerX = touchX; - mOldPointerY = touchY; - return true; + int index = me.getActionIndex(); + int touchX = getTouchX(me.getX(index)); + int touchY = getTouchY(me.getY(index)); + int id = me.getPointerId(index); + PointerTracker tracker = getPointerTracker(id); + switch (action) { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_POINTER_DOWN: + tracker.onDownEvent(touchX, touchY, eventTime); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_POINTER_UP: + tracker.onUpEvent(touchX, touchY, eventTime); + break; + case MotionEvent.ACTION_CANCEL: + tracker.onCancelEvent(touchX, touchY, eventTime); + break; } } - return false; + return true; } protected void swipeRight() { diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java index 185fca40c..3c67ebece 100644 --- a/java/src/com/android/inputmethod/latin/PointerTracker.java +++ b/java/src/com/android/inputmethod/latin/PointerTracker.java @@ -21,7 +21,6 @@ import com.android.inputmethod.latin.LatinKeyboardBaseView.UIHandler; import android.inputmethodservice.Keyboard; import android.inputmethodservice.Keyboard.Key; -import android.view.MotionEvent; import android.view.ViewConfiguration; public class PointerTracker { @@ -119,23 +118,6 @@ public class PointerTracker { } } - public void onModifiedTouchEvent(int action, int touchX, int touchY, long eventTime) { - switch (action) { - case MotionEvent.ACTION_DOWN: - onDownEvent(touchX, touchY, eventTime); - break; - case MotionEvent.ACTION_MOVE: - onMoveEvent(touchX, touchY, eventTime); - break; - case MotionEvent.ACTION_UP: - onUpEvent(touchX, touchY, eventTime); - break; - case MotionEvent.ACTION_CANCEL: - onCancelEvent(touchX, touchY, eventTime); - break; - } - } - public void onDownEvent(int touchX, int touchY, long eventTime) { int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); mCurrentKey = keyIndex; From 2085d43daf44752deae1b6b00a14cb0f517d69cb Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Wed, 1 Sep 2010 23:18:39 +0900 Subject: [PATCH 31/58] Make abstract KeyDetector class The KeyDetector abstracts key detection algorithm. The ProximityKeyDetector is one of its concrete implementations. Another one that might be called XAxisKeyDetector will follow to realize the pop-up mini-keyboard behavior described in bug#2959169. Bug: 2959169 Change-Id: Idd3fc53282e6b721ec7a4ce500af8aba21ce07a3 --- .../inputmethod/latin/KeyDetector.java | 56 +++++++++++++++++++ .../latin/LatinKeyboardBaseView.java | 23 +++----- .../inputmethod/latin/PointerTracker.java | 4 +- .../latin/ProximityKeyDetector.java | 30 +--------- 4 files changed, 70 insertions(+), 43 deletions(-) create mode 100644 java/src/com/android/inputmethod/latin/KeyDetector.java diff --git a/java/src/com/android/inputmethod/latin/KeyDetector.java b/java/src/com/android/inputmethod/latin/KeyDetector.java new file mode 100644 index 000000000..11d5f861d --- /dev/null +++ b/java/src/com/android/inputmethod/latin/KeyDetector.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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.inputmethodservice.Keyboard; +import android.inputmethodservice.Keyboard.Key; + +import java.util.List; + +abstract class KeyDetector { + protected Keyboard mKeyboard; + protected Key[] mKeys; + + protected boolean mProximityCorrectOn; + protected int mProximityThresholdSquare; + + public Key[] setKeyboard(Keyboard keyboard) { + if (keyboard == null) + throw new NullPointerException(); + mKeyboard = keyboard; + List keys = mKeyboard.getKeys(); + Key[] array = keys.toArray(new Key[keys.size()]); + mKeys = array; + return array; + } + + public void setProximityCorrectionEnabled(boolean enabled) { + mProximityCorrectOn = enabled; + } + + public boolean isProximityCorrectionEnabled() { + return mProximityCorrectOn; + } + + public void setProximityThreshold(int threshold) { + mProximityThresholdSquare = threshold * threshold; + } + + abstract public int[] newCodeArray(); + + abstract public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys); +} \ No newline at end of file diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index d1a5cd8e4..9ebab256d 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -45,7 +45,6 @@ import android.widget.TextView; import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; /** @@ -202,7 +201,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, private final ArrayList mPointerTrackers = new ArrayList(); private final float mDebounceHysteresis; - private final ProximityKeyDetector mProximityKeyDetector = new ProximityKeyDetector(); + protected KeyDetector mKeyDetector = new ProximityKeyDetector(); // Swipe gesture detector private final GestureDetector mGestureDetector; @@ -473,8 +472,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, public void setOnKeyboardActionListener(OnKeyboardActionListener listener) { mKeyboardActionListener = listener; for (PointerTracker tracker : mPointerTrackers) { - if (tracker != null) - tracker.setOnKeyboardActionListener(listener); + tracker.setOnKeyboardActionListener(listener); } } @@ -501,13 +499,10 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, mHandler.cancelKeyTimers(); mHandler.cancelPopupPreview(); mKeyboard = keyboard; - LatinImeLogger.onSetKeyboard(mKeyboard); - List keys = mKeyboard.getKeys(); - mKeys = keys.toArray(new Key[keys.size()]); - mProximityKeyDetector.setKeyboard(keyboard, mKeys); + LatinImeLogger.onSetKeyboard(keyboard); + mKeys = mKeyDetector.setKeyboard(keyboard); for (PointerTracker tracker : mPointerTrackers) { - if (tracker != null) - tracker.setKeyboard(mKeys, mDebounceHysteresis); + tracker.setKeyboard(mKeys, mDebounceHysteresis); } requestLayout(); // Hint to reallocate the buffer if the size changed @@ -599,14 +594,14 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, * @param enabled whether or not the proximity correction is enabled */ public void setProximityCorrectionEnabled(boolean enabled) { - mProximityKeyDetector.setProximityCorrectionEnabled(enabled); + mKeyDetector.setProximityCorrectionEnabled(enabled); } /** * Returns true if proximity correction is enabled. */ public boolean isProximityCorrectionEnabled() { - return mProximityKeyDetector.isProximityCorrectionEnabled(); + return mKeyDetector.isProximityCorrectionEnabled(); } /** @@ -658,7 +653,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, dimensionSum += Math.min(key.width, key.height) + key.gap; } if (dimensionSum < 0 || length == 0) return; - mProximityKeyDetector.setProximityThreshold((int) (dimensionSum * 1.4f / length)); + mKeyDetector.setProximityThreshold((int) (dimensionSum * 1.4f / length)); } @Override @@ -1052,7 +1047,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, // 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(mHandler, mProximityKeyDetector, this); + new PointerTracker(mHandler, mKeyDetector, this); if (keys != null) tracker.setKeyboard(keys, mDebounceHysteresis); if (listener != null) diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java index 3c67ebece..8c85e97f9 100644 --- a/java/src/com/android/inputmethod/latin/PointerTracker.java +++ b/java/src/com/android/inputmethod/latin/PointerTracker.java @@ -45,7 +45,7 @@ public class PointerTracker { private final UIProxy mProxy; private final UIHandler mHandler; - private final ProximityKeyDetector mKeyDetector; + private final KeyDetector mKeyDetector; private OnKeyboardActionListener mListener; private Key[] mKeys; @@ -77,7 +77,7 @@ public class PointerTracker { // pressed key private int mPreviousKey = NOT_A_KEY; - public PointerTracker(UIHandler handler, ProximityKeyDetector keyDetector, UIProxy proxy) { + public PointerTracker(UIHandler handler, KeyDetector keyDetector, UIProxy proxy) { if (proxy == null || handler == null || keyDetector == null) throw new NullPointerException(); mProxy = proxy; diff --git a/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java b/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java index eae2d7f08..6ee005510 100644 --- a/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java +++ b/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java @@ -16,48 +16,24 @@ package com.android.inputmethod.latin; -import android.inputmethodservice.Keyboard; import android.inputmethodservice.Keyboard.Key; import java.util.Arrays; -class ProximityKeyDetector { +class ProximityKeyDetector extends KeyDetector { private static final int MAX_NEARBY_KEYS = 12; - private Keyboard mKeyboard; - private Key[] mKeys; - - private boolean mProximityCorrectOn; - private int mProximityThresholdSquare; - // working area private int[] mDistances = new int[MAX_NEARBY_KEYS]; - public void setKeyboard(Keyboard keyboard, Key[] keys) { - if (keyboard == null || keys == null) - throw new NullPointerException(); - mKeyboard = keyboard; - mKeys = keys; - } - - public void setProximityCorrectionEnabled(boolean enabled) { - mProximityCorrectOn = enabled; - } - - public boolean isProximityCorrectionEnabled() { - return mProximityCorrectOn; - } - - public void setProximityThreshold(int threshold) { - mProximityThresholdSquare = threshold * threshold; - } - + @Override public int[] newCodeArray() { int[] codes = new int[MAX_NEARBY_KEYS]; Arrays.fill(codes, LatinKeyboardBaseView.NOT_A_KEY); return codes; } + @Override public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys) { final Key[] keys = mKeys; if (keys == null) From c6cb2ec1f3264a7b626022bcfdc8da180b87920c Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 2 Sep 2010 01:07:11 +0900 Subject: [PATCH 32/58] Add new public attribute mPointerId to PointerTracker It is easier to track each pointer if a PointerTracker object keeps its pointer id. Bug: 2910379 Change-Id: If3e3b0cf3d834d22302598f4d85d54c9a4ce92ba --- .../com/android/inputmethod/latin/LatinKeyboardBaseView.java | 3 +-- java/src/com/android/inputmethod/latin/PointerTracker.java | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index 9ebab256d..4daf6515f 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -774,7 +774,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, if (DEBUG) { if (mShowTouchPoints) { for (PointerTracker tracker : mPointerTrackers) { - if (tracker == null) continue; int startX = tracker.getStartX(); int startY = tracker.getStartY(); int lastX = tracker.getLastX(); @@ -1047,7 +1046,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, // 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(mHandler, mKeyDetector, this); + new PointerTracker(i, mHandler, mKeyDetector, this); if (keys != null) tracker.setKeyboard(keys, mDebounceHysteresis); if (listener != null) diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java index 8c85e97f9..504c85784 100644 --- a/java/src/com/android/inputmethod/latin/PointerTracker.java +++ b/java/src/com/android/inputmethod/latin/PointerTracker.java @@ -32,6 +32,8 @@ public class PointerTracker { public boolean isMiniKeyboardOnScreen(); } + public final int mPointerId; + // Timing constants private static final int REPEAT_START_DELAY = 400; /* package */ static final int REPEAT_INTERVAL = 50; // ~20 keys per second @@ -77,9 +79,10 @@ public class PointerTracker { // pressed key private int mPreviousKey = NOT_A_KEY; - public PointerTracker(UIHandler handler, KeyDetector keyDetector, UIProxy proxy) { + public PointerTracker(int id, UIHandler handler, KeyDetector keyDetector, UIProxy proxy) { if (proxy == null || handler == null || keyDetector == null) throw new NullPointerException(); + mPointerId = id; mProxy = proxy; mHandler = handler; mKeyDetector = keyDetector; From c6df09182cac288c9a4de2cc05628dac6b6db41e Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Wed, 1 Sep 2010 17:50:24 +0900 Subject: [PATCH 33/58] Refactor PointerTracker to add isValidKeyIndex() predicate. Bug: 2910379 Change-Id: If2b28764dc777bb62949a95bc61c4a16ff152220 --- .../inputmethod/latin/PointerTracker.java | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java index 504c85784..c8976a372 100644 --- a/java/src/com/android/inputmethod/latin/PointerTracker.java +++ b/java/src/com/android/inputmethod/latin/PointerTracker.java @@ -100,21 +100,25 @@ public class PointerTracker { mKeyDebounceThresholdSquared = (int)(hysteresisPixel * hysteresisPixel); } + private boolean isValidKeyIndex(int keyIndex) { + return keyIndex >= 0 && keyIndex < mKeys.length; + } + public Key getKey(int keyIndex) { - return (keyIndex >= 0 && keyIndex < mKeys.length) ? mKeys[keyIndex] : null; + return isValidKeyIndex(keyIndex) ? mKeys[keyIndex] : null; } public void updateKey(int keyIndex) { int oldKeyIndex = mPreviousKey; mPreviousKey = keyIndex; if (keyIndex != oldKeyIndex) { - if (oldKeyIndex != NOT_A_KEY && oldKeyIndex < mKeys.length) { + if (isValidKeyIndex(oldKeyIndex)) { // if new key index is not a key, old key was just released inside of the key. final boolean inside = (keyIndex == NOT_A_KEY); mKeys[oldKeyIndex].onReleased(inside); mProxy.invalidateKey(mKeys[oldKeyIndex]); } - if (keyIndex != NOT_A_KEY && keyIndex < mKeys.length) { + if (isValidKeyIndex(keyIndex)) { mKeys[keyIndex].onPressed(); mProxy.invalidateKey(mKeys[keyIndex]); } @@ -130,14 +134,14 @@ public class PointerTracker { startTimeDebouncing(eventTime); checkMultiTap(eventTime, keyIndex); if (mListener != null) { - int primaryCode = (keyIndex != NOT_A_KEY) ? mKeys[keyIndex].codes[0] : 0; + int primaryCode = isValidKeyIndex(keyIndex) ? mKeys[keyIndex].codes[0] : 0; mListener.onPress(primaryCode); } - if (keyIndex >= 0 && mKeys[keyIndex].repeatable) { - repeatKey(keyIndex); - mHandler.startKeyRepeatTimer(REPEAT_START_DELAY, keyIndex, this); - } - if (keyIndex != NOT_A_KEY) { + if (isValidKeyIndex(keyIndex)) { + if (mKeys[keyIndex].repeatable) { + repeatKey(keyIndex); + mHandler.startKeyRepeatTimer(REPEAT_START_DELAY, keyIndex, this); + } mHandler.startLongPressTimer(keyIndex, LONGPRESS_TIMEOUT); } showKeyPreviewAndUpdateKey(keyIndex); @@ -146,7 +150,7 @@ public class PointerTracker { public void onMoveEvent(int touchX, int touchY, long eventTime) { int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); - if (keyIndex != NOT_A_KEY) { + if (isValidKeyIndex(keyIndex)) { if (mCurrentKey == NOT_A_KEY) { updateTimeDebouncing(eventTime); mCurrentKey = keyIndex; @@ -195,7 +199,7 @@ public class PointerTracker { if (!wasInKeyRepeat && !mProxy.isMiniKeyboardOnScreen()) { detectAndSendKey(mCurrentKey, touchX, touchY, eventTime); } - if (keyIndex != NOT_A_KEY && keyIndex < mKeys.length) + if (isValidKeyIndex(keyIndex)) mProxy.invalidateKey(mKeys[keyIndex]); } @@ -205,15 +209,17 @@ public class PointerTracker { mProxy.dismissPopupKeyboard(); showKeyPreviewAndUpdateKey(NOT_A_KEY); int keyIndex = mCurrentKey; - if (keyIndex != NOT_A_KEY && keyIndex < mKeys.length) + if (isValidKeyIndex(keyIndex)) mProxy.invalidateKey(mKeys[keyIndex]); } public void repeatKey(int keyIndex) { - Key key = mKeys[keyIndex]; - // While key is repeating, because there is no need to handle multi-tap key, we can pass - // -1 as eventTime argument. - detectAndSendKey(keyIndex, key.x, key.y, -1); + Key key = getKey(keyIndex); + if (key != null) { + // While key is repeating, because there is no need to handle multi-tap key, we can + // pass -1 as eventTime argument. + detectAndSendKey(keyIndex, key.x, key.y, -1); + } } // These package scope methods are only for debugging purpose. @@ -253,7 +259,7 @@ public class PointerTracker { throw new IllegalStateException("keyboard and/or hysteresis not set"); if (newKey == curKey) { return true; - } else if (curKey >= 0 && curKey < mKeys.length) { + } else if (isValidKeyIndex(curKey)) { return getSquareDistanceToKeyEdge(x, y, mKeys[curKey]) < mKeyDebounceThresholdSquared; } else { @@ -303,7 +309,7 @@ public class PointerTracker { } private void detectAndSendKey(int index, int x, int y, long eventTime) { - if (index != NOT_A_KEY && index < mKeys.length) { + if (isValidKeyIndex(index)) { final Key key = mKeys[index]; OnKeyboardActionListener listener = mListener; if (key.text != null) { @@ -366,11 +372,15 @@ public class PointerTracker { } private void checkMultiTap(long eventTime, int keyIndex) { - if (keyIndex == NOT_A_KEY) return; - Key key = mKeys[keyIndex]; + Key key = getKey(keyIndex); + if (key == null) + return; + + final boolean isMultiTap = + (eventTime < mLastTapTime + MULTITAP_INTERVAL && keyIndex == mLastSentIndex); if (key.codes.length > 1) { mInMultiTap = true; - if (eventTime < mLastTapTime + MULTITAP_INTERVAL && keyIndex == mLastSentIndex) { + if (isMultiTap) { mTapCount = (mTapCount + 1) % key.codes.length; return; } else { @@ -378,7 +388,7 @@ public class PointerTracker { return; } } - if (eventTime > mLastTapTime + MULTITAP_INTERVAL || keyIndex != mLastSentIndex) { + if (!isMultiTap) { resetMultiTap(); } } From b00a1d0c0adbdfc507676772201e979e539a2801 Mon Sep 17 00:00:00 2001 From: Amith Yamasani Date: Thu, 26 Aug 2010 12:22:58 -0700 Subject: [PATCH 34/58] Correction improvements - use the new InputConnection APIs for underlining and fetching the selected text. Bug: 2950652 Some refinements to correction behavior, such as retaining the tap-to-save when in correction mode. Use reflection to access the new InputConnection APIs with fallbacks, in case we run on older OS versions. Some refactoring to separate lookup for voice alternatives and typed alternatives. Change-Id: I7c4178bf7e6b47ee274c49fa7a694f8c2d50cea7 --- .../inputmethod/latin/CandidateView.java | 5 +- .../inputmethod/latin/EditingUtil.java | 190 +++++++++--- .../android/inputmethod/latin/LatinIME.java | 271 +++++++++--------- 3 files changed, 288 insertions(+), 178 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java index 7fcc3d532..4995727da 100755 --- a/java/src/com/android/inputmethod/latin/CandidateView.java +++ b/java/src/com/android/inputmethod/latin/CandidateView.java @@ -107,7 +107,6 @@ public class CandidateView extends View { } break; } - } }; @@ -333,6 +332,10 @@ public class CandidateView extends View { requestLayout(); } + public boolean isShowingAddToDictionaryHint() { + return mShowingAddToDictionary; + } + public void showAddToDictionaryHint(CharSequence word) { ArrayList suggestions = new ArrayList(); suggestions.add(word); diff --git a/java/src/com/android/inputmethod/latin/EditingUtil.java b/java/src/com/android/inputmethod/latin/EditingUtil.java index be31cb787..781d7fd4a 100644 --- a/java/src/com/android/inputmethod/latin/EditingUtil.java +++ b/java/src/com/android/inputmethod/latin/EditingUtil.java @@ -16,10 +16,13 @@ package com.android.inputmethod.latin; +import android.text.TextUtils; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.InputConnection; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.regex.Pattern; /** @@ -31,6 +34,11 @@ public class EditingUtil { */ private static final int LOOKBACK_CHARACTER_NUM = 15; + // Cache Method pointers + private static boolean sMethodsInitialized; + private static Method sMethodGetSelectedText; + private static Method sMethodSetComposingRegion; + private EditingUtil() {}; /** @@ -65,36 +73,16 @@ public class EditingUtil { return extracted.startOffset + extracted.selectionStart; } - private static int getSelectionEnd(InputConnection connection) { - ExtractedText extracted = connection.getExtractedText( - new ExtractedTextRequest(), 0); - if (extracted == null) { - return -1; - } - return extracted.startOffset + extracted.selectionEnd; - } - /** * @param connection connection to the current text field. * @param sep characters which may separate words + * @param range the range object to store the result into * @return the word that surrounds the cursor, including up to one trailing * separator. For example, if the field contains "he|llo world", where | * represents the cursor, then "hello " will be returned. */ public static String getWordAtCursor( - InputConnection connection, String separators) { - return getWordAtCursor(connection, separators, null); - } - - /** - * @param connection connection to the current text field. - * @param sep characters which may separate words - * @return the word that surrounds the cursor, including up to one trailing - * separator. For example, if the field contains "he|llo world", where | - * represents the cursor, then "hello " will be returned. - */ - public static String getWordAtCursor( - InputConnection connection, String separators, Range range) { + InputConnection connection, String separators, Range range) { Range r = getWordRangeAtCursor(connection, separators, range); return (r == null) ? null : r.word; } @@ -204,26 +192,146 @@ public class EditingUtil { } } - /** - * Checks if the cursor is touching/inside a word or the selection is for a whole - * word and no more and no less. - * @param range the Range object that contains the bounds of the word around the cursor - * @param start the start of the selection - * @param end the end of the selection, which could be the same as the start, if text is not - * in selection mode - * @return false if the selection is a partial word or straddling multiple words, true if - * the selection is a full word or there is no selection. - */ - public static boolean isFullWordOrInside(Range range, int start, int end) { - // Is the cursor inside or touching a word? - if (start == end) return true; + public static class SelectedWord { + public int start; + public int end; + public CharSequence word; + } - // Is it a selection? Then is the start of the selection the start of the word and - // the size of the selection the size of the word? Then return true - if (start < end - && (range.charsBefore == 0 && range.charsAfter == end - start)) { - return true; + /** + * Takes a character sequence with a single character and checks if the character occurs + * in a list of word separators or is empty. + * @param singleChar A CharSequence with null, zero or one character + * @param wordSeparators A String containing the word separators + * @return true if the character is at a word boundary, false otherwise + */ + private static boolean isWordBoundary(CharSequence singleChar, String wordSeparators) { + return TextUtils.isEmpty(singleChar) || wordSeparators.contains(singleChar); + } + + /** + * Checks if the cursor is inside a word or the current selection is a whole word. + * @param ic the InputConnection for accessing the text field + * @param selStart the start position of the selection within the text field + * @param selEnd the end position of the selection within the text field. This could be + * the same as selStart, if there's no selection. + * @param wordSeparators the word separator characters for the current language + * @return an object containing the text and coordinates of the selected/touching word, + * null if the selection/cursor is not marking a whole word. + */ + public static SelectedWord getWordAtCursorOrSelection(final InputConnection ic, + int selStart, int selEnd, String wordSeparators) { + if (selStart == selEnd) { + // There is just a cursor, so get the word at the cursor + EditingUtil.Range range = new EditingUtil.Range(); + CharSequence touching = getWordAtCursor(ic, wordSeparators, range); + if (!TextUtils.isEmpty(touching)) { + SelectedWord selWord = new SelectedWord(); + selWord.word = touching; + selWord.start = selStart - range.charsBefore; + selWord.end = selEnd + range.charsAfter; + return selWord; + } + } else { + // Is the previous character empty or a word separator? If not, return null. + CharSequence charsBefore = ic.getTextBeforeCursor(1, 0); + if (!isWordBoundary(charsBefore, wordSeparators)) { + return null; + } + + // Is the next character empty or a word separator? If not, return null. + CharSequence charsAfter = ic.getTextAfterCursor(1, 0); + if (!isWordBoundary(charsAfter, wordSeparators)) { + return null; + } + + // Extract the selection alone + CharSequence touching = getSelectedText(ic, selStart, selEnd); + if (TextUtils.isEmpty(touching)) return null; + // Is any part of the selection a separator? If so, return null. + final int length = touching.length(); + for (int i = 0; i < length; i++) { + if (wordSeparators.contains(touching.subSequence(i, i + 1))) { + return null; + } + } + // Prepare the selected word + SelectedWord selWord = new SelectedWord(); + selWord.start = selStart; + selWord.end = selEnd; + selWord.word = touching; + return selWord; + } + return null; + } + + /** + * Cache method pointers for performance + */ + private static void initializeMethodsForReflection() { + try { + // These will either both exist or not, so no need for separate try/catch blocks. + // If other methods are added later, use separate try/catch blocks. + sMethodGetSelectedText = InputConnection.class.getMethod("getSelectedText", int.class); + sMethodSetComposingRegion = InputConnection.class.getMethod("setComposingRegion", + int.class, int.class); + } catch (NoSuchMethodException exc) { + // Ignore + } + sMethodsInitialized = true; + } + + /** + * Returns the selected text between the selStart and selEnd positions. + */ + private static CharSequence getSelectedText(InputConnection ic, int selStart, int selEnd) { + // Use reflection, for backward compatibility + CharSequence result = null; + if (!sMethodsInitialized) { + initializeMethodsForReflection(); + } + if (sMethodGetSelectedText != null) { + try { + result = (CharSequence) sMethodGetSelectedText.invoke(ic, 0); + return result; + } catch (InvocationTargetException exc) { + // Ignore + } catch (IllegalArgumentException e) { + // Ignore + } catch (IllegalAccessException e) { + // Ignore + } + } + // Reflection didn't work, try it the poor way, by moving the cursor to the start, + // getting the text after the cursor and moving the text back to selected mode. + // TODO: Verify that this works properly in conjunction with + // LatinIME#onUpdateSelection + ic.setSelection(selStart, selEnd); + result = ic.getTextAfterCursor(selEnd - selStart, 0); + ic.setSelection(selStart, selEnd); + return result; + } + + /** + * Tries to set the text into composition mode if there is support for it in the framework. + */ + public static void underlineWord(InputConnection ic, SelectedWord word) { + // Use reflection, for backward compatibility + // If method not found, there's nothing we can do. It still works but just wont underline + // the word. + if (!sMethodsInitialized) { + initializeMethodsForReflection(); + } + if (sMethodSetComposingRegion != null) { + try { + sMethodSetComposingRegion.invoke(ic, word.start, word.end); + } catch (InvocationTargetException exc) { + // Ignore + } catch (IllegalArgumentException e) { + // Ignore + } catch (IllegalAccessException e) { + // Ignore + } } - return false; } } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 9312ce2c8..76f774c96 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -86,7 +86,6 @@ public class LatinIME extends InputMethodService static final boolean TRACE = false; static final boolean VOICE_INSTALLED = true; static final boolean ENABLE_VOICE_BUTTON = true; - private static final boolean MODIFY_TEXT_FOR_CORRECTION = false; private static final String PREF_VIBRATE_ON = "vibrate_on"; private static final String PREF_SOUND_ON = "sound_on"; @@ -767,16 +766,21 @@ public class LatinIME extends InputMethodService mLastSelectionEnd = newSelEnd; - // Check if we should go in or out of correction mode. - if (isPredictionOn() && mJustRevertedSeparator == null - && (candidatesStart == candidatesEnd || newSelStart != oldSelStart - || TextEntryState.isCorrecting()) - && (newSelStart < newSelEnd - 1 || (!mPredicting)) - && !mVoiceInputHighlighted) { - if (isCursorTouchingWord() || mLastSelectionStart < mLastSelectionEnd) { - postUpdateOldSuggestions(); - } else { - abortCorrection(false); + // Don't look for corrections if the keyboard is not visible + if (mKeyboardSwitcher != null && mKeyboardSwitcher.getInputView() != null + && mKeyboardSwitcher.getInputView().isShown()) { + // Check if we should go in or out of correction mode. + if (isPredictionOn() + && mJustRevertedSeparator == null + && (candidatesStart == candidatesEnd || newSelStart != oldSelStart + || TextEntryState.isCorrecting()) + && (newSelStart < newSelEnd - 1 || (!mPredicting)) + && !mVoiceInputHighlighted) { + if (isCursorTouchingWord() || mLastSelectionStart < mLastSelectionEnd) { + postUpdateOldSuggestions(); + } else { + abortCorrection(false); + } } } } @@ -818,7 +822,7 @@ public class LatinIME extends InputMethodService if (mCompletionOn) { mCompletions = completions; if (completions == null) { - setSuggestions(null, false, false, false); + clearSuggestions(); return; } @@ -1253,7 +1257,7 @@ public class LatinIME extends InputMethodService private void abortCorrection(boolean force) { if (force || TextEntryState.isCorrecting()) { getCurrentInputConnection().finishComposingText(); - setSuggestions(null, false, false, false); + clearSuggestions(); } } @@ -1266,7 +1270,9 @@ public class LatinIME extends InputMethodService // Assume input length is 1. This assumption fails for smiley face insertions. mVoiceInput.incrementTextModificationInsertCount(1); } - abortCorrection(false); + if (mLastSelectionStart == mLastSelectionEnd && TextEntryState.isCorrecting()) { + abortCorrection(false); + } if (isAlphabet(primaryCode) && isPredictionOn() && !isCursorTouchingWord()) { if (!mPredicting) { @@ -1495,7 +1501,7 @@ public class LatinIME extends InputMethodService } // Clear N-best suggestions - setSuggestions(null, false, false, true); + clearSuggestions(); FieldContext context = new FieldContext( getCurrentInputConnection(), @@ -1602,13 +1608,15 @@ public class LatinIME extends InputMethodService mVoiceInputHighlighted = true; mWordToSuggestions.putAll(mVoiceResults.alternatives); + } + private void clearSuggestions() { + setSuggestions(null, false, false, false); } private void setSuggestions( List suggestions, boolean completions, - boolean typedWordValid, boolean haveMinimalSuggestion) { @@ -1652,14 +1660,14 @@ public class LatinIME extends InputMethodService } private void showSuggestions(WordComposer word) { - //long startTime = System.currentTimeMillis(); // TIME MEASUREMENT! + // long startTime = System.currentTimeMillis(); // TIME MEASUREMENT! // TODO Maybe need better way of retrieving previous word CharSequence prevWord = EditingUtil.getPreviousWord(getCurrentInputConnection(), mWordSeparators); List stringList = mSuggest.getSuggestions( - mKeyboardSwitcher.getInputView(), word, false, prevWord); - //long stopTime = System.currentTimeMillis(); // TIME MEASUREMENT! - //Log.d("LatinIME","Suggest Total Time - " + (stopTime - startTime)); + mKeyboardSwitcher.getInputView(), word, false, prevWord); + // long stopTime = System.currentTimeMillis(); // TIME MEASUREMENT! + // Log.d("LatinIME","Suggest Total Time - " + (stopTime - startTime)); int[] nextLettersFrequencies = mSuggest.getNextLettersFrequencies(); @@ -1780,18 +1788,23 @@ public class LatinIME extends InputMethodService mJustAddedAutoSpace = true; } - // Fool the state watcher so that a subsequent backspace will not do a revert, unless - // we just did a correction, in which case we need to stay in - // TextEntryState.State.PICKED_SUGGESTION state. + final boolean showingAddToDictionaryHint = index == 0 && mCorrectionMode > 0 + && !mSuggest.isValidWord(suggestion) + && !mSuggest.isValidWord(suggestion.toString().toLowerCase()); + if (!correcting) { + // Fool the state watcher so that a subsequent backspace will not do a revert, unless + // we just did a correction, in which case we need to stay in + // TextEntryState.State.PICKED_SUGGESTION state. TextEntryState.typedCharacter((char) KEYCODE_SPACE, true); setNextSuggestions(); - } else { + } else if (!showingAddToDictionaryHint) { + // If we're not showing the "Tap again to save hint", then show corrections again. // In case the cursor position doesn't change, make sure we show the suggestions again. + clearSuggestions(); postUpdateOldSuggestions(); } - if (index == 0 && mCorrectionMode > 0 && !mSuggest.isValidWord(suggestion) - && !mSuggest.isValidWord(suggestion.toString().toLowerCase())) { + if (showingAddToDictionaryHint) { mCandidateView.showAddToDictionaryHint(suggestion); } if (ic != null) { @@ -1841,16 +1854,6 @@ public class LatinIME extends InputMethodService InputConnection ic = getCurrentInputConnection(); if (ic != null) { rememberReplacedWord(suggestion); - // If text is in correction mode and we're not using composing - // text to underline, then the word at the cursor position needs - // to be removed before committing the correction - if (correcting && !MODIFY_TEXT_FOR_CORRECTION) { - if (mLastSelectionStart < mLastSelectionEnd) { - ic.setSelection(mLastSelectionStart, mLastSelectionStart); - } - EditingUtil.deleteWordAtCursor(ic, getWordSeparators()); - } - ic.commitText(suggestion, 1); } saveWordInHistory(suggestion); @@ -1864,96 +1867,108 @@ public class LatinIME extends InputMethodService updateShiftKeyState(getCurrentInputEditorInfo()); } + /** + * Tries to apply any voice alternatives for the word if this was a spoken word and + * there are voice alternatives. + * @param touching The word that the cursor is touching, with position information + * @return true if an alternative was found, false otherwise. + */ + private boolean applyVoiceAlternatives(EditingUtil.SelectedWord touching) { + // Search for result in spoken word alternatives + String selectedWord = touching.word.toString().trim(); + if (!mWordToSuggestions.containsKey(selectedWord)) { + selectedWord = selectedWord.toLowerCase(); + } + if (mWordToSuggestions.containsKey(selectedWord)) { + mShowingVoiceSuggestions = true; + List suggestions = mWordToSuggestions.get(selectedWord); + // If the first letter of touching is capitalized, make all the suggestions + // start with a capital letter. + if (Character.isUpperCase((char) touching.word.charAt(0))) { + for (int i = 0; i < suggestions.size(); i++) { + String origSugg = (String) suggestions.get(i); + String capsSugg = origSugg.toUpperCase().charAt(0) + + origSugg.subSequence(1, origSugg.length()).toString(); + suggestions.set(i, capsSugg); + } + } + setSuggestions(suggestions, false, true, true); + setCandidatesViewShown(true); + return true; + } + return false; + } + + /** + * Tries to apply any typed alternatives for the word if we have any cached alternatives, + * otherwise tries to find new corrections and completions for the word. + * @param touching The word that the cursor is touching, with position information + * @return true if an alternative was found, false otherwise. + */ + private boolean applyTypedAlternatives(EditingUtil.SelectedWord touching) { + // If we didn't find a match, search for result in typed word history + WordComposer foundWord = null; + WordAlternatives alternatives = null; + for (WordAlternatives entry : mWordHistory) { + if (TextUtils.equals(entry.getChosenWord(), touching.word)) { + if (entry instanceof TypedWordAlternatives) { + foundWord = ((TypedWordAlternatives) entry).word; + } + alternatives = entry; + break; + } + } + // If we didn't find a match, at least suggest completions + if (foundWord == null + && (mSuggest.isValidWord(touching.word) + || mSuggest.isValidWord(touching.word.toString().toLowerCase()))) { + foundWord = new WordComposer(); + for (int i = 0; i < touching.word.length(); i++) { + foundWord.add(touching.word.charAt(i), new int[] { + touching.word.charAt(i) + }); + } + foundWord.setCapitalized(Character.isUpperCase(touching.word.charAt(0))); + } + // Found a match, show suggestions + if (foundWord != null || alternatives != null) { + if (alternatives == null) { + alternatives = new TypedWordAlternatives(touching.word, foundWord); + } + showCorrections(alternatives); + if (foundWord != null) { + mWord = new WordComposer(foundWord); + } else { + mWord.reset(); + } + return true; + } + return false; + } + private void setOldSuggestions() { - // TODO: Inefficient to check if touching word and then get the touching word. Do it - // in one go. mShowingVoiceSuggestions = false; + if (mCandidateView != null && mCandidateView.isShowingAddToDictionaryHint()) { + return; + } InputConnection ic = getCurrentInputConnection(); if (ic == null) return; - ic.beginBatchEdit(); - // If there is a selection, then undo the selection first. Unfortunately this causes - // a flicker. TODO: Add getSelectionText() to InputConnection API. - if (mLastSelectionStart < mLastSelectionEnd) { - ic.setSelection(mLastSelectionStart, mLastSelectionStart); - } - if (!mPredicting && isCursorTouchingWord()) { - EditingUtil.Range range = new EditingUtil.Range(); - CharSequence touching = EditingUtil.getWordAtCursor(getCurrentInputConnection(), - mWordSeparators, range); - // If it's a selection, check if it's an entire word and no more, no less. - boolean fullword = EditingUtil.isFullWordOrInside(range, mLastSelectionStart, - mLastSelectionEnd); - if (fullword && touching != null && touching.length() > 1) { - // Strip out any trailing word separator - if (mWordSeparators.indexOf(touching.charAt(touching.length() - 1)) > 0) { - touching = touching.toString().substring(0, touching.length() - 1); + if (!mPredicting) { + // Extract the selected or touching text + EditingUtil.SelectedWord touching = EditingUtil.getWordAtCursorOrSelection(ic, + mLastSelectionStart, mLastSelectionEnd, mWordSeparators); + + if (touching != null && touching.word.length() > 1) { + ic.beginBatchEdit(); + + if (!applyVoiceAlternatives(touching) && !applyTypedAlternatives(touching)) { + abortCorrection(true); + } else { + TextEntryState.selectedForCorrection(); + EditingUtil.underlineWord(ic, touching); } - // Search for result in spoken word alternatives - String selectedWord = touching.toString().trim(); - if (!mWordToSuggestions.containsKey(selectedWord)){ - selectedWord = selectedWord.toLowerCase(); - } - if (mWordToSuggestions.containsKey(selectedWord)){ - mShowingVoiceSuggestions = true; - underlineWord(touching, range.charsBefore, range.charsAfter); - List suggestions = mWordToSuggestions.get(selectedWord); - // If the first letter of touching is capitalized, make all the suggestions - // start with a capital letter. - if (Character.isUpperCase((char) touching.charAt(0))) { - for (int i=0; i< suggestions.size(); i++) { - String origSugg = (String) suggestions.get(i); - String capsSugg = origSugg.toUpperCase().charAt(0) - + origSugg.subSequence(1, origSugg.length()).toString(); - suggestions.set(i,capsSugg); - } - } - setSuggestions(suggestions, false, true, true); - setCandidatesViewShown(true); - TextEntryState.selectedForCorrection(); - ic.endBatchEdit(); - return; - } - - // If we didn't find a match, search for result in typed word history - WordComposer foundWord = null; - WordAlternatives alternatives = null; - for (WordAlternatives entry : mWordHistory) { - if (TextUtils.equals(entry.getChosenWord(), touching)) { - if (entry instanceof TypedWordAlternatives) { - foundWord = ((TypedWordAlternatives)entry).word; - } - alternatives = entry; - break; - } - } - // If we didn't find a match, at least suggest completions - if (foundWord == null && mSuggest.isValidWord(touching)) { - foundWord = new WordComposer(); - for (int i = 0; i < touching.length(); i++) { - foundWord.add(touching.charAt(i), new int[] { touching.charAt(i) }); - } - } - // Found a match, show suggestions - if (foundWord != null || alternatives != null) { - underlineWord(touching, range.charsBefore, range.charsAfter); - TextEntryState.selectedForCorrection(); - if (alternatives == null) alternatives = new TypedWordAlternatives(touching, - foundWord); - showCorrections(alternatives); - if (foundWord != null) { - mWord = new WordComposer(foundWord); - } else { - mWord.reset(); - } - // Revert the selection - if (mLastSelectionStart < mLastSelectionEnd) { - ic.setSelection(mLastSelectionStart, mLastSelectionEnd); - } - ic.endBatchEdit(); - return; - } - abortCorrection(true); + ic.endBatchEdit(); } else { abortCorrection(true); setNextSuggestions(); @@ -1961,28 +1976,12 @@ public class LatinIME extends InputMethodService } else { abortCorrection(true); } - // Revert the selection - if (mLastSelectionStart < mLastSelectionEnd) { - ic.setSelection(mLastSelectionStart, mLastSelectionEnd); - } - ic.endBatchEdit(); } private void setNextSuggestions() { setSuggestions(mSuggestPuncList, false, false, false); } - private void underlineWord(CharSequence word, int left, int right) { - InputConnection ic = getCurrentInputConnection(); - if (ic == null) return; - if (MODIFY_TEXT_FOR_CORRECTION) { - ic.finishComposingText(); - ic.deleteSurroundingText(left, right); - ic.setComposingText(word, 1); - } - ic.setSelection(mLastSelectionStart, mLastSelectionStart); - } - private void addToDictionaries(CharSequence suggestion, int frequencyDelta) { checkAddToDictionary(suggestion, frequencyDelta, false); } From dd8dd9fc1b10d0457a0b4b74c1c1899ff5350601 Mon Sep 17 00:00:00 2001 From: satok Date: Wed, 1 Sep 2010 23:33:43 +0900 Subject: [PATCH 35/58] Change background color for functional keys in LatinIME Change-Id: I45f13c1fd139ce43478e5d0b2cdb62e56e9f77a8 --- .../drawable/btn_keyboard_key_gingerbread.xml | 10 +++- java/res/xml/kbd_qwerty.xml | 59 ++++++++++--------- java/res/xml/kbd_qwerty_black.xml | 1 - java/res/xml/kbd_symbols.xml | 14 ++--- java/res/xml/kbd_symbols_shift.xml | 14 ++--- .../inputmethod/latin/LatinKeyboard.java | 37 ++++++++++-- 6 files changed, 86 insertions(+), 49 deletions(-) diff --git a/java/res/drawable/btn_keyboard_key_gingerbread.xml b/java/res/drawable/btn_keyboard_key_gingerbread.xml index 24a547974..4a113a8a1 100644 --- a/java/res/drawable/btn_keyboard_key_gingerbread.xml +++ b/java/res/drawable/btn_keyboard_key_gingerbread.xml @@ -16,10 +16,16 @@ + + + + + - diff --git a/java/res/xml/kbd_qwerty.xml b/java/res/xml/kbd_qwerty.xml index 59c61e4c8..d7d1ee0d5 100755 --- a/java/res/xml/kbd_qwerty.xml +++ b/java/res/xml/kbd_qwerty.xml @@ -18,6 +18,9 @@ */ --> + + + + android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> @@ -182,23 +185,23 @@ + android:keyWidth="10%p" android:keyEdgeFlags="left" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="20%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="15%p" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="right" android:isModifier="true"/> diff --git a/java/res/xml/kbd_qwerty_black.xml b/java/res/xml/kbd_qwerty_black.xml index 076359c95..286547283 100755 --- a/java/res/xml/kbd_qwerty_black.xml +++ b/java/res/xml/kbd_qwerty_black.xml @@ -201,5 +201,4 @@ android:iconPreview="@drawable/sym_keyboard_feedback_return" android:keyWidth="15%p" android:keyEdgeFlags="right"/> - diff --git a/java/res/xml/kbd_symbols.xml b/java/res/xml/kbd_symbols.xml index 3f6b8ac85..fad3ebc10 100755 --- a/java/res/xml/kbd_symbols.xml +++ b/java/res/xml/kbd_symbols.xml @@ -118,25 +118,25 @@ /> + android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> - + android:keyWidth="10%p" android:isModifier="true"/> + + android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:isModifier="true"/> diff --git a/java/res/xml/kbd_symbols_shift.xml b/java/res/xml/kbd_symbols_shift.xml index 0ec4c713c..b0693917e 100755 --- a/java/res/xml/kbd_symbols_shift.xml +++ b/java/res/xml/kbd_symbols_shift.xml @@ -85,24 +85,24 @@ /> + android:isRepeatable="true" android:isModifier="true"/> + android:keyEdgeFlags="left" android:isModifier="true"/> - + android:keyWidth="10%p" android:isModifier="true"/> + - + android:isRepeatable="true" android:isModifier="true"/> + + android:isModifier="true"/> diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboard.java b/java/src/com/android/inputmethod/latin/LatinKeyboard.java index 15e22f318..33519e4be 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboard.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboard.java @@ -628,9 +628,20 @@ public class LatinKeyboard extends Keyboard { } class LatinKey extends Keyboard.Key { - + + // functional normal state (with properties) + private final int[] KEY_STATE_FUNCTIONAL_NORMAL = { + android.R.attr.state_single + }; + + // functional pressed state (with properties) + private final int[] KEY_STATE_FUNCTIONAL_PRESSED = { + android.R.attr.state_single, + android.R.attr.state_pressed + }; + private boolean mShiftLockEnabled; - + public LatinKey(Resources res, Keyboard.Row parent, int x, int y, XmlResourceParser parser) { super(res, parent, x, y, parser); @@ -639,11 +650,17 @@ public class LatinKeyboard extends Keyboard { popupResId = 0; } } - - void enableShiftLock() { + + private void enableShiftLock() { mShiftLockEnabled = true; } + // sticky is used for shift key. If a key is not sticky and is modifier, + // the key will be treated as functional. + private boolean isFunctionalKey() { + return !sticky && modifier; + } + @Override public void onReleased(boolean inside) { if (!mShiftLockEnabled) { @@ -665,6 +682,18 @@ public class LatinKeyboard extends Keyboard { boolean isInsideSuper(int x, int y) { return super.isInside(x, y); } + + @Override + public int[] getCurrentDrawableState() { + if (isFunctionalKey()) { + if (pressed) { + return KEY_STATE_FUNCTIONAL_PRESSED; + } else { + return KEY_STATE_FUNCTIONAL_NORMAL; + } + } + return super.getCurrentDrawableState(); + } } /** From a327485e595c9f7676989097c830ff452085d4c9 Mon Sep 17 00:00:00 2001 From: satok Date: Thu, 2 Sep 2010 13:48:48 +0900 Subject: [PATCH 36/58] Change the preference name for a theme and remove a preference settings Change-Id: I5ad980559477775eb44df022e54ce5ef32398601 --- java/res/xml/prefs.xml | 4 ++-- java/src/com/android/inputmethod/latin/KeyboardSwitcher.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml index a3c956e71..b4d2d903d 100644 --- a/java/res/xml/prefs.xml +++ b/java/res/xml/prefs.xml @@ -61,14 +61,14 @@ android:defaultValue="@string/voice_mode_main" /> - + />--> Date: Thu, 2 Sep 2010 12:57:07 +0900 Subject: [PATCH 37/58] Add modifiers to functional keys - update assets for language switcher Change-Id: I8f29d3d38fb73ab5673f9e58cf28ed37cc8b4004 --- .../res/drawable-hdpi/sym_bkeyboard_globe.png | Bin 2136 -> 0 bytes java/res/drawable-hdpi/sym_keyboard_globe.png | Bin 2093 -> 0 bytes .../sym_keyboard_language_arrows_left.png | Bin 314 -> 1253 bytes .../sym_keyboard_language_arrows_right.png | Bin 316 -> 1242 bytes .../res/drawable-mdpi/sym_bkeyboard_globe.png | Bin 1303 -> 0 bytes java/res/drawable-mdpi/sym_keyboard_globe.png | Bin 1290 -> 0 bytes java/res/xml-da/kbd_qwerty.xml | 73 ++++++----- java/res/xml-da/kbd_qwerty_black.xml | 58 +++++---- java/res/xml-de/kbd_qwerty.xml | 115 +++++++++-------- java/res/xml-de/kbd_qwerty_black.xml | 65 ++++++---- java/res/xml-fr/kbd_qwerty.xml | 119 ++++++++++-------- java/res/xml-fr/kbd_qwerty_black.xml | 66 +++++----- java/res/xml-iw/kbd_qwerty.xml | 83 ++++++------ java/res/xml-iw/kbd_qwerty_black.xml | 67 +++++----- java/res/xml-nb/kbd_qwerty.xml | 73 ++++++----- java/res/xml-nb/kbd_qwerty_black.xml | 57 +++++---- java/res/xml-ru/kbd_qwerty.xml | 83 ++++++------ java/res/xml-ru/kbd_qwerty_black.xml | 67 +++++----- java/res/xml-sr/kbd_qwerty.xml | 83 ++++++------ java/res/xml-sr/kbd_qwerty_black.xml | 67 +++++----- java/res/xml-sv/kbd_qwerty.xml | 71 ++++++----- java/res/xml-sv/kbd_qwerty_black.xml | 57 +++++---- java/res/xml/kbd_qwerty.xml | 32 ++--- 23 files changed, 692 insertions(+), 544 deletions(-) delete mode 100644 java/res/drawable-hdpi/sym_bkeyboard_globe.png delete mode 100644 java/res/drawable-hdpi/sym_keyboard_globe.png delete mode 100644 java/res/drawable-mdpi/sym_bkeyboard_globe.png delete mode 100644 java/res/drawable-mdpi/sym_keyboard_globe.png diff --git a/java/res/drawable-hdpi/sym_bkeyboard_globe.png b/java/res/drawable-hdpi/sym_bkeyboard_globe.png deleted file mode 100644 index f5dbe0cd1b3f9db7c836480592e24e93d695532b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2136 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 diff --git a/java/res/drawable-hdpi/sym_keyboard_globe.png b/java/res/drawable-hdpi/sym_keyboard_globe.png deleted file mode 100644 index fa747642d9d91642bf56f769150e095fa372b542..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2093 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 qz`($Q%wc3?B&41L znDc+o$_EYt0s=`C`2Yuy0O9~QH@66JAONzbQPTnkMMcF3TU%RyZf7(YM10##EH5O_E^I25RC>kd0;xut=47BH4M55fh#%6dr~q1W07w}C@dTQcMLPx#07*qoM6N<$g0oa& AH2?qr diff --git a/java/res/drawable-hdpi/sym_keyboard_language_arrows_right.png b/java/res/drawable-hdpi/sym_keyboard_language_arrows_right.png index 0d01bc224322f14f91828d248e9c81cc637a59f3..310952383efa63d251bf615ffdc514aafd27fd6e 100644 GIT binary patch literal 1242 zcmeAS@N?(olHy`uVBq!ia0vp^5{{auq$EpRBT9nv(@M${i&7aJQ}UBi z6+Ckj(^G>|6H_V+Po~;1FfgZOhD4M^`1)8S=jZArg4F0$^BXQ!4Z zB&DWj=GiK}-@RW+Av48RDcsc8z_-9TH6zobswg$M$}c3jDm&RSMakYy!KT6rXh3di zNuokUZcbjYRfVk**jy_h8zii+qySb@l5ML5aa4qFfP!;=QL2Keo`G(%fti7VnW3Jc zv5C34xsHO7fuVuEfswwUk*=Y+m9dePfq?=PC;@FNN=dT{a&d#&1?1T(Wt5Z@Sn2DR zmzV368|&p4rRy77T3Uk4Ff!5ws?aU2%qvN((9J7WhMC}!TAW;zSx}OhpQivaF)=B> zw8T~k=u(ImatnNY;RfdwLjwvJWcn3}1^R}12Ku?VAb){X7ncO3BAkI$b#X{#L8^XG zYH@yPQ8F+-(v)GEfnkT=B9KC$Ypnc>GJ%njnB$V4T$-DjSK{ens|1wMOUX>JaxyY? zb}=?Fa5XV9H?uG_baZobu`o6?FtxOFHFq_4hM9p)uc?8PiJ_B$v!kP%rJr6!i-7lq{K=fF}xKt_H^ zesM;Afr4|ese*4}a%LWg4~ia$Z(UN0GRsm^+=}vZ6~N(Zm5IfECu2hXhUiTpC(QJL zj?o7t4y42a69T3{5EGvCfgE_|NzDW1m?B`-*m3KzC<6l{m#2$kNX4zBKmY&RGwU)w zUctIptS8EVM<+ok^zhx?<rl9zkwNr5S69H-U%`qC*WQFHaonKRcL z4r#AUVm$HT{{H%AWjTo$@rIS!=gyyhZxmX?z%94n;Qhvr7mu7fckk`fr(eZmWh2G@ z{P`*T>{YWv_;PkOwtGjGPD|l-&}8q}&!D`OC*wnj)2ql61%Ja5ZZyaIE!na|Zfk>` c7z2w0LoMscEeux~T|lLcr>mdKI;Vst0Fl|OegFUf delta 252 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 + android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="10%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="20%p" android:isRepeatable="true" android:isModifier="true"/> - + android:keyWidth="15%p" android:isModifier="true"/> + + android:keyWidth="15%p" android:keyEdgeFlags="right" android:isModifier="true"/> - diff --git a/java/res/xml-da/kbd_qwerty_black.xml b/java/res/xml-da/kbd_qwerty_black.xml index 575f0fa49..b9d1d1796 100644 --- a/java/res/xml-da/kbd_qwerty_black.xml +++ b/java/res/xml-da/kbd_qwerty_black.xml @@ -114,77 +114,83 @@ android:iconPreview="@drawable/sym_keyboard_feedback_delete" android:isRepeatable="true"/> - + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="10%p" android:keyEdgeFlags="left"/> + @@ -193,11 +199,11 @@ android:keyWidth="20%p" android:isRepeatable="true"/> - + android:keyWidth="15%p"/> + + android:keyWidth="15%p" android:keyEdgeFlags="right"/> - diff --git a/java/res/xml-de/kbd_qwerty.xml b/java/res/xml-de/kbd_qwerty.xml index 827ad62c7..763627a34 100755 --- a/java/res/xml-de/kbd_qwerty.xml +++ b/java/res/xml-de/kbd_qwerty.xml @@ -1,19 +1,19 @@ @@ -49,9 +49,9 @@ /> - + - @@ -67,7 +67,7 @@ - + + android:isRepeatable="true" android:isModifier="true"/> - + - - + + + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> - + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> - + android:keyWidth="10%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + + android:keyWidth="20%p" android:isRepeatable="true" android:isModifier="true"/> - + android:keyWidth="15%p" android:isModifier="true"/> + + android:keyWidth="15%p" android:keyEdgeFlags="right" android:isModifier="true"/> diff --git a/java/res/xml-de/kbd_qwerty_black.xml b/java/res/xml-de/kbd_qwerty_black.xml index 18fdc7d01..b0b6c238f 100755 --- a/java/res/xml-de/kbd_qwerty_black.xml +++ b/java/res/xml-de/kbd_qwerty_black.xml @@ -97,83 +97,94 @@ - + + + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> - + + + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> - + + - + android:keyWidth="15%p"/> + + android:keyWidth="15%p" android:keyEdgeFlags="right"/> diff --git a/java/res/xml-fr/kbd_qwerty.xml b/java/res/xml-fr/kbd_qwerty.xml index 7df32d914..0f08c26c2 100644 --- a/java/res/xml-fr/kbd_qwerty.xml +++ b/java/res/xml-fr/kbd_qwerty.xml @@ -1,19 +1,19 @@ @@ -26,7 +26,7 @@ > - @@ -55,7 +55,7 @@ /> - + - @@ -91,93 +91,102 @@ /> - + android:isRepeatable="true" android:isModifier="true"/> - + - - + + + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> - + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> - + android:keyWidth="10%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + + android:keyWidth="20%p" android:isRepeatable="true" android:isModifier="true"/> - + android:keyWidth="15%p" android:isModifier="true"/> + + android:keyWidth="15%p" android:keyEdgeFlags="right" android:isModifier="true"/> - - diff --git a/java/res/xml-fr/kbd_qwerty_black.xml b/java/res/xml-fr/kbd_qwerty_black.xml index 78b1da986..6d3aeb829 100644 --- a/java/res/xml-fr/kbd_qwerty_black.xml +++ b/java/res/xml-fr/kbd_qwerty_black.xml @@ -99,84 +99,94 @@ - + + + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> - + + + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> - + + - + android:keyWidth="15%p"/> + + android:keyWidth="15%p" android:keyEdgeFlags="right"/> - diff --git a/java/res/xml-iw/kbd_qwerty.xml b/java/res/xml-iw/kbd_qwerty.xml index 0ce5d367f..208ba92b4 100755 --- a/java/res/xml-iw/kbd_qwerty.xml +++ b/java/res/xml-iw/kbd_qwerty.xml @@ -41,7 +41,7 @@ android:keyIcon="@drawable/sym_keyboard_delete" android:keyWidth="13.75%p" android:keyEdgeFlags="right" android:iconPreview="@drawable/sym_keyboard_feedback_delete" - android:isRepeatable="true"/> + android:isRepeatable="true" android:isModifier="true"/> @@ -71,84 +71,95 @@ - + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> - + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> - + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> - + android:keyWidth="10%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + + android:keyWidth="20%p" android:isRepeatable="true" android:isModifier="true"/> - + android:keyWidth="15%p" android:isModifier="true"/> + + android:keyWidth="15%p" android:keyEdgeFlags="right" android:isModifier="true"/> diff --git a/java/res/xml-iw/kbd_qwerty_black.xml b/java/res/xml-iw/kbd_qwerty_black.xml index 2bf0c2a0c..981ad37c3 100755 --- a/java/res/xml-iw/kbd_qwerty_black.xml +++ b/java/res/xml-iw/kbd_qwerty_black.xml @@ -71,84 +71,95 @@ - + + + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> - + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> - + + + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> - + + - + android:keyWidth="15%p"/> + + android:keyWidth="15%p" android:keyEdgeFlags="right"/> diff --git a/java/res/xml-nb/kbd_qwerty.xml b/java/res/xml-nb/kbd_qwerty.xml index a9e6adc9e..d033bb02c 100644 --- a/java/res/xml-nb/kbd_qwerty.xml +++ b/java/res/xml-nb/kbd_qwerty.xml @@ -110,92 +110,99 @@ + android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="10%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="20%p" android:isRepeatable="true" android:isModifier="true"/> - + android:keyWidth="15%p" android:isModifier="true"/> + + android:keyWidth="15%p" android:keyEdgeFlags="right" android:isModifier="true"/> - diff --git a/java/res/xml-nb/kbd_qwerty_black.xml b/java/res/xml-nb/kbd_qwerty_black.xml index 8d23cc196..14456e6b6 100644 --- a/java/res/xml-nb/kbd_qwerty_black.xml +++ b/java/res/xml-nb/kbd_qwerty_black.xml @@ -115,74 +115,81 @@ + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="10%p" android:keyEdgeFlags="left"/> + @@ -191,11 +198,11 @@ android:keyWidth="20%p" android:isRepeatable="true"/> - + android:keyWidth="15%p"/> + + android:keyWidth="15%p" android:keyEdgeFlags="right"/> - diff --git a/java/res/xml-ru/kbd_qwerty.xml b/java/res/xml-ru/kbd_qwerty.xml index 0c49f3781..e512c0b84 100755 --- a/java/res/xml-ru/kbd_qwerty.xml +++ b/java/res/xml-ru/kbd_qwerty.xml @@ -78,89 +78,100 @@ + android:isRepeatable="true" android:isModifier="true"/> - + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> - + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> - + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> - + android:keyWidth="10%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + + android:keyWidth="20%p" android:isRepeatable="true" android:isModifier="true"/> - + android:keyWidth="15%p" android:isModifier="true"/> + + android:keyWidth="15%p" android:keyEdgeFlags="right" android:isModifier="true"/> diff --git a/java/res/xml-ru/kbd_qwerty_black.xml b/java/res/xml-ru/kbd_qwerty_black.xml index a9c88b7d2..00c399273 100755 --- a/java/res/xml-ru/kbd_qwerty_black.xml +++ b/java/res/xml-ru/kbd_qwerty_black.xml @@ -83,83 +83,94 @@ - + + + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> - + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> - + + + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> - + + - + android:keyWidth="15%p"/> + + android:keyWidth="15%p" android:keyEdgeFlags="right"/> diff --git a/java/res/xml-sr/kbd_qwerty.xml b/java/res/xml-sr/kbd_qwerty.xml index 117db4c54..cab846004 100644 --- a/java/res/xml-sr/kbd_qwerty.xml +++ b/java/res/xml-sr/kbd_qwerty.xml @@ -74,88 +74,99 @@ + android:isRepeatable="true" android:isModifier="true"/> - + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> - + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> - + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> - + android:keyWidth="10%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + + android:keyWidth="20%p" android:isRepeatable="true" android:isModifier="true"/> - + android:keyWidth="15%p" android:isModifier="true"/> + + android:keyWidth="15%p" android:keyEdgeFlags="right" android:isModifier="true"/> diff --git a/java/res/xml-sr/kbd_qwerty_black.xml b/java/res/xml-sr/kbd_qwerty_black.xml index 91b118f27..00a289449 100644 --- a/java/res/xml-sr/kbd_qwerty_black.xml +++ b/java/res/xml-sr/kbd_qwerty_black.xml @@ -79,83 +79,94 @@ - + + + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> - + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> - + + + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> - + + - + android:keyWidth="15%p"/> + + android:keyWidth="15%p" android:keyEdgeFlags="right"/> diff --git a/java/res/xml-sv/kbd_qwerty.xml b/java/res/xml-sv/kbd_qwerty.xml index 1ffa9dd1c..514a44154 100644 --- a/java/res/xml-sv/kbd_qwerty.xml +++ b/java/res/xml-sv/kbd_qwerty.xml @@ -119,87 +119,94 @@ + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + - + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="15%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="30%p" android:isRepeatable="true" android:isModifier="true"/> + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> + android:keyWidth="10%p" android:keyEdgeFlags="left" android:isModifier="true"/> + + android:keyWidth="10%p" android:isModifier="true"/> + android:keyWidth="20%p" android:isRepeatable="true" android:isModifier="true"/> - + android:keyWidth="15%p" android:isModifier="true"/> + + android:keyWidth="15%p" android:keyEdgeFlags="right" android:isModifier="true"/> - diff --git a/java/res/xml-sv/kbd_qwerty_black.xml b/java/res/xml-sv/kbd_qwerty_black.xml index af8cda60e..4cc37cec8 100644 --- a/java/res/xml-sv/kbd_qwerty_black.xml +++ b/java/res/xml-sv/kbd_qwerty_black.xml @@ -119,74 +119,81 @@ + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + - + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="15%p" android:keyEdgeFlags="left"/> + + android:keyWidth="30%p" android:isRepeatable="true"/> + android:keyWidth="25%p" android:keyEdgeFlags="right"/> + android:keyWidth="10%p" android:keyEdgeFlags="left"/> + @@ -195,11 +202,11 @@ android:keyWidth="20%p" android:isRepeatable="true"/> - + android:keyWidth="15%p"/> + + android:keyWidth="15%p" android:keyEdgeFlags="right"/> - diff --git a/java/res/xml/kbd_qwerty.xml b/java/res/xml/kbd_qwerty.xml index d7d1ee0d5..0a0691dd1 100755 --- a/java/res/xml/kbd_qwerty.xml +++ b/java/res/xml/kbd_qwerty.xml @@ -4,16 +4,16 @@ ** ** Copyright 2008, 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 +** 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 +** 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 +** 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. */ --> @@ -59,9 +59,9 @@ /> - + - @@ -85,9 +85,9 @@ android:popupCharacters="@string/alternates_for_l" android:keyEdgeFlags="right"/> - + - @@ -113,7 +113,7 @@ - - - + android:keyWidth="25%p" android:keyEdgeFlags="right" android:isModifier="true"/> From 40a05f62edc6cdedb4365a722b48a72826ef2bf6 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 2 Sep 2010 01:35:24 +0900 Subject: [PATCH 38/58] Queuing PointerTracker to support n-key roll-over and shift modifier. Bug: 2910379 Change-Id: I5cfae33e72a406585137842a2260310813cee07f --- .../android/inputmethod/latin/LatinIME.java | 29 +++++++- .../latin/LatinKeyboardBaseView.java | 67 ++++++++++++++++++- .../inputmethod/latin/ModifierKeyState.java | 42 ++++++++++++ .../inputmethod/latin/PointerTracker.java | 22 +++++- 4 files changed, 153 insertions(+), 7 deletions(-) create mode 100644 java/src/com/android/inputmethod/latin/ModifierKeyState.java diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 76f774c96..7afee3fad 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -227,6 +227,9 @@ public class LatinIME extends InputMethodService private int mDeleteCount; private long mLastKeyTime; + // Shift modifier key state + private ModifierKeyState mShiftKeyState = new ModifierKeyState(); + private Tutorial mTutorial; private AudioManager mAudioManager; @@ -976,7 +979,8 @@ public class LatinIME extends InputMethodService public void updateShiftKeyState(EditorInfo attr) { InputConnection ic = getCurrentInputConnection(); if (ic != null && attr != null && mKeyboardSwitcher.isAlphabetMode()) { - mKeyboardSwitcher.setShifted(mCapsLock || getCursorCapsMode(ic, attr) != 0); + mKeyboardSwitcher.setShifted(mShiftKeyState.isMomentary() || mCapsLock + || getCursorCapsMode(ic, attr) != 0); } } @@ -1233,12 +1237,20 @@ public class LatinIME extends InputMethodService ic.endBatchEdit(); } + private void resetShift() { + handleShiftInternal(true); + } + private void handleShift() { + handleShiftInternal(false); + } + + private void handleShiftInternal(boolean forceNormal) { mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE); KeyboardSwitcher switcher = mKeyboardSwitcher; LatinKeyboardView inputView = switcher.getInputView(); if (switcher.isAlphabetMode()) { - if (mCapsLock) { + if (mCapsLock || forceNormal) { mCapsLock = false; switcher.setShifted(false); } else if (inputView != null) { @@ -2146,15 +2158,26 @@ public class LatinIME extends InputMethodService vibrate(); playKeyClick(primaryCode); if (primaryCode == Keyboard.KEYCODE_SHIFT) { + mShiftKeyState.onPress(); handleShift(); + } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE) { + // TODO: We should handle KEYCODE_MODE_CHANGE (symbol) here as well. + } else { + mShiftKeyState.onOtherKeyPressed(); } - // TODO: We should handle KEYCODE_MODE_CHANGE (symbol) here as well. } public void onRelease(int primaryCode) { // Reset any drag flags in the keyboard ((LatinKeyboard) mKeyboardSwitcher.getInputView().getKeyboard()).keyReleased(); //vibrate(); + if (primaryCode == Keyboard.KEYCODE_SHIFT) { + if (mShiftKeyState.isMomentary()) + resetShift(); + mShiftKeyState.onRelease(); + } else if (primaryCode == Keyboard.KEYCODE_MODE_CHANGE) { + // TODO: We should handle KEYCODE_MODE_CHANGE (symbol) here as well. + } } private FieldContext makeFieldContext() { diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index 4daf6515f..30042d8a1 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -33,6 +33,7 @@ import android.inputmethodservice.Keyboard.Key; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; +import android.util.Log; import android.util.TypedValue; import android.view.GestureDetector; import android.view.Gravity; @@ -45,6 +46,7 @@ import android.widget.TextView; import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedList; import java.util.Map; /** @@ -62,6 +64,7 @@ import java.util.Map; */ public class LatinKeyboardBaseView extends View implements View.OnClickListener, PointerTracker.UIProxy { + private static final String TAG = "LatinKeyboardBaseView"; private static final boolean DEBUG = false; public static final int NOT_A_TOUCH_COORDINATE = -1; @@ -199,6 +202,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, private OnKeyboardActionListener mKeyboardActionListener; private final ArrayList mPointerTrackers = new ArrayList(); + private final PointerQueue mPointerQueue = new PointerQueue(); private final float mDebounceHysteresis; protected KeyDetector mKeyDetector = new ProximityKeyDetector(); @@ -316,6 +320,41 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, } }; + static class PointerQueue { + private LinkedList mQueue = new LinkedList(); + + public void add(PointerTracker tracker) { + mQueue.add(tracker); + } + + public int lastIndexOf(PointerTracker tracker) { + LinkedList queue = mQueue; + for (int index = queue.size() - 1; index >= 0; index--) { + PointerTracker t = queue.get(index); + if (t == tracker) + return index; + } + return -1; + } + + public void releasePointersOlderThan(PointerTracker tracker, long eventTime) { + LinkedList queue = mQueue; + int oldestPos = 0; + for (PointerTracker t = queue.get(oldestPos); t != tracker; t = queue.get(oldestPos)) { + if (t.isModifier()) { + oldestPos++; + } else { + t.onUpEvent(t.getLastX(), t.getLastY(), eventTime); + queue.remove(oldestPos); + } + } + } + + public void remove(PointerTracker tracker) { + mQueue.remove(tracker); + } + } + public LatinKeyboardBaseView(Context context, AttributeSet attrs) { this(context, attrs, R.attr.keyboardViewStyle); } @@ -1107,14 +1146,14 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, switch (action) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_POINTER_DOWN: - tracker.onDownEvent(touchX, touchY, eventTime); + onDownEvent(tracker, touchX, touchY, eventTime); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: - tracker.onUpEvent(touchX, touchY, eventTime); + onUpEvent(tracker, touchX, touchY, eventTime); break; case MotionEvent.ACTION_CANCEL: - tracker.onCancelEvent(touchX, touchY, eventTime); + onCancelEvent(tracker, touchX, touchY, eventTime); break; } } @@ -1122,6 +1161,28 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, return true; } + private void onDownEvent(PointerTracker tracker, int touchX, int touchY, long eventTime) { + tracker.onDownEvent(touchX, touchY, eventTime); + mPointerQueue.add(tracker); + } + + private void onUpEvent(PointerTracker tracker, int touchX, int touchY, long eventTime) { + int index = mPointerQueue.lastIndexOf(tracker); + if (index >= 0) { + mPointerQueue.releasePointersOlderThan(tracker, eventTime); + } else { + Log.w(TAG, "onUpEvent: corresponding down event not found for pointer " + + tracker.mPointerId); + } + tracker.onUpEvent(touchX, touchY, eventTime); + mPointerQueue.remove(tracker); + } + + private void onCancelEvent(PointerTracker tracker, int touchX, int touchY, long eventTime) { + tracker.onCancelEvent(touchX, touchY, eventTime); + mPointerQueue.remove(tracker); + } + protected void swipeRight() { mKeyboardActionListener.swipeRight(); } diff --git a/java/src/com/android/inputmethod/latin/ModifierKeyState.java b/java/src/com/android/inputmethod/latin/ModifierKeyState.java new file mode 100644 index 000000000..097e87abe --- /dev/null +++ b/java/src/com/android/inputmethod/latin/ModifierKeyState.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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; + +class ModifierKeyState { + private static final int RELEASING = 0; + private static final int PRESSING = 1; + private static final int MOMENTARY = 2; + + private int mState = RELEASING; + + public void onPress() { + mState = PRESSING; + } + + public void onRelease() { + mState = RELEASING; + } + + public void onOtherKeyPressed() { + if (mState == PRESSING) + mState = MOMENTARY; + } + + public boolean isMomentary() { + return mState == MOMENTARY; + } +} diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java index c8976a372..10f51bd48 100644 --- a/java/src/com/android/inputmethod/latin/PointerTracker.java +++ b/java/src/com/android/inputmethod/latin/PointerTracker.java @@ -21,9 +21,13 @@ import com.android.inputmethod.latin.LatinKeyboardBaseView.UIHandler; import android.inputmethodservice.Keyboard; import android.inputmethodservice.Keyboard.Key; +import android.util.Log; import android.view.ViewConfiguration; public class PointerTracker { + private static final String TAG = "PointerTracker"; + private static final boolean DEBUG = false; + public interface UIProxy { public void invalidateKey(Key key); public void showPreview(int keyIndex, PointerTracker tracker); @@ -108,6 +112,15 @@ public class PointerTracker { return isValidKeyIndex(keyIndex) ? mKeys[keyIndex] : null; } + public boolean isModifier() { + Key key = getKey(mCurrentKey); + if (key == null) + return false; + int primaryCode = key.codes[0]; + // TODO: KEYCODE_MODE_CHANGE (symbol) will be also a modifier key + return primaryCode == Keyboard.KEYCODE_SHIFT; + } + public void updateKey(int keyIndex) { int oldKeyIndex = mPreviousKey; mPreviousKey = keyIndex; @@ -146,6 +159,8 @@ public class PointerTracker { } showKeyPreviewAndUpdateKey(keyIndex); updateMoveDebouncing(touchX, touchY); + if (DEBUG) + Log.d(TAG, "onDownEvent: [" + mPointerId + "] modifier=" + isModifier()); } public void onMoveEvent(int touchX, int touchY, long eventTime) { @@ -178,6 +193,8 @@ public class PointerTracker { } public void onUpEvent(int touchX, int touchY, long eventTime) { + if (DEBUG) + Log.d(TAG, "onUpEvent: [" + mPointerId + "] modifier=" + isModifier()); int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); boolean wasInKeyRepeat = mHandler.isInKeyRepeat(); mHandler.cancelKeyTimers(); @@ -204,6 +221,8 @@ public class PointerTracker { } public void onCancelEvent(int touchX, int touchY, long eventTime) { + if (DEBUG) + Log.d(TAG, "onCancelEvent: [" + mPointerId + "]"); mHandler.cancelKeyTimers(); mHandler.cancelPopupPreview(); mProxy.dismissPopupKeyboard(); @@ -305,7 +324,8 @@ public class PointerTracker { private void showKeyPreviewAndUpdateKey(int keyIndex) { updateKey(keyIndex); - mProxy.showPreview(keyIndex, this); + if (!isModifier()) + mProxy.showPreview(keyIndex, this); } private void detectAndSendKey(int index, int x, int y, long eventTime) { From 8f5b0ccc507ea7569fec0b8fb0260eedc486ed95 Mon Sep 17 00:00:00 2001 From: satok Date: Thu, 2 Sep 2010 16:00:06 +0900 Subject: [PATCH 39/58] Update assets for LatinIME Change-Id: Ia3027b68abcc9a51bc6a21320926b9c8b5c5975a --- .../btn_keyboard_key_dark_normal.9.png | Bin 520 -> 530 bytes .../btn_keyboard_key_dark_normal_off.9.png | Bin 774 -> 780 bytes .../btn_keyboard_key_dark_normal_on.9.png | Bin 1130 -> 1108 bytes .../btn_keyboard_key_dark_pressed.9.png | Bin 795 -> 744 bytes .../btn_keyboard_key_dark_pressed_off.9.png | Bin 1029 -> 965 bytes .../btn_keyboard_key_dark_pressed_on.9.png | Bin 1332 -> 1290 bytes .../btn_keyboard_key_light_normal.9.png | Bin 497 -> 460 bytes .../btn_keyboard_key_light_popup_normal.9.png | Bin 642 -> 640 bytes ...tn_keyboard_key_light_popup_selected.9.png | Bin 1514 -> 692 bytes .../btn_keyboard_key_light_pressed.9.png | Bin 812 -> 829 bytes .../keyboard_key_feedback_background.9.png | Bin 1184 -> 1175 bytes ...eyboard_key_feedback_more_background.9.png | Bin 1544 -> 1478 bytes .../keyboard_suggest_strip_divider.png | Bin 945 -> 1012 bytes ...keyboard_feedback_language_arrows_left.png | Bin 322 -> 1275 bytes ...eyboard_feedback_language_arrows_right.png | Bin 328 -> 1329 bytes .../sym_keyboard_language_arrows_right.png | Bin 1242 -> 1372 bytes .../drawable-hdpi/sym_keyboard_settings.png | Bin 1459 -> 2253 bytes 17 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png mode change 100755 => 100644 java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off.9.png mode change 100755 => 100644 java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on.9.png mode change 100755 => 100644 java/res/drawable-hdpi/btn_keyboard_key_dark_pressed.9.png mode change 100755 => 100644 java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off.9.png mode change 100755 => 100644 java/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.png mode change 100755 => 100644 java/res/drawable-hdpi/btn_keyboard_key_light_normal.9.png mode change 100755 => 100644 java/res/drawable-hdpi/btn_keyboard_key_light_popup_normal.9.png mode change 100755 => 100644 java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png mode change 100755 => 100644 java/res/drawable-hdpi/keyboard_key_feedback_background.9.png mode change 100755 => 100644 java/res/drawable-hdpi/keyboard_key_feedback_more_background.9.png mode change 100755 => 100644 java/res/drawable-hdpi/keyboard_suggest_strip_divider.png mode change 100644 => 100755 java/res/drawable-hdpi/sym_keyboard_settings.png diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png old mode 100755 new mode 100644 index 48ebb6183b270bf86619f8b7b9ad0f7fcb185286..045e1bba7c04cec4db136dbcd5d5c88d274d23ec GIT binary patch delta 467 zcmV;^0WAKA1d;@hNq@9SL_t(|+U%N3Zi6rohR0yBL##-5+@v{7bFTC-$xYZbtPm1H zyd3NXMJnduR&@rLi7ZR8fcY{W`!^E+J0|}1=0X6s@gNJ&U=D1=2n3rki#Y<6Ba|Zq z@;c+XFQX`e_u~=X4hJ-=fLxWnZa27IE)d7@vQ_KjbW+=XS$~$QM*+eZc%G;F&+~aO ztc^(1G>~PP>M?=1t_!~JFP~aPQK)G2H^5+R+o~T{`nDKEUL+e9h+g5!CjHV4^Qnt4 zS?|-BUj#xRHbDR}2pC1=aUsfxm`D`L5dt9)0$C>r!}NOPFCapyUqq4lJqXs_eRm+x zYZ_!AV6L^EAAeLF6F%udTJhbmfjs;&Q@?=k&GwW}lTOAoGah7pgNf!1ObF$I81w(u^kaUCro&;xXDB01 zTD1s-Kz0Jcw*Vox2%1_1LLfTy%oDn7hMugNLP$GZWHYIjiL1`_|2)af#)qc$pJ6jaCD6A3I$SO5rArgAT z{Ytge1uU^!M1RcPpqmpEaz@N0GS{o2=8~oD7rg~@X>nE8yluP{#N=9yJWZ)0w z6&X~q>yR1lwfZ)P+O;<2exWDBMVUOJdb?e|KG6y z%ZQ33NhnRz;iEB;l?MOq0xu;C?Efn8UIZ8b;ac;cc!wbU00000NkvXXu0mjfjqcM} diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_off.9.png old mode 100755 new mode 100644 index 38b8b48aae600c82c23365a54a11e7797970f740..14424b4c2eb3ee956a6aaaf1326d8e474c839209 GIT binary patch delta 719 zcmV;=0x`U6(FKS0WJ; zMSlQ7_-gCCBUNviQi@VfVTLpfoxq%j_k7W*@H~$;J%kW)8BYYR{n+<|!SWYM0%nt6 zpP?-o2E>4DCjN{f2E>3w3`=*h(P+@w`8gdO9+Jl;pyl!S^nXORH#gL3wHD`5-h);5 z;__0J{mEoPNwhGlW~N*&r_R?`R}0fxMI6VWe!s8IoItYKES1aU)m>{e8Ywk?y1Dz# za9vmZu&`}q5PS#+7YM(@#R0o?)7G*NB{ingDYe^e8V-jvo6YFY-X8rsKBiKsv|v-1 zUB3&*tER|Gr>sepsJ|JQ#GFN5OBcIPx zZ^>G?9&{@&PK%P1Yr$o*(zRS!9}wh08yuOzPyol{F@NtEfr0gt6V*GxjeHoajg*Y6 zg>?L%B3!c;I*4YoNe{A)Aov|w@ZfTd(^C~6{nyuYq+h6l)}vmptCR~>paxPe=2BA- z{mTCQ^0HEk!Wtw_ueBD4n5SYUBr~#3e{@0$UielD@cOT>2#>u?JiF1K++f^CTkfG17bkZ zGmv?WA_l~O>EQ;7G~eqhezK87yv=ZbTEAQ#AE;f002ovPDHLkV1iJX BTG9Xj delta 713 zcmV;)0yh1O28ITZNq?wGL_t(|+U#3xYQjJeoy5c{)r$B5BKp%~)Wg(cwTEd>qE?|* zEQlXyOiX7MQ#6S-5nRW(3nFBd%-i?o&17A5kTcv%-$0Xfqf6t^At6HnQ9u-s)5Gvz zXf~Vh+-^g)T4fpVXf%S4_jl;``={;qrPBe|b-}VM@y^O)HGd7#>9lx%dwo5a3NYf> zHq7R8a2$svkW?xK`CRUQX|305*dQC;7degXb_-ivV2aV-IT)cI#uqmbB3e`ky(qqa z8Sy?Wb8I#n7!HT9SS*C3v)L@vYBk9DB;>^w7M~H;-N}TpTCJel?Lsz_feJb$DPfJ* zJ_iG+R4Py^m45=Uxl!y_HY49(U+|RA!{grSo2CgSy3=$z6|9g`#b-n!5MqN|h@=F* zdp=)~?2Ii2Qq@x%fmRz?z#46gWWHamJhZO6>tycZj{ zWH)zgIB2J|@_uF5=wLa_A8S|FVkJ9Blol1Xdc6+4UVl%3^1x7?u(87^m&*qo#-FSr zGa}KosD`v!Ef}EPQt}fBl2fzM5NuJh2kHn%`z2Or)rlFhSsm+$h2SW6{H+MvWcP-R zf&WYp)nqh v#i6u=DL;@K9qMlv{3wag{@+BrzXA*ZQNC(QBskc@00000NkvXXu0mjflCMtV diff --git a/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on.9.png b/java/res/drawable-hdpi/btn_keyboard_key_dark_normal_on.9.png old mode 100755 new mode 100644 index 147c1b22e383165b2e7cd8c8662a356f2f5d8d73..f30ad1e7bf9b25382491d0f139d1876898865b4b GIT binary patch delta 1051 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 delta 734 zcmV<40wMkA1)BztNq@abL_t(|+U%Q4a_TS;MO)@u6susskS(wgrmTu78(|9!88Bo4 z6ax&wdavblsx4WzNFn(XiBcIWCc1~)`q=3JgelT@2O?BQzBv-;Nr@m4B!X0zq291s ztzf&|!g9F;DT|XCp6hMirXe9z)!R;|6YO?7I3ADH)9-%2hkyBe4zJfsoo895DnWz> z!I~tAs#pet0o-mk*lae1%MC|nvl-m)cLhQaI!s6qf}n~ZsIfM*()13G$3y)R8;EZh z?uL{}p?-Zm{~t4B=U{-K$Sgylxp?kOla8PhdEcT`LkS4{h|WPwS3-dx0CtymDbz7{ z30y$rk6?0xj(?#;tE?|-uLa@XJV9XPfT2KgN2Jk?I^J@GzYjT1_!@#R*e@NO9pT}l zLxdV5*au$>$pvaF)6m~73U|a-Lls-!PNC%j(=^E6a-^#u{T=Ks&NS(Wevi`G(6VXh zFGzl~SSQvujHv0`aT{OvrTaETi0Zzbw()HWFYgOt(|;h&Ta>nJQ{I_=|Mu>;Nk=}q zj?6C5n47~F|;B`6JvxYwD30lnovd8 zQI^MLU4IaH<^lbEoARZ~vJSk2%6Bpi*J6XHb%du;U?rGPAUr!r*X0Dl1@q~yDuv?H z;iM;>VVV<%atbYeF+uT+ols+=EPKv5v`9P`Oj$xSW ztL~A^r)Mg1g`Aj7CNLh4VK_8Lgwb-jT$E^pAy*KdDbxfAg*Adqr&G9IujXgi-LNW) z#RAsrHH=0hBaE5=(ZlWee8S;yfb;oW{D=J`7h6uWwUv!NsM*}mY6^?^K)i)HnT|`k4K7HQmNEGHOG{4 zEwtx@!D2;mz(o1@G+l`p5CalT{uz%L5Ch^NmhNJ!)uLXnM}JRGPqqrmD}kt11YGfP zRIC4ZJf?oXPw(&V_WNLvT6JGuUZ_wg(0;!c=ZC{V3@C4F{;76~$RWxVXVH zNOD<_m#Am;dfgXD+AA5O9J}3)9v>gYvIF_RVT9lF`CKGA0R8-V>2m=;=8Y{Zk2u-$w>%YKtZ+5V<9!+7k#wHdszFul9Zz z;iPVaqDd!11qv9{~RoB@IzEOhI&_vt?2Kuf>V>4^P3 zHH_i}QNsn-1gx#e8LIKn#chxgZgXS>q7{VnF@|i1k0~QyvSsv#!OQ g?2{Lk-vSH((77Yk#-1hl00000NkvXXt^-0~g4_D1X#fBK delta 970 zcmV;*12z1`2ZacbNq?tFL_t(|+U#3RPwGGvy+sg2jVuh{&R|qnX#5BK5w`v+w)_zm zY)sq`S1w!`6XME`M82f&o#9>HW!ln#^b684liCWMb9&CbGi|R#(KI{k0j#J73Y$lU zcBG|5QX(ml)h(+ZxV^ol`}=#ky1F9UUQTA%*N=skhAc~U{eRf=^E0*EZR+>?tJ80% z)1jlIBl`XQRr|BqOm!v^H4*eoCZjsq-rgR4e}7Y})mr+vLy=;!NWs$tuir9Pcb{%&WEm4kx_K+a|WItMS6iBl0MF(2D< z#o$7O7NF-uoPVkW-F|+4=<)H9-rwJ8GMP}RRHD1PJ32c%Q+Vb>T53C2iA;#t3&5-f zZ^N+G=jSK&dObQhIic(8YszM`^zrdQ4-XI2Xf){Z^3tJ{ks|WSGYND_FeoB8&(qTr zRjXAxJw08d+e)QEhlhvs`ua-ca#@j-b_0&J6p_D&5q~GR^6)-@%JTv&h#=_<1_L@i zK2~vp@r@Oc_R&cM9V64}Q~`#a+%Oahg(WPkm>Y&zmna~i&)#}G92^{MwnUMNc=ezf zK;nGJRBozZVm?1VcZ_YUhzXe>I;?eZaiNwRqtR%QSP&auUtcQFLD1wvX5u2j9YAkx zZq(Qygnx7lg0)&rWi$M4;)+4X@U zwE|tD#7$(ac_gVsywdOPKA=mwwE~?-l1L=AR)1=()LI)XbN{7L|M?n@3;Bwkz3V4C|3DbOe3*) zk$>=2gipYkVx3oEK@gGEK{_rYA`-AncdJS$g0_=hbcRw7Ny^At^21E(e<4_O^;&M# zbH>(U@Dear331FsX)RWQx5h;H9XF~EP>mq#w)`H+1f8i^6;>jj&(r??zN6fO+=?^b z-rf{wkYOUSQYa20Y-h7h sD>{)aZRx*VBu^59Crev__m2Pr0NC$|V?0G7761SM07*qoM6N<$f$7h$+hhsEukdLNFTc8eL1PI`3fB=CJ zAlLK>e01N+x%u96fL#0vZkvPA7$}gaK?1|E9LbbO?sjI^V{Isk5=D`*9j>&dB#Yen z?fhqFmn#X?6kY1YwFbY6hAL=7NVp=U2B|^H2oND^kJKPF$bXdLr+v7-z7AVkTd=ma zHkLuD^6Rn!myi6K%l`g8Y;SMF-rnB$d1+a9XJ-eNmzN=qWAk1qWh#R#8e(LxIDaqf zACQ={rL@BFJP&%k9&B!Ij$I*!v%8*{ROc;L9yqLG;5NJ)#uIcoF~P!SV+Eps&dF|D&I>YkRdy7Lu}0w? zI6C?s2En-Qqew&dSmVI((0o_L*+ajac6VaYm4A9x8HgBy{t&{`=Qv79_d7}*pN9L>K2DPcpHYey zfPWUVJY~uaGEH`cymHpNCfP;`cD=T7{?b+GZ0wogXbqctK^oz_OyxvKMrIkx^?=H&V5;wiC{j z9!y+}+7lTr`Fb9i;l^~HcCQS`)xL{TOMmO4fw;rmMFE+XgfEpxvS6-$uveB4b9iL# zN#iu2szB1-*9q}5#E7nZl~}+dSs)?_Q%mcj&$Y4=RM{SxWY4$d5niRaE3)M3ENiv4 zsFG|yZC`Qfr15<1jH`dT)4{L#Zhe`B+M(*&kOeW5NBBalPlhQQgxhr?a(l$>{eNWO zv3JVco^~Oq(k7@2l}lRgNesn}ls#f4K^P{twAgspVBUV?n5jZq>_Ivry)!7xa2Yq}~BmNS90+imD}yXohR?)Qz# z>gpzuu@Mrrn(QUw{Ds{og-p=%k0300000NkvXXu0mjfLMm7i delta 1275 zcmVFPP$rSOi5Mv+-{TUw!;XpV9BQy+yu*PIdfeeQOj7B4M;yjS6 z!f5eYxSnmH#D9+8XP8LFQ1pldq~P%#1c6V_QEKIo0%4JnI*ArUdWn+vWyfoHXUba$N<4uv<69A<*L@;*$2A{cTy0_4xS%B#YN{& z1bz>3L`SJkm zuO+_PZo>0gIQ#oGUOfMe-25jz*!%|MRRj}q*ei%a7O`jEKybGKuL9z*n>g$y>{=2R z=fC6I?-~TLMuDuqv-!ZqCl6h`c=i-Q*d{A(DsUbjvB%715&L*yal-MzFr+95U*Yqu zbA0h-Ykv%3+M`cB^gcv*{ns8ii@gWKB_aeM~6X2is zKVZcDCSy4EVBR(QbbGjh!>`G7;uq{CN3(> z3Ygbeh%F(6OkJZaFGgUC)r!UCy53sl#|z8xa(}vp<$+*w_LEoJdghHw&DP*%-xQRy zN3Z0*VcysUm+`YEz3j_&A!cMfSuofucYm)r5>8(Gs2Eu`$Xs<~RYCI7?-EwO<+N+( zS_`css|ZrNR_$7~Yt89ecEMRSi{ur<8&%nFlxxX(-D=rOl)S7ZY#3=hlCP7WRd6dW zSIg{Rmx*f^nbWHw$=6cXkri(@zaXx%Yu)HYV;v*c?s{b2+cIUiR-UffwQ7)M#D9p{ zCuQFV%i1?pRZHr~+Q*e!5Y3l)lMDYh$sBXb+I3KhtHgV>Y%O^ZGc96HU^0b)sS3o5 zZ$lKeh&}ts6lkndcKWp^(RAK$W=H6DQ>AMe zOPJ@vAS{^oH1c-9;cz&yZ)?^qnRG>GDq|I6iM6#gG@DJhZaN}T@0^{TDbWmLK!M l1(|kdX{7|`eejU?=?OlK_!0lMOAUpRYF2KTGEd~EG zlYlVH(|I<}iSY!|1VZkYlXEZVHRzhbKYakZ>Yz_^7^KP22ZVEedkDb*kH8}Uc?gKL zw-|;YB}qa-5GWOFS(cP#85KowuCk|TN}lIY-}khxs~S(oFn`E(T^Uat$1fbaia3r# zZQIf`O{7YlVT_SwS@MEUKdr9oXdFkmSxgm%P(oa+ZQJKTgbJ!v{4J(~xVSDL1Q37# zwj~W_`L_t(|+U%P>j)O1|g$MA8nnTcYAxcg~$sxD~Jy(E^utxlN zV<(Z=jmdLF6UE|vnP<~|``d4pW#qapbzMi(H1V>}U6=3sMt@fv$G-(Ohlr)YbE3uyEnQNtKblIF) zRTZ^uYr0HzgC?tQT?o@n+a07*qoM6N<$g7GKNtpET3 diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_popup_normal.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_popup_normal.9.png old mode 100755 new mode 100644 index ce58880db5ff4de1f5ddacbb0d4fd434c416a80d..959c6d14a6db41e223f844eca85e16f703fe4743 GIT binary patch delta 578 zcmV-I0=@l$1%L&RNq-_qL_t(|+U%OmPQpMC$9D@w^aKYJu6`Unc;mp42k>ru1$h{r z!FcxpIC3|}c&c8(kXR4ICH-`!me`OspomO|+2o&4Lh1av|Cuf9Sn7X9yy*+*6rUu&@esjmA4{eFL~^LxGCMv`5pvww67ItDd}-S~IV3&;UQ z*@d>6W3}^cw|mj)bS_)1)(I{)RI1Z>JboSyhqr^l;11rp2Zco-HPBJJ-M$8hhHcxV zrUP#*#s(k{aQFl=MId`1I|zb?=XuH)L#9rnGb)ve!q_mzG}c0p+0`*F|0TFdf;HweY5wcFMz}wIIu|4ef@FIdL8!ps9)Ekf&%V-(V1Gw28jU8#m_yuW zrv!p~?XK&-VvK35g&;o2bsVQ(uh*|?Fev%Qg8@#tftPP-tl!>R`0PID5OfA=;*C&r z+6D311nuF19zhe8Y2jE55(7U_U+qoJ6pRAQ9Kxg^*zWY9GTlK%{aR?bTG3pRTkv><9OeY1R?wWu_ftz|1|@)r;R`J3_!$+XoP4KXgQNS^`>0B0Tt`>r>e QWB>pF07*qoM6N<$g4q=mVE_OC delta 580 zcmV-K0=xZy1%d^TNq;0sL_t(|+U#4sPQp+WKDWJS6df#yI5HR~CZEFBFk$8moO}Zo z7ABs;2XPVyMnaIp)Y4E|>N#);mkKx_=1|T_zR*IOe&0Pmx5Ed(|3td)2dLRo(i9Fk zlu{revCkgaB^r&!PWRXA^*3RbzLBi#1-+mP6!=e1VI4f@ffJAxMhS&D~@9zj>OgC zpV~rZjZRrufPY(LxE1VSq_f#OAR#N|qPN|^Rmi%~zo_P%5jc*F9I6lpauU)b(jzi{ zw{y#HvrB1ln_AK%Tzka+=@2C30Z*5$}jML=TKzR%QByvOs=X z^3^Wvs6Cv7#3mC%#0O%u$V%25@50g-uYspGK8B?~K7lpf_)V+8DK_%`7GMA_Ga*Gu S?AcfV0000wmnkr7QIrAkBEfF&p>-K5G- zFfM44B4v~xV46gNe-X)b3XlS{KtV-8gCL0%$zTin&c4m;B`2NF7yIlOd-psejdpGM zbnorFnOWVfZ6O5i+YG~?+Xy4_-B|BoV*(Z>k>K~kE)-0p#D7vl#8wg1?YqHBoUe#3 zDRM-nZPBV{$At9-4Q28I`OEtPa`Sei%Z|yvk?)Y7brB1fIwG<8_eVNdd0`v7Jw%Aa zD;f?pQ`icTIf_cF989hrJjFroHSTiHVVY{x1JCm?S3AdQ?F$y&i!kOMB86a5wTs9S ziA*M=)bh)Pt$#L(D7l||Fo%ge3no9^EEXLH&1Msm*o!6JhLAcWwm8hO<+on1qt$Bp z7mj;#_dn8dUDwBkhY9-hiTC#K1nxeEg*?&3NIY(wCN8(=QYbmXMBv@Kp zemNpcgo!W_CZd-av3;c7Zo_dL|CMm3(@_GcWm*2~a*1tFL%bwk@@KbK_(df8T{!X1 zZQK6BnvL&>VD2Fzj}N_(lT!W^A5ZdV7>||G&m&RChvjQTF#pk3=ycE;4SSm9#`?lG z_PdgOzHlP;+aBKQ!a!mTNOVQS|3G%Vg^i4bvT0zI{E157J%JzO2Tlh&`A_&N_mQzg zCR#819M(y4Opv0%4N>imsG_t+!IX-K@F9OD!bHYYwdB*tX@X4hkD%WI3;RFmnI^ literal 1514 zcmeAS@N?(olHy`uVBq!ia0vp^MnLSs!3HD`yQJj;DajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_cg49sbnArU1JzCKpT`MG+DAT@dwxdlMo3=B5*6$OdO*{LN8 zNvY|XdA3ULckfqH$V{%1*XSQL?vFu&J;D8jzb> zlBiITo0C^;Rbi_HHrEQs1_|pcDS(xfWZNo192Makpx~Tel&WB=XP}#GU}m6TW~gUq zY+`P1uA^XNU}&IkV5Dzoq-$tyWo%?+V4wg6Nh+i#(Mch>H3D2mX;thjEr=FDs+o0^GXscbn}XpVJ5hw7AF^F7L;V>=P7_pOiaoz zEwNPsx)kDt+yY-;xWReF(0~F4nSMoLfxe-hfqrf-$X{U9#U(+h2xnkbT^v$bkg6Y) zTAW{6lnjiIG-a4(VA$ce2&53`8Y};zOkkuW=D6f1m*%GCm3X??DgkBmQZiGl++57v z3=Pdq49txT%q$EIEzKQGot;e$TwTrGOw27@U}j*`>tbR7)amNv=m-pXLl-wES0h(P zS7Qqo7b9agXID3vUeCPZlEl2^RG7V)KzpHj9r5b5axO|uEXgkl$xAZ!`CVki~X)Q=>r|34@w+Ji3KJEOo1RKJm~{D@XV8%2h1@=z^oD1tz^o;z$E4A;uunK>rM22 z@52rvb)Lb3S_iE}?=ETb>(gsm^x(;ZXY&Xf`(F?sTAd&h}c zQbL!HR4a1KjRiut>v#_{oZj@u z<{?u`)peL=HSeW zizeE9vhVL$zbRGqvz(_}u^Sr!|&i>hKq*VMzbM1q) zeeSW{YA#0Bz8xltliW`zgH)=tv`i2Xa&juN+HBp&ye;?l?RQms=Y^yc+AF`SaqSb- zh&iF$E&2b&Ye~Bq9gONd-&SSMs&5Q^94b>MVtgrSV=ue)RBMY}Ya15&ctkp>zL(|` zk3X_-+Wbig>fgA!XZPGn4qfj&dG_9yI|?S4vYwE1{ZhJiWw6D&e+Srpe>n8@fp6HS z6TFs6;ZJ0C*}lBEFVdQ&MBb@0P9mI A0{{R3 diff --git a/java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png b/java/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png old mode 100755 new mode 100644 index d09bd3db3ce5421d83cb2b1f29bbba78847a6915..597eb15b2c6ca1d1cea1f8806fa22cb6dbaff31f GIT binary patch delta 768 zcmV+b1ONQ22E7K5Nq^r-L_t(|+U%M^uJRxd$EURmHM%n1!i90^X}pQ?CZ5KnapB4X zxN)gbW7NKkFVk-x0)>7B6(J$iCN1;hKLeBzz)#6tcaZq%$Tdd_fs}AS@;v`|2xN#c z5@RHSdMS8s++-|qRc)Ui#3B(l)haeDa8;wQ*gti&G*5z_} z7){1ptc>V-7&^?wb({NdA zY84?VMTJ}kI|VxLlfbMy^ae`AO-V(nTw<6i+{(qC2;;#DA(T&oPqCrH_JU+P*W zFLwo^`~6+6WeVgQM6u5@TSwk0Mywaa;1qec1+kJM?|&HVx;~B8kt!=~T_7rZEMg=# zs7_I=`qX?O=E~}J_xoGX=p^~qCtmA7!akr=Z4X|tMKRr~gg+W%oM77d<(&0n+3!+X1*NTW|zyCe`>ON$Amoi(@D!%Ju+O5U4 zDA~fVd4D>LpT)W;lyc)$w95*F4w5lr#79YY23v;)bfWJ-V^SVLE z77k>!MWGSkK1-eW0zn(HEGs~)Pf@UtJ8}QStd*Eeas|SbKo~x-vd5$#*XtDyhXb6? zXE+{@McR#8AB8}uZMWOdY&N0O>6k0B*=!yU?|Jw82MABO`ASdoKMY`tAl+^kw%e`z zId)`Gl;Lm)lgR{Ht=1m}eC@NuX_pi_olY>H&tbJ%$<8dEK|Zj=f6zsc2vPmw+TD({J*dE_&tkT6#e6BftPO{_>MoFG*Vf0000L2Ww# delta 751 zcmV z#-+xeMB!uj-f6}{X?gQfpwOg28(`*PerW3mV5dc83-D|SDx1RxM_LEcfpj4GEszJ6 z%O$MWYgjB6-}y6&M7NTLJWq7q_WM0-HXGROcKPY|cs#;%I)4=khhdoXDnWeTPdbfX zE*F^1W?!eLEHar)gz}%yCljP>7!JWfdc9t9L>;xR^?JP$#qkEHa2AYBi*N|ifvm$l zKghZXUO;idLHKyt5J@JA73L3*k83RwUj<>TJSmKy2}Zb656!B3Zf^gUBb#Cbj)`&yr^pBXzP!5xLF;d#-EM z4J6OC++88c0bVqFl$n0p86&1ZRe{KBc=uyO^#ZI*)_+pT?_8@fuBCG?+ZNHy^%^(V zQpwg%QHoC9$^cR6)xIf8qg|`1Aa1AMtnXFMeobblnnt$L5Rzp$!$U#rM=srwd@t8?Vv zxorfxPJa(Ah^(|+ZbX$sr3Y^;OZ6bLL&5B}OB*iklhDt9slq1q@q z87V6UC@p!;?yM@Ey@O`=r($LoZ?V^4r h(M>{|qVGQe1^|pVY=j6pbcg@|002ovPDHLkV1oW&W}^TA diff --git a/java/res/drawable-hdpi/keyboard_key_feedback_background.9.png b/java/res/drawable-hdpi/keyboard_key_feedback_background.9.png old mode 100755 new mode 100644 index 1dd1d0f20bb1b55d5318b929a217943c47585ea7..92b4788543592c913a3ba154a9f8cc075a3d2834 GIT binary patch delta 1117 zcmV-j1fu((36}|wNq;#>L_t(|+U%UoP8%^0$Gu;CNUf@%9-<=k!aH#36Yv&!l1lB9 zaISjjjZ3es#6uu)p^B;slqMvb^{!oe<$oJB+1KU|D%Rzx~hn13NMEr$}So zl+>fPM9i}iGb(P%kx~*7E#W9y9##hj2SkX%ir_pR9Edk6-G7xcPSCcfLbY4ekh zb3Ps&9ep}EIbnx~hu-&aIufp~u8z;n&WmSybp^mM5FcxU`r`c~CFZpr~D2xR~A@{$dQLzW~-{ZOBa zeu-68v3|c_w|^b{002#pQU@>*%1^aSMxznCzP=7Bx$f`pW1oew8qzXAt~m$5)c5N* zq2(G%&!*FbZZq<^gsAJ3kdbOIm=qos(p1B0FZg^1XqkFaN7VqBoh=x?U?0jR^{j#e z>PeL8%)7e<%GpKZpUU{xI_E%0CB`)Iy%1;cR$KRsT7N3zmtcz*+N6teAgnTg6S#7; z58PPE8W!1HbI!JfRc?HW*O@-xoCE3!9ZqI^Nsxb?;lxNi+tQUM$gil&tUN;YADqAo zh7&cZ$3;1Ic!jPUJDk=^$PefS4u`E$OqcbXyUGHGvl7ZWi(R1)0$U}g$B=1gVdcCO zL4}kf34hLG!;!4z4hK>W!D*gbP(mi<5F8rk_z+e!eW0+Sup;G9Z$)86VMWT>X63wu zu?{KcrRSW^$^l2|P{@OqA5mCQ&LKDihu~~OR~|wyr#F&od#+jegmeB%?_k#!0vvrX zq$mpg>)$60tFkP=Pp8xRP)I06w{G1FrI%&dhg6k7_>`*MKPHpO zSJvWSzl(FQff=^J3-yq1>hq_vx60lqd#y|#OVQg{H!Uf>`FgHwrfjTir0kEf-`EG{ z@C^v50~idbLZ&x37svpL4{!?0N~`VC@~t%-X{iQ7nIp?lJ(WjrW~Obptr(K9eC!lf z0)N5b=D{G_TLeQtc*i3+xoO|6Y3tlv=Ln8iH>@O53^xx2FsT*iJ01)y1$u$HjS~bY zXZL3ws#ST%1&*-7DYwAD^<8$q0eaKQDJ^x6%_oEzw?b=eINVe`wZP;C4D?h!D5pYs z1_PQ}xks#D{YaC3*@vw`6n}$ zppe=m9EN%%jubyfVO1b7osTgxq#XP0aMXY je51|_d(R2yp8x{@b5R_L5m9My00000NkvXXu0mjfJ_!`{ delta 1126 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 diff --git a/java/res/drawable-hdpi/keyboard_suggest_strip_divider.png b/java/res/drawable-hdpi/keyboard_suggest_strip_divider.png old mode 100755 new mode 100644 index 8cc85b7f5fae8f0835e26adb9c0fe6a79b08eb2b..7ca3e6131b03adfd1b2d2fa7a29ce314d086a981 GIT binary patch delta 320 zcmdnU{)K&lCu7=1FLlPrvlvq*XEADK6!`jD`4?rTXXYj5xa237=BDPAc)HjsRpb`v zrDUd9nORy`xEfiw88{i4n^_ndI=Z>JSQr}`m|9x8n!B1iD=7d~0?ojt*U8Pv!qmdj z+0n_+aPmDSvB^42Qan&WC%E7rM*Yc)ne=0v%$!XeU7U>EjB(jiToRO;W|cyQD<|tQ zJ30KD$GwYzfkDO7#WAGfR??sU|LvJM4EXrin!CHXJHF2EWaM&_4B?4uU|?p@n&Wld T$uZXosGh;o)z4*}Q$iB}cxqoH delta 265 zcmeyuzL9-`C!^9vFLlPrcNmo>XEA0^-o>Olxtd8@!NtVF(A>n;)zQ(&z|hde&B@is z)zQ`1!o|hN*v;A1ZL%Gc3`~(5PDRg{3}T=rIpb2Kq)=QEl$vIhlAm0fo0?bR>0+x? zkz1gbl9^%!)$4*w@8lw8C&%eE(fkYy462?kjv*DdlK%YvZ_mtOaB1Gb2ag^xCH+lL kYG?{%t96n)$G~C0(4FaZJ+-*~HBbYCr>mdKI;Vst0Hi`sy#N3J diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_language_arrows_left.png b/java/res/drawable-hdpi/sym_keyboard_feedback_language_arrows_left.png index c7638bff116129cce866b02aa74827726ae2f0fb..889477cfb0d6b32d956d65b05df4c0113f462911 100644 GIT binary patch literal 1275 zcmeAS@N?(olHy`uVBq!ia0vp^GC-`x!3HF+zxf>xq$EpRBT9nv(@M${i&7aJQ}UBi z6+Ckj(^G>|6H_V+Po~;1Ffc1+hD4M^`1)8S=jZArg4F0$^BXQ!4Z zB&DWj=GiK}-@RW+Av48RDcsc8z_-9TH6zobswg$M$}c3jDm&RSMakYy!KT6rXh3di zNuokUZcbjYRfVk**jy_h8zii+qySb@l5ML5aa4qFfP!;=QL2Keo`G(%fti7VnW3Jc zv5C34xsHO7fuVuEfswwUk*=Y+m9dePfq?=PC;@FNN=dT{a&d#&1?1T(Wt5Z@Sn2DR zmzV368|&p4rRy77T3Uk4Ff!5ws?aU2%qvN((9J7WhMC}!TAW;zSx}OhpQivaF)=B> zw8T~k=u(Imatq+b<`qMO2^e7d6^RAATTyQcrg{TUQ+_+4w#2%hX>s>#m>M40{fLOvO!u0Zw2Xh*gqL$quK#lC zOOWl)AJL}zNnSHHt=_t#WtuYsYXAt{W}cL#m&xq0>uz59&X`qi_I}p*u${GIS>~qH z$n!j>?w<6uQki_x<<{FW|G#zfSsWXzwtb0i-y6rjEYqv`AVZ*tqNmW5)JX43cNj}! zk5}zgTeV7w$N5R+J)dc(Hue0h={uXo>>60GGbXG3u7wO=yF{@Lep$Ew{ISP{Z+7YV-)vty$$s0f$gA5vi`iu?zPkS( mLm?yg0tT)J{~rZ6Ffy$Bytwq5f}jYfIP!G$b6Mw<&;$Tx?8sLD delta 258 zcmV+d0sa2_3Bm%9NPht2NklKd#WD-V+P{uLtIixnZuDGv+krIOc%aW9)cM_bxkN zE&&A;P(T5hz+o6%SirvTAw7w=>w2|ioCFCVh`_DN z=jiGKwAMmZRqo?p*%nGEHq3!pmO)Vz5QZV&#*gC|%CdwsP5CBG5ClNo5*$Sl-)JLj z%Wfw}+g9CrbB_9L+q(DshA%$q`*WTuNfP-13n-v~%j+e;00@+8L@gf<@c;k-07*qo IM6N<$f;cdD^Z)<= diff --git a/java/res/drawable-hdpi/sym_keyboard_feedback_language_arrows_right.png b/java/res/drawable-hdpi/sym_keyboard_feedback_language_arrows_right.png index 7acb07c86fb4704019cb0a72cca130537fd45fb0..b0f6d7feba34837e4c2a097cef541ef3ead6bf71 100644 GIT binary patch literal 1329 zcmeAS@N?(olHy`uVBq!ia0vp^GC-`x!3HF+zxf>xq$EpRBT9nv(@M${i&7aJQ}UBi z6+Ckj(^G>|6H_V+Po~;1FfgZOhD4M^`1)8S=jZArg4F0$^BXQ!4Z zB&DWj=GiK}-@RW+Av48RDcsc8z_-9TH6zobswg$M$}c3jDm&RSMakYy!KT6rXh3di zNuokUZcbjYRfVk**jy_h8zii+qySb@l5ML5aa4qFfP!;=QL2Keo`G(%fti7VnW3Jc zv5C34xsHO7fuVuEfswwUk*=Y+m9dePfq?=PC;@FNN=dT{a&d#&1?1T(Wt5Z@Sn2DR zmzV368|&p4rRy77T3Uk4Ff!5ws?aU2%qvN((9J7WhMC}!TAW;zSx}OhpQivaF)=B> zw8T~k=u(ImatnNY;RfdwLjwvJWcn3}1^R}12Ku?VAb){X7ncO3BAkI$b#X{#L8^XG zYH@yPQ8F+-(v)GEfnkT=B9KC$Ypnc>GJ%njnB$V4T$-DjSK{ens|1wMOUX>Jar6!i-7lq{K=fF}xKt_H^ zesM;Afr4|ese*4}a%LWg4~ia$Z(UN0GRsm^+=}vZ6~N(Zm5IfE!v2QnO(7@D^ns4i z2PF=q!~zonra%xAp7ennc;-pX1Ll|_VAfc1@XaFz2F65B7srr_TW_Y>b~QVQG~8do zd9us9ELEKUA)`~&-nLl3gqgxDYgnYMb=T&hlIS=JcXf ztKMztTI3+&nsD2!W6_CieD=;h`_`sLCd_&k?zLHH(ua57s|#e<`P!MK6K`(|n3h_; z$$;m!MW5ir`y#pVn|7_+t#dbT`-5G1#Wr&9r@84n6|FMyJ^1}^)z+x3;b%>S6ZhVJ zt9AbKDV@_DPafW9`+DJ(|BGFMwbLtC-w%kYV=Pt_FM4?Qqv8RE>OWO88D;9Xg9{5QeWMOG)Vml6H0Xr#L6GyR*Byv%g1Y zcXxMZXL}bc6e$*q35DLlgMt^4Epwv$b diff --git a/java/res/drawable-hdpi/sym_keyboard_language_arrows_right.png b/java/res/drawable-hdpi/sym_keyboard_language_arrows_right.png index 310952383efa63d251bf615ffdc514aafd27fd6e..ecf61a98e207f98b44b0dfd9c7f7f389f50de489 100644 GIT binary patch delta 479 zcmV<50U-X`3ET>>S^^9~Lohf(IWa{+LNPOwW&$t_K|?S&LOC%+K|(PzlcEB30W^~! z0w9w(1AKp1^Mk+u00E3iL_t(|+G70w|33pQ0TTm_!KekJ7ElgYh*ikQ$T-A(00mq? z%niiff%q#B|EIPOq_%C_wpvL^$qC370b*u?IzVL+F&GN0u3fwK|IC>)Z^FaFYk+(e zAZDkg1rDc9o%(ec@@Z{GaV-QB$zC}sx4e7Ju?gXBp5_wOIW_wU~se*XN)?CRf*HMIyDWSmq>rhotbW%%~( z8v`>lGjB;rN%6F4)28zA@u>o(*r=8dK=A{zdC?M_VmE>K6SAu* z$!O}pBzeKWz#s+4Rv?&*L8UOU%@$~J4Js?>c%g;eXHdSQwgn@w%48h!O-FzL0|4As V{_?!>Jr4i?002ovPDHLkV1j-X>JR_` delta 348 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 A`2YX_ delta 1404 zcmV-?1%vv{5wi=BNPh)YNklY;^qx-~Z|iwbpMG^A`k;a3rs?02{;6p{RsgMaQb7v32|XPaKvmj zKU!T~eJVRUJHu+VCQVFCT*=GJYciQk@pE%?ZGS?pLB__$uC}za{Ni%CuHd@`(Uvn1 zp+FJ_qyQ&@Cx3wKfq{YVygOuZaq;i=_V%v^2M53R`blPH=9~EDaefCp2_$n)TG0o8 z(QA;25Hhxkii&fPERLU?oSfb{C?+Q6a9LT|`GSIi!ky1IH#aw;qoa*9GdA%y#^ehj z8?+K0tm7U8jswrNwY7cecDrxif{c!i{>XcOP4KzhZh!yP|2fCPdUoG^b8~Ym=FA0- z0mfjegaycKZEgL+8$jSP^YE)z;Ztv|L$t>J0})cE7?r`8jNxl8Dk^$ji#6tVS5;Mg z;&3=-p{2>r&d!UP`2rFV5fLuy!g4ypUQFe4;?vx<$K%;j+i_P{SGSnJ2AlxSUWKTQ zUxHAZ7=QPSXz7^bHC0JsM8JvPO;1mMeQ0RtlG4Nr3k!cC^xvnC0gnhFEASK-?CB92zvO`TalRGjp@9}f|Dl@7bIva+h?Kg>UL z=0Hx(wIqL8l{CcNxZwG}E3u7>i;G35Gn5aFkB?u&eG5pf_>V(fbJW(>eu~8yK`{*t z4d;wT<3Xi4Wi6Lrm#`&0$+Drfa|!3uKo)n;hK)OA4f__tOwXjq_r=AwG2G%+)v)+V=3mnz*#RTB##>U2vwQ>wK z#S$ZxJ70<{Ta|ojsIRZ@Yps$&LBIXERQ*J)Cf^`hItu%K7AW7WuCA`l%*Dll*nbkcwZ_N$dLfno?>-A#Va_dn7{AwKw%r$1R#v_j zNcF)8!(SYkzLpeBPi+*_<&u<^bM93*hmgsYuGA3hQBb&$%3`y{%6z9}*e{8hvV=^S z+JD(zG?gUwE@a!O)}E;Skw_C(C{10G@ApTI&|d#z>3k2!)m&0il3H3?dUYl(E$uie zc2sO^>|xZ;?Is?9u!^5adrwc#Prbdpb|!CtIp-ED(0(2^7=%!yoOJk3I}Fl~ACUHB zOAZ-U1iZfqGM@kA^us4nLPm>_Q?4Po$B* Date: Thu, 2 Sep 2010 18:07:50 +0900 Subject: [PATCH 40/58] Decrease LatinKeyboardBaseView_keyPreviewOffset. Popup will be displayed closer to each key typed. Change-Id: I863ade61cb4688214d90b24240743ee7fe16e491 --- java/res/values/styles.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml index 24fee02d8..16478c883 100644 --- a/java/res/values/styles.xml +++ b/java/res/values/styles.xml @@ -22,7 +22,7 @@ @dimen/key_text_size #FFFFFFFF @layout/keyboard_key_preview - -12dip + 5dip 80dip 14sp @layout/keyboard_popup_keyboard From 3d4123fabb51a0c929401d98fca496759a5aa0d6 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 2 Sep 2010 20:28:31 +0900 Subject: [PATCH 41/58] Add PointerTracker argument to long press related methods This change also adds debugging log to PointerTracker class Bug: 2959169 Change-Id: Ie6cf67681180467bd8ba35d0205ce6727b7684a2 --- .../latin/LatinKeyboardBaseView.java | 19 ++++++------ .../inputmethod/latin/PointerTracker.java | 29 +++++++++++++++---- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index 30042d8a1..14b8143a9 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -254,9 +254,11 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, startKeyRepeatTimer(REPEAT_INTERVAL, msg.arg1, tracker); break; } - case MSG_LONGPRESS_KEY: - openPopupIfRequired(msg.arg1); + case MSG_LONGPRESS_KEY: { + final PointerTracker tracker = (PointerTracker)msg.obj; + openPopupIfRequired(msg.arg1, tracker); break; + } } } @@ -299,9 +301,9 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, return mInKeyRepeat; } - public void startLongPressTimer(int keyIndex, long delay) { + public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker) { removeMessages(MSG_LONGPRESS_KEY); - sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, keyIndex, 0), delay); + sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, keyIndex, 0, tracker), delay); } public void cancelLongPressTimer() { @@ -962,16 +964,15 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, key.x + key.width + getPaddingLeft(), key.y + key.height + getPaddingTop()); } - private boolean openPopupIfRequired(int keyIndex) { + private boolean openPopupIfRequired(int keyIndex, PointerTracker tracker) { // Check if we have a popup layout specified first. if (mPopupLayout == 0) { return false; } - if (keyIndex < 0 || keyIndex >= mKeys.length) { - return false; - } - Key popupKey = mKeys[keyIndex]; + Key popupKey = tracker.getKey(keyIndex); + if (popupKey == null) + return false; boolean result = onLongPress(popupKey); if (result) { dismissKeyPreview(); diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java index 10f51bd48..f5f2c11ff 100644 --- a/java/src/com/android/inputmethod/latin/PointerTracker.java +++ b/java/src/com/android/inputmethod/latin/PointerTracker.java @@ -27,6 +27,7 @@ import android.view.ViewConfiguration; public class PointerTracker { private static final String TAG = "PointerTracker"; private static final boolean DEBUG = false; + private static final boolean DEBUG_MOVE = true && DEBUG; public interface UIProxy { public void invalidateKey(Key key); @@ -155,12 +156,12 @@ public class PointerTracker { repeatKey(keyIndex); mHandler.startKeyRepeatTimer(REPEAT_START_DELAY, keyIndex, this); } - mHandler.startLongPressTimer(keyIndex, LONGPRESS_TIMEOUT); + mHandler.startLongPressTimer(LONGPRESS_TIMEOUT, keyIndex, this); } showKeyPreviewAndUpdateKey(keyIndex); updateMoveDebouncing(touchX, touchY); if (DEBUG) - Log.d(TAG, "onDownEvent: [" + mPointerId + "] modifier=" + isModifier()); + debugLog("onDownEvent:", touchX, touchY); } public void onMoveEvent(int touchX, int touchY, long eventTime) { @@ -169,7 +170,7 @@ public class PointerTracker { if (mCurrentKey == NOT_A_KEY) { updateTimeDebouncing(eventTime); mCurrentKey = keyIndex; - mHandler.startLongPressTimer(keyIndex, LONGPRESS_TIMEOUT); + mHandler.startLongPressTimer(LONGPRESS_TIMEOUT, keyIndex, this); } else if (isMinorMoveBounce(touchX, touchY, keyIndex, mCurrentKey)) { updateTimeDebouncing(eventTime); } else { @@ -177,7 +178,7 @@ public class PointerTracker { resetTimeDebouncing(eventTime, mCurrentKey); resetMoveDebouncing(); mCurrentKey = keyIndex; - mHandler.startLongPressTimer(keyIndex, LONGPRESS_TIMEOUT); + mHandler.startLongPressTimer(LONGPRESS_TIMEOUT, keyIndex, this); } } else { mHandler.cancelLongPressTimer(); @@ -190,11 +191,13 @@ public class PointerTracker { */ showKeyPreviewAndUpdateKey(isMinorTimeBounce() ? mLastKey : mCurrentKey); updateMoveDebouncing(touchX, touchY); + if (DEBUG_MOVE) + debugLog("onMoveEvent:", touchX, touchY); } public void onUpEvent(int touchX, int touchY, long eventTime) { if (DEBUG) - Log.d(TAG, "onUpEvent: [" + mPointerId + "] modifier=" + isModifier()); + debugLog("onUpEvent :", touchX, touchY); int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); boolean wasInKeyRepeat = mHandler.isInKeyRepeat(); mHandler.cancelKeyTimers(); @@ -222,7 +225,7 @@ public class PointerTracker { public void onCancelEvent(int touchX, int touchY, long eventTime) { if (DEBUG) - Log.d(TAG, "onCancelEvent: [" + mPointerId + "]"); + debugLog("onCancelEvt:", touchX, touchY); mHandler.cancelKeyTimers(); mHandler.cancelPopupPreview(); mProxy.dismissPopupKeyboard(); @@ -412,4 +415,18 @@ public class PointerTracker { resetMultiTap(); } } + + private void debugLog(String title, int x, int y) { + Key key = getKey(mCurrentKey); + final String code; + if (key == null) { + code = "----"; + } else { + int primaryCode = key.codes[0]; + code = String.format((primaryCode < 0) ? "%4d" : "0x%02x", primaryCode); + } + Log.d(TAG, + String.format("%s [%d] %d,%d %s %s", title, mPointerId, x, y, code, + isModifier() ? "modifier" : "")); + } } \ No newline at end of file From 3b4ecdeb05eebcba65ba2f27bedbfc849321d951 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 2 Sep 2010 21:06:30 +0900 Subject: [PATCH 42/58] Add a number alternation to English popup mini keyboard This change is only for English locale. For other locales we should need specification because keyboard layout and alternations are different by locale. Bug: 2959169 Change-Id: Ib63f53ce6c30d75eff78777aa0049b05d58ce55f --- java/res/values-en/donottranslate.xml | 31 +++++++++++++++++++++++++++ java/res/values/donottranslate.xml | 10 +++++++-- java/res/xml/kbd_qwerty.xml | 21 +++++++++++++----- java/res/xml/kbd_qwerty_black.xml | 21 +++++++++++++----- 4 files changed, 71 insertions(+), 12 deletions(-) create mode 100644 java/res/values-en/donottranslate.xml diff --git a/java/res/values-en/donottranslate.xml b/java/res/values-en/donottranslate.xml new file mode 100644 index 000000000..f5692735a --- /dev/null +++ b/java/res/values-en/donottranslate.xml @@ -0,0 +1,31 @@ + + + + + èéêë3 + + ìíîï8 + + òóôõöœø9 + + ùúûü7 + + ýÿ6 + diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml index b7bfd9c3a..97b645c4a 100644 --- a/java/res/values/donottranslate.xml +++ b/java/res/values/donottranslate.xml @@ -24,16 +24,22 @@ .,!?) !?,\u0022\u0027:()-/@_ + + 1 + + 2 - + 4 - + 5 + + 0 diff --git a/java/res/xml/kbd_qwerty.xml b/java/res/xml/kbd_qwerty.xml index 0a0691dd1..0aeaf6cc7 100755 --- a/java/res/xml/kbd_qwerty.xml +++ b/java/res/xml/kbd_qwerty.xml @@ -29,18 +29,26 @@ > - - + + + android:popupCharacters="@string/alternates_for_r" + /> + android:popupCharacters="@string/alternates_for_t" + /> - + diff --git a/java/res/xml/kbd_qwerty_black.xml b/java/res/xml/kbd_qwerty_black.xml index 286547283..8b68d7500 100755 --- a/java/res/xml/kbd_qwerty_black.xml +++ b/java/res/xml/kbd_qwerty_black.xml @@ -26,18 +26,26 @@ > - - + + + android:popupCharacters="@string/alternates_for_r" + /> + android:popupCharacters="@string/alternates_for_t" + /> - + From 400046d62e22899e28efd2a62321c637c7831f81 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 2 Sep 2010 21:54:26 +0900 Subject: [PATCH 43/58] Encapsulate vertical and horizontal correction values into KeyDetector. Bug: 2959169 Change-Id: Id2b0b974fffdf6f09ee1828e957b973d2ce1c315 --- .../inputmethod/latin/KeyDetector.java | 14 ++++- .../latin/LatinKeyboardBaseView.java | 44 ++++++-------- .../inputmethod/latin/PointerTracker.java | 60 +++++++++---------- .../latin/ProximityKeyDetector.java | 8 ++- 4 files changed, 65 insertions(+), 61 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/KeyDetector.java b/java/src/com/android/inputmethod/latin/KeyDetector.java index 11d5f861d..5583e3275 100644 --- a/java/src/com/android/inputmethod/latin/KeyDetector.java +++ b/java/src/com/android/inputmethod/latin/KeyDetector.java @@ -25,12 +25,16 @@ abstract class KeyDetector { protected Keyboard mKeyboard; protected Key[] mKeys; + protected int mCorrectionX; + protected int mCorrectionY; protected boolean mProximityCorrectOn; protected int mProximityThresholdSquare; - public Key[] setKeyboard(Keyboard keyboard) { + public Key[] setKeyboard(Keyboard keyboard, float correctionX, float correctionY) { if (keyboard == null) throw new NullPointerException(); + mCorrectionX = (int)correctionX; + mCorrectionY = (int)correctionY; mKeyboard = keyboard; List keys = mKeyboard.getKeys(); Key[] array = keys.toArray(new Key[keys.size()]); @@ -38,6 +42,14 @@ abstract class KeyDetector { return array; } + protected int getTouchX(int x) { + return x + mCorrectionX; + } + + protected int getTouchY(int y) { + return y + mCorrectionY; + } + public void setProximityCorrectionEnabled(boolean enabled) { mProximityCorrectOn = enabled; } diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index 14b8143a9..48cccea92 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -165,7 +165,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, private float mShadowRadius; private Drawable mKeyBackground; private float mBackgroundDimAmount; - private int mVerticalCorrection; + private float mVerticalCorrection; private int mPreviewOffset; private int mPreviewHeight; private int mPopupLayout; @@ -541,7 +541,8 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, mHandler.cancelPopupPreview(); mKeyboard = keyboard; LatinImeLogger.onSetKeyboard(keyboard); - mKeys = mKeyDetector.setKeyboard(keyboard); + mKeys = mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(), + -getPaddingTop() + mVerticalCorrection); for (PointerTracker tracker : mPointerTrackers) { tracker.setKeyboard(mKeys, mDebounceHysteresis); } @@ -613,9 +614,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, return mSymbolColorScheme; } - public void setVerticalCorrection(int verticalOffset) { - } - public void setPopupParent(View v) { mPopupParent = v; } @@ -1070,14 +1068,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, return mMiniKeyboardOnScreen; } - private int getTouchX(float x) { - return (int)x - getPaddingLeft(); - } - - private int getTouchY(float y) { - return (int)y + mVerticalCorrection - getPaddingTop(); - } - private PointerTracker getPointerTracker(final int id) { final ArrayList pointers = mPointerTrackers; final Key[] keys = mKeys; @@ -1132,29 +1122,29 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, if (action == MotionEvent.ACTION_MOVE) { for (int index = 0; index < pointerCount; index++) { - int touchX = getTouchX(me.getX(index)); - int touchY = getTouchY(me.getY(index)); + int x = (int)me.getX(index); + int y = (int)me.getY(index); int id = me.getPointerId(index); PointerTracker tracker = getPointerTracker(id); - tracker.onMoveEvent(touchX, touchY, eventTime); + tracker.onMoveEvent(x, y, eventTime); } } else { int index = me.getActionIndex(); - int touchX = getTouchX(me.getX(index)); - int touchY = getTouchY(me.getY(index)); + int x = (int)me.getX(index); + int y = (int)me.getY(index); int id = me.getPointerId(index); PointerTracker tracker = getPointerTracker(id); switch (action) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_POINTER_DOWN: - onDownEvent(tracker, touchX, touchY, eventTime); + onDownEvent(tracker, x, y, eventTime); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: - onUpEvent(tracker, touchX, touchY, eventTime); + onUpEvent(tracker, x, y, eventTime); break; case MotionEvent.ACTION_CANCEL: - onCancelEvent(tracker, touchX, touchY, eventTime); + onCancelEvent(tracker, x, y, eventTime); break; } } @@ -1162,12 +1152,12 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, return true; } - private void onDownEvent(PointerTracker tracker, int touchX, int touchY, long eventTime) { - tracker.onDownEvent(touchX, touchY, eventTime); + private void onDownEvent(PointerTracker tracker, int x, int y, long eventTime) { + tracker.onDownEvent(x, y, eventTime); mPointerQueue.add(tracker); } - private void onUpEvent(PointerTracker tracker, int touchX, int touchY, long eventTime) { + private void onUpEvent(PointerTracker tracker, int x, int y, long eventTime) { int index = mPointerQueue.lastIndexOf(tracker); if (index >= 0) { mPointerQueue.releasePointersOlderThan(tracker, eventTime); @@ -1175,12 +1165,12 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, Log.w(TAG, "onUpEvent: corresponding down event not found for pointer " + tracker.mPointerId); } - tracker.onUpEvent(touchX, touchY, eventTime); + tracker.onUpEvent(x, y, eventTime); mPointerQueue.remove(tracker); } - private void onCancelEvent(PointerTracker tracker, int touchX, int touchY, long eventTime) { - tracker.onCancelEvent(touchX, touchY, eventTime); + private void onCancelEvent(PointerTracker tracker, int x, int y, long eventTime) { + tracker.onCancelEvent(x, y, eventTime); mPointerQueue.remove(tracker); } diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java index f5f2c11ff..2a7a31793 100644 --- a/java/src/com/android/inputmethod/latin/PointerTracker.java +++ b/java/src/com/android/inputmethod/latin/PointerTracker.java @@ -139,12 +139,12 @@ public class PointerTracker { } } - public void onDownEvent(int touchX, int touchY, long eventTime) { - int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); + public void onDownEvent(int x, int y, long eventTime) { + int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null); mCurrentKey = keyIndex; - mStartX = touchX; - mStartY = touchY; - startMoveDebouncing(touchX, touchY); + mStartX = x; + mStartY = y; + startMoveDebouncing(x, y); startTimeDebouncing(eventTime); checkMultiTap(eventTime, keyIndex); if (mListener != null) { @@ -159,19 +159,19 @@ public class PointerTracker { mHandler.startLongPressTimer(LONGPRESS_TIMEOUT, keyIndex, this); } showKeyPreviewAndUpdateKey(keyIndex); - updateMoveDebouncing(touchX, touchY); + updateMoveDebouncing(x, y); if (DEBUG) - debugLog("onDownEvent:", touchX, touchY); + debugLog("onDownEvent:", x, y); } - public void onMoveEvent(int touchX, int touchY, long eventTime) { - int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); + public void onMoveEvent(int x, int y, long eventTime) { + int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null); if (isValidKeyIndex(keyIndex)) { if (mCurrentKey == NOT_A_KEY) { updateTimeDebouncing(eventTime); mCurrentKey = keyIndex; mHandler.startLongPressTimer(LONGPRESS_TIMEOUT, keyIndex, this); - } else if (isMinorMoveBounce(touchX, touchY, keyIndex, mCurrentKey)) { + } else if (isMinorMoveBounce(x, y, keyIndex, mCurrentKey)) { updateTimeDebouncing(eventTime); } else { resetMultiTap(); @@ -190,19 +190,19 @@ public class PointerTracker { * should not be showed as popup preview. */ showKeyPreviewAndUpdateKey(isMinorTimeBounce() ? mLastKey : mCurrentKey); - updateMoveDebouncing(touchX, touchY); + updateMoveDebouncing(x, y); if (DEBUG_MOVE) - debugLog("onMoveEvent:", touchX, touchY); + debugLog("onMoveEvent:", x, y); } - public void onUpEvent(int touchX, int touchY, long eventTime) { + public void onUpEvent(int x, int y, long eventTime) { if (DEBUG) - debugLog("onUpEvent :", touchX, touchY); - int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(touchX, touchY, null); + debugLog("onUpEvent :", x, y); + int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null); boolean wasInKeyRepeat = mHandler.isInKeyRepeat(); mHandler.cancelKeyTimers(); mHandler.cancelPopupPreview(); - if (isMinorMoveBounce(touchX, touchY, keyIndex, mCurrentKey)) { + if (isMinorMoveBounce(x, y, keyIndex, mCurrentKey)) { updateTimeDebouncing(eventTime); } else { resetMultiTap(); @@ -211,21 +211,21 @@ public class PointerTracker { } if (isMinorTimeBounce()) { mCurrentKey = mLastKey; - touchX = mLastCodeX; - touchY = mLastCodeY; + x = mLastCodeX; + y = mLastCodeY; } showKeyPreviewAndUpdateKey(NOT_A_KEY); // If we're not on a repeating key (which sends on a DOWN event) if (!wasInKeyRepeat && !mProxy.isMiniKeyboardOnScreen()) { - detectAndSendKey(mCurrentKey, touchX, touchY, eventTime); + detectAndSendKey(mCurrentKey, (int)x, (int)y, eventTime); } if (isValidKeyIndex(keyIndex)) mProxy.invalidateKey(mKeys[keyIndex]); } - public void onCancelEvent(int touchX, int touchY, long eventTime) { + public void onCancelEvent(int x, int y, long eventTime) { if (DEBUG) - debugLog("onCancelEvt:", touchX, touchY); + debugLog("onCancelEvt:", x, y); mHandler.cancelKeyTimers(); mHandler.cancelPopupPreview(); mProxy.dismissPopupKeyboard(); @@ -244,6 +244,14 @@ public class PointerTracker { } } + public int getLastX() { + return mLastX; + } + + public int getLastY() { + return mLastY; + } + // These package scope methods are only for debugging purpose. /* package */ int getStartX() { return mStartX; @@ -253,14 +261,6 @@ public class PointerTracker { return mStartY; } - /* package */ int getLastX() { - return mLastX; - } - - /* package */ int getLastY() { - return mLastY; - } - private void startMoveDebouncing(int x, int y) { mLastCodeX = x; mLastCodeY = y; @@ -426,7 +426,7 @@ public class PointerTracker { code = String.format((primaryCode < 0) ? "%4d" : "0x%02x", primaryCode); } Log.d(TAG, - String.format("%s [%d] %d,%d %s %s", title, mPointerId, x, y, code, + String.format("%s [%d] %3d,%3d %s %s", title, mPointerId, x, y, code, isModifier() ? "modifier" : "")); } } \ No newline at end of file diff --git a/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java b/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java index 6ee005510..eaaed91aa 100644 --- a/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java +++ b/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java @@ -35,6 +35,8 @@ class ProximityKeyDetector extends KeyDetector { @Override public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys) { + int touchX = getTouchX(x); + int touchY = getTouchY(y); final Key[] keys = mKeys; if (keys == null) throw new IllegalStateException("keyboard isn't set"); @@ -44,18 +46,18 @@ class ProximityKeyDetector extends KeyDetector { int closestKeyDist = mProximityThresholdSquare + 1; int[] distances = mDistances; Arrays.fill(distances, Integer.MAX_VALUE); - int [] nearestKeyIndices = mKeyboard.getNearestKeys(x, y); + int [] nearestKeyIndices = mKeyboard.getNearestKeys(touchX, touchY); final int keyCount = nearestKeyIndices.length; for (int i = 0; i < keyCount; i++) { final Key key = keys[nearestKeyIndices[i]]; int dist = 0; - boolean isInside = key.isInside(x,y); + boolean isInside = key.isInside(touchX, touchY); if (isInside) { primaryIndex = nearestKeyIndices[i]; } if (((mProximityCorrectOn - && (dist = key.squaredDistanceFrom(x, y)) < mProximityThresholdSquare) + && (dist = key.squaredDistanceFrom(touchX, touchY)) < mProximityThresholdSquare) || isInside) && key.codes[0] > 32) { // Find insertion point From 0fe4c9e1a78445a27b74ae24afb292a84a893703 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 2 Sep 2010 22:23:50 +0900 Subject: [PATCH 44/58] Corresponding to TBR of Ie6cf6768 This is follow up change of Ie6cf67681180467bd8ba35d0205ce6727b7684a2 Bug: 2959169 Change-Id: I9e4cb0c9178856ddd6049f0b751b54f3ad26a266 --- java/src/com/android/inputmethod/latin/PointerTracker.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java index 2a7a31793..5b5cbe5cc 100644 --- a/java/src/com/android/inputmethod/latin/PointerTracker.java +++ b/java/src/com/android/inputmethod/latin/PointerTracker.java @@ -27,7 +27,7 @@ import android.view.ViewConfiguration; public class PointerTracker { private static final String TAG = "PointerTracker"; private static final boolean DEBUG = false; - private static final boolean DEBUG_MOVE = true && DEBUG; + private static final boolean DEBUG_MOVE = DEBUG && true; public interface UIProxy { public void invalidateKey(Key key); @@ -425,8 +425,7 @@ public class PointerTracker { int primaryCode = key.codes[0]; code = String.format((primaryCode < 0) ? "%4d" : "0x%02x", primaryCode); } - Log.d(TAG, - String.format("%s [%d] %3d,%3d %s %s", title, mPointerId, x, y, code, - isModifier() ? "modifier" : "")); + Log.d(TAG, String.format("%s [%d] %3d,%3d %s %s", title, mPointerId, x, y, code, + isModifier() ? "modifier" : "")); } } \ No newline at end of file From 72d98fab21a23a1a2b88e1da07723a8a9630272b Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 2 Sep 2010 22:36:22 +0900 Subject: [PATCH 45/58] Corresponding to TBR of Id2b0b974 This is follow up change of Id2b0b974fffdf6f09ee1828e957b973d2ce1c315 Bug: 2959169 Change-Id: Ie47db5fce7937a4d70c432ab76510d0dc3f68401 --- .../com/android/inputmethod/latin/ProximityKeyDetector.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java b/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java index eaaed91aa..408e4e147 100644 --- a/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java +++ b/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java @@ -35,8 +35,8 @@ class ProximityKeyDetector extends KeyDetector { @Override public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys) { - int touchX = getTouchX(x); - int touchY = getTouchY(y); + final int touchX = getTouchX(x); + final int touchY = getTouchY(y); final Key[] keys = mKeys; if (keys == null) throw new IllegalStateException("keyboard isn't set"); From 6bfb234f294b6ad95176f987256c85e8607d23f5 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 3 Sep 2010 00:45:26 +0900 Subject: [PATCH 46/58] Refactor KeyDetector to share more methods Bug: 2959169 Change-Id: I87060049cad6f9d6432b6c4a246c15587ae0d837 --- .../android/inputmethod/latin/KeyDetector.java | 18 ++++++++++++++++-- .../latin/ProximityKeyDetector.java | 11 +++-------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/KeyDetector.java b/java/src/com/android/inputmethod/latin/KeyDetector.java index 5583e3275..e443f272b 100644 --- a/java/src/com/android/inputmethod/latin/KeyDetector.java +++ b/java/src/com/android/inputmethod/latin/KeyDetector.java @@ -19,11 +19,12 @@ package com.android.inputmethod.latin; import android.inputmethodservice.Keyboard; import android.inputmethodservice.Keyboard.Key; +import java.util.Arrays; import java.util.List; abstract class KeyDetector { protected Keyboard mKeyboard; - protected Key[] mKeys; + private Key[] mKeys; protected int mCorrectionX; protected int mCorrectionY; @@ -50,6 +51,13 @@ abstract class KeyDetector { return y + mCorrectionY; } + protected Key[] getKeys() { + if (mKeys == null) + throw new IllegalStateException("keyboard isn't set"); + // mKeyboard is guaranteed not null at setKeybaord() method + return mKeys; + } + public void setProximityCorrectionEnabled(boolean enabled) { mProximityCorrectOn = enabled; } @@ -62,7 +70,13 @@ abstract class KeyDetector { mProximityThresholdSquare = threshold * threshold; } - abstract public int[] newCodeArray(); + public int[] newCodeArray() { + int[] codes = new int[getMaxNearbyKeys()]; + Arrays.fill(codes, LatinKeyboardBaseView.NOT_A_KEY); + return codes; + } + + abstract protected int getMaxNearbyKeys(); abstract public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys); } \ No newline at end of file diff --git a/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java b/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java index 408e4e147..d17bedb56 100644 --- a/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java +++ b/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java @@ -27,20 +27,15 @@ class ProximityKeyDetector extends KeyDetector { private int[] mDistances = new int[MAX_NEARBY_KEYS]; @Override - public int[] newCodeArray() { - int[] codes = new int[MAX_NEARBY_KEYS]; - Arrays.fill(codes, LatinKeyboardBaseView.NOT_A_KEY); - return codes; + protected int getMaxNearbyKeys() { + return MAX_NEARBY_KEYS; } @Override public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys) { + final Key[] keys = getKeys(); final int touchX = getTouchX(x); final int touchY = getTouchY(y); - final Key[] keys = mKeys; - if (keys == null) - throw new IllegalStateException("keyboard isn't set"); - // mKeyboard is guaranteed not null at setKeybaord() method int primaryIndex = LatinKeyboardBaseView.NOT_A_KEY; int closestKey = LatinKeyboardBaseView.NOT_A_KEY; int closestKeyDist = mProximityThresholdSquare + 1; From 07221a4ad11fa5ae6275c107f1f86260691bd505 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 3 Sep 2010 00:48:16 +0900 Subject: [PATCH 47/58] Support sliding pop-up mini-keyboard input TODO: - Remove close button on mini-keyboard - Dismiss mini-keyboard when finger leave the screen while no key is selected This change also renames some instance variables to have more meaningful name. Bug: 2959169 Change-Id: I9fd79116a647d7be82415c6e9e7cdaf6edcb2bf6 --- .../latin/LatinKeyboardBaseView.java | 84 ++++++++++++------- .../inputmethod/latin/PointerTracker.java | 20 ++++- 2 files changed, 74 insertions(+), 30 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index 48cccea92..a58c6e5d2 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -185,17 +185,20 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, private boolean mShowTouchPoints = true; private int mPopupPreviewX; private int mPopupPreviewY; + private int mPopupPreviewOffsetX; + private int mPopupPreviewOffsetY; private int mWindowY; // Popup mini keyboard - private PopupWindow mPopupKeyboard; + private PopupWindow mMiniKeyboardPopup; private View mMiniKeyboardContainer; private LatinKeyboardBaseView mMiniKeyboard; private boolean mMiniKeyboardOnScreen; - private View mPopupParent; - private int mMiniKeyboardOffsetX; - private int mMiniKeyboardOffsetY; + private View mMiniKeyboardParent; private Map mMiniKeyboardCache; + private int mMiniKeyboardOriginX; + private int mMiniKeyboardOriginY; + private long mMiniKeyboardPopupTime; private int[] mWindowOffset; /** Listener for {@link OnKeyboardActionListener}. */ @@ -445,10 +448,10 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, mShowPreview = false; } mPreviewPopup.setTouchable(false); - mPopupParent = this; + mMiniKeyboardParent = this; - mPopupKeyboard = new PopupWindow(context); - mPopupKeyboard.setBackgroundDrawable(null); + mMiniKeyboardPopup = new PopupWindow(context); + mMiniKeyboardPopup.setBackgroundDrawable(null); mPaint = new Paint(); mPaint.setAntiAlias(true); @@ -615,12 +618,12 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, } public void setPopupParent(View v) { - mPopupParent = v; + mMiniKeyboardParent = v; } public void setPopupOffset(int x, int y) { - mMiniKeyboardOffsetX = x; - mMiniKeyboardOffsetY = y; + mPopupPreviewOffsetX = x; + mPopupPreviewOffsetY = y; if (mPreviewPopup.isShowing()) { mPreviewPopup.dismiss(); } @@ -896,8 +899,8 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, if (mOffsetInWindow == null) { mOffsetInWindow = new int[2]; getLocationInWindow(mOffsetInWindow); - mOffsetInWindow[0] += mMiniKeyboardOffsetX; // Offset may be zero - mOffsetInWindow[1] += mMiniKeyboardOffsetY; // Offset may be zero + mOffsetInWindow[0] += mPopupPreviewOffsetX; // Offset may be zero + mOffsetInWindow[1] += mPopupPreviewOffsetY; // Offset may be zero int[] mWindowLocation = new int[2]; getLocationOnScreen(mWindowLocation); mWindowY = mWindowLocation[1]; @@ -926,7 +929,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, } else { previewPopup.setWidth(popupWidth); previewPopup.setHeight(popupHeight); - previewPopup.showAtLocation(mPopupParent, Gravity.NO_GRAVITY, + previewPopup.showAtLocation(mMiniKeyboardParent, Gravity.NO_GRAVITY, mPopupPreviewX, mPopupPreviewY); } mPreviewText.setVisibility(VISIBLE); @@ -974,6 +977,13 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, boolean result = onLongPress(popupKey); if (result) { dismissKeyPreview(); + + long eventTime = tracker.getDownTime(); + mMiniKeyboardPopupTime = eventTime; + MotionEvent downEvent = generateMiniKeyboardMotionEvent(MotionEvent.ACTION_DOWN, + tracker.getLastX(), tracker.getLastY(), eventTime); + mMiniKeyboard.onTouchEvent(downEvent); + downEvent.recycle(); } return result; } @@ -1020,7 +1030,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, mKeyboardActionListener.onRelease(primaryCode); } }); - //mInputView.setSuggest(mSuggest); + Keyboard keyboard; if (popupKey.popupCharacters != null) { keyboard = new Keyboard(getContext(), popupKeyboardId, @@ -1043,20 +1053,25 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, mWindowOffset = new int[2]; getLocationInWindow(mWindowOffset); } - int popupX = popupKey.x + getPaddingLeft(); + int popupX = popupKey.x + popupKey.width + getPaddingLeft(); int popupY = popupKey.y + getPaddingTop(); - popupX = popupX + popupKey.width - mMiniKeyboardContainer.getMeasuredWidth(); - popupY = popupY - mMiniKeyboardContainer.getMeasuredHeight(); - final int x = popupX + mMiniKeyboardContainer.getPaddingRight() + mWindowOffset[0]; - final int y = popupY + mMiniKeyboardContainer.getPaddingBottom() + mWindowOffset[1]; - mMiniKeyboard.setPopupOffset(x < 0 ? 0 : x, y); + popupX -= mMiniKeyboardContainer.getMeasuredWidth(); + popupY -= mMiniKeyboardContainer.getMeasuredHeight(); + popupX += mWindowOffset[0]; + popupY += mWindowOffset[1]; + final int x = popupX + mMiniKeyboardContainer.getPaddingRight(); + final int y = popupY + mMiniKeyboardContainer.getPaddingBottom(); + mMiniKeyboardOriginX = (x < 0 ? 0 : x) + mMiniKeyboardContainer.getPaddingLeft(); + mMiniKeyboardOriginY = y + mMiniKeyboardContainer.getPaddingTop(); + mMiniKeyboard.setPopupOffset((x < 0) ? 0 : x, y); mMiniKeyboard.setShifted(isShifted()); - mPopupKeyboard.setContentView(mMiniKeyboardContainer); - mPopupKeyboard.setWidth(mMiniKeyboardContainer.getMeasuredWidth()); - mPopupKeyboard.setHeight(mMiniKeyboardContainer.getMeasuredHeight()); - mPopupKeyboard.showAtLocation(this, Gravity.NO_GRAVITY, x, y); + mMiniKeyboardPopup.setContentView(mMiniKeyboardContainer); + mMiniKeyboardPopup.setWidth(mMiniKeyboardContainer.getMeasuredWidth()); + mMiniKeyboardPopup.setHeight(mMiniKeyboardContainer.getMeasuredHeight()); + mMiniKeyboardPopup.showAtLocation(this, Gravity.NO_GRAVITY, x, y); mMiniKeyboardOnScreen = true; - //mMiniKeyboard.onTouchEvent(getTranslatedEvent(me)); + + // TODO: down event? invalidateAllKeys(); return true; } @@ -1068,6 +1083,11 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, return mMiniKeyboardOnScreen; } + private MotionEvent generateMiniKeyboardMotionEvent(int action, int x, int y, long eventTime) { + return MotionEvent.obtain(mMiniKeyboardPopupTime, eventTime, action, + x - mMiniKeyboardOriginX, y - mMiniKeyboardOriginY, 0); + } + private PointerTracker getPointerTracker(final int id) { final ArrayList pointers = mPointerTrackers; final Key[] keys = mKeys; @@ -1105,7 +1125,11 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, // Needs to be called after the gesture detector gets a turn, as it may have // displayed the mini keyboard - if (mMiniKeyboardOnScreen && action != MotionEvent.ACTION_CANCEL) { + if (mMiniKeyboardOnScreen) { + MotionEvent translated = generateMiniKeyboardMotionEvent(action, (int)me.getX(), + (int)me.getY(), eventTime); + mMiniKeyboard.onTouchEvent(translated); + translated.recycle(); return true; } @@ -1209,15 +1233,17 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, } public void dismissPopupKeyboard() { - if (mPopupKeyboard.isShowing()) { - mPopupKeyboard.dismiss(); + if (mMiniKeyboardPopup.isShowing()) { + mMiniKeyboardPopup.dismiss(); mMiniKeyboardOnScreen = false; + mMiniKeyboardOriginX = 0; + mMiniKeyboardOriginY = 0; invalidateAllKeys(); } } public boolean handleBack() { - if (mPopupKeyboard.isShowing()) { + if (mMiniKeyboardPopup.isShowing()) { dismissPopupKeyboard(); return true; } diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java index 5b5cbe5cc..cb45e2100 100644 --- a/java/src/com/android/inputmethod/latin/PointerTracker.java +++ b/java/src/com/android/inputmethod/latin/PointerTracker.java @@ -61,6 +61,7 @@ public class PointerTracker { private int mCurrentKey = NOT_A_KEY; private int mStartX; private int mStartY; + private long mDownTime; // for move de-bouncing private int mLastCodeX; @@ -144,6 +145,7 @@ public class PointerTracker { mCurrentKey = keyIndex; mStartX = x; mStartY = y; + mDownTime = eventTime; startMoveDebouncing(x, y); startTimeDebouncing(eventTime); checkMultiTap(eventTime, keyIndex); @@ -181,7 +183,19 @@ public class PointerTracker { mHandler.startLongPressTimer(LONGPRESS_TIMEOUT, keyIndex, this); } } else { - mHandler.cancelLongPressTimer(); + if (mCurrentKey != NOT_A_KEY) { + updateTimeDebouncing(eventTime); + mCurrentKey = keyIndex; + mHandler.cancelLongPressTimer(); + } else if (isMinorMoveBounce(x, y, keyIndex, mCurrentKey)) { + updateTimeDebouncing(eventTime); + } else { + resetMultiTap(); + resetTimeDebouncing(eventTime, mCurrentKey); + resetMoveDebouncing(); + mCurrentKey = keyIndex; + mHandler.cancelLongPressTimer(); + } } /* * While time debouncing is in effect, mCurrentKey holds the new key and this tracker @@ -252,6 +266,10 @@ public class PointerTracker { return mLastY; } + public long getDownTime() { + return mDownTime; + } + // These package scope methods are only for debugging purpose. /* package */ int getStartX() { return mStartX; From fe72f135b855cbbebe2c1a00650a58736370693c Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Thu, 2 Sep 2010 20:42:28 +0900 Subject: [PATCH 48/58] Remove close button from mini keyboard Bug: 2959169 Change-Id: I9c78f9417aaa448b8b23596bc3e748fe99085393 --- java/res/drawable-hdpi/btn_close_normal.png | Bin 1884 -> 0 bytes java/res/drawable-hdpi/btn_close_pressed.png | Bin 2737 -> 0 bytes java/res/drawable-hdpi/btn_close_selected.png | Bin 2807 -> 0 bytes java/res/drawable-mdpi/btn_close_normal.png | Bin 1259 -> 0 bytes java/res/drawable-mdpi/btn_close_pressed.png | Bin 1726 -> 0 bytes java/res/drawable-mdpi/btn_close_selected.png | Bin 1716 -> 0 bytes java/res/drawable/btn_close.xml | 27 ------------------ java/res/layout/input_gingerbread_popup.xml | 9 ------ java/res/layout/input_stone_popup.xml | 9 ------ java/res/layout/keyboard_popup_keyboard.xml | 9 ------ .../latin/LatinKeyboardBaseView.java | 13 +-------- 11 files changed, 1 insertion(+), 66 deletions(-) delete mode 100644 java/res/drawable-hdpi/btn_close_normal.png delete mode 100644 java/res/drawable-hdpi/btn_close_pressed.png delete mode 100644 java/res/drawable-hdpi/btn_close_selected.png delete mode 100644 java/res/drawable-mdpi/btn_close_normal.png delete mode 100644 java/res/drawable-mdpi/btn_close_pressed.png delete mode 100644 java/res/drawable-mdpi/btn_close_selected.png delete mode 100644 java/res/drawable/btn_close.xml diff --git a/java/res/drawable-hdpi/btn_close_normal.png b/java/res/drawable-hdpi/btn_close_normal.png deleted file mode 100644 index 38b49f1a392cba9f79efc7b1815883c6a9b183b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1884 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 diff --git a/java/res/drawable-hdpi/btn_close_selected.png b/java/res/drawable-hdpi/btn_close_selected.png deleted file mode 100644 index 870c670f72364b0bb8a013590264b677c5218e34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2807 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 ULR7(SfdBvi07*qoM6N<$g69e{_5c6? diff --git a/java/res/drawable-mdpi/btn_close_selected.png b/java/res/drawable-mdpi/btn_close_selected.png deleted file mode 100644 index f2bf91a2d716935b05298c513c69457691f93293..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1716 zcmV;l221&gP)BS~}H|cX9`p}0y^`U=2Yf6)*eKM&DDvd_50cmQ} zTJT!1f+!#eg0RBw%$)wt%q;A(vujMC=|d-cIkRWZoZn}D=XZYR%rGGY{yz#F%%iT7 zR7YAtDp^9?mr1usgN1u&qbkAG;Unv10C zUO>_#d-}fJ|4B_ePz%!nEX%nf7I{1rI#E^hkInSe9y$Iw)tn>^$V)tT4A>qLO9-SYfX2~KhI%(< zu@GokrJkz5Yzi=3prt${ki}7{YZcPA7Z4Xll3@NNAVEMN8>-0SSO6qpk{Lkk2@x%x zBAes`!jpg&dT8G0u|GI&J`i}lUSL~|S8Bg|&gGZEdn34=(4qPTzWH+oij}~Y<+GkJor3|K?u$SVtLV5lW6$y<>k{(;Ee}f} zH0qn%zf~_FMS5s1j%*K!IiOjs8k?$BX!JzgcY)?^3sx$LrsXqPFc*h{Xd5ZU`bt0I zAq~~VD*n2!(nF4C06DWvFac)RK#I4A2*y^*1a}HlScZw_s}U+K zG*vpD>KqQ>+-M1E;v7*QWn@Yp@qmJr%c2C|pFL{QLj(jPzlT(dhFTB{NW#pH+0E-} z(B5?$6O)hZ-_Ml#VG>O9wFpv4K@ZIE^H>S0V+5lym`Nwb0(uDVHr2tp)|~~!$q#8b?6GJA{-H)lGS8zGKKat-ALA(*jipVac8XEp0kY08)f8+JRq{@ z7*=uWUH}zgAgEZB)U(&T>M*1Anc>(Cjdm{rTPsX3;SFZbGFE8mNZWS7<|y3r_8}E5 z13pxQ1VYr>FdcuF#A9~(V9ZH=E2E4OJ;T>GIOI#jwkj)U|bs z%T$dT`W$grvW{ygFY+NsIm0BknY3+)#9}z`S|eCbE7hbN-E76%uQnoH8nfHTw$(Iz zrBT1#htpTO-?X&6K&ns!^glp11gVKDO{Y@Ffw%TSqx@o$ccbxg9C~9rlv{0NlH!Di z9LaT{w+;JuZ%0XKx!qRv={Wk{KD!U6FQ;GIhO{MZ=9^_q4ceP;Mj1;mD`Q#+L`N>; z{lkawaOyEiLn@S>b97mwKc2fe`@0u4cXbUq;#`cdT-k z>VAM&s^hHOhLg^a?iUIOO7 - - - - - - - - - - diff --git a/java/res/layout/input_gingerbread_popup.xml b/java/res/layout/input_gingerbread_popup.xml index 0f0f080b5..0cc953edf 100755 --- a/java/res/layout/input_gingerbread_popup.xml +++ b/java/res/layout/input_gingerbread_popup.xml @@ -36,13 +36,4 @@ latin:keyBackground="@drawable/btn_keyboard_key_gingerbread" latin:popupLayout="@layout/input_gingerbread_popup" /> - diff --git a/java/res/layout/input_stone_popup.xml b/java/res/layout/input_stone_popup.xml index 1efa56c5e..f159625f7 100755 --- a/java/res/layout/input_stone_popup.xml +++ b/java/res/layout/input_stone_popup.xml @@ -38,13 +38,4 @@ latin:shadowColor="@color/latinkeyboard_key_color_white" latin:popupLayout="@layout/input_stone_popup" /> - diff --git a/java/res/layout/keyboard_popup_keyboard.xml b/java/res/layout/keyboard_popup_keyboard.xml index 0b0046a49..6d3985065 100644 --- a/java/res/layout/keyboard_popup_keyboard.xml +++ b/java/res/layout/keyboard_popup_keyboard.xml @@ -36,13 +36,4 @@ latin:keyPreviewLayout="@layout/keyboard_key_preview" latin:popupLayout="@layout/keyboard_popup_keyboard" /> - diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index a58c6e5d2..ab1789ffe 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -62,8 +62,7 @@ import java.util.Map; * @attr ref R.styleable#LatinKeyboardBaseView_verticalCorrection * @attr ref R.styleable#LatinKeyboardBaseView_popupLayout */ -public class LatinKeyboardBaseView extends View implements View.OnClickListener, - PointerTracker.UIProxy { +public class LatinKeyboardBaseView extends View implements PointerTracker.UIProxy { private static final String TAG = "LatinKeyboardBaseView"; private static final boolean DEBUG = false; @@ -646,14 +645,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, return mKeyDetector.isProximityCorrectionEnabled(); } - /** - * Popup keyboard close button clicked. - * @hide - */ - public void onClick(View v) { - dismissPopupKeyboard(); - } - protected CharSequence adjustCase(CharSequence label) { if (mKeyboard.isShifted() && label != null && label.length() < 3 && Character.isLowerCase(label.charAt(0))) { @@ -1006,8 +997,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener, mMiniKeyboardContainer = inflater.inflate(mPopupLayout, null); mMiniKeyboard = (LatinKeyboardBaseView) mMiniKeyboardContainer.findViewById( R.id.LatinKeyboardBaseView); - View closeButton = mMiniKeyboardContainer.findViewById(R.id.closeButton); - if (closeButton != null) closeButton.setOnClickListener(this); mMiniKeyboard.setOnKeyboardActionListener(new OnKeyboardActionListener() { public void onKey(int primaryCode, int[] keyCodes, int x, int y) { mKeyboardActionListener.onKey(primaryCode, keyCodes, x, y); From 7083b7486ec62ab06818e1bfbd0694d5f3563473 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 3 Sep 2010 05:28:43 +0900 Subject: [PATCH 49/58] Propagate preview enable attribute to mini-keyboard Bug: 2959169 Change-Id: Iea1bec44baf3344d9f91280bd2b8f28476cbcf51 --- .../src/com/android/inputmethod/latin/LatinKeyboardBaseView.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index ab1789ffe..805bc2d6b 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -1054,6 +1054,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx mMiniKeyboardOriginY = y + mMiniKeyboardContainer.getPaddingTop(); mMiniKeyboard.setPopupOffset((x < 0) ? 0 : x, y); mMiniKeyboard.setShifted(isShifted()); + mMiniKeyboard.setPreviewEnabled(isPreviewEnabled()); mMiniKeyboardPopup.setContentView(mMiniKeyboardContainer); mMiniKeyboardPopup.setWidth(mMiniKeyboardContainer.getMeasuredWidth()); mMiniKeyboardPopup.setHeight(mMiniKeyboardContainer.getMeasuredHeight()); From c5d33b16521de56ad01b0b6308217efb009078b7 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 3 Sep 2010 12:51:03 +0900 Subject: [PATCH 50/58] Fix NPE in LatinKeyboardBaseView This change also refactors some mini-keyboard related methods in LatinKeyboardBaseView and PointerTracker class. Bug: 2973236 Change-Id: I3190fe89ea3ac3c6d351ed4b6d77de98a0aa65db --- .../latin/LatinKeyboardBaseView.java | 67 +++++++++---------- .../inputmethod/latin/PointerTracker.java | 14 ++-- 2 files changed, 39 insertions(+), 42 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index 805bc2d6b..ba901eddb 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -190,9 +190,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx // Popup mini keyboard private PopupWindow mMiniKeyboardPopup; - private View mMiniKeyboardContainer; private LatinKeyboardBaseView mMiniKeyboard; - private boolean mMiniKeyboardOnScreen; private View mMiniKeyboardParent; private Map mMiniKeyboardCache; private int mMiniKeyboardOriginX; @@ -799,7 +797,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx } mInvalidatedKey = null; // Overlay a dark rectangle to dim the keyboard - if (mMiniKeyboardOnScreen) { + if (mMiniKeyboard != null) { paint.setColor((int) (mBackgroundDimAmount * 0xFF) << 24); canvas.drawRect(0, 0, getWidth(), getHeight(), paint); } @@ -967,14 +965,8 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx return false; boolean result = onLongPress(popupKey); if (result) { + tracker.setAlreadyProcessed(); dismissKeyPreview(); - - long eventTime = tracker.getDownTime(); - mMiniKeyboardPopupTime = eventTime; - MotionEvent downEvent = generateMiniKeyboardMotionEvent(MotionEvent.ACTION_DOWN, - tracker.getLastX(), tracker.getLastY(), eventTime); - mMiniKeyboard.onTouchEvent(downEvent); - downEvent.recycle(); } return result; } @@ -990,12 +982,12 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx int popupKeyboardId = popupKey.popupResId; if (popupKeyboardId != 0) { - mMiniKeyboardContainer = mMiniKeyboardCache.get(popupKey); - if (mMiniKeyboardContainer == null) { + View container = mMiniKeyboardCache.get(popupKey); + if (container == null) { LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); - mMiniKeyboardContainer = inflater.inflate(mPopupLayout, null); - mMiniKeyboard = (LatinKeyboardBaseView) mMiniKeyboardContainer.findViewById( + container = inflater.inflate(mPopupLayout, null); + mMiniKeyboard = (LatinKeyboardBaseView) container.findViewById( R.id.LatinKeyboardBaseView); mMiniKeyboard.setOnKeyboardActionListener(new OnKeyboardActionListener() { public void onKey(int primaryCode, int[] keyCodes, int x, int y) { @@ -1029,13 +1021,13 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx } mMiniKeyboard.setKeyboard(keyboard); mMiniKeyboard.setPopupParent(this); - mMiniKeyboardContainer.measure( + container.measure( MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST)); - mMiniKeyboardCache.put(popupKey, mMiniKeyboardContainer); + mMiniKeyboardCache.put(popupKey, container); } else { - mMiniKeyboard = (LatinKeyboardBaseView) mMiniKeyboardContainer.findViewById( + mMiniKeyboard = (LatinKeyboardBaseView) container.findViewById( R.id.LatinKeyboardBaseView); } if (mWindowOffset == null) { @@ -1044,35 +1036,36 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx } int popupX = popupKey.x + popupKey.width + getPaddingLeft(); int popupY = popupKey.y + getPaddingTop(); - popupX -= mMiniKeyboardContainer.getMeasuredWidth(); - popupY -= mMiniKeyboardContainer.getMeasuredHeight(); + popupX -= container.getMeasuredWidth(); + popupY -= container.getMeasuredHeight(); popupX += mWindowOffset[0]; popupY += mWindowOffset[1]; - final int x = popupX + mMiniKeyboardContainer.getPaddingRight(); - final int y = popupY + mMiniKeyboardContainer.getPaddingBottom(); - mMiniKeyboardOriginX = (x < 0 ? 0 : x) + mMiniKeyboardContainer.getPaddingLeft(); - mMiniKeyboardOriginY = y + mMiniKeyboardContainer.getPaddingTop(); + final int x = popupX + container.getPaddingRight(); + final int y = popupY + container.getPaddingBottom(); + mMiniKeyboardOriginX = (x < 0 ? 0 : x) + container.getPaddingLeft(); + mMiniKeyboardOriginY = y + container.getPaddingTop(); mMiniKeyboard.setPopupOffset((x < 0) ? 0 : x, y); mMiniKeyboard.setShifted(isShifted()); mMiniKeyboard.setPreviewEnabled(isPreviewEnabled()); - mMiniKeyboardPopup.setContentView(mMiniKeyboardContainer); - mMiniKeyboardPopup.setWidth(mMiniKeyboardContainer.getMeasuredWidth()); - mMiniKeyboardPopup.setHeight(mMiniKeyboardContainer.getMeasuredHeight()); + mMiniKeyboardPopup.setContentView(container); + mMiniKeyboardPopup.setWidth(container.getMeasuredWidth()); + mMiniKeyboardPopup.setHeight(container.getMeasuredHeight()); mMiniKeyboardPopup.showAtLocation(this, Gravity.NO_GRAVITY, x, y); - mMiniKeyboardOnScreen = true; - // TODO: down event? + // Inject down event on the key to mini keyboard. + long eventTime = System.currentTimeMillis(); + mMiniKeyboardPopupTime = eventTime; + MotionEvent downEvent = generateMiniKeyboardMotionEvent(MotionEvent.ACTION_DOWN, + popupKey.x + popupKey.width / 2, popupKey.y + popupKey.height / 2, eventTime); + mMiniKeyboard.onTouchEvent(downEvent); + downEvent.recycle(); + invalidateAllKeys(); return true; } return false; } - // TODO: Should cleanup after refactoring mini-keyboard. - public boolean isMiniKeyboardOnScreen() { - return mMiniKeyboardOnScreen; - } - private MotionEvent generateMiniKeyboardMotionEvent(int action, int x, int y, long eventTime) { return MotionEvent.obtain(mMiniKeyboardPopupTime, eventTime, action, x - mMiniKeyboardOriginX, y - mMiniKeyboardOriginY, 0); @@ -1107,7 +1100,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx mSwipeTracker.addMovement(me); // We must disable gesture detector while mini-keyboard is on the screen. - if (!mMiniKeyboardOnScreen && mGestureDetector.onTouchEvent(me)) { + if (mMiniKeyboard == null && mGestureDetector.onTouchEvent(me)) { dismissKeyPreview(); mHandler.cancelKeyTimers(); return true; @@ -1115,7 +1108,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx // Needs to be called after the gesture detector gets a turn, as it may have // displayed the mini keyboard - if (mMiniKeyboardOnScreen) { + if (mMiniKeyboard != null) { MotionEvent translated = generateMiniKeyboardMotionEvent(action, (int)me.getX(), (int)me.getY(), eventTime); mMiniKeyboard.onTouchEvent(translated); @@ -1222,10 +1215,10 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx closing(); } - public void dismissPopupKeyboard() { + private void dismissPopupKeyboard() { if (mMiniKeyboardPopup.isShowing()) { mMiniKeyboardPopup.dismiss(); - mMiniKeyboardOnScreen = false; + mMiniKeyboard = null; mMiniKeyboardOriginX = 0; mMiniKeyboardOriginY = 0; invalidateAllKeys(); diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java index cb45e2100..a4447d58b 100644 --- a/java/src/com/android/inputmethod/latin/PointerTracker.java +++ b/java/src/com/android/inputmethod/latin/PointerTracker.java @@ -32,9 +32,6 @@ public class PointerTracker { public interface UIProxy { public void invalidateKey(Key key); public void showPreview(int keyIndex, PointerTracker tracker); - // TODO: These methods might be temporary. - public void dismissPopupKeyboard(); - public boolean isMiniKeyboardOnScreen(); } public final int mPointerId; @@ -63,6 +60,9 @@ public class PointerTracker { private int mStartY; private long mDownTime; + // true if event is already translated to a key action (long press or mini-keyboard) + private boolean mKeyAlreadyProcessed; + // for move de-bouncing private int mLastCodeX; private int mLastCodeY; @@ -140,12 +140,17 @@ public class PointerTracker { } } + public void setAlreadyProcessed() { + mKeyAlreadyProcessed = true; + } + public void onDownEvent(int x, int y, long eventTime) { int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null); mCurrentKey = keyIndex; mStartX = x; mStartY = y; mDownTime = eventTime; + mKeyAlreadyProcessed = false; startMoveDebouncing(x, y); startTimeDebouncing(eventTime); checkMultiTap(eventTime, keyIndex); @@ -230,7 +235,7 @@ public class PointerTracker { } showKeyPreviewAndUpdateKey(NOT_A_KEY); // If we're not on a repeating key (which sends on a DOWN event) - if (!wasInKeyRepeat && !mProxy.isMiniKeyboardOnScreen()) { + if (!wasInKeyRepeat && !mKeyAlreadyProcessed) { detectAndSendKey(mCurrentKey, (int)x, (int)y, eventTime); } if (isValidKeyIndex(keyIndex)) @@ -242,7 +247,6 @@ public class PointerTracker { debugLog("onCancelEvt:", x, y); mHandler.cancelKeyTimers(); mHandler.cancelPopupPreview(); - mProxy.dismissPopupKeyboard(); showKeyPreviewAndUpdateKey(NOT_A_KEY); int keyIndex = mCurrentKey; if (isValidKeyIndex(keyIndex)) From 41feaaadb758a8b31d3e436063b4b5faed104d4d Mon Sep 17 00:00:00 2001 From: satok Date: Thu, 2 Sep 2010 22:54:37 +0900 Subject: [PATCH 51/58] Change symbol on space bar when autocompletion is activated bug: 2959279 Change-Id: Icc70b7cce0c245ae2451d324debd346f226b8769 --- .../sym_keyboard_space_led.9.png | Bin 1291 -> 563 bytes .../inputmethod/latin/CandidateView.java | 4 + .../inputmethod/latin/KeyboardSwitcher.java | 19 +++-- .../android/inputmethod/latin/LatinIME.java | 3 + .../inputmethod/latin/LatinKeyboard.java | 69 ++++++++++++------ 5 files changed, 68 insertions(+), 27 deletions(-) diff --git a/java/res/drawable-hdpi/sym_keyboard_space_led.9.png b/java/res/drawable-hdpi/sym_keyboard_space_led.9.png index 71da57319421de5694f096ad10c42e319d7c4828..af5c7d80f9b90e2e6ba68a73f149e7b99447e908 100644 GIT binary patch delta 536 zcmeC?+RUQZ8Q|y6%O%Cdz`(%k>ERLtq%DBhl!FaOib!Z2n5d{;&v@0-#WAGf)|*?W zy$(BwusxU=W02drh+DK!`HGm=_kGRY+aH}<`at_DXAQ&MpB#%GEtPf*=ytuJ<~wI* zkFf2=#TE4 z4hJ-5J(_U6XQlG`8~LKwb3ZTH@jUgs7R!&?vj_G@-r4wm7N2^^46g7>%{mtQ@Umk| z7X<}zs9q6XGPA$u;BQDy>w9Ut;@`84oaiIlU^MNrGVm&j}%)(CbVF7YlxN z9CKy1W!S5De*KHK1>UzCpX*s)sXy~_O^BD#gFnaAzrS_!mCFh?mHNHZeV)AZx|(^@ z7L;GS85_N0?U@dBCst#oDeL@&*6%91+51gu>s4h5*ZfJ1g>G_vK&3(6vz94&9iBJK z;mm_4DK1~+J4AH;UAlilY4Z8MK2vnI&3b$8<;`cKi^-U{h9si*R{z`w)bBMDO)O^zh18L&h3J=8S5GQci*cY>4jHr+2Ff`flE1Vh-a^73J?AU$?5){jb=|Wxz01cEz)=LRX}K PkgTe~DWM4f46ElV literal 1291 zcmeAS@N?(olHy`uVBq!ia0vp^8bHj)!3HE_x#Qe`lw^r(L`iUdT1k0gQ7VIDN`6wR zf@f}GdTLN=VoGJ<$y6H#24v4 zq}24xJX@vryZ0+8WTx0Eg`4^s_!c;)W@LI)6{QAO`Gq7`WhYyvDB0U7*i={n4aiL` zNmQuF&B-gas<2f8n`;GRgM{^!6u?SKvTcwn`Gtf;oFf&jvGt@IQ zHZeCh*HJJsFf`CNFw!?P(ls=ndS0-B(gnVDkcYHDiXVq|XS=xFF_Xz1eRv4~Pj*wm=R%;iu*SQ+p9GSr?1m^k-mTtoL+r45_$v zX6kOg!v-P_>o2?bMlYDMFhqxgvxTLGDL&xXxtyAadImMKG`ocyA0;M8ELdc7ORaaK zY%%loNu5EqH8nJ2S6=Bh9s(N=7p^n}T3wisudN`(4Jsj0hqgo?e-rI?)L z{-yFox3c#1uCCHP=lz==8a_Lsb5$xW$d2v9o%?sMiHEIB-u?W{leJ3OZKpr~-aNN# zabRe2f|rHhm8lFn?zhZNw6V0g_3Gh8=}%sJ(%)BHi@G3|Ict?guUiDe!wox_u6$wL zBINn*-yucAt>=4w{5lx-Kd+#4(-D``$$ftUlrJ6B*v-BE*|l90U8@aV?-!Mtpw{wM zOeepr;b-Gz!HYo$o;>87lo)o8KgnnB5AEhzopr E04}7?xBvhE diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java index 4995727da..bd73c6fb8 100755 --- a/java/src/com/android/inputmethod/latin/CandidateView.java +++ b/java/src/com/android/inputmethod/latin/CandidateView.java @@ -237,6 +237,8 @@ public class CandidateView extends View { final boolean typedWordValid = mTypedWordValid; final int y = (int) (height + mPaint.getTextSize() - mDescent) / 2; + boolean existsAutoCompletion = false; + for (int i = 0; i < count; i++) { CharSequence suggestion = mSuggestions.get(i); if (suggestion == null) continue; @@ -245,6 +247,7 @@ public class CandidateView extends View { && ((i == 1 && !typedWordValid) || (i == 0 && typedWordValid))) { paint.setTypeface(Typeface.DEFAULT_BOLD); paint.setColor(mColorRecommended); + existsAutoCompletion = true; } else if (i != 0) { paint.setColor(mColorOther); } @@ -285,6 +288,7 @@ public class CandidateView extends View { paint.setTypeface(Typeface.DEFAULT); x += wordWidth; } + mService.onAutoCompletionStateChanged(existsAutoCompletion); mTotalWidth = x; if (mTargetScrollX != scrollX) { scrollToTarget(); diff --git a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java index 9c0a5a3aa..2919e9b56 100644 --- a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java @@ -88,6 +88,9 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha private int mMode = MODE_NONE; /** One of the MODE_XXX values */ private int mImeOptions; private boolean mIsSymbols; + /** mIsAutoCompletionActive indicates that auto completed word will be input instead of + * what user actually typed. */ + private boolean mIsAutoCompletionActive; private boolean mHasVoice; private boolean mVoiceOnPrimary; private boolean mPreferSymbols; @@ -239,7 +242,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha keyboard.setShifted(false); keyboard.setShiftLocked(keyboard.isShiftLocked()); keyboard.setImeOptions(mContext.getResources(), mMode, imeOptions); - keyboard.setBlackFlag(isBlackSym()); + keyboard.setColorOfSymbolIcons(mIsAutoCompletionActive, isBlackSym()); } private LatinKeyboard getKeyboard(KeyboardId id) { @@ -249,12 +252,10 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha Locale saveLocale = conf.locale; conf.locale = mInputLocale; orig.updateConfiguration(conf, null); - LatinKeyboard keyboard = new LatinKeyboard( - mContext, id.mXml, id.mKeyboardMode); + LatinKeyboard keyboard = new LatinKeyboard(mContext, id.mXml, id.mKeyboardMode); keyboard.setVoiceMode(hasVoiceButton(id.mXml == R.xml.kbd_symbols || id.mXml == R.xml.kbd_symbols_black), mHasVoice); - keyboard.setLanguageSwitcher(mLanguageSwitcher); - keyboard.setBlackFlag(isBlackSym()); + keyboard.setLanguageSwitcher(mLanguageSwitcher, mIsAutoCompletionActive, isBlackSym()); if (id.mEnableShiftLock) { keyboard.enableShiftLock(); @@ -450,4 +451,12 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha } } + public void onAutoCompletionStateChanged(boolean isAutoCompletion) { + if (isAutoCompletion != mIsAutoCompletionActive) { + LatinKeyboardView keyboardView = getInputView(); + mIsAutoCompletionActive = isAutoCompletion; + keyboardView.invalidateKey(((LatinKeyboard) keyboardView.getKeyboard()) + .onAutoCompletionStateChanged(isAutoCompletion)); + } + } } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 7afee3fad..d0e6e69c7 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -2483,4 +2483,7 @@ public class LatinIME extends InputMethodService System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total)); } + public void onAutoCompletionStateChanged(boolean isAutoCompletion) { + mKeyboardSwitcher.onAutoCompletionStateChanged(isAutoCompletion); + } } diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboard.java b/java/src/com/android/inputmethod/latin/LatinKeyboard.java index 33519e4be..b7c4fc4dc 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboard.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboard.java @@ -43,11 +43,13 @@ public class LatinKeyboard extends Keyboard { private static final boolean DEBUG_PREFERRED_LETTER = false; private static final String TAG = "LatinKeyboard"; + private static final int OPACITY_FULLY_OPAQUE = 255; private Drawable mShiftLockIcon; private Drawable mShiftLockPreviewIcon; private Drawable mOldShiftIcon; private Drawable mSpaceIcon; + private Drawable mSpaceAutoCompletionIndicator; private Drawable mSpacePreviewIcon; private Drawable mMicIcon; private Drawable mMicPreviewIcon; @@ -111,6 +113,7 @@ public class LatinKeyboard extends Keyboard { mShiftLockPreviewIcon.getIntrinsicWidth(), mShiftLockPreviewIcon.getIntrinsicHeight()); mSpaceIcon = res.getDrawable(R.drawable.sym_keyboard_space); + mSpaceAutoCompletionIndicator = res.getDrawable(R.drawable.sym_keyboard_space_led); mSpacePreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_space); mMicIcon = res.getDrawable(R.drawable.sym_keyboard_mic); mMicPreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_mic); @@ -277,9 +280,9 @@ public class LatinKeyboard extends Keyboard { return mIsAlphaKeyboard; } - public void setBlackFlag(boolean f) { - mIsBlackSym = f; - if (f) { + public void setColorOfSymbolIcons(boolean isAutoCompletion, boolean isBlack) { + mIsBlackSym = isBlack; + if (isBlack) { mShiftLockIcon = mRes.getDrawable(R.drawable.sym_bkeyboard_shift_locked); mSpaceIcon = mRes.getDrawable(R.drawable.sym_bkeyboard_space); mMicIcon = mRes.getDrawable(R.drawable.sym_bkeyboard_mic); @@ -292,8 +295,7 @@ public class LatinKeyboard extends Keyboard { } updateF1Key(); if (mSpaceKey != null) { - mSpaceKey.icon = mSpaceIcon; - updateSpaceBarForLocale(f); + updateSpaceBarForLocale(isAutoCompletion, isBlack); } } @@ -334,23 +336,34 @@ public class LatinKeyboard extends Keyboard { } } - private void updateSpaceBarForLocale(boolean isBlack) { + /** + * @return a key which should be invalidated. + */ + public Key onAutoCompletionStateChanged(boolean isAutoCompletion) { + updateSpaceBarForLocale(isAutoCompletion, mIsBlackSym); + return mSpaceKey; + } + + private void updateSpaceBarForLocale(boolean isAutoCompletion, boolean isBlack) { if (mLocale != null) { - // Create the graphic for spacebar - Bitmap buffer = Bitmap.createBitmap(mSpaceKey.width, mSpaceIcon.getIntrinsicHeight(), - Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(buffer); - drawSpaceBar(canvas, buffer.getWidth(), buffer.getHeight(), 255, isBlack); + Bitmap buffer = drawSpaceBar(OPACITY_FULLY_OPAQUE, isAutoCompletion, isBlack); mSpaceKey.icon = new BitmapDrawable(mRes, buffer); mSpaceKey.repeatable = mLanguageSwitcher.getLocaleCount() < 2; } else { - mSpaceKey.icon = isBlack ? mRes.getDrawable(R.drawable.sym_bkeyboard_space) - : mRes.getDrawable(R.drawable.sym_keyboard_space); + // sym_keyboard_space_led can be shared with Black and White symbol themes. + mSpaceKey.icon = + isAutoCompletion ? mRes.getDrawable(R.drawable.sym_keyboard_space_led) + : isBlack ? mRes.getDrawable(R.drawable.sym_bkeyboard_space) + : mRes.getDrawable(R.drawable.sym_keyboard_space); mSpaceKey.repeatable = true; } } - private void drawSpaceBar(Canvas canvas, int width, int height, int opacity, boolean isBlack) { + private Bitmap drawSpaceBar(int opacity, boolean isAutoCompletion, boolean isBlack) { + int width = mSpaceKey.width; + int height = mSpaceIcon.getIntrinsicHeight(); + Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(buffer); canvas.drawColor(mRes.getColor(R.color.latinkeyboard_transparent), PorterDuff.Mode.CLEAR); Paint paint = new Paint(); paint.setAntiAlias(true); @@ -380,11 +393,22 @@ public class LatinKeyboard extends Keyboard { (mSpaceKey.width + bounds.right) / 2, (int) paint.getTextSize()); } // Draw the spacebar icon at the bottom - int x = (width - mSpaceIcon.getIntrinsicWidth()) / 2; - int y = height - mSpaceIcon.getIntrinsicHeight(); - mSpaceIcon.setBounds(x, y, - x + mSpaceIcon.getIntrinsicWidth(), y + mSpaceIcon.getIntrinsicHeight()); - mSpaceIcon.draw(canvas); + if (isAutoCompletion) { + final int iconWidth = mSpaceAutoCompletionIndicator.getIntrinsicWidth(); + final int iconHeight = mSpaceAutoCompletionIndicator.getIntrinsicHeight(); + int x = (width - iconWidth) / 2; + int y = height - iconHeight; + mSpaceAutoCompletionIndicator.setBounds(x, y, x + iconWidth, y + iconHeight); + mSpaceAutoCompletionIndicator.draw(canvas); + } else { + final int iconWidth = mSpaceIcon.getIntrinsicWidth(); + final int iconHeight = mSpaceIcon.getIntrinsicHeight(); + int x = (width - iconWidth) / 2; + int y = height - iconHeight; + mSpaceIcon.setBounds(x, y, x + iconWidth, y + iconHeight); + mSpaceIcon.draw(canvas); + } + return buffer; } private void drawButtonArrow(Drawable arrow, Canvas canvas, int x, int bottomY) { @@ -438,7 +462,8 @@ public class LatinKeyboard extends Keyboard { return mSpaceDragLastDiff > 0 ? 1 : -1; } - public void setLanguageSwitcher(LanguageSwitcher switcher) { + public void setLanguageSwitcher(LanguageSwitcher switcher, boolean isAutoCompletion, + boolean isBlackSym) { mLanguageSwitcher = switcher; Locale locale = mLanguageSwitcher.getLocaleCount() > 0 ? mLanguageSwitcher.getInputLocale() @@ -450,9 +475,9 @@ public class LatinKeyboard extends Keyboard { .equalsIgnoreCase(locale.getLanguage())) { locale = null; } + setColorOfSymbolIcons(isAutoCompletion, isBlackSym); if (mLocale != null && mLocale.equals(locale)) return; mLocale = locale; - updateSpaceBarForLocale(mIsBlackSym); } boolean isCurrentlyInSpace() { @@ -729,7 +754,7 @@ public class LatinKeyboard extends Keyboard { mTextPaint.setTextSize(textSize); mTextPaint.setColor(R.color.latinkeyboard_transparent); mTextPaint.setTextAlign(Align.CENTER); - mTextPaint.setAlpha(255); + mTextPaint.setAlpha(OPACITY_FULLY_OPAQUE); mTextPaint.setAntiAlias(true); mAscent = (int) mTextPaint.ascent(); mMiddleX = (mWidth - mBackground.getIntrinsicWidth()) / 2; From cf41bd392f4c5d1c793eef3ac174e71fd84517e7 Mon Sep 17 00:00:00 2001 From: satok Date: Fri, 3 Sep 2010 15:27:07 +0900 Subject: [PATCH 52/58] Update delete key Change-Id: I0348e4846131f9913b4ab6c2c2a9427a9a53c74e --- .../res/drawable-hdpi/sym_keyboard_delete.png | Bin 1465 -> 2058 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/java/res/drawable-hdpi/sym_keyboard_delete.png b/java/res/drawable-hdpi/sym_keyboard_delete.png index ee29af02e6ba3dcc9e6497a5c967cba275ace802..3c89e2820d990fa660e45cdf6756cc9efab726cb 100755 GIT binary patch delta 1210 zcmV;r1V#I~3yKi19s&$DIXE~)GB`#sLNYg#DgrPJGB-CdG&DmvK|(P^lV$=i3^F%2 zF*GzoH$g%%M3bTdbqhp7HbgZ;LohKiIFlj+Fbp<1I56@U?s}Cwlg0K)B>*L9h8;0eamS(y2|I4{@+wRxy?p0>@z@N=C?(Tl~ zoclljok{uq{-}f4C>5r{RG5DXQ(^xljH0NBgakRlh3)r<)1OyS7#ypCha`w>@~BbB zCSx zF*3|?MCkxkKR7sOO-f2Swz|5y*4^Db;Pd%h8jZ%MM6O6oOmxGeTX26WNgT1Ak*ce! zYokZX+2swe-4BeB2l3@0uimmR189Sz23EkhK485pNX#rzPAz~H!KLXzP|p$ zY&JiI{^NKhIX*-j#0fH*2_ipuJjt>c@k+v2QB6%v&!9g`0CjPAc=+x7{JcFQBjYMg zDG{jRiHV6R416AllM8BWbl^7Hf0IUJ6U%#_WAV?$wESXlT{QBiS;dH;qBLsSN! z+L@@fwzfVp_oGGJD_Xr?f8B1kf9AvSp^QeOiBvSQjMy#;Q#pU0`-fK>rEQ<2O3PjH_)F45zAMSg^0^cOG|r% z6$=xEiOFCv^pJmhSRP|zkYUxXLWsaJ}(ZY*#d3=1_#vCb} z?##b!Hk(7JLXnz0Qp?K9?$9`#lD)mXugK~jD=~Q>>dJrQVRX&79qB zMa1F#LgSW}mX@(%;k$qK0w%|=EqFjO;3`K(M*3c}va&MWZui&9%E~^t;T>e3Ju>(1 z*+%X_?A-_8ZaJM!*M7s~{uzlP+uGUW9*d4rrU_0(^%u>EhpGQHpu$v`3R7VRvHcZb Y08I9I6tkq|1ONa407*qoM6N<$f@$7G`~Uy| delta 613 zcmeAY*vY*?j)}+I)Wp%;(cIY0)yQnJ7Lx&wfwP;jsgaqHqobkoEaktaVzQ1|Nr)f3s`)34vX|u^&}l=@|`eoV&REOmc54dvqaimgO;dpE>O+1TkuD{=2zy_HaYsb=8^>Cbhw*y-)KZKg*}KwzfKT|9LiF9v|<2@34>8%=*N}`fio-fYZqi3Jgc0 zCad|r`oY2Cu<^h1y<~?44<0-aD0+Emsqz1b2Lis$Fc5fsZmxCtrR(eC_y2KccD|bI zwQt|PK=b^2dp^mtOJvCjGbc5RYKNWq$I0^lV?*N?3C*t(#v1xZj~%lzF*Oa<($LTl zjt*z)u3^^_e^%e{LsH=W;w|+%rayW3u<+KN%Fmzf@2~&=%l-hvG$9S&t~)m!K74t3 z`S^c!PK9I1F57KpG$fob{od)@6}>Gd(llg}lCoL(;HJBrg7h zg+H5{n-5QB``8#*k?^DW&ZD}svrM_!iVOYMr7qA2<>KP%+FSbi+SZ3p3?&2@lj>~) zCUZUM1oCE7sRk(jI5k!KdE3~_=I#g)Ilyi`7XDmmcq9)~se zE?fv;^jgOJ&@kwgVG&#LkH$~(FAZljzvJt&HM2^vvP$qe%y{|Xh83wMntiB|$ie8) cz{oJ==nqzll`b6&3=EtMp00i_>zopr0277|-v9sr From 0529a04b6aece3db34b4e7c895c67ad0858c8bd9 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 3 Sep 2010 14:46:14 +0900 Subject: [PATCH 53/58] Followup TBR in I87060049 This change is followup TBR in I87060049cad6f9d6432b6c4a246c15587ae0d837 Change-Id: I02ee33da269162f5e95ce5b985dbf5094ba14c0d --- .../inputmethod/latin/KeyDetector.java | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/KeyDetector.java b/java/src/com/android/inputmethod/latin/KeyDetector.java index e443f272b..76fe1200e 100644 --- a/java/src/com/android/inputmethod/latin/KeyDetector.java +++ b/java/src/com/android/inputmethod/latin/KeyDetector.java @@ -24,11 +24,15 @@ import java.util.List; abstract class KeyDetector { protected Keyboard mKeyboard; + private Key[] mKeys; protected int mCorrectionX; + protected int mCorrectionY; + protected boolean mProximityCorrectOn; + protected int mProximityThresholdSquare; public Key[] setKeyboard(Keyboard keyboard, float correctionX, float correctionY) { @@ -54,7 +58,7 @@ abstract class KeyDetector { protected Key[] getKeys() { if (mKeys == null) throw new IllegalStateException("keyboard isn't set"); - // mKeyboard is guaranteed not null at setKeybaord() method + // mKeyboard is guaranteed not to be null at setKeybaord() method if mKeys is not null return mKeys; } @@ -70,13 +74,40 @@ abstract class KeyDetector { mProximityThresholdSquare = threshold * threshold; } + /** + * Allocates array that can hold all key indices returned by {@link #getKeyIndexAndNearbyCodes} + * method. The maximum size of the array should be computed by {@link #getMaxNearbyKeys}. + * + * @return Allocates and returns an array that can hold all key indices returned by + * {@link #getKeyIndexAndNearbyCodes} method. All elements in the returned array are + * initialized by {@link com.android.inputmethod.latin.LatinKeyboardView.NOT_A_KEY} + * value. + */ public int[] newCodeArray() { int[] codes = new int[getMaxNearbyKeys()]; Arrays.fill(codes, LatinKeyboardBaseView.NOT_A_KEY); return codes; } + /** + * Computes maximum size of the array that can contain all nearby key indices returned by + * {@link #getKeyIndexAndNearbyCodes}. + * + * @return Returns maximum size of the array that can contain all nearby key indices returned + * by {@link #getKeyIndexAndNearbyCodes}. + */ abstract protected int getMaxNearbyKeys(); + /** + * Finds all possible nearby key indices around a touch event point and returns the nearest key + * index. The algorithm to determine the nearby keys depends on the threshold set by + * {@link #setProximityThreshold(int)} and the mode set by + * {@link #setProximityCorrectionEnabled(boolean)}. + * + * @param x The x-coordinate of a touch point + * @param y The y-coordinate of a touch point + * @param allKeys All nearby key indices are returned in this array + * @return The nearest key index + */ abstract public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys); -} \ No newline at end of file +} From 0b4734396fdc4ffe7a27016225b9ab242fef1295 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 3 Sep 2010 16:52:48 +0900 Subject: [PATCH 54/58] Move inflating mini keyboard code into separate method Change-Id: Iba8e43ba6125e559d4c7d9cadb6bcb13b8eefc83 --- .../latin/LatinKeyboardBaseView.java | 175 ++++++++++-------- 1 file changed, 93 insertions(+), 82 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index ba901eddb..ef7ca5f9c 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -971,6 +971,58 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx return result; } + private View inflateMiniKeyboardContainer(Key popupKey) { + int popupKeyboardId = popupKey.popupResId; + LayoutInflater inflater = (LayoutInflater)getContext().getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + View container = inflater.inflate(mPopupLayout, null); + if (container == null) + throw new NullPointerException(); + + mMiniKeyboard = (LatinKeyboardBaseView)container.findViewById(R.id.LatinKeyboardBaseView); + mMiniKeyboard.setOnKeyboardActionListener(new OnKeyboardActionListener() { + public void onKey(int primaryCode, int[] keyCodes, int x, int y) { + mKeyboardActionListener.onKey(primaryCode, keyCodes, x, y); + dismissPopupKeyboard(); + } + + public void onText(CharSequence text) { + mKeyboardActionListener.onText(text); + dismissPopupKeyboard(); + } + + public void swipeLeft() { + } + public void swipeRight() { + } + public void swipeUp() { + } + public void swipeDown() { + } + public void onPress(int primaryCode) { + mKeyboardActionListener.onPress(primaryCode); + } + public void onRelease(int primaryCode) { + mKeyboardActionListener.onRelease(primaryCode); + } + }); + + Keyboard keyboard; + if (popupKey.popupCharacters != null) { + keyboard = new Keyboard(getContext(), popupKeyboardId, popupKey.popupCharacters, + -1, getPaddingLeft() + getPaddingRight()); + } else { + keyboard = new Keyboard(getContext(), popupKeyboardId); + } + mMiniKeyboard.setKeyboard(keyboard); + mMiniKeyboard.setPopupParent(this); + + container.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST), + MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST)); + + return container; + } + /** * Called when a key is long pressed. By default this will open any popup keyboard associated * with this key through the attributes popupLayout and popupCharacters. @@ -979,91 +1031,50 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx * method on the base class if the subclass doesn't wish to handle the call. */ protected boolean onLongPress(Key popupKey) { - int popupKeyboardId = popupKey.popupResId; + // TODO if popupKey.popupCharacters has only one letter, send it as key without opening + // mini keyboard. - if (popupKeyboardId != 0) { - View container = mMiniKeyboardCache.get(popupKey); - if (container == null) { - LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - container = inflater.inflate(mPopupLayout, null); - mMiniKeyboard = (LatinKeyboardBaseView) container.findViewById( - R.id.LatinKeyboardBaseView); - mMiniKeyboard.setOnKeyboardActionListener(new OnKeyboardActionListener() { - public void onKey(int primaryCode, int[] keyCodes, int x, int y) { - mKeyboardActionListener.onKey(primaryCode, keyCodes, x, y); - dismissPopupKeyboard(); - } + if (popupKey.popupResId == 0) + return false; - public void onText(CharSequence text) { - mKeyboardActionListener.onText(text); - dismissPopupKeyboard(); - } - - public void swipeLeft() { } - public void swipeRight() { } - public void swipeUp() { } - public void swipeDown() { } - public void onPress(int primaryCode) { - mKeyboardActionListener.onPress(primaryCode); - } - public void onRelease(int primaryCode) { - mKeyboardActionListener.onRelease(primaryCode); - } - }); - - Keyboard keyboard; - if (popupKey.popupCharacters != null) { - keyboard = new Keyboard(getContext(), popupKeyboardId, - popupKey.popupCharacters, -1, getPaddingLeft() + getPaddingRight()); - } else { - keyboard = new Keyboard(getContext(), popupKeyboardId); - } - mMiniKeyboard.setKeyboard(keyboard); - mMiniKeyboard.setPopupParent(this); - container.measure( - MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST), - MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST)); - - mMiniKeyboardCache.put(popupKey, container); - } else { - mMiniKeyboard = (LatinKeyboardBaseView) container.findViewById( - R.id.LatinKeyboardBaseView); - } - if (mWindowOffset == null) { - mWindowOffset = new int[2]; - getLocationInWindow(mWindowOffset); - } - int popupX = popupKey.x + popupKey.width + getPaddingLeft(); - int popupY = popupKey.y + getPaddingTop(); - popupX -= container.getMeasuredWidth(); - popupY -= container.getMeasuredHeight(); - popupX += mWindowOffset[0]; - popupY += mWindowOffset[1]; - final int x = popupX + container.getPaddingRight(); - final int y = popupY + container.getPaddingBottom(); - mMiniKeyboardOriginX = (x < 0 ? 0 : x) + container.getPaddingLeft(); - mMiniKeyboardOriginY = y + container.getPaddingTop(); - mMiniKeyboard.setPopupOffset((x < 0) ? 0 : x, y); - mMiniKeyboard.setShifted(isShifted()); - mMiniKeyboard.setPreviewEnabled(isPreviewEnabled()); - mMiniKeyboardPopup.setContentView(container); - mMiniKeyboardPopup.setWidth(container.getMeasuredWidth()); - mMiniKeyboardPopup.setHeight(container.getMeasuredHeight()); - mMiniKeyboardPopup.showAtLocation(this, Gravity.NO_GRAVITY, x, y); - - // Inject down event on the key to mini keyboard. - long eventTime = System.currentTimeMillis(); - mMiniKeyboardPopupTime = eventTime; - MotionEvent downEvent = generateMiniKeyboardMotionEvent(MotionEvent.ACTION_DOWN, - popupKey.x + popupKey.width / 2, popupKey.y + popupKey.height / 2, eventTime); - mMiniKeyboard.onTouchEvent(downEvent); - downEvent.recycle(); - - invalidateAllKeys(); - return true; + View container = mMiniKeyboardCache.get(popupKey); + if (container == null) { + container = inflateMiniKeyboardContainer(popupKey); + mMiniKeyboardCache.put(popupKey, container); } - return false; + mMiniKeyboard = (LatinKeyboardBaseView)container.findViewById(R.id.LatinKeyboardBaseView); + if (mWindowOffset == null) { + mWindowOffset = new int[2]; + getLocationInWindow(mWindowOffset); + } + int popupX = popupKey.x + popupKey.width + getPaddingLeft(); + int popupY = popupKey.y + getPaddingTop(); + popupX -= container.getMeasuredWidth(); + popupY -= container.getMeasuredHeight(); + popupX += mWindowOffset[0]; + popupY += mWindowOffset[1]; + final int x = popupX + container.getPaddingRight(); + final int y = popupY + container.getPaddingBottom(); + mMiniKeyboardOriginX = (x < 0 ? 0 : x) + container.getPaddingLeft(); + mMiniKeyboardOriginY = y + container.getPaddingTop(); + mMiniKeyboard.setPopupOffset((x < 0) ? 0 : x, y); + mMiniKeyboard.setShifted(isShifted()); + mMiniKeyboard.setPreviewEnabled(isPreviewEnabled()); + mMiniKeyboardPopup.setContentView(container); + mMiniKeyboardPopup.setWidth(container.getMeasuredWidth()); + mMiniKeyboardPopup.setHeight(container.getMeasuredHeight()); + mMiniKeyboardPopup.showAtLocation(this, Gravity.NO_GRAVITY, x, y); + + // Inject down event on the key to mini keyboard. + long eventTime = System.currentTimeMillis(); + mMiniKeyboardPopupTime = eventTime; + MotionEvent downEvent = generateMiniKeyboardMotionEvent(MotionEvent.ACTION_DOWN, popupKey.x + + popupKey.width / 2, popupKey.y + popupKey.height / 2, eventTime); + mMiniKeyboard.onTouchEvent(downEvent); + downEvent.recycle(); + + invalidateAllKeys(); + return true; } private MotionEvent generateMiniKeyboardMotionEvent(int action, int x, int y, long eventTime) { From 9a6a4d3d5f1ee52b56d349c002aa61c264d010d3 Mon Sep 17 00:00:00 2001 From: satok Date: Fri, 3 Sep 2010 04:25:31 +0900 Subject: [PATCH 55/58] Add a showing input method picker option by longpressing setting key Bug: 2959271 Change-Id: I4b7e9a2de3cbe17b168ed8d0541a9b1cd9a9e107 --- java/res/values/strings.xml | 5 ++- .../android/inputmethod/latin/LatinIME.java | 43 +++++++++++++++++-- .../inputmethod/latin/LatinKeyboardView.java | 8 +++- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml index 09521146f..7b760f002 100644 --- a/java/res/values/strings.xml +++ b/java/res/values/strings.xml @@ -320,7 +320,10 @@ Input method - + + + Select input method + Input languages diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index d0e6e69c7..3b4b4ffb0 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1083,6 +1083,40 @@ public class LatinIME extends InputMethodService } } + private boolean hasMultipleEnabledIMEs() { + return ((InputMethodManager) getSystemService( + INPUT_METHOD_SERVICE)).getEnabledInputMethodList().size() > 1; + } + + private void showInputMethodPicker() { + ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)) + .showInputMethodPicker(); + } + + private void onOptionKeyPressed() { + if (!isShowingOptionDialog()) { + if (hasMultipleEnabledIMEs()) { + showOptionsMenu(); + } else { + launchSettings(); + } + } + } + + private void onOptionKeyLongPressed() { + if (!isShowingOptionDialog()) { + if (hasMultipleEnabledIMEs()) { + showInputMethodPicker(); + } else { + launchSettings(); + } + } + } + + private boolean isShowingOptionDialog() { + return mOptionsDialog != null && mOptionsDialog.isShowing(); + } + // Implementation of KeyboardViewListener public void onKey(int primaryCode, int[] keyCodes, int x, int y) { @@ -1102,12 +1136,15 @@ public class LatinIME extends InputMethodService // Shift key is handled in onPress(). break; case Keyboard.KEYCODE_CANCEL: - if (mOptionsDialog == null || !mOptionsDialog.isShowing()) { + if (!isShowingOptionDialog()) { handleClose(); } break; case LatinKeyboardView.KEYCODE_OPTIONS: - showOptionsMenu(); + onOptionKeyPressed(); + break; + case LatinKeyboardView.KEYCODE_OPTIONS_LONGPRESS: + onOptionKeyLongPressed(); break; case LatinKeyboardView.KEYCODE_NEXT_LANGUAGE: toggleLanguage(false, true); @@ -2400,7 +2437,7 @@ public class LatinIME extends InputMethodService builder.setIcon(R.drawable.ic_dialog_keyboard); builder.setNegativeButton(android.R.string.cancel, null); CharSequence itemSettings = getString(R.string.english_ime_settings); - CharSequence itemInputMethod = getString(R.string.inputMethod); + CharSequence itemInputMethod = getString(R.string.selectInputMethod); builder.setItems(new CharSequence[] { itemSettings, itemInputMethod}, new DialogInterface.OnClickListener() { diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java index 7a993669b..9236d6820 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java @@ -32,6 +32,7 @@ import java.util.List; public class LatinKeyboardView extends LatinKeyboardBaseView { static final int KEYCODE_OPTIONS = -100; + static final int KEYCODE_OPTIONS_LONGPRESS = -101; static final int KEYCODE_VOICE = -102; static final int KEYCODE_F1 = -103; static final int KEYCODE_NEXT_LANGUAGE = -104; @@ -76,7 +77,12 @@ public class LatinKeyboardView extends LatinKeyboardBaseView { @Override protected boolean onLongPress(Key key) { - if (key.codes[0] == '0' && getKeyboard() == mPhoneKeyboard) { + if (key.codes[0] == KEYCODE_OPTIONS) { + getOnKeyboardActionListener().onKey(KEYCODE_OPTIONS_LONGPRESS, null, + LatinKeyboardBaseView.NOT_A_TOUCH_COORDINATE, + LatinKeyboardBaseView.NOT_A_TOUCH_COORDINATE); + return true; + } else if (key.codes[0] == '0' && getKeyboard() == mPhoneKeyboard) { // Long pressing on 0 in phone number keypad gives you a '+'. getOnKeyboardActionListener().onKey( '+', null, LatinKeyboardBaseView.NOT_A_TOUCH_COORDINATE, From e8f45ab56f3e6f358953dede794a63fc5901961d Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 3 Sep 2010 17:54:37 +0900 Subject: [PATCH 56/58] One alternate is treated as key action, not open mini keyboard This change also fixes bug#2973683. Bug: 2973546 Bug: 2973683 Change-Id: I67573e5b7cad4af261591a4a608d0596dd7901f2 --- .../latin/LatinKeyboardBaseView.java | 2 +- .../inputmethod/latin/LatinKeyboardView.java | 55 +++++++++++++------ .../inputmethod/latin/PointerTracker.java | 8 ++- 3 files changed, 47 insertions(+), 18 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index ef7ca5f9c..c449b36e7 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -965,8 +965,8 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx return false; boolean result = onLongPress(popupKey); if (result) { - tracker.setAlreadyProcessed(); dismissKeyPreview(); + tracker.setAlreadyProcessed(); } return result; } diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java index 9236d6820..71ca8b81a 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java @@ -42,7 +42,7 @@ public class LatinKeyboardView extends LatinKeyboardBaseView { /** Whether we've started dropping move events because we found a big jump */ private boolean mDroppingEvents; - /** + /** * Whether multi-touch disambiguation needs to be disabled if a real multi-touch event has * occured */ @@ -52,6 +52,9 @@ public class LatinKeyboardView extends LatinKeyboardBaseView { /** The y coordinate of the last row */ private int mLastRowY; + // This is local working variable for onLongPress(). + private int[] mKeyCodes = new int[1]; + public LatinKeyboardView(Context context, AttributeSet attrs) { super(context, attrs); } @@ -75,17 +78,37 @@ public class LatinKeyboardView extends LatinKeyboardBaseView { setKeyboardLocal(k); } + private static boolean hasOneDigitAlternate(Key key) { + final CharSequence alternates = key.popupCharacters; + if (alternates == null) + return false; + final String altChars = alternates.toString(); + if (altChars.codePointCount(0, altChars.length()) != 1) + return false; + final int altCode = altChars.codePointAt(0); + return altCode >= '0' && altCode <= '9'; + } + @Override protected boolean onLongPress(Key key) { - if (key.codes[0] == KEYCODE_OPTIONS) { + int primaryCode = key.codes[0]; + if (primaryCode == KEYCODE_OPTIONS) { getOnKeyboardActionListener().onKey(KEYCODE_OPTIONS_LONGPRESS, null, LatinKeyboardBaseView.NOT_A_TOUCH_COORDINATE, LatinKeyboardBaseView.NOT_A_TOUCH_COORDINATE); return true; - } else if (key.codes[0] == '0' && getKeyboard() == mPhoneKeyboard) { + } else if (primaryCode == '0' && getKeyboard() == mPhoneKeyboard) { // Long pressing on 0 in phone number keypad gives you a '+'. getOnKeyboardActionListener().onKey( - '+', null, LatinKeyboardBaseView.NOT_A_TOUCH_COORDINATE, + '+', null, + LatinKeyboardBaseView.NOT_A_TOUCH_COORDINATE, + LatinKeyboardBaseView.NOT_A_TOUCH_COORDINATE); + return true; + } else if (hasOneDigitAlternate(key)) { + mKeyCodes[0] = primaryCode = key.popupCharacters.charAt(0); + // when there is only one alternate character, send it as key action. + getOnKeyboardActionListener().onKey(primaryCode, mKeyCodes, + LatinKeyboardBaseView.NOT_A_TOUCH_COORDINATE, LatinKeyboardBaseView.NOT_A_TOUCH_COORDINATE); return true; } else { @@ -121,10 +144,10 @@ public class LatinKeyboardView extends LatinKeyboardBaseView { * that could be due to a multi-touch being treated as a move by the firmware or hardware. * Once a sudden jump is detected, all subsequent move events are discarded * until an UP is received.

- * When a sudden jump is detected, an UP event is simulated at the last position and when + * When a sudden jump is detected, an UP event is simulated at the last position and when * the sudden moves subside, a DOWN event is simulated for the second key. * @param me the motion event - * @return true if the event was consumed, so that it doesn't continue to be handled by + * @return true if the event was consumed, so that it doesn't continue to be handled by * KeyboardView. */ private boolean handleSuddenJump(MotionEvent me) { @@ -232,9 +255,9 @@ public class LatinKeyboardView extends LatinKeyboardBaseView { static final boolean DEBUG_LINE = false; private static final int MSG_TOUCH_DOWN = 1; private static final int MSG_TOUCH_UP = 2; - + Handler mHandler2; - + private String mStringToPlay; private int mStringIndex; private boolean mDownDelivered; @@ -254,7 +277,7 @@ public class LatinKeyboardView extends LatinKeyboardBaseView { removeMessages(MSG_TOUCH_DOWN); removeMessages(MSG_TOUCH_UP); if (mPlaying == false) return; - + switch (msg.what) { case MSG_TOUCH_DOWN: if (mStringIndex >= mStringToPlay.length()) { @@ -262,7 +285,7 @@ public class LatinKeyboardView extends LatinKeyboardBaseView { return; } char c = mStringToPlay.charAt(mStringIndex); - while (c > 255 || mAsciiKeys[(int) c] == null) { + while (c > 255 || mAsciiKeys[c] == null) { mStringIndex++; if (mStringIndex >= mStringToPlay.length()) { mPlaying = false; @@ -272,8 +295,8 @@ public class LatinKeyboardView extends LatinKeyboardBaseView { } int x = mAsciiKeys[c].x + 10; int y = mAsciiKeys[c].y + 26; - MotionEvent me = MotionEvent.obtain(SystemClock.uptimeMillis(), - SystemClock.uptimeMillis(), + MotionEvent me = MotionEvent.obtain(SystemClock.uptimeMillis(), + SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, x, y, 0); LatinKeyboardView.this.dispatchTouchEvent(me); me.recycle(); @@ -286,9 +309,9 @@ public class LatinKeyboardView extends LatinKeyboardBaseView { int x2 = mAsciiKeys[cUp].x + 10; int y2 = mAsciiKeys[cUp].y + 26; mStringIndex++; - - MotionEvent me2 = MotionEvent.obtain(SystemClock.uptimeMillis(), - SystemClock.uptimeMillis(), + + MotionEvent me2 = MotionEvent.obtain(SystemClock.uptimeMillis(), + SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, x2, y2, 0); LatinKeyboardView.this.dispatchTouchEvent(me2); me2.recycle(); @@ -309,7 +332,7 @@ public class LatinKeyboardView extends LatinKeyboardBaseView { // Get the keys on this keyboard for (int i = 0; i < keys.size(); i++) { int code = keys.get(i).codes[0]; - if (code >= 0 && code <= 255) { + if (code >= 0 && code <= 255) { mAsciiKeys[code] = keys.get(i); } } diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java index a4447d58b..2685e87c6 100644 --- a/java/src/com/android/inputmethod/latin/PointerTracker.java +++ b/java/src/com/android/inputmethod/latin/PointerTracker.java @@ -124,6 +124,8 @@ public class PointerTracker { } public void updateKey(int keyIndex) { + if (mKeyAlreadyProcessed) + return; int oldKeyIndex = mPreviousKey; mPreviousKey = keyIndex; if (keyIndex != oldKeyIndex) { @@ -172,6 +174,8 @@ public class PointerTracker { } public void onMoveEvent(int x, int y, long eventTime) { + if (mKeyAlreadyProcessed) + return; int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null); if (isValidKeyIndex(keyIndex)) { if (mCurrentKey == NOT_A_KEY) { @@ -215,6 +219,8 @@ public class PointerTracker { } public void onUpEvent(int x, int y, long eventTime) { + if (mKeyAlreadyProcessed) + return; if (DEBUG) debugLog("onUpEvent :", x, y); int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null); @@ -235,7 +241,7 @@ public class PointerTracker { } showKeyPreviewAndUpdateKey(NOT_A_KEY); // If we're not on a repeating key (which sends on a DOWN event) - if (!wasInKeyRepeat && !mKeyAlreadyProcessed) { + if (!wasInKeyRepeat) { detectAndSendKey(mCurrentKey, (int)x, (int)y, eventTime); } if (isValidKeyIndex(keyIndex)) From 1bf265d185bc6b214588dcca4888691f4f8038d4 Mon Sep 17 00:00:00 2001 From: satok Date: Fri, 3 Sep 2010 19:05:23 +0900 Subject: [PATCH 57/58] Extend space LED for autocompletion Change-Id: If59ea7c871ffc2af6fe2bfde72303f2612e43c3b --- .../android/inputmethod/latin/LatinIME.java | 2 + .../inputmethod/latin/LatinKeyboard.java | 71 +++++++++++-------- 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 3b4b4ffb0..ea8c93934 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -687,6 +687,7 @@ public class LatinIME extends InputMethodService super.onFinishInput(); LatinImeLogger.commit(); + onAutoCompletionStateChanged(false); if (VOICE_INSTALLED && !mConfigurationChanging) { if (mAfterVoiceInput) { @@ -791,6 +792,7 @@ public class LatinIME extends InputMethodService @Override public void hideWindow() { LatinImeLogger.commit(); + onAutoCompletionStateChanged(false); if (TRACE) Debug.stopMethodTracing(); if (mOptionsDialog != null && mOptionsDialog.isShowing()) { diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboard.java b/java/src/com/android/inputmethod/latin/LatinKeyboard.java index b7c4fc4dc..c7ca67727 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboard.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboard.java @@ -44,6 +44,7 @@ public class LatinKeyboard extends Keyboard { private static final boolean DEBUG_PREFERRED_LETTER = false; private static final String TAG = "LatinKeyboard"; private static final int OPACITY_FULLY_OPAQUE = 255; + private static final int SPACE_LED_LENGTH_PERCENT = 80; private Drawable mShiftLockIcon; private Drawable mShiftLockPreviewIcon; @@ -345,16 +346,20 @@ public class LatinKeyboard extends Keyboard { } private void updateSpaceBarForLocale(boolean isAutoCompletion, boolean isBlack) { + // If application locales are explicitly selected. if (mLocale != null) { - Bitmap buffer = drawSpaceBar(OPACITY_FULLY_OPAQUE, isAutoCompletion, isBlack); - mSpaceKey.icon = new BitmapDrawable(mRes, buffer); + mSpaceKey.icon = new BitmapDrawable(mRes, + drawSpaceBar(OPACITY_FULLY_OPAQUE, isAutoCompletion, isBlack)); mSpaceKey.repeatable = mLanguageSwitcher.getLocaleCount() < 2; } else { // sym_keyboard_space_led can be shared with Black and White symbol themes. - mSpaceKey.icon = - isAutoCompletion ? mRes.getDrawable(R.drawable.sym_keyboard_space_led) - : isBlack ? mRes.getDrawable(R.drawable.sym_bkeyboard_space) - : mRes.getDrawable(R.drawable.sym_keyboard_space); + if (isAutoCompletion) { + mSpaceKey.icon = new BitmapDrawable(mRes, + drawSpaceBar(OPACITY_FULLY_OPAQUE, isAutoCompletion, isBlack)); + } else { + mSpaceKey.icon = isBlack ? mRes.getDrawable(R.drawable.sym_bkeyboard_space) + : mRes.getDrawable(R.drawable.sym_keyboard_space); + } mSpaceKey.repeatable = true; } } @@ -365,36 +370,40 @@ public class LatinKeyboard extends Keyboard { Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(buffer); canvas.drawColor(mRes.getColor(R.color.latinkeyboard_transparent), PorterDuff.Mode.CLEAR); - Paint paint = new Paint(); - paint.setAntiAlias(true); - paint.setAlpha(opacity); - // Get the text size from the theme - paint.setTextSize(getTextSizeFromTheme(android.R.style.TextAppearance_Small, 14)); - paint.setTextAlign(Align.CENTER); - final String language = getInputLanguage(mSpaceKey.width, paint); - final int ascent = (int) -paint.ascent(); + // If application locales are explicitly selected. + if (mLocale != null) { + Paint paint = new Paint(); + paint.setAntiAlias(true); + paint.setAlpha(opacity); + // Get the text size from the theme + paint.setTextSize(getTextSizeFromTheme(android.R.style.TextAppearance_Small, 14)); + paint.setTextAlign(Align.CENTER); + final String language = getInputLanguage(mSpaceKey.width, paint); + final int ascent = (int) -paint.ascent(); - int shadowColor = isBlack ? mRes.getColor(R.color.latinkeyboard_bar_language_shadow_black) - : mRes.getColor(R.color.latinkeyboard_bar_language_shadow_white); + int shadowColor = isBlack ? + mRes.getColor(R.color.latinkeyboard_bar_language_shadow_black) + : mRes.getColor(R.color.latinkeyboard_bar_language_shadow_white); - paint.setColor(shadowColor); - canvas.drawText(language, width / 2, ascent - 1, paint); - paint.setColor(mRes.getColor(R.color.latinkeyboard_bar_language_text)); - canvas.drawText(language, width / 2, ascent, paint); - // Put arrows on either side of the text - if (mLanguageSwitcher.getLocaleCount() > 1) { - Rect bounds = new Rect(); - paint.getTextBounds(language, 0, language.length(), bounds); - drawButtonArrow(mButtonArrowLeftIcon, canvas, - (mSpaceKey.width - bounds.right) / 2 - - mButtonArrowLeftIcon.getIntrinsicWidth(), - (int) paint.getTextSize()); - drawButtonArrow(mButtonArrowRightIcon, canvas, - (mSpaceKey.width + bounds.right) / 2, (int) paint.getTextSize()); + paint.setColor(shadowColor); + canvas.drawText(language, width / 2, ascent - 1, paint); + paint.setColor(mRes.getColor(R.color.latinkeyboard_bar_language_text)); + canvas.drawText(language, width / 2, ascent, paint); + // Put arrows on either side of the text + if (mLanguageSwitcher.getLocaleCount() > 1) { + Rect bounds = new Rect(); + paint.getTextBounds(language, 0, language.length(), bounds); + drawButtonArrow(mButtonArrowLeftIcon, canvas, + (mSpaceKey.width - bounds.right) / 2 + - mButtonArrowLeftIcon.getIntrinsicWidth(), + (int) paint.getTextSize()); + drawButtonArrow(mButtonArrowRightIcon, canvas, + (mSpaceKey.width + bounds.right) / 2, (int) paint.getTextSize()); + } } // Draw the spacebar icon at the bottom if (isAutoCompletion) { - final int iconWidth = mSpaceAutoCompletionIndicator.getIntrinsicWidth(); + final int iconWidth = width * SPACE_LED_LENGTH_PERCENT / 100; final int iconHeight = mSpaceAutoCompletionIndicator.getIntrinsicHeight(); int x = (width - iconWidth) / 2; int y = height - iconHeight; From 9b195dda60bb2a072fcdc477206e223d60f8776c Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Fri, 3 Sep 2010 22:43:10 +0900 Subject: [PATCH 58/58] Revert https://android-git.corp.google.com/g/#change,63791 as library loading issue seems to have been fixed now. bug: 2963855 Change-Id: Iafdfda801083f85126c443508755e3cc711fbf52 --- native/Android.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/native/Android.mk b/native/Android.mk index e9ceceb71..b2944699c 100644 --- a/native/Android.mk +++ b/native/Android.mk @@ -8,8 +8,8 @@ LOCAL_SRC_FILES := \ src/dictionary.cpp \ src/char_utils.cpp -#LOCAL_NDK_VERSION := 4 -#LOCAL_SDK_VERSION := 8 +LOCAL_NDK_VERSION := 4 +LOCAL_SDK_VERSION := 8 LOCAL_MODULE := libjni_latinime

w@5gmr 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 delta 1621 zcmV-b2CDgp4CM@vBYy@gNkl6TGt!c_0Q%%!MR8!My?8)TN zG}8lmTls!_uaEo92lhe168zv4W{D_%vJ^q3k5QmlD58l7lBj5)9|S)bA{vOY`~PK~ z%enUo8TXv)@v;{z?$OOXYoFgt(X{lMTu(BqD6}p;(w~CsktdRIr&IoVc}7H z#`=7|Td3LD*~cQKhE3W}N=mw!^WnTWzXJgxlZXYB6KQE_x98>M-Ip z^n0nfxw-e*t+WF`3ACG%l5$sSYU&;M{cV`raaphx;O44%aVW!he@CGcyzIRNA1@9)5ln*H2*%kKyxS0)x7_c!XrPC%Nb?;>vD9!Gz8W zh$QGc(2wxD&+wU=m6er->vX%7cAzQHPhs~1=v$c6YxsOd7VU0&l7yWtUSxR8ae52% zAsWYo-XILP^jBW5_t)a$;=c}9r#&9ePncgN=Jg@wcYhiBBo~sQPe9^9)(LOO8#A88 zWiP?#dj$mrUze1WESHv+DyJzHYaH_|#yqb9)YH)W35Y4dNS>rVfC&n&a6f5vHT=$3IiF9;ysF9HoH9I?dU^*}` zpc)$+_kRLZ!Muo_?NO!$dXFW!he?=T!*BweSK&QHG-w#Fudi22OH0a0!bK`CFZTmN zE?U5%e!`uU`G-50C80&ixbaEc_zCVv2&Z2RqnyCz=B9F@OioS)co6dA4S4_S+`%OG zgdJKg*}4;$Yq&EZ0sn0nEC`8f9QB`Y5LWTH={X*zaQ)q3hQn749$@8V^;lSN9iH?3VTL2`V~O0(H5|L)@D1F6gM{3y;b=G-j)tS*XgC^R#rmBnwpyY-|g(|3>lxAn%Wl}OA84IhXu~K=~>nsBj+?)0e@$4 zaZy!NRQMl`4{Vn1?r#5BSy`D{SXl6n5nfeQm4CdsxmoS(?Ccj#iWHSwQ=h})B`KD? z3{YQ~E4#uG=83VfF*QFwzvnoCjE;_~wY9a7v5k$5-K0D{J^jCSD^|I)4S;8HGwfCEd2u)+1tPpdUNfuQ-$@4 zEX_0K>hXB`q?-Lak0&f44jT>$v#g&tW$7D?beO%zsTHMMICG&k7T1gUzl?=`kg39w zDt6w4CGiX`CNst@i=NGZdU|>sQ(4M96I{ja^?HAnGTRG`0`63n6lohxA%Cphl`Wm^ zL&fGQc5^j5Cw5S34kJ_j@gH1JKzWf~!=s7h8%tV?cKfX8J855Y_ zSYFHiE2)S*X_?mqRh1s)nTH1`0d$3i**)VlNZgs&?!=xeDK0<9!ffuml8CKsNRu;9 zECJDjBta)~2Y~TpdJ>F(!+%<3zGhJQqH4Dqw#4oY9ybVui^nq!3(RHfHn%fcFNOy( z#H3l|GY*mMD6RZD7oRXh?b{<0Mfh z5ENI5lcF1oXGKJ%i2N*1^0KRPM{-N!S!^Ubgai7?X`D%pZp)C9-A*80D&O69t6@vp zgyJ|4E}YReZM(PZ2bKZM1TA7}*fq6ByJECx(V|6*7A;z|Xwjl2x|v#@XoC^$4QFfxG{cJ~i`JN?nK s#60UCia1cg$Mhq!*sf$g5=~&Z6)E*a;IrJGn+!nU>FVdQ&MBb@091WCRsaA1 delta 1523 zcmV zW1j1Mx}43==Xc%o(|r!}DNYVdP$yO3`7hoV$tTb<&C6+%dwjES!96&*GSCFVeM4u%#t2^A>x*EH4 z`%YN-<@{FJ=lZ}XFZ)C?tOT`b_QS#_Zk-GfVdcW75Y# z2@cgArhl{@(UH5odSq}Qo|bPYJfR#jf%Nq$i>4nLCq5a82g5nhQRu2hUnS#r->r$6 zrnHO}idJ;?sWDdGK+C|aYrIdCUwvllclG2D8H7|aC#Yvmua-b59dgq9B)30-oekmg z4uKyhdZ>&u$p$UA>U!@3l!Joi1F$$?$u-FtqJKJOa>pdiK#{WoJXoAOA_*35v61Nf z!xLX++qa+47bJMhrTa$6`V=tO+0-6H%UP%lm?*|#$JQmwb+>g&#zCkkR4*WwXG*Cev)i?`Itg_~N6d;ncs3prGkO=NW@t|N4; zTYnIeJGx5G0y6num{1?R?1~7w*3C<%5pjE2NssKQ+-pX&ly2A)SLrUvm{#~95I`3H zo0O8C*pU9JmbeO6ut~96Z-}8g$dgiJdseKLf3XD&!p>`%70+vMp@kt;JCE!&Pm@pr! zM#1J-N|$Ddlx(*|-JBJfU?>cQnpot^yH``CCD4kUFgBZ^`6 z%@tPJ(Vm+mT|=TMY$@|7*zvNaId4aNNT zpOn5DdsG(zK;e9ty3)CY($izl9k*nsNc+vz@<^qyM&V04Iw3V+NCpRCilHi6Hb0+lcXHqJ68YPUn*xBenYYI%-PJ@!S)bDCHK%F7@L?CCM=*U7S{G z4YvxVMO>r-YIMYe7>K5;E&(tWhT2)>eq|M8N+;)@l?{#3=htkrXjM5dHWvp8_v#$c zQzk!9v(_O~?yT(2M}En65o~anGhd={%Q~spy??P^(zx`a=t7`j6!G?BYLe(_vPGW- z4x(uW=}+ENpnY2TEKM_Q32=UjG{oQ)?KYRT)_Pmcbkh>xF&t6miwkG}v ZFaQl6J&grV=e+;`002ovPDHLkV1lM`>CpfH diff --git a/java/res/drawable-hdpi/keyboard_suggest_strip_divider.png b/java/res/drawable-hdpi/keyboard_suggest_strip_divider.png old mode 100644 new mode 100755 index a5980388a979b9348d43a7c9e8b97b312c0fa00e..8cc85b7f5fae8f0835e26adb9c0fe6a79b08eb2b GIT binary patch literal 945 zcmaJ=O^ee&7>>KJl!e8!9%RU}o@~C_Znr~YX)}o%F{QQz3tr5}v<=;4VluU9QINfe z_yar${sjMk2l42|gBQV*?A3#RKv^fqMH(La$BP*E7VW;fn7B2MZ`=m; z6f%JTQyZkgNtnP?<(ImUowI9^2TKT@sQg7x1FHix5@S#iq@pVwO5jiyt=Ch_X_YtFWX%Ndl{nXWn9O2)oEw`C^vJk136yD9&axVOA1IJQC$vt(IvhN|7Oo z$vmWXS`3r@Tmj+4js1xFBm|kF?T{%|c^2tK3PH4%4U<)wSi!{9jzn3IvXpY5W&Ix- z1Z#9cyZAERe+no4d4$C-PRKNNS>uNLnX3qDF}5j*`-Gh2RqTujCCQjXK=D$f)I-}fLYAIa6St~Z;k$}%!qx}rDr(h)*R$s@k zWyX5&amc1UW@G*O>BFn+NgSA{*-yVYzs}Da+Xd;%+mGMR&bFN2Bj@?){hep68=tv? X#J%$Ge#Oa)AK4=^^)`CfdUW~+b{i%f literal 2852 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 z z;8Y@2^ATLiY&KhQK|w(gj(n%n=?1R?z{)oojd>6XO(!8m0Bst_@Z{vAe`;!K(&zJy z0iatb)hSG=S12xs|Bfsa+D#2iz%nYZsHhsGS}33faH`61R8&;d+U@oloGS(>@Uv-n z)DtZ!VCg9s3~B%y#pfpgYH(y^q;qI!$UQMJQGnO^inC%6>Pz4nqPYq!7Zqj@h3FI} zkgys7r>?ZLwASPCGy={o`T6;7s7os>EY$E^gX;7Ih0S!n;&DC2VlhH9LtQ1~WewOohe`CQXbQ^!q82J@fMaqCl(ZWKUIb{ms^DnMs%gGqGCOVjs(nP1WF7jeYI#VwrA!XQ1f& z=!zsTD3!mJclq+=t*8(*!9f7@pv-w4vmNUSNIi_|3 zD@4t&tf{Hl1yxnj3@$gUD`XAx>UO&|R17Or{ZTkKH2~=rUaBR>$|z?pMs||(QD|-y zUJX>XiLlt#q;q~vDvjn56{G_Hxe2N(6>X_iT-zG36n!s!U>D}E1U3F6C_Ii}=mp9) zE1ii4Rg8WfAGgE7DMuUUl)!|^UIUhN9eLkD$$z4u3-|*D6D+A+_&P<$xd;mLk(yeSy517HbUV}1=yOxQe6v762}DBv17d0 zzSfd109^+5^8l&#G=6TI&G!70<>k8-Xg7z#a{aJ$bj-rK*wpk) zmC1C!7L96o@wn^L1qDC(n%jMwHWP_uTvJ$j3n+8}8 z9`nNLibjV%HaPhGbCF1&HWS2?Se3w5fJv0F3eQV3NLbP6><2odQSZlwh7MndL{8!5 zAd*kG_^V%GH|kbrq7vaz2DRD&>qm8frSZM1VLb_0C-9Pi_6++Du3BKZsxV$xBobj; zX}{t1uKxIdM$?kB8hl&~&pGYc#N>4LT9)?epf__p8gFFaLW|ATt7d4DQpWg1pa zDlFS3Q7B6TEXxat#9y|UOgmF4>!8=0aae0!VhUJXJP`_ow6CY{6P< z!&1Ns1OnP0z5l+p!{@6^q=5DD;o+>oT2ojGSbuQ*xVGKv)wCRhl__BA6vS0qGB|pA zvfhSq;U8iB;XChW+xz=d!a6uSeE4EC`WwE~X2Q7RqWt7;1)7$DkZyAZV3|c<#;Oe2 zM6|iB7^2x!mxM)SZ3C=iGuRQ0j(mJ%rA@U~MGMSIyN>-R`zieDU zUQ$w0>vFm3STm=mr@h0&!vSu?pv|px%twdSk||gRsI0!etCf|Pr+vfY;rR*M#DrIv zLBip>wQ{%HUB{K7R;xA7=kqZizOk{fA@LdGN(W}LSS;4Y#>V2x%F27uA>GADHo$8~ zrk^`^?%Wg#Pul(>zu#YwPLnvFvIy%RTU)iff&$Iy_eVrPtKMeed2v-$m8ZVG{-fb= zc(2iDG$RkarKP1m{P4pM+X2m-iMBZHULxS+A(PF3up5th7@ODYZNlSS#l^+Ly}iBC z{yT!fU|}|u^&P;nS61rb+U%F%I|agw$8o)GRJtZqz`e)^cihoNMn-B-$@bUP)x8H` zhSdO!3&0tE-2zi$-~v5{`!O6E1yYOiW!l`fcy`p>qIARB4p^y_^__L=bXeRTf}f{? z@K`L`s00AfBsN!6RG6W(*~m%qnU8PTvc=fe)~0hqrcKq=)q23~a)oNot1JbUx={cI`6aH;lX6s4YOeM?cs?cl!OC)!Q<;s1U$*59@Ts6XT+-hjqI>pyfmR&J}(#-L{ zc^%vrgd4EPYavKs%4g4IW85>{z!J!4${eA9&cg|L5rBG72ocogd=x|zysj@Vml@nj zWhG5MUXZZhU=Wt7EcF1KV`XJ!zr_0^%)`XQL@|DM2cF-bA}^}~SVGiHIWm7mp#o6g z{Q2|mbaZr_Mr{tly)W3kdp9@#(rfl|I2c+gSZ!_d!r}xberM=|4?Z|HI5@~*DJrW0 z?QH|wF)m(L+GkeEjBWg!ZeVe=S21QvH6Nm2ji|NSnKNhNVzfK7ZQHgG3y*7@7XyoX zBko6=bzNn_47yydE6iZBSrZ`wQS`F{Cr_T_NQ}9usVQDlQ=^+jC8|n7i)$I07c-_C z7z!muXekQVfQDV&Rw0T;J-nEGcU4$RQI_f$aa<6eiHLk~OIkCMB}MznJj(6W<0~21 zY-Ug}z7&OGL+0finO^Q_?78o5cu}z4dQ02d+p8sFv6)zRp=frB7XnLZmnOxv5SSU) zX2#%P!xsagBv{o<(1#a0!UR^TL>$K zvYr4e+YOk(D=r$)0ks$HY*2KbEw~(^_x1u9E`h@)@zJFnLp5S7V>?-t;@Woktt zIGi69Bl@w`U=m|fQ&S-{)R$2P2^AO%0G?MVObrKExt_`Zbxq;i8MSXVpBdcJ({r^M zTmmdHg3*O*9PaDui;BwR;C2*vuUP#ZRxEt38`mSZ>C;v^u*AT?KoGTZ44EB~ri8Ur zj3uszsp8IQ`l>~^_|tHke@QRxhG3;q7CN?v770uKJ}S{En8R^VKKZZ^E}V1YddpbZ zRBsorFT$Ig&Qu$gcBg|4GTMYmKx$_OWo9{=z#XmutX#AW_7f*ggexj4euK|<$Tm++ z1j&BZeQ&;bZDp~|0<2VR){P`q2AIPaFI>35kN{4o7NFl%3h>Ra6n4UwpXJ8R=z^TO zeEG6p%g|P{nHXh`vbG|lr;~@FaMVFj6?l&-D@4D{jLzyXl<|DB%C7PTuc0h^Rh15F zp~{jb4i)Pi06KB}`0v#+e4NW4`zX*jw zaar35429|{Dk^FNGzPYCFIVRqZ@dw1Zf^b=09{l~4`E4V#ZxG2sj$QdM--joBk#WZ z?ieZ=y;m2^VL5)Y3ctnu@~@~sc<&_I=rJvWp?aB6SRAVH+wJ!AsFm%~)Ul>=hzB+I z&a$$yS`;vE)lq!z+&K%NjpE!94iTwl@LJ0H-YvH*$qdTKUtGig;ClY|=Rf~Bzs`W0 z3RE-?(ngrRLRK<){k%5(-z#Xp#xvD^WeQlLySqCA7kLszxwK{y=c4GFJu^7Eq=Ei zPS8dusf1=$9cx5|dWF$a@N6@>>vqPbwx56g`5JKBNQBSIx|+g22IEson!F!lJT zo;o`_J)e8|<*#oZ9CW2p)*&d%Dn>9k!oL_ZD3mphcI&I~P*1(~+G{qUat{DC@b)42 z-L0HGP`yK#!=cvJ*8e> zSy}BSlmGFyw$M^xap(z9egQN1Cr6JSJ%i)`07mpS;`f>Wi8tr@J*dB);RB)zA{BW7 z>U!?%*|QT`hL;*;8kk;I@B+to?%eqlGX8<|xLD{kI{;Ae_u=sVJtkAjRm)TpiLuWo z690-G_+OzwUxH~3F4PPPPw+UD{3-nZUmQAgX!zK%V{Vu@n&D==*GyRGR@@4QV-xqX zrz@{`hSA2x#&5$Z>3R0qXG6VCXU10}W;&uI0cRqNn%$3D`Zt#@UHS?4hnH>IXWHAf z9aB^Gc(NIc$EO|+24C(=B-)EkojQ+N|LZ+__WUyn{Vw#E_QAy7AqJ6Cnm&Ly1G9D# zrtH;$fq@Gs>?qnF8@|UoKrlA45`Ze8DXCt~K>Otn-OP@PRj{g_jNE%zDD1@j_uv08KzD!XOJ52T7~iY)`EIDa zT+zUIJoeaQc_{E2sO)d=`PHvJo62?n&}2${wXm?W$LH(t`~7_=Xl@I{1qvKppohjT zf**_k(QDE5$vNJsW^wTEP{`e~fLt||?oN@%?+a8a>WH5Nz zYHJx|5rR20j*pKQihF#`-j5j|1EZs(VJ5{9Flux6bg>DO$>ikJ4&d;vNlto$IM)V6 z6|l`>H$#nrf^z%O=6)LIe}_(TK!uf+g3E%!W;fb;r>N+eT7%)Ly_+tgq5mhi?&i`` zy`}>el|m=uBA{IIdc8q3{6UyJ_U+^y_2e{tT=^e)+k0;OY=LKJhobCIqP@JlybR~o z16&DjNhSMp^7^IQzkU1m&*JkO44(e%6Hi>_6=qstnFcls>v&;dN?4by*2MR2yUk!1 zV}tCcaiA4|bQ6b1KWC+(vH>_8LjV~CxF}x7nebUXLjcYBHY3cX5zmcKNFEBl5baeB zKyc!;lrB5XU-Dov+bo#XcVPzq9L~{c^w9#JdHnH|E_|I5xxCtd%?s1ZfJe5@=)mLKzJHVVpjv_Gua!@Z-X37fl|2mmVM$ zrQVrVc!Ob>#vh@r`aWI`!7B`1&kU|sU~{kv3ZAJ+0joQa@P0B9IXqQT^8P12@d+Oa z^f4&sk41s21*(rWaI{YH=FG5Xsr`kuJ zrb`8-&Qhx@OGFIG^;VknpiTS9!Gi~%MR%bOo?_s#-F`y_v)X{o!g|~3yq>b2>=3Xt zvBL~|rMZ?>WXe9y?p$X>Kxn{n+Wi@3f4nA^9YqSqdL z@WKCvLdWpi{)K{CZNO$>z2$J|uo&HxNP_jLX!I&r9TrRc8U-`EQ436DK1^Kx(W6H< zcXV{@gWJCj09*0j%}EXfos#$9Xq<)n-f{cwxBq(IzI~S%mWFd2q6n*%V=+f#IGj;n z>FPM^8>+mSmv^{28aAh$ z?HNE$dal}mx>gurx;pr7`ImtTIF|K-JhEc+%dt3_e@%9U@$Vkb~S zKYh$-{3HyOfv_Hp#jb+Yo|hM2YNk||UKs;STft@PNEa}wg|*pxC>DDKb>4B0!SIn! z$6`MKtp7`fwOr!9M(xhX{uwJB7^^ae0Jw*{=^L@wGe6L@pN-FqwD)St=8y}i_07?! zK^fRJ3e#&xN7~L!mDNRq;yKr#S;gS5wJ8!&*Ks8-nazncU~|A&IGq0A4wmENGyfG3 z=Wci>PX&@m8O+U7M&Vt7K)?kswp8kZM=9sNV&XdynVM%pkyjMFbT65W2ta;emgM$y zaRtbHCe9=PNu@B^MdEac3ku_;r6a{}7~v^$M!8meUhdB*6Nf263cQT0Q_fXjs?ru3 z%4|piMHqDdsFp(U=#=N+-j{{L;lku?7~t9)p}rbXLB<6zIgchMK;>&WO%uyyaJjZg zvvd&50u+I8cGxA%TCsR8f$2&^SE7K+SyPxq?qpNJU2O2YOsL8yKr!lxi}A+9W!#y@jR1LUND#6GlFI6}ihiPK4HTfM**+SfsWaz``?%OcDlmBesq26l4gNV(N& zEh#E0asf_3VPRnj0M+2X7`nu}tJ^ukp+@KO08grPtIOqz;ClhCp+;LbGCe)rJ3c<{ zo0ymw2gnk@bBhY%(B{@$OSQ#nYiqBWsqXIXl|9n2h>;NqOPat^0jd@ST#G`lLSdIx zR8*Ab=jXSez)Jy#yPV29n(K31a;{6=gpB({anh5C&*l6XXQ=W17|dwr;NW1-=;$aR z4geg3e7Z%~!z&aRxE{2d3YY@RBHAUIJvs?>0KuqR#@u@VX9E=nGpNT3N>EgkoRPj> zXadI-Z_`%ZpZa;9kf|Q2G7nGFKHMC0Oh)~si`SFRs`qzU?NX;;lQ~LhPDZC5?Uw~ zv`hmtXIWh);px%y(^ri+oz6xsiU6cNFmV;7rKNiO1wl!3x713;zvk~zrHt#~fHBNs zHB90?ZEbDuw70h#@R~6qQKeg=_aU?0gk;-GG%LU=pdwEb4u`{WH-Hrrmb#)c4V7jV zoM;F0VHS6IP1ru!Jx$;~A*1xr1| zick%0Cj(FSZQQuggSOP1G*oue0@LTr04us@&mP7K9zgdw&c^ z<2byvo}3xjG#DnJ{Bw8SdFQv_46z>;LwlBWV1^usbC5T;=CG74N4zn)Pcb{o9NiC~ l!<^C__Vi@7j{Uy?0|3tn{21gEY83zg002ovPDHLkV1nuvb3p(A literal 5615 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 JPDHLkV1m-vmY4tl diff --git a/java/res/drawable-hdpi/ok_cancel.png b/java/res/drawable-hdpi/ok_cancel.png index 6a99528ef3e6e2bbc00e516001c923b295361a0a..f11e57a38991396ccff91cd61604d01888b95eff 100755 GIT binary patch delta 714 zcmdnR+{QM+qn>Gnr;B4q#jQ7Y9kXsbFtlBqxU{3>^{s#t_ryQs?$UZ9)HrS0H@Vg| zRZ{m4M2mB&#!9K5C~`km*2AsXo5s`l-9eBuGV}9C@2+5<<(C;4{>;Cb^KH$2?WBy? z75`-V`9JO`ddaY0`}~hPdXI0{s{8q?%w(4&U;9EG@9As|aVs?HyK=qRn-5-{zk7Fo z_t8afoT~pm`($)yeOTh=n>)N1E+}ug8+g4`qSsBa?c1)dLfP`lTvsuMs+)Y*D(=|Z zw7hz>=y%;6-CGy7yS!NK15a!$WrsfGc=gq)jY%G-f_^|mrtPGNoTNoxJUj&Oyy=EN6U~zlV)JO&oiCYiOS2H}&>AnWiG|`ot zK~j9}1ty1g7k+(~WAKQ&RsVmbgW#T89)^=qyRGf@ZY|o7!>I6dm2G|879nninPP80 zI!7}o99>{rE9sTNsF0f3FP2*Xw0TllS^2gM#siC38^ZTw>;*buCHvax3mFvBF;y@C zJ-Q)-@j;Ca(06iCK;EQVbK0%}wN6=TTj|Eluq1v9^K>SLPnI>;3>hXATzq#ctNtQW z1JJd=04Q(*+N-?1k5PdcNIc+a0ft)DpXE#p4pw=x%no%<+zb%Jq00b4AGWOe-Lc|v ze}Ycep-{#K@muDl_pfK|jr*T>yKK+@MxgiiUntXE``W6cckQfYKjoaOh4*uQe8a`) z;GY`V_O$3`>DO(}UGe*loVd2}!29IJ`#WtIF8JrXUVk;~t1{d7V8fX{hh7#(F+9lp h{PR!b{_o)pj0{U37b;(mIUCFX1fH&bF6*2UngCO3Jgxu$ literal 442 zcmeAS@N?(olHy`uVBq!ia0y~yV7vunyKt}pNwxo9G=P+3iEBhjaDG}zd16s2gJVj5 zQmTSyZen_BP-$-(Y0O{@L@`f>(2?d)-beeuju}xy|R} zGxYnI7*<*Ef3~q^V_4ym!RP=+3=3JIs6~un8+UHcMNNhVS8fI|U512FxWL5lzs8D+7x6vGCXQ4M8(7PBHGf$~6xBfvf_sbhK7IaFgCQaG{hvG4|1%gD%v;aE%%C=V#o7g*i&KD+!QkoY=d#Wz Gp$P!_K#6Yv diff --git a/java/res/drawable-hdpi/speak_now_level0.png b/java/res/drawable-hdpi/speak_now_level0.png index a681da606b634b33c3ce5be7096c5ec42afca4ba..342849cfeb13cd8f3a6dcd6befe53f3a6abca5d3 100755 GIT binary patch delta 5998 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