Merge "Support Persian Keyboard"
diff --git a/java/res/values-in/strings.xml b/java/res/values-in/strings.xml
index 1f03a05..f10d613 100644
--- a/java/res/values-in/strings.xml
+++ b/java/res/values-in/strings.xml
@@ -45,7 +45,7 @@
     <skip />
     <string name="key_preview_popup_dismiss_delay" msgid="6213164897443068248">"Tundaan singkir munculan kunci"</string>
     <string name="key_preview_popup_dismiss_no_delay" msgid="2096123151571458064">"Tanpa penundaan"</string>
-    <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Bawaan"</string>
+    <string name="key_preview_popup_dismiss_default_delay" msgid="2166964333903906734">"Default"</string>
     <string name="use_contacts_dict" msgid="4435317977804180815">"Sarankan nama Kenalan"</string>
     <string name="use_contacts_dict_summary" msgid="6599983334507879959">"Menggunakan nama dari Kenalan untuk saran dan koreksi"</string>
     <string name="enable_span_insert" msgid="7204653105667167620">"Aktifkan koreksi ulang"</string>
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index a726878..44c6a49 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -125,6 +125,7 @@
     /** Array of keys and icons in this keyboard */
     public final Key[] mKeys;
     public final Key[] mShiftKeys;
+    public final Key[] mAltCodeKeysWhileTyping;
     public final KeyboardIconsSet mIconsSet;
 
     private final HashMap<Integer, Key> mKeyCache = new HashMap<Integer, Key>();
@@ -148,6 +149,8 @@
 
         mKeys = params.mKeys.toArray(new Key[params.mKeys.size()]);
         mShiftKeys = params.mShiftKeys.toArray(new Key[params.mShiftKeys.size()]);
+        mAltCodeKeysWhileTyping = params.mAltCodeKeysWhileTyping.toArray(
+                new Key[params.mAltCodeKeysWhileTyping.size()]);
         mIconsSet = params.mIconsSet;
         mAdditionalProximityChars = params.mAdditionalProximityChars;
 
@@ -224,6 +227,7 @@
 
         public final ArrayList<Key> mKeys = new ArrayList<Key>();
         public final ArrayList<Key> mShiftKeys = new ArrayList<Key>();
+        public final ArrayList<Key> mAltCodeKeysWhileTyping = new ArrayList<Key>();
         public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet();
         // TODO: Should be in Key instead of Keyboard.Params?
         public final Map<Integer, List<Integer>> mAdditionalProximityChars =
@@ -305,12 +309,15 @@
             if (key.mCode == Keyboard.CODE_SHIFT) {
                 mShiftKeys.add(key);
             }
+            if (key.altCodeWhileTyping()) {
+                mAltCodeKeysWhileTyping.add(key);
+            }
         }
 
         private int mMaxHeightCount = 0;
         private int mMaxWidthCount = 0;
-        private final Map<Integer, Integer> mHeightHistogram = new HashMap<Integer, Integer>();
-        private final Map<Integer, Integer> mWidthHistogram = new HashMap<Integer, Integer>();
+        private final HashMap<Integer, Integer> mHeightHistogram = new HashMap<Integer, Integer>();
+        private final HashMap<Integer, Integer> mWidthHistogram = new HashMap<Integer, Integer>();
 
         private void clearHistogram() {
             mMostCommonKeyHeight = 0;
@@ -322,7 +329,8 @@
             mWidthHistogram.clear();
         }
 
-        private static int updateHistogramCounter(Map<Integer, Integer> histogram, Integer key) {
+        private static int updateHistogramCounter(HashMap<Integer, Integer> histogram,
+                Integer key) {
             final int count = (histogram.containsKey(key) ? histogram.get(key) : 0) + 1;
             histogram.put(key, count);
             return count;
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 316177f..607b33b 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -322,55 +322,74 @@
 
     private void setReleasedKeyGraphics(Key key) {
         mDrawingProxy.dismissKeyPreview(this);
-        if (key != null && key.isEnabled()) {
-            key.onReleased();
-            mDrawingProxy.invalidateKey(key);
+        if (key == null || !key.isEnabled()) {
+            return;
+        }
 
-            if (key.isShift()) {
-                for (final Key shiftKey : mKeyboard.mShiftKeys) {
-                    if (shiftKey != key) {
-                        shiftKey.onReleased();
-                        mDrawingProxy.invalidateKey(shiftKey);
-                    }
+        updateReleaseKeyGraphics(key);
+
+        if (key.isShift()) {
+            for (final Key shiftKey : mKeyboard.mShiftKeys) {
+                if (shiftKey != key) {
+                    updateReleaseKeyGraphics(shiftKey);
                 }
             }
+        }
 
-            if (key.altCodeWhileTyping()) {
-                final Key altKey = mKeyboard.getKey(key.mAltCode);
-                if (altKey != null) {
-                    altKey.onReleased();
-                    mDrawingProxy.invalidateKey(altKey);
+        if (key.altCodeWhileTyping()) {
+            final int altCode = key.mAltCode;
+            final Key altKey = mKeyboard.getKey(altCode);
+            if (altKey != null) {
+                updateReleaseKeyGraphics(altKey);
+            }
+            for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) {
+                if (k != key && k.mAltCode == altCode) {
+                    updateReleaseKeyGraphics(k);
                 }
             }
         }
     }
 
     private void setPressedKeyGraphics(Key key) {
-        if (key != null && key.isEnabled()) {
-            if (!key.noKeyPreview()) {
-                mDrawingProxy.showKeyPreview(this);
-            }
-            key.onPressed();
-            mDrawingProxy.invalidateKey(key);
+        if (key == null || !key.isEnabled()) {
+            return;
+        }
 
-            if (key.isShift()) {
-                for (final Key shiftKey : mKeyboard.mShiftKeys) {
-                    if (shiftKey != key) {
-                        shiftKey.onPressed();
-                        mDrawingProxy.invalidateKey(shiftKey);
-                    }
-                }
-            }
+        if (!key.noKeyPreview()) {
+            mDrawingProxy.showKeyPreview(this);
+        }
+        updatePressKeyGraphics(key);
 
-            if (key.altCodeWhileTyping() && mTimerProxy.isTyping()) {
-                final Key altKey = mKeyboard.getKey(key.mAltCode);
-                if (altKey != null) {
-                    // TODO: Show altKey's preview.
-                    altKey.onPressed();
-                    mDrawingProxy.invalidateKey(altKey);
+        if (key.isShift()) {
+            for (final Key shiftKey : mKeyboard.mShiftKeys) {
+                if (shiftKey != key) {
+                    updatePressKeyGraphics(shiftKey);
                 }
             }
         }
+
+        if (key.altCodeWhileTyping() && mTimerProxy.isTyping()) {
+            final int altCode = key.mAltCode;
+            final Key altKey = mKeyboard.getKey(altCode);
+            if (altKey != null) {
+                updatePressKeyGraphics(altKey);
+            }
+            for (final Key k : mKeyboard.mAltCodeKeysWhileTyping) {
+                if (k != key && k.mAltCode == altCode) {
+                    updatePressKeyGraphics(k);
+                }
+            }
+        }
+    }
+
+    private void updateReleaseKeyGraphics(Key key) {
+        key.onReleased();
+        mDrawingProxy.invalidateKey(key);
+    }
+
+    private void updatePressKeyGraphics(Key key) {
+        key.onPressed();
+        mDrawingProxy.invalidateKey(key);
     }
 
     public int getLastX() {