aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java10
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyDetector.java9
-rw-r--r--java/src/com/android/inputmethod/keyboard/Keyboard.java53
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java5
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java5
-rw-r--r--java/src/com/android/inputmethod/keyboard/KeyboardView.java7
-rw-r--r--java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java330
-rw-r--r--java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java4
-rw-r--r--java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java2
-rw-r--r--java/src/com/android/inputmethod/keyboard/PointerTracker.java263
-rw-r--r--java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java115
-rw-r--r--java/src/com/android/inputmethod/keyboard/PopupPanel.java20
-rw-r--r--java/src/com/android/inputmethod/keyboard/ProximityInfo.java69
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java27
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/PointerTrackerKeyState.java105
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/SwipeTracker.java157
-rw-r--r--java/src/com/android/inputmethod/latin/CandidateView.java9
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java190
-rw-r--r--java/src/com/android/inputmethod/latin/Settings.java16
-rw-r--r--java/src/com/android/inputmethod/latin/SettingsActivity.java20
-rw-r--r--java/src/com/android/inputmethod/latin/TextEntryState.java3
21 files changed, 622 insertions, 797 deletions
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
index a87ff9891..8ca834148 100644
--- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
+++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java
@@ -29,7 +29,7 @@ import com.android.inputmethod.compat.AccessibilityEventCompatUtils;
import com.android.inputmethod.compat.MotionEventCompatUtils;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.KeyDetector;
-import com.android.inputmethod.keyboard.KeyboardView;
+import com.android.inputmethod.keyboard.LatinKeyboardBaseView;
import com.android.inputmethod.keyboard.PointerTracker;
public class AccessibleKeyboardViewProxy {
@@ -40,7 +40,7 @@ public class AccessibleKeyboardViewProxy {
private static final long DELAY_KEY_PRESS = 10;
private int mScaledEdgeSlop;
- private KeyboardView mView;
+ private LatinKeyboardBaseView mView;
private AccessibleKeyboardActionListener mListener;
private FlickGestureDetector mGestureDetector;
@@ -57,7 +57,7 @@ public class AccessibleKeyboardViewProxy {
return sInstance;
}
- public static void setView(KeyboardView view) {
+ public static void setView(LatinKeyboardBaseView view) {
sInstance.mView = view;
}
@@ -200,8 +200,8 @@ public class AccessibleKeyboardViewProxy {
}
private void fireKeyPressEvent(PointerTracker tracker, int x, int y, long eventTime) {
- tracker.onDownEvent(x, y, eventTime, null);
- tracker.onUpEvent(x, y, eventTime + DELAY_KEY_PRESS, null);
+ tracker.onDownEvent(x, y, eventTime, mView);
+ tracker.onUpEvent(x, y, eventTime + DELAY_KEY_PRESS);
}
private class KeyboardFlickGestureDetector extends FlickGestureDetector {
diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
index 85418a61d..6d25025c5 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
@@ -73,11 +73,10 @@ public class KeyDetector {
return y + mCorrectionY;
}
- protected List<Key> getKeys() {
+ public Keyboard getKeyboard() {
if (mKeyboard == null)
throw new IllegalStateException("keyboard isn't set");
- // mKeyboard is guaranteed not to be null at setKeybaord() method if mKeys is not null
- return mKeyboard.getKeys();
+ return mKeyboard;
}
public void setProximityCorrectionEnabled(boolean enabled) {
@@ -154,7 +153,7 @@ public class KeyDetector {
}
private void getNearbyKeyCodes(final int[] allCodes) {
- final List<Key> keys = getKeys();
+ final List<Key> keys = getKeyboard().getKeys();
final int[] indices = mIndices;
// allCodes[0] should always have the key code even if it is a non-letter key.
@@ -188,7 +187,7 @@ public class KeyDetector {
* @return The nearest key index
*/
public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) {
- final List<Key> keys = getKeys();
+ final List<Key> keys = getKeyboard().getKeys();
final int touchX = getTouchX(x);
final int touchY = getTouchY(y);
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index 280c0c9d8..0b4fce417 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -141,14 +141,6 @@ public class Keyboard {
// TODO: Change GRID_WIDTH and GRID_HEIGHT to private.
public final int GRID_WIDTH;
public final int GRID_HEIGHT;
- private final int GRID_SIZE;
- private int mCellWidth;
- private int mCellHeight;
- private int[][] mGridNeighbors;
- private int mProximityThreshold;
- private static int[] EMPTY_INT_ARRAY = new int[0];
- /** Number of key widths from current touch point to search for nearest keys. */
- private static float SEARCH_DISTANCE = 1.2f;
private final ProximityInfo mProximityInfo;
@@ -164,7 +156,6 @@ public class Keyboard {
final Resources res = context.getResources();
GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width);
GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
- GRID_SIZE = GRID_WIDTH * GRID_HEIGHT;
final int horizontalEdgesPadding = (int)res.getDimension(
R.dimen.keyboard_horizontal_edges_padding);
@@ -177,12 +168,13 @@ public class Keyboard {
mDefaultVerticalGap = 0;
mDefaultHeight = mDefaultWidth;
mId = id;
- mProximityInfo = new ProximityInfo(GRID_WIDTH, GRID_HEIGHT);
loadKeyboard(context, xmlLayoutResId);
+ mProximityInfo = new ProximityInfo(
+ GRID_WIDTH, GRID_HEIGHT, getMinWidth(), getHeight(), getKeyWidth(), mKeys);
}
public int getProximityInfo() {
- return mProximityInfo.getNativeProximityInfo(this);
+ return mProximityInfo.getNativeProximityInfo();
}
public List<Key> getKeys() {
@@ -219,8 +211,6 @@ public class Keyboard {
public void setKeyWidth(int width) {
mDefaultWidth = width;
- final int threshold = (int) (width * SEARCH_DISTANCE);
- mProximityThreshold = threshold * threshold;
}
/**
@@ -365,34 +355,6 @@ public class Keyboard {
return label;
}
- // TODO: Move this function to ProximityInfo and make this private.
- public void computeNearestNeighbors() {
- // Round-up so we don't have any pixels outside the grid
- mCellWidth = (getMinWidth() + GRID_WIDTH - 1) / GRID_WIDTH;
- mCellHeight = (getHeight() + GRID_HEIGHT - 1) / GRID_HEIGHT;
- mGridNeighbors = new int[GRID_SIZE][];
- final int[] indices = new int[mKeys.size()];
- final int gridWidth = GRID_WIDTH * mCellWidth;
- final int gridHeight = GRID_HEIGHT * mCellHeight;
- final int threshold = mProximityThreshold;
- for (int x = 0; x < gridWidth; x += mCellWidth) {
- for (int y = 0; y < gridHeight; y += mCellHeight) {
- final int centerX = x + mCellWidth / 2;
- final int centerY = y + mCellHeight / 2;
- int count = 0;
- for (int i = 0; i < mKeys.size(); i++) {
- final Key key = mKeys.get(i);
- if (key.squaredDistanceToEdge(centerX, centerY) < threshold)
- indices[count++] = i;
- }
- final int[] cell = new int[count];
- System.arraycopy(indices, 0, cell, 0, count);
- mGridNeighbors[(y / mCellHeight) * GRID_WIDTH + (x / mCellWidth)] = cell;
- }
- }
- mProximityInfo.setProximityInfo(mGridNeighbors, getMinWidth(), getHeight(), mKeys);
- }
-
/**
* Returns the indices of the keys that are closest to the given point.
* @param x the x-coordinate of the point
@@ -401,14 +363,7 @@ public class Keyboard {
* point is out of range, then an array of size zero is returned.
*/
public int[] getNearestKeys(int x, int y) {
- if (mGridNeighbors == null) computeNearestNeighbors();
- if (x >= 0 && x < getMinWidth() && y >= 0 && y < getHeight()) {
- int index = (y / mCellHeight) * GRID_WIDTH + (x / mCellWidth);
- if (index < GRID_SIZE) {
- return mGridNeighbors[index];
- }
- }
- return EMPTY_INT_ARRAY;
+ return mProximityInfo.getNearestKeys(x, y);
}
/**
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
index 7e67d6f6b..905f779c0 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
@@ -70,9 +70,4 @@ public interface KeyboardActionListener {
* Called when user released a finger outside any key.
*/
public void onCancelInput();
-
- /**
- * Called when the user quickly moves the finger from up to down.
- */
- public void onSwipeDown();
}
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 275e9d1fe..bb21d7a63 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -152,7 +152,8 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
boolean voiceButtonOnPrimary) {
mSwitchState = SWITCH_STATE_ALPHA;
try {
- loadKeyboardInternal(attribute, voiceKeyEnabled, voiceButtonOnPrimary, false);
+ final boolean isSymbols = (mCurrentId != null) ? mCurrentId.isSymbolsKeyboard() : false;
+ loadKeyboardInternal(attribute, voiceKeyEnabled, voiceButtonOnPrimary, isSymbols);
} catch (RuntimeException e) {
// Get KeyboardId to record which keyboard has been failed to load.
final KeyboardId id = getKeyboardId(attribute, false);
@@ -763,7 +764,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
}
mKeyboardView = (LatinKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view);
- mKeyboardView.setOnKeyboardActionListener(mInputMethodService);
+ mKeyboardView.setKeyboardActionListener(mInputMethodService);
// This always needs to be set since the accessibility state can
// potentially change without the input view being re-created.
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index d1345db9d..e31aa8478 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -331,7 +331,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
mPreviewText = null;
mShowKeyPreviewPopup = false;
}
- // TODO: Use Theme (android.R.styleable.Theme_backgroundDimAmount)
mBackgroundDimAmount = a.getFloat(R.styleable.KeyboardView_backgroundDimAmount, 0.5f);
a.recycle();
@@ -350,12 +349,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
return a.getFraction(index, 1000, 1000, 1) / 1000.0f;
}
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- // TODO: Should notify InputMethodService instead?
- KeyboardSwitcher.getInstance().onSizeChanged();
- }
-
/**
* Attaches a keyboard to this view. The keyboard can be switched at any time and the
* view will re-layout itself to accommodate the keyboard.
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java
index c8cfb43e3..b5b623223 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java
@@ -21,6 +21,7 @@ import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.os.Message;
+import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
@@ -33,9 +34,10 @@ import android.widget.PopupWindow;
import com.android.inputmethod.accessibility.AccessibilityUtils;
import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
+import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy;
+import com.android.inputmethod.keyboard.PointerTracker.TimerProxy;
import com.android.inputmethod.keyboard.internal.MiniKeyboardBuilder;
import com.android.inputmethod.keyboard.internal.PointerTrackerQueue;
-import com.android.inputmethod.keyboard.internal.SwipeTracker;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
@@ -49,7 +51,7 @@ import java.util.WeakHashMap;
* @attr ref R.styleable#KeyboardView_verticalCorrection
* @attr ref R.styleable#KeyboardView_popupLayout
*/
-public class LatinKeyboardBaseView extends KeyboardView {
+public class LatinKeyboardBaseView extends KeyboardView implements PointerTracker.KeyEventHandler {
private static final String TAG = LatinKeyboardBaseView.class.getSimpleName();
private static final boolean ENABLE_CAPSLOCK_BY_LONGPRESS = true;
@@ -64,7 +66,8 @@ public class LatinKeyboardBaseView extends KeyboardView {
// Mini keyboard
private PopupWindow mPopupWindow;
- private PopupPanel mPopupMiniKeyboardPanel;
+ private PopupPanel mPopupPanel;
+ private int mPopupPanelPointerTrackerId;
private final WeakHashMap<Key, PopupPanel> mPopupPanelCache =
new WeakHashMap<Key, PopupPanel>();
@@ -74,7 +77,7 @@ public class LatinKeyboardBaseView extends KeyboardView {
private final ArrayList<PointerTracker> mPointerTrackers = new ArrayList<PointerTracker>();
// TODO: Let the PointerTracker class manage this pointer queue
- private final PointerTrackerQueue mPointerQueue = new PointerTrackerQueue();
+ private final PointerTrackerQueue mPointerQueue;
private final boolean mHasDistinctMultitouch;
private int mOldPointerCount = 1;
@@ -82,15 +85,13 @@ public class LatinKeyboardBaseView extends KeyboardView {
protected KeyDetector mKeyDetector;
- // Swipe gesture detector
+ // To detect double tap.
protected GestureDetector mGestureDetector;
- private final SwipeTracker mSwipeTracker = new SwipeTracker();
- private final int mSwipeThreshold;
- private final boolean mDisambiguateSwipe;
private final KeyTimerHandler mKeyTimerHandler = new KeyTimerHandler(this);
- public static class KeyTimerHandler extends StaticInnerHandlerWrapper<LatinKeyboardBaseView> {
+ private static class KeyTimerHandler extends StaticInnerHandlerWrapper<LatinKeyboardBaseView>
+ implements TimerProxy {
private static final int MSG_REPEAT_KEY = 1;
private static final int MSG_LONGPRESS_KEY = 2;
private static final int MSG_LONGPRESS_SHIFT_KEY = 3;
@@ -120,6 +121,7 @@ public class LatinKeyboardBaseView extends KeyboardView {
}
}
+ @Override
public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker) {
mInKeyRepeat = true;
sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, keyIndex, 0, tracker), delay);
@@ -134,11 +136,13 @@ public class LatinKeyboardBaseView extends KeyboardView {
return mInKeyRepeat;
}
+ @Override
public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker) {
cancelLongPressTimers();
sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, keyIndex, 0, tracker), delay);
}
+ @Override
public void startLongPressShiftTimer(long delay, int keyIndex, PointerTracker tracker) {
cancelLongPressTimers();
if (ENABLE_CAPSLOCK_BY_LONGPRESS) {
@@ -147,11 +151,13 @@ public class LatinKeyboardBaseView extends KeyboardView {
}
}
+ @Override
public void cancelLongPressTimers() {
removeMessages(MSG_LONGPRESS_KEY);
removeMessages(MSG_LONGPRESS_SHIFT_KEY);
}
+ @Override
public void cancelKeyTimers() {
cancelKeyRepeatTimer();
cancelLongPressTimers();
@@ -172,6 +178,52 @@ public class LatinKeyboardBaseView extends KeyboardView {
}
}
+ private class DoubleTapListener extends GestureDetector.SimpleOnGestureListener {
+ private boolean mProcessingShiftDoubleTapEvent = false;
+
+ @Override
+ public boolean onDoubleTap(MotionEvent firstDown) {
+ final Keyboard keyboard = getKeyboard();
+ if (ENABLE_CAPSLOCK_BY_DOUBLETAP && keyboard instanceof LatinKeyboard
+ && ((LatinKeyboard) keyboard).isAlphaKeyboard()) {
+ final int pointerIndex = firstDown.getActionIndex();
+ final int id = firstDown.getPointerId(pointerIndex);
+ final PointerTracker tracker = getPointerTracker(id);
+ // If the first down event is on shift key.
+ if (tracker.isOnShiftKey((int) firstDown.getX(), (int) firstDown.getY())) {
+ mProcessingShiftDoubleTapEvent = true;
+ return true;
+ }
+ }
+ mProcessingShiftDoubleTapEvent = false;
+ return false;
+ }
+
+ @Override
+ public boolean onDoubleTapEvent(MotionEvent secondTap) {
+ if (mProcessingShiftDoubleTapEvent
+ && secondTap.getAction() == MotionEvent.ACTION_DOWN) {
+ final MotionEvent secondDown = secondTap;
+ final int pointerIndex = secondDown.getActionIndex();
+ final int id = secondDown.getPointerId(pointerIndex);
+ final PointerTracker tracker = getPointerTracker(id);
+ // If the second down event is also on shift key.
+ if (tracker.isOnShiftKey((int) secondDown.getX(), (int) secondDown.getY())) {
+ // Detected a double tap on shift key. If we are in the ignoring double tap
+ // mode, it means we have already turned off caps lock in
+ // {@link KeyboardSwitcher#onReleaseShift} .
+ final boolean ignoringDoubleTap = mKeyTimerHandler.isIgnoringDoubleTap();
+ if (!ignoringDoubleTap)
+ onDoubleTapShiftKey(tracker);
+ return true;
+ }
+ // Otherwise these events should not be handled as double tap.
+ mProcessingShiftDoubleTapEvent = false;
+ }
+ return mProcessingShiftDoubleTapEvent;
+ }
+ }
+
public LatinKeyboardBaseView(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.keyboardViewStyle);
}
@@ -183,91 +235,23 @@ public class LatinKeyboardBaseView extends KeyboardView {
attrs, R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
mVerticalCorrection = a.getDimensionPixelOffset(
R.styleable.KeyboardView_verticalCorrection, 0);
-
mPopupLayout = a.getResourceId(R.styleable.KeyboardView_popupLayout, 0);
- // TODO: Use Theme (android.R.styleable.Theme_backgroundDimAmount)
a.recycle();
final Resources res = getResources();
-
final float keyHysteresisDistance = res.getDimension(R.dimen.key_hysteresis_distance);
mKeyDetector = new KeyDetector(keyHysteresisDistance);
- mSwipeThreshold = (int) (500 * res.getDisplayMetrics().density);
- // TODO: Refer to frameworks/base/core/res/res/values/config.xml
- mDisambiguateSwipe = res.getBoolean(R.bool.config_swipeDisambiguation);
-
- GestureDetector.SimpleOnGestureListener listener =
- new GestureDetector.SimpleOnGestureListener() {
- private boolean mProcessingShiftDoubleTapEvent = false;
-
- @Override
- public boolean onFling(MotionEvent me1, MotionEvent me2, float velocityX,
- float velocityY) {
- final float absX = Math.abs(velocityX);
- final float absY = Math.abs(velocityY);
- float deltaY = me2.getY() - me1.getY();
- int travelY = getHeight() / 2; // Half the keyboard height
- mSwipeTracker.computeCurrentVelocity(1000);
- final float endingVelocityY = mSwipeTracker.getYVelocity();
- if (velocityY > mSwipeThreshold && absX < absY / 2 && deltaY > travelY) {
- if (mDisambiguateSwipe && endingVelocityY >= velocityY / 4) {
- onSwipeDown();
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean onDoubleTap(MotionEvent firstDown) {
- final Keyboard keyboard = getKeyboard();
- if (ENABLE_CAPSLOCK_BY_DOUBLETAP && keyboard instanceof LatinKeyboard
- && ((LatinKeyboard) keyboard).isAlphaKeyboard()) {
- final int pointerIndex = firstDown.getActionIndex();
- final int id = firstDown.getPointerId(pointerIndex);
- final PointerTracker tracker = getPointerTracker(id);
- // If the first down event is on shift key.
- if (tracker.isOnShiftKey((int)firstDown.getX(), (int)firstDown.getY())) {
- mProcessingShiftDoubleTapEvent = true;
- return true;
- }
- }
- mProcessingShiftDoubleTapEvent = false;
- return false;
- }
-
- @Override
- public boolean onDoubleTapEvent(MotionEvent secondTap) {
- if (mProcessingShiftDoubleTapEvent
- && secondTap.getAction() == MotionEvent.ACTION_DOWN) {
- final MotionEvent secondDown = secondTap;
- final int pointerIndex = secondDown.getActionIndex();
- final int id = secondDown.getPointerId(pointerIndex);
- final PointerTracker tracker = getPointerTracker(id);
- // If the second down event is also on shift key.
- if (tracker.isOnShiftKey((int)secondDown.getX(), (int)secondDown.getY())) {
- // Detected a double tap on shift key. If we are in the ignoring double tap
- // mode, it means we have already turned off caps lock in
- // {@link KeyboardSwitcher#onReleaseShift} .
- final boolean ignoringDoubleTap = mKeyTimerHandler.isIgnoringDoubleTap();
- if (!ignoringDoubleTap)
- onDoubleTapShiftKey(tracker);
- return true;
- }
- // Otherwise these events should not be handled as double tap.
- mProcessingShiftDoubleTapEvent = false;
- }
- return mProcessingShiftDoubleTapEvent;
- }
- };
final boolean ignoreMultitouch = true;
- mGestureDetector = new GestureDetector(getContext(), listener, null, ignoreMultitouch);
+ mGestureDetector = new GestureDetector(
+ getContext(), new DoubleTapListener(), null, ignoreMultitouch);
mGestureDetector.setIsLongpressEnabled(false);
mHasDistinctMultitouch = context.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT);
mKeyRepeatInterval = res.getInteger(R.integer.config_key_repeat_interval);
+
+ mPointerQueue = mHasDistinctMultitouch ? new PointerTrackerQueue() : null;
}
public void startIgnoringDoubleTap() {
@@ -275,10 +259,10 @@ public class LatinKeyboardBaseView extends KeyboardView {
mKeyTimerHandler.startIgnoringDoubleTap();
}
- public void setOnKeyboardActionListener(KeyboardActionListener listener) {
+ public void setKeyboardActionListener(KeyboardActionListener listener) {
mKeyboardActionListener = listener;
for (PointerTracker tracker : mPointerTrackers) {
- tracker.setOnKeyboardActionListener(listener);
+ tracker.setKeyboardActionListener(listener);
}
}
@@ -286,10 +270,32 @@ public class LatinKeyboardBaseView extends KeyboardView {
* Returns the {@link KeyboardActionListener} object.
* @return the listener attached to this keyboard
*/
- protected KeyboardActionListener getOnKeyboardActionListener() {
+ @Override
+ public KeyboardActionListener getKeyboardActionListener() {
return mKeyboardActionListener;
}
+ @Override
+ public KeyDetector getKeyDetector() {
+ return mKeyDetector;
+ }
+
+ @Override
+ public DrawingProxy getDrawingProxy() {
+ return this;
+ }
+
+ @Override
+ public TimerProxy getTimerProxy() {
+ return mKeyTimerHandler;
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ // TODO: Should notify InputMethodService instead?
+ KeyboardSwitcher.getInstance().onSizeChanged();
+ }
+
/**
* Attaches a keyboard to this view. The keyboard can be switched at any time and the
* view will re-layout itself to accommodate the keyboard.
@@ -305,10 +311,10 @@ public class LatinKeyboardBaseView extends KeyboardView {
// Remove any pending messages, except dismissing preview
mKeyTimerHandler.cancelKeyTimers();
super.setKeyboard(keyboard);
- mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
- -getPaddingTop() + mVerticalCorrection);
+ mKeyDetector.setKeyboard(
+ keyboard, -getPaddingLeft(), -getPaddingTop() + mVerticalCorrection);
for (PointerTracker tracker : mPointerTrackers) {
- tracker.setKeyboard(keyboard, mKeyDetector);
+ tracker.setKeyDetector(mKeyDetector);
}
mKeyDetector.setProximityThreshold(keyboard.getMostCommonKeyWidth());
mPopupPanelCache.clear();
@@ -359,26 +365,24 @@ public class LatinKeyboardBaseView extends KeyboardView {
return false;
}
+ // Check if we are already displaying popup panel.
+ if (mPopupPanel != null)
+ return false;
final Key parentKey = tracker.getKey(keyIndex);
if (parentKey == null)
return false;
- boolean result = onLongPress(parentKey, tracker);
- if (result) {
- dismissAllKeyPreviews();
- tracker.onLongPressed(mPointerQueue);
- }
- return result;
+ return onLongPress(parentKey, tracker);
}
private void onLongPressShiftKey(PointerTracker tracker) {
- tracker.onLongPressed(mPointerQueue);
+ tracker.onLongPressed();
mKeyboardActionListener.onCodeInput(Keyboard.CODE_CAPSLOCK, null, 0, 0);
}
private void onDoubleTapShiftKey(@SuppressWarnings("unused") PointerTracker tracker) {
// When shift key is double tapped, the first tap is correctly processed as usual tap. And
// the second tap is treated as this double tap event, so that we need not mark tracker
- // calling setAlreadyProcessed() nor remove the tracker from mPointerQueueueue.
+ // calling setAlreadyProcessed() nor remove the tracker from mPointerQueue.
mKeyboardActionListener.onCodeInput(Keyboard.CODE_CAPSLOCK, null, 0, 0);
}
@@ -394,39 +398,6 @@ public class LatinKeyboardBaseView extends KeyboardView {
final PopupMiniKeyboardView miniKeyboardView =
(PopupMiniKeyboardView)container.findViewById(R.id.mini_keyboard_view);
- miniKeyboardView.setOnKeyboardActionListener(new KeyboardActionListener() {
- @Override
- public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) {
- mKeyboardActionListener.onCodeInput(primaryCode, keyCodes, x, y);
- dismissMiniKeyboard();
- }
-
- @Override
- public void onTextInput(CharSequence text) {
- mKeyboardActionListener.onTextInput(text);
- dismissMiniKeyboard();
- }
-
- @Override
- public void onCancelInput() {
- mKeyboardActionListener.onCancelInput();
- dismissMiniKeyboard();
- }
-
- @Override
- public void onSwipeDown() {
- // Nothing to do.
- }
- @Override
- public void onPress(int primaryCode, boolean withSliding) {
- mKeyboardActionListener.onPress(primaryCode, withSliding);
- }
- @Override
- public void onRelease(int primaryCode, boolean withSliding) {
- mKeyboardActionListener.onRelease(primaryCode, withSliding);
- }
- });
-
final Keyboard parentKeyboard = getKeyboard();
final Keyboard miniKeyboard = new MiniKeyboardBuilder(
this, parentKeyboard.getPopupKeyboardResId(), parentKey, parentKeyboard).build();
@@ -440,7 +411,7 @@ public class LatinKeyboardBaseView extends KeyboardView {
@Override
protected boolean needsToDimKeyboard() {
- return mPopupMiniKeyboardPanel != null;
+ return mPopupPanel != null;
}
/**
@@ -466,8 +437,14 @@ public class LatinKeyboardBaseView extends KeyboardView {
// Allow popup window to be drawn off the screen.
mPopupWindow.setClippingEnabled(false);
}
- mPopupMiniKeyboardPanel = popupPanel;
+ mPopupPanel = popupPanel;
+ mPopupPanelPointerTrackerId = tracker.mPointerId;
+
+ tracker.onLongPressed();
popupPanel.showPanel(this, parentKey, tracker, mPopupWindow);
+ final int translatedX = popupPanel.translateX(tracker.getLastX());
+ final int translatedY = popupPanel.translateY(tracker.getLastY());
+ tracker.onDownEvent(translatedX, translatedY, SystemClock.uptimeMillis(), popupPanel);
invalidateAllKeys();
return true;
@@ -476,17 +453,14 @@ public class LatinKeyboardBaseView extends KeyboardView {
private PointerTracker getPointerTracker(final int id) {
final ArrayList<PointerTracker> pointers = mPointerTrackers;
final KeyboardActionListener listener = mKeyboardActionListener;
- final Keyboard keyboard = getKeyboard();
// Create pointer trackers until we can get 'id+1'-th tracker, if needed.
for (int i = pointers.size(); i <= id; i++) {
final PointerTracker tracker =
new PointerTracker(i, getContext(), mKeyTimerHandler, mKeyDetector, this,
- mHasDistinctMultitouch);
- if (keyboard != null)
- tracker.setKeyboard(keyboard, mKeyDetector);
+ mPointerQueue);
if (listener != null)
- tracker.setOnKeyboardActionListener(listener);
+ tracker.setKeyboardActionListener(listener);
pointers.add(tracker);
}
@@ -494,10 +468,12 @@ public class LatinKeyboardBaseView extends KeyboardView {
}
public boolean isInSlidingKeyInput() {
- if (mPopupMiniKeyboardPanel != null) {
- return mPopupMiniKeyboardPanel.isInSlidingKeyInput();
- } else {
+ if (mPopupPanel != null) {
+ return true;
+ } else if (mPointerQueue != null) {
return mPointerQueue.isInSlidingKeyInput();
+ } else {
+ return getPointerTracker(0).isInSlidingKeyInput();
}
}
@@ -520,11 +496,8 @@ public class LatinKeyboardBaseView extends KeyboardView {
return true;
}
- // Track the last few movements to look for spurious swipes.
- mSwipeTracker.addMovement(me);
-
// Gesture detector must be enabled only when mini-keyboard is not on the screen.
- if (mPopupMiniKeyboardPanel == null && mGestureDetector != null
+ if (mPopupPanel == null && mGestureDetector != null
&& mGestureDetector.onTouchEvent(me)) {
dismissAllKeyPreviews();
mKeyTimerHandler.cancelKeyTimers();
@@ -534,13 +507,13 @@ public class LatinKeyboardBaseView extends KeyboardView {
final long eventTime = me.getEventTime();
final int index = me.getActionIndex();
final int id = me.getPointerId(index);
- final int x = (int)me.getX(index);
- final int y = (int)me.getY(index);
-
- // Needs to be called after the gesture detector gets a turn, as it may have displayed the
- // mini keyboard
- if (mPopupMiniKeyboardPanel != null) {
- return mPopupMiniKeyboardPanel.onTouchEvent(me);
+ final int x, y;
+ if (mPopupPanel != null && id == mPopupPanelPointerTrackerId) {
+ x = mPopupPanel.translateX((int)me.getX(index));
+ y = mPopupPanel.translateY((int)me.getY(index));
+ } else {
+ x = (int)me.getX(index);
+ y = (int)me.getY(index);
}
if (mKeyTimerHandler.isInKeyRepeat()) {
@@ -565,9 +538,9 @@ public class LatinKeyboardBaseView extends KeyboardView {
// previous key.
final int newKeyIndex = tracker.getKeyIndexOn(x, y);
if (mOldKeyIndex != newKeyIndex) {
- tracker.onDownEvent(x, y, eventTime, null);
+ tracker.onDownEvent(x, y, eventTime, this);
if (action == MotionEvent.ACTION_UP)
- tracker.onUpEvent(x, y, eventTime, null);
+ tracker.onUpEvent(x, y, eventTime);
}
} else if (pointerCount == 2 && oldPointerCount == 1) {
// Single-touch to multi-touch transition.
@@ -575,9 +548,9 @@ public class LatinKeyboardBaseView extends KeyboardView {
final int lastX = tracker.getLastX();
final int lastY = tracker.getLastY();
mOldKeyIndex = tracker.getKeyIndexOn(lastX, lastY);
- tracker.onUpEvent(lastX, lastY, eventTime, null);
+ tracker.onUpEvent(lastX, lastY, eventTime);
} else if (pointerCount == 1 && oldPointerCount == 1) {
- tracker.onTouchEvent(action, x, y, eventTime, null);
+ processMotionEvent(tracker, action, x, y, eventTime, this);
} else {
Log.w(TAG, "Unknown touch panel behavior: pointer count is " + pointerCount
+ " (old " + oldPointerCount + ")");
@@ -585,34 +558,44 @@ public class LatinKeyboardBaseView extends KeyboardView {
return true;
}
- final PointerTrackerQueue queue = mPointerQueue;
if (action == MotionEvent.ACTION_MOVE) {
for (int i = 0; i < pointerCount; i++) {
final PointerTracker tracker = getPointerTracker(me.getPointerId(i));
- tracker.onMoveEvent((int)me.getX(i), (int)me.getY(i), eventTime, queue);
+ final int px, py;
+ if (mPopupPanel != null && tracker.mPointerId == mPopupPanelPointerTrackerId) {
+ px = mPopupPanel.translateX((int)me.getX(i));
+ py = mPopupPanel.translateY((int)me.getY(i));
+ } else {
+ px = (int)me.getX(i);
+ py = (int)me.getY(i);
+ }
+ tracker.onMoveEvent(px, py, eventTime);
}
} else {
- final PointerTracker tracker = getPointerTracker(id);
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- case MotionEvent.ACTION_POINTER_DOWN:
- tracker.onDownEvent(x, y, eventTime, queue);
- break;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_POINTER_UP:
- tracker.onUpEvent(x, y, eventTime, queue);
- break;
- case MotionEvent.ACTION_CANCEL:
- tracker.onCancelEvent(x, y, eventTime, queue);
- break;
- }
+ processMotionEvent(getPointerTracker(id), action, x, y, eventTime, this);
}
return true;
}
- protected void onSwipeDown() {
- mKeyboardActionListener.onSwipeDown();
+ private static void processMotionEvent(PointerTracker tracker, int action, int x, int y,
+ long eventTime, PointerTracker.KeyEventHandler handler) {
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_POINTER_DOWN:
+ tracker.onDownEvent(x, y, eventTime, handler);
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_POINTER_UP:
+ tracker.onUpEvent(x, y, eventTime);
+ break;
+ case MotionEvent.ACTION_MOVE:
+ tracker.onMoveEvent(x, y, eventTime);
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ tracker.onCancelEvent(x, y, eventTime);
+ break;
+ }
}
@Override
@@ -622,10 +605,11 @@ public class LatinKeyboardBaseView extends KeyboardView {
mPopupPanelCache.clear();
}
- private boolean dismissMiniKeyboard() {
+ public boolean dismissMiniKeyboard() {
if (mPopupWindow != null && mPopupWindow.isShowing()) {
mPopupWindow.dismiss();
- mPopupMiniKeyboardPanel = null;
+ mPopupPanel = null;
+ mPopupPanelPointerTrackerId = -1;
invalidateAllKeys();
return true;
}
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 510bc16b4..5f5475ce8 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -96,8 +96,10 @@ public class LatinKeyboardView extends LatinKeyboardBaseView {
protected boolean onLongPress(Key key, PointerTracker tracker) {
int primaryCode = key.mCode;
if (primaryCode == Keyboard.CODE_SETTINGS) {
+ tracker.onLongPressed();
return invokeOnKey(Keyboard.CODE_SETTINGS_LONGPRESS);
} else if (primaryCode == '0' && getLatinKeyboard().isPhoneKeyboard()) {
+ tracker.onLongPressed();
// Long pressing on 0 in phone number keypad gives you a '+'.
return invokeOnKey('+');
} else {
@@ -106,7 +108,7 @@ public class LatinKeyboardView extends LatinKeyboardBaseView {
}
private boolean invokeOnKey(int primaryCode) {
- getOnKeyboardActionListener().onCodeInput(primaryCode, null,
+ getKeyboardActionListener().onCodeInput(primaryCode, null,
KeyboardActionListener.NOT_A_TOUCH_COORDINATE,
KeyboardActionListener.NOT_A_TOUCH_COORDINATE);
return true;
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java
index 69005db57..1ec0dda15 100644
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java
+++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java
@@ -37,7 +37,7 @@ public class MiniKeyboardKeyDetector extends KeyDetector {
@Override
public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) {
- final List<Key> keys = getKeys();
+ final List<Key> keys = getKeyboard().getKeys();
final int touchX = getTouchX(x);
final int touchY = getTouchY(y);
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 4ceabff4c..d23fb4aad 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -18,12 +18,8 @@ package com.android.inputmethod.keyboard;
import android.content.Context;
import android.content.res.Resources;
-import android.os.SystemClock;
import android.util.Log;
-import android.view.MotionEvent;
-import com.android.inputmethod.keyboard.LatinKeyboardBaseView.KeyTimerHandler;
-import com.android.inputmethod.keyboard.internal.PointerTrackerKeyState;
import com.android.inputmethod.keyboard.internal.PointerTrackerQueue;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
@@ -34,12 +30,38 @@ import java.util.List;
public class PointerTracker {
private static final String TAG = PointerTracker.class.getSimpleName();
- private static final boolean ENABLE_ASSERTION = false;
private static final boolean DEBUG_EVENT = false;
private static final boolean DEBUG_MOVE_EVENT = false;
private static final boolean DEBUG_LISTENER = false;
private static boolean DEBUG_MODE = LatinImeLogger.sDBG;
+ public interface KeyEventHandler {
+ /**
+ * Get KeyDetector object that is used for this PointerTracker.
+ * @return the KeyDetector object that is used for this PointerTracker
+ */
+ public KeyDetector getKeyDetector();
+
+ /**
+ * Get KeyboardActionListener object that is used to register key code and so on.
+ * @return the KeyboardActionListner for this PointerTracker
+ */
+ public KeyboardActionListener getKeyboardActionListener();
+
+ /**
+ * Get DrawingProxy object that is used for this PointerTracker.
+ * @return the DrawingProxy object that is used for this PointerTracker
+ */
+ public DrawingProxy getDrawingProxy();
+
+ /**
+ * Get TimerProxy object that handles key repeat and long press timer event for this
+ * PointerTracker.
+ * @return the TimerProxy object that handles key repeat and long press timer event.
+ */
+ public TimerProxy getTimerProxy();
+ }
+
public interface DrawingProxy {
public void invalidateKey(Key key);
public void showKeyPreview(int keyIndex, PointerTracker tracker);
@@ -47,6 +69,14 @@ public class PointerTracker {
public void dismissKeyPreview(PointerTracker tracker);
}
+ public interface TimerProxy {
+ public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker);
+ public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker);
+ public void startLongPressShiftTimer(long delay, int keyIndex, PointerTracker tracker);
+ public void cancelLongPressTimers();
+ public void cancelKeyTimers();
+ }
+
public final int mPointerId;
// Timing constants
@@ -54,12 +84,12 @@ public class PointerTracker {
private final int mLongPressKeyTimeout;
private final int mLongPressShiftKeyTimeout;
- private final DrawingProxy mDrawingProxy;
- private final KeyTimerHandler mKeyTimerHandler;
+ private DrawingProxy mDrawingProxy;
+ private TimerProxy mTimerProxy;
+ private final PointerTrackerQueue mPointerTrackerQueue;
private KeyDetector mKeyDetector;
private KeyboardActionListener mListener = EMPTY_LISTENER;
private final KeyboardSwitcher mKeyboardSwitcher;
- private final boolean mHasDistinctMultitouch;
private final boolean mConfigSlidingKeyInputEnabled;
private final int mTouchNoiseThresholdMillis;
@@ -69,7 +99,19 @@ public class PointerTracker {
private List<Key> mKeys;
private int mKeyQuarterWidthSquared;
- private final PointerTrackerKeyState mKeyState;
+ // The position and time at which first down event occurred.
+ private long mDownTime;
+ private long mUpTime;
+
+ // The current key index where this pointer is.
+ private int mKeyIndex = KeyDetector.NOT_A_KEY;
+ // The position where mKeyIndex was recognized for the first time.
+ private int mKeyX;
+ private int mKeyY;
+
+ // Last pointer position.
+ private int mLastX;
+ private int mLastY;
// true if keyboard layout has been changed.
private boolean mKeyboardLayoutHasBeenChanged;
@@ -107,21 +149,18 @@ public class PointerTracker {
public void onTextInput(CharSequence text) {}
@Override
public void onCancelInput() {}
- @Override
- public void onSwipeDown() {}
};
- public PointerTracker(int id, Context context, KeyTimerHandler keyTimerHandler,
- KeyDetector keyDetector, DrawingProxy drawingProxy, boolean hasDistinctMultitouch) {
- if (drawingProxy == null || keyTimerHandler == null || keyDetector == null)
+ public PointerTracker(int id, Context context, TimerProxy timerProxy, KeyDetector keyDetector,
+ DrawingProxy drawingProxy, PointerTrackerQueue queue) {
+ if (drawingProxy == null || timerProxy == null || keyDetector == null)
throw new NullPointerException();
mPointerId = id;
mDrawingProxy = drawingProxy;
- mKeyTimerHandler = keyTimerHandler;
- mKeyDetector = keyDetector;
+ mTimerProxy = timerProxy;
+ mPointerTrackerQueue = queue; // This is null for non-distinct multi-touch device.
+ setKeyDetectorInner(keyDetector);
mKeyboardSwitcher = KeyboardSwitcher.getInstance();
- mKeyState = new PointerTrackerKeyState(keyDetector);
- mHasDistinctMultitouch = hasDistinctMultitouch;
final Resources res = context.getResources();
mConfigSlidingKeyInputEnabled = res.getBoolean(R.bool.config_sliding_key_input_enabled);
mDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start);
@@ -135,7 +174,7 @@ public class PointerTracker {
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
}
- public void setOnKeyboardActionListener(KeyboardActionListener listener) {
+ public void setKeyboardActionListener(KeyboardActionListener listener) {
mListener = listener;
}
@@ -196,15 +235,18 @@ public class PointerTracker {
mListener.onCancelInput();
}
- public void setKeyboard(Keyboard keyboard, KeyDetector keyDetector) {
- if (keyboard == null || keyDetector == null)
- throw new NullPointerException();
- mKeyboard = keyboard;
- mKeys = keyboard.getKeys();
+ public void setKeyDetectorInner(KeyDetector keyDetector) {
mKeyDetector = keyDetector;
- mKeyState.setKeyDetector(keyDetector);
- final int keyQuarterWidth = keyboard.getKeyWidth() / 4;
+ mKeyboard = keyDetector.getKeyboard();
+ mKeys = mKeyboard.getKeys();
+ final int keyQuarterWidth = mKeyboard.getKeyWidth() / 4;
mKeyQuarterWidthSquared = keyQuarterWidth * keyQuarterWidth;
+ }
+
+ public void setKeyDetector(KeyDetector keyDetector) {
+ if (keyDetector == null)
+ throw new NullPointerException();
+ setKeyDetectorInner(keyDetector);
// Mark that keyboard layout has been changed.
mKeyboardLayoutHasBeenChanged = true;
}
@@ -232,7 +274,7 @@ public class PointerTracker {
}
public boolean isModifier() {
- return isModifierInternal(mKeyState.getKeyIndex());
+ return isModifierInternal(mKeyIndex);
}
private boolean isOnModifierKey(int x, int y) {
@@ -254,7 +296,7 @@ public class PointerTracker {
}
public void setReleasedKeyGraphics() {
- setReleasedKeyGraphics(mKeyState.getKeyIndex());
+ setReleasedKeyGraphics(mKeyIndex);
}
private void setReleasedKeyGraphics(int keyIndex) {
@@ -273,44 +315,59 @@ public class PointerTracker {
}
}
- private void checkAssertion(PointerTrackerQueue queue) {
- if (mHasDistinctMultitouch && queue == null)
- throw new RuntimeException(
- "PointerTrackerQueue must be passed on distinct multi touch device");
- if (!mHasDistinctMultitouch && queue != null)
- throw new RuntimeException(
- "PointerTrackerQueue must be null on non-distinct multi touch device");
- }
-
- public void onTouchEvent(int action, int x, int y, long eventTime, PointerTrackerQueue queue) {
- switch (action) {
- case MotionEvent.ACTION_MOVE:
- onMoveEvent(x, y, eventTime, queue);
- break;
- case MotionEvent.ACTION_DOWN:
- case MotionEvent.ACTION_POINTER_DOWN:
- onDownEvent(x, y, eventTime, queue);
- break;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_POINTER_UP:
- onUpEvent(x, y, eventTime, queue);
- break;
- case MotionEvent.ACTION_CANCEL:
- onCancelEvent(x, y, eventTime, queue);
- break;
- }
+ public int getLastX() {
+ return mLastX;
+ }
+
+ public int getLastY() {
+ return mLastY;
}
- public void onDownEvent(int x, int y, long eventTime, PointerTrackerQueue queue) {
- if (ENABLE_ASSERTION) checkAssertion(queue);
+ public long getDownTime() {
+ return mDownTime;
+ }
+
+ private int onDownKey(int x, int y, long eventTime) {
+ mDownTime = eventTime;
+ return onMoveToNewKey(onMoveKeyInternal(x, y), x, y);
+ }
+
+ private int onMoveKeyInternal(int x, int y) {
+ mLastX = x;
+ mLastY = y;
+ return mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null);
+ }
+
+ private int onMoveKey(int x, int y) {
+ return onMoveKeyInternal(x, y);
+ }
+
+ private int onMoveToNewKey(int keyIndex, int x, int y) {
+ mKeyIndex = keyIndex;
+ mKeyX = x;
+ mKeyY = y;
+ return keyIndex;
+ }
+
+ private int onUpKey(int x, int y, long eventTime) {
+ mUpTime = eventTime;
+ mKeyIndex = KeyDetector.NOT_A_KEY;
+ return onMoveKeyInternal(x, y);
+ }
+
+ public void onDownEvent(int x, int y, long eventTime, KeyEventHandler handler) {
if (DEBUG_EVENT)
printTouchEvent("onDownEvent:", x, y, eventTime);
+ mDrawingProxy = handler.getDrawingProxy();
+ mTimerProxy = handler.getTimerProxy();
+ setKeyboardActionListener(handler.getKeyboardActionListener());
+ setKeyDetectorInner(handler.getKeyDetector());
// Naive up-to-down noise filter.
- final long deltaT = eventTime - mKeyState.getUpTime();
+ final long deltaT = eventTime - mUpTime;
if (deltaT < mTouchNoiseThresholdMillis) {
- final int dx = x - mKeyState.getLastX();
- final int dy = y - mKeyState.getLastY();
+ final int dx = x - mLastX;
+ final int dy = y - mLastY;
final int distanceSquared = (dx * dx + dy * dy);
if (distanceSquared < mTouchNoiseThresholdDistanceSquared) {
if (DEBUG_MODE)
@@ -321,6 +378,7 @@ public class PointerTracker {
}
}
+ final PointerTrackerQueue queue = mPointerTrackerQueue;
if (queue != null) {
if (isOnModifierKey(x, y)) {
// Before processing a down event of modifier key, all pointers already being
@@ -333,7 +391,7 @@ public class PointerTracker {
}
private void onDownEventInternal(int x, int y, long eventTime) {
- int keyIndex = mKeyState.onDownKey(x, y, eventTime);
+ int keyIndex = onDownKey(x, y, eventTime);
// Sliding key is allowed when 1) enabled by configuration, 2) this pointer starts sliding
// from modifier key, or 3) this pointer is on mini-keyboard.
mIsAllowedSlidingKeyInput = mConfigSlidingKeyInputEnabled || isModifierInternal(keyIndex)
@@ -349,7 +407,7 @@ public class PointerTracker {
// {@link #setKeyboard}. In those cases, we should update keyIndex according to the new
// keyboard layout.
if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), false))
- keyIndex = mKeyState.onDownKey(x, y, eventTime);
+ keyIndex = onDownKey(x, y, eventTime);
startRepeatKey(keyIndex);
startLongPressTimer(keyIndex);
@@ -364,25 +422,23 @@ public class PointerTracker {
mIsInSlidingKeyInput = true;
}
- public void onMoveEvent(int x, int y, long eventTime, PointerTrackerQueue queue) {
- if (ENABLE_ASSERTION) checkAssertion(queue);
+ public void onMoveEvent(int x, int y, long eventTime) {
if (DEBUG_MOVE_EVENT)
printTouchEvent("onMoveEvent:", x, y, eventTime);
if (mKeyAlreadyProcessed)
return;
- final PointerTrackerKeyState keyState = mKeyState;
// TODO: Remove this hacking code
if (mIsInSlidingLanguageSwitch) {
- ((LatinKeyboard)mKeyboard).updateSpacebarPreviewIcon(x - keyState.getKeyX());
+ ((LatinKeyboard)mKeyboard).updateSpacebarPreviewIcon(x - mKeyX);
showKeyPreview(mSpaceKeyIndex);
return;
}
- final int lastX = keyState.getLastX();
- final int lastY = keyState.getLastY();
- final int oldKeyIndex = keyState.getKeyIndex();
+ final int lastX = mLastX;
+ final int lastY = mLastY;
+ final int oldKeyIndex = mKeyIndex;
final Key oldKey = getKey(oldKeyIndex);
- int keyIndex = keyState.onMoveKey(x, y);
+ int keyIndex = onMoveKey(x, y);
if (isValidKeyIndex(keyIndex)) {
if (oldKey == null) {
// The pointer has been slid in to the new key, but the finger was not on any keys.
@@ -391,8 +447,8 @@ public class PointerTracker {
// {@link #setKeyboard}. In those cases, we should update keyIndex according to the
// new keyboard layout.
if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), true))
- keyIndex = keyState.onMoveKey(x, y);
- keyState.onMoveToNewKey(keyIndex, x, y);
+ keyIndex = onMoveKey(x, y);
+ onMoveToNewKey(keyIndex, x, y);
startLongPressTimer(keyIndex);
showKeyPreview(keyIndex);
setPressedKeyGraphics(keyIndex);
@@ -403,15 +459,15 @@ public class PointerTracker {
setReleasedKeyGraphics(oldKeyIndex);
callListenerOnRelease(oldKey, oldKey.mCode, true);
startSlidingKeyInput(oldKey);
- mKeyTimerHandler.cancelKeyTimers();
+ mTimerProxy.cancelKeyTimers();
startRepeatKey(keyIndex);
if (mIsAllowedSlidingKeyInput) {
// This onPress call may have changed keyboard layout. Those cases are detected
// at {@link #setKeyboard}. In those cases, we should update keyIndex according
// to the new keyboard layout.
if (callListenerOnPressAndCheckKeyboardLayoutChange(getKey(keyIndex), true))
- keyIndex = keyState.onMoveKey(x, y);
- keyState.onMoveToNewKey(keyIndex, x, y);
+ keyIndex = onMoveKey(x, y);
+ onMoveToNewKey(keyIndex, x, y);
startLongPressTimer(keyIndex);
setPressedKeyGraphics(keyIndex);
showKeyPreview(keyIndex);
@@ -441,7 +497,7 @@ public class PointerTracker {
final LatinKeyboard keyboard = ((LatinKeyboard)mKeyboard);
if (mSubtypeSwitcher.useSpacebarLanguageSwitcher()
&& mSubtypeSwitcher.getEnabledKeyboardLocaleCount() > 1) {
- final int diff = x - keyState.getKeyX();
+ final int diff = x - mKeyX;
if (keyboard.shouldTriggerSpacebarSlidingLanguageSwitch(diff)) {
// Detect start sliding language switch.
mIsInSlidingLanguageSwitch = true;
@@ -449,6 +505,7 @@ public class PointerTracker {
keyboard.updateSpacebarPreviewIcon(diff);
// Display spacebar slide language switcher.
showKeyPreview(keyIndex);
+ final PointerTrackerQueue queue = mPointerTrackerQueue;
if (queue != null)
queue.releaseAllPointersExcept(this, eventTime, true);
}
@@ -461,9 +518,9 @@ public class PointerTracker {
setReleasedKeyGraphics(oldKeyIndex);
callListenerOnRelease(oldKey, oldKey.mCode, true);
startSlidingKeyInput(oldKey);
- mKeyTimerHandler.cancelLongPressTimers();
+ mTimerProxy.cancelLongPressTimers();
if (mIsAllowedSlidingKeyInput) {
- keyState.onMoveToNewKey(keyIndex, x, y);
+ onMoveToNewKey(keyIndex, x, y);
} else {
mKeyAlreadyProcessed = true;
dismissKeyPreview();
@@ -472,11 +529,11 @@ public class PointerTracker {
}
}
- public void onUpEvent(int x, int y, long eventTime, PointerTrackerQueue queue) {
- if (ENABLE_ASSERTION) checkAssertion(queue);
+ public void onUpEvent(int x, int y, long eventTime) {
if (DEBUG_EVENT)
printTouchEvent("onUpEvent :", x, y, eventTime);
+ final PointerTrackerQueue queue = mPointerTrackerQueue;
if (queue != null) {
if (isModifier()) {
// Before processing an up event of modifier key, all pointers already being
@@ -502,20 +559,19 @@ public class PointerTracker {
private void onUpEventInternal(int x, int y, long eventTime,
boolean updateReleasedKeyGraphics) {
- mKeyTimerHandler.cancelKeyTimers();
+ mTimerProxy.cancelKeyTimers();
mDrawingProxy.cancelShowKeyPreview(this);
mIsInSlidingKeyInput = false;
- final PointerTrackerKeyState keyState = mKeyState;
final int keyX, keyY;
- if (isMajorEnoughMoveToBeOnNewKey(x, y, keyState.onMoveKey(x, y))) {
+ if (isMajorEnoughMoveToBeOnNewKey(x, y, onMoveKey(x, y))) {
keyX = x;
keyY = y;
} else {
// Use previous fixed key coordinates.
- keyX = keyState.getKeyX();
- keyY = keyState.getKeyY();
+ keyX = mKeyX;
+ keyY = mKeyY;
}
- final int keyIndex = keyState.onUpKey(keyX, keyY, eventTime);
+ final int keyIndex = onUpKey(keyX, keyY, eventTime);
dismissKeyPreview();
if (updateReleasedKeyGraphics)
setReleasedKeyGraphics(keyIndex);
@@ -540,20 +596,21 @@ public class PointerTracker {
}
}
- public void onLongPressed(PointerTrackerQueue queue) {
+ public void onLongPressed() {
mKeyAlreadyProcessed = true;
+ setReleasedKeyGraphics();
+ dismissKeyPreview();
+ final PointerTrackerQueue queue = mPointerTrackerQueue;
if (queue != null) {
- // TODO: Support chording + long-press input.
- queue.releaseAllPointersExcept(this, SystemClock.uptimeMillis(), true);
queue.remove(this);
}
}
- public void onCancelEvent(int x, int y, long eventTime, PointerTrackerQueue queue) {
- if (ENABLE_ASSERTION) checkAssertion(queue);
+ public void onCancelEvent(int x, int y, long eventTime) {
if (DEBUG_EVENT)
printTouchEvent("onCancelEvt:", x, y, eventTime);
+ final PointerTrackerQueue queue = mPointerTrackerQueue;
if (queue != null) {
queue.releaseAllPointersExcept(this, eventTime, true);
queue.remove(this);
@@ -562,10 +619,10 @@ public class PointerTracker {
}
private void onCancelEventInternal() {
- mKeyTimerHandler.cancelKeyTimers();
+ mTimerProxy.cancelKeyTimers();
mDrawingProxy.cancelShowKeyPreview(this);
dismissKeyPreview();
- setReleasedKeyGraphics(mKeyState.getKeyIndex());
+ setReleasedKeyGraphics(mKeyIndex);
mIsInSlidingKeyInput = false;
}
@@ -574,7 +631,7 @@ public class PointerTracker {
if (key != null && key.mRepeatable) {
dismissKeyPreview();
onRepeatKey(keyIndex);
- mKeyTimerHandler.startKeyRepeatTimer(mDelayBeforeKeyRepeatStart, keyIndex, this);
+ mTimerProxy.startKeyRepeatTimer(mDelayBeforeKeyRepeatStart, keyIndex, this);
mIsRepeatableKey = true;
} else {
mIsRepeatableKey = false;
@@ -588,22 +645,10 @@ public class PointerTracker {
}
}
- public int getLastX() {
- return mKeyState.getLastX();
- }
-
- public int getLastY() {
- return mKeyState.getLastY();
- }
-
- public long getDownTime() {
- return mKeyState.getDownTime();
- }
-
private boolean isMajorEnoughMoveToBeOnNewKey(int x, int y, int newKey) {
if (mKeys == null || mKeyDetector == null)
throw new NullPointerException("keyboard and/or key detector not set");
- int curKey = mKeyState.getKeyIndex();
+ int curKey = mKeyIndex;
if (newKey == curKey) {
return false;
} else if (isValidKeyIndex(curKey)) {
@@ -640,16 +685,16 @@ public class PointerTracker {
private void startLongPressTimer(int keyIndex) {
Key key = getKey(keyIndex);
if (key.mCode == Keyboard.CODE_SHIFT) {
- mKeyTimerHandler.startLongPressShiftTimer(mLongPressShiftKeyTimeout, keyIndex, this);
+ mTimerProxy.startLongPressShiftTimer(mLongPressShiftKeyTimeout, keyIndex, this);
} else if (key.hasUppercaseLetter() && mKeyboard.isManualTemporaryUpperCase()) {
// We need not start long press timer on the key which has manual temporary upper case
// code defined and the keyboard is in manual temporary upper case mode.
return;
} else if (mKeyboardSwitcher.isInMomentarySwitchState()) {
// We use longer timeout for sliding finger input started from the symbols mode key.
- mKeyTimerHandler.startLongPressTimer(mLongPressKeyTimeout * 3, keyIndex, this);
+ mTimerProxy.startLongPressTimer(mLongPressKeyTimeout * 3, keyIndex, this);
} else {
- mKeyTimerHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this);
+ mTimerProxy.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this);
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java b/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java
index 959427aad..af8e59568 100644
--- a/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/PopupMiniKeyboardView.java
@@ -18,26 +18,73 @@ package com.android.inputmethod.keyboard;
import android.content.Context;
import android.content.res.Resources;
-import android.os.SystemClock;
+import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.Gravity;
-import android.view.MotionEvent;
import android.view.View;
import android.widget.PopupWindow;
+import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy;
+import com.android.inputmethod.keyboard.PointerTracker.TimerProxy;
import com.android.inputmethod.latin.R;
/**
* A view that renders a virtual {@link MiniKeyboard}. It handles rendering of keys and detecting
* key presses and touch movements.
*/
-public class PopupMiniKeyboardView extends LatinKeyboardBaseView implements PopupPanel {
+public class PopupMiniKeyboardView extends KeyboardView implements PopupPanel {
private final int[] mCoordinates = new int[2];
private final boolean mConfigShowMiniKeyboardAtTouchedPoint;
+ private final KeyDetector mKeyDetector;
+ private final int mVerticalCorrection;
+
+ private LatinKeyboardBaseView mParentKeyboardView;
private int mOriginX;
private int mOriginY;
- private long mDownTime;
+
+ private static final TimerProxy EMPTY_TIMER_PROXY = new TimerProxy() {
+ @Override
+ public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker) {}
+ @Override
+ public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker) {}
+ @Override
+ public void startLongPressShiftTimer(long delay, int keyIndex, PointerTracker tracker) {}
+ @Override
+ public void cancelLongPressTimers() {}
+ @Override
+ public void cancelKeyTimers() {}
+ };
+
+ private final KeyboardActionListener mListner = new KeyboardActionListener() {
+ @Override
+ public void onCodeInput(int primaryCode, int[] keyCodes, int x, int y) {
+ mParentKeyboardView.getKeyboardActionListener()
+ .onCodeInput(primaryCode, keyCodes, x, y);
+ mParentKeyboardView.dismissMiniKeyboard();
+ }
+
+ @Override
+ public void onTextInput(CharSequence text) {
+ mParentKeyboardView.getKeyboardActionListener().onTextInput(text);
+ mParentKeyboardView.dismissMiniKeyboard();
+ }
+
+ @Override
+ public void onCancelInput() {
+ mParentKeyboardView.getKeyboardActionListener().onCancelInput();
+ mParentKeyboardView.dismissMiniKeyboard();
+ }
+
+ @Override
+ public void onPress(int primaryCode, boolean withSliding) {
+ mParentKeyboardView.getKeyboardActionListener().onPress(primaryCode, withSliding);
+ }
+ @Override
+ public void onRelease(int primaryCode, boolean withSliding) {
+ mParentKeyboardView.getKeyboardActionListener().onRelease(primaryCode, withSliding);
+ }
+ };
public PopupMiniKeyboardView(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.popupMiniKeyboardViewStyle);
@@ -46,6 +93,12 @@ public class PopupMiniKeyboardView extends LatinKeyboardBaseView implements Popu
public PopupMiniKeyboardView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ final TypedArray a = context.obtainStyledAttributes(
+ attrs, R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
+ mVerticalCorrection = a.getDimensionPixelOffset(
+ R.styleable.KeyboardView_verticalCorrection, 0);
+ a.recycle();
+
final Resources res = context.getResources();
mConfigShowMiniKeyboardAtTouchedPoint = res.getBoolean(
R.bool.config_show_mini_keyboard_at_touched_point);
@@ -53,11 +106,42 @@ public class PopupMiniKeyboardView extends LatinKeyboardBaseView implements Popu
mKeyDetector = new MiniKeyboardKeyDetector(res.getDimension(
R.dimen.mini_keyboard_slide_allowance));
// Remove gesture detector on mini-keyboard
- mGestureDetector = null;
setKeyPreviewPopupEnabled(false, 0);
}
@Override
+ public void setKeyboard(Keyboard keyboard) {
+ super.setKeyboard(keyboard);
+ mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
+ -getPaddingTop() + mVerticalCorrection);
+ }
+
+ @Override
+ public KeyDetector getKeyDetector() {
+ return mKeyDetector;
+ }
+
+ @Override
+ public KeyboardActionListener getKeyboardActionListener() {
+ return mListner;
+ }
+
+ @Override
+ public DrawingProxy getDrawingProxy() {
+ return this;
+ }
+
+ @Override
+ public TimerProxy getTimerProxy() {
+ return EMPTY_TIMER_PROXY;
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ // Do nothing for the mini keyboard.
+ }
+
+ @Override
public void setKeyPreviewPopupEnabled(boolean previewEnabled, int delay) {
// Mini keyboard needs no pop-up key preview displayed, so we pass always false with a
// delay of 0. The delay does not matter actually since the popup is not shown anyway.
@@ -65,8 +149,9 @@ public class PopupMiniKeyboardView extends LatinKeyboardBaseView implements Popu
}
@Override
- public void showPanel(KeyboardView parentKeyboardView, Key parentKey,
+ public void showPanel(LatinKeyboardBaseView parentKeyboardView, Key parentKey,
PointerTracker tracker, PopupWindow window) {
+ mParentKeyboardView = parentKeyboardView;
final View container = (View)getParent();
final MiniKeyboard miniKeyboard = (MiniKeyboard)getKeyboard();
final Keyboard parentKeyboard = parentKeyboardView.getKeyboard();
@@ -94,19 +179,15 @@ public class PopupMiniKeyboardView extends LatinKeyboardBaseView implements Popu
mOriginX = x + container.getPaddingLeft() - mCoordinates[0];
mOriginY = y + container.getPaddingTop() - mCoordinates[1];
- mDownTime = SystemClock.uptimeMillis();
-
- // Inject down event on the key to mini keyboard.
- final MotionEvent downEvent = MotionEvent.obtain(mDownTime, mDownTime,
- MotionEvent.ACTION_DOWN, pointX - mOriginX,
- pointY + parentKey.mHeight / 2 - mOriginY, 0);
- onTouchEvent(downEvent);
- downEvent.recycle();
}
@Override
- public boolean onTouchEvent(MotionEvent me) {
- me.offsetLocation(-mOriginX, -mOriginY);
- return super.onTouchEvent(me);
+ public int translateX(int x) {
+ return x - mOriginX;
+ }
+
+ @Override
+ public int translateY(int y) {
+ return y - mOriginY;
}
}
diff --git a/java/src/com/android/inputmethod/keyboard/PopupPanel.java b/java/src/com/android/inputmethod/keyboard/PopupPanel.java
index 386e11f2c..f94d1c562 100644
--- a/java/src/com/android/inputmethod/keyboard/PopupPanel.java
+++ b/java/src/com/android/inputmethod/keyboard/PopupPanel.java
@@ -16,10 +16,9 @@
package com.android.inputmethod.keyboard;
-import android.view.MotionEvent;
import android.widget.PopupWindow;
-public interface PopupPanel {
+public interface PopupPanel extends PointerTracker.KeyEventHandler {
/**
* Show popup panel.
* @param parentKeyboardView the parent KeyboardView that has the parent key.
@@ -27,19 +26,20 @@ public interface PopupPanel {
* @param tracker the pointer tracker that pressesd the parent key
* @param window PopupWindow to be used to show this popup panel
*/
- public void showPanel(KeyboardView parentKeyboardView, Key parentKey,
+ public void showPanel(LatinKeyboardBaseView parentKeyboardView, Key parentKey,
PointerTracker tracker, PopupWindow window);
/**
- * Check if the pointer is in siding key input mode.
- * @return true if the pointer is sliding key input mode.
+ * Translate X-coordinate of touch event to the local X-coordinate of this PopupPanel.
+ * @param x the global X-coordinate
+ * @return the local X-coordinate to this PopupPanel
*/
- public boolean isInSlidingKeyInput();
+ public int translateX(int x);
/**
- * The motion event handler.
- * @param me the MotionEvent to be processed.
- * @return true if the motion event is processed and should be consumed.
+ * Translate Y-coordinate of touch event to the local Y-coordinate of this PopupPanel.
+ * @param y the global Y-coordinate
+ * @return the local Y-coordinate to this PopupPanel
*/
- public boolean onTouchEvent(MotionEvent me);
+ public int translateY(int y);
}
diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
index 33acc6907..aadedc69d 100644
--- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
+++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java
@@ -23,15 +23,35 @@ import java.util.List;
public class ProximityInfo {
public static final int MAX_PROXIMITY_CHARS_SIZE = 16;
+ /** Number of key widths from current touch point to search for nearest keys. */
+ private static float SEARCH_DISTANCE = 1.2f;
+ private static final int[] EMPTY_INT_ARRAY = new int[0];
private final int mGridWidth;
private final int mGridHeight;
private final int mGridSize;
+ private final int mCellWidth;
+ private final int mCellHeight;
+ // TODO: Find a proper name for mKeyboardMinWidth
+ private final int mKeyboardMinWidth;
+ private final int mKeyboardHeight;
+ private final int[][] mGridNeighbors;
- ProximityInfo(int gridWidth, int gridHeight) {
+ ProximityInfo(
+ int gridWidth, int gridHeight, int minWidth, int height, int keyWidth, List<Key> keys) {
mGridWidth = gridWidth;
mGridHeight = gridHeight;
mGridSize = mGridWidth * mGridHeight;
+ mCellWidth = (minWidth + mGridWidth - 1) / mGridWidth;
+ mCellHeight = (height + mGridHeight - 1) / mGridHeight;
+ mKeyboardMinWidth = minWidth;
+ mKeyboardHeight = height;
+ mGridNeighbors = new int[mGridSize][];
+ if (minWidth == 0 || height == 0) {
+ // No proximity required. Keyboard might be mini keyboard.
+ return;
+ }
+ computeNearestNeighbors(keyWidth, keys);
}
private int mNativeProximityInfo;
@@ -42,7 +62,7 @@ public class ProximityInfo {
int displayHeight, int gridWidth, int gridHeight, int[] proximityCharsArray);
private native void releaseProximityInfoNative(int nativeProximityInfo);
- public final void setProximityInfo(int[][] gridNeighborKeyIndexes, int keyboardWidth,
+ private final void setProximityInfo(int[][] gridNeighborKeyIndexes, int keyboardWidth,
int keyboardHeight, List<Key> keys) {
int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE];
Arrays.fill(proximityCharsArray, KeyDetector.NOT_A_CODE);
@@ -57,12 +77,7 @@ public class ProximityInfo {
keyboardWidth, keyboardHeight, mGridWidth, mGridHeight, proximityCharsArray);
}
- // TODO: Get rid of this function's input (keyboard).
- public int getNativeProximityInfo(Keyboard keyboard) {
- if (mNativeProximityInfo == 0) {
- // TODO: Move this function to ProximityInfo and make this private.
- keyboard.computeNearestNeighbors();
- }
+ public int getNativeProximityInfo() {
return mNativeProximityInfo;
}
@@ -77,4 +92,42 @@ public class ProximityInfo {
super.finalize();
}
}
+
+ private void computeNearestNeighbors(int defaultWidth, List<Key> keys) {
+ final int thresholdBase = (int) (defaultWidth * SEARCH_DISTANCE);
+ final int threshold = thresholdBase * thresholdBase;
+ // Round-up so we don't have any pixels outside the grid
+ final int[] indices = new int[keys.size()];
+ final int gridWidth = mGridWidth * mCellWidth;
+ final int gridHeight = mGridHeight * mCellHeight;
+ for (int x = 0; x < gridWidth; x += mCellWidth) {
+ for (int y = 0; y < gridHeight; y += mCellHeight) {
+ final int centerX = x + mCellWidth / 2;
+ final int centerY = y + mCellHeight / 2;
+ int count = 0;
+ for (int i = 0; i < keys.size(); i++) {
+ final Key key = keys.get(i);
+ if (key.squaredDistanceToEdge(centerX, centerY) < threshold)
+ indices[count++] = i;
+ }
+ final int[] cell = new int[count];
+ System.arraycopy(indices, 0, cell, 0, count);
+ mGridNeighbors[(y / mCellHeight) * mGridWidth + (x / mCellWidth)] = cell;
+ }
+ }
+ setProximityInfo(mGridNeighbors, mKeyboardMinWidth, mKeyboardHeight, keys);
+ }
+
+ public int[] getNearestKeys(int x, int y) {
+ if (mGridNeighbors == null) {
+ return EMPTY_INT_ARRAY;
+ }
+ if (x >= 0 && x < mKeyboardMinWidth && y >= 0 && y < mKeyboardHeight) {
+ int index = (y / mCellHeight) * mGridWidth + (x / mCellWidth);
+ if (index < mGridSize) {
+ return mGridNeighbors[index];
+ }
+ }
+ return EMPTY_INT_ARRAY;
+ }
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
index 1530fed6f..535a6954c 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java
@@ -34,21 +34,22 @@ public class KeyboardIconsSet {
private static final int ICON_TO_SYMBOL_KEY = 2;
private static final int ICON_TO_SYMBOL_KEY_WITH_SHORTCUT = 3;
private static final int ICON_DELETE_KEY = 4;
- private static final int ICON_SETTINGS_KEY = 5;
- private static final int ICON_SHORTCUT_KEY = 6;
- private static final int ICON_SPACE_KEY = 7;
- private static final int ICON_RETURN_KEY = 8;
- private static final int ICON_SEARCH_KEY = 9;
- private static final int ICON_TAB_KEY = 10;
+ private static final int ICON_DELETE_RTL_KEY = 5;
+ private static final int ICON_SETTINGS_KEY = 6;
+ private static final int ICON_SHORTCUT_KEY = 7;
+ private static final int ICON_SPACE_KEY = 8;
+ private static final int ICON_RETURN_KEY = 9;
+ private static final int ICON_SEARCH_KEY = 10;
+ private static final int ICON_TAB_KEY = 11;
// This should be aligned with Keyboard.keyIconShifted enum.
- private static final int ICON_SHIFTED_SHIFT_KEY = 11;
+ private static final int ICON_SHIFTED_SHIFT_KEY = 12;
// This should be aligned with Keyboard.keyIconPreview enum.
- private static final int ICON_PREVIEW_SPACE_KEY = 12;
- private static final int ICON_PREVIEW_TAB_KEY = 13;
- private static final int ICON_PREVIEW_SETTINGS_KEY = 14;
- private static final int ICON_PREVIEW_SHORTCUT_KEY = 15;
+ private static final int ICON_PREVIEW_SPACE_KEY = 13;
+ private static final int ICON_PREVIEW_TAB_KEY = 14;
+ private static final int ICON_PREVIEW_SETTINGS_KEY = 15;
+ private static final int ICON_PREVIEW_SHORTCUT_KEY = 16;
- private static final int ICON_LAST = 15;
+ private static final int ICON_LAST = 16;
private final Drawable mIcons[] = new Drawable[ICON_LAST + 1];
@@ -62,6 +63,8 @@ public class KeyboardIconsSet {
return ICON_TO_SYMBOL_KEY_WITH_SHORTCUT;
case R.styleable.Keyboard_iconDeleteKey:
return ICON_DELETE_KEY;
+ case R.styleable.Keyboard_iconDeleteRtlKey:
+ return ICON_DELETE_RTL_KEY;
case R.styleable.Keyboard_iconSettingsKey:
return ICON_SETTINGS_KEY;
case R.styleable.Keyboard_iconShortcutKey:
diff --git a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerKeyState.java b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerKeyState.java
deleted file mode 100644
index 6e2b60c30..000000000
--- a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerKeyState.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2010 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.keyboard.internal;
-
-import com.android.inputmethod.keyboard.KeyDetector;
-import com.android.inputmethod.keyboard.PointerTracker;
-
-/**
- * This class keeps track of a key index and a position where {@link PointerTracker} is.
- */
-public class PointerTrackerKeyState {
- private KeyDetector mKeyDetector;
-
- // The position and time at which first down event occurred.
- private long mDownTime;
- private long mUpTime;
-
- // The current key index where this pointer is.
- private int mKeyIndex = KeyDetector.NOT_A_KEY;
- // The position where mKeyIndex was recognized for the first time.
- private int mKeyX;
- private int mKeyY;
-
- // Last pointer position.
- private int mLastX;
- private int mLastY;
-
- public PointerTrackerKeyState(KeyDetector keyDetecor) {
- mKeyDetector = keyDetecor;
- }
-
- public void setKeyDetector(KeyDetector keyDetector) {
- mKeyDetector = keyDetector;
- }
-
- public int getKeyIndex() {
- return mKeyIndex;
- }
-
- public int getKeyX() {
- return mKeyX;
- }
-
- public int getKeyY() {
- return mKeyY;
- }
-
- public long getDownTime() {
- return mDownTime;
- }
-
- public long getUpTime() {
- return mUpTime;
- }
-
- public int getLastX() {
- return mLastX;
- }
-
- public int getLastY() {
- return mLastY;
- }
-
- public int onDownKey(int x, int y, long eventTime) {
- mDownTime = eventTime;
- return onMoveToNewKey(onMoveKeyInternal(x, y), x, y);
- }
-
- private int onMoveKeyInternal(int x, int y) {
- mLastX = x;
- mLastY = y;
- return mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null);
- }
-
- public int onMoveKey(int x, int y) {
- return onMoveKeyInternal(x, y);
- }
-
- public int onMoveToNewKey(int keyIndex, int x, int y) {
- mKeyIndex = keyIndex;
- mKeyX = x;
- mKeyY = y;
- return keyIndex;
- }
-
- public int onUpKey(int x, int y, long eventTime) {
- mUpTime = eventTime;
- mKeyIndex = KeyDetector.NOT_A_KEY;
- return onMoveKeyInternal(x, y);
- }
-}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/SwipeTracker.java b/java/src/com/android/inputmethod/keyboard/internal/SwipeTracker.java
deleted file mode 100644
index 8d192c2f0..000000000
--- a/java/src/com/android/inputmethod/keyboard/internal/SwipeTracker.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2010 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.keyboard.internal;
-
-import android.view.MotionEvent;
-
-public class SwipeTracker {
- private static final int NUM_PAST = 4;
- private static final int LONGEST_PAST_TIME = 200;
-
- final EventRingBuffer mBuffer = new EventRingBuffer(NUM_PAST);
-
- private float mYVelocity;
- private float mXVelocity;
-
- public void addMovement(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mBuffer.clear();
- return;
- }
- long time = ev.getEventTime();
- final int count = ev.getHistorySize();
- for (int i = 0; i < count; i++) {
- addPoint(ev.getHistoricalX(i), ev.getHistoricalY(i), ev.getHistoricalEventTime(i));
- }
- addPoint(ev.getX(), ev.getY(), time);
- }
-
- private void addPoint(float x, float y, long time) {
- final EventRingBuffer buffer = mBuffer;
- while (buffer.size() > 0) {
- long lastT = buffer.getTime(0);
- if (lastT >= time - LONGEST_PAST_TIME)
- break;
- buffer.dropOldest();
- }
- buffer.add(x, y, time);
- }
-
- public void computeCurrentVelocity(int units) {
- computeCurrentVelocity(units, Float.MAX_VALUE);
- }
-
- public void computeCurrentVelocity(int units, float maxVelocity) {
- final EventRingBuffer buffer = mBuffer;
- final float oldestX = buffer.getX(0);
- final float oldestY = buffer.getY(0);
- final long oldestTime = buffer.getTime(0);
-
- float accumX = 0;
- float accumY = 0;
- final int count = buffer.size();
- for (int pos = 1; pos < count; pos++) {
- final int dur = (int)(buffer.getTime(pos) - oldestTime);
- if (dur == 0) continue;
- float dist = buffer.getX(pos) - oldestX;
- float vel = (dist / dur) * units; // pixels/frame.
- if (accumX == 0) accumX = vel;
- else accumX = (accumX + vel) * .5f;
-
- dist = buffer.getY(pos) - oldestY;
- vel = (dist / dur) * units; // pixels/frame.
- if (accumY == 0) accumY = vel;
- else accumY = (accumY + vel) * .5f;
- }
- mXVelocity = accumX < 0.0f ? Math.max(accumX, -maxVelocity)
- : Math.min(accumX, maxVelocity);
- mYVelocity = accumY < 0.0f ? Math.max(accumY, -maxVelocity)
- : Math.min(accumY, maxVelocity);
- }
-
- public float getXVelocity() {
- return mXVelocity;
- }
-
- public float getYVelocity() {
- return mYVelocity;
- }
-
- public static class EventRingBuffer {
- private final int bufSize;
- private final float xBuf[];
- private final float yBuf[];
- private final long timeBuf[];
- private int top; // points new event
- private int end; // points oldest event
- private int count; // the number of valid data
-
- public EventRingBuffer(int max) {
- this.bufSize = max;
- xBuf = new float[max];
- yBuf = new float[max];
- timeBuf = new long[max];
- clear();
- }
-
- public void clear() {
- top = end = count = 0;
- }
-
- public int size() {
- return count;
- }
-
- // Position 0 points oldest event
- private int index(int pos) {
- return (end + pos) % bufSize;
- }
-
- private int advance(int index) {
- return (index + 1) % bufSize;
- }
-
- public void add(float x, float y, long time) {
- xBuf[top] = x;
- yBuf[top] = y;
- timeBuf[top] = time;
- top = advance(top);
- if (count < bufSize) {
- count++;
- } else {
- end = advance(end);
- }
- }
-
- public float getX(int pos) {
- return xBuf[index(pos)];
- }
-
- public float getY(int pos) {
- return yBuf[index(pos)];
- }
-
- public long getTime(int pos) {
- return timeBuf[index(pos)];
- }
-
- public void dropOldest() {
- count--;
- end = advance(end);
- }
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/CandidateView.java b/java/src/com/android/inputmethod/latin/CandidateView.java
index 7ec18b38a..565b01d5a 100644
--- a/java/src/com/android/inputmethod/latin/CandidateView.java
+++ b/java/src/com/android/inputmethod/latin/CandidateView.java
@@ -333,7 +333,9 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
final TypedArray keyboardViewAttr = context.obtainStyledAttributes(
attrs, R.styleable.KeyboardView, R.attr.keyboardViewStyle, R.style.KeyboardView);
- final Drawable keyBackground = keyboardViewAttr.getDrawable(
+ final Drawable expandBackground = keyboardViewAttr.getDrawable(
+ R.styleable.KeyboardView_keyBackground);
+ final Drawable closeBackground = keyboardViewAttr.getDrawable(
R.styleable.KeyboardView_keyBackground);
final int keyTextColor = keyboardViewAttr.getColor(
R.styleable.KeyboardView_keyTextColor, 0xFF000000);
@@ -341,7 +343,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
mCandidatesPaneControl = (ViewGroup)findViewById(R.id.candidates_pane_control);
mExpandCandidatesPane = (TextView)findViewById(R.id.expand_candidates_pane);
- mExpandCandidatesPane.setBackgroundDrawable(keyBackground);
+ mExpandCandidatesPane.setBackgroundDrawable(expandBackground);
mExpandCandidatesPane.setTextColor(keyTextColor);
mExpandCandidatesPane.setOnClickListener(new OnClickListener() {
@Override
@@ -350,7 +352,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
}
});
mCloseCandidatesPane = (TextView)findViewById(R.id.close_candidates_pane);
- mCloseCandidatesPane.setBackgroundDrawable(keyBackground);
+ mCloseCandidatesPane.setBackgroundDrawable(closeBackground);
mCloseCandidatesPane.setTextColor(keyTextColor);
mCloseCandidatesPane.setOnClickListener(new OnClickListener() {
@Override
@@ -704,6 +706,7 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
mCandidatesStrip.setVisibility(VISIBLE);
mCandidatesStrip.removeAllViews();
mCandidatesPane.removeAllViews();
+ closeCandidatesPane();
}
private void hidePreview() {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index a9f34c6c7..5304d830d 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -164,8 +164,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
private boolean mIsSettingsSuggestionStripOn;
private boolean mApplicationSpecifiedCompletionOn;
- private final StringBuilder mComposing = new StringBuilder();
- private WordComposer mWord = new WordComposer();
+ private final StringBuilder mComposingStringBuilder = new StringBuilder();
+ private WordComposer mWordComposer = new WordComposer();
private CharSequence mBestWord;
private boolean mHasUncommittedTypedChars;
private boolean mHasDictionary;
@@ -233,7 +233,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
case MSG_UPDATE_OLD_SUGGESTIONS:
latinIme.mRecorrection.fetchAndDisplayRecorrectionSuggestions(
latinIme.mVoiceProxy, latinIme.mCandidateView,
- latinIme.mSuggest, latinIme.mKeyboardSwitcher, latinIme.mWord,
+ latinIme.mSuggest, latinIme.mKeyboardSwitcher, latinIme.mWordComposer,
latinIme.mHasUncommittedTypedChars, latinIme.mLastSelectionStart,
latinIme.mLastSelectionEnd, latinIme.mSettingsValues.mWordSeparators);
break;
@@ -555,7 +555,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
inputView.closing();
mEnteredText = null;
- mComposing.setLength(0);
+ mComposingStringBuilder.setLength(0);
mHasUncommittedTypedChars = false;
mDeleteCount = 0;
mJustAddedMagicSpace = false;
@@ -580,6 +580,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
switcher.updateShiftState();
}
+ if (mCandidateView != null)
+ mCandidateView.clear();
setSuggestionStripShownInternal(isCandidateStripVisible(), /* needsInputViewShown */ false);
// Delay updating suggestions because keyboard input view may not be shown at this point.
mHandler.postUpdateSuggestions();
@@ -715,16 +717,16 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
final boolean selectionChanged = (newSelStart != candidatesEnd
|| newSelEnd != candidatesEnd) && mLastSelectionStart != newSelStart;
final boolean candidatesCleared = candidatesStart == -1 && candidatesEnd == -1;
- if (((mComposing.length() > 0 && mHasUncommittedTypedChars)
+ if (((mComposingStringBuilder.length() > 0 && mHasUncommittedTypedChars)
|| mVoiceProxy.isVoiceInputHighlighted())
&& (selectionChanged || candidatesCleared)) {
if (candidatesCleared) {
// If the composing span has been cleared, save the typed word in the history for
// recorrection before we reset the candidate strip. Then, we'll be able to show
// suggestions for recorrection right away.
- mRecorrection.saveRecorrectionSuggestion(mWord, mComposing);
+ mRecorrection.saveRecorrectionSuggestion(mWordComposer, mComposingStringBuilder);
}
- mComposing.setLength(0);
+ mComposingStringBuilder.setLength(0);
mHasUncommittedTypedChars = false;
if (isCursorTouchingWord()) {
mHandler.cancelUpdateBigramPredictions();
@@ -738,15 +740,13 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
ic.finishComposingText();
}
mVoiceProxy.setVoiceInputHighlighted(false);
- } else if (!mHasUncommittedTypedChars && !mExpectingUpdateSelection) {
- if (TextEntryState.isAcceptedDefault() || TextEntryState.isSpaceAfterPicked()) {
- if (TextEntryState.isAcceptedDefault())
- TextEntryState.reset();
- }
+ } else if (!mHasUncommittedTypedChars && !mExpectingUpdateSelection
+ && TextEntryState.isAcceptedDefault()) {
+ TextEntryState.reset();
}
if (!mExpectingUpdateSelection) {
- mJustAddedMagicSpace = false; // The user moved the cursor.
- mJustReplacedDoubleSpace = false;
+ mJustAddedMagicSpace = false; // The user moved the cursor.
+ mJustReplacedDoubleSpace = false;
}
mExpectingUpdateSelection = false;
mHandler.postUpdateShiftKeyState();
@@ -943,18 +943,18 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
public void commitTyped(InputConnection inputConnection) {
- if (mHasUncommittedTypedChars) {
- mHasUncommittedTypedChars = false;
- if (mComposing.length() > 0) {
- if (inputConnection != null) {
- inputConnection.commitText(mComposing, 1);
- }
- mCommittedLength = mComposing.length();
- TextEntryState.acceptedTyped(mComposing);
- addToAutoAndUserBigramDictionaries(mComposing, AutoDictionary.FREQUENCY_FOR_TYPED);
+ if (!mHasUncommittedTypedChars) return;
+ mHasUncommittedTypedChars = false;
+ if (mComposingStringBuilder.length() > 0) {
+ if (inputConnection != null) {
+ inputConnection.commitText(mComposingStringBuilder, 1);
}
- updateSuggestions();
+ mCommittedLength = mComposingStringBuilder.length();
+ TextEntryState.acceptedTyped(mComposingStringBuilder);
+ addToAutoAndUserBigramDictionaries(mComposingStringBuilder,
+ AutoDictionary.FREQUENCY_FOR_TYPED);
}
+ updateSuggestions();
}
public boolean getCurrentAutoCapsState() {
@@ -1183,12 +1183,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
final boolean deleteChar = !mHasUncommittedTypedChars;
if (mHasUncommittedTypedChars) {
- final int length = mComposing.length();
+ final int length = mComposingStringBuilder.length();
if (length > 0) {
- mComposing.delete(length - 1, length);
- mWord.deleteLast();
- ic.setComposingText(mComposing, 1);
- if (mComposing.length() == 0) {
+ mComposingStringBuilder.delete(length - 1, length);
+ mWordComposer.deleteLast();
+ ic.setComposingText(mComposingStringBuilder, 1);
+ if (mComposingStringBuilder.length() == 0) {
mHasUncommittedTypedChars = false;
}
if (1 == length) {
@@ -1278,9 +1278,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (isAlphabet(code) && isSuggestionsRequested() && !isCursorTouchingWord()) {
if (!mHasUncommittedTypedChars) {
mHasUncommittedTypedChars = true;
- mComposing.setLength(0);
- mRecorrection.saveRecorrectionSuggestion(mWord, mBestWord);
- mWord.reset();
+ mComposingStringBuilder.setLength(0);
+ mRecorrection.saveRecorrectionSuggestion(mWordComposer, mBestWord);
+ mWordComposer.reset();
clearSuggestions();
}
}
@@ -1306,19 +1306,19 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
}
if (mHasUncommittedTypedChars) {
- if (mComposing.length() == 0 && switcher.isAlphabetMode()
+ if (mComposingStringBuilder.length() == 0 && switcher.isAlphabetMode()
&& switcher.isShiftedOrShiftLocked()) {
- mWord.setFirstCharCapitalized(true);
+ mWordComposer.setFirstCharCapitalized(true);
}
- mComposing.append((char) code);
- mWord.add(code, keyCodes, x, y);
+ mComposingStringBuilder.append((char) code);
+ mWordComposer.add(code, keyCodes, x, y);
InputConnection ic = getCurrentInputConnection();
if (ic != null) {
// If it's the first letter, make note of auto-caps state
- if (mWord.size() == 1) {
- mWord.setAutoCapitalized(getCurrentAutoCapsState());
+ if (mWordComposer.size() == 1) {
+ mWordComposer.setAutoCapitalized(getCurrentAutoCapsState());
}
- ic.setComposingText(mComposing, 1);
+ ic.setComposingText(mComposingStringBuilder, 1);
}
mHandler.postUpdateSuggestions();
} else {
@@ -1386,7 +1386,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
TextEntryState.typedCharacter((char) primaryCode, true, x, y);
if (pickedDefault) {
- CharSequence typedWord = mWord.getTypedWord();
+ CharSequence typedWord = mWordComposer.getTypedWord();
TextEntryState.backToAcceptedDefault(typedWord);
if (!TextUtils.isEmpty(typedWord) && !typedWord.equals(mBestWord)) {
InputConnectionCompatUtils.commitCorrection(
@@ -1489,28 +1489,26 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
setPunctuationSuggestions();
return;
}
- showSuggestions(mWord);
- }
- private void showSuggestions(WordComposer word) {
+ final WordComposer wordComposer = mWordComposer;
// TODO: May need a better way of retrieving previous word
CharSequence prevWord = EditingUtils.getPreviousWord(getCurrentInputConnection(),
mSettingsValues.mWordSeparators);
SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(
- mKeyboardSwitcher.getKeyboardView(), word, prevWord);
+ mKeyboardSwitcher.getKeyboardView(), wordComposer, prevWord);
- boolean correctionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasAutoCorrection();
- final CharSequence typedWord = word.getTypedWord();
+ boolean autoCorrectionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasAutoCorrection();
+ final CharSequence typedWord = wordComposer.getTypedWord();
// Here, we want to promote a whitelisted word if exists.
final boolean typedWordValid = AutoCorrection.isValidWordForAutoCorrection(
mSuggest.getUnigramDictionaries(), typedWord, preferCapitalization());
if (mCorrectionMode == Suggest.CORRECTION_FULL
|| mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) {
- correctionAvailable |= typedWordValid;
+ autoCorrectionAvailable |= typedWordValid;
}
// Don't auto-correct words with multiple capital letter
- correctionAvailable &= !word.isMostlyCaps();
- correctionAvailable &= !TextEntryState.isRecorrecting();
+ autoCorrectionAvailable &= !wordComposer.isMostlyCaps();
+ autoCorrectionAvailable &= !TextEntryState.isRecorrecting();
// Basically, we update the suggestion strip only when suggestion count > 1. However,
// there is an exception: We update the suggestion strip whenever typed word's length
@@ -1522,7 +1520,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (builder.size() > 1 || typedWord.length() == 1 || typedWordValid
|| mCandidateView.isShowingAddToDictionaryHint()) {
builder.setTypedWordValid(typedWordValid).setHasMinimalSuggestion(
- correctionAvailable);
+ autoCorrectionAvailable);
} else {
final SuggestedWords previousSuggestions = mCandidateView.getSuggestions();
if (previousSuggestions == mSettingsValues.mSuggestPuncList)
@@ -1556,7 +1554,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
updateSuggestions();
}
if (mBestWord != null && mBestWord.length() > 0) {
- TextEntryState.acceptedDefault(mWord.getTypedWord(), mBestWord, separatorCode);
+ TextEntryState.acceptedDefault(mWordComposer.getTypedWord(), mBestWord, separatorCode);
mExpectingUpdateSelection = true;
commitBestWord(mBestWord);
// Add the word to the auto dictionary if it's not a known word
@@ -1623,7 +1621,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
if (!mHasUncommittedTypedChars) {
// If we are not composing a word, then it was a suggestion inferred from
// context - no user input. We should reset the word composer.
- mWord.reset();
+ mWordComposer.reset();
}
mExpectingUpdateSelection = true;
commitBestWord(suggestion);
@@ -1633,9 +1631,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} else {
addToOnlyBigramDictionary(suggestion, 1);
}
- LatinImeLogger.logOnManualSuggestion(mComposing.toString(), suggestion.toString(),
- index, suggestions.mWords);
- TextEntryState.acceptedSuggestion(mComposing.toString(), suggestion);
+ LatinImeLogger.logOnManualSuggestion(mComposingStringBuilder.toString(),
+ suggestion.toString(), index, suggestions.mWords);
+ TextEntryState.acceptedSuggestion(mComposingStringBuilder.toString(), suggestion);
// Follow it with a space
if (mShouldInsertMagicSpace && !recorrecting) {
sendMagicSpace();
@@ -1680,8 +1678,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
/**
- * Commits the chosen word to the text field and saves it for later
- * retrieval.
+ * Commits the chosen word to the text field and saves it for later retrieval.
*/
private void commitBestWord(CharSequence bestWord) {
KeyboardSwitcher switcher = mKeyboardSwitcher;
@@ -1694,7 +1691,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
ic.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan(
this, bestWord, suggestedWords), 1);
}
- mRecorrection.saveRecorrectionSuggestion(mWord, bestWord);
+ mRecorrection.saveRecorrectionSuggestion(mWordComposer, bestWord);
mHasUncommittedTypedChars = false;
mCommittedLength = bestWord.length();
}
@@ -1798,41 +1795,40 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
private void revertLastWord(boolean deleteChar) {
- final int length = mComposing.length();
- if (!mHasUncommittedTypedChars && length > 0) {
- final InputConnection ic = getCurrentInputConnection();
- final CharSequence punctuation = ic.getTextBeforeCursor(1, 0);
- if (deleteChar) ic.deleteSurroundingText(1, 0);
- int toDelete = mCommittedLength;
- final CharSequence toTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0);
- if (!TextUtils.isEmpty(toTheLeft)
- && mSettingsValues.isWordSeparator(toTheLeft.charAt(0))) {
- toDelete--;
- }
- ic.deleteSurroundingText(toDelete, 0);
- // Re-insert punctuation only when the deleted character was word separator and the
- // composing text wasn't equal to the auto-corrected text.
- if (deleteChar
- && !TextUtils.isEmpty(punctuation)
- && mSettingsValues.isWordSeparator(punctuation.charAt(0))
- && !TextUtils.equals(mComposing, toTheLeft)) {
- ic.commitText(mComposing, 1);
- TextEntryState.acceptedTyped(mComposing);
- ic.commitText(punctuation, 1);
- TextEntryState.typedCharacter(punctuation.charAt(0), true,
- WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
- // Clear composing text
- mComposing.setLength(0);
- } else {
- mHasUncommittedTypedChars = true;
- ic.setComposingText(mComposing, 1);
- TextEntryState.backspace();
- }
- mHandler.cancelUpdateBigramPredictions();
- mHandler.postUpdateSuggestions();
- } else {
+ if (mHasUncommittedTypedChars || mComposingStringBuilder.length() <= 0) {
sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
+ return;
+ }
+
+ final InputConnection ic = getCurrentInputConnection();
+ final CharSequence punctuation = ic.getTextBeforeCursor(1, 0);
+ if (deleteChar) ic.deleteSurroundingText(1, 0);
+ final CharSequence textToTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0);
+ final int toDeleteLength = (!TextUtils.isEmpty(textToTheLeft)
+ && mSettingsValues.isWordSeparator(textToTheLeft.charAt(0)))
+ ? mCommittedLength - 1 : mCommittedLength;
+ ic.deleteSurroundingText(toDeleteLength, 0);
+
+ // Re-insert punctuation only when the deleted character was word separator and the
+ // composing text wasn't equal to the auto-corrected text.
+ if (deleteChar
+ && !TextUtils.isEmpty(punctuation)
+ && mSettingsValues.isWordSeparator(punctuation.charAt(0))
+ && !TextUtils.equals(mComposingStringBuilder, textToTheLeft)) {
+ ic.commitText(mComposingStringBuilder, 1);
+ TextEntryState.acceptedTyped(mComposingStringBuilder);
+ ic.commitText(punctuation, 1);
+ TextEntryState.typedCharacter(punctuation.charAt(0), true,
+ WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
+ // Clear composing text
+ mComposingStringBuilder.setLength(0);
+ } else {
+ mHasUncommittedTypedChars = true;
+ ic.setComposingText(mComposingStringBuilder, 1);
+ TextEntryState.backspace();
}
+ mHandler.cancelUpdateBigramPredictions();
+ mHandler.postUpdateSuggestions();
}
private boolean revertDoubleSpace() {
@@ -1861,7 +1857,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
public boolean preferCapitalization() {
- return mWord.isFirstCharCapitalized();
+ return mWordComposer.isFirstCharCapitalized();
}
// Notify that language or mode have been changed and toggleLanguage will update KeyboardID
@@ -1890,12 +1886,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// subtype changes.
if (!CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED)
onRefreshKeyboard();
- }
-
- @Override
- public void onSwipeDown() {
- if (mSettingsValues.mSwipeDownDismissKeyboardEnabled)
- handleClose();
}
@Override
@@ -1991,7 +1981,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
}
public WordComposer getCurrentWord() {
- return mWord;
+ return mWordComposer;
}
boolean isSoundOn() {
@@ -2127,7 +2117,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
final Printer p = new PrintWriterPrinter(fout);
p.println("LatinIME state :");
p.println(" Keyboard mode = " + mKeyboardSwitcher.getKeyboardMode());
- p.println(" mComposing=" + mComposing.toString());
+ p.println(" mComposingStringBuilder=" + mComposingStringBuilder.toString());
p.println(" mIsSuggestionsRequested=" + mIsSettingsSuggestionStripOn);
p.println(" mCorrectionMode=" + mCorrectionMode);
p.println(" mHasUncommittedTypedChars=" + mHasUncommittedTypedChars);
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index d6b989073..33e9bc35f 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -18,8 +18,10 @@ package com.android.inputmethod.latin;
import com.android.inputmethod.compat.CompatUtils;
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
+import com.android.inputmethod.compat.InputMethodServiceCompatWrapper;
import com.android.inputmethod.deprecated.VoiceProxy;
import com.android.inputmethod.compat.VibratorCompatWrapper;
+import com.android.inputmethodcommon.InputMethodSettingsActivity;
import android.app.Activity;
import android.app.AlertDialog;
@@ -36,7 +38,6 @@ import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
-import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.speech.SpeechRecognizer;
@@ -48,7 +49,7 @@ import android.widget.TextView;
import java.util.Arrays;
import java.util.Locale;
-public class Settings extends PreferenceActivity
+public class Settings extends InputMethodSettingsActivity
implements SharedPreferences.OnSharedPreferenceChangeListener,
DialogInterface.OnDismissListener, OnPreferenceClickListener {
private static final String TAG = "Settings";
@@ -90,7 +91,6 @@ public class Settings extends PreferenceActivity
public static class Values {
// From resources:
- public final boolean mSwipeDownDismissKeyboardEnabled;
public final int mDelayBeforeFadeoutLanguageOnSpacebar;
public final int mDelayUpdateSuggestions;
public final int mDelayUpdateOldSuggestions;
@@ -131,8 +131,6 @@ public class Settings extends PreferenceActivity
}
// Get the resources
- mSwipeDownDismissKeyboardEnabled = res.getBoolean(
- R.bool.config_swipe_down_dismiss_keyboard_enabled);
mDelayBeforeFadeoutLanguageOnSpacebar = res.getInteger(
R.integer.config_delay_before_fadeout_language_on_spacebar);
mDelayUpdateSuggestions =
@@ -292,7 +290,6 @@ public class Settings extends PreferenceActivity
}
private PreferenceScreen mInputLanguageSelection;
- private CheckBoxPreference mQuickFixes;
private ListPreference mVoicePreference;
private ListPreference mSettingsKeyPreference;
private ListPreference mShowCorrectionSuggestionsPreference;
@@ -334,13 +331,14 @@ public class Settings extends PreferenceActivity
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ setInputMethodSettingsCategoryTitle(R.string.language_selection_title);
+ setSubtypeEnablerTitle(R.string.select_language);
final Resources res = getResources();
final Context context = getActivityInternal();
addPreferencesFromResource(R.xml.prefs);
mInputLanguageSelection = (PreferenceScreen) findPreference(PREF_SUBTYPES);
mInputLanguageSelection.setOnPreferenceClickListener(this);
- mQuickFixes = (CheckBoxPreference) findPreference(PREF_QUICK_FIXES);
mVoicePreference = (ListPreference) findPreference(PREF_VOICE_SETTINGS_KEY);
mSettingsKeyPreference = (ListPreference) findPreference(PREF_SETTINGS_KEY);
mShowCorrectionSuggestionsPreference =
@@ -387,6 +385,10 @@ public class Settings extends PreferenceActivity
generalSettings.removePreference(findPreference(PREF_VIBRATE_ON));
}
+ if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) {
+ generalSettings.removePreference(findPreference(PREF_SUBTYPES));
+ }
+
final boolean showPopupOption = res.getBoolean(
R.bool.config_enable_show_popup_on_keypress_option);
if (!showPopupOption) {
diff --git a/java/src/com/android/inputmethod/latin/SettingsActivity.java b/java/src/com/android/inputmethod/latin/SettingsActivity.java
deleted file mode 100644
index 2da171a63..000000000
--- a/java/src/com/android/inputmethod/latin/SettingsActivity.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2011 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;
-
-public class SettingsActivity extends Settings {
-}
diff --git a/java/src/com/android/inputmethod/latin/TextEntryState.java b/java/src/com/android/inputmethod/latin/TextEntryState.java
index b6e261114..79b3bdebb 100644
--- a/java/src/com/android/inputmethod/latin/TextEntryState.java
+++ b/java/src/com/android/inputmethod/latin/TextEntryState.java
@@ -16,6 +16,7 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.latin.Utils.RingCharBuffer;
import android.util.Log;
@@ -100,7 +101,7 @@ public class TextEntryState {
}
public static void typedCharacter(char c, boolean isSeparator, int x, int y) {
- final boolean isSpace = (c == ' ');
+ final boolean isSpace = (c == Keyboard.CODE_SPACE);
switch (sState) {
case IN_WORD:
if (isSpace || isSeparator) {