summaryrefslogtreecommitdiffstats
path: root/core/java/android/inputmethodservice
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-02-19 10:57:31 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-02-19 10:57:31 -0800
commit3001a035439d8134a7d70d796376d1dfbff3cdcd (patch)
tree343ccdba15a594ff6e50c874a145232753315a30 /core/java/android/inputmethodservice
parentda996f390e17e16f2dfa60e972e7ebc4f868f37e (diff)
downloadframeworks_base-3001a035439d8134a7d70d796376d1dfbff3cdcd.zip
frameworks_base-3001a035439d8134a7d70d796376d1dfbff3cdcd.tar.gz
frameworks_base-3001a035439d8134a7d70d796376d1dfbff3cdcd.tar.bz2
auto import from //branches/cupcake/...@132276
Diffstat (limited to 'core/java/android/inputmethodservice')
-rw-r--r--core/java/android/inputmethodservice/ExtractEditText.java7
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java76
-rwxr-xr-xcore/java/android/inputmethodservice/Keyboard.java60
-rwxr-xr-xcore/java/android/inputmethodservice/KeyboardView.java149
4 files changed, 194 insertions, 98 deletions
diff --git a/core/java/android/inputmethodservice/ExtractEditText.java b/core/java/android/inputmethodservice/ExtractEditText.java
index d9f10a9..52f8209 100644
--- a/core/java/android/inputmethodservice/ExtractEditText.java
+++ b/core/java/android/inputmethodservice/ExtractEditText.java
@@ -102,7 +102,7 @@ public class ExtractEditText extends EditText {
* highlight and cursor will be displayed.
*/
@Override public boolean hasWindowFocus() {
- return true;
+ return this.isEnabled() ? true : false;
}
/**
@@ -110,7 +110,7 @@ public class ExtractEditText extends EditText {
* highlight and cursor will be displayed.
*/
@Override public boolean isFocused() {
- return true;
+ return this.isEnabled() ? true : false;
}
/**
@@ -118,7 +118,6 @@ public class ExtractEditText extends EditText {
* highlight and cursor will be displayed.
*/
@Override public boolean hasFocus() {
- return true;
+ return this.isEnabled() ? true : false;
}
-
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index c884120..4be1fc7 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -229,9 +229,11 @@ public class InputMethodService extends AbstractInputMethodService {
InputConnection mStartedInputConnection;
EditorInfo mInputEditorInfo;
+ int mShowInputFlags;
boolean mShowInputRequested;
boolean mLastShowInputRequested;
int mCandidatesVisibility;
+ CompletionInfo[] mCurCompletions;
boolean mShowInputForced;
@@ -328,6 +330,7 @@ public class InputMethodService extends AbstractInputMethodService {
*/
public void hideSoftInput() {
if (DEBUG) Log.v(TAG, "hideSoftInput()");
+ mShowInputFlags = 0;
mShowInputRequested = false;
mShowInputForced = false;
hideWindow();
@@ -338,7 +341,10 @@ public class InputMethodService extends AbstractInputMethodService {
*/
public void showSoftInput(int flags) {
if (DEBUG) Log.v(TAG, "showSoftInput()");
- onShowRequested(flags);
+ mShowInputFlags = 0;
+ if (onShowInputRequested(flags, false)) {
+ showWindow(true);
+ }
}
}
@@ -364,6 +370,7 @@ public class InputMethodService extends AbstractInputMethodService {
if (!isEnabled()) {
return;
}
+ mCurCompletions = completions;
onDisplayCompletions(completions);
}
@@ -557,8 +564,9 @@ public class InputMethodService extends AbstractInputMethodService {
super.onConfigurationChanged(newConfig);
boolean visible = mWindowVisible;
+ int showFlags = mShowInputFlags;
boolean showingInput = mShowInputRequested;
- boolean showingForced = mShowInputForced;
+ CompletionInfo[] completions = mCurCompletions;
initViews();
mInputViewStarted = false;
mCandidatesViewStarted = false;
@@ -567,19 +575,24 @@ public class InputMethodService extends AbstractInputMethodService {
getCurrentInputEditorInfo(), true);
}
if (visible) {
- if (showingForced) {
- // If we are showing the full soft keyboard, then go through
- // this path to take care of current decisions about fullscreen
- // etc.
- onShowRequested(InputMethod.SHOW_FORCED|InputMethod.SHOW_EXPLICIT);
- } else if (showingInput) {
- // If we are showing the full soft keyboard, then go through
- // this path to take care of current decisions about fullscreen
- // etc.
- onShowRequested(InputMethod.SHOW_EXPLICIT);
- } else {
- // Otherwise just put it back for its candidates.
+ if (showingInput) {
+ // If we were last showing the soft keyboard, try to do so again.
+ if (onShowInputRequested(showFlags, true)) {
+ showWindow(true);
+ if (completions != null) {
+ mCurCompletions = completions;
+ onDisplayCompletions(completions);
+ }
+ } else {
+ hideWindow();
+ }
+ } else if (mCandidatesVisibility == View.VISIBLE) {
+ // If the candidates are currently visible, make sure the
+ // window is shown for them.
showWindow(false);
+ } else {
+ // Otherwise hide the window.
+ hideWindow();
}
}
}
@@ -1065,36 +1078,42 @@ public class InputMethodService extends AbstractInputMethodService {
* The system has decided that it may be time to show your input method.
* This is called due to a corresponding call to your
* {@link InputMethod#showSoftInput(int) InputMethod.showSoftInput(int)}
- * method. The default implementation simply calls
- * {@link #showWindow(boolean)}, except if the
- * {@link InputMethod#SHOW_EXPLICIT InputMethod.SHOW_EXPLICIT} flag is
- * not set and the input method is running in fullscreen mode.
+ * method. The default implementation uses
+ * {@link #onEvaluateInputViewShown()}, {@link #onEvaluateFullscreenMode()},
+ * and the current configuration to decide whether the input view should
+ * be shown at this point.
*
* @param flags Provides additional information about the show request,
* as per {@link InputMethod#showSoftInput(int) InputMethod.showSoftInput(int)}.
+ * @param configChange This is true if we are re-showing due to a
+ * configuration change.
+ * @return Returns true to indicate that the window should be shown.
*/
- public void onShowRequested(int flags) {
+ public boolean onShowInputRequested(int flags, boolean configChange) {
if (!onEvaluateInputViewShown()) {
- return;
+ return false;
}
if ((flags&InputMethod.SHOW_EXPLICIT) == 0) {
- if (onEvaluateFullscreenMode()) {
+ if (!configChange && onEvaluateFullscreenMode()) {
// Don't show if this is not explicitly requested by the user and
// the input method is fullscreen. That would be too disruptive.
- return;
+ // However, we skip this change for a config change, since if
+ // the IME is already shown we do want to go into fullscreen
+ // mode at this point.
+ return false;
}
Configuration config = getResources().getConfiguration();
if (config.keyboard != Configuration.KEYBOARD_NOKEYS) {
// And if the device has a hard keyboard, even if it is
// currently hidden, don't show the input method implicitly.
// These kinds of devices don't need it that much.
- return;
+ return false;
}
}
if ((flags&InputMethod.SHOW_FORCED) != 0) {
mShowInputForced = true;
}
- showWindow(true);
+ return true;
}
public void showWindow(boolean showInput) {
@@ -1106,7 +1125,6 @@ public class InputMethodService extends AbstractInputMethodService {
+ " mInputStarted=" + mInputStarted);
boolean doShowInput = false;
boolean wasVisible = mWindowVisible;
- boolean wasCreated = mWindowCreated;
mWindowVisible = true;
if (!mShowInputRequested) {
if (mInputStarted) {
@@ -1240,6 +1258,7 @@ public class InputMethodService extends AbstractInputMethodService {
}
mInputStarted = false;
mStartedInputConnection = null;
+ mCurCompletions = null;
}
void doStartInput(InputConnection ic, EditorInfo attribute, boolean restarting) {
@@ -1550,7 +1569,11 @@ public class InputMethodService extends AbstractInputMethodService {
eet.setInputType(inputType);
eet.setHint(mInputEditorInfo.hintText);
if (mExtractedText != null) {
+ eet.setEnabled(true);
eet.setExtractedText(mExtractedText);
+ } else {
+ eet.setEnabled(false);
+ eet.setText("");
}
} finally {
eet.finishInternalChanges();
@@ -1586,7 +1609,8 @@ public class InputMethodService extends AbstractInputMethodService {
p.println(" mShowInputRequested=" + mShowInputRequested
+ " mLastShowInputRequested=" + mLastShowInputRequested
- + " mShowInputForced=" + mShowInputForced);
+ + " mShowInputForced=" + mShowInputForced
+ + " mShowInputFlags=0x" + Integer.toHexString(mShowInputFlags));
p.println(" mCandidatesVisibility=" + mCandidatesVisibility
+ " mFullscreenApplied=" + mFullscreenApplied
+ " mIsFullscreen=" + mIsFullscreen);
diff --git a/core/java/android/inputmethodservice/Keyboard.java b/core/java/android/inputmethodservice/Keyboard.java
index 228acbe..6a560ce 100755
--- a/core/java/android/inputmethodservice/Keyboard.java
+++ b/core/java/android/inputmethodservice/Keyboard.java
@@ -132,7 +132,19 @@ public class Keyboard {
/** 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.4f;
+
/**
* 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}
@@ -637,6 +649,52 @@ public class Keyboard {
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);
@@ -738,6 +796,8 @@ public class Keyboard {
mDefaultVerticalGap = getDimensionOrFraction(a,
com.android.internal.R.styleable.Keyboard_verticalGap,
mDisplayHeight, 0);
+ mProximityThreshold = (int) (mDefaultWidth * SEARCH_DISTANCE);
+ mProximityThreshold = mProximityThreshold * mProximityThreshold; // Square it for comparison
a.recycle();
}
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index b8bd10d..886e688 100755
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -159,6 +159,9 @@ public class KeyboardView extends View implements View.OnClickListener {
private static final int MSG_REPEAT = 3;
private static final int MSG_LONGPRESS = 4;
+ private static final int DELAY_BEFORE_PREVIEW = 70;
+ private static final int DELAY_AFTER_PREVIEW = 60;
+
private int mVerticalCorrection;
private int mProximityThreshold;
@@ -219,7 +222,7 @@ public class KeyboardView extends View implements View.OnClickListener {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SHOW_PREVIEW:
- mPreviewText.setVisibility(VISIBLE);
+ showKey(msg.arg1);
break;
case MSG_REMOVE_PREVIEW:
mPreviewText.setVisibility(INVISIBLE);
@@ -234,7 +237,6 @@ public class KeyboardView extends View implements View.OnClickListener {
openPopupIfRequired((MotionEvent) msg.obj);
break;
}
-
}
};
@@ -533,10 +535,10 @@ public class KeyboardView extends View implements View.OnClickListener {
dimensionSum += Math.min(key.width, key.height) + key.gap;
}
if (dimensionSum < 0 || length == 0) return;
- mProximityThreshold = (int) (dimensionSum * 1.5f / length);
+ mProximityThreshold = (int) (dimensionSum * 1.4f / length);
mProximityThreshold *= mProximityThreshold; // Square it
}
-
+
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
@@ -647,9 +649,10 @@ public class KeyboardView extends View implements View.OnClickListener {
int closestKey = NOT_A_KEY;
int closestKeyDist = mProximityThreshold + 1;
java.util.Arrays.fill(mDistances, Integer.MAX_VALUE);
- final int keyCount = keys.length;
+ int [] nearestKeyIndices = mKeyboard.getNearestKeys(x, y);
+ final int keyCount = nearestKeyIndices.length;
for (int i = 0; i < keyCount; i++) {
- final Key key = keys[i];
+ final Key key = keys[nearestKeyIndices[i]];
int dist = 0;
boolean isInside = key.isInside(x,y);
if (((mProximityCorrectOn
@@ -660,7 +663,7 @@ public class KeyboardView extends View implements View.OnClickListener {
final int nCodes = key.codes.length;
if (dist < closestKeyDist) {
closestKeyDist = dist;
- closestKey = i;
+ closestKey = nearestKeyIndices[i];
}
if (allKeys == null) continue;
@@ -674,9 +677,6 @@ public class KeyboardView extends View implements View.OnClickListener {
allKeys.length - j - nCodes);
for (int c = 0; c < nCodes; c++) {
allKeys[j + c] = key.codes[c];
- if (shifted) {
- //allKeys[j + c] = Character.toUpperCase(key.codes[c]);
- }
mDistances[j + c] = dist;
}
break;
@@ -685,7 +685,7 @@ public class KeyboardView extends View implements View.OnClickListener {
}
if (isInside) {
- primaryIndex = i;
+ primaryIndex = nearestKeyIndices[i];
}
}
if (primaryIndex == NOT_A_KEY) {
@@ -696,7 +696,7 @@ public class KeyboardView extends View implements View.OnClickListener {
private void detectAndSendKey(int x, int y, long eventTime) {
int index = mCurrentKey;
- if (index != NOT_A_KEY) {
+ if (index != NOT_A_KEY && index < mKeys.length) {
final Key key = mKeys[index];
if (key.text != null) {
for (int i = 0; i < key.text.length(); i++) {
@@ -763,70 +763,83 @@ public class KeyboardView extends View implements View.OnClickListener {
if (previewPopup.isShowing()) {
if (keyIndex == NOT_A_KEY) {
mHandler.sendMessageDelayed(mHandler
- .obtainMessage(MSG_REMOVE_PREVIEW), 60);
+ .obtainMessage(MSG_REMOVE_PREVIEW),
+ DELAY_AFTER_PREVIEW);
}
}
if (keyIndex != NOT_A_KEY) {
- Key key = keys[keyIndex];
- if (key.icon != null) {
- mPreviewText.setCompoundDrawables(null, null, null,
- key.iconPreview != null ? key.iconPreview : key.icon);
- mPreviewText.setText(null);
- } else {
- mPreviewText.setCompoundDrawables(null, null, null, null);
- mPreviewText.setText(getPreviewText(key));
- if (key.label.length() > 1 && key.codes.length < 2) {
- mPreviewText.setTextSize(mLabelTextSize);
- mPreviewText.setTypeface(Typeface.DEFAULT_BOLD);
- } else {
- mPreviewText.setTextSize(mPreviewTextSizeLarge);
- mPreviewText.setTypeface(Typeface.DEFAULT);
- }
- }
- mPreviewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
- MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
- int popupWidth = Math.max(mPreviewText.getMeasuredWidth(), key.width
- + mPreviewText.getPaddingLeft() + mPreviewText.getPaddingRight());
- final int popupHeight = mPreviewHeight;
- LayoutParams lp = mPreviewText.getLayoutParams();
- if (lp != null) {
- lp.width = popupWidth;
- lp.height = popupHeight;
- }
- if (!mPreviewCentered) {
- mPopupPreviewX = key.x - mPreviewText.getPaddingLeft() + mPaddingLeft;
- mPopupPreviewY = key.y - popupHeight + mPreviewOffset;
- } else {
- // TODO: Fix this if centering is brought back
- mPopupPreviewX = 160 - mPreviewText.getMeasuredWidth() / 2;
- mPopupPreviewY = - mPreviewText.getMeasuredHeight();
- }
- mHandler.removeMessages(MSG_REMOVE_PREVIEW);
- if (mOffsetInWindow == null) {
- mOffsetInWindow = new int[2];
- getLocationInWindow(mOffsetInWindow);
- mOffsetInWindow[0] += mMiniKeyboardOffsetX; // Offset may be zero
- mOffsetInWindow[1] += mMiniKeyboardOffsetY; // Offset may be zero
- }
- // Set the preview background state
- mPreviewText.getBackground().setState(
- key.popupResId != 0 ? LONG_PRESSABLE_STATE_SET : EMPTY_STATE_SET);
- if (previewPopup.isShowing()) {
- previewPopup.update(mPopupPreviewX + mOffsetInWindow[0],
- mPopupPreviewY + mOffsetInWindow[1],
- popupWidth, popupHeight);
+ if (previewPopup.isShowing() && mPreviewText.getVisibility() == VISIBLE) {
+ // Show right away, if it's already visible and finger is moving around
+ showKey(keyIndex);
} else {
- previewPopup.setWidth(popupWidth);
- previewPopup.setHeight(popupHeight);
- previewPopup.showAtLocation(mPopupParent, Gravity.NO_GRAVITY,
- mPopupPreviewX + mOffsetInWindow[0],
- mPopupPreviewY + mOffsetInWindow[1]);
+ mHandler.sendMessageDelayed(
+ mHandler.obtainMessage(MSG_SHOW_PREVIEW, keyIndex, 0),
+ DELAY_BEFORE_PREVIEW);
}
- mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SHOW_PREVIEW, keyIndex, 0),
- ViewConfiguration.getTapTimeout());
}
}
}
+
+ private void showKey(final int keyIndex) {
+ final PopupWindow previewPopup = mPreviewPopup;
+ final Key[] keys = mKeys;
+ Key key = keys[keyIndex];
+ if (key.icon != null) {
+ mPreviewText.setCompoundDrawables(null, null, null,
+ key.iconPreview != null ? key.iconPreview : key.icon);
+ mPreviewText.setText(null);
+ } else {
+ mPreviewText.setCompoundDrawables(null, null, null, null);
+ mPreviewText.setText(getPreviewText(key));
+ if (key.label.length() > 1 && key.codes.length < 2) {
+ mPreviewText.setTextSize(mLabelTextSize);
+ mPreviewText.setTypeface(Typeface.DEFAULT_BOLD);
+ } else {
+ mPreviewText.setTextSize(mPreviewTextSizeLarge);
+ mPreviewText.setTypeface(Typeface.DEFAULT);
+ }
+ }
+ mPreviewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
+ MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+ int popupWidth = Math.max(mPreviewText.getMeasuredWidth(), key.width
+ + mPreviewText.getPaddingLeft() + mPreviewText.getPaddingRight());
+ final int popupHeight = mPreviewHeight;
+ LayoutParams lp = mPreviewText.getLayoutParams();
+ if (lp != null) {
+ lp.width = popupWidth;
+ lp.height = popupHeight;
+ }
+ if (!mPreviewCentered) {
+ mPopupPreviewX = key.x - mPreviewText.getPaddingLeft() + mPaddingLeft;
+ mPopupPreviewY = key.y - popupHeight + mPreviewOffset;
+ } else {
+ // TODO: Fix this if centering is brought back
+ mPopupPreviewX = 160 - mPreviewText.getMeasuredWidth() / 2;
+ mPopupPreviewY = - mPreviewText.getMeasuredHeight();
+ }
+ mHandler.removeMessages(MSG_REMOVE_PREVIEW);
+ if (mOffsetInWindow == null) {
+ mOffsetInWindow = new int[2];
+ getLocationInWindow(mOffsetInWindow);
+ mOffsetInWindow[0] += mMiniKeyboardOffsetX; // Offset may be zero
+ mOffsetInWindow[1] += mMiniKeyboardOffsetY; // Offset may be zero
+ }
+ // Set the preview background state
+ mPreviewText.getBackground().setState(
+ key.popupResId != 0 ? LONG_PRESSABLE_STATE_SET : EMPTY_STATE_SET);
+ if (previewPopup.isShowing()) {
+ previewPopup.update(mPopupPreviewX + mOffsetInWindow[0],
+ mPopupPreviewY + mOffsetInWindow[1],
+ popupWidth, popupHeight);
+ } else {
+ previewPopup.setWidth(popupWidth);
+ previewPopup.setHeight(popupHeight);
+ previewPopup.showAtLocation(mPopupParent, Gravity.NO_GRAVITY,
+ mPopupPreviewX + mOffsetInWindow[0],
+ mPopupPreviewY + mOffsetInWindow[1]);
+ }
+ mPreviewText.setVisibility(VISIBLE);
+ }
private void invalidateKey(int keyIndex) {
if (keyIndex < 0 || keyIndex >= mKeys.length) {