From c986d16e8aa97c042e1791cabb0a79bb9aaf04a1 Mon Sep 17 00:00:00 2001 From: "Tadashi G. Takaoka" Date: Fri, 20 Dec 2013 15:57:56 +0900 Subject: [PATCH] Separate BogusMoveEventDetector class Change-Id: I24f0ff385f338ff313ef32514f2930f120183be7 --- .../inputmethod/keyboard/PointerTracker.java | 91 +------------- .../internal/BogusMoveEventDetector.java | 115 ++++++++++++++++++ 2 files changed, 121 insertions(+), 85 deletions(-) create mode 100644 java/src/com/android/inputmethod/keyboard/internal/BogusMoveEventDetector.java diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java index d70286281..80f61b695 100644 --- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java +++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java @@ -19,11 +19,11 @@ package com.android.inputmethod.keyboard; import android.content.res.Resources; import android.content.res.TypedArray; import android.os.SystemClock; -import android.util.DisplayMetrics; import android.util.Log; import android.view.MotionEvent; import com.android.inputmethod.accessibility.AccessibilityUtils; +import com.android.inputmethod.keyboard.internal.BogusMoveEventDetector; import com.android.inputmethod.keyboard.internal.GestureStroke; import com.android.inputmethod.keyboard.internal.GestureStroke.GestureStrokeParams; import com.android.inputmethod.keyboard.internal.GestureStrokeWithPreviewPoints; @@ -145,9 +145,6 @@ public final class PointerTracker implements PointerTrackerQueue.Element { // Move this threshold to resource. // TODO: Device specific parameter would be better for device specific hack? private static final float PHANTOM_SUDDEN_MOVE_THRESHOLD = 0.25f; // in keyWidth - // This hack is applied to certain classes of tablets. - // See {@link #needsProximateBogusDownMoveUpEventHack(Resources)}. - private static boolean sNeedsProximateBogusDownMoveUpEventHack; private static final ArrayList sTrackers = CollectionUtils.newArrayList(); private static final PointerTrackerQueue sPointerTrackerQueue = new PointerTrackerQueue(); @@ -174,57 +171,6 @@ public final class PointerTracker implements PointerTrackerQueue.Element { private static int sLastRecognitionPointSize = 0; // synchronized using sAggregatedPointers private static long sLastRecognitionTime = 0; // synchronized using sAggregatedPointers - static final class BogusMoveEventDetector { - // Move these thresholds to resource. - // These thresholds' unit is a diagonal length of a key. - private static final float BOGUS_MOVE_ACCUMULATED_DISTANCE_THRESHOLD = 0.53f; - private static final float BOGUS_MOVE_RADIUS_THRESHOLD = 1.14f; - - private int mAccumulatedDistanceThreshold; - private int mRadiusThreshold; - - // Accumulated distance from actual and artificial down keys. - /* package */ int mAccumulatedDistanceFromDownKey; - private int mActualDownX; - private int mActualDownY; - - public void setKeyboardGeometry(final int keyWidth, final int keyHeight) { - final float keyDiagonal = (float)Math.hypot(keyWidth, keyHeight); - mAccumulatedDistanceThreshold = (int)( - keyDiagonal * BOGUS_MOVE_ACCUMULATED_DISTANCE_THRESHOLD); - mRadiusThreshold = (int)(keyDiagonal * BOGUS_MOVE_RADIUS_THRESHOLD); - } - - public void onActualDownEvent(final int x, final int y) { - mActualDownX = x; - mActualDownY = y; - } - - public void onDownKey() { - mAccumulatedDistanceFromDownKey = 0; - } - - public void onMoveKey(final int distance) { - mAccumulatedDistanceFromDownKey += distance; - } - - public boolean hasTraveledLongDistance(final int x, final int y) { - final int dx = Math.abs(x - mActualDownX); - final int dy = Math.abs(y - mActualDownY); - // A bogus move event should be a horizontal movement. A vertical movement might be - // a sloppy typing and should be ignored. - return dx >= dy && mAccumulatedDistanceFromDownKey >= mAccumulatedDistanceThreshold; - } - - /* package */ int getDistanceFromDownEvent(final int x, final int y) { - return getDistance(x, y, mActualDownX, mActualDownY); - } - - public boolean isCloseToActualDownEvent(final int x, final int y) { - return getDistanceFromDownEvent(x, y) < mRadiusThreshold; - } - } - // The position and time at which first down event occurred. private long mDownTime; private int[] mDownCoordinates = CoordinateUtils.newInstance(); @@ -263,29 +209,6 @@ public final class PointerTracker implements PointerTrackerQueue.Element { private final GestureStrokeWithPreviewPoints mGestureStrokeWithPreviewPoints; - private static final int SMALL_TABLET_SMALLEST_WIDTH = 600; // dp - private static final int LARGE_TABLET_SMALLEST_WIDTH = 768; // dp - - private static boolean needsProximateBogusDownMoveUpEventHack(final Resources res) { - // The proximate bogus down move up event hack is needed for a device such like, - // 1) is large tablet, or 2) is small tablet and the screen density is less than hdpi. - // Though it seems odd to use screen density as criteria of the quality of the touch - // screen, the small table that has a less density screen than hdpi most likely has been - // made with the touch screen that needs the hack. - final int sw = res.getConfiguration().smallestScreenWidthDp; - final boolean isLargeTablet = (sw >= LARGE_TABLET_SMALLEST_WIDTH); - final boolean isSmallTablet = - (sw >= SMALL_TABLET_SMALLEST_WIDTH && sw < LARGE_TABLET_SMALLEST_WIDTH); - final int densityDpi = res.getDisplayMetrics().densityDpi; - final boolean hasLowDensityScreen = (densityDpi < DisplayMetrics.DENSITY_HIGH); - final boolean needsTheHack = isLargeTablet || (isSmallTablet && hasLowDensityScreen); - if (DEBUG_MODE) { - Log.d(TAG, "needsProximateBogusDownMoveUpEventHack=" + needsTheHack - + " smallestScreenWidthDp=" + sw + " densityDpi=" + densityDpi); - } - return needsTheHack; - } - // TODO: Add PointerTrackerFactory singleton and move some class static methods into it. public static void init(final TypedArray mainKeyboardViewAttr, final TimerProxy timerProxy, final DrawingProxy drawingProxy) { @@ -300,7 +223,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { sNeedsPhantomSuddenMoveEventHack = Boolean.parseBoolean( ResourceUtils.getDeviceOverrideValue( res, R.array.phantom_sudden_move_event_device_list)); - sNeedsProximateBogusDownMoveUpEventHack = needsProximateBogusDownMoveUpEventHack(res); + BogusMoveEventDetector.init(res); sTimerProxy = timerProxy; sDrawingProxy = drawingProxy; @@ -637,7 +560,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { return onMoveToNewKey(onMoveKeyInternal(x, y), x, y); } - static int getDistance(final int x1, final int y1, final int x2, final int y2) { + private static int getDistance(final int x1, final int y1, final int x2, final int y2) { return (int)Math.hypot(x1 - x2, y1 - y2); } @@ -1047,8 +970,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element { // HACK: On some devices, quick successive proximate touches may be reported as a bogus // down-move-up event by touch panel firmware. This hack detects such cases and breaks // these events into separate up and down events. - else if (sNeedsProximateBogusDownMoveUpEventHack - && sTypingTimeRecorder.isInFastTyping(eventTime) + else if (sTypingTimeRecorder.isInFastTyping(eventTime) && mBogusMoveEventDetector.isCloseToActualDownEvent(x, y)) { processProximateBogusDownMoveUpEventHack(key, x, y, eventTime, oldKey, lastX, lastY); } @@ -1265,14 +1187,13 @@ public final class PointerTracker implements PointerTrackerQueue.Element { } return true; } - if (sNeedsProximateBogusDownMoveUpEventHack && !mIsAllowedDraggingFinger - && sTypingTimeRecorder.isInFastTyping(eventTime) + if (!mIsAllowedDraggingFinger && sTypingTimeRecorder.isInFastTyping(eventTime) && mBogusMoveEventDetector.hasTraveledLongDistance(x, y)) { if (DEBUG_MODE) { final float keyDiagonal = (float)Math.hypot( mKeyboard.mMostCommonKeyWidth, mKeyboard.mMostCommonKeyHeight); final float lengthFromDownRatio = - mBogusMoveEventDetector.mAccumulatedDistanceFromDownKey / keyDiagonal; + mBogusMoveEventDetector.getAccumulatedDistanceFromDownKey() / keyDiagonal; Log.d(TAG, String.format("[%d] isMajorEnoughMoveToBeOnNewKey:" + " %.2f key diagonal from virtual down point", mPointerId, lengthFromDownRatio)); diff --git a/java/src/com/android/inputmethod/keyboard/internal/BogusMoveEventDetector.java b/java/src/com/android/inputmethod/keyboard/internal/BogusMoveEventDetector.java new file mode 100644 index 000000000..ab052ddd8 --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/internal/BogusMoveEventDetector.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.inputmethod.keyboard.internal; + +import android.content.res.Resources; +import android.util.DisplayMetrics; +import android.util.Log; + +import com.android.inputmethod.latin.LatinImeLogger; + +// This hack is applied to certain classes of tablets. +public final class BogusMoveEventDetector { + private static final String TAG = BogusMoveEventDetector.class.getSimpleName(); + private static final boolean DEBUG_MODE = LatinImeLogger.sDBG; + + // Move these thresholds to resource. + // These thresholds' unit is a diagonal length of a key. + private static final float BOGUS_MOVE_ACCUMULATED_DISTANCE_THRESHOLD = 0.53f; + private static final float BOGUS_MOVE_RADIUS_THRESHOLD = 1.14f; + + private static final int SMALL_TABLET_SMALLEST_WIDTH = 600; // dp + private static final int LARGE_TABLET_SMALLEST_WIDTH = 768; // dp + + private static boolean sNeedsProximateBogusDownMoveUpEventHack; + + public static void init(final Resources res) { + // The proximate bogus down move up event hack is needed for a device such like, + // 1) is large tablet, or 2) is small tablet and the screen density is less than hdpi. + // Though it seems odd to use screen density as criteria of the quality of the touch + // screen, the small table that has a less density screen than hdpi most likely has been + // made with the touch screen that needs the hack. + final int sw = res.getConfiguration().smallestScreenWidthDp; + final boolean isLargeTablet = (sw >= LARGE_TABLET_SMALLEST_WIDTH); + final boolean isSmallTablet = + (sw >= SMALL_TABLET_SMALLEST_WIDTH && sw < LARGE_TABLET_SMALLEST_WIDTH); + final int densityDpi = res.getDisplayMetrics().densityDpi; + final boolean hasLowDensityScreen = (densityDpi < DisplayMetrics.DENSITY_HIGH); + final boolean needsTheHack = isLargeTablet || (isSmallTablet && hasLowDensityScreen); + if (DEBUG_MODE) { + Log.d(TAG, "needsProximateBogusDownMoveUpEventHack=" + needsTheHack + + " smallestScreenWidthDp=" + sw + " densityDpi=" + densityDpi); + } + sNeedsProximateBogusDownMoveUpEventHack = needsTheHack; + } + + private int mAccumulatedDistanceThreshold; + private int mRadiusThreshold; + + // Accumulated distance from actual and artificial down keys. + /* package */ int mAccumulatedDistanceFromDownKey; + private int mActualDownX; + private int mActualDownY; + + public void setKeyboardGeometry(final int keyWidth, final int keyHeight) { + final float keyDiagonal = (float)Math.hypot(keyWidth, keyHeight); + mAccumulatedDistanceThreshold = (int)( + keyDiagonal * BOGUS_MOVE_ACCUMULATED_DISTANCE_THRESHOLD); + mRadiusThreshold = (int)(keyDiagonal * BOGUS_MOVE_RADIUS_THRESHOLD); + } + + public void onActualDownEvent(final int x, final int y) { + mActualDownX = x; + mActualDownY = y; + } + + public void onDownKey() { + mAccumulatedDistanceFromDownKey = 0; + } + + public void onMoveKey(final int distance) { + mAccumulatedDistanceFromDownKey += distance; + } + + public boolean hasTraveledLongDistance(final int x, final int y) { + if (!sNeedsProximateBogusDownMoveUpEventHack) { + return false; + } + final int dx = Math.abs(x - mActualDownX); + final int dy = Math.abs(y - mActualDownY); + // A bogus move event should be a horizontal movement. A vertical movement might be + // a sloppy typing and should be ignored. + return dx >= dy && mAccumulatedDistanceFromDownKey >= mAccumulatedDistanceThreshold; + } + + public int getAccumulatedDistanceFromDownKey() { + return mAccumulatedDistanceFromDownKey; + } + + public int getDistanceFromDownEvent(final int x, final int y) { + return getDistance(x, y, mActualDownX, mActualDownY); + } + + private static int getDistance(final int x1, final int y1, final int x2, final int y2) { + return (int)Math.hypot(x1 - x2, y1 - y2); + } + + public boolean isCloseToActualDownEvent(final int x, final int y) { + return sNeedsProximateBogusDownMoveUpEventHack + && getDistanceFromDownEvent(x, y) < mRadiusThreshold; + } +}