Merge "Add onGetSuggestedWordsCallback."
diff --git a/java/res/layout/input_view.xml b/java/res/layout/input_view.xml
index 86bd1e6..1ffb8a3 100644
--- a/java/res/layout/input_view.xml
+++ b/java/res/layout/input_view.xml
@@ -20,33 +20,34 @@
 
 <com.android.inputmethod.latin.InputView
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:gravity="bottom|center_horizontal"
-    android:orientation="vertical" >
-    <include
-        layout="@layout/emoji_keyboard_view" />
-    <LinearLayout
-        android:id="@+id/main_keyboard_frame"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:orientation="vertical" >
-        <!-- To ensure that key preview popup is correctly placed when the current system locale is
-             one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. -->
-        <com.android.inputmethod.latin.suggestions.SuggestionStripView
-            android:id="@+id/suggestion_strip_view"
-            android:layoutDirection="ltr"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/suggestions_strip_height"
-            android:paddingRight="@dimen/suggestions_strip_padding"
-            android:paddingLeft="@dimen/suggestions_strip_padding"
-            style="?attr/suggestionStripViewStyle" />
-        <!-- To ensure that key preview popup is correctly placed when the current system locale is
-             one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. -->
-        <com.android.inputmethod.keyboard.MainKeyboardView
-            android:id="@+id/keyboard_view"
-            android:layoutDirection="ltr"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
-    </LinearLayout>
+>
+    <!-- The height of key_preview_backing view will automatically be determined by code. -->
+    <View
+        android:id="@+id/key_preview_backing"
+        android:layout_width="match_parent"
+        android:layout_height="0dp" />
+
+    <!-- To ensure that key preview popup is correctly placed when the current system locale is
+         one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. -->
+    <com.android.inputmethod.latin.suggestions.SuggestionStripView
+        android:id="@+id/suggestion_strip_view"
+        android:layoutDirection="ltr"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/suggestions_strip_height"
+        android:gravity="center_vertical"
+        android:paddingRight="@dimen/suggestions_strip_padding"
+        android:paddingLeft="@dimen/suggestions_strip_padding"
+        style="?attr/suggestionStripViewStyle" />
+
+    <!-- To ensure that key preview popup is correctly placed when the current system locale is
+         one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. -->
+    <com.android.inputmethod.keyboard.MainKeyboardView
+        android:id="@+id/keyboard_view"
+        android:layoutDirection="ltr"
+        android:layout_alignParentBottom="true"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
 </com.android.inputmethod.latin.InputView>
diff --git a/java/res/values/emoji-categories.xml b/java/res/values/emoji-categories.xml
index ce82a8b..8f3dead 100644
--- a/java/res/values/emoji-categories.xml
+++ b/java/res/values/emoji-categories.xml
@@ -36,73 +36,26 @@
         name="emoji_nature"
         format="string"
     >
-        <item>2744</item> <!-- SNOWFLAKE -->
     </array>
     <array
         name="emoji_symbols"
         format="string"
     >
-        <item>2460</item> <!-- CIRCLED DIGIT ONE -->
-        <item>2461</item> <!-- CIRCLED DIGIT TWO -->
-        <item>2462</item> <!-- CIRCLED DIGIT THREE -->
-        <item>2463</item> <!-- CIRCLED DIGIT FOUR -->
-        <item>2464</item> <!-- CIRCLED DIGIT FIVE -->
-        <item>2465</item> <!-- CIRCLED DIGIT SIX -->
-        <item>2466</item> <!-- CIRCLED DIGIT SEVEN -->
-        <item>2467</item> <!-- CIRCLED DIGIT EIGHT -->
-        <item>2468</item> <!-- CIRCLED DIGIT NINE -->
-        <item>2469</item> <!-- CIRCLED DIGIT TEN -->
-        <item>00ae</item> <!-- REGISTERED SIGN -->
-        <item>00a9</item> <!-- COPYRIGHT SIGN -->
-        <item>2122</item> <!-- TRADE MARK SIGN -->
-        <item>2734</item> <!-- EIGHT POINTED BLACK STAR -->
-        <item>2733</item> <!-- EIGHT POINTED PINWHEEL STAR -->
-        <item>2716</item> <!-- HEAVY MULTIPLICATION MARK -->
-        <item>2195</item> <!-- UP DOWN ARROW -->
-        <item>2197</item> <!-- NORTH EAST ARROW -->
-        <item>27a1</item> <!-- BLACK RIGHTWARDS ARROW -->
-        <item>2198</item> <!-- SOUTH EAST ARROW -->
-        <item>2199</item> <!-- SOUTH WEST ARROW -->
-        <item>2196</item> <!-- NORTH EAST ARROW -->
-        <item>2194</item> <!-- LEFT RIGHT ARROW -->
-        <item>25c0</item> <!-- BLACK LEFT-POINTING TRIANGLE -->
-        <item>25b6</item> <!-- BLACK ROGHT-POINTING TRIANGLE -->
-        <item>2747</item> <!-- SPARKLE -->
-        <item>25aa</item> <!-- BLACK SMALL SQUARE -->
-        <item>203c</item> <!-- DOUBLE EXCLAMATION MARK -->
-        <item>2660</item> <!-- BLACK SPADE SUIT -->
-        <item>2665</item> <!-- BLACK HEART SUIT -->
-        <item>2663</item> <!-- BLACK CLUB SUIT -->
-        <item>2666</item> <!-- BLACK DIAMOND SUIT -->
-        <item>21a9</item> <!-- LEFTWARDS ARROW WITH HOOK -->
-        <item>21aa</item> <!-- RIGHTWARDS ARROW WITH HOOK -->
     </array>
     <array
         name="emoji_faces"
         format="string"
     >
-        <item>270C</item> <!-- VICTORY HAND -->
-        <item>2764</item> <!-- HEAVY BLACK HEART -->
     </array>
     <array
         name="emoji_objects"
         format="string"
     >
-        <item>260e</item> <!-- BLACK TELEPHONE -->
-        <item>2709</item> <!-- ENVELOPE -->
-        <item>2712</item> <!-- BLACK NIB -->
-        <item>270f</item> <!-- PENCIL -->
-        <item>2702</item> <!-- BLACK SCISSORS -->
-        <item>2669</item> <!-- QUARTER NOTE -->
-        <item>266a</item> <!-- EIGHTH NOTE -->
-        <item>266c</item> <!-- BEAMED SIXTEENTH NOTES -->
     </array>
     <array
         name="emoji_places"
         format="string"
     >
-        <item>2708</item> <!-- AIRPLANE -->
-        <item>2668</item> <!-- HOT SPRINGS -->
     </array>
     <array
         name="emoji_emoticons"
diff --git a/java/res/values/themes-common.xml b/java/res/values/themes-common.xml
index 8e9cfc9..473a125 100644
--- a/java/res/values/themes-common.xml
+++ b/java/res/values/themes-common.xml
@@ -104,14 +104,7 @@
     <style
         name="MainKeyboardView"
         parent="KeyboardView" />
-    <!-- Though {@link EmojiKeyboardView} doesn't extend {@link KeyboardView}, some views inside it,
-         for instance delete button, need themed {@link KeyboardView} attributes. -->
-    <style
-        name="EmojiKeyboardView"
-        parent="KeyboardView"
-    >
-        <item name="emojiTabLabelColor">@color/emoji_tab_label_color_ics</item>
-    </style>
+    <style name="EmojiKeyboardView" />
     <style name="MoreKeysKeyboard" />
     <style
         name="MoreKeysKeyboardView"
diff --git a/java/res/values/themes-gb.xml b/java/res/values/themes-gb.xml
index 7f8dd23..d39003d 100644
--- a/java/res/values/themes-gb.xml
+++ b/java/res/values/themes-gb.xml
@@ -96,8 +96,6 @@
         <item name="spacebarTextColor">@color/spacebar_text_color_gb</item>
         <item name="spacebarTextShadowColor">@color/spacebar_text_shadow_color_gb</item>
     </style>
-    <!-- Though {@link EmojiKeyboardView} doesn't extend {@link KeyboardView}, some views inside it,
-         for instance delete button, need themed {@link KeyboardView} attributes. -->
     <style
         name="EmojiKeyboardView.GB"
         parent="KeyboardView.GB"
diff --git a/java/res/values/themes-ics.xml b/java/res/values/themes-ics.xml
index f3b6b13..f5b7483 100644
--- a/java/res/values/themes-ics.xml
+++ b/java/res/values/themes-ics.xml
@@ -97,8 +97,6 @@
         <item name="spacebarTextColor">@color/spacebar_text_color_ics</item>
         <item name="spacebarTextShadowColor">@color/spacebar_text_shadow_color_ics</item>
     </style>
-    <!-- Though {@link EmojiKeyboardView} doesn't extend {@link KeyboardView}, some views inside it,
-         for instance delete button, need themed {@link KeyboardView} attributes. -->
     <style
         name="EmojiKeyboardView.ICS"
         parent="KeyboardView.ICS"
diff --git a/java/res/xml-sw600dp/key_f2.xml b/java/res/xml-sw600dp/key_f2.xml
index 56f233d..ca3b30b 100644
--- a/java/res/xml-sw600dp/key_f2.xml
+++ b/java/res/xml-sw600dp/key_f2.xml
@@ -39,7 +39,7 @@
         </case>
         <default>
             <Key
-                latin:keyStyle="emojiKeyStyle" />
+                latin:keyStyle="smileyKeyStyle" />
         </default>
     </switch>
 </merge>
diff --git a/java/res/xml-sw600dp/key_styles_common.xml b/java/res/xml-sw600dp/key_styles_common.xml
index 3b20281..fc9342b 100644
--- a/java/res/xml-sw600dp/key_styles_common.xml
+++ b/java/res/xml-sw600dp/key_styles_common.xml
@@ -123,8 +123,7 @@
         latin:styleName="emojiKeyStyle"
         latin:code="!code/key_emoji"
         latin:keyIcon="!icon/emoji_key"
-        latin:keyActionFlags="noKeyPreview"
-        latin:backgroundType="functional" />
+        latin:keyActionFlags="noKeyPreview" />
     <key-style
         latin:styleName="settingsKeyStyle"
         latin:code="!code/key_settings"
diff --git a/java/res/xml-sw768dp/key_styles_common.xml b/java/res/xml-sw768dp/key_styles_common.xml
index 5ee9ac5..5389309 100644
--- a/java/res/xml-sw768dp/key_styles_common.xml
+++ b/java/res/xml-sw768dp/key_styles_common.xml
@@ -113,8 +113,7 @@
         latin:styleName="emojiKeyStyle"
         latin:code="!code/key_emoji"
         latin:keyIcon="!icon/emoji_key"
-        latin:keyActionFlags="noKeyPreview"
-        latin:backgroundType="functional" />
+        latin:keyActionFlags="noKeyPreview" />
     <key-style
         latin:styleName="settingsKeyStyle"
         latin:code="!code/key_settings"
diff --git a/java/res/xml/key_styles_common.xml b/java/res/xml/key_styles_common.xml
index c1c2c3e..dabe1e7 100644
--- a/java/res/xml/key_styles_common.xml
+++ b/java/res/xml/key_styles_common.xml
@@ -67,6 +67,30 @@
         latin:backgroundType="functional" />
     <include
         latin:keyboardLayout="@xml/key_styles_enter" />
+    <switch>
+        <!-- Shift + Enter in textMultiLine field. -->
+        <case
+            latin:isMultiLine="true"
+            latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLockShifted"
+        >
+            <key-style
+                latin:styleName="enterKeyStyle"
+                latin:parentStyle="shiftEnterKeyStyle" />
+        </case>
+        <!-- Smiley in textShortMessage field.
+             Overrides common enter key style. -->
+        <case
+            latin:mode="im"
+        >
+            <key-style
+                latin:styleName="enterKeyStyle"
+                latin:keyLabel=":-)"
+                latin:keyOutputText=":-) "
+                latin:keyLabelFlags="hasPopupHint"
+                latin:moreKeys="!text/more_keys_for_smiley"
+                latin:backgroundType="functional" />
+        </case>
+    </switch>
     <key-style
         latin:styleName="spaceKeyStyle"
         latin:code="!code/key_space"
@@ -105,8 +129,7 @@
         latin:styleName="emojiKeyStyle"
         latin:code="!code/key_emoji"
         latin:keyIcon="!icon/emoji_key"
-        latin:keyActionFlags="noKeyPreview"
-        latin:backgroundType="functional" />
+        latin:keyActionFlags="noKeyPreview" />
     <key-style
         latin:styleName="tabKeyStyle"
         latin:code="!code/key_tab"
diff --git a/java/res/xml/row_symbols4.xml b/java/res/xml/row_symbols4.xml
index bea139a..5c15da6 100644
--- a/java/res/xml/row_symbols4.xml
+++ b/java/res/xml/row_symbols4.xml
@@ -50,7 +50,7 @@
             latin:keyboardLayout="@xml/key_symbols_period"
             latin:backgroundType="functional" />
         <Key
-            latin:keyStyle="emojiKeyStyle"
+            latin:keyStyle="enterKeyStyle"
             latin:keyWidth="fillRight" />
     </Row>
 </merge>
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 0208249..098c8b3 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -66,9 +66,7 @@
     private SharedPreferences mPrefs;
 
     private InputView mCurrentInputView;
-    private View mMainKeyboardFrame;
     private MainKeyboardView mKeyboardView;
-    private EmojiKeyboardView mEmojiKeyboardView;
     private LatinIME mLatinIME;
     private Resources mResources;
 
@@ -169,8 +167,6 @@
     }
 
     private void setKeyboard(final Keyboard keyboard) {
-        // Make {@link MainKeyboardView} visible and hide {@link EmojiKeyboardView}.
-        setMainKeyboardFrame();
         final MainKeyboardView keyboardView = mKeyboardView;
         final Keyboard oldKeyboard = keyboardView.getKeyboard();
         keyboardView.setKeyboard(keyboard);
@@ -257,18 +253,6 @@
         setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_SYMBOLS));
     }
 
-    private void setMainKeyboardFrame() {
-        mMainKeyboardFrame.setVisibility(View.VISIBLE);
-        mEmojiKeyboardView.setVisibility(View.GONE);
-    }
-
-    // Implements {@link KeyboardState.SwitchActions}.
-    @Override
-    public void setEmojiKeyboard() {
-        mMainKeyboardFrame.setVisibility(View.GONE);
-        mEmojiKeyboardView.setVisibility(View.VISIBLE);
-    }
-
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void requestUpdatingShiftState() {
@@ -320,16 +304,10 @@
         setContextThemeWrapper(mLatinIME, mKeyboardTheme);
         mCurrentInputView = (InputView)LayoutInflater.from(mThemeContext).inflate(
                 R.layout.input_view, null);
-        mMainKeyboardFrame = mCurrentInputView.findViewById(R.id.main_keyboard_frame);
-        mEmojiKeyboardView = (EmojiKeyboardView)mCurrentInputView.findViewById(
-                R.id.emoji_keyboard_view);
 
         mKeyboardView = (MainKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view);
         mKeyboardView.setHardwareAcceleratedDrawingEnabled(isHardwareAcceleratedDrawingEnabled);
         mKeyboardView.setKeyboardActionListener(mLatinIME);
-        mEmojiKeyboardView.setHardwareAcceleratedDrawingEnabled(
-                isHardwareAcceleratedDrawingEnabled);
-        mEmojiKeyboardView.setKeyboardActionListener(mLatinIME);
 
         // This always needs to be set since the accessibility state can
         // potentially change without the input view being re-created.
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index 089db12..0b10a1d 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -46,7 +46,6 @@
         public void setAlphabetShiftLockedKeyboard();
         public void setAlphabetShiftLockShiftedKeyboard();
         public void setSymbolsKeyboard();
-        public void setEmojiKeyboard();
 
         /**
          * Request to call back {@link KeyboardState#onUpdateShiftState(int, int)}.
@@ -72,10 +71,7 @@
     private static final int SWITCH_STATE_MOMENTARY_ALPHA_SHIFT = 5;
     private int mSwitchState = SWITCH_STATE_ALPHA;
 
-    // TODO: Consolidate these two mode booleans into one integer to distinguish between alphabet,
-    // symbols, and emoji mode.
     private boolean mIsAlphabetMode;
-    private boolean mIsEmojiMode;
     private AlphabetShiftState mAlphabetShiftState = new AlphabetShiftState();
     private boolean mPrevMainKeyboardWasShiftLocked;
     private int mRecapitalizeMode;
@@ -90,7 +86,6 @@
         public boolean mIsValid;
         public boolean mIsAlphabetMode;
         public boolean mIsAlphabetShiftLocked;
-        public boolean mIsEmojiMode;
         public int mShiftMode;
 
         @Override
@@ -99,8 +94,6 @@
             if (mIsAlphabetMode) {
                 if (mIsAlphabetShiftLocked) return "ALPHABET_SHIFT_LOCKED";
                 return "ALPHABET_" + shiftModeToString(mShiftMode);
-            } else if (mIsEmojiMode) {
-                return "EMOJI";
             } else {
                 return "SYMBOLS";
             }
@@ -132,7 +125,6 @@
     public void onSaveKeyboardState() {
         final SavedKeyboardState state = mSavedKeyboardState;
         state.mIsAlphabetMode = mIsAlphabetMode;
-        state.mIsEmojiMode = mIsEmojiMode;
         if (mIsAlphabetMode) {
             state.mIsAlphabetShiftLocked = mAlphabetShiftState.isShiftLocked();
             state.mShiftMode = mAlphabetShiftState.isAutomaticShifted() ? AUTOMATIC_SHIFT
@@ -153,8 +145,6 @@
         }
         if (!state.mIsValid || state.mIsAlphabetMode) {
             setAlphabetKeyboard();
-        } else if (state.mIsEmojiMode) {
-            setEmojiKeyboard();
         } else {
             setSymbolsKeyboard();
         }
@@ -264,7 +254,6 @@
 
         mSwitchActions.setAlphabetKeyboard();
         mIsAlphabetMode = true;
-        mIsEmojiMode = false;
         mRecapitalizeMode = RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE;
         mSwitchState = SWITCH_STATE_ALPHA;
         mSwitchActions.requestUpdatingShiftState();
@@ -281,15 +270,6 @@
         mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
     }
 
-    private void setEmojiKeyboard() {
-        if (DEBUG_ACTION) {
-            Log.d(TAG, "setEmojiKeyboard");
-        }
-        mIsAlphabetMode = false;
-        mIsEmojiMode = true;
-        mSwitchActions.setEmojiKeyboard();
-    }
-
     public void onPressKey(final int code, final boolean isSinglePointer, final int autoCaps) {
         if (DEBUG_EVENT) {
             Log.d(TAG, "onPressKey: code=" + Constants.printableCode(code)
@@ -567,8 +547,6 @@
         // If the code is a letter, update keyboard shift state.
         if (Constants.isLetterCode(code)) {
             updateAlphabetShiftState(autoCaps, RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE);
-        } else if (code == Constants.CODE_EMOJI) {
-            setEmojiKeyboard();
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 89f89b1..25fdf57 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -31,6 +31,7 @@
 import android.content.pm.PackageInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.Rect;
 import android.inputmethodservice.InputMethodService;
 import android.media.AudioManager;
 import android.net.ConnectivityManager;
@@ -50,6 +51,7 @@
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.View;
+import android.view.ViewGroup.LayoutParams;
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.inputmethod.CompletionInfo;
@@ -154,8 +156,8 @@
 
     private final Settings mSettings;
 
-    private View mInputView;
-    private int mInputViewMinHeight;
+    private View mExtractArea;
+    private View mKeyPreviewBackingView;
     private SuggestionStripView mSuggestionStripView;
     // Never null
     private SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
@@ -674,25 +676,17 @@
         return mKeyboardSwitcher.onCreateInputView(mIsHardwareAcceleratedDrawingEnabled);
     }
 
-    private void setInputViewMinHeight(final int minHeight) {
-        if (mInputView != null && mInputViewMinHeight != minHeight) {
-            mInputView.setMinimumHeight(minHeight);
-            mInputViewMinHeight = minHeight;
-        }
-    }
-
     @Override
-    public void setInputView(final View inputView) {
-        super.setInputView(inputView);
-        mInputView = inputView;
-        setInputViewMinHeight(0);
-        mSuggestionStripView = (SuggestionStripView)inputView.findViewById(
-                R.id.suggestion_strip_view);
-        if (mSuggestionStripView != null) {
-            mSuggestionStripView.setListener(this, inputView);
-        }
+    public void setInputView(final View view) {
+        super.setInputView(view);
+        mExtractArea = getWindow().getWindow().getDecorView()
+                .findViewById(android.R.id.extractArea);
+        mKeyPreviewBackingView = view.findViewById(R.id.key_preview_backing);
+        mSuggestionStripView = (SuggestionStripView)view.findViewById(R.id.suggestion_strip_view);
+        if (mSuggestionStripView != null)
+            mSuggestionStripView.setListener(this, view);
         if (LatinImeLogger.sVISUALDEBUG) {
-            inputView.setBackgroundColor(0x10FF0000);
+            mKeyPreviewBackingView.setBackgroundColor(0x10FF0000);
         }
     }
 
@@ -1170,11 +1164,6 @@
                 mSuggestionStripView.setVisibility(
                         shouldShowSuggestions ? View.VISIBLE : View.INVISIBLE);
             }
-            if (shouldShowSuggestions && mainKeyboardView != null) {
-                final int remainingHeight = getWindow().getWindow().getDecorView().getHeight()
-                        - mainKeyboardView.getHeight() - mSuggestionStripView.getHeight();
-                mSuggestionStripView.setMoreSuggestionsHeight(remainingHeight);
-            }
         }
     }
 
@@ -1182,6 +1171,31 @@
         setSuggestionStripShownInternal(shown, /* needsInputViewShown */true);
     }
 
+    private int getAdjustedBackingViewHeight() {
+        final int currentHeight = mKeyPreviewBackingView.getHeight();
+        if (currentHeight > 0) {
+            return currentHeight;
+        }
+
+        final MainKeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
+        if (mainKeyboardView == null) {
+            return 0;
+        }
+        final int keyboardHeight = mainKeyboardView.getHeight();
+        final int suggestionsHeight = mSuggestionStripView.getHeight();
+        final int displayHeight = getResources().getDisplayMetrics().heightPixels;
+        final Rect rect = new Rect();
+        mKeyPreviewBackingView.getWindowVisibleDisplayFrame(rect);
+        final int notificationBarHeight = rect.top;
+        final int remainingHeight = displayHeight - notificationBarHeight - suggestionsHeight
+                - keyboardHeight;
+
+        final LayoutParams params = mKeyPreviewBackingView.getLayoutParams();
+        params.height = mSuggestionStripView.setMoreSuggestionsHeight(remainingHeight);
+        mKeyPreviewBackingView.setLayoutParams(params);
+        return params.height;
+    }
+
     @Override
     public void onComputeInsets(final InputMethodService.Insets outInsets) {
         super.onComputeInsets(outInsets);
@@ -1189,30 +1203,32 @@
         if (mainKeyboardView == null || mSuggestionStripView == null) {
             return;
         }
-        // This method is never called when in fullscreen mode.
-        // The contentTop is the top coordinate of the keyboard. The application behind will be
-        // resized/panned above this coordibnate to be able to show an input field.
-        final int contentTop = mInputView.getHeight() - mainKeyboardView.getHeight();
-        final int suggestionsHeight = (mSuggestionStripView.getVisibility() == View.VISIBLE)
-                ? mSuggestionStripView.getHeight() : 0;
-        // The visibleTop is the top coordinates of the visible part of this IME. The application
-        // behind will never be resized, but may be panned or scrolled.
-        final int visibleTop = mainKeyboardView.isShowingMoreKeysPanel() ? 0
-                : contentTop - suggestionsHeight;
-        outInsets.contentTopInsets = contentTop;
-        outInsets.visibleTopInsets = visibleTop;
+        final int adjustedBackingHeight = getAdjustedBackingViewHeight();
+        final boolean backingGone = (mKeyPreviewBackingView.getVisibility() == View.GONE);
+        final int backingHeight = backingGone ? 0 : adjustedBackingHeight;
+        // In fullscreen mode, the height of the extract area managed by InputMethodService should
+        // be considered.
+        // See {@link android.inputmethodservice.InputMethodService#onComputeInsets}.
+        final int extractHeight = isFullscreenMode() ? mExtractArea.getHeight() : 0;
+        final int suggestionsHeight = (mSuggestionStripView.getVisibility() == View.GONE) ? 0
+                : mSuggestionStripView.getHeight();
+        final int extraHeight = extractHeight + backingHeight + suggestionsHeight;
+        int visibleTopY = extraHeight;
         // Need to set touchable region only if input view is being shown
         if (mainKeyboardView.isShown()) {
-            final int touchLeft = 0;
-            final int touchTop = visibleTop;
-            final int touchRight = touchLeft + mainKeyboardView.getWidth();
-            final int touchBottom = contentTop + mainKeyboardView.getHeight()
+            if (mSuggestionStripView.getVisibility() == View.VISIBLE) {
+                visibleTopY -= suggestionsHeight;
+            }
+            final int touchY = mainKeyboardView.isShowingMoreKeysPanel() ? 0 : visibleTopY;
+            final int touchWidth = mainKeyboardView.getWidth();
+            final int touchHeight = mainKeyboardView.getHeight() + extraHeight
                     // Extend touchable region below the keyboard.
                     + EXTENDED_TOUCHABLE_REGION_HEIGHT;
-            // The touch event on touchableRegion will be delivered to this IME.
-            outInsets.touchableRegion.set(touchLeft, touchTop, touchRight, touchBottom);
             outInsets.touchableInsets = InputMethodService.Insets.TOUCHABLE_INSETS_REGION;
+            outInsets.touchableRegion.set(0, touchY, touchWidth, touchHeight);
         }
+        outInsets.contentTopInsets = visibleTopY;
+        outInsets.visibleTopInsets = visibleTopY;
     }
 
     @Override
@@ -1235,11 +1251,11 @@
     @Override
     public void updateFullscreenMode() {
         super.updateFullscreenMode();
-        if (!isFullscreenMode()) {
-            // Expand the input view to cover entire display to be able to show key previews and
-            // more suggestions view that may be displayed above the keyboard.
-            setInputViewMinHeight(getResources().getDisplayMetrics().heightPixels);
-        }
+
+        if (mKeyPreviewBackingView == null) return;
+        // In fullscreen mode, no need to have extra space to show the key preview.
+        // If not, we should have extra space above the keyboard to show the key preview.
+        mKeyPreviewBackingView.setVisibility(isFullscreenMode() ? View.GONE : View.VISIBLE);
     }
 
     // This will reset the whole input state to the starting state. It will clear
@@ -1533,8 +1549,7 @@
             handleLanguageSwitchKey();
             break;
         case Constants.CODE_EMOJI:
-            // Note: Switching emoji keyboard is being handled in
-            // {@link KeyboardState#onCodeInput(int,int)}.
+            // TODO: Implement emoji keyboard switch.
             break;
         case Constants.CODE_ENTER:
             final EditorInfo editorInfo = getCurrentInputEditorInfo();
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
index aca2492..8d2689a 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
@@ -165,9 +165,20 @@
         return mMaxMoreSuggestionsRow;
     }
 
-    public void setMoreSuggestionsHeight(final int remainingHeight) {
+    private int getMoreSuggestionsHeight() {
+        return mMaxMoreSuggestionsRow * mMoreSuggestionsRowHeight + mMoreSuggestionsBottomGap;
+    }
+
+    public int setMoreSuggestionsHeight(final int remainingHeight) {
+        final int currentHeight = getMoreSuggestionsHeight();
+        if (currentHeight <= remainingHeight) {
+            return currentHeight;
+        }
+
         mMaxMoreSuggestionsRow = (remainingHeight - mMoreSuggestionsBottomGap)
                 / mMoreSuggestionsRowHeight;
+        final int newHeight = getMoreSuggestionsHeight();
+        return newHeight;
     }
 
     private static Drawable getMoreSuggestionsHint(final Resources res, final float textSize,
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
index badc942..75f17c5 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java
@@ -135,8 +135,8 @@
         }
     }
 
-    public void setMoreSuggestionsHeight(final int remainingHeight) {
-        mLayoutHelper.setMoreSuggestionsHeight(remainingHeight);
+    public int setMoreSuggestionsHeight(final int remainingHeight) {
+        return mLayoutHelper.setMoreSuggestionsHeight(remainingHeight);
     }
 
     public boolean isShowingAddToDictionaryHint() {
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
index b209b00..682d8fc 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
@@ -113,11 +113,6 @@
     }
 
     @Override
-    public void setEmojiKeyboard() {
-        // Just ignore.
-    }
-
-    @Override
     public void requestUpdatingShiftState() {
         mState.onUpdateShiftState(mAutoCapsState, RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE);
     }