diff --git a/java/res/values-sw600dp/config.xml b/java/res/values-sw600dp/config.xml
index 1dd93121d425e30fe927eeec5fe848ee50d985f7..35da3009f9883548d34fffed16fe0fcd25947e4d 100644
--- a/java/res/values-sw600dp/config.xml
+++ b/java/res/values-sw600dp/config.xml
@@ -24,14 +24,11 @@
     <bool name="config_enable_show_voice_key_option">false</bool>
     <bool name="config_enable_show_popup_on_keypress_option">false</bool>
     <bool name="config_enable_bigram_suggestions_option">false</bool>
-    <bool name="config_sliding_key_input_enabled">false</bool>
     <bool name="config_digit_more_keys_enabled">false</bool>
     <!-- Whether or not Popup on key press is enabled by default -->
     <bool name="config_default_popup_preview">false</bool>
     <bool name="config_default_sound_enabled">true</bool>
     <bool name="config_auto_correction_spacebar_led_enabled">false</bool>
-    <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false -->
-    <bool name="config_show_mini_keyboard_at_touched_point">true</bool>
     <!-- The language is never displayed if == 0, always displayed if < 0 -->
     <integer name="config_delay_before_fadeout_language_on_spacebar">1200</integer>
     <!-- Long pressing space will invoke IME switcher if > 0, never invoke IME switcher if == 0 -->
@@ -39,4 +36,10 @@
     <!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. -->
     <string name="config_default_keyboard_theme_id" translatable="false">5</string>
     <integer name="config_max_more_keys_column">5</integer>
+    <!--
+        Configuration for LatinKeyboardView
+    -->
+    <bool name="config_sliding_key_input_enabled">false</bool>
+    <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false -->
+    <bool name="config_show_mini_keyboard_at_touched_point">true</bool>
 </resources>
diff --git a/java/res/values-sw768dp/config.xml b/java/res/values-sw768dp/config.xml
index 06553a7c997aac8269988ee284831377b5a32eca..ddeadaf0f0f5b1abbfa6a249c9bea3430f817053 100644
--- a/java/res/values-sw768dp/config.xml
+++ b/java/res/values-sw768dp/config.xml
@@ -24,19 +24,22 @@
     <bool name="config_enable_show_voice_key_option">false</bool>
     <bool name="config_enable_show_popup_on_keypress_option">false</bool>
     <bool name="config_enable_bigram_suggestions_option">false</bool>
-    <bool name="config_sliding_key_input_enabled">false</bool>
     <bool name="config_digit_more_keys_enabled">false</bool>
     <!-- Whether or not Popup on key press is enabled by default -->
     <bool name="config_default_popup_preview">false</bool>
     <bool name="config_default_sound_enabled">true</bool>
     <bool name="config_auto_correction_spacebar_led_enabled">false</bool>
-    <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false -->
-    <bool name="config_show_mini_keyboard_at_touched_point">true</bool>
     <!-- Long pressing space will invoke IME switcher if > 0, never invoke IME switcher if == 0 -->
     <integer name="config_long_press_space_key_timeout">0</integer>
     <!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. -->
     <string name="config_default_keyboard_theme_id" translatable="false">5</string>
     <integer name="config_max_more_keys_column">5</integer>
+    <!--
+        Configuration for LatinKeyboardView
+    -->
+    <bool name="config_sliding_key_input_enabled">false</bool>
+    <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false -->
+    <bool name="config_show_mini_keyboard_at_touched_point">true</bool>
     <!--  Screen metrics for logging.
             0 = "mdpi phone screen"
             1 = "hdpi phone screen"
diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index 5824d1736f957488e7675e383a7fd3231f80f682..3f26cb64c1f1d7c2190e260eda3f8a0bbc672522 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -103,6 +103,8 @@
         <attr name="keyPreviewHeight" format="dimension" />
         <!-- Size of the text for key press feedback popup, int the proportion of key height -->
         <attr name="keyPreviewTextRatio" format="float" />
+        <!-- Delay after key releasing and key press feedback dismissing in millisecond -->
+        <attr name="keyPreviewLingerTimeout" format="integer" />
 
         <!-- Amount to offset the touch Y coordinate by, for bias correction. -->
         <attr name="verticalCorrection" format="dimension" />
@@ -130,6 +132,28 @@
         <attr name="spacebarTextRatio" format="fraction" />
         <attr name="spacebarTextColor" format="color" />
         <attr name="spacebarTextShadowColor" format="color" />
+        <!-- Key detection hysteresis distance. -->
+        <attr name="keyHysteresisDistance" format="dimension" />
+        <!-- Touch noise threshold time in millisecond -->
+        <attr name="touchNoiseThresholdTime" format="integer" />
+        <!-- Touch noise threshold distance in millimeter -->
+        <attr name="touchNoiseThresholdDistance" format="dimension" />
+        <!-- Sliding key input enable -->
+        <attr name="slidingKeyInputEnable" format="boolean" />
+        <!-- Key repeat start timeout -->
+        <attr name="keyRepeatStartTimeout" format="integer" />
+        <!-- Key repeat interval in millisecond. -->
+        <attr name="keyRepeatInterval" format="integer" />
+        <!-- Long press timeout of letter key in millisecond. -->
+        <attr name="longPressKeyTimeout" format="integer" />
+        <!-- Long press timeout of shift key in millisecond. -->
+        <attr name="longPressShiftKeyTimeout" format="integer" />
+        <!-- Long press timeout of space key in millisecond. -->
+        <attr name="longPressSpaceKeyTimeout" format="integer" />
+        <!-- Ignore special key timeout while typing in millisecond. -->
+        <attr name="ignoreSpecialKeyTimeout" format="integer" />
+        <!-- Mini-keyboard will shown at touched point. -->
+        <attr name="showMiniKeyboardAtTouchedPoint" format="boolean" />
     </declare-styleable>
 
     <declare-styleable name="SuggestionsView">
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
index 5e6804364f741f21f92f2df7e5d93940adf3d3a2..32041df7450d6d53c3a3532f7b6f9a72b66bf4a6 100644
--- a/java/res/values/config.xml
+++ b/java/res/values/config.xml
@@ -27,7 +27,6 @@
     <bool name="config_enable_bigram_suggestions_option">true</bool>
     <!-- TODO: Disable the following configuration for production. -->
     <bool name="config_enable_usability_study_mode_option">true</bool>
-    <bool name="config_sliding_key_input_enabled">true</bool>
     <bool name="config_digit_more_keys_enabled">true</bool>
     <!-- Whether or not Popup on key press is enabled by default -->
     <bool name="config_default_popup_preview">true</bool>
@@ -39,8 +38,6 @@
     <bool name="config_default_bigram_prediction">false</bool>
     <bool name="config_default_sound_enabled">false</bool>
     <bool name="config_default_vibration_enabled">true</bool>
-    <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false -->
-    <bool name="config_show_mini_keyboard_at_touched_point">false</bool>
     <!-- The language is never displayed if == 0, always displayed if < 0 -->
     <integer name="config_delay_before_fadeout_language_on_spacebar">1200</integer>
     <integer name="config_delay_update_suggestions">100</integer>
@@ -48,26 +45,38 @@
     <integer name="config_delay_update_shift_state">100</integer>
     <integer name="config_duration_of_fadeout_language_on_spacebar">50</integer>
     <integer name="config_final_fadeout_percentage_of_language_on_spacebar">50</integer>
-    <integer name="config_delay_before_preview">0</integer>
-    <integer name="config_delay_after_preview">70</integer>
     <integer name="config_mini_keyboard_fadein_anim_time">0</integer>
     <integer name="config_mini_keyboard_fadeout_anim_time">100</integer>
-    <integer name="config_delay_before_key_repeat_start">400</integer>
-    <integer name="config_key_repeat_interval">50</integer>
     <integer name="config_keyboard_grid_width">32</integer>
     <integer name="config_keyboard_grid_height">16</integer>
+    <integer name="config_double_spaces_turn_into_period_timeout">1100</integer>
+    <!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. -->
+    <string name="config_default_keyboard_theme_id" translatable="false">5</string>
+    <integer name="config_max_more_keys_column">5</integer>
+    <!--
+         Configuration for KeyboardView
+    -->
+    <integer name="config_key_preview_linger_timeout">70</integer>
+    <!--
+         Configuration for LatinKeyboardView
+    -->
+    <dimen name="config_key_hysteresis_distance">0.05in</dimen>
+    <integer name="config_touch_noise_threshold_time">40</integer>
+    <dimen name="config_touch_noise_threshold_distance">2.0mm</dimen>
+    <bool name="config_sliding_key_input_enabled">true</bool>
+    <integer name="config_key_repeat_start_timeout">400</integer>
+    <integer name="config_key_repeat_interval">50</integer>
     <integer name="config_long_press_key_timeout">400</integer>
     <!-- Long pressing shift will invoke caps-lock if > 0, never invoke caps-lock if == 0 -->
     <integer name="config_long_press_shift_key_timeout">1200</integer>
     <!-- Long pressing space will invoke IME switcher if > 0, never invoke IME switcher if == 0 -->
     <integer name="config_long_press_space_key_timeout">@integer/config_long_press_key_timeout</integer>
-    <integer name="config_touch_noise_threshold_millis">40</integer>
-    <integer name="config_double_spaces_turn_into_period_timeout">1100</integer>
     <integer name="config_ignore_special_key_timeout">700</integer>
-    <dimen name="config_touch_noise_threshold_distance">2.0mm</dimen>
-    <!-- This configuration is the index of the array {@link KeyboardSwitcher.KEYBOARD_THEMES}. -->
-    <string name="config_default_keyboard_theme_id" translatable="false">5</string>
-    <integer name="config_max_more_keys_column">5</integer>
+    <!-- Showing mini keyboard, just above the touched point if true, aligned to the key if false -->
+    <bool name="config_show_mini_keyboard_at_touched_point">false</bool>
+    <!--
+        Configuration for auto correction
+     -->
     <string-array name="auto_correction_threshold_values" translatable="false">
         <!-- Off, When auto correction setting is Off, this value is not used. -->
         <item></item>
diff --git a/java/res/values/dimens.xml b/java/res/values/dimens.xml
index e46ff7718f3167df9bc731004ccd35886817ab95..95c4e5b8b6ab53d93ba510256c24a1500b86411d 100644
--- a/java/res/values/dimens.xml
+++ b/java/res/values/dimens.xml
@@ -96,6 +96,4 @@
     <dimen name="more_suggestions_hint_text_size">27dip</dimen>
     <integer name="suggestions_count_in_strip">3</integer>
     <integer name="center_suggestion_percentile">36</integer>
-
-    <dimen name="key_hysteresis_distance">0.05in</dimen>
 </resources>
diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml
index c4e39e35705a2c9197ec42a4c8afc3827a75d86e..69637d75ad2751730a4f0b0fac149e362039ba20 100644
--- a/java/res/values/styles.xml
+++ b/java/res/values/styles.xml
@@ -59,11 +59,24 @@
         <item name="keyPreviewOffset">@dimen/key_preview_offset</item>
         <item name="keyPreviewHeight">@dimen/key_preview_height</item>
         <item name="keyPreviewTextRatio">@fraction/key_preview_text_ratio</item>
+        <item name="keyPreviewLingerTimeout">@integer/config_key_preview_linger_timeout</item>
         <item name="moreKeysLayout">@layout/mini_keyboard</item>
         <item name="verticalCorrection">@dimen/keyboard_vertical_correction</item>
         <item name="shadowColor">#BB000000</item>
         <item name="shadowRadius">2.75</item>
         <item name="backgroundDimAmount">0.5</item>
+        <!-- Common attributes of LatinKeyboardView -->
+        <item name="keyHysteresisDistance">@dimen/config_key_hysteresis_distance</item>
+        <item name="touchNoiseThresholdTime">@integer/config_touch_noise_threshold_time</item>
+        <item name="touchNoiseThresholdDistance">@dimen/config_touch_noise_threshold_distance</item>
+        <item name="slidingKeyInputEnable">@bool/config_sliding_key_input_enabled</item>
+        <item name="keyRepeatStartTimeout">@integer/config_key_repeat_start_timeout</item>
+        <item name="keyRepeatInterval">@integer/config_key_repeat_interval</item>
+        <item name="longPressKeyTimeout">@integer/config_long_press_key_timeout</item>
+        <item name="longPressShiftKeyTimeout">@integer/config_long_press_shift_key_timeout</item>
+        <item name="longPressSpaceKeyTimeout">@integer/config_long_press_space_key_timeout</item>
+        <item name="ignoreSpecialKeyTimeout">@integer/config_ignore_special_key_timeout</item>
+        <item name="showMiniKeyboardAtTouchedPoint">@bool/config_show_mini_keyboard_at_touched_point</item>
     </style>
     <style
         name="LatinKeyboardView"
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index afcf51059963dea8fe742b1f8eadb1e7ee2ded1c..6f4ef2580c264b5e21d2784a087630daf4f705e4 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -17,7 +17,6 @@
 package com.android.inputmethod.keyboard;
 
 import android.content.Context;
-import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -39,7 +38,6 @@ import android.widget.RelativeLayout;
 import android.widget.TextView;
 
 import com.android.inputmethod.compat.FrameLayoutCompatUtils;
-import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
 import com.android.inputmethod.latin.LatinImeLogger;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
@@ -103,7 +101,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
     private final int mKeyPreviewLayoutId;
     protected final KeyPreviewDrawParams mKeyPreviewDrawParams;
     private boolean mShowKeyPreviewPopup = true;
-    private final int mDelayBeforePreview;
     private int mDelayAfterPreview;
     private ViewGroup mPreviewPlacer;
 
@@ -135,8 +132,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
     private final DrawingHandler mDrawingHandler = new DrawingHandler(this);
 
     public static class DrawingHandler extends StaticInnerHandlerWrapper<KeyboardView> {
-        private static final int MSG_SHOW_KEY_PREVIEW = 1;
-        private static final int MSG_DISMISS_KEY_PREVIEW = 2;
+        private static final int MSG_DISMISS_KEY_PREVIEW = 1;
 
         public DrawingHandler(KeyboardView outerInstance) {
             super(outerInstance);
@@ -148,35 +144,12 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
             if (keyboardView == null) return;
             final PointerTracker tracker = (PointerTracker) msg.obj;
             switch (msg.what) {
-            case MSG_SHOW_KEY_PREVIEW:
-                keyboardView.showKey(tracker);
-                break;
             case MSG_DISMISS_KEY_PREVIEW:
                 tracker.getKeyPreviewText().setVisibility(View.INVISIBLE);
                 break;
             }
         }
 
-        public void showKeyPreview(long delay, PointerTracker tracker) {
-            removeMessages(MSG_SHOW_KEY_PREVIEW);
-            final KeyboardView keyboardView = getOuterInstance();
-            if (keyboardView == null) return;
-            if (tracker.getKeyPreviewText().getVisibility() == VISIBLE || delay == 0) {
-                // Show right away, if it's already visible and finger is moving around
-                keyboardView.showKey(tracker);
-            } else {
-                sendMessageDelayed(obtainMessage(MSG_SHOW_KEY_PREVIEW, tracker), delay);
-            }
-        }
-
-        public void cancelShowKeyPreview(PointerTracker tracker) {
-            removeMessages(MSG_SHOW_KEY_PREVIEW, tracker);
-        }
-
-        public void cancelAllShowKeyPreviews() {
-            removeMessages(MSG_SHOW_KEY_PREVIEW);
-        }
-
         public void dismissKeyPreview(long delay, PointerTracker tracker) {
             sendMessageDelayed(obtainMessage(MSG_DISMISS_KEY_PREVIEW, tracker), delay);
         }
@@ -190,7 +163,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
         }
 
         public void cancelAllMessages() {
-            cancelAllShowKeyPreviews();
             cancelAllDismissKeyPreviews();
         }
     }
@@ -295,6 +267,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
         public final int mPreviewOffset;
         public final int mPreviewHeight;
         public final Typeface mKeyTextStyle;
+        public final int mLingerTimeout;
 
         private final float mPreviewTextRatio;
         private final float mKeyLetterRatio;
@@ -324,6 +297,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
                     R.styleable.KeyboardView_keyPreviewHeight, 80);
             mPreviewTextRatio = getRatio(a, R.styleable.KeyboardView_keyPreviewTextRatio);
             mPreviewTextColor = a.getColor(R.styleable.KeyboardView_keyPreviewTextColor, 0);
+            mLingerTimeout = a.getInt(R.styleable.KeyboardView_keyPreviewLingerTimeout, 0);
 
             mKeyLetterRatio = keyDrawParams.mKeyLetterRatio;
             mKeyTextStyle = keyDrawParams.mKeyTextStyle;
@@ -363,10 +337,7 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
         mBackgroundDimAmount = a.getFloat(R.styleable.KeyboardView_backgroundDimAmount, 0.5f);
         a.recycle();
 
-        final Resources res = getResources();
-
-        mDelayBeforePreview = res.getInteger(R.integer.config_delay_before_preview);
-        mDelayAfterPreview = res.getInteger(R.integer.config_delay_after_preview);
+        mDelayAfterPreview = mKeyPreviewDrawParams.mLingerTimeout;
 
         mPaint.setAntiAlias(true);
         mPaint.setTextAlign(Align.CENTER);
@@ -386,8 +357,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
      * @param keyboard the keyboard to display in this view
      */
     public void setKeyboard(Keyboard keyboard) {
-        // Remove any pending dismissing preview
-        mDrawingHandler.cancelAllShowKeyPreviews();
+        // Remove any pending messages.
+        mDrawingHandler.cancelAllMessages();
         if (mKeyboard != null) {
             PointerTracker.dismissAllKeyPreviews();
         }
@@ -841,18 +812,12 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
     @Override
     public void showKeyPreview(PointerTracker tracker) {
         if (mShowKeyPreviewPopup) {
-            mDrawingHandler.showKeyPreview(mDelayBeforePreview, tracker);
+            showKey(tracker);
         }
     }
 
-    @Override
-    public void cancelShowKeyPreview(PointerTracker tracker) {
-        mDrawingHandler.cancelShowKeyPreview(tracker);
-    }
-
     @Override
     public void dismissKeyPreview(PointerTracker tracker) {
-        mDrawingHandler.cancelShowKeyPreview(tracker);
         mDrawingHandler.dismissKeyPreview(mDelayAfterPreview, tracker);
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index f5b282df34eaec7a01644920f98cf617e2d60dc3..aee356a0c7c85e0ed44d11a6f649a2e0ca8c6f70 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -18,7 +18,6 @@ package com.android.inputmethod.keyboard;
 
 import android.content.Context;
 import android.content.pm.PackageManager;
-import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -103,6 +102,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
             new WeakHashMap<Key, MoreKeysPanel>();
     private final boolean mConfigShowMiniKeyboardAtTouchedPoint;
 
+    private final PointerTrackerParams mPointerTrackerParams;
     private final boolean mIsSpacebarTriggeringPopupByLongPress;
     private final SuddenJumpingTouchEventHandler mTouchScreenRegulator;
 
@@ -114,7 +114,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
     // To detect double tap.
     protected GestureDetector mGestureDetector;
 
-    private final KeyTimerHandler mKeyTimerHandler = new KeyTimerHandler(this);
+    private final KeyTimerHandler mKeyTimerHandler;
 
     private static class KeyTimerHandler extends StaticInnerHandlerWrapper<LatinKeyboardView>
             implements TimerProxy {
@@ -126,11 +126,9 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
         private final int mKeyRepeatInterval;
         private boolean mInKeyRepeat;
 
-        public KeyTimerHandler(LatinKeyboardView outerInstance) {
+        public KeyTimerHandler(LatinKeyboardView outerInstance, int keyRepeatInterval) {
             super(outerInstance);
-            // TODO: This should be the attribute of LatinKeyboardView.
-            final Resources res = outerInstance.getContext().getResources();
-            mKeyRepeatInterval = res.getInteger(R.integer.config_key_repeat_interval);
+            mKeyRepeatInterval = keyRepeatInterval;
         }
 
         @Override
@@ -253,6 +251,49 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
         }
     }
 
+    public static class PointerTrackerParams {
+        public final boolean mSlidingKeyInputEnabled;
+        public final int mKeyRepeatStartTimeout;
+        public final int mLongPressKeyTimeout;
+        public final int mLongPressShiftKeyTimeout;
+        public final int mLongPressSpaceKeyTimeout;
+        public final int mIgnoreSpecialKeyTimeout;
+        public final int mTouchNoiseThresholdTime;
+        public final float mTouchNoiseThresholdDistance;
+
+        public static final PointerTrackerParams DEFAULT = new PointerTrackerParams();
+
+        private PointerTrackerParams() {
+            mSlidingKeyInputEnabled = false;
+            mKeyRepeatStartTimeout = 0;
+            mLongPressKeyTimeout = 0;
+            mLongPressShiftKeyTimeout = 0;
+            mLongPressSpaceKeyTimeout = 0;
+            mIgnoreSpecialKeyTimeout = 0;
+            mTouchNoiseThresholdTime =0;
+            mTouchNoiseThresholdDistance = 0;
+        }
+
+        public PointerTrackerParams(TypedArray latinKeyboardViewAttr) {
+            mSlidingKeyInputEnabled = latinKeyboardViewAttr.getBoolean(
+                    R.styleable.LatinKeyboardView_slidingKeyInputEnable, false);
+            mKeyRepeatStartTimeout = latinKeyboardViewAttr.getInt(
+                    R.styleable.LatinKeyboardView_keyRepeatStartTimeout, 0);
+            mLongPressKeyTimeout = latinKeyboardViewAttr.getInt(
+                    R.styleable.LatinKeyboardView_longPressKeyTimeout, 0);
+            mLongPressShiftKeyTimeout = latinKeyboardViewAttr.getInt(
+                    R.styleable.LatinKeyboardView_longPressShiftKeyTimeout, 0);
+            mLongPressSpaceKeyTimeout = latinKeyboardViewAttr.getInt(
+                    R.styleable.LatinKeyboardView_longPressSpaceKeyTimeout, 0);
+            mIgnoreSpecialKeyTimeout = latinKeyboardViewAttr.getInt(
+                    R.styleable.LatinKeyboardView_ignoreSpecialKeyTimeout, 0);
+            mTouchNoiseThresholdTime = latinKeyboardViewAttr.getInt(
+                    R.styleable.LatinKeyboardView_touchNoiseThresholdTime, 0);
+            mTouchNoiseThresholdDistance = latinKeyboardViewAttr.getDimension(
+                    R.styleable.LatinKeyboardView_touchNoiseThresholdDistance, 0);
+        }
+    }
+
     public LatinKeyboardView(Context context, AttributeSet attrs) {
         this(context, attrs, R.attr.latinKeyboardViewStyle);
     }
@@ -262,14 +303,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
 
         mTouchScreenRegulator = new SuddenJumpingTouchEventHandler(getContext(), this);
 
-        final Resources res = getResources();
-        // TODO: This should be the attribute of LatinKeyboardView.
-        mConfigShowMiniKeyboardAtTouchedPoint = res.getBoolean(
-                R.bool.config_show_mini_keyboard_at_touched_point);
-        // TODO: This should be the attribute of LatinKeyboardView.
-        final float keyHysteresisDistance = res.getDimension(R.dimen.key_hysteresis_distance);
-        mKeyDetector = new KeyDetector(keyHysteresisDistance);
-
         final boolean ignoreMultitouch = true;
         mGestureDetector = new GestureDetector(
                 getContext(), new DoubleTapListener(), null, ignoreMultitouch);
@@ -280,11 +313,6 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
 
         PointerTracker.init(mHasDistinctMultitouch, getContext());
 
-        // TODO: This should be the attribute of LatinKeyboardView.
-        final int longPressSpaceKeyTimeout =
-                res.getInteger(R.integer.config_long_press_space_key_timeout);
-        mIsSpacebarTriggeringPopupByLongPress = (longPressSpaceKeyTimeout > 0);
-
         final TypedArray a = context.obtainStyledAttributes(
                 attrs, R.styleable.LatinKeyboardView, defStyle, R.style.LatinKeyboardView);
         mAutoCorrectionSpacebarLedEnabled = a.getBoolean(
@@ -296,7 +324,22 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
         mSpacebarTextColor = a.getColor(R.styleable.LatinKeyboardView_spacebarTextColor, 0);
         mSpacebarTextShadowColor = a.getColor(
                 R.styleable.LatinKeyboardView_spacebarTextShadowColor, 0);
+
+        mPointerTrackerParams = new PointerTrackerParams(a);
+        mIsSpacebarTriggeringPopupByLongPress = (
+                mPointerTrackerParams.mLongPressSpaceKeyTimeout > 0);
+
+        final float keyHysteresisDistance = a.getDimension(
+                R.styleable.LatinKeyboardView_keyHysteresisDistance, 0);
+        mKeyDetector = new KeyDetector(keyHysteresisDistance);
+        final int keyRepeatInterval = a.getInt(
+                R.styleable.LatinKeyboardView_keyRepeatInterval, 0);
+        mKeyTimerHandler = new KeyTimerHandler(this, keyRepeatInterval);
+        mConfigShowMiniKeyboardAtTouchedPoint = a.getBoolean(
+                R.styleable.LatinKeyboardView_showMiniKeyboardAtTouchedPoint, false);
         a.recycle();
+
+        PointerTracker.setParameters(mPointerTrackerParams);
     }
 
     public void startIgnoringDoubleTap() {
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 274bd0b31329d914e38cc5ad29698c9ff1565f4b..a75b8f9e6d7fa85ec7ff6e9fb4380deab55655b0 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -17,7 +17,6 @@
 package com.android.inputmethod.keyboard;
 
 import android.content.Context;
-import android.content.res.Resources;
 import android.os.SystemClock;
 import android.util.Log;
 import android.view.MotionEvent;
@@ -25,7 +24,6 @@ import android.widget.TextView;
 
 import com.android.inputmethod.keyboard.internal.PointerTrackerQueue;
 import com.android.inputmethod.latin.LatinImeLogger;
-import com.android.inputmethod.latin.R;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -69,7 +67,6 @@ public class PointerTracker {
         public void invalidateKey(Key key);
         public TextView inflateKeyPreviewText();
         public void showKeyPreview(PointerTracker tracker);
-        public void cancelShowKeyPreview(PointerTracker tracker);
         public void dismissKeyPreview(PointerTracker tracker);
     }
 
@@ -98,14 +95,8 @@ public class PointerTracker {
     }
 
     private static KeyboardSwitcher sKeyboardSwitcher;
-    private static boolean sConfigSlidingKeyInputEnabled;
-    // Timing constants
-    private static int sDelayBeforeKeyRepeatStart;
-    private static int sLongPressKeyTimeout;
-    private static int sLongPressShiftKeyTimeout;
-    private static int sLongPressSpaceKeyTimeout;
-    private static int sIgnoreSpecialKeyTimeout;
-    private static int sTouchNoiseThresholdMillis;
+    // Parameters for pointer handling.
+    private static LatinKeyboardView.PointerTrackerParams sParams;
     private static int sTouchNoiseThresholdDistanceSquared;
 
     private static final List<PointerTracker> sTrackers = new ArrayList<PointerTracker>();
@@ -169,20 +160,14 @@ public class PointerTracker {
             sPointerTrackerQueue = null;
         }
 
-        final Resources res = context.getResources();
-        sConfigSlidingKeyInputEnabled = res.getBoolean(R.bool.config_sliding_key_input_enabled);
-        sDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start);
-        sLongPressKeyTimeout = res.getInteger(R.integer.config_long_press_key_timeout);
-        sLongPressShiftKeyTimeout = res.getInteger(R.integer.config_long_press_shift_key_timeout);
-        sLongPressSpaceKeyTimeout = res.getInteger(R.integer.config_long_press_space_key_timeout);
-        sIgnoreSpecialKeyTimeout = res.getInteger(R.integer.config_ignore_special_key_timeout);
-        sTouchNoiseThresholdMillis = res.getInteger(R.integer.config_touch_noise_threshold_millis);
+        setParameters(LatinKeyboardView.PointerTrackerParams.DEFAULT);
+        sKeyboardSwitcher = KeyboardSwitcher.getInstance();
+    }
 
-        final float touchNoiseThresholdDistance = res.getDimension(
-                R.dimen.config_touch_noise_threshold_distance);
+    public static void setParameters(LatinKeyboardView.PointerTrackerParams params) {
+        sParams = params;
         sTouchNoiseThresholdDistanceSquared = (int)(
-                touchNoiseThresholdDistance * touchNoiseThresholdDistance);
-        sKeyboardSwitcher = KeyboardSwitcher.getInstance();
+                params.mTouchNoiseThresholdDistance * params.mTouchNoiseThresholdDistance);
     }
 
     public static PointerTracker getPointerTracker(final int id, KeyEventHandler handler) {
@@ -278,7 +263,7 @@ public class PointerTracker {
                 mListener.onCodeInput(code, keyCodes, x, y);
             }
             if (!key.altCodeWhileTyping() && !key.isModifier()) {
-                mTimerProxy.startKeyTypedTimer(sIgnoreSpecialKeyTimeout);
+                mTimerProxy.startKeyTypedTimer(sParams.mIgnoreSpecialKeyTimeout);
             }
         }
     }
@@ -453,7 +438,7 @@ public class PointerTracker {
         setKeyDetectorInner(handler.getKeyDetector());
         // Naive up-to-down noise filter.
         final long deltaT = eventTime - mUpTime;
-        if (deltaT < sTouchNoiseThresholdMillis) {
+        if (deltaT < sParams.mTouchNoiseThresholdTime) {
             final int dx = x - mLastX;
             final int dy = y - mLastY;
             final int distanceSquared = (dx * dx + dy * dy);
@@ -483,7 +468,7 @@ public class PointerTracker {
         Key key = onDownKey(x, y, eventTime);
         // Sliding key is allowed when 1) enabled by configuration, 2) this pointer starts sliding
         // from modifier key, or 3) this pointer's KeyDetector always allows sliding input.
-        mIsAllowedSlidingKeyInput = sConfigSlidingKeyInputEnabled
+        mIsAllowedSlidingKeyInput = sParams.mSlidingKeyInputEnabled
                 || (key != null && key.isModifier())
                 || mKeyDetector.alwaysAllowsSlidingInput();
         mKeyboardLayoutHasBeenChanged = false;
@@ -620,7 +605,6 @@ public class PointerTracker {
 
     private void onUpEventInternal(int x, int y, long eventTime) {
         mTimerProxy.cancelKeyTimers();
-        mDrawingProxy.cancelShowKeyPreview(this);
         mIsInSlidingKeyInput = false;
         final int keyX, keyY;
         if (isMajorEnoughMoveToBeOnNewKey(x, y, onMoveKey(x, y))) {
@@ -673,7 +657,6 @@ public class PointerTracker {
 
     private void onCancelEventInternal() {
         mTimerProxy.cancelKeyTimers();
-        mDrawingProxy.cancelShowKeyPreview(this);
         setReleasedKeyGraphics(mCurrentKey);
         mIsInSlidingKeyInput = false;
         if (mIsShowingMoreKeysPanel) {
@@ -685,7 +668,7 @@ public class PointerTracker {
     private void startRepeatKey(Key key) {
         if (key != null && key.isRepeatable()) {
             onRepeatKey(key);
-            mTimerProxy.startKeyRepeatTimer(sDelayBeforeKeyRepeatStart, this);
+            mTimerProxy.startKeyRepeatTimer(sParams.mKeyRepeatStartTimeout, this);
             mIsRepeatableKey = true;
         } else {
             mIsRepeatableKey = false;
@@ -715,12 +698,12 @@ public class PointerTracker {
     private void startLongPressTimer(Key key) {
         if (key == null) return;
         if (key.mCode == Keyboard.CODE_SHIFT) {
-            if (sLongPressShiftKeyTimeout > 0) {
-                mTimerProxy.startLongPressTimer(sLongPressShiftKeyTimeout, this);
+            if (sParams.mLongPressShiftKeyTimeout > 0) {
+                mTimerProxy.startLongPressTimer(sParams.mLongPressShiftKeyTimeout, this);
             }
         } else if (key.mCode == Keyboard.CODE_SPACE) {
-            if (sLongPressSpaceKeyTimeout > 0) {
-                mTimerProxy.startLongPressTimer(sLongPressSpaceKeyTimeout, this);
+            if (sParams.mLongPressSpaceKeyTimeout > 0) {
+                mTimerProxy.startLongPressTimer(sParams.mLongPressSpaceKeyTimeout, this);
             }
         } else if (key.hasUppercaseLetter() && mKeyboard.isManualTemporaryUpperCase()) {
             // We need not start long press timer on the key which has manual temporary upper case
@@ -728,9 +711,9 @@ public class PointerTracker {
             return;
         } else if (sKeyboardSwitcher.isInMomentarySwitchState()) {
             // We use longer timeout for sliding finger input started from the symbols mode key.
-            mTimerProxy.startLongPressTimer(sLongPressKeyTimeout * 3, this);
+            mTimerProxy.startLongPressTimer(sParams.mLongPressKeyTimeout * 3, this);
         } else {
-            mTimerProxy.startLongPressTimer(sLongPressKeyTimeout, this);
+            mTimerProxy.startLongPressTimer(sParams.mLongPressKeyTimeout, this);
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 5af21452aaef75ba9beeec7815fae7e691cea23c..d32310096fad06293b157674bf026f1f25b527ec 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -218,7 +218,7 @@ public class Settings extends InputMethodSettingsActivity
                 res.getString(R.string.key_preview_popup_dismiss_default_delay),
         };
         final String popupDismissDelayDefaultValue = Integer.toString(res.getInteger(
-                R.integer.config_delay_after_preview));
+                R.integer.config_key_preview_linger_timeout));
         mKeyPreviewPopupDismissDelay.setEntries(entries);
         mKeyPreviewPopupDismissDelay.setEntryValues(
                 new String[] { "0", popupDismissDelayDefaultValue });
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index 0ae28d3fcc70185ec58917b08791cfe90a259742..e6ef3962e8828e01097e3e015894b559d3761d48 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -124,7 +124,7 @@ public class SettingsValues {
         mUsabilityStudyMode = getUsabilityStudyMode(prefs);
         mKeyPreviewPopupDismissDelayRawValue = prefs.getString(
                 Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
-                Integer.toString(res.getInteger(R.integer.config_delay_after_preview)));
+                Integer.toString(res.getInteger(R.integer.config_key_preview_linger_timeout)));
         mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true);
         mAutoCorrectEnabled = isAutoCorrectEnabled(res, mAutoCorrectionThresholdRawValue);
         mBigramSuggestionEnabled = mAutoCorrectEnabled
@@ -234,7 +234,8 @@ public class SettingsValues {
             Resources resources) {
         // TODO: use mKeyPreviewPopupDismissDelayRawValue instead of reading it again here.
         return Integer.parseInt(sp.getString(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
-                Integer.toString(resources.getInteger(R.integer.config_delay_after_preview))));
+                Integer.toString(resources.getInteger(
+                        R.integer.config_key_preview_linger_timeout))));
     }
 
     private static boolean isBigramSuggestionEnabled(final SharedPreferences sp,