From 6f0a60d10de056cbb89cf7984c9f8f64bb95db9d Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Mon, 3 Dec 2012 14:42:26 +0900 Subject: Cancel gesture preview update when gesture typing is canceled Bug: 7594165 Change-Id: I2854a49b2a2e5d3e36cafc5196191359fd2bf003 --- java/src/com/android/inputmethod/keyboard/PointerTracker.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'java/src') diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index c3cf49f3b..73eab76f3 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -721,6 +721,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element { if (key != null) { updateBatchInput(eventTime); } + if (mIsTrackingCanceled) { + return; + } mDrawingProxy.showGesturePreviewTrail(this, isOldestTrackerInQueue(this)); } @@ -759,6 +762,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } } } + if (mIsTrackingCanceled) { + return; + } mDrawingProxy.showGesturePreviewTrail(this, isOldestTrackerInQueue(this)); } -- cgit v1.2.3-83-g751a From 547b638194c05f971003edb06c3c6c489a76da5f Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Wed, 28 Nov 2012 15:24:13 +0900 Subject: Groundwork for sliding key input preview Bug: 7548583 Change-Id: Id807af31f581c08ff8074ed1f6766337bea9469f --- .../android/inputmethod/keyboard/KeyboardView.java | 22 ++++---- .../inputmethod/keyboard/MainKeyboardView.java | 18 ++++--- .../inputmethod/keyboard/PointerTracker.java | 25 ++++++--- .../keyboard/internal/PreviewPlacerView.java | 59 +++++++++++++++------- .../android/inputmethod/latin/CoordinateUtils.java | 10 ++++ 5 files changed, 93 insertions(+), 41 deletions(-) (limited to 'java/src') diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index d7cb5aa92..51fb3701c 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -135,7 +135,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { // Preview placer view private final PreviewPlacerView mPreviewPlacerView; - private final int[] mCoordinates = CoordinateUtils.newInstance(); + private final int[] mOriginCoords = CoordinateUtils.newInstance(); // Key preview private static final int PREVIEW_ALPHA = 240; @@ -833,10 +833,9 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { // In transient state. return; } - final int[] viewOrigin = CoordinateUtils.newInstance(); - getLocationInWindow(viewOrigin); + getLocationInWindow(mOriginCoords); final DisplayMetrics dm = getResources().getDisplayMetrics(); - if (CoordinateUtils.y(viewOrigin) < dm.heightPixels / 4) { + if (CoordinateUtils.y(mOriginCoords) < dm.heightPixels / 4) { // In transient state. return; } @@ -851,11 +850,16 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { Log.w(TAG, "Cannot find android.R.id.content view to add PreviewPlacerView"); } else { windowContentView.addView(mPreviewPlacerView); - mPreviewPlacerView.setKeyboardViewGeometry( - CoordinateUtils.x(viewOrigin), CoordinateUtils.y(viewOrigin), width, height); + mPreviewPlacerView.setKeyboardViewGeometry(mOriginCoords, width, height); } } + @Override + public void showSlidingKeyInputPreview(final PointerTracker tracker) { + locatePreviewPlacerView(); + mPreviewPlacerView.showSlidingKeyInputPreview(tracker); + } + public void showGestureFloatingPreviewText(final String gestureFloatingPreviewText) { locatePreviewPlacerView(); mPreviewPlacerView.setGestureFloatingPreviewText(gestureFloatingPreviewText); @@ -937,13 +941,13 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { // The distance between the top edge of the parent key and the bottom of the visible part // of the key preview background. previewParams.mPreviewVisibleOffset = mPreviewOffset - previewText.getPaddingBottom(); - getLocationInWindow(mCoordinates); + getLocationInWindow(mOriginCoords); // The key preview is horizontally aligned with the center of the visible part of the // parent key. If it doesn't fit in this {@link KeyboardView}, it is moved inward to fit and // the left/right background is used if such background is specified. final int statePosition; int previewX = key.getDrawX() - (previewWidth - keyDrawWidth) / 2 - + CoordinateUtils.x(mCoordinates); + + CoordinateUtils.x(mOriginCoords); if (previewX < 0) { previewX = 0; statePosition = STATE_LEFT; @@ -956,7 +960,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { // The key preview is placed vertically above the top edge of the parent key with an // arbitrary offset. final int previewY = key.mY - previewHeight + mPreviewOffset - + CoordinateUtils.y(mCoordinates); + + CoordinateUtils.y(mOriginCoords); if (background != null) { final int hasMoreKeys = (key.mMoreKeys != null) ? STATE_HAS_MOREKEYS : STATE_NORMAL; diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java index 7e9e3ce1a..b9ce4fb1f 100644 --- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java @@ -49,6 +49,7 @@ import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; import com.android.inputmethod.keyboard.internal.KeyDrawParams; import com.android.inputmethod.keyboard.internal.TouchScreenRegulator; import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.CoordinateUtils; import com.android.inputmethod.latin.DebugSettings; import com.android.inputmethod.latin.LatinIME; import com.android.inputmethod.latin.LatinImeLogger; @@ -672,12 +673,14 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack mMoreKeysPanel = moreKeysPanel; mMoreKeysPanelPointerTrackerId = tracker.mPointerId; + final int[] lastCoords = CoordinateUtils.newInstance(); + tracker.getLastCoordinates(lastCoords); final boolean keyPreviewEnabled = isKeyPreviewPopupEnabled() && !parentKey.noKeyPreview(); // The more keys keyboard is usually horizontally aligned with the center of the parent key. // If showMoreKeysKeyboardAtTouchedPoint is true and the key preview is disabled, the more // keys keyboard is placed at the touch point of the parent key. final int pointX = (mConfigShowMoreKeysKeyboardAtTouchedPoint && !keyPreviewEnabled) - ? tracker.getLastX() + ? CoordinateUtils.x(lastCoords) : parentKey.mX + parentKey.mWidth / 2; // The more keys keyboard is usually vertically aligned with the top edge of the parent key // (plus vertical gap). If the key preview is enabled, the more keys keyboard is vertically @@ -687,8 +690,8 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack final int pointY = parentKey.mY + mKeyPreviewDrawParams.mPreviewVisibleOffset; moreKeysPanel.showMoreKeysPanel( this, this, pointX, pointY, mMoreKeysWindow, mKeyboardActionListener); - final int translatedX = moreKeysPanel.translateX(tracker.getLastX()); - final int translatedY = moreKeysPanel.translateY(tracker.getLastY()); + final int translatedX = moreKeysPanel.translateX(CoordinateUtils.x(lastCoords)); + final int translatedY = moreKeysPanel.translateY(CoordinateUtils.y(lastCoords)); tracker.onShowMoreKeysPanel(translatedX, translatedY, moreKeysPanel); dimEntireKeyboard(true); return true; @@ -788,10 +791,11 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack } else if (pointerCount == 2 && oldPointerCount == 1) { // Single-touch to multi-touch transition. // Send an up event for the last pointer. - final int lastX = tracker.getLastX(); - final int lastY = tracker.getLastY(); - mOldKey = tracker.getKeyOn(lastX, lastY); - tracker.onUpEvent(lastX, lastY, eventTime); + final int[] lastCoords = CoordinateUtils.newInstance(); + mOldKey = tracker.getKeyOn( + CoordinateUtils.x(lastCoords), CoordinateUtils.y(lastCoords)); + tracker.onUpEvent( + CoordinateUtils.x(lastCoords), CoordinateUtils.y(lastCoords), eventTime); } else if (pointerCount == 1 && oldPointerCount == 1) { tracker.processMotionEvent(action, x, y, eventTime, this); } else { diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index c3cf49f3b..f9d16be0a 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -28,6 +28,7 @@ import com.android.inputmethod.keyboard.internal.GestureStrokeWithPreviewPoints; import com.android.inputmethod.keyboard.internal.PointerTrackerQueue; import com.android.inputmethod.latin.CollectionUtils; import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.CoordinateUtils; import com.android.inputmethod.latin.InputPointers; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; @@ -80,6 +81,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { public void invalidateKey(Key key); public void showKeyPreview(PointerTracker tracker); public void dismissKeyPreview(PointerTracker tracker); + public void showSlidingKeyInputPreview(PointerTracker tracker); public void showGesturePreviewTrail(PointerTracker tracker, boolean isOldestTracker); } @@ -296,6 +298,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { // The position and time at which first down event occurred. private long mDownTime; + private int[] mDownCoordinates = CoordinateUtils.newInstance(); private long mUpTime; // The current key where this pointer is. @@ -540,6 +543,10 @@ public final class PointerTracker implements PointerTrackerQueue.Element { return mIsInSlidingKeyInput; } + public boolean isInSlidingKeyInputFromModifier() { + return mIsInSlidingKeyInputFromModifier; + } + public Key getKey() { return mCurrentKey; } @@ -642,20 +649,21 @@ public final class PointerTracker implements PointerTrackerQueue.Element { return mGestureStrokeWithPreviewPoints; } - public int getLastX() { - return mLastX; - } - - public int getLastY() { - return mLastY; + public void getLastCoordinates(final int[] outCoords) { + CoordinateUtils.set(outCoords, mLastX, mLastY); } public long getDownTime() { return mDownTime; } + public void getDownCoordinates(final int[] outCoords) { + CoordinateUtils.copy(outCoords, mDownCoordinates); + } + private Key onDownKey(final int x, final int y, final long eventTime) { mDownTime = eventTime; + CoordinateUtils.set(mDownCoordinates, x, y); mBogusMoveEventDetector.onDownKey(); return onMoveToNewKey(onMoveKeyInternal(x, y), x, y); } @@ -867,6 +875,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { private void resetSlidingKeyInput() { mIsInSlidingKeyInput = false; mIsInSlidingKeyInputFromModifier = false; + mDrawingProxy.showSlidingKeyInputPreview(this); } private void onGestureMoveEvent(final int x, final int y, final long eventTime, @@ -1061,6 +1070,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { slideOutFromOldKey(oldKey, x, y); } } + mDrawingProxy.showSlidingKeyInputPreview(this); } public void onUpEvent(final int x, final int y, final long eventTime) { @@ -1087,7 +1097,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { @Override public void onPhantomUpEvent(final long eventTime) { if (DEBUG_EVENT) { - printTouchEvent("onPhntEvent:", getLastX(), getLastY(), eventTime); + printTouchEvent("onPhntEvent:", mLastX, mLastY, eventTime); } onUpEventInternal(eventTime); cancelTracking(); @@ -1134,6 +1144,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } public void onLongPressed() { + resetSlidingKeyInput(); cancelTracking(); setReleasedKeyGraphics(mCurrentKey); sPointerTrackerQueue.remove(this); diff --git a/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java b/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java index 0d44ecdff..7847499cd 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java +++ b/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java @@ -36,6 +36,7 @@ import android.widget.RelativeLayout; import com.android.inputmethod.keyboard.PointerTracker; import com.android.inputmethod.keyboard.internal.GesturePreviewTrail.Params; import com.android.inputmethod.latin.CollectionUtils; +import com.android.inputmethod.latin.CoordinateUtils; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.StaticInnerHandlerWrapper; @@ -47,8 +48,7 @@ public final class PreviewPlacerView extends RelativeLayout { private final float mGestureFloatingPreviewVerticalPadding; private final float mGestureFloatingPreviewRoundRadius; - private int mKeyboardViewOriginX; - private int mKeyboardViewOriginY; + private final int[] mKeyboardViewOrigin = CoordinateUtils.newInstance(); private final SparseArray mGesturePreviewTrails = CollectionUtils.newSparseArray(); @@ -68,11 +68,14 @@ public final class PreviewPlacerView extends RelativeLayout { private final int mGestureFloatingPreviewTextHeight; // {@link RectF} is needed for {@link Canvas#drawRoundRect(RectF, float, float, Paint)}. private final RectF mGestureFloatingPreviewRectangle = new RectF(); - private int mLastPointerX; - private int mLastPointerY; + private final int[] mLastPointerCoords = CoordinateUtils.newInstance(); private static final char[] TEXT_HEIGHT_REFERENCE_CHAR = { 'M' }; private boolean mDrawsGestureFloatingPreviewText; + private boolean mShowSlidingKeyInputPreview; + private final int[] mRubberBandFrom = CoordinateUtils.newInstance(); + private final int[] mRubberBandTo = CoordinateUtils.newInstance(); + private final DrawingHandler mDrawingHandler; private static final class DrawingHandler extends StaticInnerHandlerWrapper { @@ -168,9 +171,8 @@ public final class PreviewPlacerView extends RelativeLayout { setLayerType(LAYER_TYPE_HARDWARE, layerPaint); } - public void setKeyboardViewGeometry(final int x, final int y, final int w, final int h) { - mKeyboardViewOriginX = x; - mKeyboardViewOriginY = y; + public void setKeyboardViewGeometry(final int[] originCoords, final int w, final int h) { + CoordinateUtils.copy(mKeyboardViewOrigin, originCoords); mOffscreenOffsetY = (int)(h * GestureStroke.EXTRA_GESTURE_TRAIL_AREA_ABOVE_KEYBOARD_RATIO); mOffscreenWidth = w; mOffscreenHeight = mOffscreenOffsetY + h; @@ -186,8 +188,7 @@ public final class PreviewPlacerView extends RelativeLayout { final boolean needsToUpdateLastPointer = isOldestTracker && mDrawsGestureFloatingPreviewText; if (needsToUpdateLastPointer) { - mLastPointerX = tracker.getLastX(); - mLastPointerY = tracker.getLastY(); + tracker.getLastCoordinates(mLastPointerCoords); } if (mDrawsGesturePreviewTrail) { @@ -208,6 +209,17 @@ public final class PreviewPlacerView extends RelativeLayout { } } + public void showSlidingKeyInputPreview(final PointerTracker tracker) { + if (!tracker.isInSlidingKeyInputFromModifier()) { + mShowSlidingKeyInputPreview = false; + return; + } + tracker.getDownCoordinates(mRubberBandFrom); + tracker.getLastCoordinates(mRubberBandTo); + mShowSlidingKeyInputPreview = true; + invalidate(); + } + @Override protected void onDetachedFromWindow() { freeOffscreenBuffer(); @@ -234,6 +246,8 @@ public final class PreviewPlacerView extends RelativeLayout { @Override public void onDraw(final Canvas canvas) { super.onDraw(canvas); + final int originX = CoordinateUtils.x(mKeyboardViewOrigin); + final int originY = CoordinateUtils.y(mKeyboardViewOrigin); if (mDrawsGesturePreviewTrail) { mayAllocateOffscreenBuffer(); // Draw gesture trails to offscreen buffer. @@ -241,11 +255,11 @@ public final class PreviewPlacerView extends RelativeLayout { mOffscreenCanvas, mGesturePaint, mOffscreenDirtyRect); // Transfer offscreen buffer to screen. if (!mOffscreenDirtyRect.isEmpty()) { - final int offsetY = mKeyboardViewOriginY - mOffscreenOffsetY; - canvas.translate(mKeyboardViewOriginX, offsetY); + final int offsetY = originY - mOffscreenOffsetY; + canvas.translate(originX, offsetY); canvas.drawBitmap(mOffscreenBuffer, mOffscreenDirtyRect, mOffscreenDirtyRect, mGesturePaint); - canvas.translate(-mKeyboardViewOriginX, -offsetY); + canvas.translate(-originX, -offsetY); // Note: Defer clearing the dirty rectangle here because we will get cleared // rectangle on the canvas. } @@ -254,9 +268,14 @@ public final class PreviewPlacerView extends RelativeLayout { } } if (mDrawsGestureFloatingPreviewText) { - canvas.translate(mKeyboardViewOriginX, mKeyboardViewOriginY); + canvas.translate(originX, originY); drawGestureFloatingPreviewText(canvas, mGestureFloatingPreviewText); - canvas.translate(-mKeyboardViewOriginX, -mKeyboardViewOriginY); + canvas.translate(-originX, -originY); + } + if (mShowSlidingKeyInputPreview) { + canvas.translate(originX, originY); + drawSlidingKeyInputPreview(canvas); + canvas.translate(-originX, -originY); } } @@ -317,8 +336,6 @@ public final class PreviewPlacerView extends RelativeLayout { final Paint paint = mTextPaint; final RectF rectangle = mGestureFloatingPreviewRectangle; - // TODO: Figure out how we should deal with the floating preview text with multiple moving - // fingers. // Paint the round rectangle background. final int textHeight = mGestureFloatingPreviewTextHeight; @@ -328,9 +345,11 @@ public final class PreviewPlacerView extends RelativeLayout { final float rectWidth = textWidth + hPad * 2.0f; final float rectHeight = textHeight + vPad * 2.0f; final int canvasWidth = canvas.getWidth(); - final float rectX = Math.min(Math.max(mLastPointerX - rectWidth / 2.0f, 0.0f), + final float rectX = Math.min( + Math.max(CoordinateUtils.x(mLastPointerCoords) - rectWidth / 2.0f, 0.0f), canvasWidth - rectWidth); - final float rectY = mLastPointerY - mGestureFloatingPreviewTextOffset - rectHeight; + final float rectY = CoordinateUtils.y(mLastPointerCoords) + - mGestureFloatingPreviewTextOffset - rectHeight; rectangle.set(rectX, rectY, rectX + rectWidth, rectY + rectHeight); final float round = mGestureFloatingPreviewRoundRadius; paint.setColor(mGestureFloatingPreviewColor); @@ -341,4 +360,8 @@ public final class PreviewPlacerView extends RelativeLayout { final float textY = rectY + vPad + textHeight; canvas.drawText(gestureFloatingPreviewText, textX, textY, paint); } + + private void drawSlidingKeyInputPreview(final Canvas canvas) { + // TODO: Implement rubber band preview + } } diff --git a/java/src/com/android/inputmethod/latin/CoordinateUtils.java b/java/src/com/android/inputmethod/latin/CoordinateUtils.java index cd3177299..af270e1e4 100644 --- a/java/src/com/android/inputmethod/latin/CoordinateUtils.java +++ b/java/src/com/android/inputmethod/latin/CoordinateUtils.java @@ -36,4 +36,14 @@ public final class CoordinateUtils { public static int y(final int[] coords) { return coords[INDEX_Y]; } + + public static void set(final int[] coords, final int x, final int y) { + coords[INDEX_X] = x; + coords[INDEX_Y] = y; + } + + public static void copy(final int[] destination, final int[] source) { + destination[INDEX_X] = source[INDEX_X]; + destination[INDEX_Y] = source[INDEX_Y]; + } } -- cgit v1.2.3-83-g751a From 308aaff80cf7b2c17d286aaab4cc223269b2bc52 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Mon, 3 Dec 2012 16:35:56 +0900 Subject: Get rid of special keys from ProximityInfo Bug: 7601672 Change-Id: I15faa4829b98f7b4dd07013fdd58bc2c527bcd6f --- .../inputmethod/keyboard/ProximityInfo.java | 108 +++++++++++++++------ 1 file changed, 78 insertions(+), 30 deletions(-) (limited to 'java/src') diff --git a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java index ed01f3458..b5ba98d85 100644 --- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java +++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java @@ -99,6 +99,7 @@ public final class ProximityInfo { JniUtils.loadNativeLibrary(); } + // TODO: Stop passing proximityCharsArray private native long setProximityInfoNative( String locale, int maxProximityCharsSize, int displayWidth, int displayHeight, int gridWidth, int gridHeight, @@ -109,22 +110,56 @@ public final class ProximityInfo { private native void releaseProximityInfoNative(long nativeProximityInfo); - private final long createNativeProximityInfo( - final TouchPositionCorrection touchPositionCorrection) { + private static boolean needsProximityInfo(final Key key) { + // Don't include special keys into ProximityInfo. + return key.mCode >= Constants.CODE_SPACE; + } + + private static int getProximityInfoKeysCount(final Key[] keys) { + int count = 0; + for (final Key key : keys) { + if (needsProximityInfo(key)) { + count++; + } + } + return count; + } + + private long createNativeProximityInfo(final TouchPositionCorrection touchPositionCorrection) { final Key[][] gridNeighborKeys = mGridNeighbors; - final int keyboardWidth = mKeyboardMinWidth; - final int keyboardHeight = mKeyboardHeight; - final Key[] keys = mKeys; final int[] proximityCharsArray = new int[mGridSize * MAX_PROXIMITY_CHARS_SIZE]; Arrays.fill(proximityCharsArray, Constants.NOT_A_CODE); for (int i = 0; i < mGridSize; ++i) { final int proximityCharsLength = gridNeighborKeys[i].length; + int infoIndex = i * MAX_PROXIMITY_CHARS_SIZE; for (int j = 0; j < proximityCharsLength; ++j) { - proximityCharsArray[i * MAX_PROXIMITY_CHARS_SIZE + j] = - gridNeighborKeys[i][j].mCode; + final Key neighborKey = gridNeighborKeys[i][j]; + // Excluding from proximityCharsArray + if (!needsProximityInfo(neighborKey)) { + continue; + } + proximityCharsArray[infoIndex] = neighborKey.mCode; + infoIndex++; } } - final int keyCount = keys.length; + if (DEBUG) { + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < mGridSize; i++) { + sb.setLength(0); + for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE; j++) { + final int code = proximityCharsArray[i * MAX_PROXIMITY_CHARS_SIZE + j]; + if (code == Constants.NOT_A_CODE) { + break; + } + if (sb.length() > 0) sb.append(" "); + sb.append(Constants.printableCode(code)); + } + Log.d(TAG, "proxmityChars["+i+"]: " + sb); + } + } + + final Key[] keys = mKeys; + final int keyCount = getProximityInfoKeysCount(keys); final int[] keyXCoordinates = new int[keyCount]; final int[] keyYCoordinates = new int[keyCount]; final int[] keyWidths = new int[keyCount]; @@ -134,13 +169,18 @@ public final class ProximityInfo { final float[] sweetSpotCenterYs; final float[] sweetSpotRadii; - for (int i = 0; i < keyCount; ++i) { - final Key key = keys[i]; - keyXCoordinates[i] = key.mX; - keyYCoordinates[i] = key.mY; - keyWidths[i] = key.mWidth; - keyHeights[i] = key.mHeight; - keyCharCodes[i] = key.mCode; + for (int infoIndex = 0, keyIndex = 0; keyIndex < keys.length; keyIndex++) { + final Key key = keys[keyIndex]; + // Excluding from key coordinate arrays + if (!needsProximityInfo(key)) { + continue; + } + keyXCoordinates[infoIndex] = key.mX; + keyYCoordinates[infoIndex] = key.mY; + keyWidths[infoIndex] = key.mWidth; + keyHeights[infoIndex] = key.mHeight; + keyCharCodes[infoIndex] = key.mCode; + infoIndex++; } if (touchPositionCorrection != null && touchPositionCorrection.isValid()) { @@ -153,28 +193,36 @@ public final class ProximityInfo { final int rows = touchPositionCorrection.getRows(); final float defaultRadius = DEFAULT_TOUCH_POSITION_CORRECTION_RADIUS * (float)Math.hypot(mMostCommonKeyWidth, mMostCommonKeyHeight); - for (int i = 0; i < keyCount; i++) { - final Key key = keys[i]; + for (int infoIndex = 0, keyIndex = 0; keyIndex < keys.length; keyIndex++) { + final Key key = keys[keyIndex]; + // Excluding from touch position correction arrays + if (!needsProximityInfo(key)) { + continue; + } final Rect hitBox = key.mHitBox; - sweetSpotCenterXs[i] = hitBox.exactCenterX(); - sweetSpotCenterYs[i] = hitBox.exactCenterY(); - sweetSpotRadii[i] = defaultRadius; + sweetSpotCenterXs[infoIndex] = hitBox.exactCenterX(); + sweetSpotCenterYs[infoIndex] = hitBox.exactCenterY(); + sweetSpotRadii[infoIndex] = defaultRadius; final int row = hitBox.top / mMostCommonKeyHeight; if (row < rows) { final int hitBoxWidth = hitBox.width(); final int hitBoxHeight = hitBox.height(); final float hitBoxDiagonal = (float)Math.hypot(hitBoxWidth, hitBoxHeight); - sweetSpotCenterXs[i] += touchPositionCorrection.getX(row) * hitBoxWidth; - sweetSpotCenterYs[i] += touchPositionCorrection.getY(row) * hitBoxHeight; - sweetSpotRadii[i] = touchPositionCorrection.getRadius(row) * hitBoxDiagonal; + sweetSpotCenterXs[infoIndex] += + touchPositionCorrection.getX(row) * hitBoxWidth; + sweetSpotCenterYs[infoIndex] += + touchPositionCorrection.getY(row) * hitBoxHeight; + sweetSpotRadii[infoIndex] = + touchPositionCorrection.getRadius(row) * hitBoxDiagonal; } if (DEBUG) { Log.d(TAG, String.format( - " [%2d] row=%d x/y/r=%7.2f/%7.2f/%5.2f %s code=%s", i, row, - sweetSpotCenterXs[i], sweetSpotCenterYs[i], sweetSpotRadii[i], - (row < rows ? "correct" : "default"), + " [%2d] row=%d x/y/r=%7.2f/%7.2f/%5.2f %s code=%s", infoIndex, row, + sweetSpotCenterXs[infoIndex], sweetSpotCenterYs[infoIndex], + sweetSpotRadii[infoIndex], (row < rows ? "correct" : "default"), Constants.printableCode(key.mCode))); } + infoIndex++; } } else { sweetSpotCenterXs = sweetSpotCenterYs = sweetSpotRadii = null; @@ -183,11 +231,11 @@ public final class ProximityInfo { } } + // TODO: Stop passing proximityCharsArray return setProximityInfoNative(mLocaleStr, MAX_PROXIMITY_CHARS_SIZE, - keyboardWidth, keyboardHeight, mGridWidth, mGridHeight, mMostCommonKeyWidth, - proximityCharsArray, - keyCount, keyXCoordinates, keyYCoordinates, keyWidths, keyHeights, keyCharCodes, - sweetSpotCenterXs, sweetSpotCenterYs, sweetSpotRadii); + mKeyboardMinWidth, mKeyboardHeight, mGridWidth, mGridHeight, mMostCommonKeyWidth, + proximityCharsArray, keyCount, keyXCoordinates, keyYCoordinates, keyWidths, + keyHeights, keyCharCodes, sweetSpotCenterXs, sweetSpotCenterYs, sweetSpotRadii); } public long getNativeProximityInfo() { -- cgit v1.2.3-83-g751a From b10ec5319b1ce5d0e61af73840aabc00707a5e4c Mon Sep 17 00:00:00 2001 From: Kurt Partridge Date: Mon, 3 Dec 2012 11:46:25 -0800 Subject: Fix crashes related to setSpan(-1 ... -1) errors Fixes b/7652661 In some circumstnaces, when hiding the window, the logger tries to capture the TextView contents and restore the cursor position based on the values stored in LatinIME. However, the IME may not know the cursor position. This fix does two things 1) doesn't try to reposition the cursor if the TextView contents are not to be captured, and 2) if the cursor position is unknown (i.e., == -1), doesn't try to move it back. Change-Id: I3976aaccf58c18f892c3a8530218ae52bcac9989 --- .../inputmethod/research/ResearchLogger.java | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'java/src') diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java index fe31039e3..3443b7a7a 100644 --- a/java/src/com/android/inputmethod/research/ResearchLogger.java +++ b/java/src/com/android/inputmethod/research/ResearchLogger.java @@ -925,18 +925,20 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang public static void latinIME_onWindowHidden(final int savedSelectionStart, final int savedSelectionEnd, final InputConnection ic) { if (ic != null) { - // Capture the TextView contents. This will trigger onUpdateSelection(), so we - // set sLatinIMEExpectingUpdateSelection so that when onUpdateSelection() is called, - // it can tell that it was generated by the logging code, and not by the user, and - // therefore keep user-visible state as is. - ic.beginBatchEdit(); - ic.performContextMenuAction(android.R.id.selectAll); - CharSequence charSequence = ic.getSelectedText(0); - ic.setSelection(savedSelectionStart, savedSelectionEnd); - ic.endBatchEdit(); - sLatinIMEExpectingUpdateSelection = true; final Object[] values = new Object[2]; if (OUTPUT_ENTIRE_BUFFER) { + // Capture the TextView contents. This will trigger onUpdateSelection(), so we + // set sLatinIMEExpectingUpdateSelection so that when onUpdateSelection() is called, + // it can tell that it was generated by the logging code, and not by the user, and + // therefore keep user-visible state as is. + ic.beginBatchEdit(); + ic.performContextMenuAction(android.R.id.selectAll); + CharSequence charSequence = ic.getSelectedText(0); + if (savedSelectionStart != -1 && savedSelectionEnd != -1) { + ic.setSelection(savedSelectionStart, savedSelectionEnd); + } + ic.endBatchEdit(); + sLatinIMEExpectingUpdateSelection = true; if (TextUtils.isEmpty(charSequence)) { values[0] = false; values[1] = ""; -- cgit v1.2.3-83-g751a From 139bd83f0c552e3fdb5f763b5f6fe25ad138802b Mon Sep 17 00:00:00 2001 From: Ken Wakasa Date: Tue, 4 Dec 2012 15:24:55 +0900 Subject: Add a new option for the double-space period functionality bug: 6934756 Change-Id: I94b2d08cac6533e96031d8e97f347e9b5fd72859 --- java/res/values/strings.xml | 5 +++++ java/res/xml/prefs.xml | 6 ++++++ java/src/com/android/inputmethod/latin/LatinIME.java | 1 + java/src/com/android/inputmethod/latin/Settings.java | 2 ++ java/src/com/android/inputmethod/latin/SettingsValues.java | 2 ++ 5 files changed, 16 insertions(+) (limited to 'java/src') diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml index 13aca717f..09be9b73f 100644 --- a/java/res/values/strings.xml +++ b/java/res/values/strings.xml @@ -81,6 +81,11 @@ Use names from Contacts for suggestions and corrections + + Double-space period + + Double tap on spacebar inserts a period followed by a space + Auto-capitalization diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml index 9172b2415..4ffbf14d5 100644 --- a/java/res/xml/prefs.xml +++ b/java/res/xml/prefs.xml @@ -118,6 +118,12 @@ android:summary="@string/use_contacts_dict_summary" android:persistent="true" android:defaultValue="true" /> + Date: Tue, 4 Dec 2012 16:04:21 +0900 Subject: Dismiss sliding key input preview when touch event is canceled This is a follow up of Id807af31. Bug: 7662486 Change-Id: I13895140f1214592257d0023c1450875a4885ee9 --- java/src/com/android/inputmethod/keyboard/KeyboardView.java | 5 +++++ java/src/com/android/inputmethod/keyboard/PointerTracker.java | 3 ++- .../com/android/inputmethod/keyboard/internal/PreviewPlacerView.java | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'java/src') diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java index 51fb3701c..992282bf9 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java @@ -860,6 +860,11 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { mPreviewPlacerView.showSlidingKeyInputPreview(tracker); } + @Override + public void dismissSlidingKeyInputPreview() { + mPreviewPlacerView.dismissSlidingKeyInputPreview(); + } + public void showGestureFloatingPreviewText(final String gestureFloatingPreviewText) { locatePreviewPlacerView(); mPreviewPlacerView.setGestureFloatingPreviewText(gestureFloatingPreviewText); diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index 035fb58f8..d9a520917 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -82,6 +82,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { public void showKeyPreview(PointerTracker tracker); public void dismissKeyPreview(PointerTracker tracker); public void showSlidingKeyInputPreview(PointerTracker tracker); + public void dismissSlidingKeyInputPreview(); public void showGesturePreviewTrail(PointerTracker tracker, boolean isOldestTracker); } @@ -881,7 +882,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { private void resetSlidingKeyInput() { mIsInSlidingKeyInput = false; mIsInSlidingKeyInputFromModifier = false; - mDrawingProxy.showSlidingKeyInputPreview(this); + mDrawingProxy.dismissSlidingKeyInputPreview(); } private void onGestureMoveEvent(final int x, final int y, final long eventTime, diff --git a/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java b/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java index 7847499cd..bc734b08d 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java +++ b/java/src/com/android/inputmethod/keyboard/internal/PreviewPlacerView.java @@ -220,6 +220,10 @@ public final class PreviewPlacerView extends RelativeLayout { invalidate(); } + public void dismissSlidingKeyInputPreview() { + mShowSlidingKeyInputPreview = false; + } + @Override protected void onDetachedFromWindow() { freeOffscreenBuffer(); -- cgit v1.2.3-83-g751a From 95bfb8ac474d242f7abe83709df5c853a6d08619 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Tue, 4 Dec 2012 16:11:18 +0900 Subject: Fix wrong misspelling reports of fully capitalized words Two flavors of words would be wrongly reported as misspelled by the android spell checker when they are written in all upper case letters: - Words containing a quote or a dash or any other non-letter - Words that need the first letter to be capitalized Bug: 7659216 Change-Id: Ibc5d261945ffcbb8a858d4c73b7c62cef6671abf --- .../spellcheck/AndroidSpellCheckerService.java | 22 ++++++++---- .../AndroidWordLevelSpellCheckerSession.java | 41 +++++++++++++++++----- 2 files changed, 48 insertions(+), 15 deletions(-) (limited to 'java/src') diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 49b98863f..2f146f86c 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -438,15 +438,23 @@ public final class AndroidSpellCheckerService extends SpellCheckerService if (!Character.isUpperCase(text.codePointAt(0))) return CAPITALIZE_NONE; final int len = text.length(); int capsCount = 1; + int letterCount = 1; for (int i = 1; i < len; i = text.offsetByCodePoints(i, 1)) { - if (1 != capsCount && i != capsCount) break; - if (Character.isUpperCase(text.codePointAt(i))) ++capsCount; + if (1 != capsCount && letterCount != capsCount) break; + final int codePoint = text.codePointAt(i); + if (Character.isUpperCase(codePoint)) { + ++capsCount; + ++letterCount; + } else if (Character.isLetter(codePoint)) { + // We need to discount non-letters since they may not be upper-case, but may + // still be part of a word (e.g. single quote or dash, as in "IT'S" or "FULL-TIME") + ++letterCount; + } } - // We know the first char is upper case. So we want to test if either everything - // else is lower case, or if everything else is upper case. If the string is - // exactly one char long, then we will arrive here with capsCount 1, and this is - // correct, too. + // We know the first char is upper case. So we want to test if either every letter other + // than the first is lower case, or if they are all upper case. If the string is exactly + // one char long, then we will arrive here with letterCount 1, and this is correct, too. if (1 == capsCount) return CAPITALIZE_FIRST; - return (len == capsCount ? CAPITALIZE_ALL : CAPITALIZE_NONE); + return (letterCount == capsCount ? CAPITALIZE_ALL : CAPITALIZE_NONE); } } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java index a8f323999..470943be1 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java @@ -28,9 +28,11 @@ import android.view.textservice.TextInfo; import com.android.inputmethod.compat.SuggestionsInfoCompatUtils; import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.LocaleUtils; -import com.android.inputmethod.latin.WordComposer; +import com.android.inputmethod.latin.StringUtils; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.latin.WordComposer; import com.android.inputmethod.latin.spellcheck.AndroidSpellCheckerService.SuggestionsGatherer; import java.util.ArrayList; @@ -188,6 +190,35 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { return (letterCount * 4 < length * 3); } + /** + * Helper method to test valid capitalizations of a word. + * + * If the "text" is lower-case, we test only the exact string. + * If the "Text" is capitalized, we test the exact string "Text" and the lower-cased + * version of it "text". + * If the "TEXT" is fully upper case, we test the exact string "TEXT", the lower-cased + * version of it "text" and the capitalized version of it "Text". + */ + private boolean isInDictForAnyCapitalization(final Dictionary dict, final String text, + final int capitalizeType) { + // If the word is in there as is, then it's in the dictionary. If not, we'll test lower + // case versions, but only if the word is not already all-lower case or mixed case. + if (dict.isValidWord(text)) return true; + if (AndroidSpellCheckerService.CAPITALIZE_NONE == capitalizeType) return false; + + // If we come here, we have a capitalized word (either First- or All-). + // Downcase the word and look it up again. If the word is only capitalized, we + // tested all possibilities, so if it's still negative we can return false. + final String lowerCaseText = text.toLowerCase(mLocale); + if (dict.isValidWord(lowerCaseText)) return true; + if (AndroidSpellCheckerService.CAPITALIZE_FIRST == capitalizeType) return false; + + // If the lower case version is not in the dictionary, it's still possible + // that we have an all-caps version of a word that needs to be capitalized + // according to the dictionary. E.g. "GERMANS" only exists in the dictionary as "Germans". + return dict.isValidWord(StringUtils.toTitleCase(lowerCaseText, mLocale)); + } + // Note : this must be reentrant /** * Gets a list of suggestions for a specific string. This returns a list of possible @@ -272,13 +303,7 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { suggestionsGatherer.addWord(suggestionStr.toCharArray(), null, 0, suggestionStr.length(), suggestion.mScore); } - isInDict = dictInfo.mDictionary.isValidWord(text); - if (!isInDict && AndroidSpellCheckerService.CAPITALIZE_NONE != capitalizeType) { - // We want to test the word again if it's all caps or first caps only. - // If it's fully down, we already tested it, if it's mixed case, we don't - // want to test a lowercase version of it. - isInDict = dictInfo.mDictionary.isValidWord(text.toLowerCase(mLocale)); - } + isInDict = isInDictForAnyCapitalization(dictInfo.mDictionary, text, capitalizeType); } finally { if (null != dictInfo) { if (!mDictionaryPool.offer(dictInfo)) { -- cgit v1.2.3-83-g751a