diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index e4ffa759964ecce6168aee6fc5a93a000df66d79..ae415d0ab1ae155095f459155a7b9b2fff922c2c 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -199,10 +199,12 @@ public class BinaryDictionary extends Dictionary {
         //final int commitPoint = codes.getCommitPoint();
         //codes.clearCommitPoint();
 
+        final InputPointers ips = codes.getInputPointers();
+
         return getSuggestionsNative(mNativeDict, proximityInfo.getNativeProximityInfo(),
-            codes.getXCoordinates(), codes.getYCoordinates(), emptyArray, emptyArray, mInputCodes,
-            codesSize, 0 /* unused */, false, prevWordCodePointArray, mUseFullEditDistance,
-            outputChars, scores, spaceIndices);
+            ips.getXCoordinates(), ips.getYCoordinates(), ips.getTimes(), ips.getPointerIds(),
+            mInputCodes, codesSize, 0 /* unused */, false, prevWordCodePointArray,
+            mUseFullEditDistance, outputChars, scores, spaceIndices);
     }
 
     public static float calcNormalizedScore(String before, String after, int score) {
diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
index cfecc664af29a2c8a6631904aac61d39fb3074a4..76213c0dabae550f6ded701952f03c647945d392 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java
@@ -268,8 +268,9 @@ public class ExpandableDictionary extends Dictionary {
         final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<SuggestedWordInfo>();
         mInputLength = codes.size();
         if (mCodes.length < mInputLength) mCodes = new int[mInputLength][];
-        final int[] xCoordinates = codes.getXCoordinates();
-        final int[] yCoordinates = codes.getYCoordinates();
+        final InputPointers ips = codes.getInputPointers();
+        final int[] xCoordinates = ips.getXCoordinates();
+        final int[] yCoordinates = ips.getYCoordinates();
         // Cache the codes so that we don't have to lookup an array list
         for (int i = 0; i < mInputLength; i++) {
             // TODO: Calculate proximity info here.
diff --git a/java/src/com/android/inputmethod/latin/InputPointers.java b/java/src/com/android/inputmethod/latin/InputPointers.java
new file mode 100644
index 0000000000000000000000000000000000000000..218243e9ff78c634f16d45b91891b77d4752f8ab
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/InputPointers.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2012 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.latin;
+
+import java.util.Arrays;
+
+public class InputPointers {
+    private final ScalableIntArray mXCoordinates = new ScalableIntArray();
+    private final ScalableIntArray mYCoordinates = new ScalableIntArray();
+    private final ScalableIntArray mPointerIds = new ScalableIntArray();
+    private final ScalableIntArray mTimes = new ScalableIntArray();
+
+    public void addPointer(int index, int x, int y, int pointerId, int time) {
+        mXCoordinates.add(index, x);
+        mYCoordinates.add(index, y);
+        mPointerIds.add(index, pointerId);
+        mTimes.add(index, time);
+    }
+
+    public void addPointer(int x, int y, int pointerId, int time) {
+        mXCoordinates.add(x);
+        mYCoordinates.add(y);
+        mPointerIds.add(pointerId);
+        mTimes.add(time);
+    }
+
+    public void set(InputPointers ip) {
+        mXCoordinates.set(ip.mXCoordinates);
+        mYCoordinates.set(ip.mYCoordinates);
+        mPointerIds.set(ip.mPointerIds);
+        mTimes.set(ip.mTimes);
+    }
+
+    public void copy(InputPointers ip) {
+        mXCoordinates.copy(ip.mXCoordinates);
+        mYCoordinates.copy(ip.mYCoordinates);
+        mPointerIds.copy(ip.mPointerIds);
+        mTimes.copy(ip.mTimes);
+    }
+
+    public void reset() {
+        mXCoordinates.reset();
+        mYCoordinates.reset();
+        mPointerIds.reset();
+        mTimes.reset();
+    }
+
+    public int getPointerSize() {
+        return mXCoordinates.getLength();
+    }
+
+    public int[] getXCoordinates() {
+        return mXCoordinates.mArray;
+    }
+
+    public int[] getYCoordinates() {
+        return mYCoordinates.mArray;
+    }
+
+    public int[] getPointerIds() {
+        return mPointerIds.mArray;
+    }
+
+    public int[] getTimes() {
+        return mTimes.mArray;
+    }
+
+    private static class ScalableIntArray {
+        private static final int DEFAULT_SIZE = BinaryDictionary.MAX_WORD_LENGTH;
+        private int[] mArray;
+        private int mLength;
+
+        public ScalableIntArray() {
+            reset();
+        }
+
+        public void add(int index, int val) {
+            if (mLength < index + 1) {
+                mLength = index;
+                add(val);
+            } else {
+                mArray[index] = val;
+            }
+        }
+
+        public void add(int val) {
+            if (mLength >= mArray.length) {
+                final int[] newArray = new int[mLength * 2];
+                System.arraycopy(mArray, 0, newArray, 0, mLength);
+            }
+            mArray[mLength] = val;
+            ++mLength;
+        }
+
+        public int getLength() {
+            return mLength;
+        }
+
+        public void reset() {
+            mArray = new int[DEFAULT_SIZE];
+            mLength = 0;
+        }
+
+        public int[] getPrimitiveArray() {
+            return mArray;
+        }
+
+        public void copy(ScalableIntArray ip) {
+            mArray = Arrays.copyOf(ip.mArray, ip.mArray.length);
+        }
+
+        public void set(ScalableIntArray ip) {
+            mArray = ip.mArray;
+            mLength = ip.mLength;
+        }
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/LastComposedWord.java b/java/src/com/android/inputmethod/latin/LastComposedWord.java
index 4e1f5fe9218ae4fadb18290b9c21f0804d17e37b..318aecb5038bbd6738ac196bb8dd13bb49a2deb1 100644
--- a/java/src/com/android/inputmethod/latin/LastComposedWord.java
+++ b/java/src/com/android/inputmethod/latin/LastComposedWord.java
@@ -41,26 +41,26 @@ public class LastComposedWord {
     public static final int NOT_A_SEPARATOR = -1;
 
     public final int[] mPrimaryKeyCodes;
-    public final int[] mXCoordinates;
-    public final int[] mYCoordinates;
     public final String mTypedWord;
     public final String mCommittedWord;
     public final int mSeparatorCode;
     public final CharSequence mPrevWord;
+    public final InputPointers mInputPointers = new InputPointers();
 
     private boolean mActive;
 
     public static final LastComposedWord NOT_A_COMPOSED_WORD =
-            new LastComposedWord(null, null, null, "", "", NOT_A_SEPARATOR, null);
+            new LastComposedWord(null, null, "", "", NOT_A_SEPARATOR, null);
 
     // Warning: this is using the passed objects as is and fully expects them to be
     // immutable. Do not fiddle with their contents after you passed them to this constructor.
-    public LastComposedWord(final int[] primaryKeyCodes, final int[] xCoordinates,
-            final int[] yCoordinates, final String typedWord, final String committedWord,
+    public LastComposedWord(final int[] primaryKeyCodes, final InputPointers inputPointers,
+            final String typedWord, final String committedWord,
             final int separatorCode, final CharSequence prevWord) {
         mPrimaryKeyCodes = primaryKeyCodes;
-        mXCoordinates = xCoordinates;
-        mYCoordinates = yCoordinates;
+        if (inputPointers != null) {
+            mInputPointers.copy(inputPointers);
+        }
         mTypedWord = typedWord;
         mCommittedWord = committedWord;
         mSeparatorCode = separatorCode;
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index bcd295d2587df1af35cb510e232b7886fc8753f9..98282f970276148253c427c1c9292268b5a4cd56 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -34,8 +34,7 @@ public class WordComposer {
     private static final int N = BinaryDictionary.MAX_WORD_LENGTH;
 
     private int[] mPrimaryKeyCodes;
-    private int[] mXCoordinates;
-    private int[] mYCoordinates;
+    private final InputPointers mInputPointers = new InputPointers();
     private StringBuilder mTypedWord;
     private CharSequence mAutoCorrection;
     private boolean mIsResumed;
@@ -54,8 +53,6 @@ public class WordComposer {
     public WordComposer() {
         mPrimaryKeyCodes = new int[N];
         mTypedWord = new StringBuilder(N);
-        mXCoordinates = new int[N];
-        mYCoordinates = new int[N];
         mAutoCorrection = null;
         mTrailingSingleQuotesCount = 0;
         mIsResumed = false;
@@ -69,8 +66,7 @@ public class WordComposer {
     public void init(WordComposer source) {
         mPrimaryKeyCodes = Arrays.copyOf(source.mPrimaryKeyCodes, source.mPrimaryKeyCodes.length);
         mTypedWord = new StringBuilder(source.mTypedWord);
-        mXCoordinates = Arrays.copyOf(source.mXCoordinates, source.mXCoordinates.length);
-        mYCoordinates = Arrays.copyOf(source.mYCoordinates, source.mYCoordinates.length);
+        mInputPointers.copy(source.mInputPointers);
         mCapsCount = source.mCapsCount;
         mIsFirstCharCapitalized = source.mIsFirstCharCapitalized;
         mAutoCapitalized = source.mAutoCapitalized;
@@ -116,12 +112,8 @@ public class WordComposer {
         return mPrimaryKeyCodes[index];
     }
 
-    public int[] getXCoordinates() {
-        return mXCoordinates;
-    }
-
-    public int[] getYCoordinates() {
-        return mYCoordinates;
+    public InputPointers getInputPointers() {
+        return mInputPointers;
     }
 
     private static boolean isFirstCharCapitalized(int index, int codePoint, boolean previous) {
@@ -157,8 +149,8 @@ public class WordComposer {
         if (newIndex < BinaryDictionary.MAX_WORD_LENGTH) {
             mPrimaryKeyCodes[newIndex] = primaryCode >= Keyboard.CODE_SPACE
                     ? Character.toLowerCase(primaryCode) : primaryCode;
-            mXCoordinates[newIndex] = keyX;
-            mYCoordinates[newIndex] = keyY;
+            // TODO: Set correct pointer id and time
+            mInputPointers.addPointer(newIndex, keyX, keyY, 0, 0);
         }
         mIsFirstCharCapitalized = isFirstCharCapitalized(
                 newIndex, primaryCode, mIsFirstCharCapitalized);
@@ -318,14 +310,11 @@ public class WordComposer {
         // or a DECIDED_WORD we may cancel the commit later; otherwise, we should deactivate
         // the last composed word to ensure this does not happen.
         final int[] primaryKeyCodes = mPrimaryKeyCodes;
-        final int[] xCoordinates = mXCoordinates;
-        final int[] yCoordinates = mYCoordinates;
         mPrimaryKeyCodes = new int[N];
-        mXCoordinates = new int[N];
-        mYCoordinates = new int[N];
         final LastComposedWord lastComposedWord = new LastComposedWord(primaryKeyCodes,
-                xCoordinates, yCoordinates, mTypedWord.toString(), committedWord, separatorCode,
+                mInputPointers, mTypedWord.toString(), committedWord, separatorCode,
                 prevWord);
+        mInputPointers.reset();
         if (type != LastComposedWord.COMMIT_TYPE_DECIDED_WORD
                 && type != LastComposedWord.COMMIT_TYPE_MANUAL_PICK) {
             lastComposedWord.deactivate();
@@ -339,8 +328,7 @@ public class WordComposer {
 
     public void resumeSuggestionOnLastComposedWord(final LastComposedWord lastComposedWord) {
         mPrimaryKeyCodes = lastComposedWord.mPrimaryKeyCodes;
-        mXCoordinates = lastComposedWord.mXCoordinates;
-        mYCoordinates = lastComposedWord.mYCoordinates;
+        mInputPointers.set(lastComposedWord.mInputPointers);
         mTypedWord.setLength(0);
         mTypedWord.append(lastComposedWord.mTypedWord);
         refreshSize();