diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index d7cb5aa923f21f1d7c28a07762163a8796e7f6ca..51fb3701ccc613874b322b20e8def558844f9220 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 7e9e3ce1ad917e434e3d79d5eab81aa5443f0dde..b9ce4fb1f6c3d351227939ca746a4802adcfcd0e 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 73eab76f3e9b3afcd13193da3c03454bc1ba398f..035fb58f8fa32c74ce081d036f004efa28741a02 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);
     }
@@ -873,6 +881,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,
@@ -1067,6 +1076,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) {
@@ -1093,7 +1103,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();
@@ -1140,6 +1150,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 0d44ecdff35b46e31a944b121edb15d65c9c04cc..7847499cddc5470db1f1523a11803bbe9d3dfd7f 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<GesturePreviewTrail> 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<PreviewPlacerView> {
@@ -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 cd3177299b2ca643407de9b66522a07602e354ef..af270e1e4b810941e665f719f48a7ebf84f96faf 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];
+    }
 }