aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com')
-rw-r--r--java/src/com/android/inputmethod/latin/BaseKeyboard.java804
-rw-r--r--java/src/com/android/inputmethod/latin/KeyDetector.java7
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java21
-rw-r--r--java/src/com/android/inputmethod/latin/LatinImeLogger.java3
-rw-r--r--java/src/com/android/inputmethod/latin/LatinKeyboard.java7
-rw-r--r--java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java23
-rw-r--r--java/src/com/android/inputmethod/latin/LatinKeyboardView.java16
-rw-r--r--java/src/com/android/inputmethod/latin/MiniKeyboardKeyDetector.java2
-rw-r--r--java/src/com/android/inputmethod/latin/PointerTracker.java11
-rw-r--r--java/src/com/android/inputmethod/latin/ProximityKeyDetector.java2
-rw-r--r--java/src/com/android/inputmethod/latin/TextEntryState.java3
11 files changed, 850 insertions, 49 deletions
diff --git a/java/src/com/android/inputmethod/latin/BaseKeyboard.java b/java/src/com/android/inputmethod/latin/BaseKeyboard.java
new file mode 100644
index 000000000..f1a08cb4a
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/BaseKeyboard.java
@@ -0,0 +1,804 @@
+/*
+ * Copyright (C) 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.TypedValue;
+import android.util.Xml;
+import android.util.DisplayMetrics;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+
+/**
+ * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard
+ * consists of rows of keys.
+ * <p>The layout file for a keyboard contains XML that looks like the following snippet:</p>
+ * <pre>
+ * &lt;Keyboard
+ * latin:keyWidth="%10p"
+ * latin:keyHeight="50px"
+ * latin:horizontalGap="2px"
+ * latin:verticalGap="2px" &gt;
+ * &lt;Row latin:keyWidth="32px" &gt;
+ * &lt;Key latin:keyLabel="A" /&gt;
+ * ...
+ * &lt;/Row&gt;
+ * ...
+ * &lt;/Keyboard&gt;
+ * </pre>
+ */
+public class BaseKeyboard {
+
+ static final String TAG = "BaseKeyboard";
+
+ // Keyboard XML Tags
+ private static final String TAG_KEYBOARD = "Keyboard";
+ private static final String TAG_ROW = "Row";
+ private static final String TAG_KEY = "Key";
+
+ public static final int EDGE_LEFT = 0x01;
+ public static final int EDGE_RIGHT = 0x02;
+ public static final int EDGE_TOP = 0x04;
+ public static final int EDGE_BOTTOM = 0x08;
+
+ public static final int KEYCODE_SHIFT = -1;
+ public static final int KEYCODE_MODE_CHANGE = -2;
+ public static final int KEYCODE_CANCEL = -3;
+ public static final int KEYCODE_DONE = -4;
+ public static final int KEYCODE_DELETE = -5;
+ public static final int KEYCODE_ALT = -6;
+
+ /** Horizontal gap default for all rows */
+ private int mDefaultHorizontalGap;
+
+ /** Default key width */
+ private int mDefaultWidth;
+
+ /** Default key height */
+ private int mDefaultHeight;
+
+ /** Default gap between rows */
+ private int mDefaultVerticalGap;
+
+ /** Is the keyboard in the shifted state */
+ private boolean mShifted;
+
+ /** Key instance for the shift key, if present */
+ private Key mShiftKey;
+
+ /** Key index for the shift key, if present */
+ private int mShiftKeyIndex = -1;
+
+ /** Total height of the keyboard, including the padding and keys */
+ private int mTotalHeight;
+
+ /**
+ * Total width of the keyboard, including left side gaps and keys, but not any gaps on the
+ * right side.
+ */
+ private int mTotalWidth;
+
+ /** List of keys in this keyboard */
+ private List<Key> mKeys;
+
+ /** List of modifier keys such as Shift & Alt, if any */
+ private List<Key> mModifierKeys;
+
+ /** Width of the screen available to fit the keyboard */
+ private int mDisplayWidth;
+
+ /** Height of the screen */
+ private int mDisplayHeight;
+
+ /** Keyboard mode, or zero, if none. */
+ private int mKeyboardMode;
+
+ // Variables for pre-computing nearest keys.
+
+ private static final int GRID_WIDTH = 10;
+ private static final int GRID_HEIGHT = 5;
+ private static final int GRID_SIZE = GRID_WIDTH * GRID_HEIGHT;
+ private int mCellWidth;
+ private int mCellHeight;
+ private int[][] mGridNeighbors;
+ private int mProximityThreshold;
+ /** Number of key widths from current touch point to search for nearest keys. */
+ private static float SEARCH_DISTANCE = 1.8f;
+
+ /**
+ * Container for keys in the keyboard. All keys in a row are at the same Y-coordinate.
+ * Some of the key size defaults can be overridden per row from what the {@link Keyboard}
+ * defines.
+ */
+ public static class Row {
+ /** Default width of a key in this row. */
+ public int defaultWidth;
+ /** Default height of a key in this row. */
+ public int defaultHeight;
+ /** Default horizontal gap between keys in this row. */
+ public int defaultHorizontalGap;
+ /** Vertical gap following this row. */
+ public int verticalGap;
+ /**
+ * Edge flags for this row of keys. Possible values that can be assigned are
+ * {@link Keyboard#EDGE_TOP EDGE_TOP} and {@link Keyboard#EDGE_BOTTOM EDGE_BOTTOM}
+ */
+ public int rowEdgeFlags;
+
+ /** The keyboard mode for this row */
+ public int mode;
+
+ private BaseKeyboard parent;
+
+ public Row(BaseKeyboard parent) {
+ this.parent = parent;
+ }
+
+ public Row(Resources res, BaseKeyboard parent, XmlResourceParser parser) {
+ this.parent = parent;
+ TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.BaseKeyboard);
+ defaultWidth = getDimensionOrFraction(a,
+ R.styleable.BaseKeyboard_keyWidth,
+ parent.mDisplayWidth, parent.mDefaultWidth);
+ defaultHeight = getDimensionOrFraction(a,
+ R.styleable.BaseKeyboard_keyHeight,
+ parent.mDisplayHeight, parent.mDefaultHeight);
+ defaultHorizontalGap = getDimensionOrFraction(a,
+ R.styleable.BaseKeyboard_horizontalGap,
+ parent.mDisplayWidth, parent.mDefaultHorizontalGap);
+ verticalGap = getDimensionOrFraction(a,
+ R.styleable.BaseKeyboard_verticalGap,
+ parent.mDisplayHeight, parent.mDefaultVerticalGap);
+ a.recycle();
+ a = res.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.BaseKeyboard_Row);
+ rowEdgeFlags = a.getInt(R.styleable.BaseKeyboard_Row_rowEdgeFlags, 0);
+ mode = a.getResourceId(R.styleable.BaseKeyboard_Row_keyboardMode,
+ 0);
+ }
+ }
+
+ /**
+ * Class for describing the position and characteristics of a single key in the keyboard.
+ */
+ public static class Key {
+ /**
+ * All the key codes (unicode or custom code) that this key could generate, zero'th
+ * being the most important.
+ */
+ public int[] codes;
+
+ /** Label to display */
+ public CharSequence label;
+
+ /** Icon to display instead of a label. Icon takes precedence over a label */
+ public Drawable icon;
+ /** Preview version of the icon, for the preview popup */
+ public Drawable iconPreview;
+ /** Width of the key, not including the gap */
+ public int width;
+ /** Height of the key, not including the gap */
+ public int height;
+ /** The horizontal gap before this key */
+ public int gap;
+ /** Whether this key is sticky, i.e., a toggle key */
+ public boolean sticky;
+ /** X coordinate of the key in the keyboard layout */
+ public int x;
+ /** Y coordinate of the key in the keyboard layout */
+ public int y;
+ /** The current pressed state of this key */
+ public boolean pressed;
+ /** If this is a sticky key, is it on? */
+ public boolean on;
+ /** Text to output when pressed. This can be multiple characters, like ".com" */
+ public CharSequence text;
+ /** Popup characters */
+ public CharSequence popupCharacters;
+
+ /**
+ * Flags that specify the anchoring to edges of the keyboard for detecting touch events
+ * that are just out of the boundary of the key. This is a bit mask of
+ * {@link Keyboard#EDGE_LEFT}, {@link Keyboard#EDGE_RIGHT}, {@link Keyboard#EDGE_TOP} and
+ * {@link Keyboard#EDGE_BOTTOM}.
+ */
+ public int edgeFlags;
+ /** Whether this is a modifier key, such as Shift or Alt */
+ public boolean modifier;
+ /** The BaseKeyboard that this key belongs to */
+ private BaseKeyboard keyboard;
+ /**
+ * If this key pops up a mini keyboard, this is the resource id for the XML layout for that
+ * keyboard.
+ */
+ public int popupResId;
+ /** Whether this key repeats itself when held down */
+ public boolean repeatable;
+
+
+ private final static int[] KEY_STATE_NORMAL_ON = {
+ android.R.attr.state_checkable,
+ android.R.attr.state_checked
+ };
+
+ private final static int[] KEY_STATE_PRESSED_ON = {
+ android.R.attr.state_pressed,
+ android.R.attr.state_checkable,
+ android.R.attr.state_checked
+ };
+
+ private final static int[] KEY_STATE_NORMAL_OFF = {
+ android.R.attr.state_checkable
+ };
+
+ private final static int[] KEY_STATE_PRESSED_OFF = {
+ android.R.attr.state_pressed,
+ android.R.attr.state_checkable
+ };
+
+ private final static int[] KEY_STATE_NORMAL = {
+ };
+
+ private final static int[] KEY_STATE_PRESSED = {
+ android.R.attr.state_pressed
+ };
+
+ /** Create an empty key with no attributes. */
+ public Key(Row parent) {
+ keyboard = parent.parent;
+ height = parent.defaultHeight;
+ width = parent.defaultWidth;
+ gap = parent.defaultHorizontalGap;
+ edgeFlags = parent.rowEdgeFlags;
+ }
+
+ /** Create a key with the given top-left coordinate and extract its attributes from
+ * the XML parser.
+ * @param res resources associated with the caller's context
+ * @param parent the row that this key belongs to. The row must already be attached to
+ * a {@link Keyboard}.
+ * @param x the x coordinate of the top-left
+ * @param y the y coordinate of the top-left
+ * @param parser the XML parser containing the attributes for this key
+ */
+ public Key(Resources res, Row parent, int x, int y, XmlResourceParser parser) {
+ this(parent);
+
+ this.x = x;
+ this.y = y;
+
+ TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.BaseKeyboard);
+
+ width = getDimensionOrFraction(a,
+ R.styleable.BaseKeyboard_keyWidth,
+ keyboard.mDisplayWidth, parent.defaultWidth);
+ height = getDimensionOrFraction(a,
+ R.styleable.BaseKeyboard_keyHeight,
+ keyboard.mDisplayHeight, parent.defaultHeight);
+ gap = getDimensionOrFraction(a,
+ R.styleable.BaseKeyboard_horizontalGap,
+ keyboard.mDisplayWidth, parent.defaultHorizontalGap);
+ a.recycle();
+ a = res.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.BaseKeyboard_Key);
+ this.x += gap;
+ TypedValue codesValue = new TypedValue();
+ a.getValue(R.styleable.BaseKeyboard_Key_codes,
+ codesValue);
+ if (codesValue.type == TypedValue.TYPE_INT_DEC
+ || codesValue.type == TypedValue.TYPE_INT_HEX) {
+ codes = new int[] { codesValue.data };
+ } else if (codesValue.type == TypedValue.TYPE_STRING) {
+ codes = parseCSV(codesValue.string.toString());
+ }
+
+ iconPreview = a.getDrawable(R.styleable.BaseKeyboard_Key_iconPreview);
+ if (iconPreview != null) {
+ iconPreview.setBounds(0, 0, iconPreview.getIntrinsicWidth(),
+ iconPreview.getIntrinsicHeight());
+ }
+ popupCharacters = a.getText(
+ R.styleable.BaseKeyboard_Key_popupCharacters);
+ popupResId = a.getResourceId(
+ R.styleable.BaseKeyboard_Key_popupKeyboard, 0);
+ repeatable = a.getBoolean(
+ R.styleable.BaseKeyboard_Key_isRepeatable, false);
+ modifier = a.getBoolean(
+ R.styleable.BaseKeyboard_Key_isModifier, false);
+ sticky = a.getBoolean(
+ R.styleable.BaseKeyboard_Key_isSticky, false);
+ edgeFlags = a.getInt(R.styleable.BaseKeyboard_Key_keyEdgeFlags, 0);
+ edgeFlags |= parent.rowEdgeFlags;
+
+ icon = a.getDrawable(
+ R.styleable.BaseKeyboard_Key_keyIcon);
+ if (icon != null) {
+ icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
+ }
+ label = a.getText(R.styleable.BaseKeyboard_Key_keyLabel);
+ text = a.getText(R.styleable.BaseKeyboard_Key_keyOutputText);
+
+ if (codes == null && !TextUtils.isEmpty(label)) {
+ codes = new int[] { label.charAt(0) };
+ }
+ a.recycle();
+ }
+
+ /**
+ * Informs the key that it has been pressed, in case it needs to change its appearance or
+ * state.
+ * @see #onReleased(boolean)
+ */
+ public void onPressed() {
+ pressed = !pressed;
+ }
+
+ /**
+ * Changes the pressed state of the key. If it is a sticky key, it will also change the
+ * toggled state of the key if the finger was release inside.
+ * @param inside whether the finger was released inside the key
+ * @see #onPressed()
+ */
+ public void onReleased(boolean inside) {
+ pressed = !pressed;
+ if (sticky) {
+ on = !on;
+ }
+ }
+
+ int[] parseCSV(String value) {
+ int count = 0;
+ int lastIndex = 0;
+ if (value.length() > 0) {
+ count++;
+ while ((lastIndex = value.indexOf(",", lastIndex + 1)) > 0) {
+ count++;
+ }
+ }
+ int[] values = new int[count];
+ count = 0;
+ StringTokenizer st = new StringTokenizer(value, ",");
+ while (st.hasMoreTokens()) {
+ try {
+ values[count++] = Integer.parseInt(st.nextToken());
+ } catch (NumberFormatException nfe) {
+ Log.e(TAG, "Error parsing keycodes " + value);
+ }
+ }
+ return values;
+ }
+
+ /**
+ * Detects if a point falls inside this key.
+ * @param x the x-coordinate of the point
+ * @param y the y-coordinate of the point
+ * @return whether or not the point falls inside the key. If the key is attached to an edge,
+ * it will assume that all points between the key and the edge are considered to be inside
+ * the key.
+ */
+ public boolean isInside(int x, int y) {
+ boolean leftEdge = (edgeFlags & EDGE_LEFT) > 0;
+ boolean rightEdge = (edgeFlags & EDGE_RIGHT) > 0;
+ boolean topEdge = (edgeFlags & EDGE_TOP) > 0;
+ boolean bottomEdge = (edgeFlags & EDGE_BOTTOM) > 0;
+ if ((x >= this.x || (leftEdge && x <= this.x + this.width))
+ && (x < this.x + this.width || (rightEdge && x >= this.x))
+ && (y >= this.y || (topEdge && y <= this.y + this.height))
+ && (y < this.y + this.height || (bottomEdge && y >= this.y))) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the square of the distance between the center of the key and the given point.
+ * @param x the x-coordinate of the point
+ * @param y the y-coordinate of the point
+ * @return the square of the distance of the point from the center of the key
+ */
+ public int squaredDistanceFrom(int x, int y) {
+ int xDist = this.x + width / 2 - x;
+ int yDist = this.y + height / 2 - y;
+ return xDist * xDist + yDist * yDist;
+ }
+
+ /**
+ * Returns the drawable state for the key, based on the current state and type of the key.
+ * @return the drawable state of the key.
+ * @see android.graphics.drawable.StateListDrawable#setState(int[])
+ */
+ public int[] getCurrentDrawableState() {
+ int[] states = KEY_STATE_NORMAL;
+
+ if (on) {
+ if (pressed) {
+ states = KEY_STATE_PRESSED_ON;
+ } else {
+ states = KEY_STATE_NORMAL_ON;
+ }
+ } else {
+ if (sticky) {
+ if (pressed) {
+ states = KEY_STATE_PRESSED_OFF;
+ } else {
+ states = KEY_STATE_NORMAL_OFF;
+ }
+ } else {
+ if (pressed) {
+ states = KEY_STATE_PRESSED;
+ }
+ }
+ }
+ return states;
+ }
+ }
+
+ /**
+ * Creates a keyboard from the given xml key layout file.
+ * @param context the application or service context
+ * @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
+ */
+ public BaseKeyboard(Context context, int xmlLayoutResId) {
+ this(context, xmlLayoutResId, 0);
+ }
+
+ /**
+ * Creates a keyboard from the given xml key layout file. Weeds out rows
+ * that have a keyboard mode defined but don't match the specified mode.
+ * @param context the application or service context
+ * @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
+ * @param modeId keyboard mode identifier
+ * @param width sets width of keyboard
+ * @param height sets height of keyboard
+ */
+ public BaseKeyboard(Context context, int xmlLayoutResId, int modeId, int width, int height) {
+ mDisplayWidth = width;
+ mDisplayHeight = height;
+
+ mDefaultHorizontalGap = 0;
+ mDefaultWidth = mDisplayWidth / 10;
+ mDefaultVerticalGap = 0;
+ mDefaultHeight = mDefaultWidth;
+ mKeys = new ArrayList<Key>();
+ mModifierKeys = new ArrayList<Key>();
+ mKeyboardMode = modeId;
+ loadKeyboard(context, context.getResources().getXml(xmlLayoutResId));
+ }
+
+ /**
+ * Creates a keyboard from the given xml key layout file. Weeds out rows
+ * that have a keyboard mode defined but don't match the specified mode.
+ * @param context the application or service context
+ * @param xmlLayoutResId the resource file that contains the keyboard layout and keys.
+ * @param modeId keyboard mode identifier
+ */
+ public BaseKeyboard(Context context, int xmlLayoutResId, int modeId) {
+ DisplayMetrics dm = context.getResources().getDisplayMetrics();
+ mDisplayWidth = dm.widthPixels;
+ mDisplayHeight = dm.heightPixels;
+ //Log.v(TAG, "keyboard's display metrics:" + dm);
+
+ mDefaultHorizontalGap = 0;
+ mDefaultWidth = mDisplayWidth / 10;
+ mDefaultVerticalGap = 0;
+ mDefaultHeight = mDefaultWidth;
+ mKeys = new ArrayList<Key>();
+ mModifierKeys = new ArrayList<Key>();
+ mKeyboardMode = modeId;
+ loadKeyboard(context, context.getResources().getXml(xmlLayoutResId));
+ }
+
+ /**
+ * <p>Creates a blank keyboard from the given resource file and populates it with the specified
+ * characters in left-to-right, top-to-bottom fashion, using the specified number of columns.
+ * </p>
+ * <p>If the specified number of columns is -1, then the keyboard will fit as many keys as
+ * possible in each row.</p>
+ * @param context the application or service context
+ * @param layoutTemplateResId the layout template file, containing no keys.
+ * @param characters the list of characters to display on the keyboard. One key will be created
+ * for each character.
+ * @param columns the number of columns of keys to display. If this number is greater than the
+ * number of keys that can fit in a row, it will be ignored. If this number is -1, the
+ * keyboard will fit as many keys as possible in each row.
+ */
+ public BaseKeyboard(Context context, int layoutTemplateResId,
+ CharSequence characters, int columns, int horizontalPadding) {
+ this(context, layoutTemplateResId);
+ int x = 0;
+ int y = 0;
+ int column = 0;
+ mTotalWidth = 0;
+
+ Row row = new Row(this);
+ row.defaultHeight = mDefaultHeight;
+ row.defaultWidth = mDefaultWidth;
+ row.defaultHorizontalGap = mDefaultHorizontalGap;
+ row.verticalGap = mDefaultVerticalGap;
+ row.rowEdgeFlags = EDGE_TOP | EDGE_BOTTOM;
+ final int maxColumns = columns == -1 ? Integer.MAX_VALUE : columns;
+ for (int i = 0; i < characters.length(); i++) {
+ char c = characters.charAt(i);
+ if (column >= maxColumns
+ || x + mDefaultWidth + horizontalPadding > mDisplayWidth) {
+ x = 0;
+ y += mDefaultVerticalGap + mDefaultHeight;
+ column = 0;
+ }
+ final Key key = new Key(row);
+ key.x = x;
+ key.y = y;
+ key.label = String.valueOf(c);
+ key.codes = new int[] { c };
+ column++;
+ x += key.width + key.gap;
+ mKeys.add(key);
+ if (x > mTotalWidth) {
+ mTotalWidth = x;
+ }
+ }
+ mTotalHeight = y + mDefaultHeight;
+ }
+
+ public List<Key> getKeys() {
+ return mKeys;
+ }
+
+ public List<Key> getModifierKeys() {
+ return mModifierKeys;
+ }
+
+ protected int getHorizontalGap() {
+ return mDefaultHorizontalGap;
+ }
+
+ protected void setHorizontalGap(int gap) {
+ mDefaultHorizontalGap = gap;
+ }
+
+ protected int getVerticalGap() {
+ return mDefaultVerticalGap;
+ }
+
+ protected void setVerticalGap(int gap) {
+ mDefaultVerticalGap = gap;
+ }
+
+ protected int getKeyHeight() {
+ return mDefaultHeight;
+ }
+
+ protected void setKeyHeight(int height) {
+ mDefaultHeight = height;
+ }
+
+ protected int getKeyWidth() {
+ return mDefaultWidth;
+ }
+
+ protected void setKeyWidth(int width) {
+ mDefaultWidth = width;
+ }
+
+ /**
+ * Returns the total height of the keyboard
+ * @return the total height of the keyboard
+ */
+ public int getHeight() {
+ return mTotalHeight;
+ }
+
+ public int getMinWidth() {
+ return mTotalWidth;
+ }
+
+ public boolean setShifted(boolean shiftState) {
+ if (mShiftKey != null) {
+ mShiftKey.on = shiftState;
+ }
+ if (mShifted != shiftState) {
+ mShifted = shiftState;
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isShifted() {
+ return mShifted;
+ }
+
+ public int getShiftKeyIndex() {
+ return mShiftKeyIndex;
+ }
+
+ private 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][];
+ int[] indices = new int[mKeys.size()];
+ final int gridWidth = GRID_WIDTH * mCellWidth;
+ final int gridHeight = GRID_HEIGHT * mCellHeight;
+ for (int x = 0; x < gridWidth; x += mCellWidth) {
+ for (int y = 0; y < gridHeight; y += mCellHeight) {
+ int count = 0;
+ for (int i = 0; i < mKeys.size(); i++) {
+ final Key key = mKeys.get(i);
+ if (key.squaredDistanceFrom(x, y) < mProximityThreshold ||
+ key.squaredDistanceFrom(x + mCellWidth - 1, y) < mProximityThreshold ||
+ key.squaredDistanceFrom(x + mCellWidth - 1, y + mCellHeight - 1)
+ < mProximityThreshold ||
+ key.squaredDistanceFrom(x, y + mCellHeight - 1) < mProximityThreshold) {
+ indices[count++] = i;
+ }
+ }
+ int [] cell = new int[count];
+ System.arraycopy(indices, 0, cell, 0, count);
+ mGridNeighbors[(y / mCellHeight) * GRID_WIDTH + (x / mCellWidth)] = cell;
+ }
+ }
+ }
+
+ /**
+ * Returns the indices of the keys that are closest to the given point.
+ * @param x the x-coordinate of the point
+ * @param y the y-coordinate of the point
+ * @return the array of integer indices for the nearest keys to the given point. If the given
+ * 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 new int[0];
+ }
+
+ protected Row createRowFromXml(Resources res, XmlResourceParser parser) {
+ return new Row(res, this, parser);
+ }
+
+ protected Key createKeyFromXml(Resources res, Row parent, int x, int y,
+ XmlResourceParser parser) {
+ return new Key(res, parent, x, y, parser);
+ }
+
+ private void loadKeyboard(Context context, XmlResourceParser parser) {
+ boolean inKey = false;
+ boolean inRow = false;
+ int row = 0;
+ int x = 0;
+ int y = 0;
+ Key key = null;
+ Row currentRow = null;
+ Resources res = context.getResources();
+ boolean skipRow = false;
+
+ try {
+ int event;
+ while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) {
+ if (event == XmlResourceParser.START_TAG) {
+ String tag = parser.getName();
+ if (TAG_ROW.equals(tag)) {
+ inRow = true;
+ x = 0;
+ currentRow = createRowFromXml(res, parser);
+ skipRow = currentRow.mode != 0 && currentRow.mode != mKeyboardMode;
+ if (skipRow) {
+ skipToEndOfRow(parser);
+ inRow = false;
+ }
+ } else if (TAG_KEY.equals(tag)) {
+ inKey = true;
+ key = createKeyFromXml(res, currentRow, x, y, parser);
+ mKeys.add(key);
+ if (key.codes[0] == KEYCODE_SHIFT) {
+ mShiftKey = key;
+ mShiftKeyIndex = mKeys.size()-1;
+ mModifierKeys.add(key);
+ } else if (key.codes[0] == KEYCODE_ALT) {
+ mModifierKeys.add(key);
+ }
+ } else if (TAG_KEYBOARD.equals(tag)) {
+ parseKeyboardAttributes(res, parser);
+ }
+ } else if (event == XmlResourceParser.END_TAG) {
+ if (inKey) {
+ inKey = false;
+ x += key.gap + key.width;
+ if (x > mTotalWidth) {
+ mTotalWidth = x;
+ }
+ } else if (inRow) {
+ inRow = false;
+ y += currentRow.verticalGap;
+ y += currentRow.defaultHeight;
+ row++;
+ } else {
+ // TODO: error or extend?
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Parse error:" + e);
+ e.printStackTrace();
+ }
+ mTotalHeight = y - mDefaultVerticalGap;
+ }
+
+ private void skipToEndOfRow(XmlResourceParser parser)
+ throws XmlPullParserException, IOException {
+ int event;
+ while ((event = parser.next()) != XmlResourceParser.END_DOCUMENT) {
+ if (event == XmlResourceParser.END_TAG
+ && parser.getName().equals(TAG_ROW)) {
+ break;
+ }
+ }
+ }
+
+ private void parseKeyboardAttributes(Resources res, XmlResourceParser parser) {
+ TypedArray a = res.obtainAttributes(Xml.asAttributeSet(parser),
+ R.styleable.BaseKeyboard);
+
+ mDefaultWidth = getDimensionOrFraction(a,
+ R.styleable.BaseKeyboard_keyWidth,
+ mDisplayWidth, mDisplayWidth / 10);
+ mDefaultHeight = getDimensionOrFraction(a,
+ R.styleable.BaseKeyboard_keyHeight,
+ mDisplayHeight, 50);
+ mDefaultHorizontalGap = getDimensionOrFraction(a,
+ R.styleable.BaseKeyboard_horizontalGap,
+ mDisplayWidth, 0);
+ mDefaultVerticalGap = getDimensionOrFraction(a,
+ R.styleable.BaseKeyboard_verticalGap,
+ mDisplayHeight, 0);
+ mProximityThreshold = (int) (mDefaultWidth * SEARCH_DISTANCE);
+ mProximityThreshold = mProximityThreshold * mProximityThreshold;
+ a.recycle();
+ }
+
+ static int getDimensionOrFraction(TypedArray a, int index, int base, int defValue) {
+ TypedValue value = a.peekValue(index);
+ if (value == null) return defValue;
+ if (value.type == TypedValue.TYPE_DIMENSION) {
+ return a.getDimensionPixelOffset(index, defValue);
+ } else if (value.type == TypedValue.TYPE_FRACTION) {
+ // Round it to avoid values like 47.9999 from getting truncated
+ return Math.round(a.getFraction(index, base, base, defValue));
+ }
+ return defValue;
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/KeyDetector.java b/java/src/com/android/inputmethod/latin/KeyDetector.java
index 76fe1200e..3902b60a3 100644
--- a/java/src/com/android/inputmethod/latin/KeyDetector.java
+++ b/java/src/com/android/inputmethod/latin/KeyDetector.java
@@ -16,14 +16,13 @@
package com.android.inputmethod.latin;
-import android.inputmethodservice.Keyboard;
-import android.inputmethodservice.Keyboard.Key;
+import com.android.inputmethod.latin.BaseKeyboard.Key;
import java.util.Arrays;
import java.util.List;
abstract class KeyDetector {
- protected Keyboard mKeyboard;
+ protected BaseKeyboard mKeyboard;
private Key[] mKeys;
@@ -35,7 +34,7 @@ abstract class KeyDetector {
protected int mProximityThresholdSquare;
- public Key[] setKeyboard(Keyboard keyboard, float correctionX, float correctionY) {
+ public Key[] setKeyboard(BaseKeyboard keyboard, float correctionX, float correctionY) {
if (keyboard == null)
throw new NullPointerException();
mCorrectionX = (int)correctionX;
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 692183dbf..b41c2aa23 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -34,7 +34,6 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.inputmethodservice.InputMethodService;
-import android.inputmethodservice.Keyboard;
import android.media.AudioManager;
import android.os.Debug;
import android.os.Handler;
@@ -1170,29 +1169,29 @@ public class LatinIME extends InputMethodService
public void onKey(int primaryCode, int[] keyCodes, int x, int y) {
long when = SystemClock.uptimeMillis();
- if (primaryCode != Keyboard.KEYCODE_DELETE ||
+ if (primaryCode != BaseKeyboard.KEYCODE_DELETE ||
when > mLastKeyTime + QUICK_PRESS) {
mDeleteCount = 0;
}
mLastKeyTime = when;
final boolean distinctMultiTouch = mKeyboardSwitcher.hasDistinctMultitouch();
switch (primaryCode) {
- case Keyboard.KEYCODE_DELETE:
+ case BaseKeyboard.KEYCODE_DELETE:
handleBackspace();
mDeleteCount++;
LatinImeLogger.logOnDelete();
break;
- case Keyboard.KEYCODE_SHIFT:
+ case BaseKeyboard.KEYCODE_SHIFT:
// Shift key is handled in onPress() when device has distinct multi-touch panel.
if (!distinctMultiTouch)
handleShift();
break;
- case Keyboard.KEYCODE_MODE_CHANGE:
+ case BaseKeyboard.KEYCODE_MODE_CHANGE:
// Symbol key is handled in onPress() when device has distinct multi-touch panel.
if (!distinctMultiTouch)
changeKeyboardMode();
break;
- case Keyboard.KEYCODE_CANCEL:
+ case BaseKeyboard.KEYCODE_CANCEL:
if (!isShowingOptionDialog()) {
handleClose();
}
@@ -2266,10 +2265,10 @@ public class LatinIME extends InputMethodService
vibrate();
playKeyClick(primaryCode);
final boolean distinctMultiTouch = mKeyboardSwitcher.hasDistinctMultitouch();
- if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_SHIFT) {
+ if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_SHIFT) {
mShiftKeyState.onPress();
handleShift();
- } else if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
+ } else if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE) {
mSymbolKeyState.onPress();
changeKeyboardMode();
} else {
@@ -2283,11 +2282,11 @@ public class LatinIME extends InputMethodService
((LatinKeyboard) mKeyboardSwitcher.getInputView().getKeyboard()).keyReleased();
//vibrate();
final boolean distinctMultiTouch = mKeyboardSwitcher.hasDistinctMultitouch();
- if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_SHIFT) {
+ if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_SHIFT) {
if (mShiftKeyState.isMomentary())
resetShift();
mShiftKeyState.onRelease();
- } else if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_MODE_CHANGE) {
+ } else if (distinctMultiTouch && primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE) {
if (mSymbolKeyState.isMomentary())
changeKeyboardMode();
mSymbolKeyState.onRelease();
@@ -2346,7 +2345,7 @@ public class LatinIME extends InputMethodService
// FIXME: These should be triggered after auto-repeat logic
int sound = AudioManager.FX_KEYPRESS_STANDARD;
switch (primaryCode) {
- case Keyboard.KEYCODE_DELETE:
+ case BaseKeyboard.KEYCODE_DELETE:
sound = AudioManager.FX_KEYPRESS_DELETE;
break;
case KEYCODE_ENTER:
diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
index a8ab9cc98..dd7bc8ac1 100644
--- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java
+++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
@@ -20,7 +20,6 @@ import com.android.inputmethod.latin.Dictionary.DataType;
import android.content.Context;
import android.content.SharedPreferences;
-import android.inputmethodservice.Keyboard;
import java.util.List;
public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChangeListener {
@@ -65,7 +64,7 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang
public static void onAddSuggestedWord(String word, int typeId, DataType dataType) {
}
- public static void onSetKeyboard(Keyboard kb) {
+ public static void onSetKeyboard(BaseKeyboard kb) {
}
}
diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboard.java b/java/src/com/android/inputmethod/latin/LatinKeyboard.java
index 31394d1cc..9c252e6c6 100644
--- a/java/src/com/android/inputmethod/latin/LatinKeyboard.java
+++ b/java/src/com/android/inputmethod/latin/LatinKeyboard.java
@@ -30,7 +30,6 @@ import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
-import android.inputmethodservice.Keyboard;
import android.text.TextPaint;
import android.util.Log;
import android.view.ViewConfiguration;
@@ -41,7 +40,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
-public class LatinKeyboard extends Keyboard {
+public class LatinKeyboard extends BaseKeyboard {
private static final boolean DEBUG_PREFERRED_LETTER = false;
private static final String TAG = "LatinKeyboard";
@@ -744,7 +743,7 @@ public class LatinKeyboard extends Keyboard {
return textSize;
}
- class LatinKey extends Keyboard.Key {
+ class LatinKey extends BaseKeyboard.Key {
// functional normal state (with properties)
private final int[] KEY_STATE_FUNCTIONAL_NORMAL = {
@@ -759,7 +758,7 @@ public class LatinKeyboard extends Keyboard {
private boolean mShiftLockEnabled;
- public LatinKey(Resources res, Keyboard.Row parent, int x, int y,
+ public LatinKey(Resources res, BaseKeyboard.Row parent, int x, int y,
XmlResourceParser parser) {
super(res, parent, x, y, parser);
if (popupCharacters != null && popupCharacters.length() == 0) {
diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java
index 75ef691c8..264e2f18f 100644
--- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java
+++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java
@@ -16,6 +16,8 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.latin.BaseKeyboard.Key;
+
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
@@ -29,8 +31,6 @@ import android.graphics.Rect;
import android.graphics.Region.Op;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
-import android.inputmethodservice.Keyboard;
-import android.inputmethodservice.Keyboard.Key;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
@@ -177,7 +177,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
private int mPopupLayout;
// Main keyboard
- private Keyboard mKeyboard;
+ private BaseKeyboard mKeyboard;
private Key[] mKeys;
// Key preview popup
@@ -566,7 +566,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
* @see #getKeyboard()
* @param keyboard the keyboard to display in this view
*/
- public void setKeyboard(Keyboard keyboard) {
+ public void setKeyboard(BaseKeyboard keyboard) {
if (mKeyboard != null) {
dismissKeyPreview();
}
@@ -593,7 +593,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
* @return the currently attached keyboard
* @see #setKeyboard(Keyboard)
*/
- public Keyboard getKeyboard() {
+ public BaseKeyboard getKeyboard() {
return mKeyboard;
}
@@ -713,7 +713,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
* the touch distance from a key's center to avoid taking a square root.
* @param keyboard
*/
- private void computeProximityThreshold(Keyboard keyboard) {
+ private void computeProximityThreshold(BaseKeyboard keyboard) {
if (keyboard == null) return;
final Key[] keys = mKeys;
if (keys == null) return;
@@ -1072,12 +1072,12 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
// Override default ProximityKeyDetector.
miniKeyboard.mKeyDetector = new MiniKeyboardKeyDetector(mMiniKeyboardSlideAllowance);
- Keyboard keyboard;
+ BaseKeyboard keyboard;
if (popupKey.popupCharacters != null) {
- keyboard = new Keyboard(getContext(), popupKeyboardId, popupKey.popupCharacters,
+ keyboard = new BaseKeyboard(getContext(), popupKeyboardId, popupKey.popupCharacters,
-1, getPaddingLeft() + getPaddingRight());
} else {
- keyboard = new Keyboard(getContext(), popupKeyboardId);
+ keyboard = new BaseKeyboard(getContext(), popupKeyboardId);
}
miniKeyboard.setKeyboard(keyboard);
miniKeyboard.setPopupParent(this);
@@ -1088,7 +1088,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
return container;
}
- private static boolean isOneRowKeyboard(Keyboard keyboard) {
+ private static boolean isOneRowKeyboard(BaseKeyboard keyboard) {
final List<Key> keys = keyboard.getKeys();
if (keys.size() == 0) return false;
final int edgeFlags = keys.get(0).edgeFlags;
@@ -1098,7 +1098,8 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx
// and bottom edge flags on.
// When you want to use one row mini-keyboard from xml file, make sure that the row has
// both top and bottom edge flags set.
- return (edgeFlags & Keyboard.EDGE_TOP) != 0 && (edgeFlags & Keyboard.EDGE_BOTTOM) != 0;
+ return (edgeFlags & BaseKeyboard.EDGE_TOP) != 0
+ && (edgeFlags & BaseKeyboard.EDGE_BOTTOM) != 0;
}
/**
diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java
index 22d39f7aa..912af7e2a 100644
--- a/java/src/com/android/inputmethod/latin/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/latin/LatinKeyboardView.java
@@ -16,11 +16,11 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.latin.BaseKeyboard.Key;
+
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
-import android.inputmethodservice.Keyboard;
-import android.inputmethodservice.Keyboard.Key;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
@@ -39,7 +39,7 @@ public class LatinKeyboardView extends LatinKeyboardBaseView {
static final int KEYCODE_NEXT_LANGUAGE = -104;
static final int KEYCODE_PREV_LANGUAGE = -105;
- private Keyboard mPhoneKeyboard;
+ private BaseKeyboard mPhoneKeyboard;
/** Whether we've started dropping move events because we found a big jump */
private boolean mDroppingEvents;
@@ -61,7 +61,7 @@ public class LatinKeyboardView extends LatinKeyboardBaseView {
super(context, attrs, defStyle);
}
- public void setPhoneKeyboard(Keyboard phoneKeyboard) {
+ public void setPhoneKeyboard(BaseKeyboard phoneKeyboard) {
mPhoneKeyboard = phoneKeyboard;
}
@@ -76,7 +76,7 @@ public class LatinKeyboardView extends LatinKeyboardBaseView {
}
@Override
- public void setKeyboard(Keyboard k) {
+ public void setKeyboard(BaseKeyboard k) {
super.setKeyboard(k);
// One-seventh of the keyboard width seems like a reasonable threshold
mJumpThresholdSquare = k.getMinWidth() / 7;
@@ -108,7 +108,7 @@ public class LatinKeyboardView extends LatinKeyboardBaseView {
@Override
protected CharSequence adjustCase(CharSequence label) {
- Keyboard keyboard = getKeyboard();
+ BaseKeyboard keyboard = getKeyboard();
if (keyboard.isShifted()
&& keyboard instanceof LatinKeyboard
&& ((LatinKeyboard) keyboard).isAlphaKeyboard()
@@ -120,7 +120,7 @@ public class LatinKeyboardView extends LatinKeyboardBaseView {
}
public boolean setShiftLocked(boolean shiftLocked) {
- Keyboard keyboard = getKeyboard();
+ BaseKeyboard keyboard = getKeyboard();
if (keyboard instanceof LatinKeyboard) {
((LatinKeyboard)keyboard).setShiftLocked(shiftLocked);
invalidateAllKeys();
@@ -257,7 +257,7 @@ public class LatinKeyboardView extends LatinKeyboardBaseView {
private int mLastY;
private Paint mPaint;
- private void setKeyboardLocal(Keyboard k) {
+ private void setKeyboardLocal(BaseKeyboard k) {
if (DEBUG_AUTO_PLAY) {
findKeys();
if (mHandler2 == null) {
diff --git a/java/src/com/android/inputmethod/latin/MiniKeyboardKeyDetector.java b/java/src/com/android/inputmethod/latin/MiniKeyboardKeyDetector.java
index 356e62d48..5f4c93734 100644
--- a/java/src/com/android/inputmethod/latin/MiniKeyboardKeyDetector.java
+++ b/java/src/com/android/inputmethod/latin/MiniKeyboardKeyDetector.java
@@ -16,7 +16,7 @@
package com.android.inputmethod.latin;
-import android.inputmethodservice.Keyboard.Key;
+import com.android.inputmethod.latin.BaseKeyboard.Key;
class MiniKeyboardKeyDetector extends KeyDetector {
private static final int MAX_NEARBY_KEYS = 1;
diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java
index b416a984c..cf4f7d5c2 100644
--- a/java/src/com/android/inputmethod/latin/PointerTracker.java
+++ b/java/src/com/android/inputmethod/latin/PointerTracker.java
@@ -16,11 +16,10 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.latin.BaseKeyboard.Key;
import com.android.inputmethod.latin.LatinKeyboardBaseView.OnKeyboardActionListener;
import com.android.inputmethod.latin.LatinKeyboardBaseView.UIHandler;
-import android.inputmethodservice.Keyboard;
-import android.inputmethodservice.Keyboard.Key;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
@@ -45,7 +44,7 @@ public class PointerTracker {
// Miscellaneous constants
private static final int NOT_A_KEY = LatinKeyboardBaseView.NOT_A_KEY;
- private static final int[] KEY_DELETE = { Keyboard.KEYCODE_DELETE };
+ private static final int[] KEY_DELETE = { BaseKeyboard.KEYCODE_DELETE };
private final UIProxy mProxy;
private final UIHandler mHandler;
@@ -202,8 +201,8 @@ public class PointerTracker {
if (key == null)
return false;
int primaryCode = key.codes[0];
- return primaryCode == Keyboard.KEYCODE_SHIFT
- || primaryCode == Keyboard.KEYCODE_MODE_CHANGE;
+ return primaryCode == BaseKeyboard.KEYCODE_SHIFT
+ || primaryCode == BaseKeyboard.KEYCODE_MODE_CHANGE;
}
public boolean isModifier() {
@@ -437,7 +436,7 @@ public class PointerTracker {
// Multi-tap
if (mInMultiTap) {
if (mTapCount != -1) {
- mListener.onKey(Keyboard.KEYCODE_DELETE, KEY_DELETE, x, y);
+ mListener.onKey(BaseKeyboard.KEYCODE_DELETE, KEY_DELETE, x, y);
} else {
mTapCount = 0;
}
diff --git a/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java b/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java
index d17bedb56..a6ff8cf8c 100644
--- a/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java
+++ b/java/src/com/android/inputmethod/latin/ProximityKeyDetector.java
@@ -16,7 +16,7 @@
package com.android.inputmethod.latin;
-import android.inputmethodservice.Keyboard.Key;
+import com.android.inputmethod.latin.BaseKeyboard.Key;
import java.util.Arrays;
diff --git a/java/src/com/android/inputmethod/latin/TextEntryState.java b/java/src/com/android/inputmethod/latin/TextEntryState.java
index 9011191f1..1d7659ca3 100644
--- a/java/src/com/android/inputmethod/latin/TextEntryState.java
+++ b/java/src/com/android/inputmethod/latin/TextEntryState.java
@@ -16,8 +16,9 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.latin.BaseKeyboard.Key;
+
import android.content.Context;
-import android.inputmethodservice.Keyboard.Key;
import android.text.format.DateFormat;
import android.util.Log;