diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml
index ae47c1f82b564481eeafe5c1083b1573998798d5..b11e25bc3956fa3304aaa66d39d526c18c5b9ef3 100644
--- a/java/res/values/attrs.xml
+++ b/java/res/values/attrs.xml
@@ -201,6 +201,7 @@
             <!-- This should be aligned with Key.ACTION_FLAGS_* -->
             <flag name="isRepeatable" value="0x01" />
             <flag name="noKeyPreview" value="0x02" />
+            <flag name="ignoreWhileTyping" value="0x04" />
         </attr>
         <!-- The string of characters to output when this key is pressed. -->
         <attr name="keyOutputText" format="string" />
diff --git a/java/res/xml-sw600dp/kbd_key_styles.xml b/java/res/xml-sw600dp/kbd_key_styles.xml
index 1dc932ad86a376def32f4bc468083019d8068c4c..5e9a88dd717404e786903b36ccd6d126ed71c504 100644
--- a/java/res/xml-sw600dp/kbd_key_styles.xml
+++ b/java/res/xml-sw600dp/kbd_key_styles.xml
@@ -77,13 +77,13 @@
         latin:styleName="shortcutKeyStyle"
         latin:code="@integer/key_shortcut"
         latin:keyIcon="iconShortcutKey"
-        latin:keyActionFlags="noKeyPreview"
+        latin:keyActionFlags="noKeyPreview|ignoreWhileTyping"
         latin:parentStyle="f2PopupStyle" />
     <key-style
         latin:styleName="settingsKeyStyle"
         latin:code="@integer/key_settings"
         latin:keyIcon="iconSettingsKey"
-        latin:keyActionFlags="noKeyPreview"
+        latin:keyActionFlags="noKeyPreview|ignoreWhileTyping"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="tabKeyStyle"
diff --git a/java/res/xml-sw768dp/kbd_key_styles.xml b/java/res/xml-sw768dp/kbd_key_styles.xml
index 0d8907a2fa8802d8c0916b40ab732a82cf889a89..499728d677ffd9bec2f47d5398fe3903e60b0cee 100644
--- a/java/res/xml-sw768dp/kbd_key_styles.xml
+++ b/java/res/xml-sw768dp/kbd_key_styles.xml
@@ -55,17 +55,17 @@
         latin:keyLabelFlags="hasPopupHint"
         latin:moreKeys="@string/more_keys_for_smiley"
         latin:maxMoreKeysColumn="5" />
-    <key-style
-        latin:styleName="settingsKeyStyle"
-        latin:code="@integer/key_settings"
-        latin:keyIcon="iconSettingsKey"
-        latin:keyActionFlags="noKeyPreview"
-        latin:backgroundType="functional" />
     <key-style
         latin:styleName="shortcutKeyStyle"
         latin:code="@integer/key_shortcut"
         latin:keyIcon="iconShortcutKey"
-        latin:keyActionFlags="noKeyPreview"
+        latin:keyActionFlags="noKeyPreview|ignoreWhileTyping"
+        latin:backgroundType="functional" />
+    <key-style
+        latin:styleName="settingsKeyStyle"
+        latin:code="@integer/key_settings"
+        latin:keyIcon="iconSettingsKey"
+        latin:keyActionFlags="noKeyPreview|ignoreWhileTyping"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="tabKeyStyle"
diff --git a/java/res/xml/kbd_key_styles.xml b/java/res/xml/kbd_key_styles.xml
index 5aa8811fdd44db65fd324039b7c2fb0294af6f8d..835269a4ad246b42801139ea8bc95f205c3da8f0 100644
--- a/java/res/xml/kbd_key_styles.xml
+++ b/java/res/xml/kbd_key_styles.xml
@@ -163,13 +163,13 @@
         latin:styleName="shortcutKeyStyle"
         latin:code="@integer/key_shortcut"
         latin:keyIcon="iconShortcutKey"
-        latin:keyActionFlags="noKeyPreview"
+        latin:keyActionFlags="noKeyPreview|ignoreWhileTyping"
         latin:parentStyle="f1PopupStyle" />
     <key-style
         latin:styleName="settingsKeyStyle"
         latin:code="@integer/key_settings"
         latin:keyIcon="iconSettingsKey"
-        latin:keyActionFlags="noKeyPreview"
+        latin:keyActionFlags="noKeyPreview|ignoreWhileTyping"
         latin:backgroundType="functional" />
     <key-style
         latin:styleName="tabKeyStyle"
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index 15c41a9f2cb939474913aa7881ee4080623894f5..ce5f29d73e708eab63f755a3434cf753fd118ddd 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -108,6 +108,7 @@ public class Key {
     private final int mActionFlags;
     private static final int ACTION_FLAGS_IS_REPEATABLE = 0x01;
     private static final int ACTION_FLAGS_NO_KEY_PREVIEW = 0x02;
+    private static final int ACTION_FLAGS_IGNORE_WHILE_TYPING = 0x04;
 
     /** The current pressed state of this key */
     private boolean mPressed;
@@ -325,6 +326,10 @@ public class Key {
         return (mActionFlags & ACTION_FLAGS_NO_KEY_PREVIEW) != 0;
     }
 
+    public boolean ignoreWhileTyping() {
+        return (mActionFlags & ACTION_FLAGS_IGNORE_WHILE_TYPING) != 0;
+    }
+
     public Typeface selectTypeface(Typeface defaultTypeface) {
         // TODO: Handle "bold" here too?
         if ((mLabelFlags & LABEL_FLAGS_FONT_NORMAL) != 0) {
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 2b136e093f8738af53402677746c9f4e86c90703..60631e867900a2c4336103c83512232162bcb2cb 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -145,7 +145,7 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
         }
 
         @Override
-        public boolean isIgnoringSpecialKey() {
+        public boolean isTyping() {
             return hasMessages(MSG_KEY_TYPED);
         }
 
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 067fe94594376a77300fadc372ce0e9609257cce..f7a0d97ae333024936bc0132de2396a1050f53cb 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -75,7 +75,7 @@ public class PointerTracker {
 
     public interface TimerProxy {
         public void startKeyTypedTimer(long delay);
-        public boolean isIgnoringSpecialKey();
+        public boolean isTyping();
         public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker);
         public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker);
         public void cancelLongPressTimer();
@@ -85,7 +85,7 @@ public class PointerTracker {
             @Override
             public void startKeyTypedTimer(long delay) {}
             @Override
-            public boolean isIgnoringSpecialKey() { return false; }
+            public boolean isTyping() { return false; }
             @Override
             public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker) {}
             @Override
@@ -720,10 +720,14 @@ public class PointerTracker {
             return;
         }
         if (key.mOutputText != null) {
-            callListenerOnTextInput(key);
+            final boolean ignoreText = key.ignoreWhileTyping() && mTimerProxy.isTyping();
+            if (!ignoreText) {
+                callListenerOnTextInput(key);
+            }
             callListenerOnRelease(key, key.mCode, false);
-            // TODO: "text" input key could have a special action too
-            mTimerProxy.startKeyTypedTimer(sIgnoreSpecialKeyTimeout);
+            if (!ignoreText) {
+                mTimerProxy.startKeyTypedTimer(sIgnoreSpecialKeyTimeout);
+            }
         } else {
             int code = key.mCode;
             final int[] codes = mKeyDetector.newCodeArray();
@@ -743,16 +747,14 @@ public class PointerTracker {
                 codes[1] = codes[0];
                 codes[0] = code;
             }
-            // TODO: Move this special action to Key.keyActionFlags
-            final boolean specialCode = (
-                    code == Keyboard.CODE_SETTINGS || code == Keyboard.CODE_SHORTCUT);
-            final boolean ignoreSpecialCode = specialCode && mTimerProxy.isIgnoringSpecialKey();
-            final boolean shouldStartKeyTypedTyper = !(specialCode || isModifierCode(code));
-            if (!ignoreSpecialCode) {
+            final boolean ignoreCode = key.ignoreWhileTyping() && mTimerProxy.isTyping();
+            if (!ignoreCode) {
+                // TODO: It might be useful to register the nearest key code in codes[] instead of
+                // just ignoring.
                 callListenerOnCodeInput(key, code, codes, x, y);
             }
             callListenerOnRelease(key, code, false);
-            if (shouldStartKeyTypedTyper) {
+            if (!key.ignoreWhileTyping() && !isModifierCode(code)) {
                 mTimerProxy.startKeyTypedTimer(sIgnoreSpecialKeyTimeout);
             }
         }