diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index cf9138ba202fb41c157bd97ad9a7d2f63cf52f7b..d0d66d68b38e33663ae45955be5565b3898c7f9f 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -89,9 +89,6 @@
         <!-- Size of the text for key press feedback popup, int the proportion of key height -->
         <attr name="keyPreviewTextRatio" format="float" />
 
-        <!-- Hysteresis distance for key debouncing -->
-        <attr name="keyHysteresisDistance" format="dimension" />
-
         <!-- Amount to offset the touch Y coordinate by, for bias correction. -->
         <attr name="verticalCorrection" format="dimension" />
 
diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml
index de55cbdaed68395ab0aa44989f9f614f58eff37d..8ed3343763f22ab48a41338e8c0b563a87eb839e 100644
--- a/java/res/values/styles.xml
+++ b/java/res/values/styles.xml
@@ -62,7 +62,6 @@
         <item name="keyPreviewHeight">@dimen/key_preview_height</item>
         <item name="keyPreviewTextRatio">@fraction/key_preview_text_ratio</item>
         <item name="popupLayout">@layout/keyboard_popup</item>
-        <item name="keyHysteresisDistance">@dimen/key_hysteresis_distance</item>
         <item name="verticalCorrection">@dimen/keyboard_vertical_correction</item>
         <item name="shadowColor">#BB000000</item>
         <item name="shadowRadius">2.75</item>
@@ -70,7 +69,6 @@
     </style>
     <style name="PopupMiniKeyboardView" parent="KeyboardView">
         <item name="keyBackground">@drawable/btn_keyboard_key_popup</item>
-        <item name="keyHysteresisDistance">0dip</item>
         <item name="verticalCorrection">@dimen/mini_keyboard_vertical_correction</item>
     </style>
     <style name="PopupMiniKeyboardPanelStyle">
diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
index 7add43a6de5d7c49ce3329cd68402649d2fbfb55..85418a61dce199ebb60b159464c94f3dc0dc83ed 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
@@ -28,6 +28,8 @@ public class KeyDetector {
     public static final int NOT_A_CODE = -1;
     public static final int NOT_A_KEY = -1;
 
+    private final int mKeyHysteresisDistanceSquared;
+
     private Keyboard mKeyboard;
     private int mCorrectionX;
     private int mCorrectionY;
@@ -39,12 +41,28 @@ public class KeyDetector {
     private final int[] mDistances = new int[MAX_NEARBY_KEYS];
     private final int[] mIndices = new int[MAX_NEARBY_KEYS];
 
+    /**
+     * This class handles key detection.
+     *
+     * @param keyHysteresisDistance if the pointer movement distance is smaller than this, the
+     * movement will not been handled as meaningful movement. The unit is pixel.
+     */
+    public KeyDetector(float keyHysteresisDistance) {
+        mKeyHysteresisDistanceSquared = (int)(keyHysteresisDistance * keyHysteresisDistance);
+    }
+
     public void setKeyboard(Keyboard keyboard, float correctionX, float correctionY) {
         if (keyboard == null)
             throw new NullPointerException();
         mCorrectionX = (int)correctionX;
         mCorrectionY = (int)correctionY;
         mKeyboard = keyboard;
+        final int threshold = keyboard.getMostCommonKeyWidth();
+        mProximityThresholdSquare = threshold * threshold;
+    }
+
+    public int getKeyHysteresisDistanceSquared() {
+        return mKeyHysteresisDistanceSquared;
     }
 
     protected int getTouchX(int x) {
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java
index 0a7ba05c867a6ea1472b3ca367baa91939c0e0ec..5ef40ecb3a7dccb13ffd5f0b2a23066f51e17191 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardBaseView.java
@@ -59,7 +59,6 @@ public class LatinKeyboardBaseView extends KeyboardView {
     private final int mKeyRepeatInterval;
 
     // XML attribute
-    private final float mKeyHysteresisDistance;
     private final float mVerticalCorrection;
     private final int mPopupLayout;
 
@@ -81,7 +80,7 @@ public class LatinKeyboardBaseView extends KeyboardView {
     private int mOldPointerCount = 1;
     private int mOldKeyIndex;
 
-    protected KeyDetector mKeyDetector = new KeyDetector();
+    protected KeyDetector mKeyDetector;
 
     // Swipe gesture detector
     protected GestureDetector mGestureDetector;
@@ -182,8 +181,6 @@ public class LatinKeyboardBaseView extends KeyboardView {
 
         final TypedArray a = context.obtainStyledAttributes(
                 attrs, R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
-        mKeyHysteresisDistance = a.getDimensionPixelOffset(
-                R.styleable.KeyboardView_keyHysteresisDistance, 0);
         mVerticalCorrection = a.getDimensionPixelOffset(
                 R.styleable.KeyboardView_verticalCorrection, 0);
 
@@ -193,6 +190,8 @@ public class LatinKeyboardBaseView extends KeyboardView {
 
         final Resources res = getResources();
 
+        final float keyHysteresisDistance = res.getDimension(R.dimen.key_hysteresis_distance);
+        mKeyDetector = new KeyDetector(keyHysteresisDistance);
         mSwipeThreshold = (int) (500 * res.getDisplayMetrics().density);
         // TODO: Refer to frameworks/base/core/res/res/values/config.xml
         mDisambiguateSwipe = res.getBoolean(R.bool.config_swipeDisambiguation);
@@ -309,7 +308,7 @@ public class LatinKeyboardBaseView extends KeyboardView {
         mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(),
                 -getPaddingTop() + mVerticalCorrection);
         for (PointerTracker tracker : mPointerTrackers) {
-            tracker.setKeyboard(keyboard, mKeyHysteresisDistance);
+            tracker.setKeyboard(keyboard, mKeyDetector);
         }
         mKeyDetector.setProximityThreshold(keyboard.getMostCommonKeyWidth());
         mPopupPanelCache.clear();
@@ -484,7 +483,7 @@ public class LatinKeyboardBaseView extends KeyboardView {
             final PointerTracker tracker =
                 new PointerTracker(i, this, mHandler, mKeyDetector, this);
             if (keyboard != null)
-                tracker.setKeyboard(keyboard, mKeyHysteresisDistance);
+                tracker.setKeyboard(keyboard, mKeyDetector);
             if (listener != null)
                 tracker.setOnKeyboardActionListener(listener);
             pointers.add(tracker);
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java
index cc5c3bbfe115d339135206d5a792c62fe7e5fa65..69005db576d1cb726dfeef548932d6d4a1fe0dfe 100644
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java
+++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboardKeyDetector.java
@@ -23,7 +23,7 @@ public class MiniKeyboardKeyDetector extends KeyDetector {
     private final int mSlideAllowanceSquareTop;
 
     public MiniKeyboardKeyDetector(float slideAllowance) {
-        super();
+        super(/* keyHysteresisDistance */0);
         mSlideAllowanceSquare = (int)(slideAllowance * slideAllowance);
         // Top slide allowance is slightly longer (sqrt(2) times) than other edges.
         mSlideAllowanceSquareTop = mSlideAllowanceSquare * 2;
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 68284cd1b3555bb972cfc6c69c8c321343b6ded2..ed93978acfb58322bab6cd3eed30e060bec5897a 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -56,7 +56,7 @@ public class PointerTracker {
     private final LatinKeyboardBaseView mKeyboardView;
     private final UIProxy mProxy;
     private final UIHandler mHandler;
-    private final KeyDetector mKeyDetector;
+    private KeyDetector mKeyDetector;
     private KeyboardActionListener mListener = EMPTY_LISTENER;
     private final KeyboardSwitcher mKeyboardSwitcher;
     private final boolean mHasDistinctMultitouch;
@@ -67,7 +67,6 @@ public class PointerTracker {
 
     private Keyboard mKeyboard;
     private List<Key> mKeys;
-    private int mKeyHysteresisDistanceSquared = -1;
     private int mKeyQuarterWidthSquared;
 
     private final PointerTrackerKeyState mKeyState;
@@ -198,12 +197,13 @@ public class PointerTracker {
         mListener.onCancelInput();
     }
 
-    public void setKeyboard(Keyboard keyboard, float keyHysteresisDistance) {
-        if (keyboard == null || keyHysteresisDistance < 0)
-            throw new IllegalArgumentException();
+    public void setKeyboard(Keyboard keyboard, KeyDetector keyDetector) {
+        if (keyboard == null || keyDetector == null)
+            throw new NullPointerException();
         mKeyboard = keyboard;
         mKeys = keyboard.getKeys();
-        mKeyHysteresisDistanceSquared = (int)(keyHysteresisDistance * keyHysteresisDistance);
+        mKeyDetector = keyDetector;
+        mKeyState.setKeyDetector(keyDetector);
         final int keyQuarterWidth = keyboard.getKeyWidth() / 4;
         mKeyQuarterWidthSquared = keyQuarterWidth * keyQuarterWidth;
         // Mark that keyboard layout has been changed.
@@ -602,13 +602,14 @@ public class PointerTracker {
     }
 
     private boolean isMajorEnoughMoveToBeOnNewKey(int x, int y, int newKey) {
-        if (mKeys == null || mKeyHysteresisDistanceSquared < 0)
-            throw new IllegalStateException("keyboard and/or hysteresis not set");
+        if (mKeys == null || mKeyDetector == null)
+            throw new NullPointerException("keyboard and/or key detector not set");
         int curKey = mKeyState.getKeyIndex();
         if (newKey == curKey) {
             return false;
         } else if (isValidKeyIndex(curKey)) {
-            return mKeys.get(curKey).squaredDistanceToEdge(x, y) >= mKeyHysteresisDistanceSquared;
+            return mKeys.get(curKey).squaredDistanceToEdge(x, y)
+                    >= mKeyDetector.getKeyHysteresisDistanceSquared();
         } else {
             return true;
         }
diff --git a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerKeyState.java b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerKeyState.java
index ddadb1338d8e17a40b569bf216a40f9fd5fcc208..6e2b60c30d169f0849655c29c967cb35389e269b 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerKeyState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/PointerTrackerKeyState.java
@@ -23,7 +23,7 @@ import com.android.inputmethod.keyboard.PointerTracker;
  * This class keeps track of a key index and a position where {@link PointerTracker} is.
  */
 public class PointerTrackerKeyState {
-    private final KeyDetector mKeyDetector;
+    private KeyDetector mKeyDetector;
 
     // The position and time at which first down event occurred.
     private long mDownTime;
@@ -43,6 +43,10 @@ public class PointerTrackerKeyState {
         mKeyDetector = keyDetecor;
     }
 
+    public void setKeyDetector(KeyDetector keyDetector) {
+        mKeyDetector = keyDetector;
+    }
+
     public int getKeyIndex() {
         return mKeyIndex;
     }
diff --git a/tests/src/com/android/inputmethod/latin/SuggestHelper.java b/tests/src/com/android/inputmethod/latin/SuggestHelper.java
index 87ea011fa1d57e7b225d4c6af2a4b1704bc984e2..07d0e5d751c2acefd837b58a47f2b14e9e1aad28 100644
--- a/tests/src/com/android/inputmethod/latin/SuggestHelper.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestHelper.java
@@ -37,7 +37,7 @@ public class SuggestHelper {
         // (and not try to find a dictionary provider for a specified locale)
         mSuggest = new Suggest(context, dictionaryId, null);
         mKeyboard = new LatinKeyboard(context, keyboardId, keyboardId.mWidth);
-        mKeyDetector = new KeyDetector();
+        mKeyDetector = new KeyDetector(0);
         init();
     }
 
@@ -45,7 +45,7 @@ public class SuggestHelper {
             KeyboardId keyboardId) {
         mSuggest = new Suggest(context, dictionaryPath, startOffset, length, null);
         mKeyboard = new LatinKeyboard(context, keyboardId, keyboardId.mWidth);
-        mKeyDetector = new KeyDetector();
+        mKeyDetector = new KeyDetector(0);
         init();
     }