diff --git a/java/src/com/android/inputmethod/keyboard/KeyDetector.java b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
index 97d88af4af5df0dcfa23cf2f07b9c0134e476b9c..c0e6aa8d7793162c50bcdbc37b3f0016f32406f2 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java
@@ -59,6 +59,9 @@ public class KeyDetector {
     }
 
     public Keyboard getKeyboard() {
+        if (mKeyboard == null) {
+            throw new IllegalStateException("keyboard isn't set");
+        }
         return mKeyboard;
     }
 
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 0e6de70329a759b7defd58fe9275db7d3e2d42cd..b8eb9ec965ab85dad1f88bbcfc94008acdcea45f 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -108,9 +108,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
     private int mDelayAfterPreview;
     private final PreviewPlacerView mPreviewPlacerView;
 
-    /** True if {@link KeyboardView} should handle gesture events. */
-    protected boolean mShouldHandleGesture;
-
     // Drawing
     /** True if the entire keyboard needs to be dimmed. */
     private boolean mNeedsToDimEntireKeyboard;
@@ -438,9 +435,8 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
         return mShowKeyPreviewPopup;
     }
 
-    public void setGestureHandlingMode(boolean shouldHandleGesture,
-            boolean drawsGesturePreviewTrail, boolean drawsGestureFloatingPreviewText) {
-        mShouldHandleGesture = shouldHandleGesture;
+    public void setGesturePreviewMode(boolean drawsGesturePreviewTrail,
+            boolean drawsGestureFloatingPreviewText) {
         mPreviewPlacerView.setGesturePreviewMode(
                 drawsGesturePreviewTrail, drawsGestureFloatingPreviewText);
     }
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index fe9cb9415a69671e51a9cd87409b27648123da0d..4088f3e93297331b64a3e80b5f70ccf54bd0d79c 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -482,7 +482,7 @@ public class MainKeyboardView extends KeyboardView implements PointerTracker.Key
         super.setKeyboard(keyboard);
         mKeyDetector.setKeyboard(
                 keyboard, -getPaddingLeft(), -getPaddingTop() + mVerticalCorrection);
-        PointerTracker.setKeyDetector(mKeyDetector, mShouldHandleGesture);
+        PointerTracker.setKeyDetector(mKeyDetector);
         mTouchScreenRegulator.setKeyboard(keyboard);
         mMoreKeysPanelCache.clear();
 
@@ -500,12 +500,13 @@ public class MainKeyboardView extends KeyboardView implements PointerTracker.Key
         AccessibleKeyboardViewProxy.getInstance().setKeyboard(keyboard);
     }
 
-    @Override
-    public void setGestureHandlingMode(final boolean shouldHandleGesture,
-            boolean drawsGesturePreviewTrail, boolean drawsGestureFloatingPreviewText) {
-        super.setGestureHandlingMode(shouldHandleGesture, drawsGesturePreviewTrail,
-                drawsGestureFloatingPreviewText);
-        PointerTracker.setKeyDetector(mKeyDetector, shouldHandleGesture);
+    // Note that this method is called from a non-UI thread.
+    public void setMainDictionaryAvailability(boolean mainDictionaryAvailable) {
+        PointerTracker.setMainDictionaryAvailability(mainDictionaryAvailable);
+    }
+
+    public void setGestureHandlingEnabledByUser(boolean gestureHandlingEnabledByUser) {
+        PointerTracker.setGestureHandlingEnabledByUser(gestureHandlingEnabledByUser);
     }
 
     /**
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java b/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java
index a183546dd8881a17e94fb4703275f6977de4a5c8..cd4e3001eb2de972a28bd9619f20139af1b7a367 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysDetector.java
@@ -39,11 +39,7 @@ public class MoreKeysDetector extends KeyDetector {
 
         Key nearestKey = null;
         int nearestDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare;
-        final Keyboard keyboard = getKeyboard();
-        if (keyboard == null) {
-            throw new NullPointerException("Keyboard isn't set");
-        }
-        for (final Key key : keyboard.mKeys) {
+        for (final Key key : getKeyboard().mKeys) {
             final int dist = key.squaredDistanceToEdge(touchX, touchY);
             if (dist < nearestDist) {
                 nearestKey = key;
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 2b90a3cb9fb9a4e535d33d3b35e3085b4ff2e5a2..85360c410ece6f79fcb8e2cdf24b3b65fe4e7f41 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -29,6 +29,7 @@ import com.android.inputmethod.keyboard.internal.GestureStroke;
 import com.android.inputmethod.keyboard.internal.PointerTrackerQueue;
 import com.android.inputmethod.latin.InputPointers;
 import com.android.inputmethod.latin.LatinImeLogger;
+import com.android.inputmethod.latin.Utils;
 import com.android.inputmethod.latin.define.ProductionFlag;
 import com.android.inputmethod.research.ResearchLogger;
 
@@ -43,6 +44,9 @@ public class PointerTracker implements PointerTrackerQueue.Element {
 
     /** True if {@link PointerTracker}s should handle gesture events. */
     private static boolean sShouldHandleGesture = false;
+    private static boolean sMainDictionaryAvailable = false;
+    private static boolean sGestureHandlingEnabledByInputField = false;
+    private static boolean sGestureHandlingEnabledByUser = false;
 
     private static final int MIN_GESTURE_RECOGNITION_TIME = 100; // msec
 
@@ -198,7 +202,6 @@ public class PointerTracker implements PointerTrackerQueue.Element {
         sNeedsPhantomSuddenMoveEventHack = needsPhantomSuddenMoveEventHack;
 
         setParameters(MainKeyboardView.PointerTrackerParams.DEFAULT);
-        updateGestureHandlingMode(null, false /* shouldHandleGesture */);
     }
 
     public static void setParameters(MainKeyboardView.PointerTrackerParams params) {
@@ -207,14 +210,22 @@ public class PointerTracker implements PointerTrackerQueue.Element {
                 params.mTouchNoiseThresholdDistance * params.mTouchNoiseThresholdDistance);
     }
 
-    private static void updateGestureHandlingMode(Keyboard keyboard, boolean shouldHandleGesture) {
-        if (!shouldHandleGesture
-                || AccessibilityUtils.getInstance().isTouchExplorationEnabled()
-                || (keyboard != null && keyboard.mId.passwordInput())) {
-            sShouldHandleGesture = false;
-        } else {
-            sShouldHandleGesture = true;
-        }
+    private static void updateGestureHandlingMode() {
+        sShouldHandleGesture = sMainDictionaryAvailable
+                && sGestureHandlingEnabledByInputField
+                && sGestureHandlingEnabledByUser
+                && !AccessibilityUtils.getInstance().isTouchExplorationEnabled();
+    }
+
+    // Note that this method is called from a non-UI thread.
+    public static void setMainDictionaryAvailability(boolean mainDictionaryAvailable) {
+        sMainDictionaryAvailable = mainDictionaryAvailable;
+        updateGestureHandlingMode();
+    }
+
+    public static void setGestureHandlingEnabledByUser(boolean gestureHandlingEnabledByUser) {
+        sGestureHandlingEnabledByUser = gestureHandlingEnabledByUser;
+        updateGestureHandlingMode();
     }
 
     public static PointerTracker getPointerTracker(final int id, KeyEventHandler handler) {
@@ -241,7 +252,7 @@ public class PointerTracker implements PointerTrackerQueue.Element {
         }
     }
 
-    public static void setKeyDetector(KeyDetector keyDetector, boolean shouldHandleGesture) {
+    public static void setKeyDetector(KeyDetector keyDetector) {
         final int trackersSize = sTrackers.size();
         for (int i = 0; i < trackersSize; ++i) {
             final PointerTracker tracker = sTrackers.get(i);
@@ -250,7 +261,8 @@ public class PointerTracker implements PointerTrackerQueue.Element {
             tracker.mKeyboardLayoutHasBeenChanged = true;
         }
         final Keyboard keyboard = keyDetector.getKeyboard();
-        updateGestureHandlingMode(keyboard, shouldHandleGesture);
+        sGestureHandlingEnabledByInputField = !keyboard.mId.passwordInput();
+        updateGestureHandlingMode();
     }
 
     public static void dismissAllKeyPreviews() {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 43901bab4cb416947a4369549fb1c0f0cba27bd0..894b69b79bfc23f4f963b490f636ea29f41a7766 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -433,10 +433,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary());
     }
 
+    // Note that this method is called from a non-UI thread.
     @Override
     public void onUpdateMainDictionaryAvailability(boolean isMainDictionaryAvailable) {
         mIsMainDictionaryAvailable = isMainDictionaryAvailable;
-        updateKeyboardViewGestureHandlingModeByMainDictionaryAvailability();
+        final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
+        if (mainKeyboardView != null) {
+            mainKeyboardView.setMainDictionaryAvailability(isMainDictionaryAvailable);
+        }
     }
 
     private void initSuggest() {
@@ -701,7 +705,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
             }
 
             switcher.loadKeyboard(editorInfo, mCurrentSettings);
-            updateKeyboardViewGestureHandlingModeByMainDictionaryAvailability();
         }
         setSuggestionStripShownInternal(
                 isSuggestionsStripVisible(), /* needsInputViewShown */ false);
@@ -721,6 +724,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
 
         mainKeyboardView.setKeyPreviewPopupEnabled(mCurrentSettings.mKeyPreviewPopupOn,
                 mCurrentSettings.mKeyPreviewPopupDismissDelay);
+        mainKeyboardView.setGestureHandlingEnabledByUser(mCurrentSettings.mGestureInputEnabled);
+        mainKeyboardView.setGesturePreviewMode(mCurrentSettings.mGesturePreviewTrailEnabled,
+                mCurrentSettings.mGestureFloatingPreviewTextEnabled);
 
         if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
     }
@@ -2103,7 +2109,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         if (mKeyboardSwitcher.getMainKeyboardView() != null) {
             // Reload keyboard because the current language has been changed.
             mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mCurrentSettings);
-            updateKeyboardViewGestureHandlingModeByMainDictionaryAvailability();
         }
         // Since we just changed languages, we should re-evaluate suggestions with whatever word
         // we are currently composing. If we are not composing anything, we may want to display
@@ -2111,17 +2116,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         mHandler.postUpdateSuggestionStrip();
     }
 
-    private void updateKeyboardViewGestureHandlingModeByMainDictionaryAvailability() {
-        final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
-        if (mainKeyboardView != null) {
-            final boolean shouldHandleGesture = mCurrentSettings.mGestureInputEnabled
-                    && mIsMainDictionaryAvailable;
-            mainKeyboardView.setGestureHandlingMode(shouldHandleGesture,
-                    mCurrentSettings.mGesturePreviewTrailEnabled,
-                    mCurrentSettings.mGestureFloatingPreviewTextEnabled);
-        }
-    }
-
     // TODO: Remove this method from {@link LatinIME} and move {@link FeedbackManager} to
     // {@link KeyboardSwitcher}. Called from KeyboardSwitcher
     public void hapticAndAudioFeedback(final int primaryCode) {